From e2d48e8395a43e8264660ac37a75f7644d4f5d8b Mon Sep 17 00:00:00 2001 From: Dibin Moolakadan Subrahmanian Date: Fri, 27 Mar 2026 12:14:52 +0530 Subject: [PATCH 001/144] drm/i915/dmc: Remove invalid PIPEDMC interrupt bits On display version 35+ PIPEDMC_ATS_FAULT and PIPEDMC_GTT_FAULT interrupt bits are no longer defined. Update the interrupt mask to drop these. Changes in v2: - Move PIPEDMC_ERROR interrupt enable to a separate patch (Ville Syrjala) Changes in v3: - Add Bspec reference (Suraj Kandpal) Changes in v4: - Move bspec position in commit message(Suraj Kandpal) Bspec: 70296 Signed-off-by: Dibin Moolakadan Subrahmanian Reviewed-by: Suraj Kandpal Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260327064453.2241523-2-dibin.moolakadan.subrahmanian@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 1667a829e708..1d2e09471ba4 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -505,6 +505,9 @@ static void pipedmc_clock_gating_wa(struct intel_display *display, bool enable) static u32 pipedmc_interrupt_mask(struct intel_display *display) { + if (DISPLAY_VER(display) >= 35) + return PIPEDMC_FLIPQ_PROG_DONE; + /* * FIXME PIPEDMC_ERROR not enabled for now due to LNL pipe B * triggering it during the first DC state transition. Figure From ba48541c82dc6df5b18bd4a4db0f0c1617a37154 Mon Sep 17 00:00:00 2001 From: Dibin Moolakadan Subrahmanian Date: Fri, 27 Mar 2026 12:14:53 +0530 Subject: [PATCH 002/144] drm/i915/dmc: Enable PIPEDMC_ERROR interrupt Enable PIPEDMC_ERROR interrupt bit for display version 35+. Changes in v2: - Move PIPEDMC_ERROR interrupt enable to a separate patch (Ville Syrjala) Changes in v3: - Add Bspec reference (Suraj Kandpal) Changes in v4: - Add TODO to check the enablement of PIPEDMC_ERROR for PTL (Suraj Kandpal) Changes in v5: - Move TODO to the beginning of pipedmc_interrupt_mask() (Suraj Kandpal) Bspec: 70296 Signed-off-by: Dibin Moolakadan Subrahmanian Reviewed-by: Suraj Kandpal Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260327064453.2241523-3-dibin.moolakadan.subrahmanian@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 1d2e09471ba4..2104164e136e 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -505,8 +505,13 @@ static void pipedmc_clock_gating_wa(struct intel_display *display, bool enable) static u32 pipedmc_interrupt_mask(struct intel_display *display) { + /* + * TODO: Check if PIPEDMC_ERROR bit enabling causes errors + * on PTL, enable it if validation passes + */ if (DISPLAY_VER(display) >= 35) - return PIPEDMC_FLIPQ_PROG_DONE; + return PIPEDMC_FLIPQ_PROG_DONE | + PIPEDMC_ERROR; /* * FIXME PIPEDMC_ERROR not enabled for now due to LNL pipe B From 0f21a14987ebae3c05ad1184ea872e7b7a7b8695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 25 Mar 2026 15:58:44 +0200 Subject: [PATCH 003/144] drm/i915/cdclk: Do the full CDCLK dance for min_voltage_level changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently I forgot about the pipe min_voltage_level when I decoupled the CDCLK calculations from modesets. Even if the CDCLK frequency doesn't need changing we may still need to bump the voltage level to accommodate an increase in the port clock frequency. Currently, even if there is a full modeset, we won't notice the need to go through the full CDCLK calculations/programming, unless the set of enabled/active pipes changes, or the pipe/dbuf min CDCLK changes. Duplicate the same logic we use the pipe's min CDCLK frequency to also deal with its min voltage level. Note that the 'allow_voltage_level_decrease' stuff isn't really useful here since the min voltage level can only change during a full modeset. But I think sticking to the same approach in the three similar parts (pipe min cdclk, pipe min voltage level, dbuf min cdclk) is a good idea. Cc: stable@vger.kernel.org Tested-by: Mikhail Rudenko Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15826 Fixes: ba91b9eecb47 ("drm/i915/cdclk: Decouple cdclk from state->modeset") Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260325135849.12603-2-ville.syrjala@linux.intel.com Reviewed-by: Michał Grzelak --- drivers/gpu/drm/i915/display/intel_cdclk.c | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 121a12c5b8ac..a47736613f6e 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2972,6 +2972,53 @@ static int intel_cdclk_update_crtc_min_cdclk(struct intel_atomic_state *state, return 0; } +static int intel_cdclk_update_crtc_min_voltage_level(struct intel_atomic_state *state, + struct intel_crtc *crtc, + u8 old_min_voltage_level, + u8 new_min_voltage_level, + bool *need_cdclk_calc) +{ + struct intel_display *display = to_intel_display(state); + struct intel_cdclk_state *cdclk_state; + bool allow_voltage_level_decrease = intel_any_crtc_needs_modeset(state); + int ret; + + if (new_min_voltage_level == old_min_voltage_level) + return 0; + + if (!allow_voltage_level_decrease && + new_min_voltage_level < old_min_voltage_level) + return 0; + + cdclk_state = intel_atomic_get_cdclk_state(state); + if (IS_ERR(cdclk_state)) + return PTR_ERR(cdclk_state); + + old_min_voltage_level = cdclk_state->min_voltage_level[crtc->pipe]; + + if (new_min_voltage_level == old_min_voltage_level) + return 0; + + if (!allow_voltage_level_decrease && + new_min_voltage_level < old_min_voltage_level) + return 0; + + cdclk_state->min_voltage_level[crtc->pipe] = new_min_voltage_level; + + ret = intel_atomic_lock_global_state(&cdclk_state->base); + if (ret) + return ret; + + *need_cdclk_calc = true; + + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] min voltage level: %d -> %d\n", + crtc->base.base.id, crtc->base.name, + old_min_voltage_level, new_min_voltage_level); + + return 0; +} + int intel_cdclk_update_dbuf_bw_min_cdclk(struct intel_atomic_state *state, int old_min_cdclk, int new_min_cdclk, bool *need_cdclk_calc) @@ -3387,6 +3434,13 @@ static int intel_crtcs_calc_min_cdclk(struct intel_atomic_state *state, need_cdclk_calc); if (ret) return ret; + + ret = intel_cdclk_update_crtc_min_voltage_level(state, crtc, + old_crtc_state->min_voltage_level, + new_crtc_state->min_voltage_level, + need_cdclk_calc); + if (ret) + return ret; } return 0; From 799fe8dc2af52f35c78c4ac97f8e34994dfd8760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 25 Mar 2026 15:58:45 +0200 Subject: [PATCH 004/144] drm/i915/dp: Use crtc_state->enhanced_framing properly on ivb/hsw CPU eDP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like I missed the drm_dp_enhanced_frame_cap() in the ivb/hsw CPU eDP code when I introduced crtc_state->enhanced_framing. Fix it up so that the state we program to the hardware is guaranteed to match what we computed earlier. Cc: stable@vger.kernel.org Fixes: 3072a24c778a ("drm/i915: Introduce crtc_state->enhanced_framing") Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260325135849.12603-3-ville.syrjala@linux.intel.com Reviewed-by: Michał Grzelak --- drivers/gpu/drm/i915/display/g4x_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index d7de329abf19..5e74d8a3ba5c 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -136,7 +136,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, intel_dp->DP |= DP_SYNC_VS_HIGH; intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; - if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) + if (pipe_config->enhanced_framing) intel_dp->DP |= DP_ENHANCED_FRAMING; intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe); From c048609b05675ecae4bc10fc34fc4cb83e3264a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 25 Mar 2026 15:58:46 +0200 Subject: [PATCH 005/144] drm/i915: Split the pipe_src dump to its own line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pipe_src dump doesn't really fit in with the rest of the guys (pixel_rate, port_clock, min_cdclk) included on the same line. Split pipe_src onto its own line, next to the related pfit stuff. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260325135849.12603-4-ville.syrjala@linux.intel.com Reviewed-by: Michał Grzelak --- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 234843b8f83a..63a61caa059e 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -320,9 +320,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, drm_printf(&p, "pipe mode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&pipe_config->hw.pipe_mode)); intel_dump_crtc_timings(&p, &pipe_config->hw.pipe_mode); - drm_printf(&p, "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d, min cdclk %d\n", - pipe_config->port_clock, DRM_RECT_ARG(&pipe_config->pipe_src), - pipe_config->pixel_rate, pipe_config->min_cdclk); + drm_printf(&p, "port clock: %d, pixel rate %d, min cdclk %d\n", + pipe_config->port_clock, pipe_config->pixel_rate, + pipe_config->min_cdclk); drm_printf(&p, "linetime: %d, ips linetime: %d\n", pipe_config->linetime, pipe_config->ips_linetime); @@ -334,6 +334,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, pipe_config->scaler_state.scaler_id, pipe_config->hw.scaling_filter); + drm_printf(&p, "pipe src: " DRM_RECT_FMT "\n", + DRM_RECT_ARG(&pipe_config->pipe_src)); + if (HAS_GMCH(display)) drm_printf(&p, "gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n", pipe_config->gmch_pfit.control, From dd6eaa843c8f06949fab7de142affe05e75bb78e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 25 Mar 2026 15:58:47 +0200 Subject: [PATCH 006/144] drm/i915: Include the crtc min_voltage_level in the state dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include the pipe's min_voltage_level in its state dump, to help with debugging. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260325135849.12603-5-ville.syrjala@linux.intel.com Reviewed-by: Michał Grzelak --- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 63a61caa059e..ec667a3d09d6 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -320,9 +320,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, drm_printf(&p, "pipe mode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&pipe_config->hw.pipe_mode)); intel_dump_crtc_timings(&p, &pipe_config->hw.pipe_mode); - drm_printf(&p, "port clock: %d, pixel rate %d, min cdclk %d\n", + drm_printf(&p, "port clock: %d, pixel rate %d, min cdclk %d, min voltage level %d\n", pipe_config->port_clock, pipe_config->pixel_rate, - pipe_config->min_cdclk); + pipe_config->min_cdclk, pipe_config->min_voltage_level); drm_printf(&p, "linetime: %d, ips linetime: %d\n", pipe_config->linetime, pipe_config->ips_linetime); From b878872b7d9078752ed7bd1be29786ff7c270b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 25 Mar 2026 15:58:48 +0200 Subject: [PATCH 007/144] drm/i915: Eliminate out of place "HBlank" CamelCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing else in the crtc state dump uses CamelCase, so don't use it for "HBlank" either. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260325135849.12603-6-ville.syrjala@linux.intel.com Reviewed-by: Michał Grzelak --- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index ec667a3d09d6..e0c292c703c1 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -250,7 +250,7 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, str_enabled_disabled(pipe_config->has_sel_update), str_enabled_disabled(pipe_config->has_panel_replay), str_enabled_disabled(pipe_config->enable_psr2_sel_fetch)); - drm_printf(&p, "minimum HBlank: %d\n", pipe_config->min_hblank); + drm_printf(&p, "minimum hblank: %d\n", pipe_config->min_hblank); } drm_printf(&p, "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", From 299d59abcc3907524239e10277c8dd8b714977e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 25 Mar 2026 15:58:49 +0200 Subject: [PATCH 008/144] drm/i915: Move the sharpness filter dump next to pfit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Group the sharpness filter parameters next to all the other pfit stuff in the state dump. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260325135849.12603-7-ville.syrjala@linux.intel.com Reviewed-by: Michał Grzelak --- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index e0c292c703c1..c85ba9a95322 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -348,6 +348,11 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, str_enabled_disabled(pipe_config->pch_pfit.enabled), str_yes_no(pipe_config->pch_pfit.force_thru)); + drm_printf(&p, "sharpness strength: %d, sharpness tap size: %d, sharpness enable: %d\n", + pipe_config->hw.casf_params.strength, + pipe_config->hw.casf_params.win_size, + pipe_config->hw.casf_params.casf_enable); + drm_printf(&p, "ips: %i, double wide: %i, drrs: %i\n", pipe_config->ips_enabled, pipe_config->double_wide, pipe_config->has_drrs); @@ -383,11 +388,6 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, intel_vdsc_state_dump(&p, 0, pipe_config); - drm_printf(&p, "sharpness strength: %d, sharpness tap size: %d, sharpness enable: %d\n", - pipe_config->hw.casf_params.strength, - pipe_config->hw.casf_params.win_size, - pipe_config->hw.casf_params.casf_enable); - dump_planes: if (!state) return; From 3b6e473cdc9c8494a1030fcde5589aa22deb02c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 30 Mar 2026 23:26:28 +0300 Subject: [PATCH 009/144] drm/i915/dp: Implement the POST_LT_ADJ_REQ sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement the POST_LT_ADJ_REQ sequence, which should be used to further fine tune the link if TPS4 is not supported. The POST_LT_ADJ_REQ sequence will be performed after the normal link training has succeeded. Only the final hop between the last LTTPR and DPRX will perform the POST_LT_ADJ_REQ adjustment. The earlier hops will use TPS4 instead since it's mandatory for LTTPRs. The sequence will terminate when the sink clears the "in progress" flag, the vswing/pre-emphasis values have changed six times, or the vswing/pre-emphasis values have remained unchanged for 200 ms. Tested-by: Imre Deak Reviewed-by: Imre Deak Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260330202629.28616-2-ville.syrjala@linux.intel.com --- .../drm/i915/display/intel_dp_link_training.c | 124 +++++++++++++++++- .../drm/i915/display/intel_dp_link_training.h | 2 +- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- 3 files changed, 124 insertions(+), 4 deletions(-) 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 54c585c59b90..a26094223f78 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -742,11 +742,14 @@ static void intel_dp_update_downspread_ctrl(struct intel_dp *intel_dp, 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 enhanced_framing, bool post_lt_adj_req) { if (enhanced_framing) lane_count |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + if (post_lt_adj_req) + lane_count |= DP_POST_LT_ADJ_REQ_GRANTED; + if (link_bw) { /* DP and eDP v1.3 and earlier link bw set method. */ u8 link_config[] = { link_bw, lane_count }; @@ -825,12 +828,21 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp, return DP_TRAINING_PATTERN_2; } +static bool intel_dp_use_post_lt_adj_req(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + return intel_dp->set_idle_link_train && + drm_dp_post_lt_adj_req_supported(intel_dp->dpcd) && + intel_dp_training_pattern(intel_dp, crtc_state, DP_PHY_DPRX) != DP_TRAINING_PATTERN_4; +} + static void intel_dp_update_link_bw_set(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state, u8 link_bw, u8 rate_select) { intel_dp_link_training_set_bw(intel_dp, link_bw, rate_select, crtc_state->lane_count, - crtc_state->enhanced_framing); + crtc_state->enhanced_framing, + intel_dp_use_post_lt_adj_req(intel_dp, crtc_state)); } /* @@ -1091,6 +1103,109 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp, return channel_eq; } +static bool +intel_dp_post_lt_adj_req(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + u8 link_status[DP_LINK_STATUS_SIZE]; + unsigned long deadline; + bool timeout = false; + bool success = false; + int changes = 0; + + if (!intel_dp_use_post_lt_adj_req(intel_dp, crtc_state)) + return true; + + if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX, + link_status) < 0) { + lt_err(intel_dp, DP_PHY_DPRX, "Failed to get link status\n"); + return false; + } + + deadline = jiffies + msecs_to_jiffies_timeout(200); + + for (;;) { + /* Make sure clock is still ok */ + if (!drm_dp_clock_recovery_ok(link_status, + crtc_state->lane_count)) { + intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status); + lt_dbg(intel_dp, DP_PHY_DPRX, + "Clock recovery check failed, cannot continue POST_LT_ADJ_REQ\n"); + break; + } + + if (!drm_dp_channel_eq_ok(link_status, + crtc_state->lane_count)) { + intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status); + lt_dbg(intel_dp, DP_PHY_DPRX, "Channel EQ check failed. cannot continue POST_LT_ADJ_REQ\n"); + break; + } + + if (!drm_dp_post_lt_adj_req_in_progress(link_status)) { + success = true; + intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status); + lt_dbg(intel_dp, DP_PHY_DPRX, + "POST_LT_ADJ_REQ done (%d changes). DP Training successful\n", changes); + break; + } + + if (changes == 6) { + success = true; + intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status); + lt_dbg(intel_dp, DP_PHY_DPRX, + "POST_LT_ADJ_REQ limit reached (%d changes). DP Training successful\n", changes); + break; + } + + if (timeout) { + success = true; + intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status); + lt_dbg(intel_dp, DP_PHY_DPRX, + "POST_LT_ADJ_REQ timeout reached (%d changes). DP Training successful\n", changes); + break; + } + + fsleep(5000); + + if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX, + link_status) < 0) { + lt_err(intel_dp, DP_PHY_DPRX, "Failed to get link status\n"); + break; + } + + /* Update training set as requested by target */ + if (intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX, link_status)) { + deadline = jiffies + msecs_to_jiffies_timeout(200); + changes++; + + if (!intel_dp_update_link_train(intel_dp, crtc_state, DP_PHY_DPRX)) { + lt_err(intel_dp, DP_PHY_DPRX, "Failed to update link training\n"); + break; + } + } else if (time_after(jiffies, deadline)) { + timeout = true; + } + } + + return success; +} + +static void intel_dp_stop_post_lt_adj_req(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + u8 lane_count; + + if (!intel_dp_use_post_lt_adj_req(intel_dp, crtc_state)) + return; + + /* clear DP_POST_LT_ADJ_REQ_GRANTED */ + lane_count = crtc_state->lane_count; + if (crtc_state->enhanced_framing) + lane_count |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + + drm_dp_dpcd_writeb(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count); +} + static bool intel_dp_disable_dpcd_training_pattern(struct intel_dp *intel_dp, enum drm_dp_phy dp_phy) { @@ -1389,6 +1504,11 @@ intel_dp_link_train_all_phys(struct intel_dp *intel_dp, intel_dp_disable_dpcd_training_pattern(intel_dp, DP_PHY_DPRX); intel_dp->set_idle_link_train(intel_dp, crtc_state); + if (ret) + ret = intel_dp_post_lt_adj_req(intel_dp, crtc_state); + + intel_dp_stop_post_lt_adj_req(intel_dp, crtc_state); + return ret; } 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 1ba22ed6db08..33dcbde6a408 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h @@ -21,7 +21,7 @@ void intel_dp_link_training_set_mode(struct intel_dp *intel_dp, int link_rate, bool is_vrr); 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 enhanced_framing, bool post_lt_adj_req); bool intel_dp_get_adjust_train(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 887b6de14e46..e8de17834dcd 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -2144,7 +2144,7 @@ void intel_dp_mst_prepare_probe(struct intel_dp *intel_dp) intel_dp_link_training_set_mode(intel_dp, link_rate, false); intel_dp_link_training_set_bw(intel_dp, link_bw, rate_select, lane_count, - drm_dp_enhanced_frame_cap(intel_dp->dpcd)); + drm_dp_enhanced_frame_cap(intel_dp->dpcd), false); intel_mst_set_probed_link_params(intel_dp, link_rate, lane_count); } From e4de0fadeb6f8eec909368cb07b2d08320582897 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Mar 2026 14:40:54 +0300 Subject: [PATCH 010/144] drm/{i915, xe}: convert VLV sideband display wrappers into real functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the VLV sideband static inline wrappers into real functions. This will help the follow-up work of moving the VLV sideband to the display parent interface. The downside is that we'll have to build vlv_sideband.c as part of xe build, to avoid a plethora of stubs. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/57740dc3a820cb5fc1cfcd28e4be58b2cb48020d.1774957233.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/vlv_sideband.c | 125 +++++++++++++++ drivers/gpu/drm/i915/display/vlv_sideband.h | 159 ++++---------------- drivers/gpu/drm/xe/Makefile | 3 +- 3 files changed, 153 insertions(+), 134 deletions(-) diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.c b/drivers/gpu/drm/i915/display/vlv_sideband.c index e18045f2b89d..2472e0412728 100644 --- a/drivers/gpu/drm/i915/display/vlv_sideband.c +++ b/drivers/gpu/drm/i915/display/vlv_sideband.c @@ -8,6 +8,71 @@ #include "intel_dpio_phy.h" #include "vlv_sideband.h" +void vlv_bunit_get(struct drm_device *drm) +{ + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_BUNIT)); +} + +u32 vlv_bunit_read(struct drm_device *drm, u32 reg) +{ + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_BUNIT, reg); +} + +void vlv_bunit_write(struct drm_device *drm, u32 reg, u32 val) +{ + vlv_iosf_sb_write(drm, VLV_IOSF_SB_BUNIT, reg, val); +} + +void vlv_bunit_put(struct drm_device *drm) +{ + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_BUNIT)); +} + +void vlv_cck_get(struct drm_device *drm) +{ + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCK)); +} + +u32 vlv_cck_read(struct drm_device *drm, u32 reg) +{ + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCK, reg); +} + +void vlv_cck_write(struct drm_device *drm, u32 reg, u32 val) +{ + vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCK, reg, val); +} + +void vlv_cck_put(struct drm_device *drm) +{ + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCK)); +} + +void vlv_ccu_get(struct drm_device *drm) +{ + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCU)); +} + +u32 vlv_ccu_read(struct drm_device *drm, u32 reg) +{ + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCU, reg); +} + +void vlv_ccu_write(struct drm_device *drm, u32 reg, u32 val) +{ + vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCU, reg, val); +} + +void vlv_ccu_put(struct drm_device *drm) +{ + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCU)); +} + +void vlv_dpio_get(struct drm_device *drm) +{ + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); +} + static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct intel_display *display, enum dpio_phy phy) { @@ -48,3 +113,63 @@ void vlv_dpio_write(struct drm_device *drm, vlv_iosf_sb_write(drm, unit, reg, val); } + +void vlv_dpio_put(struct drm_device *drm) +{ + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); +} + +void vlv_flisdsi_get(struct drm_device *drm) +{ + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_FLISDSI)); +} + +u32 vlv_flisdsi_read(struct drm_device *drm, u32 reg) +{ + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_FLISDSI, reg); +} + +void vlv_flisdsi_write(struct drm_device *drm, u32 reg, u32 val) +{ + vlv_iosf_sb_write(drm, VLV_IOSF_SB_FLISDSI, reg, val); +} + +void vlv_flisdsi_put(struct drm_device *drm) +{ + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_FLISDSI)); +} + +void vlv_nc_get(struct drm_device *drm) +{ + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_NC)); +} + +u32 vlv_nc_read(struct drm_device *drm, u8 addr) +{ + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_NC, addr); +} + +void vlv_nc_put(struct drm_device *drm) +{ + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_NC)); +} + +void vlv_punit_get(struct drm_device *drm) +{ + vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_PUNIT)); +} + +u32 vlv_punit_read(struct drm_device *drm, u32 addr) +{ + return vlv_iosf_sb_read(drm, VLV_IOSF_SB_PUNIT, addr); +} + +int vlv_punit_write(struct drm_device *drm, u32 addr, u32 val) +{ + return vlv_iosf_sb_write(drm, VLV_IOSF_SB_PUNIT, addr, val); +} + +void vlv_punit_put(struct drm_device *drm) +{ + vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_PUNIT)); +} diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.h b/drivers/gpu/drm/i915/display/vlv_sideband.h index 2c240d81fead..065273726379 100644 --- a/drivers/gpu/drm/i915/display/vlv_sideband.h +++ b/drivers/gpu/drm/i915/display/vlv_sideband.h @@ -4,7 +4,6 @@ #ifndef _VLV_SIDEBAND_H_ #define _VLV_SIDEBAND_H_ -#include #include #include "vlv_iosf_sb.h" @@ -13,144 +12,38 @@ enum dpio_phy; struct drm_device; -static inline void vlv_bunit_get(struct drm_device *drm) -{ - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_BUNIT)); -} +void vlv_bunit_get(struct drm_device *drm); +u32 vlv_bunit_read(struct drm_device *drm, u32 reg); +void vlv_bunit_write(struct drm_device *drm, u32 reg, u32 val); +void vlv_bunit_put(struct drm_device *drm); -static inline u32 vlv_bunit_read(struct drm_device *drm, u32 reg) -{ - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_BUNIT, reg); -} +void vlv_cck_get(struct drm_device *drm); +u32 vlv_cck_read(struct drm_device *drm, u32 reg); +void vlv_cck_write(struct drm_device *drm, u32 reg, u32 val); +void vlv_cck_put(struct drm_device *drm); -static inline void vlv_bunit_write(struct drm_device *drm, u32 reg, u32 val) -{ - vlv_iosf_sb_write(drm, VLV_IOSF_SB_BUNIT, reg, val); -} +void vlv_ccu_get(struct drm_device *drm); +u32 vlv_ccu_read(struct drm_device *drm, u32 reg); +void vlv_ccu_write(struct drm_device *drm, u32 reg, u32 val); +void vlv_ccu_put(struct drm_device *drm); -static inline void vlv_bunit_put(struct drm_device *drm) -{ - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_BUNIT)); -} - -static inline void vlv_cck_get(struct drm_device *drm) -{ - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCK)); -} - -static inline u32 vlv_cck_read(struct drm_device *drm, u32 reg) -{ - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCK, reg); -} - -static inline void vlv_cck_write(struct drm_device *drm, u32 reg, u32 val) -{ - vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCK, reg, val); -} - -static inline void vlv_cck_put(struct drm_device *drm) -{ - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCK)); -} - -static inline void vlv_ccu_get(struct drm_device *drm) -{ - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCU)); -} - -static inline u32 vlv_ccu_read(struct drm_device *drm, u32 reg) -{ - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCU, reg); -} - -static inline void vlv_ccu_write(struct drm_device *drm, u32 reg, u32 val) -{ - vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCU, reg, val); -} - -static inline void vlv_ccu_put(struct drm_device *drm) -{ - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCU)); -} - -static inline void vlv_dpio_get(struct drm_device *drm) -{ - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); -} - -#ifdef I915 +void vlv_dpio_get(struct drm_device *drm); u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg); -void vlv_dpio_write(struct drm_device *drm, - enum dpio_phy phy, int reg, u32 val); -#else -static inline u32 vlv_dpio_read(struct drm_device *drm, int phy, int reg) -{ - return 0; -} -static inline void vlv_dpio_write(struct drm_device *drm, - int phy, int reg, u32 val) -{ -} -#endif +void vlv_dpio_write(struct drm_device *drm, enum dpio_phy phy, int reg, u32 val); +void vlv_dpio_put(struct drm_device *drm); -static inline void vlv_dpio_put(struct drm_device *drm) -{ - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); -} +void vlv_flisdsi_get(struct drm_device *drm); +u32 vlv_flisdsi_read(struct drm_device *drm, u32 reg); +void vlv_flisdsi_write(struct drm_device *drm, u32 reg, u32 val); +void vlv_flisdsi_put(struct drm_device *drm); -static inline void vlv_flisdsi_get(struct drm_device *drm) -{ - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_FLISDSI)); -} +void vlv_nc_get(struct drm_device *drm); +u32 vlv_nc_read(struct drm_device *drm, u8 addr); +void vlv_nc_put(struct drm_device *drm); -static inline u32 vlv_flisdsi_read(struct drm_device *drm, u32 reg) -{ - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_FLISDSI, reg); -} - -static inline void vlv_flisdsi_write(struct drm_device *drm, u32 reg, u32 val) -{ - vlv_iosf_sb_write(drm, VLV_IOSF_SB_FLISDSI, reg, val); -} - -static inline void vlv_flisdsi_put(struct drm_device *drm) -{ - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_FLISDSI)); -} - -static inline void vlv_nc_get(struct drm_device *drm) -{ - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_NC)); -} - -static inline u32 vlv_nc_read(struct drm_device *drm, u8 addr) -{ - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_NC, addr); -} - -static inline void vlv_nc_put(struct drm_device *drm) -{ - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_NC)); -} - -static inline void vlv_punit_get(struct drm_device *drm) -{ - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_PUNIT)); -} - -static inline u32 vlv_punit_read(struct drm_device *drm, u32 addr) -{ - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_PUNIT, addr); -} - -static inline int vlv_punit_write(struct drm_device *drm, u32 addr, u32 val) -{ - return vlv_iosf_sb_write(drm, VLV_IOSF_SB_PUNIT, addr, val); -} - -static inline void vlv_punit_put(struct drm_device *drm) -{ - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_PUNIT)); -} +void vlv_punit_get(struct drm_device *drm); +u32 vlv_punit_read(struct drm_device *drm, u32 addr); +int vlv_punit_write(struct drm_device *drm, u32 addr, u32 val); +void vlv_punit_put(struct drm_device *drm); #endif /* _VLV_SIDEBAND_H_ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 49de1c22a469..3bbd45ea327a 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -330,7 +330,8 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/skl_prefill.o \ i915-display/skl_scaler.o \ i915-display/skl_universal_plane.o \ - i915-display/skl_watermark.o + i915-display/skl_watermark.o \ + i915-display/vlv_sideband.o ifeq ($(CONFIG_ACPI),y) xe-$(CONFIG_DRM_XE_DISPLAY) += \ From 1edb41ff02ec4fcb91b6d5e8944cb255ba1ed0e8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Mar 2026 14:40:55 +0300 Subject: [PATCH 011/144] drm/i915: pass struct intel_display * to VLV sideband wrappers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In display code, the display pointer will be all around more convenient. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/a355fe0642f7e6566a22e85bda455092e49e3b68.1774957233.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_wm.c | 32 ++-- drivers/gpu/drm/i915/display/intel_cdclk.c | 32 ++-- .../drm/i915/display/intel_display_power.c | 6 +- .../i915/display/intel_display_power_well.c | 64 +++---- drivers/gpu/drm/i915/display/intel_dpio_phy.c | 174 +++++++++--------- drivers/gpu/drm/i915/display/intel_dpll.c | 116 ++++++------ drivers/gpu/drm/i915/display/vlv_clock.c | 13 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 20 +- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 38 ++-- drivers/gpu/drm/i915/display/vlv_sideband.c | 110 ++++++----- drivers/gpu/drm/i915/display/vlv_sideband.h | 56 +++--- 11 files changed, 330 insertions(+), 331 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 9e170e79dcf6..c39d56e2ea26 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -118,41 +118,41 @@ static void chv_set_memory_dvfs(struct intel_display *display, bool enable) u32 val; int ret; - vlv_punit_get(display->drm); + vlv_punit_get(display); - val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2); + val = vlv_punit_read(display, PUNIT_REG_DDR_SETUP2); if (enable) val &= ~FORCE_DDR_HIGH_FREQ; else val |= FORCE_DDR_HIGH_FREQ; val &= ~FORCE_DDR_LOW_FREQ; val |= FORCE_DDR_FREQ_REQ_ACK; - vlv_punit_write(display->drm, PUNIT_REG_DDR_SETUP2, val); + vlv_punit_write(display, PUNIT_REG_DDR_SETUP2, val); - ret = poll_timeout_us(val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2), + ret = poll_timeout_us(val = vlv_punit_read(display, PUNIT_REG_DDR_SETUP2), (val & FORCE_DDR_FREQ_REQ_ACK) == 0, 500, 3000, false); if (ret) drm_err(display->drm, "timed out waiting for Punit DDR DVFS request\n"); - vlv_punit_put(display->drm); + vlv_punit_put(display); } static void chv_set_memory_pm5(struct intel_display *display, bool enable) { u32 val; - vlv_punit_get(display->drm); + vlv_punit_get(display); - val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display, PUNIT_REG_DSPSSPM); if (enable) val |= DSP_MAXFIFO_PM5_ENABLE; else val &= ~DSP_MAXFIFO_PM5_ENABLE; - vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val); + vlv_punit_write(display, PUNIT_REG_DSPSSPM, val); - vlv_punit_put(display->drm); + vlv_punit_put(display); } #define FW_WM(value, plane) \ @@ -3918,9 +3918,9 @@ static void vlv_wm_get_hw_state(struct intel_display *display) wm->level = VLV_WM_LEVEL_PM2; if (display->platform.cherryview) { - vlv_punit_get(display->drm); + vlv_punit_get(display); - val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display, PUNIT_REG_DSPSSPM); if (val & DSP_MAXFIFO_PM5_ENABLE) wm->level = VLV_WM_LEVEL_PM5; @@ -3933,11 +3933,11 @@ static void vlv_wm_get_hw_state(struct intel_display *display) * HIGH/LOW bits so that we don't actually change * the current state. */ - val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2); + val = vlv_punit_read(display, PUNIT_REG_DDR_SETUP2); val |= FORCE_DDR_FREQ_REQ_ACK; - vlv_punit_write(display->drm, PUNIT_REG_DDR_SETUP2, val); + vlv_punit_write(display, PUNIT_REG_DDR_SETUP2, val); - ret = poll_timeout_us(val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2), + ret = poll_timeout_us(val = vlv_punit_read(display, PUNIT_REG_DDR_SETUP2), (val & FORCE_DDR_FREQ_REQ_ACK) == 0, 500, 3000, false); if (ret) { @@ -3946,12 +3946,12 @@ static void vlv_wm_get_hw_state(struct intel_display *display) "assuming DDR DVFS is disabled\n"); display->wm.num_levels = VLV_WM_LEVEL_PM5 + 1; } else { - val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2); + val = vlv_punit_read(display, PUNIT_REG_DDR_SETUP2); if ((val & FORCE_DDR_HIGH_FREQ) == 0) wm->level = VLV_WM_LEVEL_DDR_DVFS; } - vlv_punit_put(display->drm); + vlv_punit_put(display); } for_each_intel_crtc(display->drm, crtc) { diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index a47736613f6e..8e0424a2c16f 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -613,9 +613,9 @@ static void vlv_get_cdclk(struct intel_display *display, cdclk_config->vco = vlv_clock_get_hpll_vco(display->drm); cdclk_config->cdclk = vlv_clock_get_cdclk(display->drm); - vlv_punit_get(display->drm); - val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); - vlv_punit_put(display->drm); + vlv_punit_get(display); + val = vlv_punit_read(display, PUNIT_REG_DSPSSPM); + vlv_punit_put(display); if (display->platform.valleyview) cdclk_config->voltage_level = (val & DSPFREQGUAR_MASK) >> @@ -696,12 +696,12 @@ static void vlv_set_cdclk(struct intel_display *display, BIT(VLV_IOSF_SB_BUNIT) | BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); + val = vlv_punit_read(display, PUNIT_REG_DSPSSPM); val &= ~DSPFREQGUAR_MASK; val |= (cmd << DSPFREQGUAR_SHIFT); - vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val); + vlv_punit_write(display, PUNIT_REG_DSPSSPM, val); - ret = poll_timeout_us(val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM), + ret = poll_timeout_us(val = vlv_punit_read(display, PUNIT_REG_DSPSSPM), (val & DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT), 500, 50 * 1000, false); if (ret) @@ -714,12 +714,12 @@ static void vlv_set_cdclk(struct intel_display *display, cdclk) - 1; /* adjust cdclk divider */ - val = vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL); + val = vlv_cck_read(display, CCK_DISPLAY_CLOCK_CONTROL); val &= ~CCK_FREQUENCY_VALUES; val |= divider; - vlv_cck_write(display->drm, CCK_DISPLAY_CLOCK_CONTROL, val); + vlv_cck_write(display, CCK_DISPLAY_CLOCK_CONTROL, val); - ret = poll_timeout_us(val = vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL), + ret = poll_timeout_us(val = vlv_cck_read(display, CCK_DISPLAY_CLOCK_CONTROL), (val & CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT), 500, 50 * 1000, false); if (ret) @@ -727,7 +727,7 @@ static void vlv_set_cdclk(struct intel_display *display, } /* adjust self-refresh exit latency value */ - val = vlv_bunit_read(display->drm, BUNIT_REG_BISOC); + val = vlv_bunit_read(display, BUNIT_REG_BISOC); val &= ~0x7f; /* @@ -738,7 +738,7 @@ static void vlv_set_cdclk(struct intel_display *display, val |= 4500 / 250; /* 4.5 usec */ else val |= 3000 / 250; /* 3.0 usec */ - vlv_bunit_write(display->drm, BUNIT_REG_BISOC, val); + vlv_bunit_write(display, BUNIT_REG_BISOC, val); vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK) | @@ -780,19 +780,19 @@ static void chv_set_cdclk(struct intel_display *display, */ wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE); - vlv_punit_get(display->drm); - val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); + vlv_punit_get(display); + val = vlv_punit_read(display, PUNIT_REG_DSPSSPM); val &= ~DSPFREQGUAR_MASK_CHV; val |= (cmd << DSPFREQGUAR_SHIFT_CHV); - vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val); + vlv_punit_write(display, PUNIT_REG_DSPSSPM, val); - ret = poll_timeout_us(val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM), + ret = poll_timeout_us(val = vlv_punit_read(display, PUNIT_REG_DSPSSPM), (val & DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV), 500, 50 * 1000, false); if (ret) drm_err(display->drm, "timed out waiting for CDCLK change\n"); - vlv_punit_put(display->drm); + vlv_punit_put(display); intel_update_cdclk(display); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index ec96b141c74c..b1c91de9d798 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1890,9 +1890,9 @@ static bool vlv_punit_is_power_gated(struct intel_display *display, u32 reg0) { bool ret; - vlv_punit_get(display->drm); - ret = (vlv_punit_read(display->drm, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE; - vlv_punit_put(display->drm); + vlv_punit_get(display); + ret = (vlv_punit_read(display, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE; + vlv_punit_put(display); return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index f855f0f88694..f96a5088d138 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -1189,28 +1189,28 @@ static void vlv_set_power_well(struct intel_display *display, state = enable ? PUNIT_PWRGT_PWR_ON(pw_idx) : PUNIT_PWRGT_PWR_GATE(pw_idx); - vlv_punit_get(display->drm); + vlv_punit_get(display); - val = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS); + val = vlv_punit_read(display, PUNIT_REG_PWRGT_STATUS); if ((val & mask) == state) goto out; - ctrl = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL); + ctrl = vlv_punit_read(display, PUNIT_REG_PWRGT_CTRL); ctrl &= ~mask; ctrl |= state; - vlv_punit_write(display->drm, PUNIT_REG_PWRGT_CTRL, ctrl); + vlv_punit_write(display, PUNIT_REG_PWRGT_CTRL, ctrl); - ret = poll_timeout_us(val = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS), + ret = poll_timeout_us(val = vlv_punit_read(display, PUNIT_REG_PWRGT_STATUS), (val & mask) == state, 500, 100 * 1000, false); if (ret) drm_err(display->drm, "timeout setting power well state %08x (%08x)\n", state, - vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL)); + vlv_punit_read(display, PUNIT_REG_PWRGT_CTRL)); out: - vlv_punit_put(display->drm); + vlv_punit_put(display); } static void vlv_power_well_enable(struct intel_display *display, @@ -1237,9 +1237,9 @@ static bool vlv_power_well_enabled(struct intel_display *display, mask = PUNIT_PWRGT_MASK(pw_idx); ctrl = PUNIT_PWRGT_PWR_ON(pw_idx); - vlv_punit_get(display->drm); + vlv_punit_get(display); - state = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS) & mask; + state = vlv_punit_read(display, PUNIT_REG_PWRGT_STATUS) & mask; /* * We only ever set the power-on and power-gate states, anything * else is unexpected. @@ -1253,10 +1253,10 @@ static bool vlv_power_well_enabled(struct intel_display *display, * A transient state at this point would mean some unexpected party * is poking at the power controls too. */ - ctrl = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL) & mask; + ctrl = vlv_punit_read(display, PUNIT_REG_PWRGT_CTRL) & mask; drm_WARN_ON(display->drm, ctrl != state); - vlv_punit_put(display->drm); + vlv_punit_put(display); return enabled; } @@ -1533,30 +1533,30 @@ static void chv_dpio_cmn_power_well_enable(struct intel_display *display, drm_err(display->drm, "Display PHY %d is not power up\n", phy); - vlv_dpio_get(display->drm); + vlv_dpio_get(display); /* Enable dynamic power down */ - tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW28); + tmp = vlv_dpio_read(display, phy, CHV_CMN_DW28); tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN | DPIO_SUS_CLK_CONFIG_GATE_CLKREQ; - vlv_dpio_write(display->drm, phy, CHV_CMN_DW28, tmp); + vlv_dpio_write(display, phy, CHV_CMN_DW28, tmp); if (id == VLV_DISP_PW_DPIO_CMN_BC) { - tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW6_CH1); + tmp = vlv_dpio_read(display, phy, CHV_CMN_DW6_CH1); tmp |= DPIO_DYNPWRDOWNEN_CH1; - vlv_dpio_write(display->drm, phy, CHV_CMN_DW6_CH1, tmp); + vlv_dpio_write(display, phy, CHV_CMN_DW6_CH1, tmp); } else { /* * Force the non-existing CL2 off. BXT does this * too, so maybe it saves some power even though * CL2 doesn't exist? */ - tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW30); + tmp = vlv_dpio_read(display, phy, CHV_CMN_DW30); tmp |= DPIO_CL2_LDOFUSE_PWRENB; - vlv_dpio_write(display->drm, phy, CHV_CMN_DW30, tmp); + vlv_dpio_write(display, phy, CHV_CMN_DW30, tmp); } - vlv_dpio_put(display->drm); + vlv_dpio_put(display); display->power.chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy); intel_de_write(display, DISPLAY_PHY_CONTROL, @@ -1624,9 +1624,9 @@ static void assert_chv_phy_powergate(struct intel_display *display, enum dpio_ph else reg = CHV_CMN_DW6_CH1; - vlv_dpio_get(display->drm); - val = vlv_dpio_read(display->drm, phy, reg); - vlv_dpio_put(display->drm); + vlv_dpio_get(display); + val = vlv_dpio_read(display, phy, reg); + vlv_dpio_put(display); /* * This assumes !override is only used when the port is disabled. @@ -1740,9 +1740,9 @@ static bool chv_pipe_power_well_enabled(struct intel_display *display, bool enabled; u32 state, ctrl; - vlv_punit_get(display->drm); + vlv_punit_get(display); - state = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe); + state = vlv_punit_read(display, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe); /* * We only ever set the power-on and power-gate states, anything * else is unexpected. @@ -1755,10 +1755,10 @@ static bool chv_pipe_power_well_enabled(struct intel_display *display, * A transient state at this point would mean some unexpected party * is poking at the power controls too. */ - ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSC_MASK(pipe); + ctrl = vlv_punit_read(display, PUNIT_REG_DSPSSPM) & DP_SSC_MASK(pipe); drm_WARN_ON(display->drm, ctrl << 16 != state); - vlv_punit_put(display->drm); + vlv_punit_put(display); return enabled; } @@ -1774,29 +1774,29 @@ static void chv_set_pipe_power_well(struct intel_display *display, state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe); - vlv_punit_get(display->drm); + vlv_punit_get(display); - ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); + ctrl = vlv_punit_read(display, PUNIT_REG_DSPSSPM); if ((ctrl & DP_SSS_MASK(pipe)) == state) goto out; ctrl &= ~DP_SSC_MASK(pipe); ctrl |= enable ? DP_SSC_PWR_ON(pipe) : DP_SSC_PWR_GATE(pipe); - vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, ctrl); + vlv_punit_write(display, PUNIT_REG_DSPSSPM, ctrl); - ret = poll_timeout_us(ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM), + ret = poll_timeout_us(ctrl = vlv_punit_read(display, PUNIT_REG_DSPSSPM), (ctrl & DP_SSS_MASK(pipe)) == state, 500, 100 * 1000, false); if (ret) drm_err(display->drm, "timeout setting power well state %08x (%08x)\n", state, - vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM)); + vlv_punit_read(display, PUNIT_REG_DSPSSPM)); #undef COND out: - vlv_punit_put(display->drm); + vlv_punit_put(display); } static void chv_pipe_power_well_sync_hw(struct intel_display *display, diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 8027bab2951b..0e16132d0923 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -724,46 +724,46 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, u32 val; int i; - vlv_dpio_get(display->drm); + vlv_dpio_get(display); /* Clear calc init */ - val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW10(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS01_DW10(ch)); val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; - vlv_dpio_write(display->drm, phy, VLV_PCS01_DW10(ch), val); + vlv_dpio_write(display, phy, VLV_PCS01_DW10(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW10(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS23_DW10(ch)); val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; - vlv_dpio_write(display->drm, phy, VLV_PCS23_DW10(ch), val); + vlv_dpio_write(display, phy, VLV_PCS23_DW10(ch), val); } - val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW9(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS01_DW9(ch)); val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; - vlv_dpio_write(display->drm, phy, VLV_PCS01_DW9(ch), val); + vlv_dpio_write(display, phy, VLV_PCS01_DW9(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW9(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS23_DW9(ch)); val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; - vlv_dpio_write(display->drm, phy, VLV_PCS23_DW9(ch), val); + vlv_dpio_write(display, phy, VLV_PCS23_DW9(ch), val); } /* Program swing deemph */ for (i = 0; i < crtc_state->lane_count; i++) { - val = vlv_dpio_read(display->drm, phy, CHV_TX_DW4(ch, i)); + val = vlv_dpio_read(display, phy, CHV_TX_DW4(ch, i)); val &= ~DPIO_SWING_DEEMPH9P5_MASK; val |= DPIO_SWING_DEEMPH9P5(deemph_reg_value); - vlv_dpio_write(display->drm, phy, CHV_TX_DW4(ch, i), val); + vlv_dpio_write(display, phy, CHV_TX_DW4(ch, i), val); } /* Program swing margin */ for (i = 0; i < crtc_state->lane_count; i++) { - val = vlv_dpio_read(display->drm, phy, CHV_TX_DW2(ch, i)); + val = vlv_dpio_read(display, phy, CHV_TX_DW2(ch, i)); val &= ~DPIO_SWING_MARGIN000_MASK; val |= DPIO_SWING_MARGIN000(margin_reg_value); @@ -776,7 +776,7 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, val &= ~DPIO_UNIQ_TRANS_SCALE_MASK; val |= DPIO_UNIQ_TRANS_SCALE(0x9a); - vlv_dpio_write(display->drm, phy, CHV_TX_DW2(ch, i), val); + vlv_dpio_write(display, phy, CHV_TX_DW2(ch, i), val); } /* @@ -786,26 +786,26 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, * 27 for ch0 and ch1. */ for (i = 0; i < crtc_state->lane_count; i++) { - val = vlv_dpio_read(display->drm, phy, CHV_TX_DW3(ch, i)); + val = vlv_dpio_read(display, phy, CHV_TX_DW3(ch, i)); if (uniq_trans_scale) val |= DPIO_TX_UNIQ_TRANS_SCALE_EN; else val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN; - vlv_dpio_write(display->drm, phy, CHV_TX_DW3(ch, i), val); + vlv_dpio_write(display, phy, CHV_TX_DW3(ch, i), val); } /* Start swing calculation */ - val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW10(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS01_DW10(ch)); val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; - vlv_dpio_write(display->drm, phy, VLV_PCS01_DW10(ch), val); + vlv_dpio_write(display, phy, VLV_PCS01_DW10(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW10(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS23_DW10(ch)); val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; - vlv_dpio_write(display->drm, phy, VLV_PCS23_DW10(ch), val); + vlv_dpio_write(display, phy, VLV_PCS23_DW10(ch), val); } - vlv_dpio_put(display->drm); + vlv_dpio_put(display); } static void __chv_data_lane_soft_reset(struct intel_encoder *encoder, @@ -818,38 +818,38 @@ static void __chv_data_lane_soft_reset(struct intel_encoder *encoder, enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); u32 val; - val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW0(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS01_DW0(ch)); if (reset) val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); else val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; - vlv_dpio_write(display->drm, phy, VLV_PCS01_DW0(ch), val); + vlv_dpio_write(display, phy, VLV_PCS01_DW0(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW0(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS23_DW0(ch)); if (reset) val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); else val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; - vlv_dpio_write(display->drm, phy, VLV_PCS23_DW0(ch), val); + vlv_dpio_write(display, phy, VLV_PCS23_DW0(ch), val); } - val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW1(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS01_DW1(ch)); val |= CHV_PCS_REQ_SOFTRESET_EN; if (reset) val &= ~DPIO_PCS_CLK_SOFT_RESET; else val |= DPIO_PCS_CLK_SOFT_RESET; - vlv_dpio_write(display->drm, phy, VLV_PCS01_DW1(ch), val); + vlv_dpio_write(display, phy, VLV_PCS01_DW1(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW1(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS23_DW1(ch)); val |= CHV_PCS_REQ_SOFTRESET_EN; if (reset) val &= ~DPIO_PCS_CLK_SOFT_RESET; else val |= DPIO_PCS_CLK_SOFT_RESET; - vlv_dpio_write(display->drm, phy, VLV_PCS23_DW1(ch), val); + vlv_dpio_write(display, phy, VLV_PCS23_DW1(ch), val); } } @@ -859,9 +859,9 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder, { struct intel_display *display = to_intel_display(encoder); - vlv_dpio_get(display->drm); + vlv_dpio_get(display); __chv_data_lane_soft_reset(encoder, crtc_state, reset); - vlv_dpio_put(display->drm); + vlv_dpio_put(display); } void chv_phy_pre_pll_enable(struct intel_encoder *encoder, @@ -887,47 +887,47 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, chv_phy_powergate_lanes(encoder, true, lane_mask); - vlv_dpio_get(display->drm); + vlv_dpio_get(display); /* Assert data lane reset */ __chv_data_lane_soft_reset(encoder, crtc_state, true); /* program left/right clock distribution */ if (pipe != PIPE_B) { - val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW5_CH0); + val = vlv_dpio_read(display, phy, CHV_CMN_DW5_CH0); val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); if (ch == DPIO_CH0) val |= CHV_BUFLEFTENA1_FORCE; if (ch == DPIO_CH1) val |= CHV_BUFRIGHTENA1_FORCE; - vlv_dpio_write(display->drm, phy, CHV_CMN_DW5_CH0, val); + vlv_dpio_write(display, phy, CHV_CMN_DW5_CH0, val); } else { - val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW1_CH1); + val = vlv_dpio_read(display, phy, CHV_CMN_DW1_CH1); val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); if (ch == DPIO_CH0) val |= CHV_BUFLEFTENA2_FORCE; if (ch == DPIO_CH1) val |= CHV_BUFRIGHTENA2_FORCE; - vlv_dpio_write(display->drm, phy, CHV_CMN_DW1_CH1, val); + vlv_dpio_write(display, phy, CHV_CMN_DW1_CH1, val); } /* program clock channel usage */ - val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW8(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS01_DW8(ch)); val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; if (pipe == PIPE_B) val |= DPIO_PCS_USEDCLKCHANNEL; else val &= ~DPIO_PCS_USEDCLKCHANNEL; - vlv_dpio_write(display->drm, phy, VLV_PCS01_DW8(ch), val); + vlv_dpio_write(display, phy, VLV_PCS01_DW8(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW8(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS23_DW8(ch)); val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; if (pipe == PIPE_B) val |= DPIO_PCS_USEDCLKCHANNEL; else val &= ~DPIO_PCS_USEDCLKCHANNEL; - vlv_dpio_write(display->drm, phy, VLV_PCS23_DW8(ch), val); + vlv_dpio_write(display, phy, VLV_PCS23_DW8(ch), val); } /* @@ -935,14 +935,14 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, * matches the pipe, but here we need to * pick the CL based on the port. */ - val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW19(ch)); + val = vlv_dpio_read(display, phy, CHV_CMN_DW19(ch)); if (pipe == PIPE_B) val |= CHV_CMN_USEDCLKCHANNEL; else val &= ~CHV_CMN_USEDCLKCHANNEL; - vlv_dpio_write(display->drm, phy, CHV_CMN_DW19(ch), val); + vlv_dpio_write(display, phy, CHV_CMN_DW19(ch), val); - vlv_dpio_put(display->drm); + vlv_dpio_put(display); } void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, @@ -956,17 +956,17 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, int data, i, stagger; u32 val; - vlv_dpio_get(display->drm); + vlv_dpio_get(display); /* allow hardware to manage TX FIFO reset source */ - val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW11(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS01_DW11(ch)); val &= ~DPIO_LANEDESKEW_STRAP_OVRD; - vlv_dpio_write(display->drm, phy, VLV_PCS01_DW11(ch), val); + vlv_dpio_write(display, phy, VLV_PCS01_DW11(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW11(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS23_DW11(ch)); val &= ~DPIO_LANEDESKEW_STRAP_OVRD; - vlv_dpio_write(display->drm, phy, VLV_PCS23_DW11(ch), val); + vlv_dpio_write(display, phy, VLV_PCS23_DW11(ch), val); } /* Program Tx lane latency optimal setting*/ @@ -976,7 +976,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, data = 0; else data = (i == 1) ? 0 : DPIO_UPAR; - vlv_dpio_write(display->drm, phy, CHV_TX_DW14(ch, i), data); + vlv_dpio_write(display, phy, CHV_TX_DW14(ch, i), data); } /* Data lane stagger programming */ @@ -991,17 +991,17 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, else stagger = 0x2; - val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW11(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS01_DW11(ch)); val |= DPIO_TX2_STAGGER_MASK(0x1f); - vlv_dpio_write(display->drm, phy, VLV_PCS01_DW11(ch), val); + vlv_dpio_write(display, phy, VLV_PCS01_DW11(ch), val); if (crtc_state->lane_count > 2) { - val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW11(ch)); + val = vlv_dpio_read(display, phy, VLV_PCS23_DW11(ch)); val |= DPIO_TX2_STAGGER_MASK(0x1f); - vlv_dpio_write(display->drm, phy, VLV_PCS23_DW11(ch), val); + vlv_dpio_write(display, phy, VLV_PCS23_DW11(ch), val); } - vlv_dpio_write(display->drm, phy, VLV_PCS01_DW12(ch), + vlv_dpio_write(display, phy, VLV_PCS01_DW12(ch), DPIO_LANESTAGGER_STRAP(stagger) | DPIO_LANESTAGGER_STRAP_OVRD | DPIO_TX1_STAGGER_MASK(0x1f) | @@ -1009,7 +1009,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, DPIO_TX2_STAGGER_MULT(0)); if (crtc_state->lane_count > 2) { - vlv_dpio_write(display->drm, phy, VLV_PCS23_DW12(ch), + vlv_dpio_write(display, phy, VLV_PCS23_DW12(ch), DPIO_LANESTAGGER_STRAP(stagger) | DPIO_LANESTAGGER_STRAP_OVRD | DPIO_TX1_STAGGER_MASK(0x1f) | @@ -1020,7 +1020,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, /* Deassert data lane reset */ __chv_data_lane_soft_reset(encoder, crtc_state, false); - vlv_dpio_put(display->drm); + vlv_dpio_put(display); } void chv_phy_release_cl2_override(struct intel_encoder *encoder) @@ -1042,20 +1042,20 @@ void chv_phy_post_pll_disable(struct intel_encoder *encoder, enum pipe pipe = to_intel_crtc(old_crtc_state->uapi.crtc)->pipe; u32 val; - vlv_dpio_get(display->drm); + vlv_dpio_get(display); /* disable left/right clock distribution */ if (pipe != PIPE_B) { - val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW5_CH0); + val = vlv_dpio_read(display, phy, CHV_CMN_DW5_CH0); val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); - vlv_dpio_write(display->drm, phy, CHV_CMN_DW5_CH0, val); + vlv_dpio_write(display, phy, CHV_CMN_DW5_CH0, val); } else { - val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW1_CH1); + val = vlv_dpio_read(display, phy, CHV_CMN_DW1_CH1); val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); - vlv_dpio_write(display->drm, phy, CHV_CMN_DW1_CH1, val); + vlv_dpio_write(display, phy, CHV_CMN_DW1_CH1, val); } - vlv_dpio_put(display->drm); + vlv_dpio_put(display); /* * Leave the power down bit cleared for at least one @@ -1079,22 +1079,22 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder, enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); - vlv_dpio_get(display->drm); + vlv_dpio_get(display); - vlv_dpio_write(display->drm, phy, VLV_TX_DW5_GRP(ch), 0x00000000); - vlv_dpio_write(display->drm, phy, VLV_TX_DW4_GRP(ch), demph_reg_value); - vlv_dpio_write(display->drm, phy, VLV_TX_DW2_GRP(ch), + vlv_dpio_write(display, phy, VLV_TX_DW5_GRP(ch), 0x00000000); + vlv_dpio_write(display, phy, VLV_TX_DW4_GRP(ch), demph_reg_value); + vlv_dpio_write(display, phy, VLV_TX_DW2_GRP(ch), uniqtranscale_reg_value); - vlv_dpio_write(display->drm, phy, VLV_TX_DW3_GRP(ch), 0x0C782040); + vlv_dpio_write(display, phy, VLV_TX_DW3_GRP(ch), 0x0C782040); if (tx3_demph) - vlv_dpio_write(display->drm, phy, VLV_TX_DW4(ch, 3), tx3_demph); + vlv_dpio_write(display, phy, VLV_TX_DW4(ch, 3), tx3_demph); - vlv_dpio_write(display->drm, phy, VLV_PCS_DW11_GRP(ch), 0x00030000); - vlv_dpio_write(display->drm, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value); - vlv_dpio_write(display->drm, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN); + vlv_dpio_write(display, phy, VLV_PCS_DW11_GRP(ch), 0x00030000); + vlv_dpio_write(display, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value); + vlv_dpio_write(display, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN); - vlv_dpio_put(display->drm); + vlv_dpio_put(display); } void vlv_phy_pre_pll_enable(struct intel_encoder *encoder, @@ -1106,23 +1106,23 @@ void vlv_phy_pre_pll_enable(struct intel_encoder *encoder, enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); /* Program Tx lane resets to default */ - vlv_dpio_get(display->drm); + vlv_dpio_get(display); - vlv_dpio_write(display->drm, phy, VLV_PCS_DW0_GRP(ch), + vlv_dpio_write(display, phy, VLV_PCS_DW0_GRP(ch), DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(display->drm, phy, VLV_PCS_DW1_GRP(ch), + vlv_dpio_write(display, phy, VLV_PCS_DW1_GRP(ch), DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | DPIO_PCS_CLK_DATAWIDTH_8_10 | DPIO_PCS_CLK_SOFT_RESET); /* Fix up inter-pair skew failure */ - vlv_dpio_write(display->drm, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00); - vlv_dpio_write(display->drm, phy, VLV_TX_DW11_GRP(ch), 0x00001500); - vlv_dpio_write(display->drm, phy, VLV_TX_DW14_GRP(ch), 0x40400000); + vlv_dpio_write(display, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00); + vlv_dpio_write(display, phy, VLV_TX_DW11_GRP(ch), 0x00001500); + vlv_dpio_write(display, phy, VLV_TX_DW14_GRP(ch), 0x40400000); - vlv_dpio_put(display->drm); + vlv_dpio_put(display); } void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder, @@ -1137,20 +1137,20 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder, enum pipe pipe = crtc->pipe; u32 val; - vlv_dpio_get(display->drm); + vlv_dpio_get(display); /* Enable clock channels for this port */ val = DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; if (pipe == PIPE_B) val |= DPIO_PCS_USEDCLKCHANNEL; val |= 0xc4; - vlv_dpio_write(display->drm, phy, VLV_PCS_DW8_GRP(ch), val); + vlv_dpio_write(display, phy, VLV_PCS_DW8_GRP(ch), val); /* Program lane clock */ - vlv_dpio_write(display->drm, phy, VLV_PCS_DW14_GRP(ch), 0x00760018); - vlv_dpio_write(display->drm, phy, VLV_PCS_DW23_GRP(ch), 0x00400888); + vlv_dpio_write(display, phy, VLV_PCS_DW14_GRP(ch), 0x00760018); + vlv_dpio_write(display, phy, VLV_PCS_DW23_GRP(ch), 0x00400888); - vlv_dpio_put(display->drm); + vlv_dpio_put(display); } void vlv_phy_reset_lanes(struct intel_encoder *encoder, @@ -1161,10 +1161,10 @@ void vlv_phy_reset_lanes(struct intel_encoder *encoder, enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); - vlv_dpio_get(display->drm); - vlv_dpio_write(display->drm, phy, VLV_PCS_DW0_GRP(ch), 0x00000000); - vlv_dpio_write(display->drm, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060); - vlv_dpio_put(display->drm); + vlv_dpio_get(display); + vlv_dpio_write(display, phy, VLV_PCS_DW0_GRP(ch), 0x00000000); + vlv_dpio_write(display, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060); + vlv_dpio_put(display); } void vlv_wait_port_ready(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index c7d37e74fbe9..a1aa88598013 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -528,9 +528,9 @@ void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state) if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0) return; - vlv_dpio_get(display->drm); - tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW3(ch)); - vlv_dpio_put(display->drm); + vlv_dpio_get(display); + tmp = vlv_dpio_read(display, phy, VLV_PLL_DW3(ch)); + vlv_dpio_put(display); clock.m1 = REG_FIELD_GET(DPIO_M1_DIV_MASK, tmp); clock.m2 = REG_FIELD_GET(DPIO_M2_DIV_MASK, tmp); @@ -556,13 +556,13 @@ void chv_crtc_clock_get(struct intel_crtc_state *crtc_state) if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0) return; - vlv_dpio_get(display->drm); - cmn_dw13 = vlv_dpio_read(display->drm, phy, CHV_CMN_DW13(ch)); - pll_dw0 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW0(ch)); - pll_dw1 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW1(ch)); - pll_dw2 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW2(ch)); - pll_dw3 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW3(ch)); - vlv_dpio_put(display->drm); + vlv_dpio_get(display); + cmn_dw13 = vlv_dpio_read(display, phy, CHV_CMN_DW13(ch)); + pll_dw0 = vlv_dpio_read(display, phy, CHV_PLL_DW0(ch)); + pll_dw1 = vlv_dpio_read(display, phy, CHV_PLL_DW1(ch)); + pll_dw2 = vlv_dpio_read(display, phy, CHV_PLL_DW2(ch)); + pll_dw3 = vlv_dpio_read(display, phy, CHV_PLL_DW3(ch)); + vlv_dpio_put(display); clock.m1 = REG_FIELD_GET(DPIO_CHV_M1_DIV_MASK, pll_dw1) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0; clock.m2 = REG_FIELD_GET(DPIO_CHV_M2_DIV_MASK, pll_dw0) << 22; @@ -1866,24 +1866,24 @@ static void vlv_pllb_recal_opamp(struct intel_display *display, * PLLB opamp always calibrates to max value of 0x3f, force enable it * and set it to a reasonable value instead. */ - tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW17(ch)); + tmp = vlv_dpio_read(display, phy, VLV_PLL_DW17(ch)); tmp &= 0xffffff00; tmp |= 0x00000030; - vlv_dpio_write(display->drm, phy, VLV_PLL_DW17(ch), tmp); + vlv_dpio_write(display, phy, VLV_PLL_DW17(ch), tmp); - tmp = vlv_dpio_read(display->drm, phy, VLV_REF_DW11); + tmp = vlv_dpio_read(display, phy, VLV_REF_DW11); tmp &= 0x00ffffff; tmp |= 0x8c000000; - vlv_dpio_write(display->drm, phy, VLV_REF_DW11, tmp); + vlv_dpio_write(display, phy, VLV_REF_DW11, tmp); - tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW17(ch)); + tmp = vlv_dpio_read(display, phy, VLV_PLL_DW17(ch)); tmp &= 0xffffff00; - vlv_dpio_write(display->drm, phy, VLV_PLL_DW17(ch), tmp); + vlv_dpio_write(display, phy, VLV_PLL_DW17(ch), tmp); - tmp = vlv_dpio_read(display->drm, phy, VLV_REF_DW11); + tmp = vlv_dpio_read(display, phy, VLV_REF_DW11); tmp &= 0x00ffffff; tmp |= 0xb0000000; - vlv_dpio_write(display->drm, phy, VLV_REF_DW11, tmp); + vlv_dpio_write(display, phy, VLV_REF_DW11, tmp); } static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state) @@ -1896,7 +1896,7 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state) enum pipe pipe = crtc->pipe; u32 tmp, coreclk; - vlv_dpio_get(display->drm); + vlv_dpio_get(display); /* See eDP HDMI DPIO driver vbios notes doc */ @@ -1905,15 +1905,15 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state) vlv_pllb_recal_opamp(display, phy, ch); /* Set up Tx target for periodic Rcomp update */ - vlv_dpio_write(display->drm, phy, VLV_PCS_DW17_BCAST, 0x0100000f); + vlv_dpio_write(display, phy, VLV_PCS_DW17_BCAST, 0x0100000f); /* Disable target IRef on PLL */ - tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW16(ch)); + tmp = vlv_dpio_read(display, phy, VLV_PLL_DW16(ch)); tmp &= 0x00ffffff; - vlv_dpio_write(display->drm, phy, VLV_PLL_DW16(ch), tmp); + vlv_dpio_write(display, phy, VLV_PLL_DW16(ch), tmp); /* Disable fast lock */ - vlv_dpio_write(display->drm, phy, VLV_CMN_DW0, 0x610); + vlv_dpio_write(display, phy, VLV_CMN_DW0, 0x610); /* Set idtafcrecal before PLL is enabled */ tmp = DPIO_M1_DIV(clock->m1) | @@ -1929,42 +1929,42 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state) * Note: don't use the DAC post divider as it seems unstable. */ tmp |= DPIO_S1_DIV(DPIO_S1_DIV_HDMIDP); - vlv_dpio_write(display->drm, phy, VLV_PLL_DW3(ch), tmp); + vlv_dpio_write(display, phy, VLV_PLL_DW3(ch), tmp); tmp |= DPIO_ENABLE_CALIBRATION; - vlv_dpio_write(display->drm, phy, VLV_PLL_DW3(ch), tmp); + vlv_dpio_write(display, phy, VLV_PLL_DW3(ch), tmp); /* Set HBR and RBR LPF coefficients */ if (crtc_state->port_clock == 162000 || intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG) || intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) - vlv_dpio_write(display->drm, phy, VLV_PLL_DW18(ch), 0x009f0003); + vlv_dpio_write(display, phy, VLV_PLL_DW18(ch), 0x009f0003); else - vlv_dpio_write(display->drm, phy, VLV_PLL_DW18(ch), 0x00d0000f); + vlv_dpio_write(display, phy, VLV_PLL_DW18(ch), 0x00d0000f); if (intel_crtc_has_dp_encoder(crtc_state)) { /* Use SSC source */ if (pipe == PIPE_A) - vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df40000); + vlv_dpio_write(display, phy, VLV_PLL_DW5(ch), 0x0df40000); else - vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df70000); + vlv_dpio_write(display, phy, VLV_PLL_DW5(ch), 0x0df70000); } else { /* HDMI or VGA */ /* Use bend source */ if (pipe == PIPE_A) - vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df70000); + vlv_dpio_write(display, phy, VLV_PLL_DW5(ch), 0x0df70000); else - vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df40000); + vlv_dpio_write(display, phy, VLV_PLL_DW5(ch), 0x0df40000); } - coreclk = vlv_dpio_read(display->drm, phy, VLV_PLL_DW7(ch)); + coreclk = vlv_dpio_read(display, phy, VLV_PLL_DW7(ch)); coreclk = (coreclk & 0x0000ff00) | 0x01c00000; if (intel_crtc_has_dp_encoder(crtc_state)) coreclk |= 0x01000000; - vlv_dpio_write(display->drm, phy, VLV_PLL_DW7(ch), coreclk); + vlv_dpio_write(display, phy, VLV_PLL_DW7(ch), coreclk); - vlv_dpio_write(display->drm, phy, VLV_PLL_DW19(ch), 0x87871000); + vlv_dpio_write(display, phy, VLV_PLL_DW19(ch), 0x87871000); - vlv_dpio_put(display->drm); + vlv_dpio_put(display); } static void _vlv_enable_pll(const struct intel_crtc_state *crtc_state) @@ -2019,44 +2019,44 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state) m2_frac = clock->m2 & 0x3fffff; - vlv_dpio_get(display->drm); + vlv_dpio_get(display); /* p1 and p2 divider */ - vlv_dpio_write(display->drm, phy, CHV_CMN_DW13(ch), + vlv_dpio_write(display, phy, CHV_CMN_DW13(ch), DPIO_CHV_S1_DIV(5) | DPIO_CHV_P1_DIV(clock->p1) | DPIO_CHV_P2_DIV(clock->p2) | DPIO_CHV_K_DIV(1)); /* Feedback post-divider - m2 */ - vlv_dpio_write(display->drm, phy, CHV_PLL_DW0(ch), + vlv_dpio_write(display, phy, CHV_PLL_DW0(ch), DPIO_CHV_M2_DIV(clock->m2 >> 22)); /* Feedback refclk divider - n and m1 */ - vlv_dpio_write(display->drm, phy, CHV_PLL_DW1(ch), + vlv_dpio_write(display, phy, CHV_PLL_DW1(ch), DPIO_CHV_M1_DIV(DPIO_CHV_M1_DIV_BY_2) | DPIO_CHV_N_DIV(1)); /* M2 fraction division */ - vlv_dpio_write(display->drm, phy, CHV_PLL_DW2(ch), + vlv_dpio_write(display, phy, CHV_PLL_DW2(ch), DPIO_CHV_M2_FRAC_DIV(m2_frac)); /* M2 fraction division enable */ - tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW3(ch)); + tmp = vlv_dpio_read(display, phy, CHV_PLL_DW3(ch)); tmp &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN); tmp |= DPIO_CHV_FEEDFWD_GAIN(2); if (m2_frac) tmp |= DPIO_CHV_FRAC_DIV_EN; - vlv_dpio_write(display->drm, phy, CHV_PLL_DW3(ch), tmp); + vlv_dpio_write(display, phy, CHV_PLL_DW3(ch), tmp); /* Program digital lock detect threshold */ - tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW9(ch)); + tmp = vlv_dpio_read(display, phy, CHV_PLL_DW9(ch)); tmp &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK | DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE); tmp |= DPIO_CHV_INT_LOCK_THRESHOLD(0x5); if (!m2_frac) tmp |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE; - vlv_dpio_write(display->drm, phy, CHV_PLL_DW9(ch), tmp); + vlv_dpio_write(display, phy, CHV_PLL_DW9(ch), tmp); /* Loop filter */ if (clock->vco == 5400000) { @@ -2081,19 +2081,19 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state) DPIO_CHV_GAIN_CTRL(0x3); tribuf_calcntr = 0; } - vlv_dpio_write(display->drm, phy, CHV_PLL_DW6(ch), loopfilter); + vlv_dpio_write(display, phy, CHV_PLL_DW6(ch), loopfilter); - tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW8(ch)); + tmp = vlv_dpio_read(display, phy, CHV_PLL_DW8(ch)); tmp &= ~DPIO_CHV_TDC_TARGET_CNT_MASK; tmp |= DPIO_CHV_TDC_TARGET_CNT(tribuf_calcntr); - vlv_dpio_write(display->drm, phy, CHV_PLL_DW8(ch), tmp); + vlv_dpio_write(display, phy, CHV_PLL_DW8(ch), tmp); /* AFC Recal */ - vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), - vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)) | + vlv_dpio_write(display, phy, CHV_CMN_DW14(ch), + vlv_dpio_read(display, phy, CHV_CMN_DW14(ch)) | DPIO_AFC_RECAL); - vlv_dpio_put(display->drm); + vlv_dpio_put(display); } static void _chv_enable_pll(const struct intel_crtc_state *crtc_state) @@ -2106,14 +2106,14 @@ static void _chv_enable_pll(const struct intel_crtc_state *crtc_state) enum pipe pipe = crtc->pipe; u32 tmp; - vlv_dpio_get(display->drm); + vlv_dpio_get(display); /* Enable back the 10bit clock to display controller */ - tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)); + tmp = vlv_dpio_read(display, phy, CHV_CMN_DW14(ch)); tmp |= DPIO_DCLKP_EN; - vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), tmp); + vlv_dpio_write(display, phy, CHV_CMN_DW14(ch), tmp); - vlv_dpio_put(display->drm); + vlv_dpio_put(display); /* * Need to wait > 100ns between dclkp clock enable bit and PLL enable. @@ -2247,14 +2247,14 @@ void chv_disable_pll(struct intel_display *display, enum pipe pipe) intel_de_write(display, DPLL(display, pipe), val); intel_de_posting_read(display, DPLL(display, pipe)); - vlv_dpio_get(display->drm); + vlv_dpio_get(display); /* Disable 10bit clock to display controller */ - val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)); + val = vlv_dpio_read(display, phy, CHV_CMN_DW14(ch)); val &= ~DPIO_DCLKP_EN; - vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), val); + vlv_dpio_write(display, phy, CHV_CMN_DW14(ch), val); - vlv_dpio_put(display->drm); + vlv_dpio_put(display); } void i9xx_disable_pll(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/vlv_clock.c b/drivers/gpu/drm/i915/display/vlv_clock.c index 1abdae453514..a589cdb74903 100644 --- a/drivers/gpu/drm/i915/display/vlv_clock.c +++ b/drivers/gpu/drm/i915/display/vlv_clock.c @@ -22,11 +22,11 @@ int vlv_clock_get_hpll_vco(struct drm_device *drm) int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; if (!display->vlv_clock.hpll_freq) { - vlv_cck_get(drm); + vlv_cck_get(display); /* Obtain SKU information */ - hpll_freq = vlv_cck_read(drm, CCK_FUSE_REG) & + hpll_freq = vlv_cck_read(display, CCK_FUSE_REG) & CCK_FUSE_HPLL_FREQ_MASK; - vlv_cck_put(drm); + vlv_cck_put(display); display->vlv_clock.hpll_freq = vco_freq[hpll_freq] * 1000; @@ -39,12 +39,13 @@ int vlv_clock_get_hpll_vco(struct drm_device *drm) static int vlv_clock_get_cck(struct drm_device *drm, const char *name, u32 reg, int ref_freq) { + struct intel_display *display = to_intel_display(drm); u32 val; int divider; - vlv_cck_get(drm); - val = vlv_cck_read(drm, reg); - vlv_cck_put(drm); + vlv_cck_get(display); + val = vlv_cck_read(display, reg); + vlv_cck_put(display); divider = val & CCK_FREQUENCY_VALUES; diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index d4db73c184e5..76e8cd0f65a4 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -254,16 +254,16 @@ static int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs, static void band_gap_reset(struct intel_display *display) { - vlv_flisdsi_get(display->drm); + vlv_flisdsi_get(display); - vlv_flisdsi_write(display->drm, 0x08, 0x0001); - vlv_flisdsi_write(display->drm, 0x0F, 0x0005); - vlv_flisdsi_write(display->drm, 0x0F, 0x0025); + vlv_flisdsi_write(display, 0x08, 0x0001); + vlv_flisdsi_write(display, 0x0F, 0x0005); + vlv_flisdsi_write(display, 0x0F, 0x0025); udelay(150); - vlv_flisdsi_write(display->drm, 0x0F, 0x0000); - vlv_flisdsi_write(display->drm, 0x08, 0x0000); + vlv_flisdsi_write(display, 0x0F, 0x0000); + vlv_flisdsi_write(display, 0x08, 0x0000); - vlv_flisdsi_put(display->drm); + vlv_flisdsi_put(display); } static int intel_dsi_compute_config(struct intel_encoder *encoder, @@ -461,11 +461,11 @@ static void vlv_dsi_device_ready(struct intel_encoder *encoder) drm_dbg_kms(display->drm, "\n"); - vlv_flisdsi_get(display->drm); + vlv_flisdsi_get(display); /* program rcomp for compliance, reduce from 50 ohms to 45 ohms * needed everytime after power gate */ - vlv_flisdsi_write(display->drm, 0x04, 0x0004); - vlv_flisdsi_put(display->drm); + vlv_flisdsi_write(display, 0x04, 0x0004); + vlv_flisdsi_put(display); /* bandgap reset is needed after everytime we do power gate */ band_gap_reset(display); diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index a2da6285890b..68b73cca2aec 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -219,11 +219,11 @@ void vlv_dsi_pll_enable(struct intel_encoder *encoder, drm_dbg_kms(display->drm, "\n"); - vlv_cck_get(display->drm); + vlv_cck_get(display); - vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, 0); - vlv_cck_write(display->drm, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div); - vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, + vlv_cck_write(display, CCK_REG_DSI_PLL_CONTROL, 0); + vlv_cck_write(display, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div); + vlv_cck_write(display, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl & ~DSI_PLL_VCO_EN); /* wait at least 0.5 us after ungating before enabling VCO, @@ -231,17 +231,17 @@ void vlv_dsi_pll_enable(struct intel_encoder *encoder, */ usleep_range(10, 50); - vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl); + vlv_cck_write(display, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl); - ret = poll_timeout_us(val = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL), + ret = poll_timeout_us(val = vlv_cck_read(display, CCK_REG_DSI_PLL_CONTROL), val & DSI_PLL_LOCK, 500, 20 * 1000, false); if (ret) { - vlv_cck_put(display->drm); + vlv_cck_put(display); drm_err(display->drm, "DSI PLL lock failed\n"); return; } - vlv_cck_put(display->drm); + vlv_cck_put(display); drm_dbg_kms(display->drm, "DSI PLL locked\n"); } @@ -253,14 +253,14 @@ void vlv_dsi_pll_disable(struct intel_encoder *encoder) drm_dbg_kms(display->drm, "\n"); - vlv_cck_get(display->drm); + vlv_cck_get(display); - tmp = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL); + tmp = vlv_cck_read(display, CCK_REG_DSI_PLL_CONTROL); tmp &= ~DSI_PLL_VCO_EN; tmp |= DSI_PLL_LDO_GATE; - vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, tmp); + vlv_cck_write(display, CCK_REG_DSI_PLL_CONTROL, tmp); - vlv_cck_put(display->drm); + vlv_cck_put(display); } static bool has_dsic_clock(struct intel_display *display) @@ -333,10 +333,10 @@ u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, drm_dbg_kms(display->drm, "\n"); - vlv_cck_get(display->drm); - pll_ctl = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL); - pll_div = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_DIVIDER); - vlv_cck_put(display->drm); + vlv_cck_get(display); + pll_ctl = vlv_cck_read(display, CCK_REG_DSI_PLL_CONTROL); + pll_div = vlv_cck_read(display, CCK_REG_DSI_PLL_DIVIDER); + vlv_cck_put(display); config->dsi_pll.ctrl = pll_ctl & ~DSI_PLL_LOCK; config->dsi_pll.div = pll_div; @@ -603,9 +603,9 @@ static void assert_dsi_pll(struct intel_display *display, bool state) { bool cur_state; - vlv_cck_get(display->drm); - cur_state = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_VCO_EN; - vlv_cck_put(display->drm); + vlv_cck_get(display); + cur_state = vlv_cck_read(display, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_VCO_EN; + vlv_cck_put(display); INTEL_DISPLAY_STATE_WARN(display, cur_state != state, "DSI PLL state assertion failure (expected %s, current %s)\n", diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.c b/drivers/gpu/drm/i915/display/vlv_sideband.c index 2472e0412728..a9c812da3c91 100644 --- a/drivers/gpu/drm/i915/display/vlv_sideband.c +++ b/drivers/gpu/drm/i915/display/vlv_sideband.c @@ -8,69 +8,69 @@ #include "intel_dpio_phy.h" #include "vlv_sideband.h" -void vlv_bunit_get(struct drm_device *drm) +void vlv_bunit_get(struct intel_display *display) { - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_BUNIT)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_BUNIT)); } -u32 vlv_bunit_read(struct drm_device *drm, u32 reg) +u32 vlv_bunit_read(struct intel_display *display, u32 reg) { - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_BUNIT, reg); + return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_BUNIT, reg); } -void vlv_bunit_write(struct drm_device *drm, u32 reg, u32 val) +void vlv_bunit_write(struct intel_display *display, u32 reg, u32 val) { - vlv_iosf_sb_write(drm, VLV_IOSF_SB_BUNIT, reg, val); + vlv_iosf_sb_write(display->drm, VLV_IOSF_SB_BUNIT, reg, val); } -void vlv_bunit_put(struct drm_device *drm) +void vlv_bunit_put(struct intel_display *display) { - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_BUNIT)); + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_BUNIT)); } -void vlv_cck_get(struct drm_device *drm) +void vlv_cck_get(struct intel_display *display) { - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCK)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK)); } -u32 vlv_cck_read(struct drm_device *drm, u32 reg) +u32 vlv_cck_read(struct intel_display *display, u32 reg) { - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCK, reg); + return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_CCK, reg); } -void vlv_cck_write(struct drm_device *drm, u32 reg, u32 val) +void vlv_cck_write(struct intel_display *display, u32 reg, u32 val) { - vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCK, reg, val); + vlv_iosf_sb_write(display->drm, VLV_IOSF_SB_CCK, reg, val); } -void vlv_cck_put(struct drm_device *drm) +void vlv_cck_put(struct intel_display *display) { - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCK)); + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK)); } -void vlv_ccu_get(struct drm_device *drm) +void vlv_ccu_get(struct intel_display *display) { - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCU)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCU)); } -u32 vlv_ccu_read(struct drm_device *drm, u32 reg) +u32 vlv_ccu_read(struct intel_display *display, u32 reg) { - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCU, reg); + return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_CCU, reg); } -void vlv_ccu_write(struct drm_device *drm, u32 reg, u32 val) +void vlv_ccu_write(struct intel_display *display, u32 reg, u32 val) { - vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCU, reg, val); + vlv_iosf_sb_write(display->drm, VLV_IOSF_SB_CCU, reg, val); } -void vlv_ccu_put(struct drm_device *drm) +void vlv_ccu_put(struct intel_display *display) { - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCU)); + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCU)); } -void vlv_dpio_get(struct drm_device *drm) +void vlv_dpio_get(struct intel_display *display) { - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct intel_display *display, @@ -86,13 +86,12 @@ static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct intel_display *display, return VLV_IOSF_SB_DPIO; } -u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg) +u32 vlv_dpio_read(struct intel_display *display, enum dpio_phy phy, int reg) { - struct intel_display *display = to_intel_display(drm); enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(display, phy); u32 val; - val = vlv_iosf_sb_read(drm, unit, reg); + val = vlv_iosf_sb_read(display->drm, unit, reg); /* * FIXME: There might be some registers where all 1's is a valid value, @@ -105,71 +104,70 @@ u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg) return val; } -void vlv_dpio_write(struct drm_device *drm, +void vlv_dpio_write(struct intel_display *display, enum dpio_phy phy, int reg, u32 val) { - struct intel_display *display = to_intel_display(drm); enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(display, phy); - vlv_iosf_sb_write(drm, unit, reg, val); + vlv_iosf_sb_write(display->drm, unit, reg, val); } -void vlv_dpio_put(struct drm_device *drm) +void vlv_dpio_put(struct intel_display *display) { - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } -void vlv_flisdsi_get(struct drm_device *drm) +void vlv_flisdsi_get(struct intel_display *display) { - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_FLISDSI)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_FLISDSI)); } -u32 vlv_flisdsi_read(struct drm_device *drm, u32 reg) +u32 vlv_flisdsi_read(struct intel_display *display, u32 reg) { - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_FLISDSI, reg); + return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_FLISDSI, reg); } -void vlv_flisdsi_write(struct drm_device *drm, u32 reg, u32 val) +void vlv_flisdsi_write(struct intel_display *display, u32 reg, u32 val) { - vlv_iosf_sb_write(drm, VLV_IOSF_SB_FLISDSI, reg, val); + vlv_iosf_sb_write(display->drm, VLV_IOSF_SB_FLISDSI, reg, val); } -void vlv_flisdsi_put(struct drm_device *drm) +void vlv_flisdsi_put(struct intel_display *display) { - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_FLISDSI)); + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_FLISDSI)); } -void vlv_nc_get(struct drm_device *drm) +void vlv_nc_get(struct intel_display *display) { - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_NC)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_NC)); } -u32 vlv_nc_read(struct drm_device *drm, u8 addr) +u32 vlv_nc_read(struct intel_display *display, u8 addr) { - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_NC, addr); + return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_NC, addr); } -void vlv_nc_put(struct drm_device *drm) +void vlv_nc_put(struct intel_display *display) { - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_NC)); + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_NC)); } -void vlv_punit_get(struct drm_device *drm) +void vlv_punit_get(struct intel_display *display) { - vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_PUNIT)); } -u32 vlv_punit_read(struct drm_device *drm, u32 addr) +u32 vlv_punit_read(struct intel_display *display, u32 addr) { - return vlv_iosf_sb_read(drm, VLV_IOSF_SB_PUNIT, addr); + return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_PUNIT, addr); } -int vlv_punit_write(struct drm_device *drm, u32 addr, u32 val) +int vlv_punit_write(struct intel_display *display, u32 addr, u32 val) { - return vlv_iosf_sb_write(drm, VLV_IOSF_SB_PUNIT, addr, val); + return vlv_iosf_sb_write(display->drm, VLV_IOSF_SB_PUNIT, addr, val); } -void vlv_punit_put(struct drm_device *drm) +void vlv_punit_put(struct intel_display *display) { - vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_PUNIT)); + vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_PUNIT)); } diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.h b/drivers/gpu/drm/i915/display/vlv_sideband.h index 065273726379..8751a070b0ae 100644 --- a/drivers/gpu/drm/i915/display/vlv_sideband.h +++ b/drivers/gpu/drm/i915/display/vlv_sideband.h @@ -10,40 +10,40 @@ #include "vlv_iosf_sb_reg.h" enum dpio_phy; -struct drm_device; +struct intel_display; -void vlv_bunit_get(struct drm_device *drm); -u32 vlv_bunit_read(struct drm_device *drm, u32 reg); -void vlv_bunit_write(struct drm_device *drm, u32 reg, u32 val); -void vlv_bunit_put(struct drm_device *drm); +void vlv_bunit_get(struct intel_display *display); +u32 vlv_bunit_read(struct intel_display *display, u32 reg); +void vlv_bunit_write(struct intel_display *display, u32 reg, u32 val); +void vlv_bunit_put(struct intel_display *display); -void vlv_cck_get(struct drm_device *drm); -u32 vlv_cck_read(struct drm_device *drm, u32 reg); -void vlv_cck_write(struct drm_device *drm, u32 reg, u32 val); -void vlv_cck_put(struct drm_device *drm); +void vlv_cck_get(struct intel_display *display); +u32 vlv_cck_read(struct intel_display *display, u32 reg); +void vlv_cck_write(struct intel_display *display, u32 reg, u32 val); +void vlv_cck_put(struct intel_display *display); -void vlv_ccu_get(struct drm_device *drm); -u32 vlv_ccu_read(struct drm_device *drm, u32 reg); -void vlv_ccu_write(struct drm_device *drm, u32 reg, u32 val); -void vlv_ccu_put(struct drm_device *drm); +void vlv_ccu_get(struct intel_display *display); +u32 vlv_ccu_read(struct intel_display *display, u32 reg); +void vlv_ccu_write(struct intel_display *display, u32 reg, u32 val); +void vlv_ccu_put(struct intel_display *display); -void vlv_dpio_get(struct drm_device *drm); -u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg); -void vlv_dpio_write(struct drm_device *drm, enum dpio_phy phy, int reg, u32 val); -void vlv_dpio_put(struct drm_device *drm); +void vlv_dpio_get(struct intel_display *display); +u32 vlv_dpio_read(struct intel_display *display, enum dpio_phy phy, int reg); +void vlv_dpio_write(struct intel_display *display, enum dpio_phy phy, int reg, u32 val); +void vlv_dpio_put(struct intel_display *display); -void vlv_flisdsi_get(struct drm_device *drm); -u32 vlv_flisdsi_read(struct drm_device *drm, u32 reg); -void vlv_flisdsi_write(struct drm_device *drm, u32 reg, u32 val); -void vlv_flisdsi_put(struct drm_device *drm); +void vlv_flisdsi_get(struct intel_display *display); +u32 vlv_flisdsi_read(struct intel_display *display, u32 reg); +void vlv_flisdsi_write(struct intel_display *display, u32 reg, u32 val); +void vlv_flisdsi_put(struct intel_display *display); -void vlv_nc_get(struct drm_device *drm); -u32 vlv_nc_read(struct drm_device *drm, u8 addr); -void vlv_nc_put(struct drm_device *drm); +void vlv_nc_get(struct intel_display *display); +u32 vlv_nc_read(struct intel_display *display, u8 addr); +void vlv_nc_put(struct intel_display *display); -void vlv_punit_get(struct drm_device *drm); -u32 vlv_punit_read(struct drm_device *drm, u32 addr); -int vlv_punit_write(struct drm_device *drm, u32 addr, u32 val); -void vlv_punit_put(struct drm_device *drm); +void vlv_punit_get(struct intel_display *display); +u32 vlv_punit_read(struct intel_display *display, u32 addr); +int vlv_punit_write(struct intel_display *display, u32 addr, u32 val); +void vlv_punit_put(struct intel_display *display); #endif /* _VLV_SIDEBAND_H_ */ From cad5a5ed3aed160c0ae371e60c9e94a967391b3d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Mar 2026 14:40:56 +0300 Subject: [PATCH 012/144] drm/i915/dram: prefer display abstractions for VLV sideband MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the display wrappers for VLV sideband in dram code. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/c971f1a1eccceeb5599ccea5909443afe24b20d3.1774957233.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dram.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c index bd281d4b4c05..1686f808a084 100644 --- a/drivers/gpu/drm/i915/display/intel_dram.c +++ b/drivers/gpu/drm/i915/display/intel_dram.c @@ -16,7 +16,7 @@ #include "intel_mchbar_regs.h" #include "intel_parent.h" #include "intel_uncore.h" -#include "vlv_iosf_sb.h" +#include "vlv_sideband.h" struct dram_dimm_info { u16 size; @@ -109,9 +109,9 @@ static unsigned int chv_mem_freq(struct intel_display *display) { u32 val; - vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK)); - val = vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG); - vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK)); + vlv_cck_get(display); + val = vlv_cck_read(display, CCK_FUSE_REG); + vlv_cck_put(display); switch ((val >> 2) & 0x7) { case 3: @@ -125,9 +125,9 @@ static unsigned int vlv_mem_freq(struct intel_display *display) { u32 val; - vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_PUNIT)); + vlv_punit_get(display); + val = vlv_punit_read(display, PUNIT_REG_GPU_FREQ_STS); + vlv_punit_put(display); switch ((val >> 6) & 3) { case 0: From 0563e28e0851ff327542f180974d14c525981a6f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Mar 2026 14:40:57 +0300 Subject: [PATCH 013/144] drm/i915: move VLV IOSF sideband to display parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove another direct dependency from display to i915 core by moving the VLV IOSF sideband calls to the display parent interface. Xe doesn't need this, so it'll remain optional and NULL. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/15dfc67b58f5b5b381be0f9bc66d60b43bebfecf.1774957233.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_cdclk.c | 16 +++--- drivers/gpu/drm/i915/display/intel_parent.c | 34 ++++++++++++ drivers/gpu/drm/i915/display/intel_parent.h | 7 +++ drivers/gpu/drm/i915/display/vlv_sideband.c | 55 ++++++++++---------- drivers/gpu/drm/i915/i915_driver.c | 1 + drivers/gpu/drm/i915/vlv_iosf_sb.c | 8 +++ drivers/gpu/drm/i915/vlv_iosf_sb.h | 2 + include/drm/intel/display_parent_interface.h | 11 ++++ 8 files changed, 99 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 8e0424a2c16f..4a663dddf896 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -691,10 +691,10 @@ static void vlv_set_cdclk(struct intel_display *display, */ wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE); - vlv_iosf_sb_get(display->drm, - BIT(VLV_IOSF_SB_CCK) | - BIT(VLV_IOSF_SB_BUNIT) | - BIT(VLV_IOSF_SB_PUNIT)); + intel_parent_vlv_iosf_get(display, + BIT(VLV_IOSF_SB_CCK) | + BIT(VLV_IOSF_SB_BUNIT) | + BIT(VLV_IOSF_SB_PUNIT)); val = vlv_punit_read(display, PUNIT_REG_DSPSSPM); val &= ~DSPFREQGUAR_MASK; @@ -740,10 +740,10 @@ static void vlv_set_cdclk(struct intel_display *display, val |= 3000 / 250; /* 3.0 usec */ vlv_bunit_write(display, BUNIT_REG_BISOC, val); - vlv_iosf_sb_put(display->drm, - BIT(VLV_IOSF_SB_CCK) | - BIT(VLV_IOSF_SB_BUNIT) | - BIT(VLV_IOSF_SB_PUNIT)); + intel_parent_vlv_iosf_put(display, + BIT(VLV_IOSF_SB_CCK) | + BIT(VLV_IOSF_SB_BUNIT) | + BIT(VLV_IOSF_SB_PUNIT)); intel_update_cdclk(display); diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 2e3bad2b3e6b..4e01423a0392 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -22,6 +22,7 @@ #include "intel_display_core.h" #include "intel_parent.h" +#include "vlv_iosf_sb.h" /* dpt */ struct intel_dpt *intel_parent_dpt_create(struct intel_display *display, @@ -338,6 +339,39 @@ void intel_parent_stolen_node_free(struct intel_display *display, const struct i display->parent->stolen->node_free(node); } +/* vlv iosf */ +void intel_parent_vlv_iosf_get(struct intel_display *display, unsigned long unit_mask) +{ + if (drm_WARN_ON_ONCE(display->drm, !display->parent->vlv_iosf)) + return; + + display->parent->vlv_iosf->get(display->drm, unit_mask); +} + +void intel_parent_vlv_iosf_put(struct intel_display *display, unsigned long unit_mask) +{ + if (drm_WARN_ON_ONCE(display->drm, !display->parent->vlv_iosf)) + return; + + display->parent->vlv_iosf->put(display->drm, unit_mask); +} + +u32 intel_parent_vlv_iosf_read(struct intel_display *display, enum vlv_iosf_sb_unit unit, u32 addr) +{ + if (drm_WARN_ON_ONCE(display->drm, !display->parent->vlv_iosf)) + return 0; + + return display->parent->vlv_iosf->read(display->drm, unit, addr); +} + +int intel_parent_vlv_iosf_write(struct intel_display *display, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) +{ + if (drm_WARN_ON_ONCE(display->drm, !display->parent->vlv_iosf)) + return -EINVAL; + + return display->parent->vlv_iosf->write(display->drm, unit, addr, val); +} + /* vma */ int intel_parent_vma_fence_id(struct intel_display *display, const struct i915_vma *vma) { diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index 2013e5ed5aa9..1e89d24163cc 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -6,6 +6,7 @@ #include +enum vlv_iosf_sb_unit; struct dma_fence; struct drm_file; struct drm_gem_object; @@ -109,6 +110,12 @@ u64 intel_parent_stolen_node_size(struct intel_display *display, const struct in struct intel_stolen_node *intel_parent_stolen_node_alloc(struct intel_display *display); void intel_parent_stolen_node_free(struct intel_display *display, const struct intel_stolen_node *node); +/* vlv iosf */ +void intel_parent_vlv_iosf_get(struct intel_display *display, unsigned long unit_mask); +void intel_parent_vlv_iosf_put(struct intel_display *display, unsigned long unit_mask); +u32 intel_parent_vlv_iosf_read(struct intel_display *display, enum vlv_iosf_sb_unit unit, u32 addr); +int intel_parent_vlv_iosf_write(struct intel_display *display, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); + /* vma */ int intel_parent_vma_fence_id(struct intel_display *display, const struct i915_vma *vma); diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.c b/drivers/gpu/drm/i915/display/vlv_sideband.c index a9c812da3c91..068f58bd9a2b 100644 --- a/drivers/gpu/drm/i915/display/vlv_sideband.c +++ b/drivers/gpu/drm/i915/display/vlv_sideband.c @@ -6,71 +6,72 @@ #include "intel_display_core.h" #include "intel_display_types.h" #include "intel_dpio_phy.h" +#include "intel_parent.h" #include "vlv_sideband.h" void vlv_bunit_get(struct intel_display *display) { - vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_BUNIT)); + intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_BUNIT)); } u32 vlv_bunit_read(struct intel_display *display, u32 reg) { - return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_BUNIT, reg); + return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_BUNIT, reg); } void vlv_bunit_write(struct intel_display *display, u32 reg, u32 val) { - vlv_iosf_sb_write(display->drm, VLV_IOSF_SB_BUNIT, reg, val); + intel_parent_vlv_iosf_write(display, VLV_IOSF_SB_BUNIT, reg, val); } void vlv_bunit_put(struct intel_display *display) { - vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_BUNIT)); + intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_BUNIT)); } void vlv_cck_get(struct intel_display *display) { - vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK)); + intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_CCK)); } u32 vlv_cck_read(struct intel_display *display, u32 reg) { - return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_CCK, reg); + return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_CCK, reg); } void vlv_cck_write(struct intel_display *display, u32 reg, u32 val) { - vlv_iosf_sb_write(display->drm, VLV_IOSF_SB_CCK, reg, val); + intel_parent_vlv_iosf_write(display, VLV_IOSF_SB_CCK, reg, val); } void vlv_cck_put(struct intel_display *display) { - vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK)); + intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_CCK)); } void vlv_ccu_get(struct intel_display *display) { - vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCU)); + intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_CCU)); } u32 vlv_ccu_read(struct intel_display *display, u32 reg) { - return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_CCU, reg); + return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_CCU, reg); } void vlv_ccu_write(struct intel_display *display, u32 reg, u32 val) { - vlv_iosf_sb_write(display->drm, VLV_IOSF_SB_CCU, reg, val); + intel_parent_vlv_iosf_write(display, VLV_IOSF_SB_CCU, reg, val); } void vlv_ccu_put(struct intel_display *display) { - vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCU)); + intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_CCU)); } void vlv_dpio_get(struct intel_display *display) { - vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); + intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct intel_display *display, @@ -91,7 +92,7 @@ u32 vlv_dpio_read(struct intel_display *display, enum dpio_phy phy, int reg) enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(display, phy); u32 val; - val = vlv_iosf_sb_read(display->drm, unit, reg); + val = intel_parent_vlv_iosf_read(display, unit, reg); /* * FIXME: There might be some registers where all 1's is a valid value, @@ -109,65 +110,65 @@ void vlv_dpio_write(struct intel_display *display, { enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(display, phy); - vlv_iosf_sb_write(display->drm, unit, reg, val); + intel_parent_vlv_iosf_write(display, unit, reg, val); } void vlv_dpio_put(struct intel_display *display) { - vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); + intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2)); } void vlv_flisdsi_get(struct intel_display *display) { - vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_FLISDSI)); + intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_FLISDSI)); } u32 vlv_flisdsi_read(struct intel_display *display, u32 reg) { - return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_FLISDSI, reg); + return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_FLISDSI, reg); } void vlv_flisdsi_write(struct intel_display *display, u32 reg, u32 val) { - vlv_iosf_sb_write(display->drm, VLV_IOSF_SB_FLISDSI, reg, val); + intel_parent_vlv_iosf_write(display, VLV_IOSF_SB_FLISDSI, reg, val); } void vlv_flisdsi_put(struct intel_display *display) { - vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_FLISDSI)); + intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_FLISDSI)); } void vlv_nc_get(struct intel_display *display) { - vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_NC)); + intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_NC)); } u32 vlv_nc_read(struct intel_display *display, u8 addr) { - return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_NC, addr); + return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_NC, addr); } void vlv_nc_put(struct intel_display *display) { - vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_NC)); + intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_NC)); } void vlv_punit_get(struct intel_display *display) { - vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_PUNIT)); + intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_PUNIT)); } u32 vlv_punit_read(struct intel_display *display, u32 addr) { - return vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_PUNIT, addr); + return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_PUNIT, addr); } int vlv_punit_write(struct intel_display *display, u32 addr, u32 val) { - return vlv_iosf_sb_write(display->drm, VLV_IOSF_SB_PUNIT, addr, val); + return intel_parent_vlv_iosf_write(display, VLV_IOSF_SB_PUNIT, addr, val); } void vlv_punit_put(struct intel_display *display) { - vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_PUNIT)); + intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_PUNIT)); } diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 385a634c3ed0..c10cab38935a 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -780,6 +780,7 @@ static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, .rps = &i915_display_rps_interface, .stolen = &i915_display_stolen_interface, + .vlv_iosf = &i915_display_vlv_iosf_interface, .vma = &i915_display_vma_interface, .fence_priority_display = fence_priority_display, diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index 38a75651b0dc..1f0332b4ad0d 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -4,6 +4,7 @@ */ #include +#include #include "i915_drv.h" #include "i915_iosf_mbi.h" @@ -229,3 +230,10 @@ void vlv_iosf_sb_fini(struct drm_i915_private *i915) if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) mutex_destroy(&i915->vlv_iosf_sb.lock); } + +const struct intel_display_vlv_iosf_interface i915_display_vlv_iosf_interface = { + .get = vlv_iosf_sb_get, + .put = vlv_iosf_sb_put, + .read = vlv_iosf_sb_read, + .write = vlv_iosf_sb_write, +}; diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index e2fea29a30ea..e4002d5b5a2e 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -34,4 +34,6 @@ void vlv_iosf_sb_put(struct drm_device *drm, unsigned long unit_mask); u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr); int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); +extern const struct intel_display_vlv_iosf_interface i915_display_vlv_iosf_interface; + #endif /* _VLV_IOSF_SB_H_ */ diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 97ec94a2e749..c0d18d5577f3 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -6,6 +6,7 @@ #include +enum vlv_iosf_sb_unit; struct dma_fence; struct drm_crtc; struct drm_device; @@ -176,6 +177,13 @@ struct intel_display_stolen_interface { void (*node_free)(const struct intel_stolen_node *node); }; +struct intel_display_vlv_iosf_interface { + void (*get)(struct drm_device *drm, unsigned long unit_mask); + void (*put)(struct drm_device *drm, unsigned long unit_mask); + u32 (*read)(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr); + int (*write)(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); +}; + struct intel_display_vma_interface { int (*fence_id)(const struct i915_vma *vma); }; @@ -235,6 +243,9 @@ struct intel_display_parent_interface { /** @stolen: Stolen memory. */ const struct intel_display_stolen_interface *stolen; + /** @vlv_iosf: VLV IOSF sideband. Optional. */ + const struct intel_display_vlv_iosf_interface *vlv_iosf; + /** @vma: VMA interface. Optional. */ const struct intel_display_vma_interface *vma; From 2c0c1e9a6663c1c62d53a92592ec60ae169a8ee9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Mar 2026 14:40:58 +0300 Subject: [PATCH 014/144] drm/{i915, xe}: add shared header for VLV IOSF sideband units and registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move vlv_iosf_sb_reg.h to include/drm/intel/vlv_iosf_sb_regs.h. Use _regs.h suffix to align better with other register headers. Move enum vlv_iosf_sb_unit there as well, breaking the final include tie related to IOSF sideband between display and i915 core. With this, we can completely remove the xe compat vls_iosf_sb*.h headers. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/41b060b0d6453de39ca775eab10ee12b25c45b7d.1774957233.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../i915/display/intel_display_power_map.c | 2 +- .../i915/display/intel_display_power_well.c | 1 - drivers/gpu/drm/i915/display/intel_parent.c | 2 +- drivers/gpu/drm/i915/display/vlv_sideband.h | 3 +- drivers/gpu/drm/i915/vlv_iosf_sb.h | 14 +------ .../drm/xe/compat-i915-headers/vlv_iosf_sb.h | 42 ------------------- .../xe/compat-i915-headers/vlv_iosf_sb_reg.h | 6 --- .../drm/intel/vlv_iosf_sb_regs.h | 18 ++++++-- 8 files changed, 19 insertions(+), 69 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb_reg.h rename drivers/gpu/drm/i915/vlv_iosf_sb_reg.h => include/drm/intel/vlv_iosf_sb_regs.h (95%) diff --git a/drivers/gpu/drm/i915/display/intel_display_power_map.c b/drivers/gpu/drm/i915/display/intel_display_power_map.c index 65204d68a759..3400080d78d2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_map.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c @@ -4,13 +4,13 @@ */ #include +#include #include "intel_display_core.h" #include "intel_display_power_map.h" #include "intel_display_power_well.h" #include "intel_display_regs.h" #include "intel_display_types.h" -#include "vlv_iosf_sb_reg.h" #define __LIST_INLINE_ELEMS(__elem_type, ...) \ ((__elem_type[]) { __VA_ARGS__ }) diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index f96a5088d138..6fbfd46461b0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -34,7 +34,6 @@ #include "intel_vga.h" #include "skl_watermark.h" #include "vlv_dpio_phy_regs.h" -#include "vlv_iosf_sb_reg.h" #include "vlv_sideband.h" /* diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 4e01423a0392..47ce3b6fdd5b 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -19,10 +19,10 @@ #include #include +#include #include "intel_display_core.h" #include "intel_parent.h" -#include "vlv_iosf_sb.h" /* dpt */ struct intel_dpt *intel_parent_dpt_create(struct intel_display *display, diff --git a/drivers/gpu/drm/i915/display/vlv_sideband.h b/drivers/gpu/drm/i915/display/vlv_sideband.h index 8751a070b0ae..60a66abc1649 100644 --- a/drivers/gpu/drm/i915/display/vlv_sideband.h +++ b/drivers/gpu/drm/i915/display/vlv_sideband.h @@ -6,8 +6,7 @@ #include -#include "vlv_iosf_sb.h" -#include "vlv_iosf_sb_reg.h" +#include enum dpio_phy; struct intel_display; diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.h b/drivers/gpu/drm/i915/vlv_iosf_sb.h index e4002d5b5a2e..8129ba11c750 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.h +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.h @@ -8,23 +8,11 @@ #include -#include "vlv_iosf_sb_reg.h" +#include struct drm_device; struct drm_i915_private; -enum vlv_iosf_sb_unit { - VLV_IOSF_SB_BUNIT, - VLV_IOSF_SB_CCK, - VLV_IOSF_SB_CCU, - VLV_IOSF_SB_DPIO, - VLV_IOSF_SB_DPIO_2, - VLV_IOSF_SB_FLISDSI, - VLV_IOSF_SB_GPIO, - VLV_IOSF_SB_NC, - VLV_IOSF_SB_PUNIT, -}; - void vlv_iosf_sb_init(struct drm_i915_private *i915); void vlv_iosf_sb_fini(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h deleted file mode 100644 index 69e1935e9cdf..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2013-2021 Intel Corporation - */ - -#ifndef _VLV_IOSF_SB_H_ -#define _VLV_IOSF_SB_H_ - -#include - -#include "vlv_iosf_sb_reg.h" - -struct drm_device; - -enum vlv_iosf_sb_unit { - VLV_IOSF_SB_BUNIT, - VLV_IOSF_SB_CCK, - VLV_IOSF_SB_CCU, - VLV_IOSF_SB_DPIO, - VLV_IOSF_SB_DPIO_2, - VLV_IOSF_SB_FLISDSI, - VLV_IOSF_SB_GPIO, - VLV_IOSF_SB_NC, - VLV_IOSF_SB_PUNIT, -}; - -static inline void vlv_iosf_sb_get(struct drm_device *drm, unsigned long ports) -{ -} -static inline u32 vlv_iosf_sb_read(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr) -{ - return 0; -} -static inline int vlv_iosf_sb_write(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val) -{ - return 0; -} -static inline void vlv_iosf_sb_put(struct drm_device *drm, unsigned long ports) -{ -} - -#endif /* _VLV_IOSF_SB_H_ */ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb_reg.h b/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb_reg.h deleted file mode 100644 index cb7fa8e794a6..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/vlv_iosf_sb_reg.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#include "../../i915/vlv_iosf_sb_reg.h" diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb_reg.h b/include/drm/intel/vlv_iosf_sb_regs.h similarity index 95% rename from drivers/gpu/drm/i915/vlv_iosf_sb_reg.h rename to include/drm/intel/vlv_iosf_sb_regs.h index f977fb3b6e17..42d1def5534b 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb_reg.h +++ b/include/drm/intel/vlv_iosf_sb_regs.h @@ -3,8 +3,20 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _VLV_IOSF_SB_REG_H_ -#define _VLV_IOSF_SB_REG_H_ +#ifndef _VLV_IOSF_SB_REGS_H_ +#define _VLV_IOSF_SB_REGS_H_ + +enum vlv_iosf_sb_unit { + VLV_IOSF_SB_BUNIT, + VLV_IOSF_SB_CCK, + VLV_IOSF_SB_CCU, + VLV_IOSF_SB_DPIO, + VLV_IOSF_SB_DPIO_2, + VLV_IOSF_SB_FLISDSI, + VLV_IOSF_SB_GPIO, + VLV_IOSF_SB_NC, + VLV_IOSF_SB_PUNIT, +}; /* See configdb bunit SB addr map */ #define BUNIT_REG_BISOC 0x11 @@ -177,4 +189,4 @@ #define CCK_FREQUENCY_STATUS_SHIFT 8 #define CCK_FREQUENCY_VALUES (0x1f << 0) -#endif /* _VLV_IOSF_SB_REG_H_ */ +#endif /* _VLV_IOSF_SB_REGS_H_ */ From bf64bcf4baab24944be3f6252192abb87af84686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:48 +0300 Subject: [PATCH 015/144] drm/i915/qgv: Use intel_de_read() for MTL_MEM_SS_INFO* reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MTL_MEM_SS_INFO* are just regular display registers. Use intel_de_read() to access them. Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_bw.c | 6 +++--- drivers/gpu/drm/i915/display/intel_dram.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 07b4531a4376..18b80147ddc7 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -9,6 +9,7 @@ #include "intel_bw.h" #include "intel_crtc.h" +#include "intel_de.h" #include "intel_display_core.h" #include "intel_display_regs.h" #include "intel_display_types.h" @@ -211,12 +212,11 @@ static int icl_pcode_restrict_qgv_points(struct intel_display *display, static int mtl_read_qgv_point_info(struct intel_display *display, struct intel_qgv_point *sp, int point) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u32 val, val2; u16 dclk; - val = intel_uncore_read(uncore, MTL_MEM_SS_INFO_QGV_POINT_LOW(point)); - val2 = intel_uncore_read(uncore, MTL_MEM_SS_INFO_QGV_POINT_HIGH(point)); + 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->t_rp = REG_FIELD_GET(MTL_TRP_MASK, val); diff --git a/drivers/gpu/drm/i915/display/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c index 1686f808a084..d655ed163f13 100644 --- a/drivers/gpu/drm/i915/display/intel_dram.c +++ b/drivers/gpu/drm/i915/display/intel_dram.c @@ -9,6 +9,7 @@ #include #include +#include "intel_de.h" #include "intel_display_core.h" #include "intel_display_utils.h" #include "intel_display_regs.h" @@ -767,8 +768,7 @@ static int gen12_get_dram_info(struct intel_display *display, struct dram_info * static int xelpdp_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); - u32 val = intel_uncore_read(uncore, MTL_MEM_SS_INFO_GLOBAL); + u32 val = intel_de_read(display, MTL_MEM_SS_INFO_GLOBAL); switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) { case 0: From 81dbca71885df32b0683104d1f49065d792870e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:49 +0300 Subject: [PATCH 016/144] drm/i915/mchbar: Provide intel_mchbar_read*() abstraction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MCHBAR registers are a bit special in that: - we access them through the mirror - the mirror is read only on HSW+ - the mirror requires the actual MCHBAR to be enabled in device 0:0.0 - the mirror is gone on MTL+ So I'd prefer to treat MCHBAR registers as a bit special in the code as well, and do all accesses to them via dedicated functions. Prodive such functions in the form of intel_mchbar_read*(). v2: Put the function arguments on one line No intel_uncore_read64() on xe, use intel_uncore_read64_2x32() Name the new function intel_mchbar_read64_2x32() as well Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_mchbar.c | 30 +++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_mchbar.h | 19 +++++++++++++ drivers/gpu/drm/xe/Makefile | 1 + 4 files changed, 51 insertions(+) create mode 100644 drivers/gpu/drm/i915/display/intel_mchbar.c create mode 100644 drivers/gpu/drm/i915/display/intel_mchbar.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index b677720a1c2d..0e48305df8b2 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -295,6 +295,7 @@ i915-y += \ display/intel_link_bw.o \ display/intel_load_detect.o \ display/intel_lpe_audio.o \ + display/intel_mchbar.o \ display/intel_modeset_lock.o \ display/intel_modeset_setup.o \ display/intel_modeset_verify.o \ diff --git a/drivers/gpu/drm/i915/display/intel_mchbar.c b/drivers/gpu/drm/i915/display/intel_mchbar.c new file mode 100644 index 000000000000..2636fe60ef37 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_mchbar.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + */ + +#include "intel_display_core.h" +#include "intel_mchbar.h" +#include "intel_uncore.h" + +u16 intel_mchbar_read16(struct intel_display *display, i915_reg_t reg) +{ + struct intel_uncore *uncore = to_intel_uncore(display->drm); + + return intel_uncore_read16(uncore, reg); +} + +u32 intel_mchbar_read(struct intel_display *display, i915_reg_t reg) +{ + struct intel_uncore *uncore = to_intel_uncore(display->drm); + + return intel_uncore_read(uncore, reg); +} + +u64 intel_mchbar_read64_2x32(struct intel_display *display, i915_reg_t reg) +{ + struct intel_uncore *uncore = to_intel_uncore(display->drm); + i915_reg_t upper_reg = _MMIO(i915_mmio_reg_offset(reg) + 4); + + return intel_uncore_read64_2x32(uncore, reg, upper_reg); +} diff --git a/drivers/gpu/drm/i915/display/intel_mchbar.h b/drivers/gpu/drm/i915/display/intel_mchbar.h new file mode 100644 index 000000000000..002a4454e8ed --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_mchbar.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef __INTEL_MCHBAR_H__ +#define __INTEL_MCHBAR_H__ + +#include + +#include "i915_reg_defs.h" + +struct intel_display; + +u16 intel_mchbar_read16(struct intel_display *display, i915_reg_t reg); +u32 intel_mchbar_read(struct intel_display *display, i915_reg_t reg); +u64 intel_mchbar_read64_2x32(struct intel_display *display, i915_reg_t reg); + +#endif /* __INTEL_MCHBAR_H__ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 3bbd45ea327a..015ca5412f86 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -304,6 +304,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_link_bw.o \ i915-display/intel_lspcon.o \ i915-display/intel_lt_phy.o \ + i915-display/intel_mchbar.o \ i915-display/intel_modeset_lock.o \ i915-display/intel_modeset_setup.o \ i915-display/intel_modeset_verify.o \ From 03f8a13cc18c95bede16d55c08c0dda39f8e23fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:50 +0300 Subject: [PATCH 017/144] drm/i915/mchbar: Define the end of the MCHBAR mirror MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add defines for the end of the MCHBAR mirror. I'm planning to use this for some range sanity checks. BSpec: 51771 Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_mchbar_regs.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_mchbar_regs.h b/drivers/gpu/drm/i915/intel_mchbar_regs.h index 614d4017b57b..ca0d421be16c 100644 --- a/drivers/gpu/drm/i915/intel_mchbar_regs.h +++ b/drivers/gpu/drm/i915/intel_mchbar_regs.h @@ -16,11 +16,16 @@ * every way. It is not accessible from the CP register read instructions. * * Starting from Haswell, you can't write registers using the MCHBAR mirror, - * just read. + * just read. On MTL+ the mirror no longer exists. */ #define MCHBAR_MIRROR_BASE 0x10000 +#define MCHBAR_MIRROR_END 0x13fff + #define MCHBAR_MIRROR_BASE_SNB 0x140000 +#define MCHBAR_MIRROR_END_SNB 0x147fff +#define MCHBAR_MIRROR_END_ICL_RKL 0x14ffff +#define MCHBAR_MIRROR_END_TGL 0x15ffff #define CTG_STOLEN_RESERVED _MMIO(MCHBAR_MIRROR_BASE + 0x34) #define ELK_STOLEN_RESERVED _MMIO(MCHBAR_MIRROR_BASE + 0x48) From 84b0366809193fc6238e37c9839cd4b24db5e909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:51 +0300 Subject: [PATCH 018/144] drm/i915/mchbar: WARN when accessing non-MCHBAR registers via intel_mchbar_read*() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intel_mchbar_read*() functions should only be used for accessing MCHBAR registers. Warn if someone tries to use them for other registers. I suppose we could even have a dedicated type for MCHBAR registers. But that is true for many other special register types as well, and so far we haven't bothered adding any special types apart from i915_mcr_reg_t. v2: Print the register offset (Jani) Mention i915_mcr_reg_t (Jani) Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_mchbar.c | 56 +++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_mchbar.c b/drivers/gpu/drm/i915/display/intel_mchbar.c index 2636fe60ef37..a404fa38c9bd 100644 --- a/drivers/gpu/drm/i915/display/intel_mchbar.c +++ b/drivers/gpu/drm/i915/display/intel_mchbar.c @@ -3,14 +3,66 @@ * Copyright © 2026 Intel Corporation */ +#include + +#include + #include "intel_display_core.h" #include "intel_mchbar.h" +#include "intel_mchbar_regs.h" #include "intel_uncore.h" +static bool has_mchbar_mirror(struct intel_display *display) +{ + return DISPLAY_VER(display) < 14; +} + +static u32 mchbar_mirror_base(struct intel_display *display) +{ + if (DISPLAY_VER(display) >= 6) + return MCHBAR_MIRROR_BASE_SNB; + else + return MCHBAR_MIRROR_BASE; +} + +static u32 mchbar_mirror_end(struct intel_display *display) +{ + if (DISPLAY_VER(display) >= 12 && !display->platform.rocketlake) + return MCHBAR_MIRROR_END_TGL; + else if (DISPLAY_VER(display) >= 11) + return MCHBAR_MIRROR_END_ICL_RKL; + else if (DISPLAY_VER(display) >= 6) + return MCHBAR_MIRROR_END_SNB; + else + return MCHBAR_MIRROR_END; +} + +static u32 mchbar_mirror_len(struct intel_display *display) +{ + return mchbar_mirror_end(display) - mchbar_mirror_base(display) + 1; +} + +static bool is_mchbar_reg(struct intel_display *display, i915_reg_t reg) +{ + return has_mchbar_mirror(display) && + in_range32(i915_mmio_reg_offset(reg), + mchbar_mirror_base(display), + mchbar_mirror_len(display)); +} + +static void assert_is_mchbar_reg(struct intel_display *display, i915_reg_t reg) +{ + drm_WARN(display->drm, !is_mchbar_reg(display, reg), + "Reading non-MCHBAR register 0x%x\n", + i915_mmio_reg_offset(reg)); +} + u16 intel_mchbar_read16(struct intel_display *display, i915_reg_t reg) { struct intel_uncore *uncore = to_intel_uncore(display->drm); + assert_is_mchbar_reg(display, reg); + return intel_uncore_read16(uncore, reg); } @@ -18,6 +70,8 @@ u32 intel_mchbar_read(struct intel_display *display, i915_reg_t reg) { struct intel_uncore *uncore = to_intel_uncore(display->drm); + assert_is_mchbar_reg(display, reg); + return intel_uncore_read(uncore, reg); } @@ -26,5 +80,7 @@ u64 intel_mchbar_read64_2x32(struct intel_display *display, i915_reg_t reg) struct intel_uncore *uncore = to_intel_uncore(display->drm); i915_reg_t upper_reg = _MMIO(i915_mmio_reg_offset(reg) + 4); + assert_is_mchbar_reg(display, reg); + return intel_uncore_read64_2x32(uncore, reg, upper_reg); } From 1b274a3de2f198d22b367abd0e48cd05887b2abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:52 +0300 Subject: [PATCH 019/144] drm/i915/mchbar: Use intel_mchbar_read() instead of intel_de_read() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are doing a few accesses to MCHBAR registers with intel_de_read(). Use the dedicated intel_mchbar_read() instead. Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_cdclk.c | 5 +++-- drivers/gpu/drm/i915/display/intel_display_power.c | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 4a663dddf896..835a332e9686 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -41,6 +41,7 @@ #include "intel_display_utils.h" #include "intel_display_wa.h" #include "intel_dram.h" +#include "intel_mchbar.h" #include "intel_mchbar_regs.h" #include "intel_parent.h" #include "intel_pci_config.h" @@ -376,8 +377,8 @@ static unsigned int intel_hpll_vco(struct intel_display *display) else return 0; - tmp = intel_de_read(display, display->platform.pineview || - display->platform.mobile ? HPLLVCO_MOBILE : HPLLVCO); + tmp = intel_mchbar_read(display, display->platform.pineview || + display->platform.mobile ? HPLLVCO_MOBILE : HPLLVCO); vco = vco_table[tmp & 0x7]; if (vco == 0) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index b1c91de9d798..98e5a794fab7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -24,6 +24,7 @@ #include "intel_display_wa.h" #include "intel_dmc.h" #include "intel_dram.h" +#include "intel_mchbar.h" #include "intel_mchbar_regs.h" #include "intel_parent.h" #include "intel_pch_refclk.h" @@ -1252,7 +1253,7 @@ static void assert_can_disable_lcpll(struct intel_display *display) static u32 hsw_read_dcomp(struct intel_display *display) { if (display->platform.haswell) - return intel_de_read(display, D_COMP_HSW); + return intel_mchbar_read(display, D_COMP_HSW); else return intel_de_read(display, D_COMP_BDW); } From a076686acab63a2a632304af277751752e8a28d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:53 +0300 Subject: [PATCH 020/144] drm/i915/mchbar: Use intel_mchbar_read*() instead of intel_uncore_read*() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace all the naked intel_uncore_read*() accesses to MCHBAR registers with the dedicated intel_mchbar_read*(). v2: Rebase due to the intel_mchbar_read64_2x32() rename Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/i9xx_wm.c | 10 ++++---- drivers/gpu/drm/i915/display/intel_bw.c | 11 ++++----- drivers/gpu/drm/i915/display/intel_dram.c | 29 ++++++++--------------- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index c39d56e2ea26..3dbfb850fe1d 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -19,6 +19,7 @@ #include "intel_display_utils.h" #include "intel_dram.h" #include "intel_fb.h" +#include "intel_mchbar.h" #include "intel_mchbar_regs.h" #include "intel_wm.h" #include "skl_watermark.h" @@ -2742,12 +2743,11 @@ static void ilk_compute_wm_level(struct intel_display *display, static void hsw_read_wm_latency(struct intel_display *display, u16 wm[]) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u64 sskpd; display->wm.num_levels = 5; - sskpd = intel_uncore_read64(uncore, MCH_SSKPD); + sskpd = intel_mchbar_read64_2x32(display, MCH_SSKPD); wm[0] = REG_FIELD_GET64(SSKPD_NEW_WM0_MASK_HSW, sskpd); if (wm[0] == 0) @@ -2760,12 +2760,11 @@ static void hsw_read_wm_latency(struct intel_display *display, u16 wm[]) static void snb_read_wm_latency(struct intel_display *display, u16 wm[]) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u32 sskpd; display->wm.num_levels = 4; - sskpd = intel_uncore_read(uncore, MCH_SSKPD); + sskpd = intel_mchbar_read(display, MCH_SSKPD); wm[0] = REG_FIELD_GET(SSKPD_WM0_MASK_SNB, sskpd); wm[1] = REG_FIELD_GET(SSKPD_WM1_MASK_SNB, sskpd); @@ -2775,12 +2774,11 @@ static void snb_read_wm_latency(struct intel_display *display, u16 wm[]) static void ilk_read_wm_latency(struct intel_display *display, u16 wm[]) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u32 mltr; display->wm.num_levels = 3; - mltr = intel_uncore_read(uncore, MLTR_ILK); + mltr = intel_mchbar_read(display, MLTR_ILK); /* ILK primary LP0 latency is 700 ns */ wm[0] = 7; diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 18b80147ddc7..e6c8fd630294 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -15,9 +15,9 @@ #include "intel_display_types.h" #include "intel_display_utils.h" #include "intel_dram.h" +#include "intel_mchbar.h" #include "intel_mchbar_regs.h" #include "intel_parent.h" -#include "intel_uncore.h" #include "skl_watermark.h" struct intel_bw_state { @@ -75,11 +75,10 @@ static int dg1_mchbar_read_qgv_point_info(struct intel_display *display, struct intel_qgv_point *sp, int point) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u32 dclk_ratio, dclk_reference; u32 val; - val = intel_uncore_read(uncore, SA_PERF_STATUS_0_0_0_MCHBAR_PC); + 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 */ @@ -87,18 +86,18 @@ static int dg1_mchbar_read_qgv_point_info(struct intel_display *display, dclk_reference = 8; /* 8 * 16.666 MHz = 133 MHz */ sp->dclk = DIV_ROUND_UP((16667 * dclk_ratio * dclk_reference) + 500, 1000); - val = intel_uncore_read(uncore, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU); + val = intel_mchbar_read(display, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU); if (val & DG1_GEAR_TYPE) sp->dclk *= 2; if (sp->dclk == 0) return -EINVAL; - val = intel_uncore_read(uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR); + val = intel_mchbar_read(display, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR); sp->t_rp = REG_FIELD_GET(DG1_DRAM_T_RP_MASK, val); sp->t_rdpre = REG_FIELD_GET(DG1_DRAM_T_RDPRE_MASK, val); - val = intel_uncore_read(uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR_HIGH); + val = intel_mchbar_read(display, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR_HIGH); sp->t_rcd = REG_FIELD_GET(DG1_DRAM_T_RCD_MASK, val); sp->t_ras = REG_FIELD_GET(DG1_DRAM_T_RAS_MASK, val); diff --git a/drivers/gpu/drm/i915/display/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c index d655ed163f13..2079c63e3649 100644 --- a/drivers/gpu/drm/i915/display/intel_dram.c +++ b/drivers/gpu/drm/i915/display/intel_dram.c @@ -14,9 +14,9 @@ #include "intel_display_utils.h" #include "intel_display_regs.h" #include "intel_dram.h" +#include "intel_mchbar.h" #include "intel_mchbar_regs.h" #include "intel_parent.h" -#include "intel_uncore.h" #include "vlv_sideband.h" struct dram_dimm_info { @@ -59,18 +59,15 @@ const char *intel_dram_type_str(enum intel_dram_type type) static enum intel_dram_type pnv_dram_type(struct intel_display *display) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); - - return intel_uncore_read(uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ? + return intel_mchbar_read(display, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ? INTEL_DRAM_DDR3 : INTEL_DRAM_DDR2; } static unsigned int pnv_mem_freq(struct intel_display *display) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u32 tmp; - tmp = intel_uncore_read(uncore, CLKCFG); + tmp = intel_mchbar_read(display, CLKCFG); switch (tmp & CLKCFG_MEM_MASK) { case CLKCFG_MEM_533: @@ -86,10 +83,9 @@ static unsigned int pnv_mem_freq(struct intel_display *display) static unsigned int ilk_mem_freq(struct intel_display *display) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u16 ddrpll; - ddrpll = intel_uncore_read16(uncore, DDRMPLL1); + ddrpll = intel_mchbar_read16(display, DDRMPLL1); switch (ddrpll & 0xff) { case 0xc: return 800000; @@ -159,7 +155,6 @@ unsigned int intel_mem_freq(struct intel_display *display) static unsigned int i9xx_fsb_freq(struct intel_display *display) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u32 fsb; /* @@ -170,7 +165,7 @@ static unsigned int i9xx_fsb_freq(struct intel_display *display) * don't know which registers have that information, * and all the relevant docs have gone to bit heaven :( */ - fsb = intel_uncore_read(uncore, CLKCFG) & CLKCFG_FSB_MASK; + fsb = intel_mchbar_read(display, CLKCFG) & CLKCFG_FSB_MASK; if (display->platform.pineview || display->platform.mobile) { switch (fsb) { @@ -215,10 +210,9 @@ static unsigned int i9xx_fsb_freq(struct intel_display *display) static unsigned int ilk_fsb_freq(struct intel_display *display) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u16 fsb; - fsb = intel_uncore_read16(uncore, CSIPLL0) & 0x3ff; + fsb = intel_mchbar_read16(display, CSIPLL0) & 0x3ff; switch (fsb) { case 0x00c: @@ -485,7 +479,6 @@ intel_is_dram_symmetric(const struct dram_channel_info *ch0, static int skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram_info) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); struct dram_channel_info ch0 = {}, ch1 = {}; u32 val; int ret; @@ -493,12 +486,12 @@ skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram /* Assume 16Gb+ DIMMs are present until proven otherwise */ dram_info->has_16gb_dimms = true; - val = intel_uncore_read(uncore, SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); + val = intel_mchbar_read(display, SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); ret = skl_dram_get_channel_info(display, &ch0, 0, val); if (ret == 0) dram_info->num_channels++; - val = intel_uncore_read(uncore, SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); + val = intel_mchbar_read(display, SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); ret = skl_dram_get_channel_info(display, &ch1, 1, val); if (ret == 0) dram_info->num_channels++; @@ -529,10 +522,9 @@ skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram static enum intel_dram_type skl_get_dram_type(struct intel_display *display) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u32 val; - val = intel_uncore_read(uncore, SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN); + val = intel_mchbar_read(display, SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN); switch (val & SKL_DRAM_DDR_TYPE_MASK) { case SKL_DRAM_DDR_TYPE_DDR3: @@ -643,7 +635,6 @@ static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val) static int bxt_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); u32 val; u8 valid_ranks = 0; int i; @@ -655,7 +646,7 @@ static int bxt_get_dram_info(struct intel_display *display, struct dram_info *dr struct dram_dimm_info dimm; enum intel_dram_type type; - val = intel_uncore_read(uncore, BXT_D_CR_DRP0_DUNIT(i)); + val = intel_mchbar_read(display, BXT_D_CR_DRP0_DUNIT(i)); if (val == 0xFFFFFFFF) continue; From ed3643fb137386a6c8b9475a74e93ed0e63b5ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:54 +0300 Subject: [PATCH 021/144] drm/i915/de: Add intel_de_read16() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll need a replacement for intel_uncore_read16() in order to untangle intel_mchbar_read16() from uncore. As with the 8 bit counterpart this doesn't need to work on modern platforms so we can forgo all the DMC wakelock stuff and whatnot. Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_de.c | 8 ++++++++ drivers/gpu/drm/i915/display/intel_de.h | 1 + 2 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_de.c b/drivers/gpu/drm/i915/display/intel_de.c index d2a418da2d54..a96e83d76eaa 100644 --- a/drivers/gpu/drm/i915/display/intel_de.c +++ b/drivers/gpu/drm/i915/display/intel_de.c @@ -176,3 +176,11 @@ void intel_de_write8(struct intel_display *display, i915_reg_t reg, u8 val) intel_uncore_write8(__to_uncore(display), reg, val); } + +u16 intel_de_read16(struct intel_display *display, i915_reg_t reg) +{ + /* this is only used on MCHBAR registers on pre-SNB */ + drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 6); + + return intel_uncore_read16(__to_uncore(display), reg); +} diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index f87b84ab9d6d..3f9861b7a589 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -19,6 +19,7 @@ static inline struct intel_uncore *__to_uncore(struct intel_display *display) u8 intel_de_read8(struct intel_display *display, i915_reg_t reg); void intel_de_write8(struct intel_display *display, i915_reg_t reg, u8 val); +u16 intel_de_read16(struct intel_display *display, i915_reg_t reg); static inline u32 intel_de_read(struct intel_display *display, i915_reg_t reg) From 581feef63443b589b4f2013ae3a5480f4d435fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:55 +0300 Subject: [PATCH 022/144] drm/i915/de: s/intel_de_read64_2x32()/intel_de_read64_2x32_volatile()/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The raison d'etre of intel_de_read64_2x32() is that it can handle registers where volatile values are split across two registers. I don't like that it's being used needlessly. Rename it to intel_de_read64_2x32_volatile() to make it more clear when it should be used. Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-9-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_de.h | 4 ++-- drivers/gpu/drm/i915/display/intel_vblank.c | 4 ++-- drivers/gpu/drm/i915/display/intel_vrr.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 3f9861b7a589..295e7176b732 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -36,8 +36,8 @@ intel_de_read(struct intel_display *display, i915_reg_t reg) } static inline u64 -intel_de_read64_2x32(struct intel_display *display, - i915_reg_t lower_reg, i915_reg_t upper_reg) +intel_de_read64_2x32_volatile(struct intel_display *display, + i915_reg_t lower_reg, i915_reg_t upper_reg) { u64 val; diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index 1b7cfe226ff8..0726a2abed38 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -109,8 +109,8 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc) * we get a low value that's stable across two reads of the high * register. */ - frame = intel_de_read64_2x32(display, PIPEFRAMEPIXEL(display, pipe), - PIPEFRAME(display, pipe)); + frame = intel_de_read64_2x32_volatile(display, PIPEFRAMEPIXEL(display, pipe), + PIPEFRAME(display, pipe)); pixel = frame & PIPE_PIXEL_MASK; frame = (frame >> PIPE_FRAME_LOW_SHIFT) & 0xffffff; diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 8a957804cb97..ae5385e92889 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -1053,11 +1053,11 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state) if (crtc_state->cmrr.enable) { crtc_state->cmrr.cmrr_n = - intel_de_read64_2x32(display, TRANS_CMRR_N_LO(display, cpu_transcoder), - TRANS_CMRR_N_HI(display, cpu_transcoder)); + intel_de_read64_2x32_volatile(display, TRANS_CMRR_N_LO(display, cpu_transcoder), + TRANS_CMRR_N_HI(display, cpu_transcoder)); crtc_state->cmrr.cmrr_m = - intel_de_read64_2x32(display, TRANS_CMRR_M_LO(display, cpu_transcoder), - TRANS_CMRR_M_HI(display, cpu_transcoder)); + intel_de_read64_2x32_volatile(display, TRANS_CMRR_M_LO(display, cpu_transcoder), + TRANS_CMRR_M_HI(display, cpu_transcoder)); } if (DISPLAY_VER(display) >= 13) { From 57369c91daa619a17ac528578b39955b86f8a522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:56 +0300 Subject: [PATCH 023/144] drm/i915/de: Add a simple intel_de_read64_2x32() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_de_read64_2x32_volatile() is a complex beast because it needs to deal with volatile register values. For simpler cases we can simply do a pair normal intel_de_read()s. My main reason for hating overuse of intel_de_read64_2x32_volatile() is that it makes register tracepoints confusing. It always does three accesses in the somewhat weird udw,ldw,udw order, confusing the reader of the trace. Much more clear if we just observe the two reads in the natural little endian order. We also have no non-volatile use case where the LDW and UDW are stored in non-consecutive registers, so we can just pass along a single register offset. v2: Put the function arguments on one line (Jani) Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-10-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_de.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 295e7176b732..14f9dc7b6dfd 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -53,6 +53,18 @@ intel_de_read64_2x32_volatile(struct intel_display *display, return val; } +static inline u64 +intel_de_read64_2x32(struct intel_display *display, i915_reg_t reg) +{ + i915_reg_t upper_reg = _MMIO(i915_mmio_reg_offset(reg) + 4); + u32 lower, upper; + + lower = intel_de_read(display, reg); + upper = intel_de_read(display, upper_reg); + + return (u64)upper << 32 | lower; +} + static inline void intel_de_posting_read(struct intel_display *display, i915_reg_t reg) { From 38105260bac19ecf9c7abee7a3eb0e43f51de36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:57 +0300 Subject: [PATCH 024/144] drm/i915/vrr: Use intel_de_read64_2x32() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the pointless use of intel_de_read64_2x32_volatile() with the simpler intel_de_read64_2x32(). Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-11-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_vrr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index ae5385e92889..fae1186a90b2 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -1053,11 +1053,9 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state) if (crtc_state->cmrr.enable) { crtc_state->cmrr.cmrr_n = - intel_de_read64_2x32_volatile(display, TRANS_CMRR_N_LO(display, cpu_transcoder), - TRANS_CMRR_N_HI(display, cpu_transcoder)); + intel_de_read64_2x32(display, TRANS_CMRR_N_LO(display, cpu_transcoder)); crtc_state->cmrr.cmrr_m = - intel_de_read64_2x32_volatile(display, TRANS_CMRR_M_LO(display, cpu_transcoder), - TRANS_CMRR_M_HI(display, cpu_transcoder)); + intel_de_read64_2x32(display, TRANS_CMRR_M_LO(display, cpu_transcoder)); } if (DISPLAY_VER(display) >= 13) { From 86435ca5140bca8bef52809560d7678b6a9a5400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:58 +0300 Subject: [PATCH 025/144] drm/i915/mchbar: Use intel_de_read*() for MCHBAR register accesses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the naked intel_uncore_read*() with intel_de_read*() in the MCHBAR code. v2: Rebase due to intel_uncore_read64_2x32() Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-12-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_mchbar.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_mchbar.c b/drivers/gpu/drm/i915/display/intel_mchbar.c index a404fa38c9bd..16fcfe1e93ec 100644 --- a/drivers/gpu/drm/i915/display/intel_mchbar.c +++ b/drivers/gpu/drm/i915/display/intel_mchbar.c @@ -7,10 +7,10 @@ #include +#include "intel_de.h" #include "intel_display_core.h" #include "intel_mchbar.h" #include "intel_mchbar_regs.h" -#include "intel_uncore.h" static bool has_mchbar_mirror(struct intel_display *display) { @@ -59,28 +59,21 @@ static void assert_is_mchbar_reg(struct intel_display *display, i915_reg_t reg) u16 intel_mchbar_read16(struct intel_display *display, i915_reg_t reg) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); - assert_is_mchbar_reg(display, reg); - return intel_uncore_read16(uncore, reg); + return intel_de_read16(display, reg); } u32 intel_mchbar_read(struct intel_display *display, i915_reg_t reg) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); - assert_is_mchbar_reg(display, reg); - return intel_uncore_read(uncore, reg); + return intel_de_read(display, reg); } u64 intel_mchbar_read64_2x32(struct intel_display *display, i915_reg_t reg) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); - i915_reg_t upper_reg = _MMIO(i915_mmio_reg_offset(reg) + 4); - assert_is_mchbar_reg(display, reg); - return intel_uncore_read64_2x32(uncore, reg, upper_reg); + return intel_de_read64_2x32(display, reg); } From d4a06088f40e7c3b4abd79dc13cba81c01f18465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 31 Mar 2026 18:42:59 +0300 Subject: [PATCH 026/144] drm/i915/rom: Use intel_de for SPI ROM register access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we moved intel_rom.c back into the display code, just use intel_de_{read,write}() for the register accesses. Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260331154259.24600-13-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_rom.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_rom.c b/drivers/gpu/drm/i915/display/intel_rom.c index d573059fb0d9..54f842c09fb0 100644 --- a/drivers/gpu/drm/i915/display/intel_rom.c +++ b/drivers/gpu/drm/i915/display/intel_rom.c @@ -7,8 +7,9 @@ #include +#include "intel_de.h" +#include "intel_display_types.h" #include "intel_rom.h" -#include "intel_uncore.h" #include "intel_oprom_regs.h" struct intel_rom { @@ -17,7 +18,7 @@ struct intel_rom { void __iomem *oprom; /* for SPI */ - struct intel_uncore *uncore; + struct intel_display *display; loff_t offset; size_t size; @@ -30,10 +31,10 @@ struct intel_rom { static u32 spi_read32(struct intel_rom *rom, loff_t offset) { - intel_uncore_write(rom->uncore, PRIMARY_SPI_ADDRESS, - rom->offset + offset); + intel_de_write(rom->display, PRIMARY_SPI_ADDRESS, + rom->offset + offset); - return intel_uncore_read(rom->uncore, PRIMARY_SPI_TRIGGER); + return intel_de_read(rom->display, PRIMARY_SPI_TRIGGER); } static u16 spi_read16(struct intel_rom *rom, loff_t offset) @@ -50,13 +51,13 @@ struct intel_rom *intel_rom_spi(struct drm_device *drm) if (!rom) return NULL; - rom->uncore = to_intel_uncore(drm); + rom->display = to_intel_display(drm); - static_region = intel_uncore_read(rom->uncore, SPI_STATIC_REGIONS); + static_region = intel_de_read(rom->display, SPI_STATIC_REGIONS); static_region &= OPTIONROM_SPI_REGIONID_MASK; - intel_uncore_write(rom->uncore, PRIMARY_SPI_REGIONID, static_region); + intel_de_write(rom->display, PRIMARY_SPI_REGIONID, static_region); - rom->offset = intel_uncore_read(rom->uncore, OROM_OFFSET) & OROM_OFFSET_MASK; + rom->offset = intel_de_read(rom->display, OROM_OFFSET) & OROM_OFFSET_MASK; rom->size = 0x200000; From da0cdc1c329dd2ff09c41fbbe9fbd9c92c5d2c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Fri, 27 Mar 2026 13:45:53 +0200 Subject: [PATCH 027/144] drm/i915/psr: Do not use pipe_src as borders for SU area MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This far using crtc_state->pipe_src as borders for Selective Update area haven't caused visible problems as drm_rect_width(crtc_state->pipe_src) == crtc_state->hw.adjusted_mode.crtc_hdisplay and drm_rect_height(crtc_state->pipe_src) == crtc_state->hw.adjusted_mode.crtc_vdisplay when pipe scaling is not used. On the other hand using pipe scaling is forcing full frame updates and all the Selective Update area calculations are skipped. Now this improper usage of crtc_state->pipe_src is causing following warnings: <4> [7771.978166] xe 0000:00:02.0: [drm] drm_WARN_ON_ONCE(su_lines % vdsc_cfg->slice_height) after WARN_ON_ONCE was added by commit: "drm/i915/dsc: Add helper for writing DSC Selective Update ET parameters" These warnings are seen when DSC and pipe scaling are enabled simultaneously. This is because on full frame update SU area is improperly set as pipe_src which is not aligned with DSC slice height. Fix these by creating local rectangle using crtc_state->hw.adjusted_mode.crtc_hdisplay and crtc_state->hw.adjusted_mode.crtc_vdisplay. Use this local rectangle as borders for SU area. Fixes: d6774b8c3c58 ("drm/i915: Ensure damage clip area is within pipe area") Cc: # v6.0+ Signed-off-by: Jouni Högander Reviewed-by: Mika Kahola Link: https://patch.msgid.link/20260327114553.195285-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 30 +++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 2f1b48cd8efd..998c3faf5f2e 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -2689,9 +2689,9 @@ static u32 psr2_pipe_srcsz_early_tpt_calc(struct intel_crtc_state *crtc_state, static void clip_area_update(struct drm_rect *overlap_damage_area, struct drm_rect *damage_area, - struct drm_rect *pipe_src) + struct drm_rect *display_area) { - if (!drm_rect_intersect(damage_area, pipe_src)) + if (!drm_rect_intersect(damage_area, display_area)) return; if (overlap_damage_area->y1 == -1) { @@ -2742,6 +2742,7 @@ static bool intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_st static void intel_psr2_sel_fetch_et_alignment(struct intel_atomic_state *state, struct intel_crtc *crtc, + struct drm_rect *display_area, bool *cursor_in_su_area) { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); @@ -2769,7 +2770,7 @@ intel_psr2_sel_fetch_et_alignment(struct intel_atomic_state *state, continue; clip_area_update(&crtc_state->psr2_su_area, &new_plane_state->uapi.dst, - &crtc_state->pipe_src); + display_area); *cursor_in_su_area = true; } } @@ -2866,6 +2867,12 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); struct intel_plane_state *new_plane_state, *old_plane_state; struct intel_plane *plane; + struct drm_rect display_area = { + .x1 = 0, + .y1 = 0, + .x2 = crtc_state->hw.adjusted_mode.crtc_hdisplay, + .y2 = crtc_state->hw.adjusted_mode.crtc_vdisplay, + }; bool full_update = false, su_area_changed; int i, ret; @@ -2879,7 +2886,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, crtc_state->psr2_su_area.x1 = 0; crtc_state->psr2_su_area.y1 = -1; - crtc_state->psr2_su_area.x2 = drm_rect_width(&crtc_state->pipe_src); + crtc_state->psr2_su_area.x2 = drm_rect_width(&display_area); crtc_state->psr2_su_area.y2 = -1; /* @@ -2917,14 +2924,14 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, damaged_area.y1 = old_plane_state->uapi.dst.y1; damaged_area.y2 = old_plane_state->uapi.dst.y2; clip_area_update(&crtc_state->psr2_su_area, &damaged_area, - &crtc_state->pipe_src); + &display_area); } if (new_plane_state->uapi.visible) { damaged_area.y1 = new_plane_state->uapi.dst.y1; damaged_area.y2 = new_plane_state->uapi.dst.y2; clip_area_update(&crtc_state->psr2_su_area, &damaged_area, - &crtc_state->pipe_src); + &display_area); } continue; } else if (new_plane_state->uapi.alpha != old_plane_state->uapi.alpha) { @@ -2932,7 +2939,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, damaged_area.y1 = new_plane_state->uapi.dst.y1; damaged_area.y2 = new_plane_state->uapi.dst.y2; clip_area_update(&crtc_state->psr2_su_area, &damaged_area, - &crtc_state->pipe_src); + &display_area); continue; } @@ -2948,7 +2955,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, damaged_area.x1 += new_plane_state->uapi.dst.x1 - src.x1; damaged_area.x2 += new_plane_state->uapi.dst.x1 - src.x1; - clip_area_update(&crtc_state->psr2_su_area, &damaged_area, &crtc_state->pipe_src); + clip_area_update(&crtc_state->psr2_su_area, &damaged_area, &display_area); } /* @@ -2983,7 +2990,8 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, * cursor is added into affected planes even when * cursor is not updated by itself. */ - intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area); + intel_psr2_sel_fetch_et_alignment(state, crtc, &display_area, + &cursor_in_su_area); su_area_changed = intel_psr2_sel_fetch_pipe_alignment(crtc_state); @@ -3059,8 +3067,8 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, skip_sel_fetch_set_loop: if (full_update) - clip_area_update(&crtc_state->psr2_su_area, &crtc_state->pipe_src, - &crtc_state->pipe_src); + clip_area_update(&crtc_state->psr2_su_area, &display_area, + &display_area); psr2_man_trk_ctl_calc(crtc_state, full_update); crtc_state->pipe_srcsz_early_tpt = From 37b58ada0c39eb7c0b04f96615407e26e73834b5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Mar 2026 12:49:14 +0300 Subject: [PATCH 028/144] drm/xe/fbdev: put intel_fbdev_fb_prefer_stolen() behind IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify the behaviour with i915. Similar to commit b63c6b9b7f5e ("drm/i915/fbdev: fix link failure without FBDEV emulation"). The difference is that unlike i915, xe doesn't build display/intel_fbdev_fb.c conditional to CONFIG_DRM_FBDEV_EMULATION. Reviewed-by: Michał Grzelak Link: https://patch.msgid.link/245880a591fe5267a1c06bfbbcc42a4dd9f2e4ee.1774950508.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_initial_plane.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.c b/drivers/gpu/drm/xe/display/xe_initial_plane.c index 8bcae552dddc..d44746f4966c 100644 --- a/drivers/gpu/drm/xe/display/xe_initial_plane.c +++ b/drivers/gpu/drm/xe/display/xe_initial_plane.c @@ -86,6 +86,7 @@ initial_plane_bo(struct xe_device *xe, flags |= XE_BO_FLAG_STOLEN; if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && + IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) && !intel_fbdev_fb_prefer_stolen(&xe->drm, plane_config->size)) { drm_info(&xe->drm, "Initial FB size exceeds half of stolen, discarding\n"); return NULL; From b35b3148a78a5c545b2ac7981c182238431286cb Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Mar 2026 12:49:15 +0300 Subject: [PATCH 029/144] drm/{i915, xe}/fbdev: drop drm device parameter from intel_fbdev_fb_fill_info() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct drm_device *drm parameter of intel_fbdev_fb_fill_info() is redundant, as you can obtain the same information via obj->dev. Drop the drm parameter, and move obj as first (or the context) parameter. Reviewed-by: Michał Grzelak Link: https://patch.msgid.link/6c617dc41c07b0e3e9af01b82d0d1dadbd4760fc.1774950508.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fbdev.c | 2 +- drivers/gpu/drm/i915/display/intel_fbdev_fb.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_fbdev_fb.h | 4 ++-- drivers/gpu/drm/xe/display/intel_fbdev_fb.c | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index bdaaf3edba0c..6401aaaba199 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -327,7 +327,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, obj = intel_fb_bo(&fb->base); - ret = intel_fbdev_fb_fill_info(display->drm, info, obj, vma); + ret = intel_fbdev_fb_fill_info(obj, info, vma); if (ret) goto out_unpin; diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c index 6f84eb6355de..a696ce42d10b 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c @@ -66,10 +66,10 @@ void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj) drm_gem_object_put(obj); } -int intel_fbdev_fb_fill_info(struct drm_device *drm, struct fb_info *info, - struct drm_gem_object *_obj, struct i915_vma *vma) +int intel_fbdev_fb_fill_info(struct drm_gem_object *_obj, struct fb_info *info, + struct i915_vma *vma) { - struct drm_i915_private *i915 = to_i915(drm); + struct drm_i915_private *i915 = to_i915(_obj->dev); struct drm_i915_gem_object *obj = to_intel_bo(_obj); struct i915_gem_ww_ctx ww; void __iomem *vaddr; @@ -101,7 +101,7 @@ int intel_fbdev_fb_fill_info(struct drm_device *drm, struct fb_info *info, vaddr = i915_vma_pin_iomap(vma); if (IS_ERR(vaddr)) { - drm_err(drm, + drm_err(&i915->drm, "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr); ret = PTR_ERR(vaddr); continue; diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.h b/drivers/gpu/drm/i915/display/intel_fbdev_fb.h index 34ed2b9c2b4f..ddba45e9839d 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fbdev_fb.h @@ -17,8 +17,8 @@ struct i915_vma; u32 intel_fbdev_fb_pitch_align(u32 stride); struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size); void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj); -int intel_fbdev_fb_fill_info(struct drm_device *drm, struct fb_info *info, - struct drm_gem_object *obj, struct i915_vma *vma); +int intel_fbdev_fb_fill_info(struct drm_gem_object *obj, struct fb_info *info, + struct i915_vma *vma); bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size); #endif diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c index d7030e4d814c..23fa54ee781e 100644 --- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c +++ b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c @@ -91,11 +91,11 @@ void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj) xe_bo_unpin_map_no_vm(gem_to_xe_bo(obj)); } -int intel_fbdev_fb_fill_info(struct drm_device *drm, struct fb_info *info, - struct drm_gem_object *_obj, struct i915_vma *vma) +int intel_fbdev_fb_fill_info(struct drm_gem_object *_obj, struct fb_info *info, + struct i915_vma *vma) { struct xe_bo *obj = gem_to_xe_bo(_obj); - struct pci_dev *pdev = to_pci_dev(drm->dev); + struct pci_dev *pdev = to_pci_dev(_obj->dev->dev); if (!(obj->flags & XE_BO_FLAG_SYSTEM)) { if (obj->flags & XE_BO_FLAG_STOLEN) From 89f55d5859f894aada0a09f1539901a628d9a0fb Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Mar 2026 12:49:16 +0300 Subject: [PATCH 030/144] drm/{i915, xe}: move fbdev fb calls to parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the driver specific fbdev fb calls to the display parent interface. Reuse the existing struct intel_display_bo_interface, as this is mostly about gem objects. Put everything behind IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) to catch configuration issues at build or link time. v2: Rebase Reviewed-by: Michał Grzelak # v1 Link: https://patch.msgid.link/a6bb24909a58181cfc41b91a4c6538a181d27158.1774950508.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 3 +- drivers/gpu/drm/i915/display/intel_bo.c | 27 ++++ drivers/gpu/drm/i915/display/intel_bo.h | 8 ++ drivers/gpu/drm/i915/display/intel_fbdev.c | 14 +- drivers/gpu/drm/i915/display/intel_fbdev_fb.c | 118 ----------------- drivers/gpu/drm/i915/display/intel_fbdev_fb.h | 24 ---- drivers/gpu/drm/i915/i915_bo.c | 116 +++++++++++++++++ drivers/gpu/drm/i915/i915_bo.h | 6 + drivers/gpu/drm/i915/i915_initial_plane.c | 4 +- drivers/gpu/drm/xe/Makefile | 1 - drivers/gpu/drm/xe/display/intel_fbdev_fb.c | 120 ----------------- drivers/gpu/drm/xe/display/xe_display_bo.c | 121 ++++++++++++++++++ drivers/gpu/drm/xe/display/xe_display_bo.h | 6 + drivers/gpu/drm/xe/display/xe_initial_plane.c | 4 +- include/drm/intel/display_parent_interface.h | 7 + 15 files changed, 303 insertions(+), 276 deletions(-) delete mode 100644 drivers/gpu/drm/i915/display/intel_fbdev_fb.c delete mode 100644 drivers/gpu/drm/i915/display/intel_fbdev_fb.h delete mode 100644 drivers/gpu/drm/xe/display/intel_fbdev_fb.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 0e48305df8b2..272c292f06ed 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -326,8 +326,7 @@ i915-$(CONFIG_ACPI) += \ display/intel_acpi.o \ display/intel_opregion.o i915-$(CONFIG_DRM_FBDEV_EMULATION) += \ - display/intel_fbdev.o \ - display/intel_fbdev_fb.o + display/intel_fbdev.o i915-$(CONFIG_DEBUG_FS) += \ display/intel_display_debugfs.o \ display/intel_display_debugfs_params.o \ diff --git a/drivers/gpu/drm/i915/display/intel_bo.c b/drivers/gpu/drm/i915/display/intel_bo.c index 3b82d38a0504..8ecdbb7e39f3 100644 --- a/drivers/gpu/drm/i915/display/intel_bo.c +++ b/drivers/gpu/drm/i915/display/intel_bo.c @@ -85,3 +85,30 @@ struct drm_gem_object *intel_bo_framebuffer_lookup(struct intel_display *display { return display->parent->bo->framebuffer_lookup(display->drm, filp, user_mode_cmd); } + +#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) +u32 intel_bo_fbdev_pitch_align(struct intel_display *display, u32 stride) +{ + return display->parent->bo->fbdev_pitch_align(stride); +} + +struct drm_gem_object *intel_bo_fbdev_create(struct intel_display *display, int size) +{ + return display->parent->bo->fbdev_create(display->drm, size); +} + +void intel_bo_fbdev_destroy(struct drm_gem_object *obj) +{ + struct intel_display *display = to_intel_display(obj->dev); + + display->parent->bo->fbdev_destroy(obj); +} + +int intel_bo_fbdev_fill_info(struct drm_gem_object *obj, struct fb_info *info, + struct i915_vma *vma) +{ + struct intel_display *display = to_intel_display(obj->dev); + + return display->parent->bo->fbdev_fill_info(obj, info, vma); +} +#endif diff --git a/drivers/gpu/drm/i915/display/intel_bo.h b/drivers/gpu/drm/i915/display/intel_bo.h index aec188c706c2..348f7fa66960 100644 --- a/drivers/gpu/drm/i915/display/intel_bo.h +++ b/drivers/gpu/drm/i915/display/intel_bo.h @@ -10,6 +10,8 @@ struct drm_file; struct drm_gem_object; struct drm_mode_fb_cmd2; struct drm_scanout_buffer; +struct fb_info; +struct i915_vma; struct intel_display; struct intel_framebuffer; struct seq_file; @@ -31,4 +33,10 @@ struct drm_gem_object *intel_bo_framebuffer_lookup(struct intel_display *display struct drm_file *filp, const struct drm_mode_fb_cmd2 *user_mode_cmd); +u32 intel_bo_fbdev_pitch_align(struct intel_display *display, u32 stride); +struct drm_gem_object *intel_bo_fbdev_create(struct intel_display *display, int size); +void intel_bo_fbdev_destroy(struct drm_gem_object *obj); +int intel_bo_fbdev_fill_info(struct drm_gem_object *obj, struct fb_info *info, + struct i915_vma *vma); + #endif /* __INTEL_BO__ */ diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 6401aaaba199..14ac01c1b3eb 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -54,7 +54,6 @@ #include "intel_fb.h" #include "intel_fb_pin.h" #include "intel_fbdev.h" -#include "intel_fbdev_fb.h" #include "intel_frontbuffer.h" struct intel_fbdev { @@ -204,7 +203,8 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = { .fb_set_suspend = intelfb_set_suspend, }; -static void intel_fbdev_fill_mode_cmd(struct drm_fb_helper_surface_size *sizes, +static void intel_fbdev_fill_mode_cmd(struct intel_display *display, + struct drm_fb_helper_surface_size *sizes, struct drm_mode_fb_cmd2 *mode_cmd) { /* we don't do packed 24bpp */ @@ -215,7 +215,7 @@ static void intel_fbdev_fill_mode_cmd(struct drm_fb_helper_surface_size *sizes, mode_cmd->width = sizes->surface_width; mode_cmd->height = sizes->surface_height; - mode_cmd->pitches[0] = intel_fbdev_fb_pitch_align(mode_cmd->width * DIV_ROUND_UP(sizes->surface_bpp, 8)); + mode_cmd->pitches[0] = intel_bo_fbdev_pitch_align(display, mode_cmd->width * DIV_ROUND_UP(sizes->surface_bpp, 8)); mode_cmd->pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); mode_cmd->modifier[0] = DRM_FORMAT_MOD_LINEAR; @@ -230,12 +230,12 @@ __intel_fbdev_fb_alloc(struct intel_display *display, struct drm_gem_object *obj; int size; - intel_fbdev_fill_mode_cmd(sizes, &mode_cmd); + intel_fbdev_fill_mode_cmd(display, sizes, &mode_cmd); size = mode_cmd.pitches[0] * mode_cmd.height; size = PAGE_ALIGN(size); - obj = intel_fbdev_fb_bo_create(display->drm, size); + obj = intel_bo_fbdev_create(display, size); if (IS_ERR(obj)) { fb = ERR_CAST(obj); goto err; @@ -247,7 +247,7 @@ __intel_fbdev_fb_alloc(struct intel_display *display, mode_cmd.modifier[0]), &mode_cmd); if (IS_ERR(fb)) { - intel_fbdev_fb_bo_destroy(obj); + intel_bo_fbdev_destroy(obj); goto err; } @@ -327,7 +327,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, obj = intel_fb_bo(&fb->base); - ret = intel_fbdev_fb_fill_info(obj, info, vma); + ret = intel_bo_fbdev_fill_info(obj, info, vma); if (ret) goto out_unpin; diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c b/drivers/gpu/drm/i915/display/intel_fbdev_fb.c deleted file mode 100644 index a696ce42d10b..000000000000 --- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.c +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#include - -#include - -#include "gem/i915_gem_lmem.h" - -#include "i915_drv.h" -#include "intel_fbdev_fb.h" - -u32 intel_fbdev_fb_pitch_align(u32 stride) -{ - return ALIGN(stride, 64); -} - -bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size) -{ - struct drm_i915_private *i915 = to_i915(drm); - - /* Skip stolen on MTL as Wa_22018444074 mitigation. */ - if (IS_METEORLAKE(i915)) - return false; - - /* - * If the FB is too big, just don't use it since fbdev is not very - * important and we should probably use that space with FBC or other - * features. - */ - return i915->dsm.usable_size >= size * 2; -} - -struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size) -{ - struct drm_i915_private *i915 = to_i915(drm); - struct drm_i915_gem_object *obj; - - obj = ERR_PTR(-ENODEV); - if (HAS_LMEM(i915)) { - obj = i915_gem_object_create_lmem(i915, size, - I915_BO_ALLOC_CONTIGUOUS | - I915_BO_ALLOC_USER); - } else { - if (intel_fbdev_fb_prefer_stolen(drm, size)) - obj = i915_gem_object_create_stolen(i915, size); - else - drm_info(drm, "Allocating fbdev: Stolen memory not preferred.\n"); - - if (IS_ERR(obj)) - obj = i915_gem_object_create_shmem(i915, size); - } - - if (IS_ERR(obj)) { - drm_err(drm, "failed to allocate framebuffer (%pe)\n", obj); - return ERR_PTR(-ENOMEM); - } - - return &obj->base; -} - -void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj) -{ - drm_gem_object_put(obj); -} - -int intel_fbdev_fb_fill_info(struct drm_gem_object *_obj, struct fb_info *info, - struct i915_vma *vma) -{ - struct drm_i915_private *i915 = to_i915(_obj->dev); - struct drm_i915_gem_object *obj = to_intel_bo(_obj); - struct i915_gem_ww_ctx ww; - void __iomem *vaddr; - int ret; - - if (i915_gem_object_is_lmem(obj)) { - struct intel_memory_region *mem = obj->mm.region; - - /* Use fbdev's framebuffer from lmem for discrete */ - info->fix.smem_start = - (unsigned long)(mem->io.start + - i915_gem_object_get_dma_address(obj, 0) - - mem->region.start); - info->fix.smem_len = obj->base.size; - } else { - struct i915_ggtt *ggtt = to_gt(i915)->ggtt; - - /* Our framebuffer is the entirety of fbdev's system memory */ - info->fix.smem_start = - (unsigned long)(ggtt->gmadr.start + i915_ggtt_offset(vma)); - info->fix.smem_len = vma->size; - } - - for_i915_gem_ww(&ww, ret, false) { - ret = i915_gem_object_lock(vma->obj, &ww); - - if (ret) - continue; - - vaddr = i915_vma_pin_iomap(vma); - if (IS_ERR(vaddr)) { - drm_err(&i915->drm, - "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr); - ret = PTR_ERR(vaddr); - continue; - } - } - - if (ret) - return ret; - - info->screen_base = vaddr; - info->screen_size = intel_bo_to_drm_bo(obj)->size; - - return 0; -} diff --git a/drivers/gpu/drm/i915/display/intel_fbdev_fb.h b/drivers/gpu/drm/i915/display/intel_fbdev_fb.h deleted file mode 100644 index ddba45e9839d..000000000000 --- a/drivers/gpu/drm/i915/display/intel_fbdev_fb.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef __INTEL_FBDEV_FB_H__ -#define __INTEL_FBDEV_FB_H__ - -#include - -struct drm_device; -struct drm_gem_object; -struct drm_mode_fb_cmd2; -struct fb_info; -struct i915_vma; - -u32 intel_fbdev_fb_pitch_align(u32 stride); -struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size); -void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj); -int intel_fbdev_fb_fill_info(struct drm_gem_object *obj, struct fb_info *info, - struct i915_vma *vma); -bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size); - -#endif diff --git a/drivers/gpu/drm/i915/i915_bo.c b/drivers/gpu/drm/i915/i915_bo.c index 1789f7cab05c..7e38d002478e 100644 --- a/drivers/gpu/drm/i915/i915_bo.c +++ b/drivers/gpu/drm/i915/i915_bo.c @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT /* Copyright © 2024 Intel Corporation */ +#include + #include #include #include #include "display/intel_fb.h" +#include "gem/i915_gem_lmem.h" #include "gem/i915_gem_mman.h" #include "gem/i915_gem_object.h" #include "gem/i915_gem_object_frontbuffer.h" @@ -141,6 +144,113 @@ i915_bo_framebuffer_lookup(struct drm_device *drm, return intel_bo_to_drm_bo(obj); } +#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) +static u32 i915_bo_fbdev_pitch_align(u32 stride) +{ + return ALIGN(stride, 64); +} + +bool i915_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size) +{ + struct drm_i915_private *i915 = to_i915(drm); + + /* Skip stolen on MTL as Wa_22018444074 mitigation. */ + if (IS_METEORLAKE(i915)) + return false; + + /* + * If the FB is too big, just don't use it since fbdev is not very + * important and we should probably use that space with FBC or other + * features. + */ + return i915->dsm.usable_size >= size * 2; +} + +static struct drm_gem_object *i915_bo_fbdev_create(struct drm_device *drm, int size) +{ + struct drm_i915_private *i915 = to_i915(drm); + struct drm_i915_gem_object *obj; + + obj = ERR_PTR(-ENODEV); + if (HAS_LMEM(i915)) { + obj = i915_gem_object_create_lmem(i915, size, + I915_BO_ALLOC_CONTIGUOUS | + I915_BO_ALLOC_USER); + } else { + if (i915_bo_fbdev_prefer_stolen(drm, size)) + obj = i915_gem_object_create_stolen(i915, size); + else + drm_info(drm, "Allocating fbdev: Stolen memory not preferred.\n"); + + if (IS_ERR(obj)) + obj = i915_gem_object_create_shmem(i915, size); + } + + if (IS_ERR(obj)) { + drm_err(drm, "failed to allocate framebuffer (%pe)\n", obj); + return ERR_PTR(-ENOMEM); + } + + return &obj->base; +} + +static void i915_bo_fbdev_destroy(struct drm_gem_object *obj) +{ + drm_gem_object_put(obj); +} + +static int i915_bo_fbdev_fill_info(struct drm_gem_object *_obj, struct fb_info *info, + struct i915_vma *vma) +{ + struct drm_i915_private *i915 = to_i915(_obj->dev); + struct drm_i915_gem_object *obj = to_intel_bo(_obj); + struct i915_gem_ww_ctx ww; + void __iomem *vaddr; + int ret; + + if (i915_gem_object_is_lmem(obj)) { + struct intel_memory_region *mem = obj->mm.region; + + /* Use fbdev's framebuffer from lmem for discrete */ + info->fix.smem_start = + (unsigned long)(mem->io.start + + i915_gem_object_get_dma_address(obj, 0) - + mem->region.start); + info->fix.smem_len = obj->base.size; + } else { + struct i915_ggtt *ggtt = to_gt(i915)->ggtt; + + /* Our framebuffer is the entirety of fbdev's system memory */ + info->fix.smem_start = + (unsigned long)(ggtt->gmadr.start + i915_ggtt_offset(vma)); + info->fix.smem_len = vma->size; + } + + for_i915_gem_ww(&ww, ret, false) { + ret = i915_gem_object_lock(vma->obj, &ww); + + if (ret) + continue; + + vaddr = i915_vma_pin_iomap(vma); + if (IS_ERR(vaddr)) { + drm_err(&i915->drm, + "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr); + ret = PTR_ERR(vaddr); + continue; + } + } + + if (ret) + return ret; + + info->screen_base = vaddr; + info->screen_size = intel_bo_to_drm_bo(obj)->size; + + return 0; +} +#endif + const struct intel_display_bo_interface i915_display_bo_interface = { .is_tiled = i915_bo_is_tiled, .is_userptr = i915_bo_is_userptr, @@ -153,4 +263,10 @@ const struct intel_display_bo_interface i915_display_bo_interface = { .framebuffer_init = i915_bo_framebuffer_init, .framebuffer_fini = i915_bo_framebuffer_fini, .framebuffer_lookup = i915_bo_framebuffer_lookup, +#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) + .fbdev_create = i915_bo_fbdev_create, + .fbdev_destroy = i915_bo_fbdev_destroy, + .fbdev_fill_info = i915_bo_fbdev_fill_info, + .fbdev_pitch_align = i915_bo_fbdev_pitch_align, +#endif }; diff --git a/drivers/gpu/drm/i915/i915_bo.h b/drivers/gpu/drm/i915/i915_bo.h index 57255d052dd9..2a0f3050dd42 100644 --- a/drivers/gpu/drm/i915/i915_bo.h +++ b/drivers/gpu/drm/i915/i915_bo.h @@ -4,6 +4,12 @@ #ifndef __I915_BO_H__ #define __I915_BO_H__ +#include + +struct drm_device; + +bool i915_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size); + extern const struct intel_display_bo_interface i915_display_bo_interface; #endif /* __I915_BO_H__ */ diff --git a/drivers/gpu/drm/i915/i915_initial_plane.c b/drivers/gpu/drm/i915/i915_initial_plane.c index 390a9248d631..f4d631a395d0 100644 --- a/drivers/gpu/drm/i915/i915_initial_plane.c +++ b/drivers/gpu/drm/i915/i915_initial_plane.c @@ -9,10 +9,10 @@ #include "display/intel_crtc.h" #include "display/intel_display_types.h" #include "display/intel_fb.h" -#include "display/intel_fbdev_fb.h" #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_region.h" +#include "i915_bo.h" #include "i915_drv.h" #include "i915_initial_plane.h" @@ -118,7 +118,7 @@ initial_plane_vma(struct drm_i915_private *i915, if (IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) && IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && mem == i915->mm.stolen_region && - !intel_fbdev_fb_prefer_stolen(&i915->drm, size)) { + !i915_bo_fbdev_prefer_stolen(&i915->drm, size)) { drm_dbg_kms(&i915->drm, "Initial FB size exceeds half of stolen, discarding\n"); return NULL; } diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 015ca5412f86..288d621e9ccb 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -211,7 +211,6 @@ $(obj)/i915-display/%.o: $(srctree)/drivers/gpu/drm/i915/display/%.c FORCE # Display code specific to xe xe-$(CONFIG_DRM_XE_DISPLAY) += \ - display/intel_fbdev_fb.o \ display/xe_display.o \ display/xe_display_bo.o \ display/xe_display_pcode.o \ diff --git a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c b/drivers/gpu/drm/xe/display/intel_fbdev_fb.c deleted file mode 100644 index 23fa54ee781e..000000000000 --- a/drivers/gpu/drm/xe/display/intel_fbdev_fb.c +++ /dev/null @@ -1,120 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#include - -#include "intel_fbdev_fb.h" -#include "xe_bo.h" -#include "xe_ttm_stolen_mgr.h" -#include "xe_wa.h" - -#include - -/* - * FIXME: There shouldn't be any reason to have XE_PAGE_SIZE stride - * alignment. The same 64 as i915 uses should be fine, and we shouldn't need to - * have driver specific values. However, dropping the stride alignment to 64 - * leads to underflowing the bo pin count in the atomic cleanup work. - */ -u32 intel_fbdev_fb_pitch_align(u32 stride) -{ - return ALIGN(stride, XE_PAGE_SIZE); -} - -bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size) -{ - struct xe_device *xe = to_xe_device(drm); - struct ttm_resource_manager *stolen; - - stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN); - if (!stolen) - return false; - - if (IS_DGFX(xe)) - return false; - - if (XE_DEVICE_WA(xe, 22019338487_display)) - return false; - - /* - * If the FB is too big, just don't use it since fbdev is not very - * important and we should probably use that space with FBC or other - * features. - */ - return stolen->size >= size * 2; -} - -struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size) -{ - struct xe_device *xe = to_xe_device(drm); - struct xe_bo *obj; - - obj = ERR_PTR(-ENODEV); - - if (intel_fbdev_fb_prefer_stolen(drm, size)) { - obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), - size, - ttm_bo_type_kernel, - XE_BO_FLAG_FORCE_WC | - XE_BO_FLAG_STOLEN | - XE_BO_FLAG_GGTT, - false); - if (!IS_ERR(obj)) - drm_info(&xe->drm, "Allocated fbdev into stolen\n"); - else - drm_info(&xe->drm, "Allocated fbdev into stolen failed: %li\n", PTR_ERR(obj)); - } else { - drm_info(&xe->drm, "Allocating fbdev: Stolen memory not preferred.\n"); - } - - if (IS_ERR(obj)) { - obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), size, - ttm_bo_type_kernel, - XE_BO_FLAG_FORCE_WC | - XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) | - XE_BO_FLAG_GGTT, - false); - } - - if (IS_ERR(obj)) { - drm_err(&xe->drm, "failed to allocate framebuffer (%pe)\n", obj); - return ERR_PTR(-ENOMEM); - } - - return &obj->ttm.base; -} - -void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj) -{ - xe_bo_unpin_map_no_vm(gem_to_xe_bo(obj)); -} - -int intel_fbdev_fb_fill_info(struct drm_gem_object *_obj, struct fb_info *info, - struct i915_vma *vma) -{ - struct xe_bo *obj = gem_to_xe_bo(_obj); - struct pci_dev *pdev = to_pci_dev(_obj->dev->dev); - - if (!(obj->flags & XE_BO_FLAG_SYSTEM)) { - if (obj->flags & XE_BO_FLAG_STOLEN) - info->fix.smem_start = xe_ttm_stolen_io_offset(obj, 0); - else - info->fix.smem_start = - pci_resource_start(pdev, 2) + - xe_bo_addr(obj, 0, XE_PAGE_SIZE); - - info->fix.smem_len = obj->ttm.base.size; - } else { - /* XXX: Pure fiction, as the BO may not be physically accessible.. */ - info->fix.smem_start = 0; - info->fix.smem_len = obj->ttm.base.size; - } - XE_WARN_ON(iosys_map_is_null(&obj->vmap)); - - info->screen_base = obj->vmap.vaddr_iomem; - info->screen_size = obj->ttm.base.size; - - return 0; -} diff --git a/drivers/gpu/drm/xe/display/xe_display_bo.c b/drivers/gpu/drm/xe/display/xe_display_bo.c index 1d81b9908265..bb5eba226240 100644 --- a/drivers/gpu/drm/xe/display/xe_display_bo.c +++ b/drivers/gpu/drm/xe/display/xe_display_bo.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT /* Copyright © 2024 Intel Corporation */ +#include + #include #include @@ -8,6 +10,10 @@ #include "xe_bo.h" #include "xe_display_bo.h" #include "xe_pxp.h" +#include "xe_ttm_stolen_mgr.h" +#include "xe_wa.h" + +#include static bool xe_display_bo_is_protected(struct drm_gem_object *obj) { @@ -101,6 +107,115 @@ xe_display_bo_framebuffer_lookup(struct drm_device *drm, return gem; } +#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) +/* + * FIXME: There shouldn't be any reason to have XE_PAGE_SIZE stride + * alignment. The same 64 as i915 uses should be fine, and we shouldn't need to + * have driver specific values. However, dropping the stride alignment to 64 + * leads to underflowing the bo pin count in the atomic cleanup work. + */ +static u32 xe_display_bo_fbdev_pitch_align(u32 stride) +{ + return ALIGN(stride, XE_PAGE_SIZE); +} + +bool xe_display_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size) +{ + struct xe_device *xe = to_xe_device(drm); + struct ttm_resource_manager *stolen; + + stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN); + if (!stolen) + return false; + + if (IS_DGFX(xe)) + return false; + + if (XE_DEVICE_WA(xe, 22019338487_display)) + return false; + + /* + * If the FB is too big, just don't use it since fbdev is not very + * important and we should probably use that space with FBC or other + * features. + */ + return stolen->size >= size * 2; +} + +static struct drm_gem_object *xe_display_bo_fbdev_create(struct drm_device *drm, int size) +{ + struct xe_device *xe = to_xe_device(drm); + struct xe_bo *obj; + + obj = ERR_PTR(-ENODEV); + + if (xe_display_bo_fbdev_prefer_stolen(drm, size)) { + obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), + size, + ttm_bo_type_kernel, + XE_BO_FLAG_FORCE_WC | + XE_BO_FLAG_STOLEN | + XE_BO_FLAG_GGTT, + false); + if (!IS_ERR(obj)) + drm_info(&xe->drm, "Allocated fbdev into stolen\n"); + else + drm_info(&xe->drm, "Allocated fbdev into stolen failed: %li\n", PTR_ERR(obj)); + } else { + drm_info(&xe->drm, "Allocating fbdev: Stolen memory not preferred.\n"); + } + + if (IS_ERR(obj)) { + obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), size, + ttm_bo_type_kernel, + XE_BO_FLAG_FORCE_WC | + XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(xe)) | + XE_BO_FLAG_GGTT, + false); + } + + if (IS_ERR(obj)) { + drm_err(&xe->drm, "failed to allocate framebuffer (%pe)\n", obj); + return ERR_PTR(-ENOMEM); + } + + return &obj->ttm.base; +} + +static void xe_display_bo_fbdev_destroy(struct drm_gem_object *obj) +{ + xe_bo_unpin_map_no_vm(gem_to_xe_bo(obj)); +} + +static int xe_display_bo_fbdev_fill_info(struct drm_gem_object *_obj, struct fb_info *info, + struct i915_vma *vma) +{ + struct xe_bo *obj = gem_to_xe_bo(_obj); + struct pci_dev *pdev = to_pci_dev(_obj->dev->dev); + + if (!(obj->flags & XE_BO_FLAG_SYSTEM)) { + if (obj->flags & XE_BO_FLAG_STOLEN) + info->fix.smem_start = xe_ttm_stolen_io_offset(obj, 0); + else + info->fix.smem_start = + pci_resource_start(pdev, 2) + + xe_bo_addr(obj, 0, XE_PAGE_SIZE); + + info->fix.smem_len = obj->ttm.base.size; + } else { + /* XXX: Pure fiction, as the BO may not be physically accessible.. */ + info->fix.smem_start = 0; + info->fix.smem_len = obj->ttm.base.size; + } + XE_WARN_ON(iosys_map_is_null(&obj->vmap)); + + info->screen_base = obj->vmap.vaddr_iomem; + info->screen_size = obj->ttm.base.size; + + return 0; +} +#endif + const struct intel_display_bo_interface xe_display_bo_interface = { .is_protected = xe_display_bo_is_protected, .key_check = xe_pxp_obj_key_check, @@ -109,4 +224,10 @@ const struct intel_display_bo_interface xe_display_bo_interface = { .framebuffer_init = xe_display_bo_framebuffer_init, .framebuffer_fini = xe_display_bo_framebuffer_fini, .framebuffer_lookup = xe_display_bo_framebuffer_lookup, +#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) + .fbdev_create = xe_display_bo_fbdev_create, + .fbdev_destroy = xe_display_bo_fbdev_destroy, + .fbdev_fill_info = xe_display_bo_fbdev_fill_info, + .fbdev_pitch_align = xe_display_bo_fbdev_pitch_align, +#endif }; diff --git a/drivers/gpu/drm/xe/display/xe_display_bo.h b/drivers/gpu/drm/xe/display/xe_display_bo.h index 6879c104b0b1..8980e6ecf54a 100644 --- a/drivers/gpu/drm/xe/display/xe_display_bo.h +++ b/drivers/gpu/drm/xe/display/xe_display_bo.h @@ -4,6 +4,12 @@ #ifndef __XE_DISPLAY_BO_H__ #define __XE_DISPLAY_BO_H__ +#include + +struct drm_device; + +bool xe_display_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size); + extern const struct intel_display_bo_interface xe_display_bo_interface; #endif diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.c b/drivers/gpu/drm/xe/display/xe_initial_plane.c index d44746f4966c..73ae502bb2a5 100644 --- a/drivers/gpu/drm/xe/display/xe_initial_plane.c +++ b/drivers/gpu/drm/xe/display/xe_initial_plane.c @@ -12,8 +12,8 @@ #include "intel_display_types.h" #include "intel_fb.h" #include "intel_fb_pin.h" -#include "intel_fbdev_fb.h" #include "xe_bo.h" +#include "xe_display_bo.h" #include "xe_display_vma.h" #include "xe_ggtt.h" #include "xe_mmio.h" @@ -87,7 +87,7 @@ initial_plane_bo(struct xe_device *xe, if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) && - !intel_fbdev_fb_prefer_stolen(&xe->drm, plane_config->size)) { + !xe_display_bo_fbdev_prefer_stolen(&xe->drm, plane_config->size)) { drm_info(&xe->drm, "Initial FB size exceeds half of stolen, discarding\n"); return NULL; } diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index c0d18d5577f3..258e6388ef77 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -16,6 +16,7 @@ struct drm_gem_object; struct drm_mode_fb_cmd2; struct drm_plane_state; struct drm_scanout_buffer; +struct fb_info; struct i915_vma; struct intel_dpt; struct intel_dsb_buffer; @@ -44,6 +45,12 @@ struct intel_display_bo_interface { struct drm_gem_object *(*framebuffer_lookup)(struct drm_device *drm, struct drm_file *filp, const struct drm_mode_fb_cmd2 *user_mode_cmd); +#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) + struct drm_gem_object *(*fbdev_create)(struct drm_device *drm, int size); + void (*fbdev_destroy)(struct drm_gem_object *obj); + int (*fbdev_fill_info)(struct drm_gem_object *obj, struct fb_info *info, struct i915_vma *vma); + u32 (*fbdev_pitch_align)(u32 stride); +#endif }; struct intel_display_dpt_interface { From 3fd0d237c940f86857ee2bb194c06fa9a1333085 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Mar 2026 12:49:17 +0300 Subject: [PATCH 031/144] drm/i915: pass struct drm_i915_private to i915_bo_fbdev_prefer_stolen() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is i915 core code, use struct drm_i915_private for simplicity. Reviewed-by: Michał Grzelak Link: https://patch.msgid.link/321edddfd7509fd2cff0303747cdf18bb0cb911d.1774950508.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_bo.c | 6 ++---- drivers/gpu/drm/i915/i915_bo.h | 4 ++-- drivers/gpu/drm/i915/i915_initial_plane.c | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_bo.c b/drivers/gpu/drm/i915/i915_bo.c index 7e38d002478e..559341103ca7 100644 --- a/drivers/gpu/drm/i915/i915_bo.c +++ b/drivers/gpu/drm/i915/i915_bo.c @@ -150,10 +150,8 @@ static u32 i915_bo_fbdev_pitch_align(u32 stride) return ALIGN(stride, 64); } -bool i915_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size) +bool i915_bo_fbdev_prefer_stolen(struct drm_i915_private *i915, unsigned int size) { - struct drm_i915_private *i915 = to_i915(drm); - /* Skip stolen on MTL as Wa_22018444074 mitigation. */ if (IS_METEORLAKE(i915)) return false; @@ -177,7 +175,7 @@ static struct drm_gem_object *i915_bo_fbdev_create(struct drm_device *drm, int s I915_BO_ALLOC_CONTIGUOUS | I915_BO_ALLOC_USER); } else { - if (i915_bo_fbdev_prefer_stolen(drm, size)) + if (i915_bo_fbdev_prefer_stolen(i915, size)) obj = i915_gem_object_create_stolen(i915, size); else drm_info(drm, "Allocating fbdev: Stolen memory not preferred.\n"); diff --git a/drivers/gpu/drm/i915/i915_bo.h b/drivers/gpu/drm/i915/i915_bo.h index 2a0f3050dd42..39ba62696550 100644 --- a/drivers/gpu/drm/i915/i915_bo.h +++ b/drivers/gpu/drm/i915/i915_bo.h @@ -6,9 +6,9 @@ #include -struct drm_device; +struct drm_i915_private; -bool i915_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size); +bool i915_bo_fbdev_prefer_stolen(struct drm_i915_private *i915, unsigned int size); extern const struct intel_display_bo_interface i915_display_bo_interface; diff --git a/drivers/gpu/drm/i915/i915_initial_plane.c b/drivers/gpu/drm/i915/i915_initial_plane.c index f4d631a395d0..c1a12bf6b66c 100644 --- a/drivers/gpu/drm/i915/i915_initial_plane.c +++ b/drivers/gpu/drm/i915/i915_initial_plane.c @@ -118,7 +118,7 @@ initial_plane_vma(struct drm_i915_private *i915, if (IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) && IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && mem == i915->mm.stolen_region && - !i915_bo_fbdev_prefer_stolen(&i915->drm, size)) { + !i915_bo_fbdev_prefer_stolen(i915, size)) { drm_dbg_kms(&i915->drm, "Initial FB size exceeds half of stolen, discarding\n"); return NULL; } From 8e005ef09ba5a973e9401fa21b653339a5effda1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Mar 2026 12:49:18 +0300 Subject: [PATCH 032/144] drm/xe: pass struct xe_device to xe_display_bo_fbdev_prefer_stolen() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is xe core code, use struct xe_device for simplicity. Reviewed-by: Michał Grzelak Link: https://patch.msgid.link/56bd532dc5cf460cdbf17c7781f18db5378a28e6.1774950508.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display_bo.c | 5 ++--- drivers/gpu/drm/xe/display/xe_display_bo.h | 4 ++-- drivers/gpu/drm/xe/display/xe_initial_plane.c | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display_bo.c b/drivers/gpu/drm/xe/display/xe_display_bo.c index bb5eba226240..dc0d78ff2d79 100644 --- a/drivers/gpu/drm/xe/display/xe_display_bo.c +++ b/drivers/gpu/drm/xe/display/xe_display_bo.c @@ -119,9 +119,8 @@ static u32 xe_display_bo_fbdev_pitch_align(u32 stride) return ALIGN(stride, XE_PAGE_SIZE); } -bool xe_display_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size) +bool xe_display_bo_fbdev_prefer_stolen(struct xe_device *xe, unsigned int size) { - struct xe_device *xe = to_xe_device(drm); struct ttm_resource_manager *stolen; stolen = ttm_manager_type(&xe->ttm, XE_PL_STOLEN); @@ -149,7 +148,7 @@ static struct drm_gem_object *xe_display_bo_fbdev_create(struct drm_device *drm, obj = ERR_PTR(-ENODEV); - if (xe_display_bo_fbdev_prefer_stolen(drm, size)) { + if (xe_display_bo_fbdev_prefer_stolen(xe, size)) { obj = xe_bo_create_pin_map_novm(xe, xe_device_get_root_tile(xe), size, ttm_bo_type_kernel, diff --git a/drivers/gpu/drm/xe/display/xe_display_bo.h b/drivers/gpu/drm/xe/display/xe_display_bo.h index 8980e6ecf54a..c72056884ff4 100644 --- a/drivers/gpu/drm/xe/display/xe_display_bo.h +++ b/drivers/gpu/drm/xe/display/xe_display_bo.h @@ -6,9 +6,9 @@ #include -struct drm_device; +struct xe_device; -bool xe_display_bo_fbdev_prefer_stolen(struct drm_device *drm, unsigned int size); +bool xe_display_bo_fbdev_prefer_stolen(struct xe_device *xe, unsigned int size); extern const struct intel_display_bo_interface xe_display_bo_interface; diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.c b/drivers/gpu/drm/xe/display/xe_initial_plane.c index 73ae502bb2a5..1c7a4e8c390c 100644 --- a/drivers/gpu/drm/xe/display/xe_initial_plane.c +++ b/drivers/gpu/drm/xe/display/xe_initial_plane.c @@ -87,7 +87,7 @@ initial_plane_bo(struct xe_device *xe, if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) && - !xe_display_bo_fbdev_prefer_stolen(&xe->drm, plane_config->size)) { + !xe_display_bo_fbdev_prefer_stolen(xe, plane_config->size)) { drm_info(&xe->drm, "Initial FB size exceeds half of stolen, discarding\n"); return NULL; } From 3d353d6c535319894c3e1b9349cae0531159f087 Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Mon, 30 Mar 2026 19:06:18 +0530 Subject: [PATCH 033/144] drm/display: Add drm helper to check pr optimization support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add api to check panel replay optimization supported or not to drm-core DP tunneling framework which can be used by other driver as well. v2: Split generic drm changes from Intel specific changes. [Jouni] Reviewed-by: Jouni Högander Suggested-by: Imre Deak Signed-off-by: Animesh Manna Acked-by: Maarten Lankhorst Link: https://patch.msgid.link/20260330133620.3750559-2-animesh.manna@intel.com --- drivers/gpu/drm/display/drm_dp_tunnel.c | 17 +++++++++++++++++ include/drm/display/drm_dp_tunnel.h | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c b/drivers/gpu/drm/display/drm_dp_tunnel.c index 6519b4244728..08dc5d26b2c5 100644 --- a/drivers/gpu/drm/display/drm_dp_tunnel.c +++ b/drivers/gpu/drm/display/drm_dp_tunnel.c @@ -149,6 +149,7 @@ struct drm_dp_tunnel { bool bw_alloc_enabled:1; bool has_io_error:1; bool destroyed:1; + bool pr_optimization_support:1; }; struct drm_dp_tunnel_group_state; @@ -508,6 +509,8 @@ create_tunnel(struct drm_dp_tunnel_mgr *mgr, tunnel->bw_alloc_supported = tunnel_reg_bw_alloc_supported(regs); tunnel->bw_alloc_enabled = tunnel_reg_bw_alloc_enabled(regs); + tunnel->pr_optimization_support = tunnel_reg(regs, DP_TUNNELING_CAPABILITIES) & + DP_PANEL_REPLAY_OPTIMIZATION_SUPPORT; if (!add_tunnel_to_group(mgr, drv_group_id, tunnel)) { kfree(tunnel); @@ -1036,6 +1039,20 @@ bool drm_dp_tunnel_bw_alloc_is_enabled(const struct drm_dp_tunnel *tunnel) } EXPORT_SYMBOL(drm_dp_tunnel_bw_alloc_is_enabled); +/** + * drm_dp_tunnel_pr_optimization_supported - Query the PR BW optimization support + * @tunnel: Tunnel object + * + * Query if the PR BW optimization is supported for @tunnel. + * + * Returns %true if the PR BW optimiation is supported for @tunnel. + */ +bool drm_dp_tunnel_pr_optimization_supported(const struct drm_dp_tunnel *tunnel) +{ + return tunnel && tunnel->pr_optimization_support; +} +EXPORT_SYMBOL(drm_dp_tunnel_pr_optimization_supported); + static int clear_bw_req_state(struct drm_dp_aux *aux) { u8 bw_req_mask = DP_BW_REQUEST_SUCCEEDED | DP_BW_REQUEST_FAILED; diff --git a/include/drm/display/drm_dp_tunnel.h b/include/drm/display/drm_dp_tunnel.h index 87212c847915..4aa3ce9fd829 100644 --- a/include/drm/display/drm_dp_tunnel.h +++ b/include/drm/display/drm_dp_tunnel.h @@ -53,6 +53,7 @@ int drm_dp_tunnel_destroy(struct drm_dp_tunnel *tunnel); int drm_dp_tunnel_enable_bw_alloc(struct drm_dp_tunnel *tunnel); int drm_dp_tunnel_disable_bw_alloc(struct drm_dp_tunnel *tunnel); bool drm_dp_tunnel_bw_alloc_is_enabled(const struct drm_dp_tunnel *tunnel); +bool drm_dp_tunnel_pr_optimization_supported(const struct drm_dp_tunnel *tunnel); int drm_dp_tunnel_alloc_bw(struct drm_dp_tunnel *tunnel, int bw); int drm_dp_tunnel_get_allocated_bw(struct drm_dp_tunnel *tunnel); int drm_dp_tunnel_update_state(struct drm_dp_tunnel *tunnel); @@ -140,6 +141,11 @@ static inline bool drm_dp_tunnel_bw_alloc_is_enabled(const struct drm_dp_tunnel return false; } +static inline bool drm_dp_tunnel_pr_optimization_supported(const struct drm_dp_tunnel *tunnel) +{ + return false; +} + static inline int drm_dp_tunnel_alloc_bw(struct drm_dp_tunnel *tunnel, int bw) { From aa46f5470cb1c62740dc8e7125b8ae53d151066f Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Mon, 30 Mar 2026 19:06:19 +0530 Subject: [PATCH 034/144] drm/i915/display: Add hook to check optimization support for Intel platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a hook that uses the drm core tunneling function to check whether panel replay bandwidth optimization support is present. v2: Move DISPLAY_VER() check to intel_dp_tunnel_pr_optimization_supported(). [Jouni] Reviewed-by: Jouni Högander Signed-off-by: Animesh Manna Link: https://patch.msgid.link/20260330133620.3750559-3-animesh.manna@intel.com --- drivers/gpu/drm/i915/display/intel_dp_tunnel.c | 18 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp_tunnel.h | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c index 7363c9817297..11712a151f72 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c +++ b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c @@ -296,6 +296,24 @@ bool intel_dp_tunnel_bw_alloc_is_enabled(struct intel_dp *intel_dp) return drm_dp_tunnel_bw_alloc_is_enabled(intel_dp->tunnel); } +/** + * intel_dp_tunnel_pr_optimization_supported - Query the PR BW optimization support + * @intel_dp: DP port object + * + * Query whether a DP tunnel supports the PR BW optimization. + * + * Returns %true if the BW allocation mode is supported on @intel_dp. + */ +bool intel_dp_tunnel_pr_optimization_supported(struct intel_dp *intel_dp) +{ + struct intel_display *display = to_intel_display(intel_dp); + + if (DISPLAY_VER(display) < 35) + return false; + + return drm_dp_tunnel_pr_optimization_supported(intel_dp->tunnel); +} + /** * intel_dp_tunnel_suspend - Suspend a DP tunnel connected on a port * @intel_dp: DP port object diff --git a/drivers/gpu/drm/i915/display/intel_dp_tunnel.h b/drivers/gpu/drm/i915/display/intel_dp_tunnel.h index 10ab9eebcef6..8273e681a512 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_tunnel.h +++ b/drivers/gpu/drm/i915/display/intel_dp_tunnel.h @@ -32,6 +32,7 @@ void intel_dp_tunnel_resume(struct intel_dp *intel_dp, void intel_dp_tunnel_suspend(struct intel_dp *intel_dp); bool intel_dp_tunnel_bw_alloc_is_enabled(struct intel_dp *intel_dp); +bool intel_dp_tunnel_pr_optimization_supported(struct intel_dp *intel_dp); void intel_dp_tunnel_atomic_cleanup_inherited_state(struct intel_atomic_state *state); @@ -76,6 +77,11 @@ static inline bool intel_dp_tunnel_bw_alloc_is_enabled(struct intel_dp *intel_dp return false; } +static inline bool intel_dp_tunnel_pr_optimization_supported(struct intel_dp *intel_dp) +{ + return false; +} + static inline void intel_dp_tunnel_atomic_cleanup_inherited_state(struct intel_atomic_state *state) {} From ff1b43b7db95650976f9568bb0d62e59ec66e605 Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Mon, 30 Mar 2026 19:06:20 +0530 Subject: [PATCH 035/144] drm/i915/display: Panel Replay BW optimization for DP2.0 tunneling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unused bandwidth can be used by external display agents for Panel Replay enabled DP panel during idleness with link on. Enable source to replace dummy data from the display with data from another agent by programming TRANS_DP2_CTL [Panel Replay Tunneling Enable]. v2: - Enable pr bw optimization along with panel replay enable. [Jani] v3: - Write TRANS_DP2_CTL once for both bw optimization and panel replay enable. [Jani] v4: - Read DPCD once in init() and store in panel_replay_caps. [Jouni] v5: - Avoid reading DPCD for edp. [Jouni] - Use drm_dp_dpcd_read_byte() and some cosmetic changes. [Jani] v6: - Extend the corresponding interface defined in drm_dp_tunnel.c to query the Panel Replay optimization capability. [Imre] v7: - Clear TRANS_DP2_PR_TUNNELING_ENABLE if pr bw optimization is not allowed. [Jouni] - Move intel_dp_is_edp() check. [Jouni] Bspec: 68920 Reviewed-by: Arun R Murthy Reviewed-by: Jouni Högander Signed-off-by: Animesh Manna Link: https://patch.msgid.link/20260330133620.3750559-4-animesh.manna@intel.com --- .../gpu/drm/i915/display/intel_display_regs.h | 1 + drivers/gpu/drm/i915/display/intel_psr.c | 25 +++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h index 4746e9ebd920..dada8dc27ea4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_regs.h +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h @@ -2263,6 +2263,7 @@ #define TRANS_DP2_CTL(trans) _MMIO_TRANS(trans, _TRANS_DP2_CTL_A, _TRANS_DP2_CTL_B) #define TRANS_DP2_128B132B_CHANNEL_CODING REG_BIT(31) #define TRANS_DP2_PANEL_REPLAY_ENABLE REG_BIT(30) +#define TRANS_DP2_PR_TUNNELING_ENABLE REG_BIT(26) #define TRANS_DP2_DEBUG_ENABLE REG_BIT(23) #define _TRANS_DP2_VFREQHIGH_A 0x600a4 diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 998c3faf5f2e..a927b73c3f6e 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -44,6 +44,7 @@ #include "intel_dmc.h" #include "intel_dp.h" #include "intel_dp_aux.h" +#include "intel_dp_tunnel.h" #include "intel_dsb.h" #include "intel_frontbuffer.h" #include "intel_hdmi.h" @@ -1031,11 +1032,27 @@ static u8 frames_before_su_entry(struct intel_dp *intel_dp) return frames_before_su_entry; } +static bool intel_psr_allow_pr_bw_optimization(struct intel_dp *intel_dp) +{ + if (intel_dp_is_edp(intel_dp)) + return false; + + if (!intel_dp_tunnel_bw_alloc_is_enabled(intel_dp)) + return false; + + if (!intel_dp_tunnel_pr_optimization_supported(intel_dp)) + return false; + + return true; +} + static void dg2_activate_panel_replay(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); struct intel_psr *psr = &intel_dp->psr; enum transcoder cpu_transcoder = intel_dp->psr.transcoder; + u32 dp2_ctl_set = TRANS_DP2_PANEL_REPLAY_ENABLE; + u32 dp2_ctl_clear = 0; if (intel_dp_is_edp(intel_dp) && psr->sel_update_enabled) { u32 val = psr->su_region_et_enabled ? @@ -1048,12 +1065,16 @@ static void dg2_activate_panel_replay(struct intel_dp *intel_dp) val); } + if (intel_psr_allow_pr_bw_optimization(intel_dp)) + dp2_ctl_set |= TRANS_DP2_PR_TUNNELING_ENABLE; + else + dp2_ctl_clear = TRANS_DP2_PR_TUNNELING_ENABLE; + intel_de_rmw(display, PSR2_MAN_TRK_CTL(display, intel_dp->psr.transcoder), 0, ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME); - intel_de_rmw(display, TRANS_DP2_CTL(intel_dp->psr.transcoder), 0, - TRANS_DP2_PANEL_REPLAY_ENABLE); + intel_de_rmw(display, TRANS_DP2_CTL(intel_dp->psr.transcoder), dp2_ctl_clear, dp2_ctl_set); } static void hsw_activate_psr2(struct intel_dp *intel_dp) From 28f60e912cc21d4f5e208661e9c4ffe8488046a9 Mon Sep 17 00:00:00 2001 From: Nemesa Garg Date: Thu, 2 Apr 2026 11:43:10 +0530 Subject: [PATCH 036/144] drm/i915/pfit: Prevent negative coordinates in center mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the pipe_src width or height are greater than adjusted_mode hdisplay and vdisplay, computed x and y offsets for center mode can be negative. Writing negative values into the pch_fit registers result in a state error. Add a check to clamp these values so that they are never negative. v2: Compare in terms of pipe_src width and height.[Ville] v3: Change width/height to pipe_src_w/h in logging. [Ville] Signed-off-by: Nemesa Garg Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260402061310.111073-1-nemesa.garg@intel.com --- drivers/gpu/drm/i915/display/intel_pfit.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_pfit.c b/drivers/gpu/drm/i915/display/intel_pfit.c index 6dda496190e0..2dec4ccf74ce 100644 --- a/drivers/gpu/drm/i915/display/intel_pfit.c +++ b/drivers/gpu/drm/i915/display/intel_pfit.c @@ -186,6 +186,7 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { struct intel_display *display = to_intel_display(crtc_state); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); @@ -200,6 +201,16 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, switch (conn_state->scaling_mode) { case DRM_MODE_SCALE_CENTER: + if (adjusted_mode->crtc_hdisplay < pipe_src_w || + adjusted_mode->crtc_vdisplay < pipe_src_h) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] pfit center mode source (%dx%d) exceeds display (%dx%d)\n", + crtc->base.base.id, crtc->base.name, + pipe_src_w, pipe_src_h, + adjusted_mode->crtc_hdisplay, + adjusted_mode->crtc_vdisplay); + return -EINVAL; + } width = pipe_src_w; height = pipe_src_h; x = (adjusted_mode->crtc_hdisplay - width + 1)/2; From 7d7188501a7d307d56e132fce5513339d72ce48d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Apr 2026 13:04:35 +0300 Subject: [PATCH 037/144] drm/i915: move intel_fb_pin.c to i915_fb_pin.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_fb_pin.c is the final file in display/ that's specific to i915 only. Move it to i915 core, renaming it to i915_fb_pin.c. It'll still depend on a lot of display stuff, unfortunately. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/ab1ffc08bcd1364715396142f91780b6261bbe65.1775556190.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 2 +- .../{display/intel_fb_pin.c => i915_fb_pin.c} | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) rename drivers/gpu/drm/i915/{display/intel_fb_pin.c => i915_fb_pin.c} (97%) diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 272c292f06ed..fa632f4e505c 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -80,6 +80,7 @@ i915-y += \ i915_display_pc8.o \ i915_dpt.o \ i915_dsb_buffer.o \ + i915_fb_pin.o \ i915_hdcp_gsc.o \ i915_initial_plane.o \ i915_overlay.o \ @@ -279,7 +280,6 @@ i915-y += \ display/intel_drrs.o \ display/intel_dsb.o \ display/intel_fb.o \ - display/intel_fb_pin.o \ display/intel_fbc.o \ display/intel_fdi.o \ display/intel_fifo_underrun.o \ diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c similarity index 97% rename from drivers/gpu/drm/i915/display/intel_fb_pin.c rename to drivers/gpu/drm/i915/i915_fb_pin.c index 738d77a1468a..580acbb14ada 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -9,18 +9,19 @@ #include +#include "display/intel_display_core.h" +#include "display/intel_display_rpm.h" +#include "display/intel_display_types.h" +#include "display/intel_fb.h" +#include "display/intel_fb_pin.h" +#include "display/intel_plane.h" + #include "gem/i915_gem_domain.h" #include "gem/i915_gem_object.h" +#include "i915_dpt.h" #include "i915_drv.h" #include "i915_vma.h" -#include "intel_display_core.h" -#include "intel_display_rpm.h" -#include "intel_display_types.h" -#include "i915_dpt.h" -#include "intel_fb.h" -#include "intel_fb_pin.h" -#include "intel_plane.h" static struct i915_vma * intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, From 3823bf019d3b31ccd3e79860b7a3e20c719a1db4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Apr 2026 13:04:36 +0300 Subject: [PATCH 038/144] drm/i915/pin: s/dev_priv/i915/ and drop struct drm_device usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve consistency within i915_fb_pin.c by replacing dev_priv naming with i915, and dropping struct drm_device usage. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/3a4ac0a732a561a487e46838bde6327cff5ccb38.1775556190.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_fb_pin.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 580acbb14ada..9ef10cb3e3aa 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -30,9 +30,8 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, unsigned long *out_flags, struct intel_dpt *dpt) { - struct drm_device *dev = fb->dev; - struct intel_display *display = to_intel_display(dev); - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_display *display = to_intel_display(fb->dev); + struct drm_i915_private *i915 = to_i915(fb->dev); struct drm_gem_object *_obj = intel_fb_bo(fb); struct drm_i915_gem_object *obj = to_intel_bo(_obj); struct i915_address_space *vm = i915_dpt_to_vm(dpt); @@ -44,7 +43,7 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, * We are not syncing against the binding (and potential migrations) * below, so this vm must never be async. */ - if (drm_WARN_ON(&dev_priv->drm, vm->bind_async_flags)) + if (drm_WARN_ON(&i915->drm, vm->bind_async_flags)) return ERR_PTR(-EINVAL); if (WARN_ON(!i915_gem_object_is_framebuffer(obj))) @@ -57,7 +56,7 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, if (ret) continue; - if (HAS_LMEM(dev_priv)) { + if (HAS_LMEM(i915)) { unsigned int flags = obj->flags; /* @@ -119,9 +118,8 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, bool uses_fence, unsigned long *out_flags) { - struct drm_device *dev = fb->dev; - struct intel_display *display = to_intel_display(dev); - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_display *display = to_intel_display(fb->dev); + struct drm_i915_private *i915 = to_i915(fb->dev); struct drm_gem_object *_obj = intel_fb_bo(fb); struct drm_i915_gem_object *obj = to_intel_bo(_obj); struct ref_tracker *wakeref; @@ -130,10 +128,10 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, unsigned int pinctl; int ret; - if (drm_WARN_ON(dev, !i915_gem_object_is_framebuffer(obj))) + if (drm_WARN_ON(&i915->drm, !i915_gem_object_is_framebuffer(obj))) return ERR_PTR(-EINVAL); - if (drm_WARN_ON(dev, alignment && !is_power_of_2(alignment))) + if (drm_WARN_ON(&i915->drm, alignment && !is_power_of_2(alignment))) return ERR_PTR(-EINVAL); /* @@ -164,7 +162,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, ret = i915_gem_object_lock(obj, &ww); if (!ret && phys_alignment) ret = i915_gem_object_attach_phys(obj, phys_alignment); - else if (!ret && HAS_LMEM(dev_priv)) + else if (!ret && HAS_LMEM(i915)) ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0); if (!ret) ret = i915_gem_object_pin_pages(obj); @@ -265,7 +263,7 @@ intel_plane_fb_vtd_guard(const struct intel_plane_state *plane_state) int intel_plane_pin_fb(struct intel_plane_state *plane_state, const struct intel_plane_state *old_plane_state) { - struct intel_display *display = to_intel_display(plane_state); + struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct intel_framebuffer *fb = to_intel_framebuffer(plane_state->hw.fb); @@ -309,7 +307,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, * The DPT object contains only one vma, and there is no VT-d * guard, so the VMA's offset within the DPT is always 0. */ - drm_WARN_ON(display->drm, i915_dpt_offset(plane_state->dpt_vma)); + drm_WARN_ON(&i915->drm, i915_dpt_offset(plane_state->dpt_vma)); } /* From e5bec90aade0166eff1ae10327ad0c71026eb582 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Apr 2026 13:04:37 +0300 Subject: [PATCH 039/144] drm/i915/pin: switch to i915 core runtime pm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove a dependency on struct intel_display from i915 core code. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/c06366c1c6f9202be5d0b6ea649c20aba414e5bc.1775556190.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_fb_pin.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 9ef10cb3e3aa..1018f4b7bc2c 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -10,7 +10,6 @@ #include #include "display/intel_display_core.h" -#include "display/intel_display_rpm.h" #include "display/intel_display_types.h" #include "display/intel_fb.h" #include "display/intel_fb_pin.h" @@ -122,7 +121,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, struct drm_i915_private *i915 = to_i915(fb->dev); struct drm_gem_object *_obj = intel_fb_bo(fb); struct drm_i915_gem_object *obj = to_intel_bo(_obj); - struct ref_tracker *wakeref; + intel_wakeref_t wakeref; struct i915_gem_ww_ctx ww; struct i915_vma *vma; unsigned int pinctl; @@ -141,7 +140,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, * intel_runtime_pm_put(), so it is correct to wrap only the * pin/unpin/fence and not more. */ - wakeref = intel_display_rpm_get(display); + wakeref = intel_runtime_pm_get(&i915->runtime_pm); atomic_inc(&display->restore.pending_fb_pin); @@ -220,7 +219,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, vma = ERR_PTR(ret); atomic_dec(&display->restore.pending_fb_pin); - intel_display_rpm_put(display, wakeref); + intel_runtime_pm_put(&i915->runtime_pm, wakeref); return vma; } From 102d44b3a8fad96e94e9ccd0579986c14a1f2f75 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Tue, 7 Apr 2026 08:37:11 +0530 Subject: [PATCH 040/144] drm/i915/backlight: Fix VESA backlight possible check condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VESA backlight enable is possible when BACKLIGHT_AUX_ENABLE_CAPABLE is true via AUX command or when BACKLIGHT_PIN_ENABLE_CAPABLE is true via eDP connector pin. Similarly, backlight brightness adjustment can be done via AUX-based control or PWM pin-based control. It means there can be three configurations: 1) Full AUX-based: Enable and adjustment both via AUX. We currently support this (apart from the AUX luminance-based backlight control). 2) Hybrid: Enable via the BL_ENABLE pin, adjustment via either AUX or PWM. 3) Fully PWM pin-based: Enable via the BL_ENABLE pin, adjustment via PWM. Since that only 1 is supported as of now we need to make sure we do not try to manipulate backlight when BACKLIGHT_AUX_ENABLE_CAPABLE is not set. Also fix return value when condition is not fulfilled. Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/15907 Fixes: 0fb03890d182 ("drm/i915/backlight: Check if VESA backlight is possible") Signed-off-by: Suraj Kandpal Tested-by: Ville Syrjälä Reviewed-by: Ankit Nautiyal Link: https://patch.msgid.link/20260407030710.1440046-1-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 d0c76632a946..a8d56ebf06a2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -615,8 +615,13 @@ check_if_vesa_backlight_possible(struct intel_dp *intel_dp) int ret; u8 bit_min, bit_max; - if (!(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) - return true; + /* + * Since we only support Fully AUX Based VESA Backlight interface make sure + * backlight enable is possible via AUX along with backlight adjustment + */ + if (!(intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP && + intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) + return false; ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &bit_min); if (ret < 0) From d54377e487a7576d076e4993e80b7d1cded81b0a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Apr 2026 22:36:26 +0300 Subject: [PATCH 041/144] drm/i915/mchbar: include intel_mchbar_regs.h from intel_mchbar.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As an exception to the rule of not including unnecessary headers from headers, include intel_mchbar_regs.h from intel_mchbar.h. In order to use the interfaces in intel_mchbar.h you will always have to include the registers anyway, so the includes are in pairs everywhere. There is zero asymmetry. Simplify. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/e44dc2daf3fc39d02c3f598c323caa3c08a54304.1775590536.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_wm.c | 1 - drivers/gpu/drm/i915/display/intel_bw.c | 1 - drivers/gpu/drm/i915/display/intel_cdclk.c | 1 - drivers/gpu/drm/i915/display/intel_display_power.c | 1 - drivers/gpu/drm/i915/display/intel_dram.c | 1 - drivers/gpu/drm/i915/display/intel_mchbar.c | 1 - drivers/gpu/drm/i915/display/intel_mchbar.h | 1 + 7 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 3dbfb850fe1d..02ac6f9a3d0e 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -20,7 +20,6 @@ #include "intel_dram.h" #include "intel_fb.h" #include "intel_mchbar.h" -#include "intel_mchbar_regs.h" #include "intel_wm.h" #include "skl_watermark.h" #include "vlv_sideband.h" diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index e6c8fd630294..474438fc1ebc 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -16,7 +16,6 @@ #include "intel_display_utils.h" #include "intel_dram.h" #include "intel_mchbar.h" -#include "intel_mchbar_regs.h" #include "intel_parent.h" #include "skl_watermark.h" diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 835a332e9686..82955cf16c4c 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -42,7 +42,6 @@ #include "intel_display_wa.h" #include "intel_dram.h" #include "intel_mchbar.h" -#include "intel_mchbar_regs.h" #include "intel_parent.h" #include "intel_pci_config.h" #include "intel_plane.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 98e5a794fab7..4091b7c4914f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -25,7 +25,6 @@ #include "intel_dmc.h" #include "intel_dram.h" #include "intel_mchbar.h" -#include "intel_mchbar_regs.h" #include "intel_parent.h" #include "intel_pch_refclk.h" #include "intel_pmdemand.h" diff --git a/drivers/gpu/drm/i915/display/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c index 2079c63e3649..f103f7cba018 100644 --- a/drivers/gpu/drm/i915/display/intel_dram.c +++ b/drivers/gpu/drm/i915/display/intel_dram.c @@ -15,7 +15,6 @@ #include "intel_display_regs.h" #include "intel_dram.h" #include "intel_mchbar.h" -#include "intel_mchbar_regs.h" #include "intel_parent.h" #include "vlv_sideband.h" diff --git a/drivers/gpu/drm/i915/display/intel_mchbar.c b/drivers/gpu/drm/i915/display/intel_mchbar.c index 16fcfe1e93ec..a0d0a796c6bb 100644 --- a/drivers/gpu/drm/i915/display/intel_mchbar.c +++ b/drivers/gpu/drm/i915/display/intel_mchbar.c @@ -10,7 +10,6 @@ #include "intel_de.h" #include "intel_display_core.h" #include "intel_mchbar.h" -#include "intel_mchbar_regs.h" static bool has_mchbar_mirror(struct intel_display *display) { diff --git a/drivers/gpu/drm/i915/display/intel_mchbar.h b/drivers/gpu/drm/i915/display/intel_mchbar.h index 002a4454e8ed..51ecd6075bdf 100644 --- a/drivers/gpu/drm/i915/display/intel_mchbar.h +++ b/drivers/gpu/drm/i915/display/intel_mchbar.h @@ -9,6 +9,7 @@ #include #include "i915_reg_defs.h" +#include "intel_mchbar_regs.h" struct intel_display; From aa7d8dfae8a5069259da73c0184d6aa7b7d61ca4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Apr 2026 22:36:27 +0300 Subject: [PATCH 042/144] drm/i915/mchbar: drop unnecessary intel_mchbar_regs.h include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are some unnecessary includes. Remove. Suggested-by: Ville Syrjälä Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/7eaf98e648240e3011bfb85d0330787074c39205.1775590536.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 1 - drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 1 - drivers/gpu/drm/i915/gvt/handlers.c | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index babaf16e72f2..adf2512e2ed5 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -19,7 +19,6 @@ #include "intel_gt_pm_debugfs.h" #include "intel_gt_regs.h" #include "intel_llc.h" -#include "intel_mchbar_regs.h" #include "intel_pcode.h" #include "intel_rc6.h" #include "intel_rps.h" diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index fa9af08f9708..a75f05ff1110 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -16,7 +16,6 @@ #include "i915_wait_util.h" #include "intel_guc_print.h" #include "intel_guc_slpc.h" -#include "intel_mchbar_regs.h" /** * DOC: SLPC - Dynamic Frequency management diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index a34f56630af9..9f61867e2478 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -71,7 +71,6 @@ #include "i915_drv.h" #include "i915_pvinfo.h" #include "i915_reg.h" -#include "intel_mchbar_regs.h" #include "sched_policy.h" /* XXX FIXME i915 has changed PP_XXX definition */ From d96366c7027aa1f335d1391983ff3c140f02c64e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Apr 2026 22:36:28 +0300 Subject: [PATCH 043/144] drm/i915/mchbar: move intel_mchbar_regs.h under include/drm/intel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the mchbar registers are used from both i915 display and core, move intel_mchbar_regs.h to include/drm/intel/mchbar_regs.h. Drop the intel_ prefix from the name to reduce tautology. With this, we can drop the corresponding xe display compat header. v2: Rebase Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/6c951b2c05db74ea517d52a3912986f7eb886422.1775590536.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_mchbar.h | 3 ++- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 2 +- drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 2 +- drivers/gpu/drm/i915/gt/intel_llc.c | 2 +- drivers/gpu/drm/i915/gt/intel_reset.c | 3 ++- drivers/gpu/drm/i915/gt/intel_rps.c | 4 ++-- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_freq.c | 2 +- drivers/gpu/drm/i915/i915_hwmon.c | 2 +- drivers/gpu/drm/i915/intel_clock_gating.c | 4 ++-- drivers/gpu/drm/i915/intel_gvt_mmio_table.c | 2 +- drivers/gpu/drm/xe/compat-i915-headers/intel_mchbar_regs.h | 6 ------ .../intel_mchbar_regs.h => include/drm/intel/mchbar_regs.h | 0 13 files changed, 15 insertions(+), 19 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/intel_mchbar_regs.h rename drivers/gpu/drm/i915/intel_mchbar_regs.h => include/drm/intel/mchbar_regs.h (100%) diff --git a/drivers/gpu/drm/i915/display/intel_mchbar.h b/drivers/gpu/drm/i915/display/intel_mchbar.h index 51ecd6075bdf..fb645c64796c 100644 --- a/drivers/gpu/drm/i915/display/intel_mchbar.h +++ b/drivers/gpu/drm/i915/display/intel_mchbar.h @@ -8,8 +8,9 @@ #include +#include + #include "i915_reg_defs.h" -#include "intel_mchbar_regs.h" struct intel_display; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index 77f85359f279..5838fb33104d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_region.h" @@ -23,7 +24,6 @@ #include "i915_reg.h" #include "i915_utils.h" #include "i915_vgpu.h" -#include "intel_mchbar_regs.h" #include "intel_pci_config.h" struct intel_stolen_node { diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c index ac9aede82320..6efc1ed3831b 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -7,6 +7,7 @@ #include #include +#include #include "display/intel_display.h" #include "i915_drv.h" @@ -15,7 +16,6 @@ #include "i915_pvinfo.h" #include "i915_vgpu.h" #include "intel_gt_regs.h" -#include "intel_mchbar_regs.h" /** * DOC: fence register handling diff --git a/drivers/gpu/drm/i915/gt/intel_llc.c b/drivers/gpu/drm/i915/gt/intel_llc.c index bcd707e3d436..82d9a8e50867 100644 --- a/drivers/gpu/drm/i915/gt/intel_llc.c +++ b/drivers/gpu/drm/i915/gt/intel_llc.c @@ -7,12 +7,12 @@ #include #include +#include #include "i915_drv.h" #include "i915_reg.h" #include "intel_gt.h" #include "intel_llc.h" -#include "intel_mchbar_regs.h" #include "intel_pcode.h" #include "intel_rps.h" diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 984d0056c01c..4d0ea953eb6e 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -7,6 +7,8 @@ #include #include +#include + #include "display/intel_display_reset.h" #include "display/intel_overlay.h" #include "gem/i915_gem_context.h" @@ -27,7 +29,6 @@ #include "intel_gt_pm.h" #include "intel_gt_print.h" #include "intel_gt_requests.h" -#include "intel_mchbar_regs.h" #include "intel_pci_config.h" #include "intel_reset.h" diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 844f2716a386..a33b19c04737 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -5,9 +5,10 @@ #include -#include #include +#include #include +#include #include "display/intel_display_rps.h" #include "display/vlv_clock.h" @@ -25,7 +26,6 @@ #include "intel_gt_pm_irq.h" #include "intel_gt_print.h" #include "intel_gt_regs.h" -#include "intel_mchbar_regs.h" #include "intel_pcode.h" #include "intel_rps.h" #include "vlv_iosf_sb.h" diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4778ba664ec7..a3e27f9e4f47 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "gem/i915_gem_context.h" #include "gt/intel_gt.h" @@ -57,7 +58,6 @@ #include "i915_reg.h" #include "i915_scheduler.h" #include "i915_wait_util.h" -#include "intel_mchbar_regs.h" static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node) { diff --git a/drivers/gpu/drm/i915/i915_freq.c b/drivers/gpu/drm/i915/i915_freq.c index 9bdaea34aef9..9547d087555f 100644 --- a/drivers/gpu/drm/i915/i915_freq.c +++ b/drivers/gpu/drm/i915/i915_freq.c @@ -2,10 +2,10 @@ /* Copyright © 2025 Intel Corporation */ #include +#include #include "i915_drv.h" #include "i915_freq.h" -#include "intel_mchbar_regs.h" unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) { diff --git a/drivers/gpu/drm/i915/i915_hwmon.c b/drivers/gpu/drm/i915/i915_hwmon.c index c4a799f5fe92..da643b38064c 100644 --- a/drivers/gpu/drm/i915/i915_hwmon.c +++ b/drivers/gpu/drm/i915/i915_hwmon.c @@ -10,11 +10,11 @@ #include #include +#include #include "i915_drv.h" #include "i915_hwmon.h" #include "i915_reg.h" -#include "intel_mchbar_regs.h" #include "intel_pcode.h" #include "gt/intel_gt.h" #include "gt/intel_gt_regs.h" diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index ee2489a2fbe7..515f83c82abc 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -26,8 +26,9 @@ */ #include -#include #include +#include +#include #include "display/i9xx_plane_regs.h" #include "display/intel_display.h" @@ -42,7 +43,6 @@ #include "i915_drv.h" #include "i915_reg.h" #include "intel_clock_gating.h" -#include "intel_mchbar_regs.h" #include "vlv_iosf_sb.h" struct drm_i915_clock_gating_funcs { diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index ae42818ab6e0..de118fae0a49 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -7,6 +7,7 @@ #include #include +#include #include "display/bxt_dpio_phy_regs.h" #include "display/i9xx_plane_regs.h" @@ -44,7 +45,6 @@ #include "i915_pvinfo.h" #include "i915_reg.h" #include "intel_gvt.h" -#include "intel_mchbar_regs.h" #define MMIO_F(reg, s) do { \ int ret; \ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_mchbar_regs.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_mchbar_regs.h deleted file mode 100644 index 55b316985340..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_mchbar_regs.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#include "../../i915/intel_mchbar_regs.h" diff --git a/drivers/gpu/drm/i915/intel_mchbar_regs.h b/include/drm/intel/mchbar_regs.h similarity index 100% rename from drivers/gpu/drm/i915/intel_mchbar_regs.h rename to include/drm/intel/mchbar_regs.h From 65d2b7bf1a4f7c765a2c8dfa9254aa799c55040b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Apr 2026 22:36:29 +0300 Subject: [PATCH 044/144] drm/i915: drop unnecessary intel_pci_config.h include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's an unnecessary include. Drop it. Suggested-by: Ville Syrjälä Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/8323c99f379809b2973c99ebe54c21fd274d246c.1775590536.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_driver.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index c10cab38935a..129013c5fb42 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -122,7 +122,6 @@ #include "intel_cpu_info.h" #include "intel_gvt.h" #include "intel_memory_region.h" -#include "intel_pci_config.h" #include "intel_pcode.h" #include "intel_region_ttm.h" #include "vlv_iosf_sb.h" From 8b1858aaaa20255a42d8eefe7e913c161331af0c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Apr 2026 22:36:30 +0300 Subject: [PATCH 045/144] drm/i915/pci: move intel_pci_config.h under include/drm/intel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the PCI registers are used from both i915 display and core, move intel_pci_config.h to include/drm/intel/pci_config.h. Drop the intel_ prefix from the name to reduce tautology. With this, we can drop the corresponding xe display compat header. v2: Rebase Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/5aac6c711c3f0a09fc52f322455a4a4b35f80a82.1775590536.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_display_sr.c | 2 +- drivers/gpu/drm/i915/display/intel_backlight.c | 2 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/display/intel_lpe_audio.c | 2 +- drivers/gpu/drm/i915/display/intel_opregion.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 2 +- drivers/gpu/drm/i915/gt/intel_ggtt.c | 2 +- drivers/gpu/drm/i915/gt/intel_gt.c | 2 +- drivers/gpu/drm/i915/gt/intel_region_lmem.c | 2 +- drivers/gpu/drm/i915/gt/intel_reset.c | 2 +- drivers/gpu/drm/i915/gvt/cfg_space.c | 2 +- drivers/gpu/drm/i915/i915_gmch.c | 2 +- drivers/gpu/drm/i915/i915_overlay.c | 2 +- drivers/gpu/drm/i915/i915_pci.c | 2 +- drivers/gpu/drm/xe/compat-i915-headers/intel_pci_config.h | 6 ------ .../intel_pci_config.h => include/drm/intel/pci_config.h | 0 16 files changed, 14 insertions(+), 20 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/intel_pci_config.h rename drivers/gpu/drm/i915/intel_pci_config.h => include/drm/intel/pci_config.h (100%) diff --git a/drivers/gpu/drm/i915/display/i9xx_display_sr.c b/drivers/gpu/drm/i915/display/i9xx_display_sr.c index 935419441709..1eb2f636cc65 100644 --- a/drivers/gpu/drm/i915/display/i9xx_display_sr.c +++ b/drivers/gpu/drm/i915/display/i9xx_display_sr.c @@ -4,13 +4,13 @@ */ #include +#include #include "i9xx_display_sr.h" #include "i9xx_wm_regs.h" #include "intel_de.h" #include "intel_display_regs.h" #include "intel_gmbus.h" -#include "intel_pci_config.h" static void i9xx_display_save_swf(struct intel_display *display) { diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 34e95f05936e..b128896cb1c2 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -11,6 +11,7 @@ #include #include +#include #include "intel_backlight.h" #include "intel_backlight_regs.h" @@ -23,7 +24,6 @@ #include "intel_dp_aux_backlight.h" #include "intel_dsi_dcs_backlight.h" #include "intel_panel.h" -#include "intel_pci_config.h" #include "intel_pps.h" #include "intel_quirks.h" diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 82955cf16c4c..8feba2e0333b 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "hsw_ips.h" #include "intel_atomic.h" @@ -43,7 +44,6 @@ #include "intel_dram.h" #include "intel_mchbar.h" #include "intel_parent.h" -#include "intel_pci_config.h" #include "intel_plane.h" #include "intel_psr.h" #include "intel_step.h" diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c index 117b60656ca1..775493306a83 100644 --- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c @@ -70,11 +70,11 @@ #include #include +#include #include "intel_audio_regs.h" #include "intel_de.h" #include "intel_lpe_audio.h" -#include "intel_pci_config.h" #define HAS_LPE_AUDIO(display) ((display)->audio.lpe.platdev) diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index e25be56e678b..9f88b7cac9f7 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -34,13 +34,13 @@ #include #include #include +#include #include "intel_acpi.h" #include "intel_backlight.h" #include "intel_display_core.h" #include "intel_display_types.h" #include "intel_opregion.h" -#include "intel_pci_config.h" #define OPREGION_HEADER_OFFSET 0 #define OPREGION_ACPI_OFFSET 0x100 diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index 5838fb33104d..1cfdcf5c1118 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_region.h" @@ -24,7 +25,6 @@ #include "i915_reg.h" #include "i915_utils.h" #include "i915_vgpu.h" -#include "intel_pci_config.h" struct intel_stolen_node { struct drm_i915_private *i915; diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 08c4e735481b..64ca5bbc53c6 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "gem/i915_gem_lmem.h" @@ -20,7 +21,6 @@ #include "intel_gpu_commands.h" #include "intel_gt.h" #include "intel_gt_regs.h" -#include "intel_pci_config.h" #include "intel_ring.h" #include "i915_drv.h" #include "i915_pci.h" diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index d76121e117e1..5c7f862f7100 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "gem/i915_gem_internal.h" #include "gem/i915_gem_lmem.h" @@ -28,7 +29,6 @@ #include "intel_gt_requests.h" #include "intel_migrate.h" #include "intel_mocs.h" -#include "intel_pci_config.h" #include "intel_rc6.h" #include "intel_renderstate.h" #include "intel_rps.h" diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c b/drivers/gpu/drm/i915/gt/intel_region_lmem.c index a30060fd4429..b8a39567a334 100644 --- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c +++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c @@ -4,12 +4,12 @@ */ #include +#include #include "i915_drv.h" #include "i915_pci.h" #include "i915_reg.h" #include "intel_memory_region.h" -#include "intel_pci_config.h" #include "intel_region_lmem.h" #include "intel_region_ttm.h" #include "gem/i915_gem_lmem.h" diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 4d0ea953eb6e..37272871b0f2 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -8,6 +8,7 @@ #include #include +#include #include "display/intel_display_reset.h" #include "display/intel_overlay.h" @@ -29,7 +30,6 @@ #include "intel_gt_pm.h" #include "intel_gt_print.h" #include "intel_gt_requests.h" -#include "intel_pci_config.h" #include "intel_reset.h" #define RESET_MAX_RETRIES 3 diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index 1937e04d3791..e00c1478a24e 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -32,10 +32,10 @@ */ #include +#include #include "gvt.h" #include "i915_drv.h" -#include "intel_pci_config.h" enum { INTEL_GVT_PCI_BAR_GTTMMIO = 0, diff --git a/drivers/gpu/drm/i915/i915_gmch.c b/drivers/gpu/drm/i915/i915_gmch.c index 2d55831b3c58..b0ef6ef577a3 100644 --- a/drivers/gpu/drm/i915/i915_gmch.c +++ b/drivers/gpu/drm/i915/i915_gmch.c @@ -5,10 +5,10 @@ #include #include +#include #include "i915_drv.h" #include "i915_gmch.h" -#include "intel_pci_config.h" static void i915_gmch_bridge_release(struct drm_device *dev, void *bridge) { diff --git a/drivers/gpu/drm/i915/i915_overlay.c b/drivers/gpu/drm/i915/i915_overlay.c index c2d712bd2b0d..2d7aff51e39b 100644 --- a/drivers/gpu/drm/i915/i915_overlay.c +++ b/drivers/gpu/drm/i915/i915_overlay.c @@ -7,6 +7,7 @@ #include #include +#include #include "gem/i915_gem_internal.h" #include "gem/i915_gem_object_frontbuffer.h" @@ -18,7 +19,6 @@ #include "i915_drv.h" #include "i915_overlay.h" #include "i915_reg.h" -#include "intel_pci_config.h" #include "display/intel_frontbuffer.h" diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index d966a00520f1..82415af47d54 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -24,6 +24,7 @@ #include #include +#include #include #include "display/intel_display_driver.h" @@ -35,7 +36,6 @@ #include "i915_drv.h" #include "i915_pci.h" #include "i915_reg.h" -#include "intel_pci_config.h" __diag_push(); __diag_ignore_all("-Woverride-init", "Allow field initialization overrides for device info"); diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_pci_config.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_pci_config.h deleted file mode 100644 index 8c15867fd613..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_pci_config.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#include "../../i915/intel_pci_config.h" diff --git a/drivers/gpu/drm/i915/intel_pci_config.h b/include/drm/intel/pci_config.h similarity index 100% rename from drivers/gpu/drm/i915/intel_pci_config.h rename to include/drm/intel/pci_config.h From fd60a1c32e671e21cdd890bb578ced0d521810ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:52:35 +0300 Subject: [PATCH 046/144] drm/i915/casf: s/casf_enable/enable/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'casf_enable' boolean is already inside a casf specific structure, so drop the extra 'casf_' namespace from the bool. Reviewed-by: Michał Grzelak Reviewed-by: Nemesa Garg Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407175244.19654-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_casf.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 6 +++--- drivers/gpu/drm/i915/display/intel_display_types.h | 2 +- drivers/gpu/drm/i915/display/skl_scaler.c | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_casf.c b/drivers/gpu/drm/i915/display/intel_casf.c index b167af31de5b..32e6f7c8acdd 100644 --- a/drivers/gpu/drm/i915/display/intel_casf.c +++ b/drivers/gpu/drm/i915/display/intel_casf.c @@ -110,7 +110,7 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state) return 0; if (crtc_state->uapi.sharpness_strength == 0) { - crtc_state->hw.casf_params.casf_enable = false; + crtc_state->hw.casf_params.enable = false; crtc_state->hw.casf_params.strength = 0; return 0; } @@ -121,7 +121,7 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state) return -EINVAL; } - crtc_state->hw.casf_params.casf_enable = true; + crtc_state->hw.casf_params.enable = true; /* * HW takes a value in form (1.0 + strength) in 4.4 fixed format. @@ -155,7 +155,7 @@ void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state) else crtc_state->hw.casf_params.strength = REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp); - crtc_state->hw.casf_params.casf_enable = true; + crtc_state->hw.casf_params.enable = true; crtc_state->hw.casf_params.win_size = REG_FIELD_GET(FILTER_SIZE_MASK, sharp); } @@ -163,7 +163,7 @@ void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state) bool intel_casf_needs_scaler(const struct intel_crtc_state *crtc_state) { - if (crtc_state->hw.casf_params.casf_enable) + if (crtc_state->hw.casf_params.enable) return true; return false; diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index c85ba9a95322..a11a79a0211e 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -351,7 +351,7 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, drm_printf(&p, "sharpness strength: %d, sharpness tap size: %d, sharpness enable: %d\n", pipe_config->hw.casf_params.strength, pipe_config->hw.casf_params.win_size, - pipe_config->hw.casf_params.casf_enable); + pipe_config->hw.casf_params.enable); drm_printf(&p, "ips: %i, double wide: %i, drrs: %i\n", pipe_config->ips_enabled, pipe_config->double_wide, diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 10b6c6fcb03f..78d97441f682 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -994,7 +994,7 @@ static bool intel_casf_enabling(const struct intel_crtc_state *new_crtc_state, if (!new_crtc_state->hw.active) return false; - return is_enabling(hw.casf_params.casf_enable, old_crtc_state, new_crtc_state); + return is_enabling(hw.casf_params.enable, old_crtc_state, new_crtc_state); } static bool intel_casf_disabling(const struct intel_crtc_state *old_crtc_state, @@ -1003,7 +1003,7 @@ static bool intel_casf_disabling(const struct intel_crtc_state *old_crtc_state, if (!new_crtc_state->hw.active) return false; - return is_disabling(hw.casf_params.casf_enable, old_crtc_state, new_crtc_state); + return is_disabling(hw.casf_params.enable, old_crtc_state, new_crtc_state); } static bool intel_crtc_lobf_enabling(const struct intel_crtc_state *old_crtc_state, @@ -5371,7 +5371,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(scaler_state.scaler_id); PIPE_CONF_CHECK_I(pixel_rate); - PIPE_CONF_CHECK_BOOL(hw.casf_params.casf_enable); + PIPE_CONF_CHECK_BOOL(hw.casf_params.enable); PIPE_CONF_CHECK_I(hw.casf_params.win_size); PIPE_CONF_CHECK_I(hw.casf_params.strength); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index e2496db1642a..83bb5d19b6f6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -997,7 +997,7 @@ struct intel_casf { struct scaler_filter_coeff coeff[SCALER_FILTER_NUM_TAPS]; u8 strength; u8 win_size; - bool casf_enable; + bool enable; }; struct intel_crtc_state { diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 7c5cb188ebf0..cfa17ddb4018 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -986,13 +986,13 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state) if (HAS_CASF(display) && id == 1) intel_casf_sharpness_get_config(crtc_state); - if (!crtc_state->hw.casf_params.casf_enable) + if (!crtc_state->hw.casf_params.enable) 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)); - if (!crtc_state->hw.casf_params.casf_enable) + if (!crtc_state->hw.casf_params.enable) drm_rect_init(&crtc_state->pch_pfit.dst, REG_FIELD_GET(PS_WIN_XPOS_MASK, pos), REG_FIELD_GET(PS_WIN_YPOS_MASK, pos), From e68b7710066c032bba47e6a544d4b3920fe4bd8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:52:36 +0300 Subject: [PATCH 047/144] drm/i915/casf: Make a proper hw state copy of the sharpness_strength MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make a copy of the uapi.sharpness_strength property value in our hw state. This is how we deal with having proper state for joined pipes. Reviewed-by: Michał Grzelak Reviewed-by: Nemesa Garg Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407175244.19654-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_casf.c | 4 ++-- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 5 +++-- drivers/gpu/drm/i915/display/intel_display.c | 6 ++++++ drivers/gpu/drm/i915/display/intel_display_debugfs.c | 5 +++-- drivers/gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_modeset_setup.c | 1 + 6 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_casf.c b/drivers/gpu/drm/i915/display/intel_casf.c index 32e6f7c8acdd..4316d8214e80 100644 --- a/drivers/gpu/drm/i915/display/intel_casf.c +++ b/drivers/gpu/drm/i915/display/intel_casf.c @@ -109,7 +109,7 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state) if (!HAS_CASF(display)) return 0; - if (crtc_state->uapi.sharpness_strength == 0) { + if (crtc_state->hw.sharpness_strength == 0) { crtc_state->hw.casf_params.enable = false; crtc_state->hw.casf_params.strength = 0; return 0; @@ -132,7 +132,7 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state) * Also 85 + 16 = 101. */ crtc_state->hw.casf_params.strength = - min(crtc_state->uapi.sharpness_strength, 0xEF) + 0x10; + min(crtc_state->hw.sharpness_strength, 0xEF) + 0x10; intel_casf_compute_win_size(crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index a11a79a0211e..42676adf6062 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -328,11 +328,12 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, pipe_config->linetime, pipe_config->ips_linetime); if (DISPLAY_VER(display) >= 9) - drm_printf(&p, "num_scalers: %d, scaler_users: 0x%x, scaler_id: %d, scaling_filter: %d\n", + drm_printf(&p, "num_scalers: %d, scaler_users: 0x%x, scaler_id: %d, scaling_filter: %d, sharpness_strength: %d\n", crtc->num_scalers, pipe_config->scaler_state.scaler_users, pipe_config->scaler_state.scaler_id, - pipe_config->hw.scaling_filter); + pipe_config->hw.scaling_filter, + pipe_config->hw.sharpness_strength); drm_printf(&p, "pipe src: " DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_config->pipe_src)); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 78d97441f682..a02c58b5a34d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4550,6 +4550,7 @@ intel_crtc_copy_uapi_to_hw_state_modeset(struct intel_atomic_state *state, drm_mode_copy(&crtc_state->hw.adjusted_mode, &crtc_state->uapi.adjusted_mode); crtc_state->hw.scaling_filter = crtc_state->uapi.scaling_filter; + crtc_state->hw.sharpness_strength = crtc_state->uapi.sharpness_strength; intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc); } @@ -4615,6 +4616,7 @@ copy_joiner_crtc_state_modeset(struct intel_atomic_state *state, drm_mode_copy(&secondary_crtc_state->hw.adjusted_mode, &primary_crtc_state->hw.adjusted_mode); secondary_crtc_state->hw.scaling_filter = primary_crtc_state->hw.scaling_filter; + secondary_crtc_state->hw.sharpness_strength = primary_crtc_state->hw.sharpness_strength; if (primary_crtc_state->dp_tunnel_ref.tunnel) drm_dp_tunnel_ref_get(primary_crtc_state->dp_tunnel_ref.tunnel, @@ -6441,6 +6443,10 @@ int intel_atomic_check(struct drm_device *dev, if (new_crtc_state->uapi.scaling_filter != old_crtc_state->uapi.scaling_filter) new_crtc_state->uapi.mode_changed = true; + + if (new_crtc_state->uapi.sharpness_strength != + old_crtc_state->uapi.sharpness_strength) + new_crtc_state->uapi.mode_changed = true; } intel_vrr_check_modeset(state); diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 2614c4863c87..f244a2b5d139 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -416,11 +416,12 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *crtc) /* Not all platforms have a scaler */ if (num_scalers) { - seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d scaling_filter=%d", + seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d scaling_filter=%d sharpness_strength=%d", num_scalers, crtc_state->scaler_state.scaler_users, crtc_state->scaler_state.scaler_id, - crtc_state->hw.scaling_filter); + crtc_state->hw.scaling_filter, + crtc_state->hw.sharpness_strength); for (i = 0; i < num_scalers; i++) { const struct intel_scaler *sc = diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 83bb5d19b6f6..af0d870de342 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1036,6 +1036,7 @@ struct intel_crtc_state { struct drm_property_blob *degamma_lut, *gamma_lut, *ctm; struct drm_display_mode mode, pipe_mode, adjusted_mode; enum drm_scaling_filter scaling_filter; + u8 sharpness_strength; struct intel_casf casf_params; } hw; diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 4086f16a12bf..40a65a0d7ec7 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -333,6 +333,7 @@ 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; if (DISPLAY_INFO(display)->color.degamma_lut_size) { /* assume 1:1 mapping */ From 3790c44364cd995481136cdbb2457fd9ae0127dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:52:37 +0300 Subject: [PATCH 048/144] drm/i915/casf: Move the casf state to better place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The casf state is placed inside the 'hw' state for some reason. That is only really meant for things we have to duplicate from the uapi state. The rest can live on its own in our actual state. And since casf is just one aspect of the pfit/pipe scaler the proper place for it seems to be under pch_pfit. Reviewed-by: Michał Grzelak Reviewed-by: Nemesa Garg Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407175244.19654-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_casf.c | 40 +++++++++---------- .../drm/i915/display/intel_crtc_state_dump.c | 6 +-- drivers/gpu/drm/i915/display/intel_display.c | 12 +++--- .../drm/i915/display/intel_display_types.h | 2 +- drivers/gpu/drm/i915/display/skl_scaler.c | 4 +- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_casf.c b/drivers/gpu/drm/i915/display/intel_casf.c index 4316d8214e80..5a8ffb40d30d 100644 --- a/drivers/gpu/drm/i915/display/intel_casf.c +++ b/drivers/gpu/drm/i915/display/intel_casf.c @@ -82,7 +82,7 @@ void intel_casf_update_strength(struct intel_crtc_state *crtc_state) int win_size; intel_de_rmw(display, SHARPNESS_CTL(crtc->pipe), FILTER_STRENGTH_MASK, - FILTER_STRENGTH(crtc_state->hw.casf_params.strength)); + FILTER_STRENGTH(crtc_state->pch_pfit.casf.strength)); win_size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, 1)); @@ -95,11 +95,11 @@ static void intel_casf_compute_win_size(struct intel_crtc_state *crtc_state) u32 total_pixels = mode->hdisplay * mode->vdisplay; if (total_pixels <= MAX_PIXELS_FOR_3_TAP_FILTER) - crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_3X3; + crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_3X3; else if (total_pixels <= MAX_PIXELS_FOR_5_TAP_FILTER) - crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_5X5; + crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_5X5; else - crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_7X7; + crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_7X7; } int intel_casf_compute_config(struct intel_crtc_state *crtc_state) @@ -110,8 +110,8 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state) return 0; if (crtc_state->hw.sharpness_strength == 0) { - crtc_state->hw.casf_params.enable = false; - crtc_state->hw.casf_params.strength = 0; + crtc_state->pch_pfit.casf.enable = false; + crtc_state->pch_pfit.casf.strength = 0; return 0; } @@ -121,7 +121,7 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state) return -EINVAL; } - crtc_state->hw.casf_params.enable = true; + crtc_state->pch_pfit.casf.enable = true; /* * HW takes a value in form (1.0 + strength) in 4.4 fixed format. @@ -131,7 +131,7 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state) * 6.3125 in 4.4 format is b01100101 which is equal to 101. * Also 85 + 16 = 101. */ - crtc_state->hw.casf_params.strength = + crtc_state->pch_pfit.casf.strength = min(crtc_state->hw.sharpness_strength, 0xEF) + 0x10; intel_casf_compute_win_size(crtc_state); @@ -151,19 +151,19 @@ void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state) if (sharp & FILTER_EN) { if (drm_WARN_ON(display->drm, REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp) < 16)) - crtc_state->hw.casf_params.strength = 0; + crtc_state->pch_pfit.casf.strength = 0; else - crtc_state->hw.casf_params.strength = + crtc_state->pch_pfit.casf.strength = REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp); - crtc_state->hw.casf_params.enable = true; - crtc_state->hw.casf_params.win_size = + crtc_state->pch_pfit.casf.enable = true; + crtc_state->pch_pfit.casf.win_size = REG_FIELD_GET(FILTER_SIZE_MASK, sharp); } } bool intel_casf_needs_scaler(const struct intel_crtc_state *crtc_state) { - if (crtc_state->hw.casf_params.enable) + if (crtc_state->pch_pfit.casf.enable) return true; return false; @@ -179,7 +179,7 @@ static u32 casf_coeff(struct intel_crtc_state *crtc_state, int t) struct scaler_filter_coeff value; u32 coeff; - value = crtc_state->hw.casf_params.coeff[t]; + value = crtc_state->pch_pfit.casf.coeff[t]; value.sign = 0; coeff = value.sign << 15 | value.exp << 12 | value.mantissa << 3; @@ -189,7 +189,7 @@ static u32 casf_coeff(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 - * that are calculated and stored in hw.casf_params.coeff as per + * that are calculated and stored in pch_pfit.casf.coeff as per * SCALER_COEFFICIENT_FORMAT */ static void intel_casf_write_coeff(struct intel_crtc_state *crtc_state) @@ -247,9 +247,9 @@ void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state) u16 sumcoeff = 0; int i; - if (crtc_state->hw.casf_params.win_size == 0) + if (crtc_state->pch_pfit.casf.win_size == 0) filtercoeff = filtercoeff_1; - else if (crtc_state->hw.casf_params.win_size == 1) + else if (crtc_state->pch_pfit.casf.win_size == 1) filtercoeff = filtercoeff_2; else filtercoeff = filtercoeff_3; @@ -259,7 +259,7 @@ void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state) for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) { filter_coeff[i] = (*(filtercoeff + i) * 100 / sumcoeff); - convert_sharpness_coef_binary(&crtc_state->hw.casf_params.coeff[i], + convert_sharpness_coef_binary(&crtc_state->pch_pfit.casf.coeff[i], filter_coeff[i]); } } @@ -274,9 +274,9 @@ void intel_casf_enable(struct intel_crtc_state *crtc_state) intel_casf_write_coeff(crtc_state); - sharpness_ctl = FILTER_EN | FILTER_STRENGTH(crtc_state->hw.casf_params.strength); + sharpness_ctl = FILTER_EN | FILTER_STRENGTH(crtc_state->pch_pfit.casf.strength); - sharpness_ctl |= crtc_state->hw.casf_params.win_size; + sharpness_ctl |= crtc_state->pch_pfit.casf.win_size; intel_de_write(display, SHARPNESS_CTL(crtc->pipe), sharpness_ctl); diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 42676adf6062..4493483f10a9 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -350,9 +350,9 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, str_yes_no(pipe_config->pch_pfit.force_thru)); drm_printf(&p, "sharpness strength: %d, sharpness tap size: %d, sharpness enable: %d\n", - pipe_config->hw.casf_params.strength, - pipe_config->hw.casf_params.win_size, - pipe_config->hw.casf_params.enable); + pipe_config->pch_pfit.casf.strength, + pipe_config->pch_pfit.casf.win_size, + pipe_config->pch_pfit.casf.enable); drm_printf(&p, "ips: %i, double wide: %i, drrs: %i\n", pipe_config->ips_enabled, pipe_config->double_wide, diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a02c58b5a34d..e02e69467871 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -994,7 +994,7 @@ static bool intel_casf_enabling(const struct intel_crtc_state *new_crtc_state, if (!new_crtc_state->hw.active) return false; - return is_enabling(hw.casf_params.enable, old_crtc_state, new_crtc_state); + return is_enabling(pch_pfit.casf.enable, old_crtc_state, new_crtc_state); } static bool intel_casf_disabling(const struct intel_crtc_state *old_crtc_state, @@ -1003,7 +1003,7 @@ static bool intel_casf_disabling(const struct intel_crtc_state *old_crtc_state, if (!new_crtc_state->hw.active) return false; - return is_disabling(hw.casf_params.enable, old_crtc_state, new_crtc_state); + return is_disabling(pch_pfit.casf.enable, old_crtc_state, new_crtc_state); } static bool intel_crtc_lobf_enabling(const struct intel_crtc_state *old_crtc_state, @@ -5370,12 +5370,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(pch_pfit.enabled); PIPE_CONF_CHECK_RECT(pch_pfit.dst); + PIPE_CONF_CHECK_BOOL(pch_pfit.casf.enable); + PIPE_CONF_CHECK_I(pch_pfit.casf.win_size); + PIPE_CONF_CHECK_I(pch_pfit.casf.strength); PIPE_CONF_CHECK_I(scaler_state.scaler_id); PIPE_CONF_CHECK_I(pixel_rate); - PIPE_CONF_CHECK_BOOL(hw.casf_params.enable); - PIPE_CONF_CHECK_I(hw.casf_params.win_size); - PIPE_CONF_CHECK_I(hw.casf_params.strength); PIPE_CONF_CHECK_X(gamma_mode); if (display->platform.cherryview) @@ -6819,7 +6819,7 @@ static void intel_pre_update_crtc(struct intel_atomic_state *state, if (intel_casf_enabling(new_crtc_state, old_crtc_state)) intel_casf_enable(new_crtc_state); - else if (new_crtc_state->hw.casf_params.strength != old_crtc_state->hw.casf_params.strength) + else if (new_crtc_state->pch_pfit.casf.strength != old_crtc_state->pch_pfit.casf.strength) intel_casf_update_strength(new_crtc_state); intel_fbc_update(state, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index af0d870de342..ca2581fb7bbd 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1037,7 +1037,6 @@ struct intel_crtc_state { struct drm_display_mode mode, pipe_mode, adjusted_mode; enum drm_scaling_filter scaling_filter; u8 sharpness_strength; - struct intel_casf casf_params; } hw; /* actual state of LUTs */ @@ -1224,6 +1223,7 @@ struct intel_crtc_state { /* Panel fitter placement and size for Ironlake+ */ struct { + struct intel_casf casf; struct drm_rect dst; bool enabled; bool force_thru; diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index cfa17ddb4018..e9fe5c0bf6ff 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -986,13 +986,13 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state) if (HAS_CASF(display) && id == 1) intel_casf_sharpness_get_config(crtc_state); - if (!crtc_state->hw.casf_params.enable) + if (!crtc_state->pch_pfit.casf.enable) 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)); - if (!crtc_state->hw.casf_params.enable) + if (!crtc_state->pch_pfit.casf.enable) drm_rect_init(&crtc_state->pch_pfit.dst, REG_FIELD_GET(PS_WIN_XPOS_MASK, pos), REG_FIELD_GET(PS_WIN_YPOS_MASK, pos), From 17d70a0760f2baa739f84d2c0933e0e0876f541c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:52:38 +0300 Subject: [PATCH 049/144] drm/i915/casf: Extract scaler_has_casf() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract a small helper to determine if the scaler supports the sharpness filter or not. Reviewed-by: Michał Grzelak Reviewed-by: Nemesa Garg Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407175244.19654-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/skl_scaler.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index e9fe5c0bf6ff..525afd736195 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -323,19 +323,24 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, need_scaler); } +static bool scaler_has_casf(struct intel_display *display, int scaler_id) +{ + return HAS_CASF(display) && scaler_id == 1; +} + static int intel_allocate_scaler(struct intel_crtc_scaler_state *scaler_state, struct intel_crtc *crtc, struct intel_plane_state *plane_state, bool casf_scaler) { + struct intel_display *display = to_intel_display(crtc); int i; for (i = 0; i < crtc->num_scalers; i++) { if (scaler_state->scalers[i].in_use) continue; - /* CASF needs second scaler */ - if (!plane_state && casf_scaler && i != 1) + if (casf_scaler && !scaler_has_casf(display, i)) continue; scaler_state->scalers[i].in_use = true; @@ -982,8 +987,7 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state) id = i; - /* Read CASF regs for second scaler */ - if (HAS_CASF(display) && id == 1) + if (scaler_has_casf(display, i)) intel_casf_sharpness_get_config(crtc_state); if (!crtc_state->pch_pfit.casf.enable) From 7583232af13e1a0b0a44cc7c0af9db56a7de30e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:52:39 +0300 Subject: [PATCH 050/144] drm/i915/casf: Handle CASF in skl_scaler_get_filter_select() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nuke the duplicate CASF_SCALER_FILTER_SELECT and just have skl_scaler_get_filter_select() return the proper value for sharpness filter use. It is the same "use programmable coefficients" value we already use for the nearest neighbor filtering. Reviewed-by: Michał Grzelak Reviewed-by: Nemesa Garg Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407175244.19654-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/skl_scaler.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 525afd736195..d8bf65c6b4a7 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -730,9 +730,9 @@ static void glk_program_nearest_filter_coefs(struct intel_display *display, GLK_PS_COEF_INDEX_SET(pipe, id, set), 0); } -static u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter) +static u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, bool casf) { - if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR) + if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR || casf) return (PS_FILTER_PROGRAMMED | PS_Y_VERT_FILTER_SELECT(0) | PS_Y_HORZ_FILTER_SELECT(0) | @@ -757,13 +757,6 @@ static void skl_scaler_setup_filter(struct intel_display *display, } } -#define CASF_SCALER_FILTER_SELECT \ - (PS_FILTER_PROGRAMMED | \ - PS_Y_VERT_FILTER_SELECT(0) | \ - PS_Y_HORZ_FILTER_SELECT(0) | \ - PS_UV_VERT_FILTER_SELECT(0) | \ - PS_UV_HORZ_FILTER_SELECT(0)) - void skl_scaler_setup_casf(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -794,7 +787,7 @@ void skl_scaler_setup_casf(struct intel_crtc_state *crtc_state) trace_intel_pipe_scaler_update_arm(crtc, id, x, y, width, height); ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode | - CASF_SCALER_FILTER_SELECT; + skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, true); intel_de_write_fw(display, SKL_PS_CTRL(pipe, id), ps_ctrl); intel_de_write_fw(display, SKL_PS_WIN_POS(pipe, id), @@ -844,7 +837,7 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) id = scaler_state->scaler_id; ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode | - skl_scaler_get_filter_select(crtc_state->hw.scaling_filter); + skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, false); trace_intel_pipe_scaler_update_arm(crtc, id, x, y, width, height); @@ -910,7 +903,7 @@ skl_program_plane_scaler(struct intel_dsb *dsb, } ps_ctrl = PS_SCALER_EN | PS_BINDING_PLANE(plane->id) | scaler->mode | - skl_scaler_get_filter_select(plane_state->hw.scaling_filter); + skl_scaler_get_filter_select(plane_state->hw.scaling_filter, false); trace_intel_plane_scaler_update_arm(plane, scaler_id, crtc_x, crtc_y, crtc_w, crtc_h); From 114a836384b9786df3cbe815fccf9cf1a72761b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:52:40 +0300 Subject: [PATCH 051/144] drm/i915/casf: Constify crtc_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the crtc_state const everywhere in the sharpness filter code where it doesn't need to be mutated. Reviewed-by: Michał Grzelak Reviewed-by: Nemesa Garg Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407175244.19654-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_casf.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_casf.h | 4 ++-- drivers/gpu/drm/i915/display/skl_scaler.c | 8 ++++---- drivers/gpu/drm/i915/display/skl_scaler.h | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_casf.c b/drivers/gpu/drm/i915/display/intel_casf.c index 5a8ffb40d30d..f777aae3fc57 100644 --- a/drivers/gpu/drm/i915/display/intel_casf.c +++ b/drivers/gpu/drm/i915/display/intel_casf.c @@ -75,7 +75,7 @@ static void intel_casf_filter_lut_load(struct intel_crtc *crtc, sharpness_lut[i]); } -void intel_casf_update_strength(struct intel_crtc_state *crtc_state) +void intel_casf_update_strength(const 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); @@ -174,7 +174,7 @@ static int casf_coeff_tap(int i) return i % SCALER_FILTER_NUM_TAPS; } -static u32 casf_coeff(struct intel_crtc_state *crtc_state, int t) +static u32 casf_coeff(const struct intel_crtc_state *crtc_state, int t) { struct scaler_filter_coeff value; u32 coeff; @@ -192,7 +192,7 @@ static u32 casf_coeff(struct intel_crtc_state *crtc_state, int t) * that are calculated and stored in pch_pfit.casf.coeff as per * SCALER_COEFFICIENT_FORMAT */ -static void intel_casf_write_coeff(struct intel_crtc_state *crtc_state) +static void intel_casf_write_coeff(const 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); @@ -264,7 +264,7 @@ void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state) } } -void intel_casf_enable(struct intel_crtc_state *crtc_state) +void intel_casf_enable(const 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); diff --git a/drivers/gpu/drm/i915/display/intel_casf.h b/drivers/gpu/drm/i915/display/intel_casf.h index b3fb0bcb3f5b..c4f984b73348 100644 --- a/drivers/gpu/drm/i915/display/intel_casf.h +++ b/drivers/gpu/drm/i915/display/intel_casf.h @@ -11,9 +11,9 @@ struct intel_crtc_state; int intel_casf_compute_config(struct intel_crtc_state *crtc_state); -void intel_casf_update_strength(struct intel_crtc_state *new_crtc_state); +void intel_casf_update_strength(const struct intel_crtc_state *new_crtc_state); void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state); -void intel_casf_enable(struct intel_crtc_state *crtc_state); +void intel_casf_enable(const struct intel_crtc_state *crtc_state); void intel_casf_disable(const struct intel_crtc_state *crtc_state); void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state); bool intel_casf_needs_scaler(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index d8bf65c6b4a7..762f4bb46c2d 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -757,13 +757,13 @@ static void skl_scaler_setup_filter(struct intel_display *display, } } -void skl_scaler_setup_casf(struct intel_crtc_state *crtc_state) +void skl_scaler_setup_casf(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_display *display = to_intel_display(crtc); - struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - struct intel_crtc_scaler_state *scaler_state = + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + const struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; struct drm_rect src, dest; int id, width, height; diff --git a/drivers/gpu/drm/i915/display/skl_scaler.h b/drivers/gpu/drm/i915/display/skl_scaler.h index 7e8d819c019d..20ecf373eb19 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.h +++ b/drivers/gpu/drm/i915/display/skl_scaler.h @@ -36,7 +36,7 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state); void skl_scaler_get_config(struct intel_crtc_state *crtc_state); -void skl_scaler_setup_casf(struct intel_crtc_state *crtc_state); +void skl_scaler_setup_casf(const struct intel_crtc_state *crtc_state); enum drm_mode_status skl_scaler_mode_valid(struct intel_display *display, From 9a459db0ae1d742c9183b9a092d060f29b979964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:52:41 +0300 Subject: [PATCH 052/144] drm/i915/casf: Remove redundant argument from intel_casf_filter_lut_load() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_casf_filter_lut_load() can find the crtc from the crtc_state. No need to pass in both. Reviewed-by: Michał Grzelak Reviewed-by: Nemesa Garg Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407175244.19654-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_casf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_casf.c b/drivers/gpu/drm/i915/display/intel_casf.c index f777aae3fc57..21e84a4f9ff5 100644 --- a/drivers/gpu/drm/i915/display/intel_casf.c +++ b/drivers/gpu/drm/i915/display/intel_casf.c @@ -61,10 +61,10 @@ const u16 filtercoeff_3[] = { FILTER_COEFF_0_125, }; -static void intel_casf_filter_lut_load(struct intel_crtc *crtc, - const struct intel_crtc_state *crtc_state) +static void intel_casf_filter_lut_load(const 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); int i; intel_de_write(display, SHRPLUT_INDEX(crtc->pipe), @@ -270,7 +270,7 @@ void intel_casf_enable(const struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); u32 sharpness_ctl; - intel_casf_filter_lut_load(crtc, crtc_state); + intel_casf_filter_lut_load(crtc_state); intel_casf_write_coeff(crtc_state); From d4686f34bbebabeee3130678f01a17bd7cd58e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:52:42 +0300 Subject: [PATCH 053/144] drm/i915/pfit: Call intel_pfit_compute_config() unconditionally on (e)DP/HDMI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now have three different reasons for calling intel_pfit_compute_config(): - actual pfit scaling/centering - YCbCr 4:2:0 output - sharpness filter So let's just call intel_pfit_compute_config() unconditionally from both the DP and HDMI code. Both gmch and ilk+ pfit code should be capable of judging whether anything actually needs the pfit. The only slightly questionable thing in the gmch code is the dithering knob, but that's only a thing on gen2/3 which don't even have HDMI/DP outputs, and so not an issue here. Reviewed-by: Michał Grzelak Reviewed-by: Nemesa Garg Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407175244.19654-9-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 9 +++------ drivers/gpu/drm/i915/display/intel_hdmi.c | 8 +++----- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 4955bd8b11d7..ff3904b77492 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3545,12 +3545,9 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (ret) return ret; - if ((intel_dp_is_edp(intel_dp) && fixed_mode) || - pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { - ret = intel_pfit_compute_config(pipe_config, conn_state); - if (ret) - return ret; - } + ret = intel_pfit_compute_config(pipe_config, conn_state); + if (ret) + return ret; pipe_config->limited_color_range = intel_dp_limited_color_range(pipe_config, conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 05e898d10a2b..17bd2c207453 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2380,11 +2380,9 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, return ret; } - if (intel_hdmi_is_ycbcr420(pipe_config)) { - ret = intel_pfit_compute_config(pipe_config, conn_state); - if (ret) - return ret; - } + ret = intel_pfit_compute_config(pipe_config, conn_state); + if (ret) + return ret; pipe_config->limited_color_range = intel_hdmi_limited_color_range(pipe_config, conn_state); From 5400b7eb666968f77e79f42531c5a138394f2f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:52:43 +0300 Subject: [PATCH 054/144] drm/i915/casf: Integrate the sharpness filter properly into the scaler code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sharpness filter is just a special mode of the pipe scaler. It doesn't warrant all this special casing everywhere. Just integrate it properly into the scaler code so that it's treated no different from the other pipe scaler uses (scaling,centering, YCbCr 4:2:0 output). v2: Also reject scaling_filter vs. sharpness Reviewed-by: Nemesa Garg Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407175244.19654-10-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_casf.c | 62 ++------------ drivers/gpu/drm/i915/display/intel_casf.h | 6 +- drivers/gpu/drm/i915/display/intel_display.c | 34 +------- drivers/gpu/drm/i915/display/intel_pfit.c | 13 ++- drivers/gpu/drm/i915/display/skl_scaler.c | 85 ++++++++------------ drivers/gpu/drm/i915/display/skl_scaler.h | 2 - 6 files changed, 53 insertions(+), 149 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_casf.c b/drivers/gpu/drm/i915/display/intel_casf.c index 21e84a4f9ff5..c2d2746c5f04 100644 --- a/drivers/gpu/drm/i915/display/intel_casf.c +++ b/drivers/gpu/drm/i915/display/intel_casf.c @@ -75,20 +75,6 @@ static void intel_casf_filter_lut_load(const struct intel_crtc_state *crtc_state sharpness_lut[i]); } -void intel_casf_update_strength(const 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); - int win_size; - - intel_de_rmw(display, SHARPNESS_CTL(crtc->pipe), FILTER_STRENGTH_MASK, - FILTER_STRENGTH(crtc_state->pch_pfit.casf.strength)); - - win_size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, 1)); - - intel_de_write_fw(display, SKL_PS_WIN_SZ(crtc->pipe, 1), win_size); -} - static void intel_casf_compute_win_size(struct intel_crtc_state *crtc_state) { const struct drm_display_mode *mode = &crtc_state->hw.adjusted_mode; @@ -102,19 +88,15 @@ 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); + int intel_casf_compute_config(struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - if (!HAS_CASF(display)) + if (crtc_state->hw.sharpness_strength == 0) return 0; - if (crtc_state->hw.sharpness_strength == 0) { - crtc_state->pch_pfit.casf.enable = false; - crtc_state->pch_pfit.casf.strength = 0; - return 0; - } - /* CASF with joiner not supported in hardware */ if (crtc_state->joiner_pipes) { drm_dbg_kms(display->drm, "CASF not supported with joiner\n"); @@ -136,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_config(crtc_state); + intel_casf_scaler_compute_coef(crtc_state); return 0; } @@ -161,14 +143,6 @@ void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state) } } -bool intel_casf_needs_scaler(const struct intel_crtc_state *crtc_state) -{ - if (crtc_state->pch_pfit.casf.enable) - return true; - - return false; -} - static int casf_coeff_tap(int i) { return i % SCALER_FILTER_NUM_TAPS; @@ -240,7 +214,7 @@ static void convert_sharpness_coef_binary(struct scaler_filter_coeff *coeff, } } -void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state) +static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state) { const u16 *filtercoeff; u16 filter_coeff[SCALER_FILTER_NUM_TAPS]; @@ -264,32 +238,8 @@ void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state) } } -void intel_casf_enable(const struct intel_crtc_state *crtc_state) +void intel_casf_setup(const 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 sharpness_ctl; - intel_casf_filter_lut_load(crtc_state); - intel_casf_write_coeff(crtc_state); - - sharpness_ctl = FILTER_EN | FILTER_STRENGTH(crtc_state->pch_pfit.casf.strength); - - sharpness_ctl |= crtc_state->pch_pfit.casf.win_size; - - intel_de_write(display, SHARPNESS_CTL(crtc->pipe), sharpness_ctl); - - skl_scaler_setup_casf(crtc_state); -} - -void intel_casf_disable(const 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); - - intel_de_write(display, SKL_PS_CTRL(crtc->pipe, 1), 0); - intel_de_write(display, SKL_PS_WIN_POS(crtc->pipe, 1), 0); - intel_de_write(display, SHARPNESS_CTL(crtc->pipe), 0); - intel_de_write(display, SKL_PS_WIN_SZ(crtc->pipe, 1), 0); } diff --git a/drivers/gpu/drm/i915/display/intel_casf.h b/drivers/gpu/drm/i915/display/intel_casf.h index c4f984b73348..3ebb7522af0a 100644 --- a/drivers/gpu/drm/i915/display/intel_casf.h +++ b/drivers/gpu/drm/i915/display/intel_casf.h @@ -11,11 +11,7 @@ struct intel_crtc_state; int intel_casf_compute_config(struct intel_crtc_state *crtc_state); -void intel_casf_update_strength(const struct intel_crtc_state *new_crtc_state); void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state); -void intel_casf_enable(const struct intel_crtc_state *crtc_state); -void intel_casf_disable(const struct intel_crtc_state *crtc_state); -void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state); -bool intel_casf_needs_scaler(const struct intel_crtc_state *crtc_state); +void intel_casf_setup(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_CASF_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e02e69467871..58a654ca0d20 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -58,7 +58,6 @@ #include "intel_audio.h" #include "intel_bo.h" #include "intel_bw.h" -#include "intel_casf.h" #include "intel_cdclk.h" #include "intel_clock_gating.h" #include "intel_color.h" @@ -988,24 +987,6 @@ static bool audio_disabling(const struct intel_crtc_state *old_crtc_state, memcmp(old_crtc_state->eld, new_crtc_state->eld, MAX_ELD_BYTES) != 0); } -static bool intel_casf_enabling(const struct intel_crtc_state *new_crtc_state, - const struct intel_crtc_state *old_crtc_state) -{ - if (!new_crtc_state->hw.active) - return false; - - return is_enabling(pch_pfit.casf.enable, old_crtc_state, new_crtc_state); -} - -static bool intel_casf_disabling(const struct intel_crtc_state *old_crtc_state, - const struct intel_crtc_state *new_crtc_state) -{ - if (!new_crtc_state->hw.active) - return false; - - return is_disabling(pch_pfit.casf.enable, old_crtc_state, new_crtc_state); -} - static bool intel_crtc_lobf_enabling(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state) { @@ -1187,9 +1168,6 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, if (audio_disabling(old_crtc_state, new_crtc_state)) intel_encoders_audio_disable(state, crtc); - if (intel_casf_disabling(old_crtc_state, new_crtc_state)) - intel_casf_disable(new_crtc_state); - intel_drrs_deactivate(old_crtc_state); if (hsw_ips_pre_update(state, crtc)) @@ -4308,14 +4286,9 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, return ret; } - ret = intel_casf_compute_config(crtc_state); - if (ret) - return ret; - if (DISPLAY_VER(display) >= 9) { if (intel_crtc_needs_modeset(crtc_state) || - intel_crtc_needs_fastset(crtc_state) || - intel_casf_needs_scaler(crtc_state)) { + intel_crtc_needs_fastset(crtc_state)) { ret = skl_update_scaler_crtc(crtc_state); if (ret) return ret; @@ -6817,11 +6790,6 @@ static void intel_pre_update_crtc(struct intel_atomic_state *state, intel_vrr_set_transcoder_timings(new_crtc_state); } - if (intel_casf_enabling(new_crtc_state, old_crtc_state)) - intel_casf_enable(new_crtc_state); - else if (new_crtc_state->pch_pfit.casf.strength != old_crtc_state->pch_pfit.casf.strength) - intel_casf_update_strength(new_crtc_state); - intel_fbc_update(state, crtc); drm_WARN_ON(display->drm, !intel_display_power_is_enabled(display, POWER_DOMAIN_DC_OFF)); diff --git a/drivers/gpu/drm/i915/display/intel_pfit.c b/drivers/gpu/drm/i915/display/intel_pfit.c index 2dec4ccf74ce..5b170c74a510 100644 --- a/drivers/gpu/drm/i915/display/intel_pfit.c +++ b/drivers/gpu/drm/i915/display/intel_pfit.c @@ -196,7 +196,8 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, /* Native modes don't need fitting */ if (adjusted_mode->crtc_hdisplay == pipe_src_w && adjusted_mode->crtc_vdisplay == pipe_src_h && - crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420) + crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420 && + crtc_state->hw.sharpness_strength == 0) return 0; switch (conn_state->scaling_mode) { @@ -260,6 +261,16 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, return -EINVAL; } + if (crtc_state->hw.sharpness_strength && + (width != pipe_src_w || height != pipe_src_h || + crtc_state->hw.scaling_filter != DRM_SCALING_FILTER_DEFAULT || + crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)) { + drm_dbg_kms(display->drm, + "[CRTC:%d:%s] no scaling/YCbCr output with sharpness filter\n", + crtc->base.base.id, crtc->base.name); + return -EINVAL; + } + drm_rect_init(&crtc_state->pch_pfit.dst, x, y, width, height); crtc_state->pch_pfit.enabled = true; diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 762f4bb46c2d..308b8d363bba 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -270,6 +270,11 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state) { const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; int width, height; + int ret; + + ret = intel_casf_compute_config(crtc_state); + if (ret) + return ret; if (crtc_state->pch_pfit.enabled) { width = drm_rect_width(&crtc_state->pch_pfit.dst); @@ -284,8 +289,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state) drm_rect_width(&crtc_state->pipe_src), drm_rect_height(&crtc_state->pipe_src), width, height, NULL, 0, - crtc_state->pch_pfit.enabled || - intel_casf_needs_scaler(crtc_state)); + crtc_state->pch_pfit.enabled); } /** @@ -534,14 +538,11 @@ static int setup_crtc_scaler(struct intel_atomic_state *state, struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; - if (intel_casf_needs_scaler(crtc_state) && crtc_state->pch_pfit.enabled) - return -EINVAL; - return intel_atomic_setup_scaler(crtc_state, hweight32(scaler_state->scaler_users), crtc, "CRTC", crtc->base.base.id, NULL, &scaler_state->scaler_id, - intel_casf_needs_scaler(crtc_state)); + crtc_state->pch_pfit.casf.enable); } static int setup_plane_scaler(struct intel_atomic_state *state, @@ -757,43 +758,14 @@ static void skl_scaler_setup_filter(struct intel_display *display, } } -void skl_scaler_setup_casf(const struct intel_crtc_state *crtc_state) +static u32 casf_sharpness_ctl(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct intel_display *display = to_intel_display(crtc); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - const struct intel_crtc_scaler_state *scaler_state = - &crtc_state->scaler_state; - struct drm_rect src, dest; - int id, width, height; - int x = 0, y = 0; - enum pipe pipe = crtc->pipe; - u32 ps_ctrl; + if (!crtc_state->pch_pfit.casf.enable) + return 0; - width = adjusted_mode->crtc_hdisplay; - height = adjusted_mode->crtc_vdisplay; - - drm_rect_init(&dest, x, y, width, height); - - width = drm_rect_width(&dest); - height = drm_rect_height(&dest); - id = scaler_state->scaler_id; - - drm_rect_init(&src, 0, 0, - drm_rect_width(&crtc_state->pipe_src) << 16, - drm_rect_height(&crtc_state->pipe_src) << 16); - - trace_intel_pipe_scaler_update_arm(crtc, id, x, y, width, height); - - ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode | - skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, true); - - intel_de_write_fw(display, SKL_PS_CTRL(pipe, id), ps_ctrl); - intel_de_write_fw(display, SKL_PS_WIN_POS(pipe, id), - PS_WIN_XPOS(x) | PS_WIN_YPOS(y)); - intel_de_write_fw(display, SKL_PS_WIN_SZ(pipe, id), - PS_WIN_XSIZE(width) | PS_WIN_YSIZE(height)); + return FILTER_EN | + FILTER_STRENGTH(crtc_state->pch_pfit.casf.strength) | + crtc_state->pch_pfit.casf.win_size; } void skl_pfit_enable(const struct intel_crtc_state *crtc_state) @@ -837,12 +809,20 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) id = scaler_state->scaler_id; ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode | - skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, false); + skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, + crtc_state->pch_pfit.casf.enable); trace_intel_pipe_scaler_update_arm(crtc, id, x, y, width, height); - skl_scaler_setup_filter(display, NULL, pipe, id, 0, - crtc_state->hw.scaling_filter); + if (crtc_state->pch_pfit.casf.enable) + intel_casf_setup(crtc_state); + else + skl_scaler_setup_filter(display, NULL, pipe, id, 0, + crtc_state->hw.scaling_filter); + + if (scaler_has_casf(display, id)) + intel_de_write_fw(display, SHARPNESS_CTL(crtc->pipe), + casf_sharpness_ctl(crtc_state)); intel_de_write_fw(display, SKL_PS_CTRL(pipe, id), ps_ctrl); @@ -930,6 +910,9 @@ static void skl_detach_scaler(struct intel_dsb *dsb, trace_intel_scaler_disable_arm(crtc, id); + if (scaler_has_casf(display, id)) + intel_de_write_dsb(display, dsb, SHARPNESS_CTL(crtc->pipe), 0); + intel_de_write_dsb(display, dsb, SKL_PS_CTRL(crtc->pipe, id), 0); intel_de_write_dsb(display, dsb, SKL_PS_WIN_POS(crtc->pipe, id), 0); intel_de_write_dsb(display, dsb, SKL_PS_WIN_SZ(crtc->pipe, id), 0); @@ -983,18 +966,16 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state) if (scaler_has_casf(display, i)) intel_casf_sharpness_get_config(crtc_state); - if (!crtc_state->pch_pfit.casf.enable) - 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)); - if (!crtc_state->pch_pfit.casf.enable) - 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; diff --git a/drivers/gpu/drm/i915/display/skl_scaler.h b/drivers/gpu/drm/i915/display/skl_scaler.h index 20ecf373eb19..5deabca909e6 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.h +++ b/drivers/gpu/drm/i915/display/skl_scaler.h @@ -36,8 +36,6 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state); void skl_scaler_get_config(struct intel_crtc_state *crtc_state); -void skl_scaler_setup_casf(const struct intel_crtc_state *crtc_state); - enum drm_mode_status skl_scaler_mode_valid(struct intel_display *display, const struct drm_display_mode *mode, From 332021557104ccf46d40ef7bae3f12a53f56edf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 21:30:15 +0300 Subject: [PATCH 055/144] drm/i915/dp: Don't use DP link min bpp for the FRL link bandwidth check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_dp_mode_min_link_bpp_x16() gives us the min bpp for the DP link before the PCON, however intel_dp_mode_valid_downstream() is trying to check for sufficient bandwidth on the HDMI FRL link after the PCON. So the use of intel_dp_mode_min_link_bpp_x16() here is incorrect. Presumably even with FRL HDMI still can't go below 8bpc, so we should just use that to give us the minimum required FRL bandwidth. And this needs to account for the sink format (for 4:2:0 sub-sampling) since that is what will be flowing over the HDMI link. Cc: Ankit Nautiyal Cc: Nicolas Frattaroli Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407183015.16256-1-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal Reviewed-by: Nicolas Frattaroli --- drivers/gpu/drm/i915/display/intel_dp.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ff3904b77492..b8b6d62fb275 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1317,6 +1317,15 @@ intel_dp_tmds_clock_valid(struct intel_dp *intel_dp, return MODE_OK; } +static int frl_required_bw(int clock, int bpc, + enum intel_output_format sink_format) +{ + if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420) + clock /= 2; + + return clock * bpc * 3; +} + static enum drm_mode_status intel_dp_mode_valid_downstream(struct intel_connector *connector, const struct drm_display_mode *mode, @@ -1327,13 +1336,14 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, enum drm_mode_status status; enum intel_output_format sink_format; + sink_format = intel_dp_sink_format(connector, mode); + /* If PCON supports FRL MODE, check FRL bandwidth constraints */ if (intel_dp->dfp.pcon_max_frl_bw) { - int link_bpp_x16 = intel_dp_mode_min_link_bpp_x16(connector, mode); - int target_bw; - int max_frl_bw; + int target_bw, max_frl_bw; - target_bw = fxp_q4_to_int_roundup(link_bpp_x16) * target_clock; + /* Assume 8bpc for the FRL bandwidth check */ + target_bw = frl_required_bw(target_clock, 8, sink_format); max_frl_bw = intel_dp->dfp.pcon_max_frl_bw; @@ -1350,8 +1360,6 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, target_clock > intel_dp->dfp.max_dotclock) return MODE_CLOCK_HIGH; - sink_format = intel_dp_sink_format(connector, mode); - /* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */ status = intel_dp_tmds_clock_valid(intel_dp, target_clock, 8, sink_format, true); From acfc688bc51b661ed59c1065052282010aa64e50 Mon Sep 17 00:00:00 2001 From: Dibin Moolakadan Subrahmanian Date: Tue, 7 Apr 2026 16:21:02 +0530 Subject: [PATCH 056/144] drm/i915/dmc: Reduce wakelock hold time __intel_dmc_wl_release() schedules delayed work which releases the DMC wakelock after a fixed timeout of 50 ms. Until the delayed work runs, the wakelock remains held and prevents entry into deeper DC states. Reduce DMC_WAKELOCK_HOLD_TIME from 50 ms to 5 ms. This should allow the system to enter deeper DC states sooner once MMIO activity settles down. Changes in v2: - Drop detailed explanation from commit message and keep it concise (Suraj Kandpal, Luca Coelho) Signed-off-by: Dibin Moolakadan Subrahmanian Reviewed-by: Luca Coelho Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260407105102.3730973-1-dibin.moolakadan.subrahmanian@intel.com --- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index 73a3101514f3..ddf1a1f1ebc3 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -46,7 +46,7 @@ * atomic variant of waiting MMIO. */ #define DMC_WAKELOCK_CTL_TIMEOUT_US 5000 -#define DMC_WAKELOCK_HOLD_TIME 50 +#define DMC_WAKELOCK_HOLD_TIME 5 /* * Possible non-negative values for the enable_dmc_wl param. From 38b4408489f2e55932e186fbcc1cc0c3379e7a86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Mar 2026 15:48:35 +0200 Subject: [PATCH 057/144] drm/i915/wm: Reject SAGV consistently when block_time_us==0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have three ways for the platform to indicate that SAGV is not supported: - pcode returns zero block time - pcode returns only a single QGV point (icl+) - pcode rejects the SAGV enable/disable command (pre-icl) We don't currently consider all those factors when computing pipe_sagv_reject, meaning we might still try to enable SAGV when we should not. I think one plausible scenario is when pcode returns a zero block time, and all the pipes are disabled. In that case intel_crtc_can_enable_sagv() will return true for all pipes, and thus we might try to enable SAGV despite pcode indicating that it's not supported. Make sure pipe_sagv_reject will consistently reject SAGV when our cached block time is zero. That will cover all the aforementioned mechanisms by which SAGV can be disabled. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260324134843.2364-2-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/skl_watermark.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index d45b3bcc6ef0..09988f46e083 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -308,9 +308,6 @@ static bool skl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) enum plane_id plane_id; int max_level = INT_MAX; - if (!intel_has_sagv(display)) - return false; - if (!crtc_state->hw.active) return true; @@ -377,6 +374,9 @@ bool intel_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); + if (!display->sagv.block_time_us) + return false; + if (!display->params.enable_sagv) return false; From 38e936e0e5f0bba69be66622f6191dcd949dd291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Mar 2026 15:48:36 +0200 Subject: [PATCH 058/144] drm/i915/wm: Don't compute separate SAGV watermarks for RKL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RKL is supposed to use the old SKL/ICL method for determining whether the watermarks tolerate SAGV or not, not the TGL+ method. Make it so. BSpec: 49325 Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260324134843.2364-3-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- .../gpu/drm/i915/display/intel_display_device.h | 1 + drivers/gpu/drm/i915/display/skl_watermark.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index 1170ac346615..074e3ba8fb77 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -200,6 +200,7 @@ struct intel_display_platforms { #define HAS_PSR_TRANS_PUSH_FRAME_CHANGE(__display) (DISPLAY_VER(__display) >= 20) #define HAS_SAGV(__display) (DISPLAY_VER(__display) >= 9 && \ !(__display)->platform.broxton && !(__display)->platform.geminilake) +#define HAS_SAGV_WM(__display) (DISPLAY_VER(__display) >= 12 && !(__display)->platform.rocketlake) #define HAS_TRANSCODER(__display, trans) ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \ BIT(trans)) != 0) #define HAS_UNCOMPRESSED_JOINER(__display) (DISPLAY_VER(__display) >= 13) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 09988f46e083..bcdca1b99fe4 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -388,7 +388,7 @@ bool intel_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) if (crtc_state->inherited) return false; - if (DISPLAY_VER(display) >= 12) + if (HAS_SAGV_WM(display)) return tgl_crtc_can_enable_sagv(crtc_state); else return skl_crtc_can_enable_sagv(crtc_state); @@ -1939,7 +1939,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, result->enable = true; result->auto_min_alloc_wm_enable = xe3_auto_min_alloc_capable(plane, level); - if (DISPLAY_VER(display) < 12 && display->sagv.block_time_us) + if (!HAS_SAGV_WM(display) && display->sagv.block_time_us) result->can_sagv = latency >= display->sagv.block_time_us; } @@ -2065,7 +2065,7 @@ static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state, skl_compute_transition_wm(display, &wm->trans_wm, &wm->wm[0], &wm_params); - if (DISPLAY_VER(display) >= 12) { + if (HAS_SAGV_WM(display)) { tgl_compute_sagv_wm(crtc_state, plane, &wm_params, wm); skl_compute_transition_wm(display, &wm->sagv.trans_wm, @@ -2324,7 +2324,7 @@ static int skl_wm_check_vblank(struct intel_crtc_state *crtc_state) } } - if (DISPLAY_VER(display) >= 12 && + if (HAS_SAGV_WM(display) && display->sagv.block_time_us && skl_prefill_vblank_too_short(&ctx, crtc_state, display->sagv.block_time_us)) { @@ -2997,8 +2997,9 @@ skl_compute_wm(struct intel_atomic_state *state) * other crtcs can't be allowed to use the more optimal * normal (ie. non-SAGV) watermarks. */ - pipe_wm->use_sagv_wm = !HAS_HW_SAGV_WM(display) && - DISPLAY_VER(display) >= 12 && + pipe_wm->use_sagv_wm = + HAS_SAGV_WM(display) && + !HAS_HW_SAGV_WM(display) && intel_crtc_can_enable_sagv(new_crtc_state); ret = skl_wm_add_affected_planes(state, crtc); @@ -3064,7 +3065,7 @@ static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, val = intel_de_read(display, CUR_WM_SAGV_TRANS(pipe)); skl_wm_level_from_reg_val(display, val, &wm->sagv.trans_wm); - } else if (DISPLAY_VER(display) >= 12) { + } else if (HAS_SAGV_WM(display)) { wm->sagv.wm0 = wm->wm[0]; wm->sagv.trans_wm = wm->trans_wm; } From 6dffcf18d014009711b6370048be1c9437ab7d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Mar 2026 15:48:37 +0200 Subject: [PATCH 059/144] drm/i915/wm: Consolidate SAGV pipe active/interlace checks to common code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no differences between the platforms when considering whether SAGV can be used when the pipe is inactive or using an interlaced mode. Consolidate the checks to common code. Note that we weren't even checking for interlaced modes on TGL+, but since we've previously soft defeatured interlaced modes on TGL+ that was more or less fine. The hardware does still have the capability though, and in case we ever decide to resurrect it having the check seems like a good idea. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260324134843.2364-4-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/skl_watermark.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index bcdca1b99fe4..e37fde9f765d 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -308,12 +308,6 @@ static bool skl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) enum plane_id plane_id; int max_level = INT_MAX; - if (!crtc_state->hw.active) - return true; - - if (crtc_state->hw.pipe_mode.flags & DRM_MODE_FLAG_INTERLACE) - return false; - for_each_plane_id_on_crtc(crtc, plane_id) { const struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id]; @@ -356,9 +350,6 @@ static bool tgl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum plane_id plane_id; - if (!crtc_state->hw.active) - return true; - for_each_plane_id_on_crtc(crtc, plane_id) { const struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id]; @@ -388,6 +379,12 @@ bool intel_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) if (crtc_state->inherited) return false; + if (!crtc_state->hw.active) + return true; + + if (crtc_state->hw.pipe_mode.flags & DRM_MODE_FLAG_INTERLACE) + return false; + if (HAS_SAGV_WM(display)) return tgl_crtc_can_enable_sagv(crtc_state); else From f002f7c7439de18117a31ca84dc87a59719c3dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Mar 2026 15:48:38 +0200 Subject: [PATCH 060/144] drm/i915/wm: Verify the correct plane DDB entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Actually verify the DDB entry for the plane we're looking at instead of always verifying the cursor DDB. Fixes: 7d4561722c3b ("drm/i915: Tweak plane ddb allocation tracking") Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260324134843.2364-5-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/skl_watermark.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index e37fde9f765d..cbc03938442d 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -4026,8 +4026,8 @@ void intel_wm_state_verify(struct intel_atomic_state *state, } /* DDB */ - hw_ddb_entry = &hw->ddb[PLANE_CURSOR]; - sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR]; + hw_ddb_entry = &hw->ddb[plane->id]; + sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[plane->id]; if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { drm_err(display->drm, From e402ba2bde93020397f8160b7d2d41463725428c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Mar 2026 15:48:39 +0200 Subject: [PATCH 061/144] drm/i915/wm: Extract skl_wm_level_verify() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce duplicated code by extracting the code to verify a single WM level to a common function. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260324134843.2364-6-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/skl_watermark.c | 94 ++++++++------------ 1 file changed, 36 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index cbc03938442d..3e323e434bfb 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3917,6 +3917,23 @@ void skl_wm_plane_disable_noatomic(struct intel_crtc *crtc, sizeof(crtc_state->wm.skl.optimal.planes[plane->id])); } +static void skl_wm_level_verify(struct intel_plane *plane, + const char *wm_name, + const struct skl_wm_level *hw_wm_level, + const struct skl_wm_level *sw_wm_level) +{ + struct intel_display *display = to_intel_display(plane); + + if (skl_wm_level_equals(hw_wm_level, sw_wm_level)) + return; + + drm_err(display->drm, + "[PLANE:%d:%s] mismatch in %s (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", + plane->base.base.id, plane->base.name, wm_name, + sw_wm_level->enable, sw_wm_level->blocks, sw_wm_level->lines, + hw_wm_level->enable, hw_wm_level->blocks, hw_wm_level->lines); +} + void intel_wm_state_verify(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -3956,73 +3973,34 @@ void intel_wm_state_verify(struct intel_atomic_state *state, hw_enabled_slices); for_each_intel_plane_on_crtc(display->drm, crtc, plane) { + const struct skl_plane_wm *hw_plane_wm = + &hw->wm.planes[plane->id]; + const struct skl_plane_wm *sw_plane_wm = + &sw_wm->planes[plane->id]; const struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry; - const struct skl_wm_level *hw_wm_level, *sw_wm_level; - /* Watermarks */ for (level = 0; level < display->wm.num_levels; level++) { - hw_wm_level = &hw->wm.planes[plane->id].wm[level]; - sw_wm_level = skl_plane_wm_level(sw_wm, plane->id, level); + char wm_name[16]; - if (skl_wm_level_equals(hw_wm_level, sw_wm_level)) - continue; + snprintf(wm_name, sizeof(wm_name), "WM%d", level); - drm_err(display->drm, - "[PLANE:%d:%s] mismatch in WM%d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", - plane->base.base.id, plane->base.name, level, - sw_wm_level->enable, - sw_wm_level->blocks, - sw_wm_level->lines, - hw_wm_level->enable, - hw_wm_level->blocks, - hw_wm_level->lines); + skl_wm_level_verify(plane, wm_name, + &hw_plane_wm->wm[level], + skl_plane_wm_level(sw_wm, plane->id, level)); } - hw_wm_level = &hw->wm.planes[plane->id].trans_wm; - sw_wm_level = skl_plane_trans_wm(sw_wm, plane->id); + skl_wm_level_verify(plane, "trans WM", + &hw_plane_wm->trans_wm, + skl_plane_trans_wm(sw_wm, plane->id)); - if (!skl_wm_level_equals(hw_wm_level, sw_wm_level)) { - drm_err(display->drm, - "[PLANE:%d:%s] mismatch in trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", - plane->base.base.id, plane->base.name, - sw_wm_level->enable, - sw_wm_level->blocks, - sw_wm_level->lines, - hw_wm_level->enable, - hw_wm_level->blocks, - hw_wm_level->lines); - } + if (HAS_HW_SAGV_WM(display)) { + skl_wm_level_verify(plane, "SAGV WM", + &hw_plane_wm->sagv.wm0, + &sw_plane_wm->sagv.wm0); - hw_wm_level = &hw->wm.planes[plane->id].sagv.wm0; - sw_wm_level = &sw_wm->planes[plane->id].sagv.wm0; - - if (HAS_HW_SAGV_WM(display) && - !skl_wm_level_equals(hw_wm_level, sw_wm_level)) { - drm_err(display->drm, - "[PLANE:%d:%s] mismatch in SAGV WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", - plane->base.base.id, plane->base.name, - sw_wm_level->enable, - sw_wm_level->blocks, - sw_wm_level->lines, - hw_wm_level->enable, - hw_wm_level->blocks, - hw_wm_level->lines); - } - - hw_wm_level = &hw->wm.planes[plane->id].sagv.trans_wm; - sw_wm_level = &sw_wm->planes[plane->id].sagv.trans_wm; - - if (HAS_HW_SAGV_WM(display) && - !skl_wm_level_equals(hw_wm_level, sw_wm_level)) { - drm_err(display->drm, - "[PLANE:%d:%s] mismatch in SAGV trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", - plane->base.base.id, plane->base.name, - sw_wm_level->enable, - sw_wm_level->blocks, - sw_wm_level->lines, - hw_wm_level->enable, - hw_wm_level->blocks, - hw_wm_level->lines); + skl_wm_level_verify(plane, "SAGV trans WM", + &hw_plane_wm->sagv.trans_wm, + &sw_plane_wm->sagv.trans_wm); } /* DDB */ From 4268d1397d948980985c61999f4ce528e530896d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Mar 2026 15:48:40 +0200 Subject: [PATCH 062/144] drm/i915/wm: Extract skl_ddb_entry_verify() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the DDB entry verification to a helper function. We'll have another caller soon. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260324134843.2364-7-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/skl_watermark.c | 32 ++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 3e323e434bfb..17faf090a154 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3934,6 +3934,23 @@ static void skl_wm_level_verify(struct intel_plane *plane, hw_wm_level->enable, hw_wm_level->blocks, hw_wm_level->lines); } +static void skl_ddb_entry_verify(struct intel_plane *plane, + const char *ddb_name, + const struct skl_ddb_entry *hw_ddb_entry, + const struct skl_ddb_entry *sw_ddb_entry) +{ + struct intel_display *display = to_intel_display(plane); + + if (skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) + return; + + drm_err(display->drm, + "[PLANE:%d:%s] mismatch in %s (expected (%u,%u), found (%u,%u))\n", + plane->base.base.id, plane->base.name, ddb_name, + sw_ddb_entry->start, sw_ddb_entry->end, + hw_ddb_entry->start, hw_ddb_entry->end); +} + void intel_wm_state_verify(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -3977,7 +3994,6 @@ void intel_wm_state_verify(struct intel_atomic_state *state, &hw->wm.planes[plane->id]; const struct skl_plane_wm *sw_plane_wm = &sw_wm->planes[plane->id]; - const struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry; for (level = 0; level < display->wm.num_levels; level++) { char wm_name[16]; @@ -4003,17 +4019,9 @@ void intel_wm_state_verify(struct intel_atomic_state *state, &sw_plane_wm->sagv.trans_wm); } - /* DDB */ - hw_ddb_entry = &hw->ddb[plane->id]; - sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[plane->id]; - - if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { - drm_err(display->drm, - "[PLANE:%d:%s] mismatch in DDB (expected (%u,%u), found (%u,%u))\n", - plane->base.base.id, plane->base.name, - sw_ddb_entry->start, sw_ddb_entry->end, - hw_ddb_entry->start, hw_ddb_entry->end); - } + skl_ddb_entry_verify(plane, "DDB", + &hw->ddb[plane->id], + &new_crtc_state->wm.skl.plane_ddb[plane->id]); } kfree(hw); From fd52fb0d6cc21a6d1e57b07ac9e0ed427ab31b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Mar 2026 15:48:41 +0200 Subject: [PATCH 063/144] drm/i915/wm: Verify 'ddb_y' as well as 'ddb' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verify the pre-icl NV12 Y color plane DDB entry. Thus far we've only verified the RGB/UV DDB entry. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260324134843.2364-8-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/skl_watermark.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 17faf090a154..1d932c37d768 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -4022,6 +4022,10 @@ void intel_wm_state_verify(struct intel_atomic_state *state, skl_ddb_entry_verify(plane, "DDB", &hw->ddb[plane->id], &new_crtc_state->wm.skl.plane_ddb[plane->id]); + + skl_ddb_entry_verify(plane, "DDB Y", + &hw->ddb_y[plane->id], + &new_crtc_state->wm.skl.plane_ddb_y[plane->id]); } kfree(hw); From 29865dd7f30caca8d2f56e0de0e8c613abf75c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Mar 2026 15:48:42 +0200 Subject: [PATCH 064/144] drm/i915/wm: Reduce copy-pasta in skl_print_plane_wm_changes() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skl_print_plane_wm_changes() is rather ugly with the copy-pasted massive printk arguments. Reduce the duplication a bit by defining a few FMT/ARG macros. Still ugly, but perhaps a bit less fragile. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260324134843.2364-9-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/skl_watermark.c | 128 ++++++------------- 1 file changed, 40 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 1d932c37d768..4bffa27ce02c 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -2613,6 +2613,26 @@ skl_print_plane_ddb_changes(struct intel_plane *plane, skl_ddb_entry_size(old), skl_ddb_entry_size(new)); } +#define PLANE_WM_EN_FMT "%cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm" +#define PLANE_WM_EN_ARGS(__wm) \ + enast((__wm)->wm[0].enable), enast((__wm)->wm[1].enable), \ + enast((__wm)->wm[2].enable), enast((__wm)->wm[3].enable), \ + enast((__wm)->wm[4].enable), enast((__wm)->wm[5].enable), \ + enast((__wm)->wm[6].enable), enast((__wm)->wm[7].enable), \ + enast((__wm)->trans_wm.enable), \ + enast((__wm)->sagv.wm0.enable), \ + enast((__wm)->sagv.trans_wm.enable) + +#define PLANE_WM_FMT "%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d" +#define PLANE_WM_ARGS(__wm, __field) \ + (__wm)->wm[0].__field, (__wm)->wm[1].__field, \ + (__wm)->wm[2].__field, (__wm)->wm[3].__field, \ + (__wm)->wm[4].__field, (__wm)->wm[5].__field, \ + (__wm)->wm[6].__field, (__wm)->wm[7].__field, \ + (__wm)->trans_wm.__field, \ + (__wm)->sagv.wm0.__field, \ + (__wm)->sagv.trans_wm.__field + static noinline_for_stack void skl_print_plane_wm_changes(struct intel_plane *plane, const struct skl_plane_wm *old_wm, @@ -2621,112 +2641,44 @@ skl_print_plane_wm_changes(struct intel_plane *plane, struct intel_display *display = to_intel_display(plane); drm_dbg_kms(display->drm, - "[PLANE:%d:%s] level %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm" - " -> %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm\n", + "[PLANE:%d:%s] level " PLANE_WM_EN_FMT " -> " PLANE_WM_EN_FMT "\n", plane->base.base.id, plane->base.name, - enast(old_wm->wm[0].enable), enast(old_wm->wm[1].enable), - enast(old_wm->wm[2].enable), enast(old_wm->wm[3].enable), - enast(old_wm->wm[4].enable), enast(old_wm->wm[5].enable), - enast(old_wm->wm[6].enable), enast(old_wm->wm[7].enable), - enast(old_wm->trans_wm.enable), - enast(old_wm->sagv.wm0.enable), - enast(old_wm->sagv.trans_wm.enable), - enast(new_wm->wm[0].enable), enast(new_wm->wm[1].enable), - enast(new_wm->wm[2].enable), enast(new_wm->wm[3].enable), - enast(new_wm->wm[4].enable), enast(new_wm->wm[5].enable), - enast(new_wm->wm[6].enable), enast(new_wm->wm[7].enable), - enast(new_wm->trans_wm.enable), - enast(new_wm->sagv.wm0.enable), - enast(new_wm->sagv.trans_wm.enable)); + PLANE_WM_EN_ARGS(old_wm), + PLANE_WM_EN_ARGS(new_wm)); drm_dbg_kms(display->drm, - "[PLANE:%d:%s] lines %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d" - " -> %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d\n", + "[PLANE:%d:%s] lines " PLANE_WM_FMT " -> " PLANE_WM_FMT "\n", plane->base.base.id, plane->base.name, - enast(old_wm->wm[0].ignore_lines), old_wm->wm[0].lines, - enast(old_wm->wm[1].ignore_lines), old_wm->wm[1].lines, - enast(old_wm->wm[2].ignore_lines), old_wm->wm[2].lines, - enast(old_wm->wm[3].ignore_lines), old_wm->wm[3].lines, - enast(old_wm->wm[4].ignore_lines), old_wm->wm[4].lines, - enast(old_wm->wm[5].ignore_lines), old_wm->wm[5].lines, - enast(old_wm->wm[6].ignore_lines), old_wm->wm[6].lines, - enast(old_wm->wm[7].ignore_lines), old_wm->wm[7].lines, - enast(old_wm->trans_wm.ignore_lines), old_wm->trans_wm.lines, - enast(old_wm->sagv.wm0.ignore_lines), old_wm->sagv.wm0.lines, - enast(old_wm->sagv.trans_wm.ignore_lines), old_wm->sagv.trans_wm.lines, - enast(new_wm->wm[0].ignore_lines), new_wm->wm[0].lines, - enast(new_wm->wm[1].ignore_lines), new_wm->wm[1].lines, - enast(new_wm->wm[2].ignore_lines), new_wm->wm[2].lines, - enast(new_wm->wm[3].ignore_lines), new_wm->wm[3].lines, - enast(new_wm->wm[4].ignore_lines), new_wm->wm[4].lines, - enast(new_wm->wm[5].ignore_lines), new_wm->wm[5].lines, - enast(new_wm->wm[6].ignore_lines), new_wm->wm[6].lines, - enast(new_wm->wm[7].ignore_lines), new_wm->wm[7].lines, - enast(new_wm->trans_wm.ignore_lines), new_wm->trans_wm.lines, - enast(new_wm->sagv.wm0.ignore_lines), new_wm->sagv.wm0.lines, - enast(new_wm->sagv.trans_wm.ignore_lines), new_wm->sagv.trans_wm.lines); + PLANE_WM_ARGS(old_wm, lines), + PLANE_WM_ARGS(new_wm, lines)); drm_dbg_kms(display->drm, - "[PLANE:%d:%s] blocks %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d" - " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n", + "[PLANE:%d:%s] blocks " PLANE_WM_FMT " -> " PLANE_WM_FMT "\n", plane->base.base.id, plane->base.name, - old_wm->wm[0].blocks, old_wm->wm[1].blocks, - old_wm->wm[2].blocks, old_wm->wm[3].blocks, - old_wm->wm[4].blocks, old_wm->wm[5].blocks, - old_wm->wm[6].blocks, old_wm->wm[7].blocks, - old_wm->trans_wm.blocks, - old_wm->sagv.wm0.blocks, - old_wm->sagv.trans_wm.blocks, - new_wm->wm[0].blocks, new_wm->wm[1].blocks, - new_wm->wm[2].blocks, new_wm->wm[3].blocks, - new_wm->wm[4].blocks, new_wm->wm[5].blocks, - new_wm->wm[6].blocks, new_wm->wm[7].blocks, - new_wm->trans_wm.blocks, - new_wm->sagv.wm0.blocks, - new_wm->sagv.trans_wm.blocks); + PLANE_WM_ARGS(old_wm, blocks), + PLANE_WM_ARGS(new_wm, blocks)); drm_dbg_kms(display->drm, - "[PLANE:%d:%s] min_ddb %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d" - " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n", + "[PLANE:%d:%s] min_ddb " PLANE_WM_FMT " -> " PLANE_WM_FMT "\n", plane->base.base.id, plane->base.name, - old_wm->wm[0].min_ddb_alloc, old_wm->wm[1].min_ddb_alloc, - old_wm->wm[2].min_ddb_alloc, old_wm->wm[3].min_ddb_alloc, - old_wm->wm[4].min_ddb_alloc, old_wm->wm[5].min_ddb_alloc, - old_wm->wm[6].min_ddb_alloc, old_wm->wm[7].min_ddb_alloc, - old_wm->trans_wm.min_ddb_alloc, - old_wm->sagv.wm0.min_ddb_alloc, - old_wm->sagv.trans_wm.min_ddb_alloc, - new_wm->wm[0].min_ddb_alloc, new_wm->wm[1].min_ddb_alloc, - new_wm->wm[2].min_ddb_alloc, new_wm->wm[3].min_ddb_alloc, - new_wm->wm[4].min_ddb_alloc, new_wm->wm[5].min_ddb_alloc, - new_wm->wm[6].min_ddb_alloc, new_wm->wm[7].min_ddb_alloc, - new_wm->trans_wm.min_ddb_alloc, - new_wm->sagv.wm0.min_ddb_alloc, - new_wm->sagv.trans_wm.min_ddb_alloc); + PLANE_WM_ARGS(old_wm, min_ddb_alloc), + PLANE_WM_ARGS(new_wm, min_ddb_alloc)); if (DISPLAY_VER(display) >= 11) return; drm_dbg_kms(display->drm, - "[PLANE:%d:%s] min_ddb_uv %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d" - " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n", + "[PLANE:%d:%s] min_ddb_uv " PLANE_WM_FMT " -> " PLANE_WM_FMT "\n", plane->base.base.id, plane->base.name, - old_wm->wm[0].min_ddb_alloc_uv, old_wm->wm[1].min_ddb_alloc_uv, - old_wm->wm[2].min_ddb_alloc_uv, old_wm->wm[3].min_ddb_alloc_uv, - old_wm->wm[4].min_ddb_alloc_uv, old_wm->wm[5].min_ddb_alloc_uv, - old_wm->wm[6].min_ddb_alloc_uv, old_wm->wm[7].min_ddb_alloc_uv, - old_wm->trans_wm.min_ddb_alloc_uv, - old_wm->sagv.wm0.min_ddb_alloc_uv, - old_wm->sagv.trans_wm.min_ddb_alloc_uv, - new_wm->wm[0].min_ddb_alloc_uv, new_wm->wm[1].min_ddb_alloc_uv, - new_wm->wm[2].min_ddb_alloc_uv, new_wm->wm[3].min_ddb_alloc_uv, - new_wm->wm[4].min_ddb_alloc_uv, new_wm->wm[5].min_ddb_alloc_uv, - new_wm->wm[6].min_ddb_alloc_uv, new_wm->wm[7].min_ddb_alloc_uv, - new_wm->trans_wm.min_ddb_alloc_uv, - new_wm->sagv.wm0.min_ddb_alloc_uv, - new_wm->sagv.trans_wm.min_ddb_alloc_uv); + PLANE_WM_ARGS(old_wm, min_ddb_alloc_uv), + PLANE_WM_ARGS(new_wm, min_ddb_alloc_uv)); } +#undef PLANE_WM_EN_FMT +#undef PLANE_WM_EN_ARGS +#undef PLANE_WM_FMT +#undef PLANE_WM_ARGS + static void skl_print_wm_changes(struct intel_atomic_state *state) { From 77ce3160eed23df28beccffe471fda568f3c93cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Mar 2026 15:48:43 +0200 Subject: [PATCH 065/144] drm/i915/wm: Allow SAGV with multiple pipes on pre-icl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There was never any documented reason for limiting SAGV to single active pipe configuration on pre-icl. Allow SAGV with multiple active pipes. At least my CFL NUC seems happy with this when using multiple displays. The machine actually has working SAGV because the memory clock can be observed changing via SA_PERF_STATUS/mchbar:0x5918. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260324134843.2364-10-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/intel_bw.c | 40 ------------------------- 1 file changed, 40 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 474438fc1ebc..9c3a9bbb49f6 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -28,9 +28,6 @@ struct intel_bw_state { */ u8 pipe_sagv_reject; - /* bitmask of active pipes */ - u8 active_pipes; - /* * From MTL onwards, to lock a QGV point, punit expects the peak BW of * the selected QGV point as the parameter in multiples of 100MB/s @@ -1263,31 +1260,6 @@ static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *chan return 0; } -static int intel_bw_modeset_checks(struct intel_atomic_state *state) -{ - const struct intel_bw_state *old_bw_state; - struct intel_bw_state *new_bw_state; - int ret; - - if (!intel_any_crtc_active_changed(state)) - return 0; - - new_bw_state = intel_atomic_get_bw_state(state); - if (IS_ERR(new_bw_state)) - return PTR_ERR(new_bw_state); - - old_bw_state = intel_atomic_get_old_bw_state(state); - - new_bw_state->active_pipes = - intel_calc_active_pipes(state, old_bw_state->active_pipes); - - ret = intel_atomic_lock_global_state(&new_bw_state->base); - if (ret) - return ret; - - return 0; -} - static int intel_bw_check_sagv_mask(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); @@ -1344,10 +1316,6 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) if (DISPLAY_VER(display) < 9) return 0; - ret = intel_bw_modeset_checks(state); - if (ret) - return ret; - ret = intel_bw_check_sagv_mask(state); if (ret) return ret; @@ -1408,7 +1376,6 @@ void intel_bw_update_hw_state(struct intel_display *display) if (DISPLAY_VER(display) < 9) return; - bw_state->active_pipes = 0; bw_state->pipe_sagv_reject = 0; for_each_intel_crtc(display->drm, crtc) { @@ -1416,9 +1383,6 @@ void intel_bw_update_hw_state(struct intel_display *display) to_intel_crtc_state(crtc->base.state); enum pipe pipe = crtc->pipe; - if (crtc_state->hw.active) - bw_state->active_pipes |= BIT(pipe); - if (DISPLAY_VER(display) >= 11) intel_bw_crtc_update(bw_state, crtc_state); @@ -1502,10 +1466,6 @@ bool intel_bw_pmdemand_needs_update(struct intel_atomic_state *state) bool intel_bw_can_enable_sagv(struct intel_display *display, const struct intel_bw_state *bw_state) { - if (DISPLAY_VER(display) < 11 && - bw_state->active_pipes && !is_power_of_2(bw_state->active_pipes)) - return false; - return bw_state->pipe_sagv_reject == 0; } From a70e5ab00b2377149c4400f4d7c871482d806afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 18:50:42 +0300 Subject: [PATCH 066/144] drm/i915/fb: Nuke intel_tile_row_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_tile_row_size() is unused. Nuke it. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407155053.32156-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 9 --------- drivers/gpu/drm/i915/display/intel_fb.h | 1 - 2 files changed, 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 5768619f840f..83392c1a1ebe 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -876,15 +876,6 @@ static void intel_tile_block_dims(const struct drm_framebuffer *fb, int color_pl *tile_height = 1; } -unsigned int intel_tile_row_size(const struct drm_framebuffer *fb, int color_plane) -{ - unsigned int tile_width, tile_height; - - intel_tile_dims(fb, color_plane, &tile_width, &tile_height); - - return fb->pitches[color_plane] * tile_height; -} - unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, int color_plane, unsigned int height) diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index 22514d5f2bb6..fb1ec2a1e905 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -62,7 +62,6 @@ int skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane); unsigned int intel_tile_size(struct intel_display *display); unsigned int intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane); unsigned int intel_tile_height(const struct drm_framebuffer *fb, int color_plane); -unsigned int intel_tile_row_size(const struct drm_framebuffer *fb, int color_plane); unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, int color_plane, unsigned int height); From e538f2a7be92ecd18e8414aad8070d04cea75372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 18:50:43 +0300 Subject: [PATCH 067/144] drm/i915/fb: Make intel_fb_needs_pot_stride_remap() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_fb_needs_pot_stride_remap() isn't needed outside intel_fb.c. Make it static. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407155053.32156-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 2 +- drivers/gpu/drm/i915/display/intel_fb.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 83392c1a1ebe..4b0afea1c456 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1265,7 +1265,7 @@ static bool intel_plane_can_remap(const struct intel_plane_state *plane_state) return true; } -bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb) +static bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb) { struct intel_display *display = to_intel_display(fb->base.dev); diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index fb1ec2a1e905..fc2c4d59bf06 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -77,7 +77,6 @@ u32 intel_plane_compute_aligned_offset(int *x, int *y, const struct intel_plane_state *plane_state, int color_plane); -bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb); bool intel_plane_uses_fence(const struct intel_plane_state *plane_state); bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb); From 8910a07b10d33fc16a7d9e91a5375d7f79c97773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 18:50:44 +0300 Subject: [PATCH 068/144] drm/i915/fb: Reject per-plane remapping with DPT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We currently create a single DPT for the entire FB, so we can't actually do the per-plane remap. Reject it for now. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407155053.32156-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 4b0afea1c456..52a619088e8e 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1252,6 +1252,10 @@ static bool intel_plane_can_remap(const struct intel_plane_state *plane_state) if (intel_fb_is_ccs_modifier(fb->modifier)) return false; + /* TODO implement remapping with DPT */ + if (intel_fb_uses_dpt(fb)) + return false; + /* Linear needs a page aligned stride for remapping */ if (fb->modifier == DRM_FORMAT_MOD_LINEAR) { unsigned int alignment = intel_tile_size(display) - 1; From 7cefb6ab03f709fe72dbcee32a0995b62a2b2bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 18:50:48 +0300 Subject: [PATCH 069/144] drm/i915/vma: Add helpers to check GTT view type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I915_GTT_VIEW_ROTATED is going away and being replaced by just I915_GTT_VIEW_REMAPPED, so we're going to need another way to determine if the view is rotated or not (since width/height will need to be swapped when operating on the destination coordinate space). Provide small helper functions to hide such implementation details from most of the code using GTT views. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407155053.32156-8-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gtt_view_types.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gtt_view_types.h b/drivers/gpu/drm/i915/i915_gtt_view_types.h index c084f67bc880..9c4f38db32ff 100644 --- a/drivers/gpu/drm/i915/i915_gtt_view_types.h +++ b/drivers/gpu/drm/i915/i915_gtt_view_types.h @@ -56,4 +56,19 @@ struct i915_gtt_view { }; }; +static inline bool i915_gtt_view_is_normal(const struct i915_gtt_view *view) +{ + return view->type == I915_GTT_VIEW_NORMAL; +} + +static inline bool i915_gtt_view_is_remapped(const struct i915_gtt_view *view) +{ + return view->type == I915_GTT_VIEW_REMAPPED; +} + +static inline bool i915_gtt_view_is_rotated(const struct i915_gtt_view *view) +{ + return view->type == I915_GTT_VIEW_ROTATED; +} + #endif /* __I915_GTT_VIEW_TYPES_H__ */ From fa3d6c5e35fe224370d653334bb299e9f47b9cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 18:50:50 +0300 Subject: [PATCH 070/144] drm/i915/fb: Use i915_gtt_view_is_*() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the naked GTT view type checks with the new i915_gtt_view_is_*() helpers. This isolates some of the code from GTT view implementation details. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407155053.32156-10-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 52a619088e8e..ceed695d3ad4 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1284,7 +1284,7 @@ bool intel_plane_uses_fence(const struct intel_plane_state *plane_state) return DISPLAY_VER(display) < 4 || (plane->fbc && !plane_state->no_fbc_reason && - plane_state->view.gtt.type == I915_GTT_VIEW_NORMAL); + i915_gtt_view_is_normal(&plane_state->view.gtt)); } static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation) @@ -1506,7 +1506,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p plane_view_height_tiles(fb, color_plane, dims, y)); } - if (view->gtt.type == I915_GTT_VIEW_ROTATED) { + if (i915_gtt_view_is_rotated(&view->gtt)) { drm_WARN_ON(display->drm, remap_info->linear); check_array_bounds(display, view->gtt.rotated.plane, color_plane); @@ -1531,7 +1531,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p /* rotate the tile dimensions to match the GTT view */ swap(tile_width, tile_height); } else { - drm_WARN_ON(display->drm, view->gtt.type != I915_GTT_VIEW_REMAPPED); + drm_WARN_ON(display->drm, !i915_gtt_view_is_remapped(&view->gtt)); check_array_bounds(display, view->gtt.remapped.plane, color_plane); @@ -1632,7 +1632,7 @@ static void intel_fb_view_init(struct intel_display *display, memset(view, 0, sizeof(*view)); view->gtt.type = view_type; - if (view_type == I915_GTT_VIEW_REMAPPED && + if (i915_gtt_view_is_remapped(&view->gtt) && (display->platform.alderlake_p || DISPLAY_VER(display) >= 14)) view->gtt.remapped.plane_alignment = SZ_2M / PAGE_SIZE; } From 672f131ab7419194a037ae7ae6ed575993ee746e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 18:50:53 +0300 Subject: [PATCH 071/144] drm/i915/fb: Use intel_fb_needs_pot_stride_remap() in intel_fb_view_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the open coded intel_fb_needs_pot_stride_remap() check inside intel_fb_view_init() with the real thing. The current check doesn't have the intel_fb_uses_dpt() in there, but that is the only situation when we use the remapped view, and thus was always implied. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407155053.32156-13-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index ceed695d3ad4..c4af368deffd 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1627,13 +1627,14 @@ calc_plane_normal_size(const struct intel_framebuffer *fb, int color_plane, static void intel_fb_view_init(struct intel_display *display, struct intel_fb_view *view, - enum i915_gtt_view_type view_type) + enum i915_gtt_view_type view_type, + const struct intel_framebuffer *fb) { memset(view, 0, sizeof(*view)); view->gtt.type = view_type; if (i915_gtt_view_is_remapped(&view->gtt) && - (display->platform.alderlake_p || DISPLAY_VER(display) >= 14)) + intel_fb_needs_pot_stride_remap(fb)) view->gtt.remapped.plane_alignment = SZ_2M / PAGE_SIZE; } @@ -1699,16 +1700,19 @@ int intel_fill_fb_info(struct intel_display *display, struct intel_framebuffer * int i, num_planes = fb->base.format->num_planes; unsigned int tile_size = intel_tile_size(display); - intel_fb_view_init(display, &fb->normal_view, I915_GTT_VIEW_NORMAL); + intel_fb_view_init(display, &fb->normal_view, + I915_GTT_VIEW_NORMAL, fb); drm_WARN_ON(display->drm, intel_fb_supports_90_270_rotation(fb) && intel_fb_needs_pot_stride_remap(fb)); if (intel_fb_supports_90_270_rotation(fb)) - intel_fb_view_init(display, &fb->rotated_view, I915_GTT_VIEW_ROTATED); + intel_fb_view_init(display, &fb->rotated_view, + I915_GTT_VIEW_ROTATED, fb); if (intel_fb_needs_pot_stride_remap(fb)) - intel_fb_view_init(display, &fb->remapped_view, I915_GTT_VIEW_REMAPPED); + intel_fb_view_init(display, &fb->remapped_view, + I915_GTT_VIEW_REMAPPED, fb); for (i = 0; i < num_planes; i++) { struct fb_plane_view_dims view_dims; @@ -1835,8 +1839,9 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state) u32 gtt_offset = 0; intel_fb_view_init(display, &plane_state->view, - drm_rotation_90_or_270(rotation) ? I915_GTT_VIEW_ROTATED : - I915_GTT_VIEW_REMAPPED); + drm_rotation_90_or_270(rotation) ? + I915_GTT_VIEW_ROTATED : I915_GTT_VIEW_REMAPPED, + intel_fb); src_x = plane_state->uapi.src.x1 >> 16; src_y = plane_state->uapi.src.y1 >> 16; From ca97f5546f191bf460b3f4b59ade3ea5e7378796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:08:40 +0300 Subject: [PATCH 072/144] drm/i915/mst: Call intel_pfit_compute_config() for sharpness filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sharpness filter property is on the CRTC (as opposed to the connector) so the expectation is that it's usable on all output types. Since the sharpness filter is now fully integrateds into the normal pfit code intel_pfit_compute_config() must be called from the encoder .compute_config() on all relevant output types. Sharpness filter is supported on LNL+ so only HDMI and DP SST/MST outputs are actually relevant. I already took care of HDMI and DP SST, but (as usual) forgot about DP MST. Add the missing intel_pfit_compute_config() call to make the sharpness filter operational on DP MST as well. Cc: Nemesa Garg Fixes: d4686f34bbeb ("drm/i915/pfit: Call intel_pfit_compute_config() unconditionally on (e)DP/HDMI") Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409100841.1907-1-ville.syrjala@linux.intel.com Reviewed-by: Nemesa Garg --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 94f2c3a7ec59..9150763ca143 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -723,6 +723,10 @@ static int mst_stream_compute_config(struct intel_encoder *encoder, pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->has_pch_encoder = false; + ret = intel_pfit_compute_config(pipe_config, conn_state); + if (ret) + return ret; + for_each_joiner_candidate(connector, adjusted_mode, num_joined_pipes) { if (num_joined_pipes > 1) pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, From 8479336af419ddcb97b77af67a45cfa3b981a2cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:08:41 +0300 Subject: [PATCH 073/144] drm/i915/mst: Remove redundant has_pch_encoder=false assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The entire crtc_state is zeroed by default, there is no need to fiddle with crtc_state->has_pch_encoder unless we are actually dealing with a port on the PCH (which we never are for DP MST). Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409100841.1907-2-ville.syrjala@linux.intel.com Reviewed-by: Nemesa Garg --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 9150763ca143..832a43ebe00f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -721,7 +721,6 @@ static int mst_stream_compute_config(struct intel_encoder *encoder, pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; - pipe_config->has_pch_encoder = false; ret = intel_pfit_compute_config(pipe_config, conn_state); if (ret) From 6cf23bb25173261773a98eef027630a8d61217e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:15:31 +0300 Subject: [PATCH 074/144] drm/i915/hdmi: Add missing intel_pfit_mode_valid() for 4:2:0 also modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_hdmi_mode_valid() is calling intel_pfit_mode_valid() only on the first attempt (4:2:0 for "4:2:0 only" modes, 4:4:4 for everything else). Add the call also for the "4:2:0 also" modes case so that we actually know the pipe scaler can actually produce the 4:2:0 output. Cc: Nicolas Frattaroli Reviewed-by: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409101539.22032-2-ville.syrjala@linux.intel.com Tested-by: Nicolas Frattaroli --- drivers/gpu/drm/i915/display/intel_hdmi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 17bd2c207453..0d88eaefbe52 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2079,6 +2079,11 @@ intel_hdmi_mode_valid(struct drm_connector *_connector, return status; sink_format = INTEL_OUTPUT_FORMAT_YCBCR420; + + status = intel_pfit_mode_valid(display, mode, sink_format, 0); + if (status != MODE_OK) + return status; + status = intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink, sink_format); if (status != MODE_OK) From 00d4981f61af14faf4d94f1e26812573e465459d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:15:32 +0300 Subject: [PATCH 075/144] drm/i915/hdmi: Restructure the sink/output format selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_hdmi_compute_output_format() is a bit of a mess. Try to restructure it into a more readable form. Right now we basically have two main code paths: - YCbCr 4:2:0 only modes - everything else including YCbCr 4:2:0 also modes Those two basically do the same two steps (try 4:2:0 and try 4:4:4) but in opposite orders. Let's write that out in a more explicit if-else form. And since I'm running out of function names I'll rename the function with that high level logic into intel_hdmi_compute_formats() and it will call (the new) intel_hdmi_compute_output_format() with an explicit sink_format as needed. Cc: Nicolas Frattaroli Reviewed-by: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409101539.22032-3-ville.syrjala@linux.intel.com Tested-by: Nicolas Frattaroli --- drivers/gpu/drm/i915/display/intel_hdmi.c | 102 ++++++++++++++-------- 1 file changed, 65 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 0d88eaefbe52..9c241d93166c 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2021,6 +2021,30 @@ intel_hdmi_mode_clock_valid(struct drm_connector *_connector, int clock, return status; } +static enum drm_mode_status +intel_hdmi_sink_format_valid(struct intel_connector *connector, + const struct drm_display_mode *mode, + bool has_hdmi_sink, + enum intel_output_format sink_format) +{ + const struct drm_display_info *info = &connector->base.display_info; + + switch (sink_format) { + case INTEL_OUTPUT_FORMAT_YCBCR420: + if (!has_hdmi_sink || + !connector->base.ycbcr_420_allowed || + !drm_mode_is_420(info, mode)) + return MODE_NO_420; + + return MODE_OK; + case INTEL_OUTPUT_FORMAT_RGB: + return MODE_OK; + default: + MISSING_CASE(sink_format); + return MODE_BAD; + } +} + static enum drm_mode_status intel_hdmi_mode_valid(struct drm_connector *_connector, const struct drm_display_mode *mode) @@ -2246,20 +2270,6 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder, return intel_conn_state->force_audio == HDMI_AUDIO_ON; } -static enum intel_output_format -intel_hdmi_sink_format(const struct intel_crtc_state *crtc_state, - struct intel_connector *connector, - bool ycbcr_420_output) -{ - if (!crtc_state->has_hdmi_sink) - return INTEL_OUTPUT_FORMAT_RGB; - - if (connector->base.ycbcr_420_allowed && ycbcr_420_output) - return INTEL_OUTPUT_FORMAT_YCBCR420; - else - return INTEL_OUTPUT_FORMAT_RGB; -} - static enum intel_output_format intel_hdmi_output_format(const struct intel_crtc_state *crtc_state) { @@ -2268,37 +2278,55 @@ intel_hdmi_output_format(const struct intel_crtc_state *crtc_state) static int intel_hdmi_compute_output_format(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state, - bool respect_downstream_limits) + struct intel_connector *connector, + bool respect_downstream_limits, + enum intel_output_format sink_format) +{ + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + + if (intel_hdmi_sink_format_valid(connector, adjusted_mode, + crtc_state->has_hdmi_sink, sink_format) != MODE_OK) + return -EINVAL; + + crtc_state->sink_format = sink_format; + crtc_state->output_format = intel_hdmi_output_format(crtc_state); + + return intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits); +} + +static int intel_hdmi_compute_formats(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state, + bool respect_downstream_limits) { struct intel_display *display = to_intel_display(encoder); struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; const struct drm_display_info *info = &connector->base.display_info; - bool ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode); int ret; - crtc_state->sink_format = - intel_hdmi_sink_format(crtc_state, connector, ycbcr_420_only); + if (drm_mode_is_420_only(info, adjusted_mode)) { + ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector, + respect_downstream_limits, + INTEL_OUTPUT_FORMAT_YCBCR420); - if (ycbcr_420_only && crtc_state->sink_format != INTEL_OUTPUT_FORMAT_YCBCR420) { - drm_dbg_kms(display->drm, - "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); - crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB; - } + if (ret) { + drm_dbg_kms(display->drm, + "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); - crtc_state->output_format = intel_hdmi_output_format(crtc_state); - ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits); - if (ret) { - if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 || - !crtc_state->has_hdmi_sink || - !connector->base.ycbcr_420_allowed || - !drm_mode_is_420_also(info, adjusted_mode)) - return ret; + ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector, + respect_downstream_limits, + INTEL_OUTPUT_FORMAT_RGB); + } + } else { + ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector, + respect_downstream_limits, + INTEL_OUTPUT_FORMAT_RGB); - crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR420; - crtc_state->output_format = intel_hdmi_output_format(crtc_state); - ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits); + if (ret && drm_mode_is_420_also(info, adjusted_mode)) + ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector, + respect_downstream_limits, + INTEL_OUTPUT_FORMAT_YCBCR420); } return ret; @@ -2375,9 +2403,9 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, * Try to respect downstream TMDS clock limits first, if * that fails assume the user might know something we don't. */ - ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state, true); + ret = intel_hdmi_compute_formats(encoder, pipe_config, conn_state, true); if (ret) - ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state, false); + ret = intel_hdmi_compute_formats(encoder, pipe_config, conn_state, false); if (ret) { drm_dbg_kms(display->drm, "unsupported HDMI clock (%d kHz), rejecting mode\n", From a68d3d7fd9766141f2e7cf21c2644d74f24ae888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:15:33 +0300 Subject: [PATCH 076/144] drm/i915/hdmi: Restructure 4:2:0 vs. 4:4:4 mode validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure the HDMI mode validation to resemble the new intel_hdmi_compute_formats(). Keeping the two in sync helps to avoid different bugs in each. The main difference between mode_valid() and intel_hdmi_compute_formats() is that we don't want the Hail Mary RGB fallback for "4:2:0 only" modes. Cc: Nicolas Frattaroli Reviewed-by: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409101539.22032-4-ville.syrjala@linux.intel.com Tested-by: Nicolas Frattaroli --- drivers/gpu/drm/i915/display/intel_hdmi.c | 60 ++++++++++++----------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 9c241d93166c..79093d8fc2e6 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2045,6 +2045,27 @@ intel_hdmi_sink_format_valid(struct intel_connector *connector, } } +static enum drm_mode_status +intel_hdmi_mode_valid_format(struct intel_connector *connector, + const struct drm_display_mode *mode, + int clock, bool has_hdmi_sink, + enum intel_output_format sink_format) +{ + struct intel_display *display = to_intel_display(connector); + enum drm_mode_status status; + + status = intel_hdmi_sink_format_valid(connector, mode, + has_hdmi_sink, sink_format); + if (status != MODE_OK) + return status; + + status = intel_pfit_mode_valid(display, mode, sink_format, 0); + if (status != MODE_OK) + return status; + + return intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink, sink_format); +} + static enum drm_mode_status intel_hdmi_mode_valid(struct drm_connector *_connector, const struct drm_display_mode *mode) @@ -2052,12 +2073,11 @@ intel_hdmi_mode_valid(struct drm_connector *_connector, struct intel_connector *connector = to_intel_connector(_connector); struct intel_display *display = to_intel_display(connector); struct intel_hdmi *hdmi = intel_attached_hdmi(connector); + const struct drm_display_info *info = &connector->base.display_info; enum drm_mode_status status; int clock = mode->clock; int max_dotclk = display->cdclk.max_dotclk_freq; bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->base.state); - bool ycbcr_420_only; - enum intel_output_format sink_format; status = intel_cpu_transcoder_mode_valid(display, mode); if (status != MODE_OK) @@ -2084,36 +2104,20 @@ intel_hdmi_mode_valid(struct drm_connector *_connector, if (clock > 600000) return MODE_CLOCK_HIGH; - ycbcr_420_only = drm_mode_is_420_only(&connector->base.display_info, mode); + if (drm_mode_is_420_only(info, mode)) { + status = intel_hdmi_mode_valid_format(connector, mode, clock, has_hdmi_sink, + INTEL_OUTPUT_FORMAT_YCBCR420); + } else { + status = intel_hdmi_mode_valid_format(connector, mode, clock, has_hdmi_sink, + INTEL_OUTPUT_FORMAT_RGB); - if (ycbcr_420_only) - sink_format = INTEL_OUTPUT_FORMAT_YCBCR420; - else - sink_format = INTEL_OUTPUT_FORMAT_RGB; - - status = intel_pfit_mode_valid(display, mode, sink_format, 0); + if (status != MODE_OK && drm_mode_is_420_also(info, mode)) + status = intel_hdmi_mode_valid_format(connector, mode, clock, has_hdmi_sink, + INTEL_OUTPUT_FORMAT_YCBCR420); + } if (status != MODE_OK) return status; - status = intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink, sink_format); - if (status != MODE_OK) { - if (ycbcr_420_only || - !connector->base.ycbcr_420_allowed || - !drm_mode_is_420_also(&connector->base.display_info, mode)) - return status; - - sink_format = INTEL_OUTPUT_FORMAT_YCBCR420; - - status = intel_pfit_mode_valid(display, mode, sink_format, 0); - if (status != MODE_OK) - return status; - - status = intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink, - sink_format); - if (status != MODE_OK) - return status; - } - return intel_mode_valid_max_plane_size(display, mode, 1); } From d1c90599185b8e14a4c5bcc338bade2f41ac4891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:15:34 +0300 Subject: [PATCH 077/144] drm/i915/dp: Restructure the sink/output format selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure intel_dp_compute_output_format() to resemble the new intel_hdmi_compute_output_formats(). Again, we basically have two main code paths: - YCbCr 4:2:0 only modes - everything else including YCbCr 4:2:0 also modes Take the exact same approach with the DP code, making the format selection much less convoluted. Cc: Nicolas Frattaroli Cc: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409101539.22032-5-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal Tested-by: Nicolas Frattaroli --- drivers/gpu/drm/i915/display/intel_dp.c | 92 ++++++++++++++++++------- 1 file changed, 66 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index b8b6d62fb275..ed5841f224ee 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1379,6 +1379,28 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, return MODE_OK; } +static enum drm_mode_status +intel_dp_sink_format_valid(struct intel_connector *connector, + const struct drm_display_mode *mode, + enum intel_output_format sink_format) +{ + const struct drm_display_info *info = &connector->base.display_info; + + switch (sink_format) { + case INTEL_OUTPUT_FORMAT_YCBCR420: + if (!connector->base.ycbcr_420_allowed || + !drm_mode_is_420(info, mode)) + return MODE_NO_420; + + return MODE_OK; + case INTEL_OUTPUT_FORMAT_RGB: + return MODE_OK; + default: + MISSING_CASE(sink_format); + return MODE_BAD; + } +} + int intel_dp_max_hdisplay_per_pipe(struct intel_display *display) { return DISPLAY_VER(display) >= 30 ? 6144 : 5120; @@ -3338,41 +3360,59 @@ static int intel_dp_compute_output_format(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, struct drm_connector_state *conn_state, - bool respect_downstream_limits) + bool respect_downstream_limits, + enum intel_output_format sink_format) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + struct intel_connector *connector = intel_dp->attached_connector; + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + + if (intel_dp_sink_format_valid(connector, adjusted_mode, + sink_format) != MODE_OK) + return -EINVAL; + + crtc_state->sink_format = sink_format; + crtc_state->output_format = intel_dp_output_format(connector, crtc_state->sink_format); + + return intel_dp_compute_link_config(encoder, crtc_state, conn_state, + respect_downstream_limits); +} + +static int +intel_dp_compute_formats(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + bool respect_downstream_limits) { struct intel_display *display = to_intel_display(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_connector *connector = intel_dp->attached_connector; const struct drm_display_info *info = &connector->base.display_info; const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - bool ycbcr_420_only; int ret; - ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode); + if (drm_mode_is_420_only(info, adjusted_mode)) { + ret = intel_dp_compute_output_format(encoder, crtc_state, conn_state, + respect_downstream_limits, + INTEL_OUTPUT_FORMAT_YCBCR420); - if (ycbcr_420_only && !connector->base.ycbcr_420_allowed) { - drm_dbg_kms(display->drm, - "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); - crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB; + if (ret) { + drm_dbg_kms(display->drm, + "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); + + ret = intel_dp_compute_output_format(encoder, crtc_state, conn_state, + respect_downstream_limits, + INTEL_OUTPUT_FORMAT_RGB); + } } else { - crtc_state->sink_format = intel_dp_sink_format(connector, adjusted_mode); - } + ret = intel_dp_compute_output_format(encoder, crtc_state, conn_state, + respect_downstream_limits, + INTEL_OUTPUT_FORMAT_RGB); - crtc_state->output_format = intel_dp_output_format(connector, crtc_state->sink_format); - - ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state, - respect_downstream_limits); - if (ret) { - if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 || - !connector->base.ycbcr_420_allowed || - !drm_mode_is_420_also(info, adjusted_mode)) - return ret; - - crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR420; - crtc_state->output_format = intel_dp_output_format(connector, - crtc_state->sink_format); - ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state, - respect_downstream_limits); + if (ret && drm_mode_is_420_also(info, adjusted_mode)) + ret = intel_dp_compute_output_format(encoder, crtc_state, conn_state, + respect_downstream_limits, + INTEL_OUTPUT_FORMAT_YCBCR420); } return ret; @@ -3547,9 +3587,9 @@ intel_dp_compute_config(struct intel_encoder *encoder, * Try to respect downstream TMDS clock limits first, if * that fails assume the user might know something we don't. */ - ret = intel_dp_compute_output_format(encoder, pipe_config, conn_state, true); + ret = intel_dp_compute_formats(encoder, pipe_config, conn_state, true); if (ret) - ret = intel_dp_compute_output_format(encoder, pipe_config, conn_state, false); + ret = intel_dp_compute_formats(encoder, pipe_config, conn_state, false); if (ret) return ret; From dfe1879a88d8ca5f1ec69928035d62fb564702fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:15:35 +0300 Subject: [PATCH 078/144] drm/i915/dp: Validate "4:2:0 also" modes twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we only validate "4:2:0 also" modes as RGB. But if that fails we could perhaps still use the mode in with 4:2:0 output. All we have to do is retry the validation with the different sink format. So far we did the double validation only so far as it affects PCON TMDS clock limits. But validating everything twice seems a bit more sane. Note that intel_dp_output_format() might still end up picking RGB for the actual output format (and letting PCON deal with the YCbCr conversion). So I suppose we could still fail the validation due to that, and forcing even the output format to 4:2:0 might solve it on a third try. But we'd need the same fallback logic in intel_dp_compute_config(). For now this seems sufficient. v2: Pass output_format to intel_dp_mode_min_link_bpp_x16() Add TODO about remaining issues Nuke intel_dp_sink_format() Cc: Nicolas Frattaroli Reviewed-by: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409101539.22032-6-ville.syrjala@linux.intel.com Reviewed-by: Ankit Nautiyal Tested-by: Nicolas Frattaroli --- drivers/gpu/drm/i915/display/intel_dp.c | 151 ++++++++++++------------ 1 file changed, 78 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ed5841f224ee..99672341f43e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1234,28 +1234,11 @@ int intel_dp_output_format_link_bpp_x16(enum intel_output_format output_format, return fxp_q4_from_int(pipe_bpp); } -static enum intel_output_format -intel_dp_sink_format(struct intel_connector *connector, - const struct drm_display_mode *mode) -{ - const struct drm_display_info *info = &connector->base.display_info; - - if (drm_mode_is_420_only(info, mode)) - return INTEL_OUTPUT_FORMAT_YCBCR420; - - return INTEL_OUTPUT_FORMAT_RGB; -} - static int intel_dp_mode_min_link_bpp_x16(struct intel_connector *connector, - const struct drm_display_mode *mode) + const struct drm_display_mode *mode, + enum intel_output_format output_format) { - enum intel_output_format output_format, sink_format; - - sink_format = intel_dp_sink_format(connector, mode); - - output_format = intel_dp_output_format(connector, sink_format); - return intel_dp_output_format_link_bpp_x16(output_format, intel_dp_min_bpp(output_format)); } @@ -1329,14 +1312,10 @@ static int frl_required_bw(int clock, int bpc, static enum drm_mode_status intel_dp_mode_valid_downstream(struct intel_connector *connector, const struct drm_display_mode *mode, - int target_clock) + int target_clock, + enum intel_output_format sink_format) { struct intel_dp *intel_dp = intel_attached_dp(connector); - const struct drm_display_info *info = &connector->base.display_info; - enum drm_mode_status status; - enum intel_output_format sink_format; - - sink_format = intel_dp_sink_format(connector, mode); /* If PCON supports FRL MODE, check FRL bandwidth constraints */ if (intel_dp->dfp.pcon_max_frl_bw) { @@ -1361,22 +1340,8 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, return MODE_CLOCK_HIGH; /* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */ - status = intel_dp_tmds_clock_valid(intel_dp, target_clock, - 8, sink_format, true); - - if (status != MODE_OK) { - if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 || - !connector->base.ycbcr_420_allowed || - !drm_mode_is_420_also(info, mode)) - return status; - sink_format = INTEL_OUTPUT_FORMAT_YCBCR420; - status = intel_dp_tmds_clock_valid(intel_dp, target_clock, - 8, sink_format, true); - if (status != MODE_OK) - return status; - } - - return MODE_OK; + return intel_dp_tmds_clock_valid(intel_dp, target_clock, + 8, sink_format, true); } static enum drm_mode_status @@ -1472,15 +1437,14 @@ bool intel_dp_dotclk_valid(struct intel_display *display, } static enum drm_mode_status -intel_dp_mode_valid(struct drm_connector *_connector, - const struct drm_display_mode *mode) +intel_dp_mode_valid_format(struct intel_connector *connector, + const struct drm_display_mode *mode, + int target_clock, + enum intel_output_format sink_format) { - struct intel_display *display = to_intel_display(_connector->dev); - struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); struct intel_dp *intel_dp = intel_attached_dp(connector); - enum intel_output_format sink_format, output_format; - const struct drm_display_mode *fixed_mode; - int target_clock = mode->clock; + enum intel_output_format output_format; int max_rate, mode_rate, max_lanes, max_link_clock; u16 dsc_max_compressed_bpp = 0; enum drm_mode_status status; @@ -1488,29 +1452,6 @@ intel_dp_mode_valid(struct drm_connector *_connector, int num_joined_pipes; int link_bpp_x16; - status = intel_cpu_transcoder_mode_valid(display, mode); - if (status != MODE_OK) - return status; - - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - return MODE_H_ILLEGAL; - - if (mode->clock < 10000) - return MODE_CLOCK_LOW; - - if (intel_dp_hdisplay_bad(display, mode->hdisplay)) - return MODE_H_ILLEGAL; - - fixed_mode = intel_panel_fixed_mode(connector, mode); - if (intel_dp_is_edp(intel_dp) && fixed_mode) { - status = intel_panel_mode_valid(connector, mode); - if (status != MODE_OK) - return status; - - target_clock = fixed_mode->clock; - } - - sink_format = intel_dp_sink_format(connector, mode); output_format = intel_dp_output_format(connector, sink_format); max_link_clock = intel_dp_max_link_rate(intel_dp); @@ -1518,7 +1459,8 @@ intel_dp_mode_valid(struct drm_connector *_connector, max_rate = intel_dp_max_link_data_rate(intel_dp, max_link_clock, max_lanes); - link_bpp_x16 = intel_dp_mode_min_link_bpp_x16(connector, mode); + link_bpp_x16 = intel_dp_mode_min_link_bpp_x16(connector, mode, + output_format); mode_rate = intel_dp_link_required(max_link_clock, max_lanes, target_clock, mode->hdisplay, link_bpp_x16, 0); @@ -1608,7 +1550,70 @@ intel_dp_mode_valid(struct drm_connector *_connector, if (status != MODE_OK) return status; - return intel_dp_mode_valid_downstream(connector, mode, target_clock); + return intel_dp_mode_valid_downstream(connector, mode, + target_clock, sink_format); +} + +static enum drm_mode_status +intel_dp_mode_valid(struct drm_connector *_connector, + const struct drm_display_mode *mode) +{ + struct intel_display *display = to_intel_display(_connector->dev); + struct intel_connector *connector = to_intel_connector(_connector); + const struct drm_display_info *info = &connector->base.display_info; + struct intel_dp *intel_dp = intel_attached_dp(connector); + const struct drm_display_mode *fixed_mode; + int target_clock = mode->clock; + enum drm_mode_status status; + + status = intel_cpu_transcoder_mode_valid(display, mode); + if (status != MODE_OK) + return status; + + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + return MODE_H_ILLEGAL; + + if (mode->clock < 10000) + return MODE_CLOCK_LOW; + + if (intel_dp_hdisplay_bad(display, mode->hdisplay)) + return MODE_H_ILLEGAL; + + fixed_mode = intel_panel_fixed_mode(connector, mode); + if (intel_dp_is_edp(intel_dp) && fixed_mode) { + status = intel_panel_mode_valid(connector, mode); + if (status != MODE_OK) + return status; + + target_clock = fixed_mode->clock; + } + + /* + * TODO: Even when using a 4:2:0 sink_format intel_dp_output_format() + * will always choose a 4:4:4 output_format if the DFP can do the + * 4:4:4->4:2:0 conversion for us. Thus a mode may still be rejected + * if we only have enough DP link bandwidth for 4:2:0 but not for + * 4:4:4. Another attempt with an explicit 4:2:0 output_format might + * be needed here. intel_dp_compute_config() would need the same + * logic, or else the actual modeset would still fail. + * + * Also a lot of the checks only depend on output_format but not + * sink_format, so we are potentially doing redundant work by + * testing the same output_format for two different sink_formats. + */ + if (drm_mode_is_420_only(info, mode)) { + status = intel_dp_mode_valid_format(connector, mode, target_clock, + INTEL_OUTPUT_FORMAT_YCBCR420); + } else { + status = intel_dp_mode_valid_format(connector, mode, target_clock, + INTEL_OUTPUT_FORMAT_RGB); + + if (status != MODE_OK && drm_mode_is_420_also(info, mode)) + status = intel_dp_mode_valid_format(connector, mode, target_clock, + INTEL_OUTPUT_FORMAT_YCBCR420); + } + + return status; } bool intel_dp_source_supports_tps3(struct intel_display *display) From 4802b7b6c0babcb14e11e49e63d89d707f773b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:15:36 +0300 Subject: [PATCH 079/144] drm/i915/dp: Require a HDMI sink for YCbCr output via PCON MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DVI sinks can't deal with YCbCr. Make sure we have a HDMI sink connected after the PCON before doing YCbCr 4:2:0 output. Cc: Nicolas Frattaroli Reviewed-by: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409101539.22032-7-ville.syrjala@linux.intel.com Tested-by: Nicolas Frattaroli --- drivers/gpu/drm/i915/display/intel_dp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 99672341f43e..e80682834530 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1349,10 +1349,15 @@ intel_dp_sink_format_valid(struct intel_connector *connector, const struct drm_display_mode *mode, enum intel_output_format sink_format) { + struct intel_dp *intel_dp = intel_attached_dp(connector); const struct drm_display_info *info = &connector->base.display_info; switch (sink_format) { case INTEL_OUTPUT_FORMAT_YCBCR420: + if (intel_dp->dfp.min_tmds_clock && + !intel_dp_has_hdmi_sink(intel_dp)) + return MODE_NO_420; + if (!connector->base.ycbcr_420_allowed || !drm_mode_is_420(info, mode)) return MODE_NO_420; From 5c7a549671897a52f4351cbb7b279162e84a26b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:15:37 +0300 Subject: [PATCH 080/144] drm/i915/dp: Validate sink format in .mode_valid() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure the sink supports our chosen sink format. I suppose it might be at least possible that some PCONs might not snoop the EDID hard enough and filter out all the modes that they should. Also if we ever want to add a similar "force DVI" knob to DP outputs that we have for native HDMI, we'd need to manually get rid of anything DVI sinks can't handle. Cc: Nicolas Frattaroli Reviewed-by: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409101539.22032-8-ville.syrjala@linux.intel.com Tested-by: Nicolas Frattaroli --- drivers/gpu/drm/i915/display/intel_dp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index e80682834530..945994fe681b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1457,6 +1457,10 @@ intel_dp_mode_valid_format(struct intel_connector *connector, int num_joined_pipes; int link_bpp_x16; + status = intel_dp_sink_format_valid(connector, mode, sink_format); + if (status != MODE_OK) + return status; + output_format = intel_dp_output_format(connector, sink_format); max_link_clock = intel_dp_max_link_rate(intel_dp); From 654f795ca9d85818991cb9f2851bd5af4c926458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:15:38 +0300 Subject: [PATCH 081/144] drm/i915/hdmi: Make the RGB fallback for "4:2:0 only" modes the last resort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we take the Hail Mary RGB fallback for "4:2:0 only" modes already during the first pass when respect_downstream_limits==true. It seems better to try everything else first (like ignoring TMDS clock limits) while still preferring 4:2:0, and only if everything else has failed fall back to RGB. Cc: Nicolas Frattaroli Reviewed-by: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409101539.22032-9-ville.syrjala@linux.intel.com Tested-by: Nicolas Frattaroli --- drivers/gpu/drm/i915/display/intel_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 79093d8fc2e6..874076a29da4 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2314,7 +2314,7 @@ static int intel_hdmi_compute_formats(struct intel_encoder *encoder, respect_downstream_limits, INTEL_OUTPUT_FORMAT_YCBCR420); - if (ret) { + if (ret && !respect_downstream_limits) { drm_dbg_kms(display->drm, "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); From 86fe1ecdc4a2196e934194f20e22c3a747568cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 9 Apr 2026 13:15:39 +0300 Subject: [PATCH 082/144] drm/i915/dp: Make the RGB fallback for "4:2:0 only" modes the last resort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we take the Hail Mary RGB fallback for "4:2:0 only" modes already during the first pass when respect_downstream_limits==true. It seems better to try everything else first (like ignoring TMDS clock limits) while still preferring 4:2:0, and only if everything else has failed fall back to RGB. Cc: Nicolas Frattaroli Reviewed-by: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260409101539.22032-10-ville.syrjala@linux.intel.com Tested-by: Nicolas Frattaroli --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 945994fe681b..35b8fb5740aa 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3410,7 +3410,7 @@ intel_dp_compute_formats(struct intel_encoder *encoder, respect_downstream_limits, INTEL_OUTPUT_FORMAT_YCBCR420); - if (ret) { + if (ret && !respect_downstream_limits) { drm_dbg_kms(display->drm, "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n"); From 289678a90b8cf81e3514c9d6c667235cd39c7acf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 13 Apr 2026 14:23:45 +0300 Subject: [PATCH 083/144] drm/i915/psr: Init variable to avoid early exit from et alignment loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uninitialized boolean variable may cause unwanted exit from et alignment loop. Fix this by initializing it as false. Fixes: 681e12440d8b ("drm/i915/psr: Repeat Selective Update area alignment") Cc: # v6.9+ Signed-off-by: Jouni Högander Reviewed-by: Nemesa Garg Reported-by: Dan Carpenter Reviewed-by: Andi Shyti Link: https://patch.msgid.link/20260413112345.88853-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index b4ca5843d098..63c19958a9e3 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -3002,7 +3002,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, return ret; do { - bool cursor_in_su_area; + bool cursor_in_su_area = false; /* * Adjust su area to cover cursor fully as necessary From 7f30fe4592f59aad5f8c9811496e5076ab11e310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Apr 2026 18:04:40 +0300 Subject: [PATCH 084/144] drm/i915: Introduce sanity to the plane_config pointer vs. array thing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "plane_config" vs. "plane_configs" naming difference is very subtle, making it far too easy to use the wrong thing by accident. Introduce a separate type for the array, making it impossible to pass in the wrong thing. And while at it name the variable "all_plane_configs" to help the poor reader make sense of things. The .config_fini() prototype also mistakenly used the plural form despite only taking in a singular plane_config. So fix that one up as well. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260410150449.9699-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- .../drm/i915/display/intel_initial_plane.c | 21 ++++++++++++------- include/drm/intel/display_parent_interface.h | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c index ee545c033da6..4f51083dbd11 100644 --- a/drivers/gpu/drm/i915/display/intel_initial_plane.c +++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c @@ -11,6 +11,10 @@ #include "intel_initial_plane.h" #include "intel_plane.h" +struct intel_initial_plane_configs { + struct intel_initial_plane_config config[I915_MAX_PIPES]; +}; + void intel_initial_plane_vblank_wait(struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(crtc); @@ -20,7 +24,7 @@ void intel_initial_plane_vblank_wait(struct intel_crtc *crtc) static const struct intel_plane_state * intel_reuse_initial_plane_obj(struct intel_crtc *this, - const struct intel_initial_plane_config plane_configs[]) + const struct intel_initial_plane_configs *all_plane_configs) { struct intel_display *display = to_intel_display(this); struct intel_crtc *crtc; @@ -39,7 +43,8 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this, if (!plane_state->ggtt_vma) continue; - if (plane_configs[this->pipe].base == plane_configs[crtc->pipe].base) + if (all_plane_configs->config[this->pipe].base == + all_plane_configs->config[crtc->pipe].base) return plane_state; } @@ -69,10 +74,10 @@ intel_alloc_initial_plane_obj(struct intel_display *display, static void intel_find_initial_plane_obj(struct intel_crtc *crtc, - struct intel_initial_plane_config plane_configs[]) + struct intel_initial_plane_configs *all_plane_configs) { struct intel_display *display = to_intel_display(crtc); - struct intel_initial_plane_config *plane_config = &plane_configs[crtc->pipe]; + struct intel_initial_plane_config *plane_config = &all_plane_configs->config[crtc->pipe]; struct intel_plane *plane = to_intel_plane(crtc->base.primary); struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state); struct drm_framebuffer *fb; @@ -93,7 +98,7 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc, } else { const struct intel_plane_state *other_plane_state; - other_plane_state = intel_reuse_initial_plane_obj(crtc, plane_configs); + other_plane_state = intel_reuse_initial_plane_obj(crtc, all_plane_configs); if (!other_plane_state) goto nofb; @@ -158,14 +163,14 @@ static void plane_config_fini(struct intel_display *display, void intel_initial_plane_config(struct intel_display *display) { - struct intel_initial_plane_config plane_configs[I915_MAX_PIPES] = {}; + struct intel_initial_plane_configs all_plane_configs = {}; struct intel_crtc *crtc; for_each_intel_crtc(display->drm, crtc) { const struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct intel_initial_plane_config *plane_config = - &plane_configs[crtc->pipe]; + &all_plane_configs.config[crtc->pipe]; if (!crtc_state->hw.active) continue; @@ -183,7 +188,7 @@ void intel_initial_plane_config(struct intel_display *display) * If the fb is shared between multiple heads, we'll * just get the first one. */ - intel_find_initial_plane_obj(crtc, plane_configs); + intel_find_initial_plane_obj(crtc, &all_plane_configs); if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config)) intel_initial_plane_vblank_wait(crtc); diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 258e6388ef77..9041897c772e 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -91,7 +91,7 @@ struct intel_display_initial_plane_interface { struct drm_gem_object *(*alloc_obj)(struct drm_device *drm, struct intel_initial_plane_config *plane_config); int (*setup)(struct drm_plane_state *plane_state, struct intel_initial_plane_config *plane_config, struct drm_framebuffer *fb, struct i915_vma *vma); - void (*config_fini)(struct intel_initial_plane_config *plane_configs); + void (*config_fini)(struct intel_initial_plane_config *plane_config); }; struct intel_display_irq_interface { From 1f258c23503dbf546114e482e8253d3b39afc9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Apr 2026 18:04:41 +0300 Subject: [PATCH 085/144] drm/i915: Remove 'mem' and 'phy_base' from struct intel_initial_plane_config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'mem' and 'phy_base' members of struct intel_initial_plane_config only exist to be passed from initial_plane_phys() to its sole caller. Just return them via function arguments. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260410150449.9699-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_types.h | 2 -- drivers/gpu/drm/i915/i915_initial_plane.c | 13 ++++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index ca2581fb7bbd..eaa37b8d9584 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -756,8 +756,6 @@ struct intel_plane_state { struct intel_initial_plane_config { struct intel_framebuffer *fb; - struct intel_memory_region *mem; - resource_size_t phys_base; struct i915_vma *vma; int size; u32 base; diff --git a/drivers/gpu/drm/i915/i915_initial_plane.c b/drivers/gpu/drm/i915/i915_initial_plane.c index c1a12bf6b66c..060aa0388c39 100644 --- a/drivers/gpu/drm/i915/i915_initial_plane.c +++ b/drivers/gpu/drm/i915/i915_initial_plane.c @@ -34,7 +34,9 @@ initial_plane_memory_type(struct drm_i915_private *i915) static bool initial_plane_phys(struct drm_i915_private *i915, - struct intel_initial_plane_config *plane_config) + struct intel_initial_plane_config *plane_config, + resource_size_t *out_phys_base, + struct intel_memory_region **out_mem) { struct i915_ggtt *ggtt = to_gt(i915)->ggtt; struct intel_memory_region *mem; @@ -77,8 +79,8 @@ initial_plane_phys(struct drm_i915_private *i915, drm_dbg(&i915->drm, "Using dma_addr=%pa, based on initial plane programming\n", &dma_addr); - plane_config->phys_base = dma_addr - mem->region.start; - plane_config->mem = mem; + *out_phys_base = dma_addr - mem->region.start; + *out_mem = mem; return true; } @@ -99,12 +101,9 @@ initial_plane_vma(struct drm_i915_private *i915, if (plane_config->size == 0) return NULL; - if (!initial_plane_phys(i915, plane_config)) + if (!initial_plane_phys(i915, plane_config, &phys_base, &mem)) return NULL; - phys_base = plane_config->phys_base; - mem = plane_config->mem; - base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT); size = round_up(plane_config->base + plane_config->size, mem->min_page_size); From 85b4011bef446eb46e028a38bf4ed2dff976a74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Apr 2026 18:04:42 +0300 Subject: [PATCH 086/144] drm/i915: Don't pass the whole plane_config to initial_plane_phys() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit initial_plane_phys() only needs the 'base' (== ggtt virtual address) from the plane_config. Stop passing the whole plane_config and just pass the 'base'. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260410150449.9699-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/i915_initial_plane.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_initial_plane.c b/drivers/gpu/drm/i915/i915_initial_plane.c index 060aa0388c39..6df57db9b62a 100644 --- a/drivers/gpu/drm/i915/i915_initial_plane.c +++ b/drivers/gpu/drm/i915/i915_initial_plane.c @@ -34,8 +34,7 @@ initial_plane_memory_type(struct drm_i915_private *i915) static bool initial_plane_phys(struct drm_i915_private *i915, - struct intel_initial_plane_config *plane_config, - resource_size_t *out_phys_base, + u32 base, resource_size_t *out_phys_base, struct intel_memory_region **out_mem) { struct i915_ggtt *ggtt = to_gt(i915)->ggtt; @@ -43,7 +42,6 @@ initial_plane_phys(struct drm_i915_private *i915, enum intel_memory_type mem_type; bool is_present, is_local; dma_addr_t dma_addr; - u32 base; mem_type = initial_plane_memory_type(i915); mem = intel_memory_region_by_type(i915, mem_type); @@ -54,7 +52,7 @@ initial_plane_phys(struct drm_i915_private *i915, return false; } - base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT); + base = round_down(base, I915_GTT_MIN_ALIGNMENT); dma_addr = intel_ggtt_read_entry(&ggtt->vm, base, &is_present, &is_local); @@ -101,7 +99,7 @@ initial_plane_vma(struct drm_i915_private *i915, if (plane_config->size == 0) return NULL; - if (!initial_plane_phys(i915, plane_config, &phys_base, &mem)) + if (!initial_plane_phys(i915, plane_config->base, &phys_base, &mem)) return NULL; base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT); From 24104d589dad3b2fc342304db474be8e958f6852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Apr 2026 18:04:43 +0300 Subject: [PATCH 087/144] drm/i915: Make plane_config->fb a struct drm_framebuffer* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no need to use the intel specific struct intel_framebuffer* type in the initial plane_config structure. Just make it a struct drm_framebuffer*. I think the fewer special types we expose in the interface (even if just pointers) the better. At least then there is no need to change the interface definition if we ever change the internal types. And I hope that the existing examples will generally encourage people to not expose more special types unless absolutely necessary. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260410150449.9699-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_plane.c | 2 +- drivers/gpu/drm/i915/display/intel_display_types.h | 2 +- drivers/gpu/drm/i915/display/intel_initial_plane.c | 10 +++++----- drivers/gpu/drm/i915/display/skl_universal_plane.c | 2 +- drivers/gpu/drm/i915/i915_initial_plane.c | 6 +++--- drivers/gpu/drm/xe/display/xe_initial_plane.c | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 9c16753a1f3b..70734d32a409 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -1240,7 +1240,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, fb->width, fb->height, fb->format->cpp[0] * 8, base, fb->pitches[0], plane_config->size); - plane_config->fb = intel_fb; + plane_config->fb = &intel_fb->base; } bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index eaa37b8d9584..82c7e03427ff 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -755,7 +755,7 @@ struct intel_plane_state { }; struct intel_initial_plane_config { - struct intel_framebuffer *fb; + struct drm_framebuffer *fb; struct i915_vma *vma; int size; u32 base; diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c index 4f51083dbd11..911d67dceba9 100644 --- a/drivers/gpu/drm/i915/display/intel_initial_plane.c +++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c @@ -55,9 +55,9 @@ static struct drm_gem_object * intel_alloc_initial_plane_obj(struct intel_display *display, struct intel_initial_plane_config *plane_config) { - struct intel_framebuffer *fb = plane_config->fb; + struct drm_framebuffer *fb = plane_config->fb; - switch (fb->base.modifier) { + switch (fb->modifier) { case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: @@ -65,7 +65,7 @@ intel_alloc_initial_plane_obj(struct intel_display *display, break; default: drm_dbg_kms(display->drm, "Unsupported modifier for initial FB: 0x%llx\n", - fb->base.modifier); + fb->modifier); return NULL; } @@ -93,7 +93,7 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc, return; if (intel_alloc_initial_plane_obj(display, plane_config)) { - fb = &plane_config->fb->base; + fb = plane_config->fb; vma = plane_config->vma; } else { const struct intel_plane_state *other_plane_state; @@ -149,7 +149,7 @@ static void plane_config_fini(struct intel_display *display, struct intel_initial_plane_config *plane_config) { if (plane_config->fb) { - struct drm_framebuffer *fb = &plane_config->fb->base; + struct drm_framebuffer *fb = plane_config->fb; /* We may only have the stub and not a full framebuffer */ if (drm_framebuffer_read_refcount(fb)) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 7a9d494334b5..00c863e378a1 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -3206,7 +3206,7 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, fb->width, fb->height, fb->format->cpp[0] * 8, base, fb->pitches[0], plane_config->size); - plane_config->fb = intel_fb; + plane_config->fb = &intel_fb->base; return; error: diff --git a/drivers/gpu/drm/i915/i915_initial_plane.c b/drivers/gpu/drm/i915/i915_initial_plane.c index 6df57db9b62a..5cb1adde67b6 100644 --- a/drivers/gpu/drm/i915/i915_initial_plane.c +++ b/drivers/gpu/drm/i915/i915_initial_plane.c @@ -137,7 +137,7 @@ initial_plane_vma(struct drm_i915_private *i915, i915_gem_object_set_cache_coherency(obj, HAS_WT(i915) ? I915_CACHE_WT : I915_CACHE_NONE); - tiling = intel_fb_modifier_to_tiling(plane_config->fb->base.modifier); + tiling = intel_fb_modifier_to_tiling(plane_config->fb->modifier); switch (tiling) { case I915_TILING_NONE: @@ -145,7 +145,7 @@ initial_plane_vma(struct drm_i915_private *i915, case I915_TILING_X: case I915_TILING_Y: obj->tiling_and_stride = - plane_config->fb->base.pitches[0] | + plane_config->fb->pitches[0] | tiling; break; default: @@ -223,7 +223,7 @@ i915_alloc_initial_plane_obj(struct drm_device *drm, { struct drm_i915_private *i915 = to_i915(drm); struct drm_mode_fb_cmd2 mode_cmd = {}; - struct drm_framebuffer *fb = &plane_config->fb->base; + struct drm_framebuffer *fb = plane_config->fb; struct i915_vma *vma; vma = initial_plane_vma(i915, plane_config); diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.c b/drivers/gpu/drm/xe/display/xe_initial_plane.c index 1c7a4e8c390c..8f2d0244c03f 100644 --- a/drivers/gpu/drm/xe/display/xe_initial_plane.c +++ b/drivers/gpu/drm/xe/display/xe_initial_plane.c @@ -115,7 +115,7 @@ xe_alloc_initial_plane_obj(struct drm_device *drm, { struct xe_device *xe = to_xe_device(drm); struct drm_mode_fb_cmd2 mode_cmd = { 0 }; - struct drm_framebuffer *fb = &plane_config->fb->base; + struct drm_framebuffer *fb = plane_config->fb; struct xe_bo *bo; mode_cmd.pixel_format = fb->format->format; From 36f1cddea76d14d656a23eccf371247906ec8e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Apr 2026 18:04:44 +0300 Subject: [PATCH 088/144] drm/i915: Move initial plane vblank wait into display code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The initial plane vblank wait operates on display registers, so it really belongs in the display code proper. Move it there. We can use intel_parent_irq_enabled() to determine if we can rely on interrupts or not. On average we should end up waiting half a frame here, so the polling interval can be fairly long. 1 ms (which actually makes poll_timeout_us() use ~250-1000 usec) seems good enough to me. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260410150449.9699-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- .../drm/i915/display/intel_initial_plane.c | 22 ++++++++++++++++++- drivers/gpu/drm/i915/i915_initial_plane.c | 6 ----- drivers/gpu/drm/xe/display/xe_initial_plane.c | 19 ---------------- include/drm/intel/display_parent_interface.h | 2 -- 4 files changed, 21 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c index 911d67dceba9..74e10d34c63c 100644 --- a/drivers/gpu/drm/i915/display/intel_initial_plane.c +++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c @@ -1,14 +1,20 @@ // SPDX-License-Identifier: MIT /* Copyright © 2025 Intel Corporation */ +#include + #include #include +#include "intel_crtc.h" +#include "intel_de.h" #include "intel_display_core.h" +#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_fb.h" #include "intel_frontbuffer.h" #include "intel_initial_plane.h" +#include "intel_parent.h" #include "intel_plane.h" struct intel_initial_plane_configs { @@ -18,8 +24,22 @@ struct intel_initial_plane_configs { void intel_initial_plane_vblank_wait(struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(crtc); + u32 start_ts, end_ts; + int ret; - display->parent->initial_plane->vblank_wait(&crtc->base); + /* xe doesn't have interrupts enabled this early */ + if (intel_parent_irq_enabled(display)) { + intel_crtc_wait_for_next_vblank(crtc); + return; + } + + start_ts = intel_de_read(display, PIPE_FRMTMSTMP(crtc->pipe)); + + ret = poll_timeout_us(end_ts = intel_de_read(display, PIPE_FRMTMSTMP(crtc->pipe)), + end_ts != start_ts, 1000, 40 * 1000, false); + if (ret) + drm_warn(display->drm, "[CRTC:%d:%s] early vblank wait timed out\n", + crtc->base.base.id, crtc->base.name); } static const struct intel_plane_state * diff --git a/drivers/gpu/drm/i915/i915_initial_plane.c b/drivers/gpu/drm/i915/i915_initial_plane.c index 5cb1adde67b6..7775e657271b 100644 --- a/drivers/gpu/drm/i915/i915_initial_plane.c +++ b/drivers/gpu/drm/i915/i915_initial_plane.c @@ -16,11 +16,6 @@ #include "i915_drv.h" #include "i915_initial_plane.h" -static void i915_initial_plane_vblank_wait(struct drm_crtc *crtc) -{ - intel_crtc_wait_for_next_vblank(to_intel_crtc(crtc)); -} - static enum intel_memory_type initial_plane_memory_type(struct drm_i915_private *i915) { @@ -282,7 +277,6 @@ static void i915_plane_config_fini(struct intel_initial_plane_config *plane_conf } const struct intel_display_initial_plane_interface i915_display_initial_plane_interface = { - .vblank_wait = i915_initial_plane_vblank_wait, .alloc_obj = i915_alloc_initial_plane_obj, .setup = i915_initial_plane_setup, .config_fini = i915_plane_config_fini, diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.c b/drivers/gpu/drm/xe/display/xe_initial_plane.c index 8f2d0244c03f..37bd15d12169 100644 --- a/drivers/gpu/drm/xe/display/xe_initial_plane.c +++ b/drivers/gpu/drm/xe/display/xe_initial_plane.c @@ -7,8 +7,6 @@ #include "regs/xe_gtt_defs.h" -#include "intel_crtc.h" -#include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_fb.h" #include "intel_fb_pin.h" @@ -19,22 +17,6 @@ #include "xe_mmio.h" #include "xe_vram_types.h" -/* Early xe has no irq */ -static void xe_initial_plane_vblank_wait(struct drm_crtc *_crtc) -{ - struct intel_crtc *crtc = to_intel_crtc(_crtc); - struct xe_device *xe = to_xe_device(crtc->base.dev); - struct xe_reg pipe_frmtmstmp = XE_REG(i915_mmio_reg_offset(PIPE_FRMTMSTMP(crtc->pipe))); - u32 timestamp; - int ret; - - timestamp = xe_mmio_read32(xe_root_tile_mmio(xe), pipe_frmtmstmp); - - ret = xe_mmio_wait32_not(xe_root_tile_mmio(xe), pipe_frmtmstmp, ~0U, timestamp, 40000U, ×tamp, false); - if (ret < 0) - drm_warn(&xe->drm, "waiting for early vblank failed with %i\n", ret); -} - static struct xe_bo * initial_plane_bo(struct xe_device *xe, struct intel_initial_plane_config *plane_config) @@ -172,7 +154,6 @@ static void xe_plane_config_fini(struct intel_initial_plane_config *plane_config } const struct intel_display_initial_plane_interface xe_display_initial_plane_interface = { - .vblank_wait = xe_initial_plane_vblank_wait, .alloc_obj = xe_alloc_initial_plane_obj, .setup = xe_initial_plane_setup, .config_fini = xe_plane_config_fini, diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 9041897c772e..b513e3f9924d 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -8,7 +8,6 @@ enum vlv_iosf_sb_unit; struct dma_fence; -struct drm_crtc; struct drm_device; struct drm_file; struct drm_framebuffer; @@ -87,7 +86,6 @@ struct intel_display_hdcp_interface { }; struct intel_display_initial_plane_interface { - void (*vblank_wait)(struct drm_crtc *crtc); struct drm_gem_object *(*alloc_obj)(struct drm_device *drm, struct intel_initial_plane_config *plane_config); int (*setup)(struct drm_plane_state *plane_state, struct intel_initial_plane_config *plane_config, struct drm_framebuffer *fb, struct i915_vma *vma); From 2d2c566bd17e24a294dcdf872eb4f2d0131d2ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Apr 2026 18:04:45 +0300 Subject: [PATCH 089/144] drm/i915: Use a 1 second timeout for the polling vblank wait MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 40 msec seems like a very random number for a vblank wait timeout. Considering ~24Hz display modes are definitely a thing this seems way too low. Just bump it to a full second to match what we've been using for normal vblank waits. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260410150449.9699-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_initial_plane.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c index 74e10d34c63c..4f1591b55752 100644 --- a/drivers/gpu/drm/i915/display/intel_initial_plane.c +++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c @@ -36,7 +36,7 @@ void intel_initial_plane_vblank_wait(struct intel_crtc *crtc) start_ts = intel_de_read(display, PIPE_FRMTMSTMP(crtc->pipe)); ret = poll_timeout_us(end_ts = intel_de_read(display, PIPE_FRMTMSTMP(crtc->pipe)), - end_ts != start_ts, 1000, 40 * 1000, false); + end_ts != start_ts, 1000, 1000 * 1000, false); if (ret) drm_warn(display->drm, "[CRTC:%d:%s] early vblank wait timed out\n", crtc->base.base.id, crtc->base.name); From c2a9f16bc990593f11c53ff547ccdf00d066d348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Apr 2026 18:04:46 +0300 Subject: [PATCH 090/144] drm/i915: Reject tile4 BIOS FB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no such thing as tile4 fenced region, so there is no way to have a linear view of the tile4 framebuffer for the CPU. Thus we should never encounter a tile4 BIOS FB, but if we somehow do, then reject it. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260410150449.9699-8-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_initial_plane.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c index 4f1591b55752..5a5adf738d4a 100644 --- a/drivers/gpu/drm/i915/display/intel_initial_plane.c +++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c @@ -81,7 +81,6 @@ intel_alloc_initial_plane_obj(struct intel_display *display, case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: - case I915_FORMAT_MOD_4_TILED: break; default: drm_dbg_kms(display->drm, "Unsupported modifier for initial FB: 0x%llx\n", From a05eda6f64f88c215d75e68e904d2d9cef3b87db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Apr 2026 18:04:47 +0300 Subject: [PATCH 091/144] drm/i915: Reject X/Y tiled BIOS FB if we don't have fenced regions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CPU always needs linear view into the BIOS FB, and for X/Y tiled buffers that is achieved by the use of a fenced region. If the underlying driver doesn't support fenced regions then we can't keep the X/Y tiled BIOS FB. i915 has fenced regions, xe does not. Probably not a big deal since I don't think we've seen tiled BIOS FBs outside of some MacBooks. See eg. commit d9a515867bdb ("drm/i915/gen9+: Fix initial readout for Y tiled framebuffers"). Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260410150449.9699-9-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_initial_plane.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c index 5a5adf738d4a..55b6cdded126 100644 --- a/drivers/gpu/drm/i915/display/intel_initial_plane.c +++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c @@ -79,9 +79,13 @@ intel_alloc_initial_plane_obj(struct intel_display *display, switch (fb->modifier) { case DRM_FORMAT_MOD_LINEAR: + break; case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: - break; + /* fenced region needed for linear CPU access to tiled FB */ + if (intel_parent_has_fenced_regions(display)) + break; + fallthrough; default: drm_dbg_kms(display->drm, "Unsupported modifier for initial FB: 0x%llx\n", fb->modifier); From 9af46eb338ca408cf72803483ca06b91e0f67746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Apr 2026 18:04:48 +0300 Subject: [PATCH 092/144] drm/i915: Completely reject DPT BIOS FBs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our BIOS FB handling can't deal with DPT, and instead everything just assumes a direct GGTT mapping. Reject any BIOS FB using DPT. Most likely this should never happen anyway. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260410150449.9699-10-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_initial_plane.c | 9 +++++++++ drivers/gpu/drm/i915/display/skl_universal_plane.c | 6 ------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c index 55b6cdded126..e3d1b2d1669c 100644 --- a/drivers/gpu/drm/i915/display/intel_initial_plane.c +++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c @@ -92,6 +92,15 @@ intel_alloc_initial_plane_obj(struct intel_display *display, return NULL; } + /* + * Would need to preserve the DPT, its GGTT + * mapping, and the actual FB memory. + */ + if (intel_fb_modifier_uses_dpt(display, fb->modifier)) { + drm_dbg_kms(display->drm, "DPT not supported for initial FB\n"); + return NULL; + } + return display->parent->initial_plane->alloc_obj(display->drm, plane_config); } diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 00c863e378a1..5aef8123d8b8 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -3148,12 +3148,6 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, fb->format = drm_get_format_info(display->drm, fourcc, fb->modifier); - if (!display->params.enable_dpt && - intel_fb_modifier_uses_dpt(display, fb->modifier)) { - drm_dbg_kms(display->drm, "DPT disabled, skipping initial FB\n"); - goto error; - } - /* * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr * while i915 HW rotation is clockwise, that's why this swapping. From 53978256a876138ff57336f5cdedf504e61b87b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 10 Apr 2026 18:04:49 +0300 Subject: [PATCH 093/144] drm/i915: Reject BIOS FB rotation in common code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reject 90/270 degree rotated BIOS framebuffers in common code. Currently skl_get_initial_plane_config() already rejects these, but we may want to implement the missing parts there so that skl_get_initial_plane_config() could be reused for general plane state verification purposes. 90/270 degree rotated framebuffers require two completely separate GGTT mappings (0 degree for the CPU, 270 degree for the display engine), and the rest of the BIOS FB takeover code is not prepared for that. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260410150449.9699-11-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_initial_plane.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c index e3d1b2d1669c..0e5cd45f01cc 100644 --- a/drivers/gpu/drm/i915/display/intel_initial_plane.c +++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c @@ -3,6 +3,7 @@ #include +#include #include #include @@ -101,6 +102,15 @@ intel_alloc_initial_plane_obj(struct intel_display *display, return NULL; } + /* + * Would need to preserve the 270 degree rotated + * GGTT mapping used by the display hardware. + */ + if (drm_rotation_90_or_270(plane_config->rotation)) { + drm_dbg_kms(display->drm, "90/270 degree rotation not supported for initial FB\n"); + return NULL; + } + return display->parent->initial_plane->alloc_obj(display->drm, plane_config); } From eb3dd9640731ae3ace871190f80474a8e7bae121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:09:41 +0300 Subject: [PATCH 094/144] drm/i915: Track fence region ID in plane state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get rid of the needlessly complicated PLANE_HAS_FENCE + intel_parent_vma_fence_id() dance by simply tracking the fence_id directly in the plane state. v2: Don't request the redundant fence for fbdev (Jani) Assign *out_fence_id with '=' instead of '|=' (Sashiko,Jani) Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407170942.16515-1-ville.syrjala@linux.intel.com --- .../drm/i915/display/intel_display_types.h | 5 +-- drivers/gpu/drm/i915/display/intel_fb_pin.h | 5 ++- drivers/gpu/drm/i915/display/intel_fbc.c | 11 ++----- drivers/gpu/drm/i915/display/intel_fbdev.c | 9 ++--- drivers/gpu/drm/i915/display/intel_plane.c | 3 +- drivers/gpu/drm/i915/i915_fb_pin.c | 33 ++++++++++--------- drivers/gpu/drm/i915/i915_initial_plane.c | 2 +- drivers/gpu/drm/xe/display/xe_fb_pin.c | 8 ++--- drivers/gpu/drm/xe/display/xe_initial_plane.c | 2 +- 9 files changed, 37 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 82c7e03427ff..e644f78d9fe6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -683,14 +683,15 @@ struct intel_plane_state { struct i915_vma *ggtt_vma; struct i915_vma *dpt_vma; - unsigned long flags; -#define PLANE_HAS_FENCE BIT(0) struct intel_fb_view view; /* for legacy cursor fb unpin */ struct drm_vblank_work unpin_work; + /* fenced region ID (-1 if none) */ + s8 fence_id; + /* Plane pxp decryption state */ bool decrypt; diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.h b/drivers/gpu/drm/i915/display/intel_fb_pin.h index 81ab79da1af7..2eca42b74c4a 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.h +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.h @@ -20,10 +20,9 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, unsigned int alignment, unsigned int phys_alignment, unsigned int vtd_guard, - bool uses_fence, - unsigned long *out_flags); + int *out_fence_id); -void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags); +void intel_fb_unpin_vma(struct i915_vma *vma, int fence_id); int intel_plane_pin_fb(struct intel_plane_state *new_plane_state, const struct intel_plane_state *old_plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 55cb3ceb3523..a7d02dd6ca96 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1458,13 +1458,10 @@ static void intel_fbc_update_state(struct intel_atomic_state *state, fbc_state->fence_y_offset = intel_plane_fence_y_offset(plane_state); - drm_WARN_ON(display->drm, plane_state->flags & PLANE_HAS_FENCE && + drm_WARN_ON(display->drm, plane_state->fence_id >= 0 && !intel_fbc_has_fences(display)); - if (plane_state->flags & PLANE_HAS_FENCE) - fbc_state->fence_id = intel_parent_vma_fence_id(display, plane_state->ggtt_vma); - else - fbc_state->fence_id = -1; + fbc_state->fence_id = plane_state->fence_id; fbc_state->cfb_stride = intel_fbc_cfb_stride(plane_state); fbc_state->cfb_size = intel_fbc_cfb_size(plane_state); @@ -1487,9 +1484,7 @@ static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state) * so have no fence associated with it) due to aperture constraints * at the time of pinning. */ - return DISPLAY_VER(display) >= 9 || - (plane_state->flags & PLANE_HAS_FENCE && - intel_parent_vma_fence_id(display, plane_state->ggtt_vma) != -1); + return DISPLAY_VER(display) >= 9 || plane_state->fence_id >= 0; } static bool intel_fbc_is_cfb_ok(const struct intel_plane_state *plane_state) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 14ac01c1b3eb..1e22b3fd79ba 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -59,7 +59,6 @@ struct intel_fbdev { struct intel_framebuffer *fb; struct i915_vma *vma; - unsigned long vma_flags; }; static struct intel_fbdev *to_intel_fbdev(struct drm_fb_helper *fb_helper) @@ -140,7 +139,7 @@ static void intel_fbdev_fb_destroy(struct fb_info *info) * the info->screen_base mmaping. Leaking the VMA is simpler than * trying to rectify all the possible error paths leading here. */ - intel_fb_unpin_vma(ifbdev->vma, ifbdev->vma_flags); + intel_fb_unpin_vma(ifbdev->vma, -1); drm_framebuffer_remove(fb_helper->fb); drm_client_release(&fb_helper->client); @@ -269,7 +268,6 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, struct fb_info *info = helper->info; struct ref_tracker *wakeref; struct i915_vma *vma; - unsigned long flags = 0; bool prealloc = false; struct drm_gem_object *obj; int ret; @@ -314,7 +312,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, fb->min_alignment, 0, intel_fb_view_vtd_guard(&fb->base, &fb->normal_view, DRM_MODE_ROTATE_0), - false, &flags); + NULL); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_unlock; @@ -345,14 +343,13 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, drm_dbg_kms(display->drm, "allocated %dx%d fb\n", fb->base.width, fb->base.height); ifbdev->fb = fb; ifbdev->vma = vma; - ifbdev->vma_flags = flags; intel_display_rpm_put(display, wakeref); return 0; out_unpin: - intel_fb_unpin_vma(vma, flags); + intel_fb_unpin_vma(vma, -1); out_unlock: intel_display_rpm_put(display, wakeref); diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c index 5390ceb21ca4..f15dd9e91243 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.c +++ b/drivers/gpu/drm/i915/display/intel_plane.c @@ -70,6 +70,7 @@ static void intel_plane_state_reset(struct intel_plane_state *plane_state, __drm_atomic_helper_plane_state_reset(&plane_state->uapi, &plane->base); plane_state->scaler_id = -1; + plane_state->fence_id = -1; } struct intel_plane *intel_plane_alloc(void) @@ -137,7 +138,7 @@ intel_plane_duplicate_state(struct drm_plane *plane) intel_state->ggtt_vma = NULL; intel_state->dpt_vma = NULL; - intel_state->flags = 0; + intel_state->fence_id = -1; intel_state->damage = DRM_RECT_INIT(0, 0, 0, 0); /* add reference to fb */ diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 1018f4b7bc2c..efd5cb726cf8 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -26,7 +26,6 @@ static struct i915_vma * intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, const struct i915_gtt_view *view, unsigned int alignment, - unsigned long *out_flags, struct intel_dpt *dpt) { struct intel_display *display = to_intel_display(fb->dev); @@ -114,8 +113,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, unsigned int alignment, unsigned int phys_alignment, unsigned int vtd_guard, - bool uses_fence, - unsigned long *out_flags) + int *out_fence_id) { struct intel_display *display = to_intel_display(fb->dev); struct drm_i915_private *i915 = to_i915(fb->dev); @@ -175,7 +173,10 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, goto err_unpin; } - if (uses_fence && i915_vma_is_map_and_fenceable(vma)) { + if (out_fence_id) + *out_fence_id = -1; + + if (out_fence_id && i915_vma_is_map_and_fenceable(vma)) { /* * Install a fence for tiled scan-out. Pre-i965 always needs a * fence, whereas 965+ only requires a fence if using @@ -201,7 +202,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, ret = 0; if (vma->fence) - *out_flags |= PLANE_HAS_FENCE; + *out_fence_id = vma->fence->id; } i915_vma_get(vma); @@ -223,9 +224,9 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, return vma; } -void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags) +void intel_fb_unpin_vma(struct i915_vma *vma, int fence_id) { - if (flags & PLANE_HAS_FENCE) + if (fence_id >= 0) i915_vma_unpin_fence(vma); i915_vma_unpin(vma); i915_vma_put(vma); @@ -269,17 +270,18 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, struct i915_vma *vma; if (!intel_fb_uses_dpt(&fb->base)) { + int fence_id = -1; + vma = intel_fb_pin_to_ggtt(&fb->base, &plane_state->view.gtt, intel_plane_fb_min_alignment(plane_state), intel_plane_fb_min_phys_alignment(plane_state), intel_plane_fb_vtd_guard(plane_state), - intel_plane_uses_fence(plane_state), - &plane_state->flags); + intel_plane_uses_fence(plane_state) ? &fence_id : NULL); if (IS_ERR(vma)) return PTR_ERR(vma); plane_state->ggtt_vma = vma; - + plane_state->fence_id = fence_id; } else { unsigned int alignment = intel_plane_fb_min_alignment(plane_state); @@ -290,8 +292,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, plane_state->ggtt_vma = vma; vma = intel_fb_pin_to_dpt(&fb->base, &plane_state->view.gtt, - alignment, &plane_state->flags, - fb->dpt); + alignment, fb->dpt); if (IS_ERR(vma)) { i915_dpt_unpin_from_ggtt(fb->dpt); plane_state->ggtt_vma = NULL; @@ -336,12 +337,14 @@ void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state) if (!intel_fb_uses_dpt(&fb->base)) { vma = fetch_and_zero(&old_plane_state->ggtt_vma); - if (vma) - intel_fb_unpin_vma(vma, old_plane_state->flags); + if (vma) { + intel_fb_unpin_vma(vma, old_plane_state->fence_id); + old_plane_state->fence_id = -1; + } } else { vma = fetch_and_zero(&old_plane_state->dpt_vma); if (vma) - intel_fb_unpin_vma(vma, old_plane_state->flags); + intel_fb_unpin_vma(vma, -1); vma = fetch_and_zero(&old_plane_state->ggtt_vma); if (vma) diff --git a/drivers/gpu/drm/i915/i915_initial_plane.c b/drivers/gpu/drm/i915/i915_initial_plane.c index 7775e657271b..4902c0748664 100644 --- a/drivers/gpu/drm/i915/i915_initial_plane.c +++ b/drivers/gpu/drm/i915/i915_initial_plane.c @@ -260,7 +260,7 @@ i915_initial_plane_setup(struct drm_plane_state *_plane_state, plane_state->ggtt_vma = i915_vma_get(vma); if (intel_plane_uses_fence(plane_state) && i915_vma_pin_fence(vma) == 0 && vma->fence) - plane_state->flags |= PLANE_HAS_FENCE; + plane_state->fence_id = vma->fence->id; plane_state->surf = i915_ggtt_offset(plane_state->ggtt_vma); diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index e45a1e7a4670..739d9c019094 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -418,15 +418,15 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, unsigned int alignment, unsigned int phys_alignment, unsigned int vtd_guard, - bool uses_fence, - unsigned long *out_flags) + int *out_fence_id) { - *out_flags = 0; + if (out_fence_id) + *out_fence_id = -1; return __xe_pin_fb_vma(to_intel_framebuffer(fb), view, alignment); } -void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags) +void intel_fb_unpin_vma(struct i915_vma *vma, int fence_id) { __xe_unpin_fb_vma(vma); } diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.c b/drivers/gpu/drm/xe/display/xe_initial_plane.c index 37bd15d12169..381d68c58463 100644 --- a/drivers/gpu/drm/xe/display/xe_initial_plane.c +++ b/drivers/gpu/drm/xe/display/xe_initial_plane.c @@ -136,7 +136,7 @@ xe_initial_plane_setup(struct drm_plane_state *_plane_state, struct i915_vma *vma; vma = intel_fb_pin_to_ggtt(fb, &plane_state->view.gtt, - 0, 0, 0, false, &plane_state->flags); + 0, 0, 0, NULL); if (IS_ERR(vma)) return PTR_ERR(vma); From 9fce8ff956cc3493b327f6928458e2278ef531a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 7 Apr 2026 20:09:42 +0300 Subject: [PATCH 095/144] drm/i915: Remove the vma parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the fb pinning stuff directly returning the fence_id there is no longer any need for the vma parent interface. Get rid of it. Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260407170942.16515-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_parent.c | 9 --------- drivers/gpu/drm/i915/display/intel_parent.h | 3 --- drivers/gpu/drm/i915/i915_driver.c | 1 - drivers/gpu/drm/i915/i915_vma.c | 10 ---------- drivers/gpu/drm/i915/i915_vma.h | 2 -- include/drm/intel/display_parent_interface.h | 7 ------- 6 files changed, 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 47ce3b6fdd5b..67b21a42d354 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -372,15 +372,6 @@ int intel_parent_vlv_iosf_write(struct intel_display *display, enum vlv_iosf_sb_ return display->parent->vlv_iosf->write(display->drm, unit, addr, val); } -/* vma */ -int intel_parent_vma_fence_id(struct intel_display *display, const struct i915_vma *vma) -{ - if (!display->parent->vma) - return -1; - - return display->parent->vma->fence_id(vma); -} - /* generic */ void intel_parent_fence_priority_display(struct intel_display *display, struct dma_fence *fence) { diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index 1e89d24163cc..5f0c835b9416 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -116,9 +116,6 @@ void intel_parent_vlv_iosf_put(struct intel_display *display, unsigned long unit u32 intel_parent_vlv_iosf_read(struct intel_display *display, enum vlv_iosf_sb_unit unit, u32 addr); int intel_parent_vlv_iosf_write(struct intel_display *display, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); -/* vma */ -int intel_parent_vma_fence_id(struct intel_display *display, const struct i915_vma *vma); - /* generic */ bool intel_parent_has_auxccs(struct intel_display *display); bool intel_parent_has_fenced_regions(struct intel_display *display); diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 129013c5fb42..195e34acef30 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -780,7 +780,6 @@ static const struct intel_display_parent_interface parent = { .rps = &i915_display_rps_interface, .stolen = &i915_display_stolen_interface, .vlv_iosf = &i915_display_vlv_iosf_interface, - .vma = &i915_display_vma_interface, .fence_priority_display = fence_priority_display, .has_auxccs = has_auxccs, diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 6a3a4d4244dc..afc192d9931b 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -27,7 +27,6 @@ #include #include -#include #include "display/intel_fb.h" #include "display/intel_frontbuffer.h" @@ -2333,12 +2332,3 @@ int __init i915_vma_module_init(void) return 0; } - -static int i915_vma_fence_id(const struct i915_vma *vma) -{ - return vma->fence ? vma->fence->id : -1; -} - -const struct intel_display_vma_interface i915_display_vma_interface = { - .fence_id = i915_vma_fence_id, -}; diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index fa2d9b429db6..892306ab935d 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -476,6 +476,4 @@ int i915_vma_module_init(void); I915_SELFTEST_DECLARE(int i915_vma_get_pages(struct i915_vma *vma)); I915_SELFTEST_DECLARE(void i915_vma_put_pages(struct i915_vma *vma)); -extern const struct intel_display_vma_interface i915_display_vma_interface; - #endif diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index b513e3f9924d..270dc028bec2 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -189,10 +189,6 @@ struct intel_display_vlv_iosf_interface { int (*write)(struct drm_device *drm, enum vlv_iosf_sb_unit unit, u32 addr, u32 val); }; -struct intel_display_vma_interface { - int (*fence_id)(const struct i915_vma *vma); -}; - /** * struct intel_display_parent_interface - services parent driver provides to display * @@ -251,9 +247,6 @@ struct intel_display_parent_interface { /** @vlv_iosf: VLV IOSF sideband. Optional. */ const struct intel_display_vlv_iosf_interface *vlv_iosf; - /** @vma: VMA interface. Optional. */ - const struct intel_display_vma_interface *vma; - /* Generic independent functions */ struct { /** @fence_priority_display: Set display priority. Optional. */ From 81cb85cac649cc44a8cd80415626f1c36020cbbd Mon Sep 17 00:00:00 2001 From: Arun R Murthy Date: Wed, 15 Apr 2026 10:09:52 +0530 Subject: [PATCH 096/144] drm/i915/lt_phy: Update the Tx Swing for DP 1.4 Changes have been introduced in Bspec regarding the Tx Swing level, Tx pre/post coefficients. Update the Tx Swing Level and the Tx pre/post-cursor co-effecients to incorporate these changes v2: Updated the commit message (Suraj) BSpec: 74493 Signed-off-by: Arun R Murthy Reviewed-by: Suraj Kandpal Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260415043952.3189598-1-arun.r.murthy@intel.com --- drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c index 395dba8c9e4d..980ab19868b3 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -1123,8 +1123,8 @@ static const union intel_ddi_buf_trans_entry _xe3plpd_lt_trans_dp14[] = { { .lt = { 1, 2, 0, 28, 7 } }, { .lt = { 0, 3, 0, 35, 13 } }, { .lt = { 1, 1, 0, 27, 0 } }, - { .lt = { 1, 2, 0, 31, 4 } }, - { .lt = { 0, 3, 0, 39, 9 } }, + { .lt = { 1, 2, 0, 31, 5 } }, + { .lt = { 0, 3, 0, 37, 11 } }, { .lt = { 1, 2, 0, 35, 0 } }, { .lt = { 0, 3, 0, 41, 7 } }, { .lt = { 0, 3, 0, 48, 0 } }, From 758eedf64bd308d6011d740f5cc3b3ef181ce4c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 00:04:05 +0300 Subject: [PATCH 097/144] drm/i915: Clear i915->display when no longer valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't leave a stale i915->display pointer hanging around after the display driver has been torn down. Apparently the gt code calls into the reset codepaths after this, and if the display pointer is still around we may try to access freed memory. The whole teardown sequence here seems rather suspect. Why is display done first and then everything else via the managed release? Who the heck knows. Someone really needs to dig into this stuff and figure out the proper init/cleanup sequence for both i915 (real and mock) and xe... Cc: Jani Nikula Cc: Jouni Högander Cc: Maarten Lankhorst Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260415210411.24750-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/i915_driver.c | 1 + drivers/gpu/drm/i915/selftests/mock_gem_device.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 195e34acef30..d31819758f3d 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -310,6 +310,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv) i915_params_free(&dev_priv->params); intel_display_device_remove(display); + dev_priv->display = NULL; } /** diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 27dc0e40a8d7..796c9b070e41 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -277,6 +277,7 @@ void mock_destroy_device(struct drm_i915_private *i915) struct device *dev = i915->drm.dev; intel_display_device_remove(i915->display); + i915->display = NULL; devres_release_group(dev, NULL); put_device(dev); From cc07f2925b8856a3188f64a73561b4d8c0cb5a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 00:04:06 +0300 Subject: [PATCH 098/144] drm/xe: Clear xe->display when no longer valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't leave a stale xe->display pointer hanging around after the display driver has been torn down. While xe shouldn't hit the display reset related issue that affects i915, leaving stale pointer floating around still seems like a bad idea. Cc: Jani Nikula Cc: Jouni Högander Cc: Maarten Lankhorst Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260415210411.24750-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 00dfa68af29a..0747044f7c2a 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -520,9 +520,10 @@ void xe_display_pm_runtime_resume(struct xe_device *xe) static void display_device_remove(struct drm_device *dev, void *arg) { - struct intel_display *display = arg; + struct xe_device *xe = arg; - intel_display_device_remove(display); + intel_display_device_remove(xe->display); + xe->display = NULL; } static bool irq_enabled(struct drm_device *drm) @@ -587,12 +588,12 @@ int xe_display_probe(struct xe_device *xe) if (IS_ERR(display)) return PTR_ERR(display); - err = drmm_add_action_or_reset(&xe->drm, display_device_remove, display); + xe->display = display; + + err = drmm_add_action_or_reset(&xe->drm, display_device_remove, xe); if (err) return err; - xe->display = display; - if (intel_display_device_present(display)) return 0; From 2c5b4320973beabe79dc7685357cd16fe73feca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 00:04:07 +0300 Subject: [PATCH 099/144] drm/i915/reset: Reorganize display reset code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop returning the "is there a display?" status from intel_display_reset_prepare(). I plan to move the pending_fb_pin into the i915 code, so I need to make that determination already before intel_display_reset_prepare() is called. Add a new intel_display_reset_supported() function for that. v2: Also check display!=NULL for mock tests Cc: Jouni Högander Cc: Maarten Lankhorst Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260415210411.24750-4-ville.syrjala@linux.intel.com --- .../drm/i915/display/intel_display_reset.c | 25 ++++++++----------- .../drm/i915/display/intel_display_reset.h | 3 ++- drivers/gpu/drm/i915/gt/intel_reset.c | 13 ++++++---- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.c b/drivers/gpu/drm/i915/display/intel_display_reset.c index d00ef5bdcbda..fc661c623cb8 100644 --- a/drivers/gpu/drm/i915/display/intel_display_reset.c +++ b/drivers/gpu/drm/i915/display/intel_display_reset.c @@ -16,22 +16,24 @@ #include "intel_hotplug.h" #include "intel_pps.h" -bool intel_display_reset_test(struct intel_display *display) +bool intel_display_reset_supported(struct intel_display *display) { - return display->params.force_reset_modeset_test; + return display && HAS_DISPLAY(display); } -/* returns true if intel_display_reset_finish() needs to be called */ -bool intel_display_reset_prepare(struct intel_display *display, +bool intel_display_reset_test(struct intel_display *display) +{ + return display && HAS_DISPLAY(display) && + display->params.force_reset_modeset_test; +} + +void intel_display_reset_prepare(struct intel_display *display, modeset_stuck_fn modeset_stuck, void *context) { struct drm_modeset_acquire_ctx *ctx = &display->restore.reset_ctx; struct drm_atomic_state *state; int ret; - if (!HAS_DISPLAY(display)) - return false; - if (atomic_read(&display->restore.pending_fb_pin)) { drm_dbg_kms(display->drm, "Modeset potentially stuck, unbreaking through wedging\n"); @@ -60,7 +62,7 @@ bool intel_display_reset_prepare(struct intel_display *display, ret = PTR_ERR(state); drm_err(display->drm, "Duplicating state failed with %i\n", ret); - return true; + return; } ret = drm_atomic_helper_disable_all(display->drm, ctx); @@ -68,13 +70,11 @@ bool intel_display_reset_prepare(struct intel_display *display, drm_err(display->drm, "Suspending crtc's failed with %i\n", ret); drm_atomic_state_put(state); - return true; + return; } display->restore.modeset_state = state; state->acquire_ctx = ctx; - - return true; } void intel_display_reset_finish(struct intel_display *display, bool test_only) @@ -83,9 +83,6 @@ void intel_display_reset_finish(struct intel_display *display, bool test_only) struct drm_atomic_state *state; int ret; - if (!HAS_DISPLAY(display)) - return; - state = fetch_and_zero(&display->restore.modeset_state); if (!state) goto unlock; diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.h b/drivers/gpu/drm/i915/display/intel_display_reset.h index 8b3bda134454..e0f15e757728 100644 --- a/drivers/gpu/drm/i915/display/intel_display_reset.h +++ b/drivers/gpu/drm/i915/display/intel_display_reset.h @@ -12,8 +12,9 @@ struct intel_display; typedef void modeset_stuck_fn(void *context); +bool intel_display_reset_supported(struct intel_display *display); bool intel_display_reset_test(struct intel_display *display); -bool intel_display_reset_prepare(struct intel_display *display, +void intel_display_reset_prepare(struct intel_display *display, modeset_stuck_fn modeset_stuck, void *context); void intel_display_reset_finish(struct intel_display *display, bool test_only); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 37272871b0f2..ffd11767874f 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1425,16 +1425,19 @@ static void intel_gt_reset_global(struct intel_gt *gt, bool need_display_reset; bool reset_display; - need_display_reset = intel_gt_gpu_reset_clobbers_display(gt) && + need_display_reset = + intel_display_reset_supported(display) && + intel_gt_gpu_reset_clobbers_display(gt) && intel_has_gpu_reset(gt); - reset_display = intel_display_reset_test(display) || + reset_display = + intel_display_reset_test(display) || need_display_reset; if (reset_display) - reset_display = intel_display_reset_prepare(display, - display_reset_modeset_stuck, - gt); + intel_display_reset_prepare(display, + display_reset_modeset_stuck, + gt); intel_gt_reset(gt, engine_mask, reason); From 6dc69ca3c47c0f6c485a6485be72314c0cef10b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 00:04:08 +0300 Subject: [PATCH 100/144] drm/i915/reset: Move pending_fb_pin handling to i915 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only i915 uses the pending_fb_pin counter to potentially whack the GPU harder if the display gets nuked during a GPU reset. Move the atomic counter into the i915 specific bits of code, so that we don't need to worry about on the display side. For some reason the overlay code kept the pending_fb_pin counter elevated for longer than just for the pin, but from now on it'll just cover the actual pinning part. Cc: Jouni Högander Cc: Maarten Lankhorst Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260415210411.24750-5-ville.syrjala@linux.intel.com --- .../gpu/drm/i915/display/intel_display_core.h | 1 - .../drm/i915/display/intel_display_reset.c | 9 +-------- .../drm/i915/display/intel_display_reset.h | 5 +---- drivers/gpu/drm/i915/display/intel_overlay.c | 10 ++-------- drivers/gpu/drm/i915/gt/intel_reset.c | 19 ++++++++++--------- drivers/gpu/drm/i915/i915_dpt.c | 5 ++--- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_fb_pin.c | 9 ++++----- drivers/gpu/drm/i915/i915_overlay.c | 6 ++++++ 9 files changed, 28 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index d9baca2d5aaf..38296a38372c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -564,7 +564,6 @@ struct intel_display { struct drm_atomic_state *modeset_state; struct drm_modeset_acquire_ctx reset_ctx; /* modeset stuck tracking for reset */ - atomic_t pending_fb_pin; u32 saveDSPARB; u32 saveSWF0[16]; u32 saveSWF1[16]; diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.c b/drivers/gpu/drm/i915/display/intel_display_reset.c index fc661c623cb8..be4af74f0275 100644 --- a/drivers/gpu/drm/i915/display/intel_display_reset.c +++ b/drivers/gpu/drm/i915/display/intel_display_reset.c @@ -27,19 +27,12 @@ bool intel_display_reset_test(struct intel_display *display) display->params.force_reset_modeset_test; } -void intel_display_reset_prepare(struct intel_display *display, - modeset_stuck_fn modeset_stuck, void *context) +void intel_display_reset_prepare(struct intel_display *display) { struct drm_modeset_acquire_ctx *ctx = &display->restore.reset_ctx; struct drm_atomic_state *state; int ret; - if (atomic_read(&display->restore.pending_fb_pin)) { - drm_dbg_kms(display->drm, - "Modeset potentially stuck, unbreaking through wedging\n"); - modeset_stuck(context); - } - /* * Need mode_config.mutex so that we don't * trample ongoing ->detect() and whatnot. diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.h b/drivers/gpu/drm/i915/display/intel_display_reset.h index e0f15e757728..a8aa7729d33f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_reset.h +++ b/drivers/gpu/drm/i915/display/intel_display_reset.h @@ -10,12 +10,9 @@ struct intel_display; -typedef void modeset_stuck_fn(void *context); - bool intel_display_reset_supported(struct intel_display *display); bool intel_display_reset_test(struct intel_display *display); -void intel_display_reset_prepare(struct intel_display *display, - modeset_stuck_fn modeset_stuck, void *context); +void intel_display_reset_prepare(struct intel_display *display); void intel_display_reset_finish(struct intel_display *display, bool test_only); #endif /* __INTEL_RESET_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 12a325ceae6f..a809aa2950ac 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -481,13 +481,9 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, if (ret != 0) return ret; - atomic_inc(&display->restore.pending_fb_pin); - vma = intel_parent_overlay_pin_fb(display, obj, &offset); - if (IS_ERR(vma)) { - ret = PTR_ERR(vma); - goto out_pin_section; - } + if (IS_ERR(vma)) + return PTR_ERR(vma); if (!intel_parent_overlay_is_active(display)) { const struct intel_crtc_state *crtc_state = @@ -571,8 +567,6 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, out_unpin: intel_parent_overlay_unpin_fb(display, vma); -out_pin_section: - atomic_dec(&display->restore.pending_fb_pin); return ret; } diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index ffd11767874f..a1e6aaca8c9b 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1398,11 +1398,6 @@ int intel_engine_reset(struct intel_engine_cs *engine, const char *msg) return err; } -static void display_reset_modeset_stuck(void *gt) -{ - intel_gt_set_wedged(gt); -} - static void intel_gt_reset_global(struct intel_gt *gt, u32 engine_mask, const char *reason) @@ -1434,10 +1429,16 @@ static void intel_gt_reset_global(struct intel_gt *gt, intel_display_reset_test(display) || need_display_reset; - if (reset_display) - intel_display_reset_prepare(display, - display_reset_modeset_stuck, - gt); + if (reset_display) { + if (atomic_read(&i915->pending_fb_pin)) { + drm_dbg_kms(&i915->drm, + "Modeset potentially stuck, unbreaking through wedging\n"); + + intel_gt_set_wedged(gt); + } + + intel_display_reset_prepare(display); + } intel_gt_reset(gt, engine_mask, reason); diff --git a/drivers/gpu/drm/i915/i915_dpt.c b/drivers/gpu/drm/i915/i915_dpt.c index 9f47bb563c85..fcd7cced771d 100644 --- a/drivers/gpu/drm/i915/i915_dpt.c +++ b/drivers/gpu/drm/i915/i915_dpt.c @@ -129,7 +129,6 @@ static void dpt_cleanup(struct i915_address_space *vm) struct i915_vma *i915_dpt_pin_to_ggtt(struct intel_dpt *dpt, unsigned int alignment) { struct drm_i915_private *i915 = dpt->vm.i915; - struct intel_display *display = i915->display; struct ref_tracker *wakeref; struct i915_vma *vma; void __iomem *iomem; @@ -141,7 +140,7 @@ struct i915_vma *i915_dpt_pin_to_ggtt(struct intel_dpt *dpt, unsigned int alignm pin_flags |= PIN_MAPPABLE; wakeref = intel_runtime_pm_get(&i915->runtime_pm); - atomic_inc(&display->restore.pending_fb_pin); + atomic_inc(&i915->pending_fb_pin); for_i915_gem_ww(&ww, err, true) { err = i915_gem_object_lock(dpt->obj, &ww); @@ -171,7 +170,7 @@ struct i915_vma *i915_dpt_pin_to_ggtt(struct intel_dpt *dpt, unsigned int alignm dpt->obj->mm.dirty = true; - atomic_dec(&display->restore.pending_fb_pin); + atomic_dec(&i915->pending_fb_pin); intel_runtime_pm_put(&i915->runtime_pm, wakeref); return err ? ERR_PTR(err) : vma; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dafee3dcd1c5..844ed79e7211 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -315,6 +315,8 @@ struct drm_i915_private { /* The TTM device structure. */ struct ttm_device bdev; + atomic_t pending_fb_pin; + I915_SELFTEST_DECLARE(struct i915_selftest_stash selftest;) /* diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index efd5cb726cf8..85649bae25fb 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -28,7 +28,6 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, unsigned int alignment, struct intel_dpt *dpt) { - struct intel_display *display = to_intel_display(fb->dev); struct drm_i915_private *i915 = to_i915(fb->dev); struct drm_gem_object *_obj = intel_fb_bo(fb); struct drm_i915_gem_object *obj = to_intel_bo(_obj); @@ -47,7 +46,7 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, if (WARN_ON(!i915_gem_object_is_framebuffer(obj))) return ERR_PTR(-EINVAL); - atomic_inc(&display->restore.pending_fb_pin); + atomic_inc(&i915->pending_fb_pin); for_i915_gem_ww(&ww, ret, true) { ret = i915_gem_object_lock(obj, &ww); @@ -102,7 +101,7 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, i915_vma_get(vma); err: - atomic_dec(&display->restore.pending_fb_pin); + atomic_dec(&i915->pending_fb_pin); return vma; } @@ -140,7 +139,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, */ wakeref = intel_runtime_pm_get(&i915->runtime_pm); - atomic_inc(&display->restore.pending_fb_pin); + atomic_inc(&i915->pending_fb_pin); /* * Valleyview is definitely limited to scanning out the first @@ -219,7 +218,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, if (ret) vma = ERR_PTR(ret); - atomic_dec(&display->restore.pending_fb_pin); + atomic_dec(&i915->pending_fb_pin); intel_runtime_pm_put(&i915->runtime_pm, wakeref); return vma; } diff --git a/drivers/gpu/drm/i915/i915_overlay.c b/drivers/gpu/drm/i915/i915_overlay.c index 2d7aff51e39b..6de550a17756 100644 --- a/drivers/gpu/drm/i915/i915_overlay.c +++ b/drivers/gpu/drm/i915/i915_overlay.c @@ -354,11 +354,14 @@ static struct i915_vma *i915_overlay_pin_fb(struct drm_device *drm, struct drm_gem_object *obj, u32 *offset) { + struct drm_i915_private *i915 = to_i915(drm); struct drm_i915_gem_object *new_bo = to_intel_bo(obj); struct i915_gem_ww_ctx ww; struct i915_vma *vma; int ret; + atomic_inc(&i915->pending_fb_pin); + i915_gem_ww_ctx_init(&ww, true); retry: ret = i915_gem_object_lock(new_bo, &ww); @@ -373,6 +376,9 @@ static struct i915_vma *i915_overlay_pin_fb(struct drm_device *drm, goto retry; } i915_gem_ww_ctx_fini(&ww); + + atomic_dec(&i915->pending_fb_pin); + if (ret) return ERR_PTR(ret); From a9f8901e404a269f29f708012c06b40662bdc633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 00:04:09 +0300 Subject: [PATCH 101/144] drm/xe/display: Add init_clock_gating.h stubs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add static inline stubs for init_clock_gating.h functions so that we don't need ifdefs in the actual code. We already have one in intel_display_power.c, and now I need to bring over intel_display_reset.c. Cc: Jouni Högander Cc: Maarten Lankhorst Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260415210411.24750-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 2 -- .../drm/xe/compat-i915-headers/intel_clock_gating.h | 10 +++++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 8a7afe2a94bc..80ecf373fb19 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1420,9 +1420,7 @@ static void hsw_disable_pc8(struct intel_display *display) intel_init_pch_refclk(display); /* Many display registers don't survive PC8+ */ -#ifdef I915 /* FIXME */ intel_clock_gating_init(display->drm); -#endif } static void intel_pch_reset_handshake(struct intel_display *display, diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_clock_gating.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_clock_gating.h index ce986f0e8f38..552975a30ba2 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_clock_gating.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/intel_clock_gating.h @@ -3,4 +3,12 @@ * Copyright © 2023 Intel Corporation */ -#include "../../i915/intel_clock_gating.h" +#ifndef __INTEL_CLOCK_GATING_H__ +#define __INTEL_CLOCK_GATING_H__ + +struct drm_device; + +static inline void intel_clock_gating_init(struct drm_device *drm) {} +static inline void intel_clock_gating_hooks_init(struct drm_device *drm) {} + +#endif /* __INTEL_CLOCK_GATING_H__ */ From 584fff57f5410a617ce6fe64d9343a52a3793551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 00:04:10 +0300 Subject: [PATCH 102/144] drm/i915/reset: Add "intel_display_reset_count" debugfs file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expose the number of display resets performed in a new "display_reset_count" debugfs file. kms_busy can use this to confirm that the kernel actually took the full display reset path. v2: Give the file an "intel_" namespace (Jani) Cc: Jouni Högander Cc: Maarten Lankhorst Reviewed-by: Jani Nikula Testcase: igt/kms_busy/*-with-reset Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260415210411.24750-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display_core.h | 4 ++++ drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 ++ drivers/gpu/drm/i915/display/intel_display_reset.c | 10 ++++++++++ drivers/gpu/drm/i915/display/intel_display_reset.h | 2 ++ drivers/gpu/drm/xe/Makefile | 1 + 5 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 38296a38372c..c5a07090cba6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -559,6 +559,10 @@ struct intel_display { unsigned long mask; } quirks; + struct { + u32 count; + } reset; + struct { /* restore state for suspend/resume and display reset */ struct drm_atomic_state *modeset_state; diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index f244a2b5d139..81bef000a4e3 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -27,6 +27,7 @@ #include "intel_display_power.h" #include "intel_display_power_well.h" #include "intel_display_regs.h" +#include "intel_display_reset.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_dmc.h" @@ -838,6 +839,7 @@ void intel_display_debugfs_register(struct intel_display *display) intel_bios_debugfs_register(display); intel_cdclk_debugfs_register(display); + intel_display_reset_debugfs_register(display); intel_dmc_debugfs_register(display); intel_dp_test_debugfs_register(display); intel_fbc_debugfs_register(display); diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.c b/drivers/gpu/drm/i915/display/intel_display_reset.c index be4af74f0275..fb3ac52a0acf 100644 --- a/drivers/gpu/drm/i915/display/intel_display_reset.c +++ b/drivers/gpu/drm/i915/display/intel_display_reset.c @@ -3,6 +3,8 @@ * Copyright © 2023 Intel Corporation */ +#include + #include #include @@ -66,6 +68,7 @@ void intel_display_reset_prepare(struct intel_display *display) return; } + display->reset.count++; display->restore.modeset_state = state; state->acquire_ctx = ctx; } @@ -114,3 +117,10 @@ void intel_display_reset_finish(struct intel_display *display, bool test_only) drm_modeset_acquire_fini(ctx); mutex_unlock(&display->drm->mode_config.mutex); } + +void intel_display_reset_debugfs_register(struct intel_display *display) +{ + debugfs_create_u32("intel_display_reset_count", 0400, + display->drm->debugfs_root, + &display->reset.count); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.h b/drivers/gpu/drm/i915/display/intel_display_reset.h index a8aa7729d33f..b88c330a3441 100644 --- a/drivers/gpu/drm/i915/display/intel_display_reset.h +++ b/drivers/gpu/drm/i915/display/intel_display_reset.h @@ -15,4 +15,6 @@ bool intel_display_reset_test(struct intel_display *display); void intel_display_reset_prepare(struct intel_display *display); void intel_display_reset_finish(struct intel_display *display, bool test_only); +void intel_display_reset_debugfs_register(struct intel_display *display); + #endif /* __INTEL_RESET_H__ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 288d621e9ccb..c249cb106d58 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -260,6 +260,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_display_power.o \ i915-display/intel_display_power_map.o \ i915-display/intel_display_power_well.o \ + i915-display/intel_display_reset.o \ i915-display/intel_display_rpm.o \ i915-display/intel_display_rps.o \ i915-display/intel_display_trace.o \ From 71096693e8eb94554807309956ca5f787be36709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 00:04:11 +0300 Subject: [PATCH 103/144] drm/i915/reset: Disable execlist per-engine reset for display reset tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The display reset only happens from the full reset path. We must therefore force execlist submission to always take the full reset path and not the per-engine reset path. Currently the display reset tests are in fact not testing display resets at all on platforms using execlist submission. Ring submission and GuC submission always take the full path anyway. Also disable the engine reset inside __intel_gt_set_wedged() so that we simulate the intel_gt_gpu_reset_clobbers_display() behavior as closely as possible also when taking the full wedge path. The slight race between the separate intel_display_reset_test() calls in the overall reset path is harmless. kms_busy will keep the modparam fixed during the test, and even if someone were to fiddle with the modparam manually nothing bad should happen if the calls return different values. Cc: Jouni Högander Cc: Maarten Lankhorst Acked-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260415210411.24750-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/gt/intel_reset.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index a1e6aaca8c9b..0b5f3fc58009 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -967,6 +967,7 @@ static void nop_submit_request(struct i915_request *request) static void __intel_gt_set_wedged(struct intel_gt *gt) { + struct intel_display *display = gt->i915->display; struct intel_engine_cs *engine; intel_engine_mask_t awake; enum intel_engine_id id; @@ -984,7 +985,8 @@ static void __intel_gt_set_wedged(struct intel_gt *gt) awake = reset_prepare(gt); /* Even if the GPU reset fails, it should still stop the engines */ - if (!intel_gt_gpu_reset_clobbers_display(gt)) + if (!intel_gt_gpu_reset_clobbers_display(gt) && + !intel_display_reset_test(display)) intel_gt_reset_all_engines(gt); for_each_engine(engine, gt, id) @@ -1506,9 +1508,10 @@ void intel_gt_handle_error(struct intel_gt *gt, /* * Try engine reset when available. We fall back to full reset if - * single reset fails. + * single reset fails. Display reset test needs a full reset. */ - if (!intel_uc_uses_guc_submission(>->uc) && + if (!intel_display_reset_test(gt->i915->display) && + !intel_uc_uses_guc_submission(>->uc) && intel_has_reset_engine(gt) && !intel_gt_is_wedged(gt)) { local_bh_disable(); for_each_engine_masked(engine, gt, engine_mask, tmp) { From f296c423b25839f279bf22e71c5b82fb332cac78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:37 +0300 Subject: [PATCH 104/144] drm/xe/fb: Use the correct gtt view for remapped FBs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the proper gtt view from the plane state rather than always assuming that it came directly from the FB. This is in the DPT codepath so the view should currently always come from the FB, but in the future we may also want per-plane remapping with DPT. Reviewed-by: Jani Nikula Cc: Maarten Lankhorst Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/xe/display/xe_fb_pin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 739d9c019094..91e5c1052589 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -154,7 +154,7 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, if (view->type == I915_GTT_VIEW_NORMAL) dpt_size = ALIGN(size / XE_PAGE_SIZE * 8, XE_PAGE_SIZE); else if (view->type == I915_GTT_VIEW_REMAPPED) - dpt_size = ALIGN(intel_remapped_info_size(&fb->remapped_view.gtt.remapped) * 8, + dpt_size = ALIGN(intel_remapped_info_size(&view->remapped) * 8, XE_PAGE_SIZE); else /* display uses 4K tiles instead of bytes here, convert to entries.. */ From a89b7f72f20db1ae1a65e97881e785639db4480a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:38 +0300 Subject: [PATCH 105/144] drm/i915: Introduce struct intel_fb_pin_params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to pass a lot of information between the display driver and the core driver to get framebuffers mapped into GGTT/DPT correctly. Rather than passing around a swarm of integers and boolean as function arguments, let's collect it all into a structure (struct intel_fb_pin_params). Start by moving the gtt view, alignment, phys_alignment, and vtd_guard there. Going forward additional things need to added as well (mainly various boolean flags). Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb_pin.h | 12 +++-- drivers/gpu/drm/i915/display/intel_fbdev.c | 13 +++-- drivers/gpu/drm/i915/i915_fb_pin.c | 54 ++++++++++--------- drivers/gpu/drm/xe/display/xe_fb_pin.c | 39 +++++++------- drivers/gpu/drm/xe/display/xe_initial_plane.c | 6 ++- 5 files changed, 69 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.h b/drivers/gpu/drm/i915/display/intel_fb_pin.h index 2eca42b74c4a..e6271437459d 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.h +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.h @@ -14,12 +14,16 @@ struct intel_plane_state; struct i915_gtt_view; struct iosys_map; +struct intel_fb_pin_params { + const struct i915_gtt_view *view; + unsigned int alignment; + unsigned int phys_alignment; + unsigned int vtd_guard; +}; + struct i915_vma * intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, - const struct i915_gtt_view *view, - unsigned int alignment, - unsigned int phys_alignment, - unsigned int vtd_guard, + const struct intel_fb_pin_params *pin_params, int *out_fence_id); void intel_fb_unpin_vma(struct i915_vma *vma, int fence_id); diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 1e22b3fd79ba..136fa827c8f0 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -264,6 +264,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, { struct intel_display *display = to_intel_display(helper->dev); struct intel_fbdev *ifbdev = to_intel_fbdev(helper); + struct intel_fb_pin_params pin_params = {}; struct intel_framebuffer *fb = ifbdev->fb; struct fb_info *info = helper->info; struct ref_tracker *wakeref; @@ -308,11 +309,13 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, * This also validates that any existing fb inherited from the * BIOS is suitable for own access. */ - vma = intel_fb_pin_to_ggtt(&fb->base, &fb->normal_view.gtt, - fb->min_alignment, 0, - intel_fb_view_vtd_guard(&fb->base, &fb->normal_view, - DRM_MODE_ROTATE_0), - NULL); + pin_params.view = &fb->normal_view.gtt; + pin_params.alignment = fb->min_alignment; + pin_params.vtd_guard = intel_fb_view_vtd_guard(&fb->base, + &fb->normal_view, + DRM_MODE_ROTATE_0); + + vma = intel_fb_pin_to_ggtt(&fb->base, &pin_params, NULL); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_unlock; diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 85649bae25fb..4fe6b9859b3f 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -24,9 +24,8 @@ static struct i915_vma * intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, - const struct i915_gtt_view *view, - unsigned int alignment, - struct intel_dpt *dpt) + struct intel_dpt *dpt, + const struct intel_fb_pin_params *pin_params) { struct drm_i915_private *i915 = to_i915(fb->dev); struct drm_gem_object *_obj = intel_fb_bo(fb); @@ -74,19 +73,20 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, if (ret) continue; - vma = i915_vma_instance(obj, vm, view); + vma = i915_vma_instance(obj, vm, pin_params->view); if (IS_ERR(vma)) { ret = PTR_ERR(vma); continue; } - if (i915_vma_misplaced(vma, 0, alignment, 0)) { + if (i915_vma_misplaced(vma, 0, pin_params->alignment, 0)) { ret = i915_vma_unbind(vma); if (ret) continue; } - ret = i915_vma_pin_ww(vma, &ww, 0, alignment, PIN_GLOBAL); + ret = i915_vma_pin_ww(vma, &ww, 0, pin_params->alignment, + PIN_GLOBAL); if (ret) continue; } @@ -95,7 +95,8 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, goto err; } - vma->display_alignment = max(vma->display_alignment, alignment); + vma->display_alignment = max(vma->display_alignment, + pin_params->alignment); i915_gem_object_flush_if_display(obj); @@ -108,10 +109,7 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, struct i915_vma * intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, - const struct i915_gtt_view *view, - unsigned int alignment, - unsigned int phys_alignment, - unsigned int vtd_guard, + const struct intel_fb_pin_params *pin_params, int *out_fence_id) { struct intel_display *display = to_intel_display(fb->dev); @@ -127,7 +125,8 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, if (drm_WARN_ON(&i915->drm, !i915_gem_object_is_framebuffer(obj))) return ERR_PTR(-EINVAL); - if (drm_WARN_ON(&i915->drm, alignment && !is_power_of_2(alignment))) + if (drm_WARN_ON(&i915->drm, pin_params->alignment && + !is_power_of_2(pin_params->alignment))) return ERR_PTR(-EINVAL); /* @@ -156,8 +155,8 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, i915_gem_ww_ctx_init(&ww, true); retry: ret = i915_gem_object_lock(obj, &ww); - if (!ret && phys_alignment) - ret = i915_gem_object_attach_phys(obj, phys_alignment); + if (!ret && pin_params->phys_alignment) + ret = i915_gem_object_attach_phys(obj, pin_params->phys_alignment); else if (!ret && HAS_LMEM(i915)) ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0); if (!ret) @@ -165,8 +164,10 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, if (ret) goto err; - vma = i915_gem_object_pin_to_display_plane(obj, &ww, alignment, - vtd_guard, view, pinctl); + vma = i915_gem_object_pin_to_display_plane(obj, &ww, + pin_params->alignment, + pin_params->vtd_guard, + pin_params->view, pinctl); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto err_unpin; @@ -269,12 +270,15 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, struct i915_vma *vma; if (!intel_fb_uses_dpt(&fb->base)) { + struct intel_fb_pin_params pin_params = { + .view = &plane_state->view.gtt, + .alignment = intel_plane_fb_min_alignment(plane_state), + .phys_alignment = intel_plane_fb_min_phys_alignment(plane_state), + .vtd_guard = intel_plane_fb_vtd_guard(plane_state), + }; int fence_id = -1; - vma = intel_fb_pin_to_ggtt(&fb->base, &plane_state->view.gtt, - intel_plane_fb_min_alignment(plane_state), - intel_plane_fb_min_phys_alignment(plane_state), - intel_plane_fb_vtd_guard(plane_state), + vma = intel_fb_pin_to_ggtt(&fb->base, &pin_params, intel_plane_uses_fence(plane_state) ? &fence_id : NULL); if (IS_ERR(vma)) return PTR_ERR(vma); @@ -282,16 +286,18 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, plane_state->ggtt_vma = vma; plane_state->fence_id = fence_id; } else { - unsigned int alignment = intel_plane_fb_min_alignment(plane_state); + struct intel_fb_pin_params pin_params = { + .view = &plane_state->view.gtt, + .alignment = intel_plane_fb_min_alignment(plane_state), + }; - vma = i915_dpt_pin_to_ggtt(fb->dpt, alignment / 512); + vma = i915_dpt_pin_to_ggtt(fb->dpt, pin_params.alignment / 512); if (IS_ERR(vma)) return PTR_ERR(vma); plane_state->ggtt_vma = vma; - vma = intel_fb_pin_to_dpt(&fb->base, &plane_state->view.gtt, - alignment, fb->dpt); + vma = intel_fb_pin_to_dpt(&fb->base, fb->dpt, &pin_params); if (IS_ERR(vma)) { i915_dpt_unpin_from_ggtt(fb->dpt); plane_state->ggtt_vma = NULL; diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 91e5c1052589..58cd527e1fde 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -140,14 +140,14 @@ write_dpt_remapped(struct xe_bo *bo, } static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, - const struct i915_gtt_view *view, - struct i915_vma *vma, - unsigned int alignment) + const struct intel_fb_pin_params *pin_params, + struct i915_vma *vma) { struct xe_device *xe = to_xe_device(fb->base.dev); struct xe_tile *tile0 = xe_device_get_root_tile(xe); struct xe_ggtt *ggtt = tile0->mem.ggtt; struct drm_gem_object *obj = intel_fb_bo(&fb->base); + const struct i915_gtt_view *view = pin_params->view; struct xe_bo *bo = gem_to_xe_bo(obj), *dpt; u32 dpt_size, size = bo->ttm.base.size; @@ -168,7 +168,7 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, XE_BO_FLAG_VRAM0 | XE_BO_FLAG_GGTT | XE_BO_FLAG_PAGETABLE, - alignment, false); + pin_params->alignment, false); else dpt = xe_bo_create_pin_map_at_novm(xe, tile0, dpt_size, ~0ull, @@ -176,7 +176,7 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, XE_BO_FLAG_STOLEN | XE_BO_FLAG_GGTT | XE_BO_FLAG_PAGETABLE, - alignment, false); + pin_params->alignment, false); if (IS_ERR(dpt)) dpt = xe_bo_create_pin_map_at_novm(xe, tile0, dpt_size, ~0ull, @@ -185,7 +185,7 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, XE_BO_FLAG_GGTT | XE_BO_FLAG_PAGETABLE | XE_BO_FLAG_FORCE_WC, - alignment, false); + pin_params->alignment, false); if (IS_ERR(dpt)) return PTR_ERR(dpt); @@ -269,11 +269,11 @@ static void write_ggtt_rotated_node(struct xe_ggtt *ggtt, struct xe_ggtt_node *n } static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, - const struct i915_gtt_view *view, - struct i915_vma *vma, - unsigned int alignment) + const struct intel_fb_pin_params *pin_params, + struct i915_vma *vma) { struct drm_gem_object *obj = intel_fb_bo(&fb->base); + const struct i915_gtt_view *view = pin_params->view; struct xe_bo *bo = gem_to_xe_bo(obj); struct xe_device *xe = to_xe_device(fb->base.dev); struct xe_tile *tile0 = xe_device_get_root_tile(xe); @@ -319,8 +319,7 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, } static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, - const struct i915_gtt_view *view, - unsigned int alignment) + const struct intel_fb_pin_params *pin_params) { struct drm_device *dev = fb->base.dev; struct xe_device *xe = to_xe_device(dev); @@ -377,9 +376,9 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, vma->bo = bo; if (intel_fb_uses_dpt(&fb->base)) - ret = __xe_pin_fb_vma_dpt(fb, view, vma, alignment); + ret = __xe_pin_fb_vma_dpt(fb, pin_params, vma); else - ret = __xe_pin_fb_vma_ggtt(fb, view, vma, alignment); + ret = __xe_pin_fb_vma_ggtt(fb, pin_params, vma); if (ret) goto err_unpin; @@ -414,16 +413,13 @@ static void __xe_unpin_fb_vma(struct i915_vma *vma) struct i915_vma * intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, - const struct i915_gtt_view *view, - unsigned int alignment, - unsigned int phys_alignment, - unsigned int vtd_guard, + const struct intel_fb_pin_params *pin_params, int *out_fence_id) { if (out_fence_id) *out_fence_id = -1; - return __xe_pin_fb_vma(to_intel_framebuffer(fb), view, alignment); + return __xe_pin_fb_vma(to_intel_framebuffer(fb), pin_params); } void intel_fb_unpin_vma(struct i915_vma *vma, int fence_id) @@ -475,7 +471,10 @@ int intel_plane_pin_fb(struct intel_plane_state *new_plane_state, struct i915_vma *vma; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); - unsigned int alignment = plane->min_alignment(plane, fb, 0); + struct intel_fb_pin_params pin_params = { + .view = &new_plane_state->view.gtt, + .alignment = plane->min_alignment(plane, fb, 0), + }; if (reuse_vma(new_plane_state, old_plane_state)) return 0; @@ -483,7 +482,7 @@ int intel_plane_pin_fb(struct intel_plane_state *new_plane_state, /* We reject creating !SCANOUT fb's, so this is weird.. */ drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_FORCE_WC)); - vma = __xe_pin_fb_vma(intel_fb, &new_plane_state->view.gtt, alignment); + vma = __xe_pin_fb_vma(intel_fb, &pin_params); if (IS_ERR(vma)) return PTR_ERR(vma); diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.c b/drivers/gpu/drm/xe/display/xe_initial_plane.c index 381d68c58463..4f0ad4692ed6 100644 --- a/drivers/gpu/drm/xe/display/xe_initial_plane.c +++ b/drivers/gpu/drm/xe/display/xe_initial_plane.c @@ -134,9 +134,11 @@ xe_initial_plane_setup(struct drm_plane_state *_plane_state, { struct intel_plane_state *plane_state = to_intel_plane_state(_plane_state); struct i915_vma *vma; + struct intel_fb_pin_params pin_params = { + .view = &plane_state->view.gtt, + }; - vma = intel_fb_pin_to_ggtt(fb, &plane_state->view.gtt, - 0, 0, 0, NULL); + vma = intel_fb_pin_to_ggtt(fb, &pin_params, NULL); if (IS_ERR(vma)) return PTR_ERR(vma); From 861e31fb433083ffcc62e1f87f3b694c5fe8a5e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:39 +0300 Subject: [PATCH 106/144] drm/i915: Extract intel_fb_needs_cpu_access() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the naked "does the framebuffer have a clear color plane?" checks with a more abstract helper that simply tells us whether we require CPU access to the framebuffer's memory. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 5 +++++ drivers/gpu/drm/i915/display/intel_fb.h | 1 + drivers/gpu/drm/i915/i915_fb_pin.c | 2 +- drivers/gpu/drm/xe/display/xe_fb_pin.c | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index c4af368deffd..cbeb39ebdb73 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -521,6 +521,11 @@ bool intel_fb_needs_64k_phys(u64 modifier) INTEL_PLANE_CAP_NEED64K_PHYS); } +bool intel_fb_needs_cpu_access(const struct drm_framebuffer *fb) +{ + return intel_fb_rc_ccs_cc_plane(fb) >= 0; +} + /** * intel_fb_is_tile4_modifier: Check if a modifier is a tile4 modifier type * @modifier: Modifier to check diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index fc2c4d59bf06..0a027e2595b2 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -38,6 +38,7 @@ bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier); bool intel_fb_is_mc_ccs_modifier(u64 modifier); bool intel_fb_needs_64k_phys(u64 modifier); bool intel_fb_is_tile4_modifier(u64 modifier); +bool intel_fb_needs_cpu_access(const struct drm_framebuffer *fb); bool intel_fb_is_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane); int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb); diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 4fe6b9859b3f..780be25ad43b 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -61,7 +61,7 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, * ensure it is always in the mappable part of lmem, if this is * a small-bar device. */ - if (intel_fb_rc_ccs_cc_plane(fb) >= 0) + if (intel_fb_needs_cpu_access(fb)) flags &= ~I915_BO_ALLOC_GPU_ONLY; ret = __i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0, flags); diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 58cd527e1fde..205492639dba 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -335,7 +335,7 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, refcount_set(&vma->ref, 1); if (IS_DGFX(to_xe_device(bo->ttm.base.dev)) && - intel_fb_rc_ccs_cc_plane(&fb->base) >= 0 && + intel_fb_needs_cpu_access(&fb->base) && !(bo->flags & XE_BO_FLAG_NEEDS_CPU_ACCESS)) { struct xe_vram_region *vram = xe_device_get_root_tile(xe)->mem.vram; From 2423bd7e73f326c06be883f18e4620a5fd32f467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:40 +0300 Subject: [PATCH 107/144] drm/i915: Introduce pin_params.needs_cpu_lmem_access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new flag pin_params.neeeds_cpu_lmem_access so that the low level pinning code doesn't need to peek into the display driver's framebuffer structure. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb_pin.h | 1 + drivers/gpu/drm/i915/i915_fb_pin.c | 4 +++- drivers/gpu/drm/xe/display/xe_fb_pin.c | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.h b/drivers/gpu/drm/i915/display/intel_fb_pin.h index e6271437459d..bcf5a1f46092 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.h +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.h @@ -19,6 +19,7 @@ struct intel_fb_pin_params { unsigned int alignment; unsigned int phys_alignment; unsigned int vtd_guard; + bool needs_cpu_lmem_access; }; struct i915_vma * diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 780be25ad43b..96ffc4b0d809 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -61,7 +61,7 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, * ensure it is always in the mappable part of lmem, if this is * a small-bar device. */ - if (intel_fb_needs_cpu_access(fb)) + if (pin_params->needs_cpu_lmem_access) flags &= ~I915_BO_ALLOC_GPU_ONLY; ret = __i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0, flags); @@ -275,6 +275,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, .alignment = intel_plane_fb_min_alignment(plane_state), .phys_alignment = intel_plane_fb_min_phys_alignment(plane_state), .vtd_guard = intel_plane_fb_vtd_guard(plane_state), + .needs_cpu_lmem_access = intel_fb_needs_cpu_access(&fb->base), }; int fence_id = -1; @@ -289,6 +290,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, struct intel_fb_pin_params pin_params = { .view = &plane_state->view.gtt, .alignment = intel_plane_fb_min_alignment(plane_state), + .needs_cpu_lmem_access = intel_fb_needs_cpu_access(&fb->base), }; vma = i915_dpt_pin_to_ggtt(fb->dpt, pin_params.alignment / 512); diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 205492639dba..a4eb06cfa769 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -335,7 +335,7 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, refcount_set(&vma->ref, 1); if (IS_DGFX(to_xe_device(bo->ttm.base.dev)) && - intel_fb_needs_cpu_access(&fb->base) && + pin_params->needs_cpu_lmem_access && !(bo->flags & XE_BO_FLAG_NEEDS_CPU_ACCESS)) { struct xe_vram_region *vram = xe_device_get_root_tile(xe)->mem.vram; @@ -474,6 +474,7 @@ int intel_plane_pin_fb(struct intel_plane_state *new_plane_state, struct intel_fb_pin_params pin_params = { .view = &new_plane_state->view.gtt, .alignment = plane->min_alignment(plane, fb, 0), + .needs_cpu_lmem_access = intel_fb_needs_cpu_access(fb), }; if (reuse_vma(new_plane_state, old_plane_state)) From 41ff682e42077084c402fcef31ccde130f6a8d81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:41 +0300 Subject: [PATCH 108/144] drm/i915: Extract intel_plane_needs_low_address() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the naked "gmch? -> need a low ggtt address" check into a more descriptive helper (intel_plane_needs_low_address()). The goal being to eliminate all display specific stuff from the low level pinning code. The actual implementation still abuses PIN_MAPPABLE to achieve this goal. I'm not entire convinced that this whole thing even needs to exist, and the original issue wasn't just caused by some other bug. But no time to dig into it right now, so let's keep going. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_plane.c | 13 +++++++++++++ drivers/gpu/drm/i915/display/intel_plane.h | 2 ++ drivers/gpu/drm/i915/i915_fb_pin.c | 11 ++--------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c index f15dd9e91243..f41f4c2ac320 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.c +++ b/drivers/gpu/drm/i915/display/intel_plane.c @@ -171,6 +171,19 @@ intel_plane_destroy_state(struct drm_plane *plane, kfree(plane_state); } +bool intel_plane_needs_low_address(struct intel_display *display) +{ + /* + * Valleyview is definitely limited to scanning out the first + * 512MiB. Lets presume this behaviour was inherited from the + * g4x display engine and that all earlier gen are similarly + * limited. Testing suggests that it is a little more + * complicated than this. For example, Cherryview appears quite + * happy to scanout from anywhere within its global aperture. + */ + return HAS_GMCH(display); +} + bool intel_plane_needs_physical(struct intel_plane *plane) { struct intel_display *display = to_intel_display(plane); diff --git a/drivers/gpu/drm/i915/display/intel_plane.h b/drivers/gpu/drm/i915/display/intel_plane.h index 5a8f2f3baab5..7fa7fbbb58dc 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.h +++ b/drivers/gpu/drm/i915/display/intel_plane.h @@ -15,6 +15,7 @@ struct drm_rect; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; +struct intel_display; struct intel_dsb; struct intel_plane; struct intel_plane_state; @@ -79,6 +80,7 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state); void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); void intel_plane_helper_add(struct intel_plane *plane); +bool intel_plane_needs_low_address(struct intel_display *display); bool intel_plane_needs_physical(struct intel_plane *plane); void intel_plane_init_cursor_vblank_work(struct intel_plane_state *old_plane_state, struct intel_plane_state *new_plane_state); diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 96ffc4b0d809..a3e5107c12f0 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -140,16 +140,9 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, atomic_inc(&i915->pending_fb_pin); - /* - * Valleyview is definitely limited to scanning out the first - * 512MiB. Lets presume this behaviour was inherited from the - * g4x display engine and that all earlier gen are similarly - * limited. Testing suggests that it is a little more - * complicated than this. For example, Cherryview appears quite - * happy to scanout from anywhere within its global aperture. - */ pinctl = 0; - if (HAS_GMCH(display)) + /* PIN_MAPPABLE limits the address to GMADR size */ + if (intel_plane_needs_low_address(display)) pinctl |= PIN_MAPPABLE; i915_gem_ww_ctx_init(&ww, true); From 19fa21941c00107cefa0cbe962412977e3f9530a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:42 +0300 Subject: [PATCH 109/144] drm/i915: Introduce pin_params.needs_low_address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new flag pin_params.needs_low_address to inform the pinning code that the display needs a low ggtt address. The goal is to eliminate all display specific stuff from the low level pinning code (the direct intel_plane_needs_low_addres()) call in this case). Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb_pin.h | 1 + drivers/gpu/drm/i915/display/intel_fbdev.c | 2 ++ drivers/gpu/drm/i915/i915_fb_pin.c | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.h b/drivers/gpu/drm/i915/display/intel_fb_pin.h index bcf5a1f46092..cf54a96569de 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.h +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.h @@ -20,6 +20,7 @@ struct intel_fb_pin_params { unsigned int phys_alignment; unsigned int vtd_guard; bool needs_cpu_lmem_access; + bool needs_low_address; }; struct i915_vma * diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 136fa827c8f0..4c3e54acde81 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -55,6 +55,7 @@ #include "intel_fb_pin.h" #include "intel_fbdev.h" #include "intel_frontbuffer.h" +#include "intel_plane.h" struct intel_fbdev { struct intel_framebuffer *fb; @@ -314,6 +315,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, pin_params.vtd_guard = intel_fb_view_vtd_guard(&fb->base, &fb->normal_view, DRM_MODE_ROTATE_0); + pin_params.needs_low_address = intel_plane_needs_low_address(display); vma = intel_fb_pin_to_ggtt(&fb->base, &pin_params, NULL); if (IS_ERR(vma)) { diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index a3e5107c12f0..97e4cdfd2447 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -142,7 +142,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, pinctl = 0; /* PIN_MAPPABLE limits the address to GMADR size */ - if (intel_plane_needs_low_address(display)) + if (pin_params->needs_low_address) pinctl |= PIN_MAPPABLE; i915_gem_ww_ctx_init(&ww, true); @@ -256,6 +256,7 @@ intel_plane_fb_vtd_guard(const struct intel_plane_state *plane_state) int intel_plane_pin_fb(struct intel_plane_state *plane_state, const struct intel_plane_state *old_plane_state) { + struct intel_display *display = to_intel_display(plane_state); struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); const struct intel_framebuffer *fb = @@ -269,6 +270,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, .phys_alignment = intel_plane_fb_min_phys_alignment(plane_state), .vtd_guard = intel_plane_fb_vtd_guard(plane_state), .needs_cpu_lmem_access = intel_fb_needs_cpu_access(&fb->base), + .needs_low_address = intel_plane_needs_low_address(display), }; int fence_id = -1; From 08a1df744694556e6d922f695eaaf1fff52d6243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:43 +0300 Subject: [PATCH 110/144] drm/i915: Introduce pin_params.needs_physical MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new flag pin_params.needs_physical to inform the pinning code that the display needs a physical address and not GGTT address. This isn't strictly necessary as the current phys_alignment!=0 check is enough in practice. But theoretically one could have needs_physical==true without any alignment requirements. And having an explicit flag feels a bit less magical. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-8-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb_pin.h | 1 + drivers/gpu/drm/i915/i915_fb_pin.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.h b/drivers/gpu/drm/i915/display/intel_fb_pin.h index cf54a96569de..3e37e9874f50 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.h +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.h @@ -21,6 +21,7 @@ struct intel_fb_pin_params { unsigned int vtd_guard; bool needs_cpu_lmem_access; bool needs_low_address; + bool needs_physical; }; struct i915_vma * diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 97e4cdfd2447..bfe9a5342e13 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -148,7 +148,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, i915_gem_ww_ctx_init(&ww, true); retry: ret = i915_gem_object_lock(obj, &ww); - if (!ret && pin_params->phys_alignment) + if (!ret && pin_params->needs_physical) ret = i915_gem_object_attach_phys(obj, pin_params->phys_alignment); else if (!ret && HAS_LMEM(i915)) ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0); @@ -271,6 +271,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, .vtd_guard = intel_plane_fb_vtd_guard(plane_state), .needs_cpu_lmem_access = intel_fb_needs_cpu_access(&fb->base), .needs_low_address = intel_plane_needs_low_address(display), + .needs_physical = intel_plane_needs_physical(plane), }; int fence_id = -1; From cace3b42072e22332f6ab31a3556da834f62493a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:44 +0300 Subject: [PATCH 111/144] drm/i915: Extract intel_plane_needs_fence() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the naked DISPLAY_VER<4 checks into a descriptive little helper (intel_plane_needs_fence()). And while at it document the reason why the check is what it is. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-9-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 2 +- drivers/gpu/drm/i915/display/intel_plane.c | 9 +++++++++ drivers/gpu/drm/i915/display/intel_plane.h | 1 + drivers/gpu/drm/i915/i915_fb_pin.c | 2 +- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index cbeb39ebdb73..1c0859d5f829 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1287,7 +1287,7 @@ bool intel_plane_uses_fence(const struct intel_plane_state *plane_state) struct intel_display *display = to_intel_display(plane_state); struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - return DISPLAY_VER(display) < 4 || + return intel_plane_needs_fence(display) || (plane->fbc && !plane_state->no_fbc_reason && i915_gtt_view_is_normal(&plane_state->view.gtt)); } diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c index f41f4c2ac320..c2b58d3b9c23 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.c +++ b/drivers/gpu/drm/i915/display/intel_plane.c @@ -192,6 +192,15 @@ bool intel_plane_needs_physical(struct intel_plane *plane) DISPLAY_INFO(display)->cursor_needs_physical; } +bool intel_plane_needs_fence(struct intel_display *display) +{ + /* + * pre-i965 planes use the fence for tiled scanout. + * i965+ planes have their own tiled scanout control bit. + */ + return DISPLAY_VER(display) < 4; +} + bool intel_plane_can_async_flip(struct intel_plane *plane, const struct drm_format_info *info, u64 modifier) diff --git a/drivers/gpu/drm/i915/display/intel_plane.h b/drivers/gpu/drm/i915/display/intel_plane.h index 7fa7fbbb58dc..7b5456f56f42 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.h +++ b/drivers/gpu/drm/i915/display/intel_plane.h @@ -82,6 +82,7 @@ void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, void intel_plane_helper_add(struct intel_plane *plane); bool intel_plane_needs_low_address(struct intel_display *display); bool intel_plane_needs_physical(struct intel_plane *plane); +bool intel_plane_needs_fence(struct intel_display *display); void intel_plane_init_cursor_vblank_work(struct intel_plane_state *old_plane_state, struct intel_plane_state *new_plane_state); int intel_plane_add_affected(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index bfe9a5342e13..a8ed888183cb 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -188,7 +188,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, * mode that matches the user configuration. */ ret = i915_vma_pin_fence(vma); - if (ret != 0 && DISPLAY_VER(display) < 4) { + if (ret != 0 && intel_plane_needs_fence(display)) { i915_vma_unpin(vma); goto err_unpin; } From dfde353a91201f4d6e6dd92f6ff8ab6c3451c002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:45 +0300 Subject: [PATCH 112/144] drm/i915: Introduce pin_params.needs_fence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new flag pin_params.needs_fence to inform the pinning code that the display needs a fence for tiled scanout. The goal is to eliminate all display specific stuff from the low level pinning code. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-10-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb_pin.h | 1 + drivers/gpu/drm/i915/i915_fb_pin.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.h b/drivers/gpu/drm/i915/display/intel_fb_pin.h index 3e37e9874f50..95f83bf7411f 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.h +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.h @@ -22,6 +22,7 @@ struct intel_fb_pin_params { bool needs_cpu_lmem_access; bool needs_low_address; bool needs_physical; + bool needs_fence; }; struct i915_vma * diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index a8ed888183cb..5060ec8c76ca 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -112,7 +112,6 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, const struct intel_fb_pin_params *pin_params, int *out_fence_id) { - struct intel_display *display = to_intel_display(fb->dev); struct drm_i915_private *i915 = to_i915(fb->dev); struct drm_gem_object *_obj = intel_fb_bo(fb); struct drm_i915_gem_object *obj = to_intel_bo(_obj); @@ -188,7 +187,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, * mode that matches the user configuration. */ ret = i915_vma_pin_fence(vma); - if (ret != 0 && intel_plane_needs_fence(display)) { + if (ret != 0 && pin_params->needs_fence) { i915_vma_unpin(vma); goto err_unpin; } @@ -272,6 +271,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, .needs_cpu_lmem_access = intel_fb_needs_cpu_access(&fb->base), .needs_low_address = intel_plane_needs_low_address(display), .needs_physical = intel_plane_needs_physical(plane), + .needs_fence = intel_plane_needs_fence(display), }; int fence_id = -1; From ce2e18a382f3371975adbc9911bb113ec7f544ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:46 +0300 Subject: [PATCH 113/144] drm/xe: Eliminate intel_fb_uses_dpt() call from __xe_pin_fb_vma() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the intel_fb_uses_dpt() out from __xe_pin_fb_vma() into intel_plane_pin_fb() so that we don't do have display stuff that deep in the pinning code. And intel_fb_pin_to_ggtt() can just say "this does not need DPT" always since it's specifically about pinning the fb into GGTT. The previous logic here was kinda insane with the high level code assuming GGTT, and low level code potentially deciding otherwise. In practice it should have been fine because intel_fb_pin_to_ggtt() only gets used from the initial_plane code, and there we are not supposed to be have a framebuffer that needs DPT. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-11-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_fb_pin.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index a4eb06cfa769..44562769fbc9 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -318,7 +318,7 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, return ret; } -static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, +static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, bool is_dpt, const struct intel_fb_pin_params *pin_params) { struct drm_device *dev = fb->base.dev; @@ -375,7 +375,7 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, goto err; vma->bo = bo; - if (intel_fb_uses_dpt(&fb->base)) + if (is_dpt) ret = __xe_pin_fb_vma_dpt(fb, pin_params, vma); else ret = __xe_pin_fb_vma_ggtt(fb, pin_params, vma); @@ -419,7 +419,7 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, if (out_fence_id) *out_fence_id = -1; - return __xe_pin_fb_vma(to_intel_framebuffer(fb), pin_params); + return __xe_pin_fb_vma(to_intel_framebuffer(fb), false, pin_params); } void intel_fb_unpin_vma(struct i915_vma *vma, int fence_id) @@ -483,7 +483,8 @@ int intel_plane_pin_fb(struct intel_plane_state *new_plane_state, /* We reject creating !SCANOUT fb's, so this is weird.. */ drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_FORCE_WC)); - vma = __xe_pin_fb_vma(intel_fb, &pin_params); + vma = __xe_pin_fb_vma(intel_fb, intel_fb_uses_dpt(&intel_fb->base), + &pin_params); if (IS_ERR(vma)) return PTR_ERR(vma); From 4fe8f83264c5e47121725ba0fc4a23bf03fb07cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 16 Apr 2026 20:44:47 +0300 Subject: [PATCH 114/144] drm/i915: Don't pass the framebuffer to low level pinning functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have the pin_params the low level pinning code no longer needs the entire framebuffer structure. The gem object alone (along with the pin_params) is enough. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260416174448.28264-12-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb_pin.h | 4 +-- drivers/gpu/drm/i915/display/intel_fbdev.c | 6 ++-- drivers/gpu/drm/i915/i915_fb_pin.c | 15 ++++------ drivers/gpu/drm/xe/display/xe_fb_pin.c | 28 ++++++++----------- drivers/gpu/drm/xe/display/xe_initial_plane.c | 2 +- 5 files changed, 23 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.h b/drivers/gpu/drm/i915/display/intel_fb_pin.h index 95f83bf7411f..5825503c38ea 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.h +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.h @@ -8,7 +8,7 @@ #include -struct drm_framebuffer; +struct drm_gem_object; struct i915_vma; struct intel_plane_state; struct i915_gtt_view; @@ -26,7 +26,7 @@ struct intel_fb_pin_params { }; struct i915_vma * -intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, +intel_fb_pin_to_ggtt(struct drm_gem_object *obj, const struct intel_fb_pin_params *pin_params, int *out_fence_id); diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 4c3e54acde81..9ab0ac49abb7 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -306,6 +306,8 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, sizes->fb_height = fb->base.height; } + obj = intel_fb_bo(&fb->base); + /* Pin the GGTT vma for our access via info->screen_base. * This also validates that any existing fb inherited from the * BIOS is suitable for own access. @@ -317,7 +319,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, DRM_MODE_ROTATE_0); pin_params.needs_low_address = intel_plane_needs_low_address(display); - vma = intel_fb_pin_to_ggtt(&fb->base, &pin_params, NULL); + vma = intel_fb_pin_to_ggtt(obj, &pin_params, NULL); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_unlock; @@ -328,8 +330,6 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, info->fbops = &intelfb_ops; - obj = intel_fb_bo(&fb->base); - ret = intel_bo_fbdev_fill_info(obj, info, vma); if (ret) goto out_unpin; diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 5060ec8c76ca..b0e121462ca3 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -23,12 +23,10 @@ #include "i915_vma.h" static struct i915_vma * -intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, - struct intel_dpt *dpt, +intel_fb_pin_to_dpt(struct drm_gem_object *_obj, struct intel_dpt *dpt, const struct intel_fb_pin_params *pin_params) { - struct drm_i915_private *i915 = to_i915(fb->dev); - struct drm_gem_object *_obj = intel_fb_bo(fb); + struct drm_i915_private *i915 = to_i915(_obj->dev); struct drm_i915_gem_object *obj = to_intel_bo(_obj); struct i915_address_space *vm = i915_dpt_to_vm(dpt); struct i915_gem_ww_ctx ww; @@ -108,12 +106,11 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb, } struct i915_vma * -intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, +intel_fb_pin_to_ggtt(struct drm_gem_object *_obj, const struct intel_fb_pin_params *pin_params, int *out_fence_id) { - struct drm_i915_private *i915 = to_i915(fb->dev); - struct drm_gem_object *_obj = intel_fb_bo(fb); + struct drm_i915_private *i915 = to_i915(_obj->dev); struct drm_i915_gem_object *obj = to_intel_bo(_obj); intel_wakeref_t wakeref; struct i915_gem_ww_ctx ww; @@ -275,7 +272,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, }; int fence_id = -1; - vma = intel_fb_pin_to_ggtt(&fb->base, &pin_params, + vma = intel_fb_pin_to_ggtt(intel_fb_bo(&fb->base), &pin_params, intel_plane_uses_fence(plane_state) ? &fence_id : NULL); if (IS_ERR(vma)) return PTR_ERR(vma); @@ -295,7 +292,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state, plane_state->ggtt_vma = vma; - vma = intel_fb_pin_to_dpt(&fb->base, fb->dpt, &pin_params); + vma = intel_fb_pin_to_dpt(intel_fb_bo(&fb->base), fb->dpt, &pin_params); if (IS_ERR(vma)) { i915_dpt_unpin_from_ggtt(fb->dpt); plane_state->ggtt_vma = NULL; diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 44562769fbc9..5d7b30f62930 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -139,14 +139,13 @@ write_dpt_remapped(struct xe_bo *bo, } } -static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, +static int __xe_pin_fb_vma_dpt(struct drm_gem_object *obj, const struct intel_fb_pin_params *pin_params, struct i915_vma *vma) { - struct xe_device *xe = to_xe_device(fb->base.dev); + struct xe_device *xe = to_xe_device(obj->dev); struct xe_tile *tile0 = xe_device_get_root_tile(xe); struct xe_ggtt *ggtt = tile0->mem.ggtt; - struct drm_gem_object *obj = intel_fb_bo(&fb->base); const struct i915_gtt_view *view = pin_params->view; struct xe_bo *bo = gem_to_xe_bo(obj), *dpt; u32 dpt_size, size = bo->ttm.base.size; @@ -268,14 +267,13 @@ static void write_ggtt_rotated_node(struct xe_ggtt *ggtt, struct xe_ggtt_node *n rot_info->plane[i].dst_stride); } -static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, +static int __xe_pin_fb_vma_ggtt(struct drm_gem_object *obj, const struct intel_fb_pin_params *pin_params, struct i915_vma *vma) { - struct drm_gem_object *obj = intel_fb_bo(&fb->base); const struct i915_gtt_view *view = pin_params->view; struct xe_bo *bo = gem_to_xe_bo(obj); - struct xe_device *xe = to_xe_device(fb->base.dev); + struct xe_device *xe = to_xe_device(obj->dev); struct xe_tile *tile0 = xe_device_get_root_tile(xe); struct xe_ggtt *ggtt = tile0->mem.ggtt; u64 pte, size; @@ -318,13 +316,11 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, return ret; } -static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, bool is_dpt, +static struct i915_vma *__xe_pin_fb_vma(struct drm_gem_object *obj, bool is_dpt, const struct intel_fb_pin_params *pin_params) { - struct drm_device *dev = fb->base.dev; - struct xe_device *xe = to_xe_device(dev); + struct xe_device *xe = to_xe_device(obj->dev); struct i915_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL); - struct drm_gem_object *obj = intel_fb_bo(&fb->base); struct xe_bo *bo = gem_to_xe_bo(obj); struct xe_validation_ctx ctx; struct drm_exec exec; @@ -376,9 +372,9 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb, bool vma->bo = bo; if (is_dpt) - ret = __xe_pin_fb_vma_dpt(fb, pin_params, vma); + ret = __xe_pin_fb_vma_dpt(obj, pin_params, vma); else - ret = __xe_pin_fb_vma_ggtt(fb, pin_params, vma); + ret = __xe_pin_fb_vma_ggtt(obj, pin_params, vma); if (ret) goto err_unpin; @@ -412,14 +408,14 @@ static void __xe_unpin_fb_vma(struct i915_vma *vma) } struct i915_vma * -intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb, +intel_fb_pin_to_ggtt(struct drm_gem_object *obj, const struct intel_fb_pin_params *pin_params, int *out_fence_id) { if (out_fence_id) *out_fence_id = -1; - return __xe_pin_fb_vma(to_intel_framebuffer(fb), false, pin_params); + return __xe_pin_fb_vma(obj, false, pin_params); } void intel_fb_unpin_vma(struct i915_vma *vma, int fence_id) @@ -469,7 +465,6 @@ int intel_plane_pin_fb(struct intel_plane_state *new_plane_state, struct drm_gem_object *obj = intel_fb_bo(fb); struct xe_bo *bo = gem_to_xe_bo(obj); struct i915_vma *vma; - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane); struct intel_fb_pin_params pin_params = { .view = &new_plane_state->view.gtt, @@ -483,8 +478,7 @@ int intel_plane_pin_fb(struct intel_plane_state *new_plane_state, /* We reject creating !SCANOUT fb's, so this is weird.. */ drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_FORCE_WC)); - vma = __xe_pin_fb_vma(intel_fb, intel_fb_uses_dpt(&intel_fb->base), - &pin_params); + vma = __xe_pin_fb_vma(obj, intel_fb_uses_dpt(fb), &pin_params); if (IS_ERR(vma)) return PTR_ERR(vma); diff --git a/drivers/gpu/drm/xe/display/xe_initial_plane.c b/drivers/gpu/drm/xe/display/xe_initial_plane.c index 4f0ad4692ed6..8e3c0c4b81fe 100644 --- a/drivers/gpu/drm/xe/display/xe_initial_plane.c +++ b/drivers/gpu/drm/xe/display/xe_initial_plane.c @@ -138,7 +138,7 @@ xe_initial_plane_setup(struct drm_plane_state *_plane_state, .view = &plane_state->view.gtt, }; - vma = intel_fb_pin_to_ggtt(fb, &pin_params, NULL); + vma = intel_fb_pin_to_ggtt(intel_fb_bo(fb), &pin_params, NULL); if (IS_ERR(vma)) return PTR_ERR(vma); From 07095bb7ea730538c1cd92ca666a192c46977b03 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 15 Apr 2026 14:51:03 +0300 Subject: [PATCH 115/144] drm/i915/ddi: add wrapper for calling ->get_buf_trans() hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add intel_ddi_buf_trans_get() wrapper for calling the encoder->get_buf_trans() hooks, allowing for a centralized place to e.g. check for VBT overrides for the buf translations. Cc: Michał Grzelak Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260415115104.1721008-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 2 +- drivers/gpu/drm/i915/display/intel_ddi.c | 16 ++++++++-------- .../gpu/drm/i915/display/intel_ddi_buf_trans.c | 7 +++++++ .../gpu/drm/i915/display/intel_ddi_buf_trans.h | 3 +++ drivers/gpu/drm/i915/display/intel_dpio_phy.c | 2 +- drivers/gpu/drm/i915/display/intel_fdi.c | 3 ++- drivers/gpu/drm/i915/display/intel_lt_phy.c | 2 +- drivers/gpu/drm/i915/display/intel_snps_phy.c | 2 +- 8 files changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 7e59409bbf01..d832e44ef62a 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -492,7 +492,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, wakeref = intel_cx0_phy_transaction_begin(encoder); - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) { intel_cx0_phy_transaction_end(encoder, wakeref); return; diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 178074316a2c..2681940a5cfe 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -140,7 +140,7 @@ void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder, enum port port = encoder->port; const struct intel_ddi_buf_trans *trans; - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) return; @@ -172,7 +172,7 @@ static void hsw_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder, enum port port = encoder->port; const struct intel_ddi_buf_trans *trans; - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) return; @@ -1106,7 +1106,7 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder, const struct intel_ddi_buf_trans *trans; int n_entries; - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) return; @@ -1132,7 +1132,7 @@ static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp, struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; int n_entries; - encoder->get_buf_trans(encoder, crtc_state, &n_entries); + intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON(display->drm, n_entries < 1)) n_entries = 1; @@ -1175,7 +1175,7 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, int n_entries, ln; u32 val; - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) return; @@ -1293,7 +1293,7 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder))) return; - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) return; @@ -1394,7 +1394,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder))) return; - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) return; @@ -1511,7 +1511,7 @@ int intel_ddi_level(struct intel_encoder *encoder, const struct intel_ddi_buf_trans *trans; int level, n_entries; - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) return 0; diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c index 980ab19868b3..4cd1e4d76c7a 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -1852,3 +1852,10 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder) MISSING_CASE(pdev->device); } } + +const struct intel_ddi_buf_trans *intel_ddi_buf_trans_get(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + return encoder->get_buf_trans(encoder, crtc_state, n_entries); +} diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h index cec332090a20..9698697f3917 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h @@ -77,5 +77,8 @@ struct intel_ddi_buf_trans { bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table); void intel_ddi_buf_trans_init(struct intel_encoder *encoder); +const struct intel_ddi_buf_trans * +intel_ddi_buf_trans_get(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, int *n_entries); #endif diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 0e16132d0923..68802b652316 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -301,7 +301,7 @@ void bxt_dpio_phy_set_signal_levels(struct intel_encoder *encoder, enum dpio_phy phy; int lane, n_entries; - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) return; diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index 24ce8a7842c7..917f020650af 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -11,6 +11,7 @@ #include "intel_atomic.h" #include "intel_crtc.h" #include "intel_ddi.h" +#include "intel_ddi_buf_trans.h" #include "intel_de.h" #include "intel_display_regs.h" #include "intel_display_types.h" @@ -852,7 +853,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder, u32 temp, i, rx_ctl_val; int n_entries; - encoder->get_buf_trans(encoder, crtc_state, &n_entries); + intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); hsw_prepare_dp_ddi_buffers(encoder, crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.c b/drivers/gpu/drm/i915/display/intel_lt_phy.c index 657ad5cb0eff..e2f9e1a2745f 100644 --- a/drivers/gpu/drm/i915/display/intel_lt_phy.c +++ b/drivers/gpu/drm/i915/display/intel_lt_phy.c @@ -2135,7 +2135,7 @@ void intel_lt_phy_set_signal_levels(struct intel_encoder *encoder, wakeref = intel_lt_phy_transaction_begin(encoder); - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) { intel_lt_phy_transaction_end(encoder, wakeref); return; diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index 295030742294..5e5dde8f3e3a 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -72,7 +72,7 @@ void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder, enum phy phy = intel_encoder_to_phy(encoder); int n_entries, ln; - trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); + trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(display->drm, !trans)) return; From e3507e53562fd0e2483a61f68acf1ae5fc698ce0 Mon Sep 17 00:00:00 2001 From: Desnes Nunes Date: Thu, 23 Apr 2026 17:10:20 -0300 Subject: [PATCH 116/144] drm/i915/dmc: use display instead of dereferencing dmc in intel_dmc_update_dc6_allowed_count() There is no need for dereferencing the dmc pointer if the display is already in the scope of intel_dmc_update_dc6_allowed_count function. No functional change. Signed-off-by: Desnes Nunes Link: https://patch.msgid.link/20260423201020.506908-1-desnesn@redhat.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 2104164e136e..0df4f42ba3e3 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -1582,10 +1582,10 @@ void intel_dmc_update_dc6_allowed_count(struct intel_display *display, struct intel_dmc *dmc = display_to_dmc(display); u32 dc5_cur_count; - if (DISPLAY_VER(dmc->display) < 14) + if (DISPLAY_VER(display) < 14) return; - dc5_cur_count = intel_de_read(dmc->display, DG1_DMC_DEBUG_DC5_COUNT); + dc5_cur_count = intel_de_read(display, DG1_DMC_DEBUG_DC5_COUNT); if (!start_tracking) dmc->dc6_allowed.count += dc5_cur_count - dmc->dc6_allowed.dc5_start; From 28ecf45468514483131f1ba411c0fb6c94580f1a Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Thu, 23 Apr 2026 13:33:55 +0530 Subject: [PATCH 117/144] drm/i915/dp: Change drm_err to drm_dbg_kms Change the drm_err to drm_dbg_kms when we fail to read the FEC capability. This is mainly because this is called from intel_dp_detect. Which ends up in race more frequently in case of MST scenarios, when we are disabling streams but the downstream Dock still sends signals which causes intel_dp_detect to be invoked which has DPCD reads. These pass until the Transcoder and DPLL go down causing AUX to go down too. At this point AUX Timeouts are expected and not an issue. But this drm_err gets flagged in CI causing noise even for passing scenarios. Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy Link: https://patch.msgid.link/20260423080355.2744117-1-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 35b8fb5740aa..8631df908b07 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4564,7 +4564,7 @@ void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, if (drm_dp_dpcd_readb(connector->dp.dsc_decompression_aux, DP_FEC_CAPABILITY, &connector->dp.fec_capability) < 0) { - drm_err(display->drm, "Failed to read FEC DPCD register\n"); + drm_dbg_kms(display->drm, "Could not read FEC DPCD register\n"); return; } From 60656fa8feb07bc767cb3cce1ae40d1d560f8b06 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Fri, 24 Apr 2026 14:39:40 +0530 Subject: [PATCH 118/144] drm/i915/vrr: Avoid vrr for PCON with HDMI2.1 sink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we do not support VRR with HDMI so skip vrr compute config step for all DP branch devices. v2: Restrict VRR on all DP branch devices instead for checking only for HDMI. (Ville) Signed-off-by: Ankit Nautiyal Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/20260424090942.3060291-2-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_vrr.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index fae1186a90b2..1b09992ce9fd 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -55,6 +55,16 @@ bool intel_vrr_is_capable(struct intel_connector *connector) if (connector->mst.dp) return false; intel_dp = intel_attached_dp(connector); + /* + * Among non-MST DP branch devices, only an HDMI 2.1 sink connected + * via a PCON could support VRR. However, supporting VRR through a + * PCON requires non-trivial changes that are not implemented yet. + * Until that support exists, avoid VRR on all DP branch devices. + * + * TODO: Add support for VRR for DP->HDMI 2.1 PCON. + */ + if (drm_dp_is_branch(intel_dp->dpcd)) + return false; if (!drm_dp_sink_can_do_video_without_timing_msa(intel_dp->dpcd)) return false; From e2b3b2e8fa9831d54d6638c3e7e3d5cc1ea4a493 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Fri, 24 Apr 2026 14:39:41 +0530 Subject: [PATCH 119/144] drm/i915/dp: Add a helper to decide if AS SDP can be used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper that determines whether AS SDP can be used for the current DP configuration. For now this is true only when the sink supports AS SDP and VRR is enabled, but more conditions may be added later. v2: - Rename to intel_dp_needs_as_sdp(). (Ville) - Add a #FIXME documenting non-atomic of DP SDP updates. (Ville) Signed-off-by: Ankit Nautiyal Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/20260424090942.3060291-3-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 8631df908b07..8f2cd603f52a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3168,6 +3168,15 @@ static void intel_dp_compute_vsc_colorimetry(const struct intel_crtc_state *crtc vsc->content_type = DP_CONTENT_TYPE_NOT_DEFINED; } +static bool intel_dp_needs_as_sdp(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) +{ + if (!intel_dp->as_sdp_supported) + return false; + + return crtc_state->vrr.enable; +} + static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state) { @@ -3175,7 +3184,12 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - if (!crtc_state->vrr.enable || !intel_dp->as_sdp_supported) + /* + * #FIXME: SDP/infoframe updates aren’t truly atomic, and with the new + * cdclk->tc clock crossing we may transiently send a corrupted packet + * if the update lands mid‑transmission. + */ + if (!intel_dp_needs_as_sdp(intel_dp, crtc_state)) return; crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); From 9584c9a5cabef9b1694bc7e20ba7b99b3b41a8bd Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Fri, 24 Apr 2026 14:39:42 +0530 Subject: [PATCH 120/144] drm/i915/dp: Skip AS SDP for DP branch devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, VRR is not implmented for DP branch devices. So skip sending AS SDP for them. Signed-off-by: Ankit Nautiyal Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/20260424090942.3060291-4-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 8f2cd603f52a..98df93884e9a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3174,6 +3174,12 @@ static bool intel_dp_needs_as_sdp(struct intel_dp *intel_dp, if (!intel_dp->as_sdp_supported) return false; + /* + * #TODO Implement AS SDP for DP branch device. + */ + if (drm_dp_is_branch(intel_dp->dpcd)) + return false; + return crtc_state->vrr.enable; } From aee13ba1448213975f36942ba5d1ce693eb5c002 Mon Sep 17 00:00:00 2001 From: Juha-Pekka Heikkila Date: Mon, 27 Apr 2026 19:57:15 +0300 Subject: [PATCH 121/144] drm/i915/display: enable ccs modifiers on dg2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since Xe driver aux ccs enablement dg2 ccs modifiers have been disabled on i915 driver. Here allow dg2 to use ccs again for framebuffers. Fixes: 6a99e91a6ca8 ("drm/i915/display: Detect AuxCCS support via display parent interface") Signed-off-by: Juha-Pekka Heikkila Reviewed-by: Ville Syrjälä Signed-off-by: Mika Kahola Link: https://patch.msgid.link/20260427165715.864721-1-juhapekka.heikkila@gmail.com --- drivers/gpu/drm/i915/i915_driver.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index d31819758f3d..a4bd4f8e18b2 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -750,9 +750,8 @@ static bool has_auxccs(struct drm_device *drm) { struct drm_i915_private *i915 = to_i915(drm); - return IS_GRAPHICS_VER(i915, 9, 12) || - IS_ALDERLAKE_P(i915) || - IS_METEORLAKE(i915); + return IS_GRAPHICS_VER(i915, 9, 12) && + !HAS_FLAT_CCS(i915); } static bool has_fenced_regions(struct drm_device *drm) From 16df4cc63c58b6ae4dc794edcc2661c5dddc3596 Mon Sep 17 00:00:00 2001 From: Vidya Srinivas Date: Wed, 15 Apr 2026 22:28:49 +0530 Subject: [PATCH 122/144] drm/i915/display: Use ceiling division for NV12 UV surface offset calculation For LNL+, odd source size and panning for YUV 422/420 surfaces is supported. However, it requires the UV (chroma) surface Start X/Y and width/height to be calculated as ceiling(half of Y plane value) rather than floor. The current code uses (>> 17) which combines the U16.16 fixed-point to integer conversion (>> 16) with a divide-by-2 for chroma subsampling (>> 1) into a single floor division. For odd Y plane values this produces an off-by-one error in the UV plane offset. On Android systems we see PLANE ATS fault when NV12 overlays are used with odd source dimensions: [ 126.854200] xe 0000:00:02.0: [drm:intel_atomic_setup_scaler [xe]] [CRTC:148:pipe A] attached scaler id 0.0 to PLANE:33 [ 126.854617] xe 0000:00:02.0: [drm:skl_update_scaler [xe]] [CRTC:148:pipe A] scaler_user index 0.0: staged scaling request for 1279x719->1340x753 [ 126.854837] xe 0000:00:02.0: [drm:intel_plane_atomic_check [xe]] UV plane [PLANE:33:plane 1A] using Y plane [PLANE:123:plane 4A] [ 126.854926] xe 0000:00:02.0: [drm] *ERROR* [CRTC:148:pipe A] PLANE ATS fault With Y plane width 1279: floor(1279/2) = 639 (current) ceil(1279/2) = 640 (required) Introduce fp_16_16_div2() and fp_16_16_to_int_ceil() helpers to cleanly separate the two operations: first halve the U16.16 fixed-point value for chroma subsampling (staying in fixed-point domain), then convert to integer with ceiling rounding. v2: Use DIV_ROUND_UP(value, 1 << 17) to preserve sub-pixel precision while making the ceiling division readable (Jani, Uma) v3: Split into two helpers - fp_16_16_div2() for fixed-point division by 2 and fp_16_16_to_int_ceil() for ceiling conversion to integer, cleanly separating chroma subsampling from fixed-point to integer conversion (Jani) Signed-off-by: Vidya Srinivas Reviewed-by: Juha-Pekka Heikkila Signed-off-by: Mika Kahola Link: https://patch.msgid.link/20260415165849.187693-1-vidya.srinivas@intel.com --- .../drm/i915/display/skl_universal_plane.c | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 5aef8123d8b8..ef431dd32e74 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2126,6 +2126,19 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) return 0; } + +/* Divide a U16.16 fixed-point value by 2, staying in fixed-point domain */ +static inline u32 fp_16_16_div2(u32 fp) +{ + return fp >> 1; +} + +/* Convert a U16.16 fixed-point value to integer, rounding up */ +static inline int fp_16_16_to_int_ceil(u32 fp) +{ + return DIV_ROUND_UP(fp, 1 << 16); +} + static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) { struct intel_display *display = to_intel_display(plane_state); @@ -2139,10 +2152,16 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) int min_height = intel_plane_min_height(plane, fb, uv_plane, rotation); int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation); int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation); - int x = plane_state->uapi.src.x1 >> 17; - int y = plane_state->uapi.src.y1 >> 17; - int w = drm_rect_width(&plane_state->uapi.src) >> 17; - int h = drm_rect_height(&plane_state->uapi.src) >> 17; + + /* + * LNL+ UV surface start/size = + * ceiling(half of Y plane start/size). Use ceiling division + * unconditionally; it is a no-op for even values. + */ + int x = fp_16_16_to_int_ceil(fp_16_16_div2(plane_state->uapi.src.x1)); + int y = fp_16_16_to_int_ceil(fp_16_16_div2(plane_state->uapi.src.y1)); + int w = fp_16_16_to_int_ceil(fp_16_16_div2(drm_rect_width(&plane_state->uapi.src))); + int h = fp_16_16_to_int_ceil(fp_16_16_div2(drm_rect_height(&plane_state->uapi.src))); u32 offset; /* FIXME not quite sure how/if these apply to the chroma plane */ From cb8d155b0806553badbb3e9a56abcd35b563421e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Mon, 27 Apr 2026 16:05:54 +0300 Subject: [PATCH 123/144] drm/i915/psr: Disable Panel Replay on Dell XPS 16 DA16260 as a quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are observing same problems with Dell XPS 16 DA16260 as we saw with XPS 14 DA16260. This device seem to have also LGD panel with same feature as in XPS 14. Due to this disable Panel Replay as a quirk on this setup as well. Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/7682 Signed-off-by: Jouni Högander Reviewed-by: Mika Kahola Link: https://patch.msgid.link/20260427130554.86040-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_quirks.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c index 883f297d4b83..b6e840bffd44 100644 --- a/drivers/gpu/drm/i915/display/intel_quirks.c +++ b/drivers/gpu/drm/i915/display/intel_quirks.c @@ -269,6 +269,14 @@ static const struct intel_dpcd_quirk intel_dpcd_quirks[] = { .sink_oui = SINK_OUI(0x00, 0x22, 0xb9), .hook = quirk_disable_edp_panel_replay, }, + /* Dell XPS 16 DA16260 */ + { + .device = DEVICE_ID_ANY, + .subsystem_vendor = 0x1028, + .subsystem_device = 0x0dba, + .sink_oui = SINK_OUI(0x00, 0x22, 0xb9), + .hook = quirk_disable_edp_panel_replay, + }, }; void intel_init_quirks(struct intel_display *display) From 5e79af5db00b2a5f4667aaf16cfe4ecb7759383b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Fri, 17 Apr 2026 13:23:50 +0300 Subject: [PATCH 124/144] drm/i915/psr: Disable PSR2 on Xiaomi Book Pro 14 2026 as a quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new quirk (QUIRK_DISABLE_PSR2) for disabling PSR2 as a quirk for problematic setups. Apply this newly added quirk on Xiaomi Book Pro 14 2026. v2: logging adjusted Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/7677 Signed-off-by: Jouni Högander Acked-by: Jani Nikula Reviewed-by: Mika Kahola Link: https://patch.msgid.link/20260417102350.28328-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 3 +++ drivers/gpu/drm/i915/display/intel_quirks.c | 9 +++++++++ drivers/gpu/drm/i915/display/intel_quirks.h | 1 + 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 63c19958a9e3..d1bae7d32617 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -695,6 +695,9 @@ static void _psr_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *co connector->dp.psr_caps.sync_latency = intel_dp_get_sink_sync_latency(intel_dp); + if (intel_has_quirk(display, QUIRK_DISABLE_PSR2)) + return; + if (DISPLAY_VER(display) >= 9 && connector->dp.psr_caps.dpcd[0] >= DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) { bool y_req = connector->dp.psr_caps.dpcd[1] & diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c index b6e840bffd44..33245f44c0d5 100644 --- a/drivers/gpu/drm/i915/display/intel_quirks.c +++ b/drivers/gpu/drm/i915/display/intel_quirks.c @@ -94,6 +94,12 @@ static void quirk_disable_edp_panel_replay(struct intel_dp *intel_dp) drm_info(display->drm, "Applying disable Panel Replay quirk\n"); } +static void quirk_disable_psr2(struct intel_display *display) +{ + intel_set_quirk(display, QUIRK_DISABLE_PSR2); + drm_info(display->drm, "PSR2 support not currently available for this setup, applying disable PSR2 quirk\n"); +} + struct intel_quirk { int device; int subsystem_vendor; @@ -250,6 +256,9 @@ static struct intel_quirk intel_quirks[] = { /* Dell XPS 13 7390 2-in-1 */ { 0x8a52, 0x1028, 0x08b0, quirk_edp_limit_rate_hbr2 }, + + /* Xiaomi Book Pro 14 2026 */ + { 0xb081, 0x1d72, 0x2424, quirk_disable_psr2 }, }; static const struct intel_dpcd_quirk intel_dpcd_quirks[] = { diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h b/drivers/gpu/drm/i915/display/intel_quirks.h index 83214eb94b0c..970a4fe52faf 100644 --- a/drivers/gpu/drm/i915/display/intel_quirks.h +++ b/drivers/gpu/drm/i915/display/intel_quirks.h @@ -22,6 +22,7 @@ enum intel_quirk_id { QUIRK_FW_SYNC_LEN, QUIRK_EDP_LIMIT_RATE_HBR2, QUIRK_DISABLE_EDP_PANEL_REPLAY, + QUIRK_DISABLE_PSR2, }; void intel_init_quirks(struct intel_display *display); From d08e46efae16b607f13d95a4cd5b84a958b7e995 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Wed, 29 Apr 2026 09:56:50 +0530 Subject: [PATCH 125/144] drm/i915/display: Avoid stale PIPE_SCANLINE values after crtc_enable When a CRTC is moved to a different transcoder (e.g. on DP-MST stream allocation), PIPE_SCANLINE and PIPE_FRMCNT can return values latched from the previous transcoder/mode for up to one vblank period after the new pipe is enabled. The vblank evasion code in intel_pipe_update_start()/end() then samples a stale or boundary scanline and the frame counter ticks during the critical section, producing diagnostic errors of the form: [243.348405] xe 0000:00:02.0: [drm] *ERROR* Atomic update failure on pipe B (start=300 end=301) time 61 us, min 2128, max 2161, scanline start 1200, end 2165 [248.536260] xe 0000:00:02.0: [drm] *ERROR* Atomic update failure on pipe B (start=561 end=562) time 61 us, min 2128, max 2161, scanline start 2162, end 2167 Here "scanline start 1200" is the vblank_start of a previously programmed mode on a different transcoder, while "2162" is the current mode's vblank_start sampled before any real frame has been emitted. Both indicate a stale read rather than a real evasion miss. Wait for one vblank after crtc_enable() to give the new transcoder a chance to start producing live PIPE_SCANLINE/FRMCNT values before any subsequent atomic commit enters the vblank evasion section. This adds at most one frame of latency on modeset, which is invisible to users. Reproduced with igt@kms_rotation_crc@sprite-rotation-180 on a DP-MST sink; with this patch the failures no longer occur. Signed-off-by: Suraj Kandpal Reviewed-by: Pranay Samala Link: https://patch.msgid.link/20260429042650.3335718-1-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 674a4ece6d0f..8ebd0df25c11 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6741,6 +6741,8 @@ static void intel_enable_crtc(struct intel_atomic_state *state, display->funcs.display->crtc_enable(state, crtc); + intel_crtc_wait_for_next_vblank(crtc); + /* vblanks work again, re-enable pipe CRC. */ intel_crtc_enable_pipe_crc(crtc); } From b78477318593141adffc667e3d02aeb891baf38e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 Apr 2026 11:28:45 +0300 Subject: [PATCH 126/144] drm/i915/display: move audio funcs under audio sub-struct Move audio related functions under audio sub-struct of struct intel_display. The funcs sub-struct of struct intel_display seems unnecessary. Instead of display->funcs.FEATURE, prefer display->FEATURE.funcs. Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/60d626286b77c2faa9ff0518855dd083906b24be.1777537663.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_audio.c | 22 ++++++++----------- .../gpu/drm/i915/display/intel_display_core.h | 6 ++--- .../gpu/drm/i915/display/intel_display_irq.c | 4 ++++ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 081627e0d917..2a6476ccc85b 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -754,10 +754,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, crtc->base.base.id, crtc->base.name, drm_eld_size(crtc_state->eld)); - if (display->funcs.audio) - display->funcs.audio->audio_codec_enable(encoder, - crtc_state, - conn_state); + if (display->audio.funcs) + display->audio.funcs->audio_codec_enable(encoder, crtc_state, conn_state); mutex_lock(&display->audio.mutex); @@ -813,10 +811,8 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, encoder->base.base.id, encoder->base.name, crtc->base.base.id, crtc->base.name); - if (display->funcs.audio) - display->funcs.audio->audio_codec_disable(encoder, - old_crtc_state, - old_conn_state); + if (display->audio.funcs) + display->audio.funcs->audio_codec_disable(encoder, old_crtc_state, old_conn_state); mutex_lock(&display->audio.mutex); @@ -864,8 +860,8 @@ void intel_audio_codec_get_config(struct intel_encoder *encoder, if (!crtc_state->has_audio) return; - if (display->funcs.audio) - display->funcs.audio->audio_codec_get_config(encoder, crtc_state); + if (display->audio.funcs) + display->audio.funcs->audio_codec_get_config(encoder, crtc_state); } static const struct intel_audio_funcs g4x_audio_funcs = { @@ -893,12 +889,12 @@ static const struct intel_audio_funcs hsw_audio_funcs = { void intel_audio_hooks_init(struct intel_display *display) { if (display->platform.g4x) - display->funcs.audio = &g4x_audio_funcs; + display->audio.funcs = &g4x_audio_funcs; else if (display->platform.valleyview || display->platform.cherryview || HAS_PCH_CPT(display) || HAS_PCH_IBX(display)) - display->funcs.audio = &ibx_audio_funcs; + display->audio.funcs = &ibx_audio_funcs; else if (display->platform.haswell || DISPLAY_VER(display) >= 8) - display->funcs.audio = &hsw_audio_funcs; + display->audio.funcs = &hsw_audio_funcs; } struct aud_ts_cdclk_m_n { diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index c5a07090cba6..c61990ca9e29 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -100,6 +100,9 @@ struct intel_audio_state { }; struct intel_audio { + /* internal display audio functions */ + const struct intel_audio_funcs *funcs; + /* hda/i915 audio component */ struct i915_audio_component *component; bool component_registered; @@ -319,9 +322,6 @@ struct intel_display { /* Display internal color functions */ const struct intel_color_funcs *color; - - /* Display internal audio functions */ - const struct intel_audio_funcs *audio; } funcs; struct { diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index 70c1bba7c0a8..b5bfdebc66ca 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -2458,6 +2458,10 @@ void dg1_de_irq_postinstall(struct intel_display *display) intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE); } +struct intel_display_irq_funcs { + void (*reset)(struct intel_display *display); +}; + void intel_display_irq_init(struct intel_display *display) { spin_lock_init(&display->irq.lock); From 51da56f77332bb3cd5cbcb0a1c66ff043d5736a7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 Apr 2026 11:28:46 +0300 Subject: [PATCH 127/144] drm/i915/display: move color funcs under color sub-struct Move color related functions under color sub-struct of struct intel_display. The funcs sub-struct of struct intel_display seems unnecessary. Instead of display->funcs.FEATURE, prefer display->FEATURE.funcs. Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/77cc5dd365f3346c4cbbe7a5d883bca413138c94.1777537663.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_color.c | 58 +++++++++---------- .../gpu/drm/i915/display/intel_display_core.h | 6 +- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index e7950655434b..0531c60e5e5d 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1933,7 +1933,7 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state) if (crtc_state->dsb_color) return; - display->funcs.color->load_luts(crtc_state); + display->color.funcs->load_luts(crtc_state); } void intel_color_commit_noarm(struct intel_dsb *dsb, @@ -1941,8 +1941,8 @@ void intel_color_commit_noarm(struct intel_dsb *dsb, { struct intel_display *display = to_intel_display(crtc_state); - if (display->funcs.color->color_commit_noarm) - display->funcs.color->color_commit_noarm(dsb, crtc_state); + if (display->color.funcs->color_commit_noarm) + display->color.funcs->color_commit_noarm(dsb, crtc_state); } void intel_color_commit_arm(struct intel_dsb *dsb, @@ -1950,15 +1950,15 @@ void intel_color_commit_arm(struct intel_dsb *dsb, { struct intel_display *display = to_intel_display(crtc_state); - display->funcs.color->color_commit_arm(dsb, crtc_state); + display->color.funcs->color_commit_arm(dsb, crtc_state); } void intel_color_post_update(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - if (display->funcs.color->color_post_update) - display->funcs.color->color_post_update(crtc_state); + if (display->color.funcs->color_post_update) + display->color.funcs->color_post_update(crtc_state); } void intel_color_modeset(const struct intel_crtc_state *crtc_state) @@ -2022,7 +2022,7 @@ void intel_color_prepare_commit(struct intel_atomic_state *state, if (!intel_color_uses_dsb(crtc_state)) return; - display->funcs.color->load_luts(crtc_state); + display->color.funcs->load_luts(crtc_state); if (crtc_state->use_dsb && intel_color_uses_chained_dsb(crtc_state)) { intel_vrr_send_push(crtc_state->dsb_color, crtc_state); @@ -2113,19 +2113,19 @@ int intel_color_check(struct intel_atomic_state *state, if (!intel_crtc_needs_color_update(new_crtc_state)) return 0; - return display->funcs.color->color_check(state, crtc); + return display->color.funcs->color_check(state, crtc); } void intel_color_get_config(struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - display->funcs.color->get_config(crtc_state); + display->color.funcs->get_config(crtc_state); - display->funcs.color->read_luts(crtc_state); + display->color.funcs->read_luts(crtc_state); - if (display->funcs.color->read_csc) - display->funcs.color->read_csc(crtc_state); + if (display->color.funcs->read_csc) + display->color.funcs->read_csc(crtc_state); } bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, @@ -2142,7 +2142,7 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, if (!is_pre_csc_lut && crtc_state->c8_planes) return true; - return display->funcs.color->lut_equal(crtc_state, blob1, blob2, + return display->color.funcs->lut_equal(crtc_state, blob1, blob2, is_pre_csc_lut); } @@ -4253,8 +4253,8 @@ intel_color_load_plane_csc_matrix(struct intel_dsb *dsb, { struct intel_display *display = to_intel_display(plane_state); - if (display->funcs.color->load_plane_csc_matrix) - display->funcs.color->load_plane_csc_matrix(dsb, plane_state); + if (display->color.funcs->load_plane_csc_matrix) + display->color.funcs->load_plane_csc_matrix(dsb, plane_state); } static void @@ -4263,8 +4263,8 @@ intel_color_load_plane_luts(struct intel_dsb *dsb, { struct intel_display *display = to_intel_display(plane_state); - if (display->funcs.color->load_plane_luts) - display->funcs.color->load_plane_luts(dsb, plane_state); + if (display->color.funcs->load_plane_luts) + display->color.funcs->load_plane_luts(dsb, plane_state); } bool @@ -4346,29 +4346,29 @@ void intel_color_init_hooks(struct intel_display *display) { if (HAS_GMCH(display)) { if (display->platform.cherryview) - display->funcs.color = &chv_color_funcs; + display->color.funcs = &chv_color_funcs; else if (display->platform.valleyview) - display->funcs.color = &vlv_color_funcs; + display->color.funcs = &vlv_color_funcs; else if (DISPLAY_VER(display) >= 4) - display->funcs.color = &i965_color_funcs; + display->color.funcs = &i965_color_funcs; else - display->funcs.color = &i9xx_color_funcs; + display->color.funcs = &i9xx_color_funcs; } else { if (DISPLAY_VER(display) >= 12) - display->funcs.color = &tgl_color_funcs; + display->color.funcs = &tgl_color_funcs; else if (DISPLAY_VER(display) == 11) - display->funcs.color = &icl_color_funcs; + display->color.funcs = &icl_color_funcs; else if (DISPLAY_VER(display) == 10) - display->funcs.color = &glk_color_funcs; + display->color.funcs = &glk_color_funcs; else if (DISPLAY_VER(display) == 9) - display->funcs.color = &skl_color_funcs; + display->color.funcs = &skl_color_funcs; else if (DISPLAY_VER(display) == 8) - display->funcs.color = &bdw_color_funcs; + display->color.funcs = &bdw_color_funcs; else if (display->platform.haswell) - display->funcs.color = &hsw_color_funcs; + display->color.funcs = &hsw_color_funcs; else if (DISPLAY_VER(display) == 7) - display->funcs.color = &ivb_color_funcs; + display->color.funcs = &ivb_color_funcs; else - display->funcs.color = &ilk_color_funcs; + display->color.funcs = &ilk_color_funcs; } } diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index c61990ca9e29..db07e332af5a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -319,9 +319,6 @@ struct intel_display { /* fdi display functions */ const struct intel_fdi_funcs *fdi; - - /* Display internal color functions */ - const struct intel_color_funcs *color; } funcs; struct { @@ -365,6 +362,9 @@ struct intel_display { } cdclk; struct { + /* internal color functions */ + const struct intel_color_funcs *funcs; + struct drm_property_blob *glk_linear_degamma_lut; } color; From 5a6447dd1012d3e62ed31b92357308f6d14d8b06 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 Apr 2026 11:28:47 +0300 Subject: [PATCH 128/144] drm/i915/display: move fdi funcs under fdi sub-struct Move fdi related functions under fdi sub-struct of struct intel_display. The funcs sub-struct of struct intel_display seems unnecessary. Instead of display->funcs.FEATURE, prefer display->FEATURE.funcs. Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/c48bad63ec94259773d05ef056268b02e119d635.1777537663.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_core.h | 6 +++--- drivers/gpu/drm/i915/display/intel_fdi.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index db07e332af5a..0fdda5339e81 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -316,9 +316,6 @@ struct intel_display { /* pm display functions */ const struct intel_wm_funcs *wm; - - /* fdi display functions */ - const struct intel_fdi_funcs *fdi; } funcs; struct { @@ -418,6 +415,9 @@ struct intel_display { } fbdev; struct { + /* internal fdi functions */ + const struct intel_fdi_funcs *funcs; + unsigned int pll_freq; u32 rx_config; } fdi; diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index 917f020650af..f5094655a63b 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -123,7 +123,7 @@ void intel_fdi_link_train(struct intel_crtc *crtc, { struct intel_display *display = to_intel_display(crtc); - display->funcs.fdi->fdi_link_train(crtc, crtc_state); + display->fdi.funcs->fdi_link_train(crtc, crtc_state); } /** @@ -1109,11 +1109,11 @@ void intel_fdi_init_hook(struct intel_display *display) { if (display->platform.ironlake) { - display->funcs.fdi = &ilk_funcs; + display->fdi.funcs = &ilk_funcs; } else if (display->platform.sandybridge) { - display->funcs.fdi = &gen6_funcs; + display->fdi.funcs = &gen6_funcs; } else if (display->platform.ivybridge) { /* FIXME: detect B0+ stepping and use auto training */ - display->funcs.fdi = &ivb_funcs; + display->fdi.funcs = &ivb_funcs; } } From 4c5e172872af54b957220c92297e15b1ff60226f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 Apr 2026 11:28:48 +0300 Subject: [PATCH 129/144] drm/i915/display: move watermark funcs under wm sub-struct Move watermark related functions under wm sub-struct of struct intel_display. The funcs sub-struct of struct intel_display seems unnecessary. Instead of display->funcs.FEATURE, prefer display->FEATURE.funcs. Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/6b74ab66692dce20b2a6a8cb8cfdef222b2983ca.1777537663.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_wm.c | 22 ++++++------- drivers/gpu/drm/i915/display/intel_display.c | 2 +- .../gpu/drm/i915/display/intel_display_core.h | 6 ++-- drivers/gpu/drm/i915/display/intel_wm.c | 32 +++++++++---------- drivers/gpu/drm/i915/display/skl_watermark.c | 2 +- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 02ac6f9a3d0e..ca4fff10ce8f 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -3584,7 +3584,7 @@ void ilk_wm_sanitize(struct intel_display *display) int i; /* Only supported on platforms that use atomic watermark design */ - if (!display->funcs.wm->optimize_watermarks) + if (!display->wm.funcs->optimize_watermarks) return; if (drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 9)) @@ -4152,34 +4152,34 @@ void i9xx_wm_init(struct intel_display *display) /* For FIFO watermark updates */ if (HAS_PCH_SPLIT(display)) { ilk_setup_wm_latency(display); - display->funcs.wm = &ilk_wm_funcs; + display->wm.funcs = &ilk_wm_funcs; } else if (display->platform.valleyview || display->platform.cherryview) { vlv_setup_wm_latency(display); - display->funcs.wm = &vlv_wm_funcs; + display->wm.funcs = &vlv_wm_funcs; } else if (display->platform.g4x) { g4x_setup_wm_latency(display); - display->funcs.wm = &g4x_wm_funcs; + display->wm.funcs = &g4x_wm_funcs; } else if (display->platform.pineview) { if (!pnv_get_cxsr_latency(display)) { drm_info(display->drm, "Unknown FSB/MEM, disabling CxSR\n"); /* Disable CxSR and never update its watermark again */ intel_set_memory_cxsr(display, false); - display->funcs.wm = &nop_funcs; + display->wm.funcs = &nop_funcs; } else { - display->funcs.wm = &pnv_wm_funcs; + display->wm.funcs = &pnv_wm_funcs; } } else if (DISPLAY_VER(display) == 4) { - display->funcs.wm = &i965_wm_funcs; + display->wm.funcs = &i965_wm_funcs; } else if (DISPLAY_VER(display) == 3) { - display->funcs.wm = &i9xx_wm_funcs; + display->wm.funcs = &i9xx_wm_funcs; } else if (DISPLAY_VER(display) == 2) { if (INTEL_NUM_PIPES(display) == 1) - display->funcs.wm = &i845_wm_funcs; + display->wm.funcs = &i845_wm_funcs; else - display->funcs.wm = &i9xx_wm_funcs; + display->wm.funcs = &i9xx_wm_funcs; } else { drm_err(display->drm, "unexpected fall-through in %s\n", __func__); - display->funcs.wm = &nop_funcs; + display->wm.funcs = &nop_funcs; } } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8ebd0df25c11..7280c414610a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2162,7 +2162,7 @@ static void i9xx_crtc_disable(struct intel_atomic_state *state, if (DISPLAY_VER(display) != 2) intel_set_cpu_fifo_underrun_reporting(display, pipe, false); - if (!display->funcs.wm->initial_watermarks) + if (!display->wm.funcs->initial_watermarks) intel_update_watermarks(display); /* clock the pipe down to 640x480@60 to potentially save power */ diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 0fdda5339e81..01394724abc9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -247,6 +247,9 @@ struct intel_vbt_data { }; struct intel_wm { + /* internal watermark functions */ + const struct intel_wm_funcs *funcs; + /* * Raw watermark latency values: * in 0.1us units for WM0, @@ -313,9 +316,6 @@ struct intel_display { /* irq display functions */ const struct intel_hotplug_funcs *hotplug; - - /* pm display functions */ - const struct intel_wm_funcs *wm; } funcs; struct { diff --git a/drivers/gpu/drm/i915/display/intel_wm.c b/drivers/gpu/drm/i915/display/intel_wm.c index f887a664fe22..b4aded774ce6 100644 --- a/drivers/gpu/drm/i915/display/intel_wm.c +++ b/drivers/gpu/drm/i915/display/intel_wm.c @@ -48,8 +48,8 @@ */ void intel_update_watermarks(struct intel_display *display) { - if (display->funcs.wm->update_wm) - display->funcs.wm->update_wm(display); + if (display->wm.funcs->update_wm) + display->wm.funcs->update_wm(display); } int intel_wm_compute(struct intel_atomic_state *state, @@ -57,10 +57,10 @@ int intel_wm_compute(struct intel_atomic_state *state, { struct intel_display *display = to_intel_display(state); - if (!display->funcs.wm->compute_watermarks) + if (!display->wm.funcs->compute_watermarks) return 0; - return display->funcs.wm->compute_watermarks(state, crtc); + return display->wm.funcs->compute_watermarks(state, crtc); } bool intel_initial_watermarks(struct intel_atomic_state *state, @@ -68,8 +68,8 @@ bool intel_initial_watermarks(struct intel_atomic_state *state, { struct intel_display *display = to_intel_display(state); - if (display->funcs.wm->initial_watermarks) { - display->funcs.wm->initial_watermarks(state, crtc); + if (display->wm.funcs->initial_watermarks) { + display->wm.funcs->initial_watermarks(state, crtc); return true; } @@ -81,8 +81,8 @@ void intel_atomic_update_watermarks(struct intel_atomic_state *state, { struct intel_display *display = to_intel_display(state); - if (display->funcs.wm->atomic_update_watermarks) - display->funcs.wm->atomic_update_watermarks(state, crtc); + if (display->wm.funcs->atomic_update_watermarks) + display->wm.funcs->atomic_update_watermarks(state, crtc); } void intel_optimize_watermarks(struct intel_atomic_state *state, @@ -90,30 +90,30 @@ void intel_optimize_watermarks(struct intel_atomic_state *state, { struct intel_display *display = to_intel_display(state); - if (display->funcs.wm->optimize_watermarks) - display->funcs.wm->optimize_watermarks(state, crtc); + if (display->wm.funcs->optimize_watermarks) + display->wm.funcs->optimize_watermarks(state, crtc); } int intel_compute_global_watermarks(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); - if (display->funcs.wm->compute_global_watermarks) - return display->funcs.wm->compute_global_watermarks(state); + if (display->wm.funcs->compute_global_watermarks) + return display->wm.funcs->compute_global_watermarks(state); return 0; } void intel_wm_get_hw_state(struct intel_display *display) { - if (display->funcs.wm->get_hw_state) - return display->funcs.wm->get_hw_state(display); + if (display->wm.funcs->get_hw_state) + return display->wm.funcs->get_hw_state(display); } void intel_wm_sanitize(struct intel_display *display) { - if (display->funcs.wm->sanitize) - return display->funcs.wm->sanitize(display); + if (display->wm.funcs->sanitize) + return display->wm.funcs->sanitize(display); } bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 4bffa27ce02c..96d2dcbe7bbc 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3995,7 +3995,7 @@ void skl_wm_init(struct intel_display *display) skl_setup_wm_latency(display); - display->funcs.wm = &skl_wm_funcs; + display->wm.funcs = &skl_wm_funcs; } static int skl_watermark_ipc_status_show(struct seq_file *m, void *data) From a046ed3af5988a68ac7f326b7588ec02da086adf Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 Apr 2026 11:28:49 +0300 Subject: [PATCH 130/144] drm/i915/display: move hotplug irq funcs under hotplug sub-struct Move hotplug irq related functions under hotplug sub-struct of struct intel_display. The funcs sub-struct of struct intel_display seems unnecessary. Instead of display->funcs.FEATURE, prefer display->FEATURE.funcs. Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/9419cff5038d60a6c95c247b83f54b6559067e0d.1777537663.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_core.h | 8 ++--- .../gpu/drm/i915/display/intel_hotplug_irq.c | 30 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 01394724abc9..0c2e17edbd5f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -47,7 +47,7 @@ struct intel_dpll_global_funcs; struct intel_dpll_mgr; struct intel_fbdev; struct intel_fdi_funcs; -struct intel_hotplug_funcs; +struct intel_hotplug_irq_funcs; struct intel_initial_plane_config; struct intel_opregion; struct intel_overlay; @@ -155,6 +155,9 @@ struct intel_frontbuffer_tracking { }; struct intel_hotplug { + /* internal hotplug irq functions */ + const struct intel_hotplug_irq_funcs *funcs; + struct delayed_work hotplug_work; const u32 *hpd, *pch_hpd; @@ -313,9 +316,6 @@ struct intel_display { /* Display pll funcs */ const struct intel_dpll_global_funcs *dpll; - - /* irq display functions */ - const struct intel_hotplug_funcs *hotplug; } funcs; struct { diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c index 8865cb2ac569..539fd555edce 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c @@ -1420,7 +1420,7 @@ static void i915_hpd_irq_setup(struct intel_display *display) hotplug_en); } -struct intel_hotplug_funcs { +struct intel_hotplug_irq_funcs { /* Enable HPD sense and interrupts for all present encoders */ void (*hpd_irq_setup)(struct intel_display *display); /* Enable HPD sense for a single encoder */ @@ -1428,7 +1428,7 @@ struct intel_hotplug_funcs { }; #define HPD_FUNCS(platform) \ -static const struct intel_hotplug_funcs platform##_hpd_funcs = { \ +static const struct intel_hotplug_irq_funcs platform##_hpd_funcs = { \ .hpd_irq_setup = platform##_hpd_irq_setup, \ .hpd_enable_detection = platform##_hpd_enable_detection, \ } @@ -1447,8 +1447,8 @@ void intel_hpd_enable_detection(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); - if (display->funcs.hotplug) - display->funcs.hotplug->hpd_enable_detection(encoder); + if (display->hotplug.funcs) + display->hotplug.funcs->hpd_enable_detection(encoder); } void intel_hpd_irq_setup(struct intel_display *display) @@ -1457,8 +1457,8 @@ void intel_hpd_irq_setup(struct intel_display *display) !display->irq.vlv_display_irqs_enabled) return; - if (display->funcs.hotplug) - display->funcs.hotplug->hpd_irq_setup(display); + if (display->hotplug.funcs) + display->hotplug.funcs->hpd_irq_setup(display); } void intel_hotplug_irq_init(struct intel_display *display) @@ -1469,23 +1469,23 @@ void intel_hotplug_irq_init(struct intel_display *display) if (HAS_GMCH(display)) { if (HAS_HOTPLUG(display)) - display->funcs.hotplug = &i915_hpd_funcs; + display->hotplug.funcs = &i915_hpd_funcs; } else { if (HAS_PCH_DG2(display)) - display->funcs.hotplug = &icp_hpd_funcs; + display->hotplug.funcs = &icp_hpd_funcs; else if (HAS_PCH_DG1(display)) - display->funcs.hotplug = &dg1_hpd_funcs; + display->hotplug.funcs = &dg1_hpd_funcs; else if (DISPLAY_VER(display) >= 14) - display->funcs.hotplug = &xelpdp_hpd_funcs; + display->hotplug.funcs = &xelpdp_hpd_funcs; else if (DISPLAY_VER(display) >= 11) - display->funcs.hotplug = &gen11_hpd_funcs; + display->hotplug.funcs = &gen11_hpd_funcs; else if (display->platform.geminilake || display->platform.broxton) - display->funcs.hotplug = &bxt_hpd_funcs; + display->hotplug.funcs = &bxt_hpd_funcs; else if (INTEL_PCH_TYPE(display) >= PCH_ICP) - display->funcs.hotplug = &icp_hpd_funcs; + display->hotplug.funcs = &icp_hpd_funcs; else if (INTEL_PCH_TYPE(display) >= PCH_SPT) - display->funcs.hotplug = &spt_hpd_funcs; + display->hotplug.funcs = &spt_hpd_funcs; else - display->funcs.hotplug = &ilk_hpd_funcs; + display->hotplug.funcs = &ilk_hpd_funcs; } } From 70382900c37771e6c4b8842a6de3ea9bb7e9009d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 Apr 2026 11:28:50 +0300 Subject: [PATCH 131/144] drm/i915/display: move dpll funcs under dpll sub-struct Move dpll related functions under dpll sub-struct of struct intel_display. The funcs sub-struct of struct intel_display seems unnecessary. Instead of display->funcs.FEATURE, prefer display->FEATURE.funcs. Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/02efd924d7efdf42655f5c9bfd0f79a6df5fe2b4.1777537663.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_core.h | 6 ++-- drivers/gpu/drm/i915/display/intel_dpll.c | 28 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 0c2e17edbd5f..5a1aee340728 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -127,6 +127,9 @@ struct intel_audio { * dpll, because on some platforms plls share registers. */ struct intel_dpll_global { + /* internal dpll functions */ + const struct intel_dpll_global_funcs *funcs; + struct mutex lock; int num_dpll; @@ -313,9 +316,6 @@ struct intel_display { /* Display CDCLK functions */ const struct intel_cdclk_funcs *cdclk; - - /* Display pll funcs */ - const struct intel_dpll_global_funcs *dpll; } funcs; struct { diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index a1aa88598013..f40807a5566b 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1735,7 +1735,7 @@ int intel_dpll_crtc_compute_clock(struct intel_atomic_state *state, if (!crtc_state->hw.enable) return 0; - ret = display->funcs.dpll->crtc_compute_clock(state, crtc); + ret = display->dpll.funcs->crtc_compute_clock(state, crtc); if (ret) { drm_dbg_kms(display->drm, "[CRTC:%d:%s] Couldn't calculate DPLL settings\n", crtc->base.base.id, crtc->base.name); @@ -1759,10 +1759,10 @@ int intel_dpll_crtc_get_dpll(struct intel_atomic_state *state, if (!crtc_state->hw.enable || crtc_state->intel_dpll) return 0; - if (!display->funcs.dpll->crtc_get_dpll) + if (!display->dpll.funcs->crtc_get_dpll) return 0; - ret = display->funcs.dpll->crtc_get_dpll(state, crtc); + ret = display->dpll.funcs->crtc_get_dpll(state, crtc); if (ret) { drm_dbg_kms(display->drm, "[CRTC:%d:%s] Couldn't get a shared DPLL\n", crtc->base.base.id, crtc->base.name); @@ -1776,27 +1776,27 @@ void intel_dpll_init_clock_hook(struct intel_display *display) { if (HAS_LT_PHY(display)) - display->funcs.dpll = &xe3plpd_dpll_funcs; + display->dpll.funcs = &xe3plpd_dpll_funcs; else if (DISPLAY_VER(display) >= 14) - display->funcs.dpll = &mtl_dpll_funcs; + display->dpll.funcs = &mtl_dpll_funcs; else if (display->platform.dg2) - display->funcs.dpll = &dg2_dpll_funcs; + display->dpll.funcs = &dg2_dpll_funcs; else if (DISPLAY_VER(display) >= 9 || HAS_DDI(display)) - display->funcs.dpll = &hsw_dpll_funcs; + display->dpll.funcs = &hsw_dpll_funcs; else if (HAS_PCH_SPLIT(display)) - display->funcs.dpll = &ilk_dpll_funcs; + display->dpll.funcs = &ilk_dpll_funcs; else if (display->platform.cherryview) - display->funcs.dpll = &chv_dpll_funcs; + display->dpll.funcs = &chv_dpll_funcs; else if (display->platform.valleyview) - display->funcs.dpll = &vlv_dpll_funcs; + display->dpll.funcs = &vlv_dpll_funcs; else if (display->platform.g4x) - display->funcs.dpll = &g4x_dpll_funcs; + display->dpll.funcs = &g4x_dpll_funcs; else if (display->platform.pineview) - display->funcs.dpll = &pnv_dpll_funcs; + display->dpll.funcs = &pnv_dpll_funcs; else if (DISPLAY_VER(display) != 2) - display->funcs.dpll = &i9xx_dpll_funcs; + display->dpll.funcs = &i9xx_dpll_funcs; else - display->funcs.dpll = &i8xx_dpll_funcs; + display->dpll.funcs = &i8xx_dpll_funcs; } static bool i9xx_has_pps(struct intel_display *display) From d858e4840480b4513f1c4922c4fb6122740aa3bf Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 Apr 2026 11:28:51 +0300 Subject: [PATCH 132/144] drm/i915/display: move cdclk funcs under cdclk sub-struct Move cdclk related functions under cdclk sub-struct of struct intel_display. The funcs sub-struct of struct intel_display seems unnecessary. Instead of display->funcs.FEATURE, prefer display->FEATURE.funcs. Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/a3cadca7cfd03486404af497fa62efb8e2d2adcd.1777537663.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_cdclk.c | 84 +++++++++---------- .../gpu/drm/i915/display/intel_display_core.h | 6 +- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 57d714c81fc4..a1bf01021d65 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -170,27 +170,27 @@ struct intel_cdclk_funcs { void intel_cdclk_get_cdclk(struct intel_display *display, struct intel_cdclk_config *cdclk_config) { - display->funcs.cdclk->get_cdclk(display, cdclk_config); + display->cdclk.funcs->get_cdclk(display, cdclk_config); } static void intel_cdclk_set_cdclk(struct intel_display *display, const struct intel_cdclk_config *cdclk_config, enum pipe pipe) { - display->funcs.cdclk->set_cdclk(display, cdclk_config, pipe); + display->cdclk.funcs->set_cdclk(display, cdclk_config, pipe); } static int intel_cdclk_modeset_calc_cdclk(struct intel_atomic_state *state) { struct intel_display *display = to_intel_display(state); - return display->funcs.cdclk->modeset_calc_cdclk(state); + return display->cdclk.funcs->modeset_calc_cdclk(state); } static u8 intel_cdclk_calc_voltage_level(struct intel_display *display, int cdclk) { - return display->funcs.cdclk->calc_voltage_level(cdclk); + return display->cdclk.funcs->calc_voltage_level(cdclk); } static void fixed_133mhz_get_cdclk(struct intel_display *display, @@ -2619,7 +2619,7 @@ static void intel_set_cdclk(struct intel_display *display, if (!intel_cdclk_changed(&display->cdclk.hw, cdclk_config)) return; - if (drm_WARN_ON_ONCE(display->drm, !display->funcs.cdclk->set_cdclk)) + if (drm_WARN_ON_ONCE(display->drm, !display->cdclk.funcs->set_cdclk)) return; intel_cdclk_dump_config(display, cdclk_config, context); @@ -4042,100 +4042,100 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = { void intel_init_cdclk_hooks(struct intel_display *display) { if (DISPLAY_VER(display) >= 35) { - display->funcs.cdclk = &xe3lpd_cdclk_funcs; + display->cdclk.funcs = &xe3lpd_cdclk_funcs; display->cdclk.table = xe3p_lpd_cdclk_table; } else if (DISPLAY_VER(display) >= 30) { - display->funcs.cdclk = &xe3lpd_cdclk_funcs; + display->cdclk.funcs = &xe3lpd_cdclk_funcs; display->cdclk.table = xe3lpd_cdclk_table; } else if (DISPLAY_VER(display) >= 20) { - display->funcs.cdclk = &rplu_cdclk_funcs; + display->cdclk.funcs = &rplu_cdclk_funcs; display->cdclk.table = xe2lpd_cdclk_table; } else if (DISPLAY_VERx100(display) >= 1401) { - display->funcs.cdclk = &rplu_cdclk_funcs; + display->cdclk.funcs = &rplu_cdclk_funcs; display->cdclk.table = xe2hpd_cdclk_table; } else if (DISPLAY_VER(display) >= 14) { - display->funcs.cdclk = &rplu_cdclk_funcs; + display->cdclk.funcs = &rplu_cdclk_funcs; display->cdclk.table = mtl_cdclk_table; } else if (display->platform.dg2) { - display->funcs.cdclk = &tgl_cdclk_funcs; + display->cdclk.funcs = &tgl_cdclk_funcs; display->cdclk.table = dg2_cdclk_table; } else if (display->platform.alderlake_p) { /* Wa_22011320316:adl-p[a0] */ if (intel_display_wa(display, INTEL_DISPLAY_WA_22011320316)) { display->cdclk.table = adlp_a_step_cdclk_table; - display->funcs.cdclk = &tgl_cdclk_funcs; + display->cdclk.funcs = &tgl_cdclk_funcs; } else if (display->platform.alderlake_p_raptorlake_u) { display->cdclk.table = rplu_cdclk_table; - display->funcs.cdclk = &rplu_cdclk_funcs; + display->cdclk.funcs = &rplu_cdclk_funcs; } else { display->cdclk.table = adlp_cdclk_table; - display->funcs.cdclk = &tgl_cdclk_funcs; + display->cdclk.funcs = &tgl_cdclk_funcs; } } else if (display->platform.rocketlake) { - display->funcs.cdclk = &tgl_cdclk_funcs; + display->cdclk.funcs = &tgl_cdclk_funcs; display->cdclk.table = rkl_cdclk_table; } else if (DISPLAY_VER(display) >= 12) { - display->funcs.cdclk = &tgl_cdclk_funcs; + display->cdclk.funcs = &tgl_cdclk_funcs; display->cdclk.table = icl_cdclk_table; } else if (display->platform.jasperlake || display->platform.elkhartlake) { - display->funcs.cdclk = &ehl_cdclk_funcs; + display->cdclk.funcs = &ehl_cdclk_funcs; display->cdclk.table = icl_cdclk_table; } else if (DISPLAY_VER(display) >= 11) { - display->funcs.cdclk = &icl_cdclk_funcs; + display->cdclk.funcs = &icl_cdclk_funcs; display->cdclk.table = icl_cdclk_table; } else if (display->platform.geminilake || display->platform.broxton) { - display->funcs.cdclk = &bxt_cdclk_funcs; + display->cdclk.funcs = &bxt_cdclk_funcs; if (display->platform.geminilake) display->cdclk.table = glk_cdclk_table; else display->cdclk.table = bxt_cdclk_table; } else if (DISPLAY_VER(display) == 9) { - display->funcs.cdclk = &skl_cdclk_funcs; + display->cdclk.funcs = &skl_cdclk_funcs; } else if (display->platform.broadwell) { - display->funcs.cdclk = &bdw_cdclk_funcs; + display->cdclk.funcs = &bdw_cdclk_funcs; } else if (display->platform.haswell) { - display->funcs.cdclk = &hsw_cdclk_funcs; + display->cdclk.funcs = &hsw_cdclk_funcs; } else if (display->platform.cherryview) { - display->funcs.cdclk = &chv_cdclk_funcs; + display->cdclk.funcs = &chv_cdclk_funcs; } else if (display->platform.valleyview) { - display->funcs.cdclk = &vlv_cdclk_funcs; + display->cdclk.funcs = &vlv_cdclk_funcs; } else if (display->platform.sandybridge || display->platform.ivybridge) { - display->funcs.cdclk = &fixed_400mhz_cdclk_funcs; + display->cdclk.funcs = &fixed_400mhz_cdclk_funcs; } else if (display->platform.ironlake) { - display->funcs.cdclk = &ilk_cdclk_funcs; + display->cdclk.funcs = &ilk_cdclk_funcs; } else if (display->platform.gm45) { - display->funcs.cdclk = &gm45_cdclk_funcs; + display->cdclk.funcs = &gm45_cdclk_funcs; } else if (display->platform.g45) { - display->funcs.cdclk = &g33_cdclk_funcs; + display->cdclk.funcs = &g33_cdclk_funcs; } else if (display->platform.i965gm) { - display->funcs.cdclk = &i965gm_cdclk_funcs; + display->cdclk.funcs = &i965gm_cdclk_funcs; } else if (display->platform.i965g) { - display->funcs.cdclk = &fixed_400mhz_cdclk_funcs; + display->cdclk.funcs = &fixed_400mhz_cdclk_funcs; } else if (display->platform.pineview) { - display->funcs.cdclk = &pnv_cdclk_funcs; + display->cdclk.funcs = &pnv_cdclk_funcs; } else if (display->platform.g33) { - display->funcs.cdclk = &g33_cdclk_funcs; + display->cdclk.funcs = &g33_cdclk_funcs; } else if (display->platform.i945gm) { - display->funcs.cdclk = &i945gm_cdclk_funcs; + display->cdclk.funcs = &i945gm_cdclk_funcs; } else if (display->platform.i945g) { - display->funcs.cdclk = &fixed_400mhz_cdclk_funcs; + display->cdclk.funcs = &fixed_400mhz_cdclk_funcs; } else if (display->platform.i915gm) { - display->funcs.cdclk = &i915gm_cdclk_funcs; + display->cdclk.funcs = &i915gm_cdclk_funcs; } else if (display->platform.i915g) { - display->funcs.cdclk = &i915g_cdclk_funcs; + display->cdclk.funcs = &i915g_cdclk_funcs; } else if (display->platform.i865g) { - display->funcs.cdclk = &i865g_cdclk_funcs; + display->cdclk.funcs = &i865g_cdclk_funcs; } else if (display->platform.i85x) { - display->funcs.cdclk = &i85x_cdclk_funcs; + display->cdclk.funcs = &i85x_cdclk_funcs; } else if (display->platform.i845g) { - display->funcs.cdclk = &i845g_cdclk_funcs; + display->cdclk.funcs = &i845g_cdclk_funcs; } else if (display->platform.i830) { - display->funcs.cdclk = &i830_cdclk_funcs; + display->cdclk.funcs = &i830_cdclk_funcs; } - if (drm_WARN(display->drm, !display->funcs.cdclk, + if (drm_WARN(display->drm, !display->cdclk.funcs, "Unknown platform. Assuming i830\n")) - display->funcs.cdclk = &i830_cdclk_funcs; + display->cdclk.funcs = &i830_cdclk_funcs; } int intel_cdclk_logical(const struct intel_cdclk_state *cdclk_state) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 5a1aee340728..a319fb97dafa 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -313,9 +313,6 @@ struct intel_display { struct { /* Top level crtc-ish functions */ const struct intel_display_funcs *display; - - /* Display CDCLK functions */ - const struct intel_cdclk_funcs *cdclk; } funcs; struct { @@ -345,6 +342,9 @@ struct intel_display { } bw; struct { + /* Internal CDCLK functions */ + const struct intel_cdclk_funcs *funcs; + /* The current hardware cdclk configuration */ struct intel_cdclk_config hw; From 68644d8fc854bf07e7e606a0a94856dcea34fc8b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 30 Apr 2026 11:28:52 +0300 Subject: [PATCH 133/144] drm/i915/display: move display funcs under modeset sub-struct Move generic crtc-ish modeset related functions under a new modeset sub-struct of struct intel_display. Rename struct intel_display_funcs to intel_modeset_funcs to make it a little bit more specific. Remove the funcs sub-struct. The funcs sub-struct of struct intel_display seems unnecessary. Instead of display->funcs.FEATURE, prefer display->FEATURE.funcs. Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/7849de3a5c9755639c179917c6a298de9ac832c0.1777537663.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 28 +++++++++---------- .../gpu/drm/i915/display/intel_display_core.h | 13 ++++----- .../drm/i915/display/intel_initial_plane.c | 4 +-- .../drm/i915/display/intel_modeset_setup.c | 2 +- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7280c414610a..2fa10f858279 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4051,7 +4051,7 @@ bool intel_crtc_get_pipe_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); - if (!display->funcs.display->get_pipe_config(crtc, crtc_state)) + if (!display->modeset.funcs->get_pipe_config(crtc, crtc_state)) return false; crtc_state->hw.active = true; @@ -6739,7 +6739,7 @@ static void intel_enable_crtc(struct intel_atomic_state *state, intel_psr_notify_pipe_change(state, crtc, true); - display->funcs.display->crtc_enable(state, crtc); + display->modeset.funcs->crtc_enable(state, crtc); intel_crtc_wait_for_next_vblank(crtc); @@ -6872,7 +6872,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, intel_psr_notify_pipe_change(state, crtc, false); - display->funcs.display->crtc_disable(state, crtc); + display->modeset.funcs->crtc_disable(state, crtc); for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc, intel_crtc_joined_pipe_mask(old_crtc_state)) { @@ -7524,7 +7524,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) } /* Now enable the clocks, plane, pipe, and connectors that we set up. */ - display->funcs.display->commit_modeset_enables(state); + display->modeset.funcs->commit_modeset_enables(state); /* FIXME probably need to sequence this properly */ intel_program_dpkgc_latency(state); @@ -8197,7 +8197,7 @@ intel_mode_valid_max_plane_size(struct intel_display *display, return MODE_OK; } -static const struct intel_display_funcs skl_display_funcs = { +static const struct intel_modeset_funcs skl_display_funcs = { .get_pipe_config = hsw_get_pipe_config, .crtc_enable = hsw_crtc_enable, .crtc_disable = hsw_crtc_disable, @@ -8206,7 +8206,7 @@ static const struct intel_display_funcs skl_display_funcs = { .fixup_initial_plane_config = skl_fixup_initial_plane_config, }; -static const struct intel_display_funcs ddi_display_funcs = { +static const struct intel_modeset_funcs ddi_display_funcs = { .get_pipe_config = hsw_get_pipe_config, .crtc_enable = hsw_crtc_enable, .crtc_disable = hsw_crtc_disable, @@ -8215,7 +8215,7 @@ static const struct intel_display_funcs ddi_display_funcs = { .fixup_initial_plane_config = i9xx_fixup_initial_plane_config, }; -static const struct intel_display_funcs pch_split_display_funcs = { +static const struct intel_modeset_funcs pch_split_display_funcs = { .get_pipe_config = ilk_get_pipe_config, .crtc_enable = ilk_crtc_enable, .crtc_disable = ilk_crtc_disable, @@ -8224,7 +8224,7 @@ static const struct intel_display_funcs pch_split_display_funcs = { .fixup_initial_plane_config = i9xx_fixup_initial_plane_config, }; -static const struct intel_display_funcs vlv_display_funcs = { +static const struct intel_modeset_funcs vlv_display_funcs = { .get_pipe_config = i9xx_get_pipe_config, .crtc_enable = valleyview_crtc_enable, .crtc_disable = i9xx_crtc_disable, @@ -8233,7 +8233,7 @@ static const struct intel_display_funcs vlv_display_funcs = { .fixup_initial_plane_config = i9xx_fixup_initial_plane_config, }; -static const struct intel_display_funcs i9xx_display_funcs = { +static const struct intel_modeset_funcs i9xx_display_funcs = { .get_pipe_config = i9xx_get_pipe_config, .crtc_enable = i9xx_crtc_enable, .crtc_disable = i9xx_crtc_disable, @@ -8249,16 +8249,16 @@ static const struct intel_display_funcs i9xx_display_funcs = { void intel_init_display_hooks(struct intel_display *display) { if (DISPLAY_VER(display) >= 9) { - display->funcs.display = &skl_display_funcs; + display->modeset.funcs = &skl_display_funcs; } else if (HAS_DDI(display)) { - display->funcs.display = &ddi_display_funcs; + display->modeset.funcs = &ddi_display_funcs; } else if (HAS_PCH_SPLIT(display)) { - display->funcs.display = &pch_split_display_funcs; + display->modeset.funcs = &pch_split_display_funcs; } else if (display->platform.cherryview || display->platform.valleyview) { - display->funcs.display = &vlv_display_funcs; + display->modeset.funcs = &vlv_display_funcs; } else { - display->funcs.display = &i9xx_display_funcs; + display->modeset.funcs = &i9xx_display_funcs; } } diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index a319fb97dafa..796517e7bc6c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -59,7 +59,7 @@ struct task_struct; /* Amount of PSF GV points, BSpec precisely defines this */ #define I915_NUM_PSF_GV_POINTS 3 -struct intel_display_funcs { +struct intel_modeset_funcs { /* * Returns the active state of the crtc, and if the crtc is active, * fills out the pipe-config with the hw state. @@ -309,12 +309,6 @@ struct intel_display { /* list of all intel_crtcs sorted by pipe */ struct list_head pipe_list; - /* Display functions */ - struct { - /* Top level crtc-ish functions */ - const struct intel_display_funcs *display; - } funcs; - struct { bool any_task_allowed; struct task_struct *allowed_task; @@ -518,6 +512,11 @@ struct intel_display { u32 pipestat_irq_mask[I915_MAX_PIPES]; } irq; + struct { + /* Top level crtc-ish functions */ + const struct intel_modeset_funcs *funcs; + } modeset; + struct { /* protected by wm.wm_mutex */ u16 linetime[I915_MAX_PIPES]; diff --git a/drivers/gpu/drm/i915/display/intel_initial_plane.c b/drivers/gpu/drm/i915/display/intel_initial_plane.c index 0e5cd45f01cc..034fe199c2a1 100644 --- a/drivers/gpu/drm/i915/display/intel_initial_plane.c +++ b/drivers/gpu/drm/i915/display/intel_initial_plane.c @@ -224,7 +224,7 @@ void intel_initial_plane_config(struct intel_display *display) * can even allow for smooth boot transitions if the BIOS * fb is large enough for the active pipe configuration. */ - display->funcs.display->get_initial_plane_config(crtc, plane_config); + display->modeset.funcs->get_initial_plane_config(crtc, plane_config); /* * If the fb is shared between multiple heads, we'll @@ -232,7 +232,7 @@ void intel_initial_plane_config(struct intel_display *display) */ intel_find_initial_plane_obj(crtc, &all_plane_configs); - if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config)) + if (display->modeset.funcs->fixup_initial_plane_config(crtc, plane_config)) intel_initial_plane_vblank_wait(crtc); plane_config_fini(display, plane_config); diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 40a65a0d7ec7..4c646b1bd0ee 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -83,7 +83,7 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc, drm_WARN_ON(display->drm, IS_ERR(temp_crtc_state) || ret); } - display->funcs.display->crtc_disable(to_intel_atomic_state(state), crtc); + display->modeset.funcs->crtc_disable(to_intel_atomic_state(state), crtc); drm_atomic_state_put(state); From 6692ee0deae3b5a130053c94eadc888ccd83e088 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 4 May 2026 15:41:17 +0530 Subject: [PATCH 134/144] drm/i915/hdcp: Use new MST topology state in intel_conn_to_vcpi() intel_conn_to_vcpi() runs from the HDCP enable path in commit_tail and looks up the VCPI via mgr->base.state. When an ALLOCATE_PAYLOAD is being driven on the mgr just before HDCP enable, that payload list is being mutated in place, so the lookup can miss the port and trip drm_WARN_ON(!payload), causing HDCP to be programmed with VCPI 0. Use drm_atomic_get_new_mst_topology_state() to read the topology state attached to this atomic commit (stable, decided in atomic_check), and bail out cleanly when no topology state or payload is present for this port instead of WARNing. Signed-off-by: Suraj Kandpal Tested-by: Santhosh Reddy Guddati Reviewed-by: Santhosh Reddy Guddati Link: https://patch.msgid.link/20260504101117.3619984-2-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_hdcp.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 9b4ff3b80b05..02ac981ca1ea 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -72,6 +72,7 @@ intel_hdcp_adjust_hdcp_line_rekeying(struct intel_encoder *encoder, static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { + struct intel_display *display = to_intel_display(state); struct drm_dp_mst_topology_mgr *mgr; struct drm_dp_mst_atomic_payload *payload; struct drm_dp_mst_topology_state *mst_state; @@ -82,10 +83,17 @@ static int intel_conn_to_vcpi(struct intel_atomic_state *state, mgr = connector->mst.port->mgr; drm_modeset_lock(&mgr->base.lock, state->base.acquire_ctx); - mst_state = to_drm_dp_mst_topology_state(mgr->base.state); - payload = drm_atomic_get_mst_payload_state(mst_state, connector->mst.port); - if (drm_WARN_ON(mgr->dev, !payload)) + mst_state = drm_atomic_get_new_mst_topology_state(&state->base, mgr); + if (!mst_state) { + drm_dbg_kms(display->drm, "MST topology still not created\n"); return 0; + } + + payload = drm_atomic_get_mst_payload_state(mst_state, connector->mst.port); + if (!payload) { + drm_dbg_kms(display->drm, "MST Payload not present\n"); + return 0; + } return payload->vcpi; } From 9ec5a97340adf55eb705a48a4b988e72341a9432 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 4 May 2026 15:41:18 +0530 Subject: [PATCH 135/144] drm/i915/hdcp: Drop mgr->base.lock acquisition in intel_conn_to_vcpi() Now that intel_conn_to_vcpi() reads the MST topology state via drm_atomic_get_new_mst_topology_state(), the topology state belongs to this atomic commit and is already serialized through the atomic state's private object machinery. There is no need to additionally take mgr->base.lock here. Taking it from the HDCP enable path in commit_tail with state->base.acquire_ctx is also unsafe: by this point the acquire_ctx is no longer in a state where new modeset locks may be acquired through it, which produces a modeset-lock splat on MST + HDCP. Drop the drm_modeset_lock() call. Signed-off-by: Suraj Kandpal Tested-by: Santhosh Reddy Guddati Reviewed-by: Santhosh Reddy Guddati Link: https://patch.msgid.link/20260504101117.3619984-3-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_hdcp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 02ac981ca1ea..982f698e9814 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -80,9 +80,8 @@ static int intel_conn_to_vcpi(struct intel_atomic_state *state, /* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */ if (!connector->mst.port) return 0; - mgr = connector->mst.port->mgr; - drm_modeset_lock(&mgr->base.lock, state->base.acquire_ctx); + mgr = connector->mst.port->mgr; mst_state = drm_atomic_get_new_mst_topology_state(&state->base, mgr); if (!mst_state) { drm_dbg_kms(display->drm, "MST topology still not created\n"); From 8a2366d6ee88b18c81e6a37e8798d0217b9515da Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 28 Apr 2026 12:48:19 +0300 Subject: [PATCH 136/144] drm/i915: move SKL clock gating init to display Move the SKL-specific display clock gating programming into a new file inside display. This removes dependency from intel_clock_gating.c to the display's intel_pch.h file, so we can remove the include statement. Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260428095104.818360-2-luciano.coelho@intel.com Signed-off-by: Luca Coelho --- drivers/gpu/drm/i915/Makefile | 1 + .../i915/display/intel_display_clock_gating.c | 19 +++++++++++++++++++ .../i915/display/intel_display_clock_gating.h | 13 +++++++++++++ drivers/gpu/drm/i915/intel_clock_gating.c | 8 ++------ 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_display_clock_gating.c create mode 100644 drivers/gpu/drm/i915/display/intel_display_clock_gating.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index fa632f4e505c..07802a7f4ce5 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -256,6 +256,7 @@ i915-y += \ display/intel_cursor.o \ display/intel_dbuf_bw.o \ display/intel_de.o \ + display/intel_display_clock_gating.o \ display/intel_display.o \ display/intel_display_conversion.o \ display/intel_display_driver.o \ diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c new file mode 100644 index 000000000000..4a94593335e0 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2026 Intel Corporation + */ + +#include + +#include "intel_de.h" +#include "intel_display_clock_gating.h" +#include "intel_display_regs.h" + +void intel_display_skl_init_clock_gating(struct intel_display *display) +{ + /* + * WaFbcTurnOffFbcWatermark:skl + * Display WA #0562: skl + */ + intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h new file mode 100644 index 000000000000..00f416db7f47 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Intel Corporation + */ + +#ifndef __INTEL_DISPLAY_CLOCK_GATING_H__ +#define __INTEL_DISPLAY_CLOCK_GATING_H__ + +struct intel_display; + +void intel_display_skl_init_clock_gating(struct intel_display *display); + +#endif /* __INTEL_DISPLAY_CLOCK_GATING_H__ */ diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 515f83c82abc..ad28ceee012b 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -32,9 +32,9 @@ #include "display/i9xx_plane_regs.h" #include "display/intel_display.h" +#include "display/intel_display_clock_gating.h" #include "display/intel_display_core.h" #include "display/intel_display_regs.h" -#include "display/intel_pch.h" #include "gt/intel_engine_regs.h" #include "gt/intel_gt.h" #include "gt/intel_gt_mcr.h" @@ -349,11 +349,7 @@ static void skl_init_clock_gating(struct drm_i915_private *i915) /* WAC6entrylatency:skl */ intel_uncore_rmw(&i915->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); - /* - * WaFbcTurnOffFbcWatermark:skl - * Display WA #0562: skl - */ - intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); + intel_display_skl_init_clock_gating(i915->display); } static void bdw_init_clock_gating(struct drm_i915_private *i915) From 3ee59cc4057264524adcc25e6d806f8bcddf3466 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 28 Apr 2026 12:48:20 +0300 Subject: [PATCH 137/144] drm/i915: move KBL clock gating init to display Move the KBL-specific display clock gating programming into a display intel_display_clock_gating.c, to remove more dependencies from i915 to display registers. Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260428095104.818360-3-luciano.coelho@intel.com Signed-off-by: Luca Coelho --- .../gpu/drm/i915/display/intel_display_clock_gating.c | 9 +++++++++ .../gpu/drm/i915/display/intel_display_clock_gating.h | 1 + drivers/gpu/drm/i915/intel_clock_gating.c | 6 +----- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c index 4a94593335e0..508735212d6b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c @@ -17,3 +17,12 @@ void intel_display_skl_init_clock_gating(struct intel_display *display) */ intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); } + +void intel_display_kbl_init_clock_gating(struct intel_display *display) +{ + /* + * WaFbcTurnOffFbcWatermark:kbl + * Display WA #0562: kbl + */ + intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h index 00f416db7f47..8c21217de66a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h @@ -9,5 +9,6 @@ struct intel_display; void intel_display_skl_init_clock_gating(struct intel_display *display); +void intel_display_kbl_init_clock_gating(struct intel_display *display); #endif /* __INTEL_DISPLAY_CLOCK_GATING_H__ */ diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index ad28ceee012b..c446e4ac92f1 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -331,11 +331,7 @@ static void kbl_init_clock_gating(struct drm_i915_private *i915) intel_uncore_rmw(&i915->uncore, GEN6_UCGCTL1, 0, GEN6_GAMUNIT_CLOCK_GATE_DISABLE); - /* - * WaFbcTurnOffFbcWatermark:kbl - * Display WA #0562: kbl - */ - intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); + intel_display_kbl_init_clock_gating(i915->display); } static void skl_init_clock_gating(struct drm_i915_private *i915) From 1f842b5e70b3bb1179a2d410d6f1514e91906d4b Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 28 Apr 2026 12:48:21 +0300 Subject: [PATCH 138/144] drm/i915/display: move CFL clock gating init to display Move the CFL/CML-specific display clock gating programming into display intel_display_clock_gating.c, to remove more dependencies from i915 to display registers. Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260428095104.818360-4-luciano.coelho@intel.com Signed-off-by: Luca Coelho --- .../gpu/drm/i915/display/intel_display_clock_gating.c | 9 +++++++++ .../gpu/drm/i915/display/intel_display_clock_gating.h | 1 + drivers/gpu/drm/i915/intel_clock_gating.c | 6 +----- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c index 508735212d6b..82ea21d7377d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c @@ -26,3 +26,12 @@ void intel_display_kbl_init_clock_gating(struct intel_display *display) */ intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); } + +void intel_display_cfl_init_clock_gating(struct intel_display *display) +{ + /* + * WaFbcTurnOffFbcWatermark:cfl + * Display WA #0562: cfl + */ + intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h index 8c21217de66a..63960f1e80fc 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h @@ -10,5 +10,6 @@ struct intel_display; void intel_display_skl_init_clock_gating(struct intel_display *display); void intel_display_kbl_init_clock_gating(struct intel_display *display); +void intel_display_cfl_init_clock_gating(struct intel_display *display); #endif /* __INTEL_DISPLAY_CLOCK_GATING_H__ */ diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index c446e4ac92f1..80d7f057cb81 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -307,11 +307,7 @@ static void cfl_init_clock_gating(struct drm_i915_private *i915) /* WAC6entrylatency:cfl */ intel_uncore_rmw(&i915->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); - /* - * WaFbcTurnOffFbcWatermark:cfl - * Display WA #0562: cfl - */ - intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); + intel_display_cfl_init_clock_gating(i915->display); } static void kbl_init_clock_gating(struct drm_i915_private *i915) From fa00ae490cc5eba9cacd7c65f4243e9da6b2c8ae Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 28 Apr 2026 12:48:22 +0300 Subject: [PATCH 139/144] drm/i915/display: move BXT clock gating init to display Move the BXT-specific display clock gating programming into display intel_display_clock_gating.c, to remove more dependencies from i915. Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260428095104.818360-5-luciano.coelho@intel.com Signed-off-by: Luca Coelho --- .../i915/display/intel_display_clock_gating.c | 25 +++++++++++++++++++ .../i915/display/intel_display_clock_gating.h | 1 + drivers/gpu/drm/i915/intel_clock_gating.c | 22 +--------------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c index 82ea21d7377d..59041c807d6d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c @@ -35,3 +35,28 @@ void intel_display_cfl_init_clock_gating(struct intel_display *display) */ intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); } + +void intel_display_bxt_init_clock_gating(struct intel_display *display) +{ + /* + * Wa: Backlight PWM may stop in the asserted state, causing backlight + * to stay fully on. + */ + intel_de_write(display, GEN9_CLKGATE_DIS_0, + intel_de_read(display, GEN9_CLKGATE_DIS_0) | + PWM1_GATING_DIS | PWM2_GATING_DIS); + + /* + * Lower the display internal timeout. + * This is needed to avoid any hard hangs when DSI port PLL + * is off and a MMIO access is attempted by any privilege + * application, using batch buffers or any other means. + */ + intel_de_write(display, RM_TIMEOUT, MMIO_TIMEOUT_US(950)); + + /* + * WaFbcTurnOffFbcWatermark:bxt + * Display WA #0562: bxt + */ + intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h index 63960f1e80fc..6bc84a9a4342 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h @@ -11,5 +11,6 @@ struct intel_display; void intel_display_skl_init_clock_gating(struct intel_display *display); void intel_display_kbl_init_clock_gating(struct intel_display *display); void intel_display_cfl_init_clock_gating(struct intel_display *display); +void intel_display_bxt_init_clock_gating(struct intel_display *display); #endif /* __INTEL_DISPLAY_CLOCK_GATING_H__ */ diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 80d7f057cb81..a9efa5ce8f6a 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -88,27 +88,7 @@ static void bxt_init_clock_gating(struct drm_i915_private *i915) */ intel_uncore_rmw(&i915->uncore, GEN8_UCGCTL6, 0, GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ); - /* - * Wa: Backlight PWM may stop in the asserted state, causing backlight - * to stay fully on. - */ - intel_uncore_write(&i915->uncore, GEN9_CLKGATE_DIS_0, - intel_uncore_read(&i915->uncore, GEN9_CLKGATE_DIS_0) | - PWM1_GATING_DIS | PWM2_GATING_DIS); - - /* - * Lower the display internal timeout. - * This is needed to avoid any hard hangs when DSI port PLL - * is off and a MMIO access is attempted by any privilege - * application, using batch buffers or any other means. - */ - intel_uncore_write(&i915->uncore, RM_TIMEOUT, MMIO_TIMEOUT_US(950)); - - /* - * WaFbcTurnOffFbcWatermark:bxt - * Display WA #0562: bxt - */ - intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); + intel_display_bxt_init_clock_gating(i915->display); } static void glk_init_clock_gating(struct drm_i915_private *i915) From 8aa07711825485ba8beb6ee5fa4b6001503aa7bc Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 28 Apr 2026 12:48:23 +0300 Subject: [PATCH 140/144] drm/i915/display: move GLK clock gating init to display Move the GLK-specific display clock gating programming into display intel_display_clock_gating.c, to remove more dependencies from i915 to display registers. Now that all remaining Gen9-family callers moved into display, we can move the shared Gen9 display clock gating helper into display and remove the old local helper from intel_clock_gating.c. Additionally, the SKL_DE_COMPRESSED_HASH_MODE programming was protected by HAS_LLC(), but that's incidental, because in Gen9 platforms, only SKL and KBL, for which this workaround applies, have LLC(). In order not to use HAS_LLC() in display code, we can simply remove this check from the generic Gen9 function and move the SKL_DE_COMPRESSED_HASH_MODE programming to the KBL and SKL specific functions. And, intentionally or not, CFL and CML were also using this workaround, because they also have LLC, even though the comments were only mentioning SKL and KBL. In order not to change anything functionally with this patch, the workaround was also added to intel_display_cfl_init_clock_gating(). Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260428095104.818360-6-luciano.coelho@intel.com Signed-off-by: Luca Coelho --- .../i915/display/intel_display_clock_gating.c | 72 +++++++++++++++++++ .../i915/display/intel_display_clock_gating.h | 1 + drivers/gpu/drm/i915/intel_clock_gating.c | 44 +----------- 3 files changed, 74 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c index 59041c807d6d..a8966e6ace38 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c @@ -6,11 +6,39 @@ #include #include "intel_de.h" +#include "intel_display.h" #include "intel_display_clock_gating.h" +#include "intel_display_core.h" #include "intel_display_regs.h" +static void intel_display_gen9_init_clock_gating(struct intel_display *display) +{ + /* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */ + intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_EDP_PSR_FIX_RDWRAP); + + /* WaEnableChickenDCPR:skl,bxt,kbl,glk,cfl */ + intel_de_rmw(display, GEN8_CHICKEN_DCPR_1, 0, MASK_WAKEMEM); + + /* + * WaFbcWakeMemOn:skl,bxt,kbl,glk,cfl + * Display WA #0859: skl,bxt,kbl,glk,cfl + */ + intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_MEMORY_WAKE); +} + void intel_display_skl_init_clock_gating(struct intel_display *display) { + /* + * WaCompressedResourceDisplayNewHashMode:skl,kbl + * Display WA #0390: skl,kbl + * + * Must match Sampler, Pixel Back End, and Media. See + * WaCompressedResourceSamplerPbeMediaNewHashMode. + */ + intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE); + + intel_display_gen9_init_clock_gating(display); + /* * WaFbcTurnOffFbcWatermark:skl * Display WA #0562: skl @@ -20,6 +48,17 @@ void intel_display_skl_init_clock_gating(struct intel_display *display) void intel_display_kbl_init_clock_gating(struct intel_display *display) { + /* + * WaCompressedResourceDisplayNewHashMode:skl,kbl + * Display WA #0390: skl,kbl + * + * Must match Sampler, Pixel Back End, and Media. See + * WaCompressedResourceSamplerPbeMediaNewHashMode. + */ + intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE); + + intel_display_gen9_init_clock_gating(display); + /* * WaFbcTurnOffFbcWatermark:kbl * Display WA #0562: kbl @@ -29,6 +68,23 @@ void intel_display_kbl_init_clock_gating(struct intel_display *display) void intel_display_cfl_init_clock_gating(struct intel_display *display) { + /* + * WaCompressedResourceDisplayNewHashMode:skl,kbl (and cfl, cml) + * Display WA #0390: skl,kbl (and cfl, cml) + * + * Must match Sampler, Pixel Back End, and Media. See + * WaCompressedResourceSamplerPbeMediaNewHashMode. + * + * NOTE: this is the same workaround used for skl and kbl, + * because the original implementation was checking HAS_LLC(), + * which cfl/cml have, even though the comment for the + * workaround doesn't mention it. + * + */ + intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE); + + intel_display_gen9_init_clock_gating(display); + /* * WaFbcTurnOffFbcWatermark:cfl * Display WA #0562: cfl @@ -38,6 +94,8 @@ void intel_display_cfl_init_clock_gating(struct intel_display *display) void intel_display_bxt_init_clock_gating(struct intel_display *display) { + intel_display_gen9_init_clock_gating(display); + /* * Wa: Backlight PWM may stop in the asserted state, causing backlight * to stay fully on. @@ -60,3 +118,17 @@ void intel_display_bxt_init_clock_gating(struct intel_display *display) */ intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); } + +void intel_display_glk_init_clock_gating(struct intel_display *display) +{ + intel_display_gen9_init_clock_gating(display); + + /* + * WaDisablePWMClockGating:glk + * Backlight PWM may stop in the asserted state, causing backlight + * to stay fully on. + */ + intel_de_write(display, GEN9_CLKGATE_DIS_0, + intel_de_read(display, GEN9_CLKGATE_DIS_0) | + PWM1_GATING_DIS | PWM2_GATING_DIS); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h index 6bc84a9a4342..a7784db9d97a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h @@ -12,5 +12,6 @@ void intel_display_skl_init_clock_gating(struct intel_display *display); void intel_display_kbl_init_clock_gating(struct intel_display *display); void intel_display_cfl_init_clock_gating(struct intel_display *display); void intel_display_bxt_init_clock_gating(struct intel_display *display); +void intel_display_glk_init_clock_gating(struct intel_display *display); #endif /* __INTEL_DISPLAY_CLOCK_GATING_H__ */ diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index a9efa5ce8f6a..96fe16753e58 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -49,36 +49,8 @@ struct drm_i915_clock_gating_funcs { void (*init_clock_gating)(struct drm_i915_private *i915); }; -static void gen9_init_clock_gating(struct drm_i915_private *i915) -{ - if (HAS_LLC(i915)) { - /* - * WaCompressedResourceDisplayNewHashMode:skl,kbl - * Display WA #0390: skl,kbl - * - * Must match Sampler, Pixel Back End, and Media. See - * WaCompressedResourceSamplerPbeMediaNewHashMode. - */ - intel_uncore_rmw(&i915->uncore, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE); - } - - /* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */ - intel_uncore_rmw(&i915->uncore, CHICKEN_PAR1_1, 0, SKL_EDP_PSR_FIX_RDWRAP); - - /* WaEnableChickenDCPR:skl,bxt,kbl,glk,cfl */ - intel_uncore_rmw(&i915->uncore, GEN8_CHICKEN_DCPR_1, 0, MASK_WAKEMEM); - - /* - * WaFbcWakeMemOn:skl,bxt,kbl,glk,cfl - * Display WA #0859: skl,bxt,kbl,glk,cfl - */ - intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_MEMORY_WAKE); -} - static void bxt_init_clock_gating(struct drm_i915_private *i915) { - gen9_init_clock_gating(i915); - /* WaDisableSDEUnitClockGating:bxt */ intel_uncore_rmw(&i915->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE); @@ -93,16 +65,7 @@ static void bxt_init_clock_gating(struct drm_i915_private *i915) static void glk_init_clock_gating(struct drm_i915_private *i915) { - gen9_init_clock_gating(i915); - - /* - * WaDisablePWMClockGating:glk - * Backlight PWM may stop in the asserted state, causing backlight - * to stay fully on. - */ - intel_uncore_write(&i915->uncore, GEN9_CLKGATE_DIS_0, - intel_uncore_read(&i915->uncore, GEN9_CLKGATE_DIS_0) | - PWM1_GATING_DIS | PWM2_GATING_DIS); + intel_display_glk_init_clock_gating(i915->display); } static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv) @@ -282,7 +245,6 @@ static void dg2_init_clock_gating(struct drm_i915_private *i915) static void cfl_init_clock_gating(struct drm_i915_private *i915) { intel_pch_init_clock_gating(i915->display); - gen9_init_clock_gating(i915); /* WAC6entrylatency:cfl */ intel_uncore_rmw(&i915->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); @@ -292,8 +254,6 @@ static void cfl_init_clock_gating(struct drm_i915_private *i915) static void kbl_init_clock_gating(struct drm_i915_private *i915) { - gen9_init_clock_gating(i915); - /* WAC6entrylatency:kbl */ intel_uncore_rmw(&i915->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN); @@ -312,8 +272,6 @@ static void kbl_init_clock_gating(struct drm_i915_private *i915) static void skl_init_clock_gating(struct drm_i915_private *i915) { - gen9_init_clock_gating(i915); - /* WaDisableDopClockGating:skl */ intel_uncore_rmw(&i915->uncore, GEN7_MISCCPCTL, GEN7_DOP_CLOCK_GATE_ENABLE, 0); From 5c9a79d564da2a741492b2611f3c9bdae4002d65 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 28 Apr 2026 12:48:24 +0300 Subject: [PATCH 141/144] drm/i915/display: move HSW and BDW clock gating init to display Move the HSW and BDW display clock gating programming into the display code. In this case we need two different helpers, because the common code between these two is split in the middle. Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260428095104.818360-7-luciano.coelho@intel.com Signed-off-by: Luca Coelho --- .../i915/display/intel_display_clock_gating.c | 44 +++++++++++++++++++ .../i915/display/intel_display_clock_gating.h | 4 ++ .../gpu/drm/i915/display/intel_display_regs.h | 3 ++ drivers/gpu/drm/i915/i915_reg.h | 3 -- drivers/gpu/drm/i915/intel_clock_gating.c | 34 ++------------ 5 files changed, 55 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c index a8966e6ace38..74bb88d52ba9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c @@ -132,3 +132,47 @@ void intel_display_glk_init_clock_gating(struct intel_display *display) intel_de_read(display, GEN9_CLKGATE_DIS_0) | PWM1_GATING_DIS | PWM2_GATING_DIS); } + +void intel_display_bdw_clock_gating_disable_fbcq(struct intel_display *display) +{ + /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ + intel_de_rmw(display, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS); +} + +void intel_display_bdw_clock_gating_vblank_in_srd(struct intel_display *display) +{ + enum pipe pipe; + + /* WaPsrDPAMaskVBlankInSRD:hsw */ + intel_de_rmw(display, CHICKEN_PAR1_1, 0, HSW_MASK_VBL_TO_PIPE_IN_SRD); + + for_each_pipe(display, pipe) { + /* WaPsrDPRSUnmaskVBlankInSRD:hsw,bdw */ + intel_de_rmw(display, CHICKEN_PIPESL_1(pipe), 0, + BDW_UNMASK_VBL_TO_REGS_IN_SRD); + } +} + +void intel_display_bdw_clock_gating_kvm_notif(struct intel_display *display) +{ + /* WaKVMNotificationOnConfigChange:bdw */ + intel_de_rmw(display, CHICKEN_PAR2_1, 0, + KVM_CONFIG_CHANGE_NOTIFICATION_SELECT); +} + +void intel_display_hsw_init_clock_gating(struct intel_display *display) +{ + enum pipe pipe; + + /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ + intel_de_rmw(display, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS); + + /* WaPsrDPAMaskVBlankInSRD:hsw */ + intel_de_rmw(display, CHICKEN_PAR1_1, 0, HSW_MASK_VBL_TO_PIPE_IN_SRD); + + for_each_pipe(display, pipe) { + /* WaPsrDPRSUnmaskVBlankInSRD:hsw,bdw */ + intel_de_rmw(display, CHICKEN_PIPESL_1(pipe), 0, + HSW_UNMASK_VBL_TO_REGS_IN_SRD); + } +} diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h index a7784db9d97a..e0300dc8b041 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h @@ -13,5 +13,9 @@ void intel_display_kbl_init_clock_gating(struct intel_display *display); void intel_display_cfl_init_clock_gating(struct intel_display *display); void intel_display_bxt_init_clock_gating(struct intel_display *display); void intel_display_glk_init_clock_gating(struct intel_display *display); +void intel_display_bdw_clock_gating_disable_fbcq(struct intel_display *display); +void intel_display_bdw_clock_gating_vblank_in_srd(struct intel_display *display); +void intel_display_bdw_clock_gating_kvm_notif(struct intel_display *display); +void intel_display_hsw_init_clock_gating(struct intel_display *display); #endif /* __INTEL_DISPLAY_CLOCK_GATING_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h index dada8dc27ea4..1cb87ba0ebeb 100644 --- a/drivers/gpu/drm/i915/display/intel_display_regs.h +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h @@ -405,6 +405,9 @@ #define SKL_EDP_PSR_FIX_RDWRAP REG_BIT(3) #define IGNORE_PSR2_HW_TRACKING REG_BIT(1) +#define CHICKEN_PAR2_1 _MMIO(0x42090) +#define KVM_CONFIG_CHANGE_NOTIFICATION_SELECT REG_BIT(14) + /* * GEN9 clock gating regs */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5d99b99b0c57..e9d7f1c3a288 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -717,9 +717,6 @@ #define CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE REG_BIT(5) #define CHICKEN3_DGMG_DONE_FIX_DISABLE REG_BIT(2) -#define CHICKEN_PAR2_1 _MMIO(0x42090) -#define KVM_CONFIG_CHANGE_NOTIFICATION_SELECT REG_BIT(14) - #define VLV_PMWGICZ _MMIO(0x1300a4) #define HSW_EDRAM_CAP _MMIO(0x120010) diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 96fe16753e58..10aa00e003be 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -284,23 +284,12 @@ static void skl_init_clock_gating(struct drm_i915_private *i915) static void bdw_init_clock_gating(struct drm_i915_private *i915) { - struct intel_display *display = i915->display; - enum pipe pipe; - - /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ - intel_uncore_rmw(&i915->uncore, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS); + intel_display_bdw_clock_gating_disable_fbcq(i915->display); /* WaSwitchSolVfFArbitrationPriority:bdw */ intel_uncore_rmw(&i915->uncore, GAM_ECOCHK, 0, HSW_ECOCHK_ARB_PRIO_SOL); - /* WaPsrDPAMaskVBlankInSRD:bdw */ - intel_uncore_rmw(&i915->uncore, CHICKEN_PAR1_1, 0, HSW_MASK_VBL_TO_PIPE_IN_SRD); - - for_each_pipe(display, pipe) { - /* WaPsrDPRSUnmaskVBlankInSRD:bdw */ - intel_uncore_rmw(&i915->uncore, CHICKEN_PIPESL_1(pipe), - 0, BDW_UNMASK_VBL_TO_REGS_IN_SRD); - } + intel_display_bdw_clock_gating_vblank_in_srd(i915->display); /* WaVSRefCountFullforceMissDisable:bdw */ /* WaDSRefCountFullforceMissDisable:bdw */ @@ -316,9 +305,7 @@ static void bdw_init_clock_gating(struct drm_i915_private *i915) /* WaProgramL3SqcReg1Default:bdw */ gen8_set_l3sqc_credits(i915, 30, 2); - /* WaKVMNotificationOnConfigChange:bdw */ - intel_uncore_rmw(&i915->uncore, CHICKEN_PAR2_1, - 0, KVM_CONFIG_CHANGE_NOTIFICATION_SELECT); + intel_display_bdw_clock_gating_kvm_notif(i915->display); intel_pch_init_clock_gating(i915->display); @@ -332,20 +319,7 @@ static void bdw_init_clock_gating(struct drm_i915_private *i915) static void hsw_init_clock_gating(struct drm_i915_private *i915) { - struct intel_display *display = i915->display; - enum pipe pipe; - - /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ - intel_uncore_rmw(&i915->uncore, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS); - - /* WaPsrDPAMaskVBlankInSRD:hsw */ - intel_uncore_rmw(&i915->uncore, CHICKEN_PAR1_1, 0, HSW_MASK_VBL_TO_PIPE_IN_SRD); - - for_each_pipe(display, pipe) { - /* WaPsrDPRSUnmaskVBlankInSRD:hsw */ - intel_uncore_rmw(&i915->uncore, CHICKEN_PIPESL_1(pipe), - 0, HSW_UNMASK_VBL_TO_REGS_IN_SRD); - } + intel_display_hsw_init_clock_gating(i915->display); /* This is required by WaCatErrorRejectionIssue:hsw */ intel_uncore_rmw(&i915->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, From 943722d70f2b8fd839e1760a6745136251c428c0 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 28 Apr 2026 12:48:25 +0300 Subject: [PATCH 142/144] drm/i915/display: move pre-HSW clock gating init to display Move the remaining pre-HSW display clock gating programming into display. This also drops display register includes from intel_clock_gating.c. Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260428095104.818360-8-luciano.coelho@intel.com Signed-off-by: Luca Coelho --- .../i915/display/intel_display_clock_gating.c | 92 ++++++++++++++++ .../i915/display/intel_display_clock_gating.h | 6 + .../gpu/drm/i915/display/intel_display_regs.h | 28 +++++ drivers/gpu/drm/i915/i915_reg.h | 28 ----- drivers/gpu/drm/i915/intel_clock_gating.c | 103 +----------------- 5 files changed, 132 insertions(+), 125 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c index 74bb88d52ba9..d036c7e5863d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.c +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.c @@ -6,6 +6,7 @@ #include #include "intel_de.h" +#include "i9xx_plane_regs.h" #include "intel_display.h" #include "intel_display_clock_gating.h" #include "intel_display_core.h" @@ -176,3 +177,94 @@ void intel_display_hsw_init_clock_gating(struct intel_display *display) HSW_UNMASK_VBL_TO_REGS_IN_SRD); } } + +void intel_display_disable_trickle_feed(struct intel_display *display) +{ + enum pipe pipe; + + for_each_pipe(display, pipe) { + intel_de_rmw(display, DSPCNTR(display, pipe), 0, + DISP_TRICKLE_FEED_DISABLE); + + intel_de_rmw(display, DSPSURF(display, pipe), 0, 0); + intel_de_posting_read(display, DSPSURF(display, pipe)); + } +} + +void intel_display_ilk_init_clock_gating(struct intel_display *display) +{ + u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; + + /* + * Required for FBC + * WaFbcDisableDpfcClockGating:ilk + */ + dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE | + ILK_DPFCUNIT_CLOCK_GATE_DISABLE | + ILK_DPFDUNIT_CLOCK_GATE_ENABLE; + + intel_de_write(display, ILK_DISPLAY_CHICKEN2, + intel_de_read(display, ILK_DISPLAY_CHICKEN2) | + ILK_DPARB_GATE | ILK_VSDPFD_FULL); + dspclk_gate |= ILK_DPARBUNIT_CLOCK_GATE_ENABLE; + intel_de_write(display, DISP_ARB_CTL, + intel_de_read(display, DISP_ARB_CTL) | + DISP_FBC_WM_DIS); + + if (display->platform.ironlake && display->platform.mobile) { + /* WaFbcAsynchFlipDisableFbcQueue:ilk */ + intel_de_rmw(display, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS); + intel_de_rmw(display, ILK_DISPLAY_CHICKEN2, 0, ILK_DPARB_GATE); + } + + intel_de_write(display, ILK_DSPCLK_GATE_D, dspclk_gate); + intel_de_rmw(display, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT); + + intel_display_disable_trickle_feed(display); +} + +void intel_display_gen6_init_clock_gating(struct intel_display *display) +{ + u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; + + intel_de_write(display, ILK_DSPCLK_GATE_D, dspclk_gate); + intel_de_rmw(display, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT); + + intel_de_write(display, ILK_DISPLAY_CHICKEN1, + intel_de_read(display, ILK_DISPLAY_CHICKEN1) | + ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS); + intel_de_write(display, ILK_DISPLAY_CHICKEN2, + intel_de_read(display, ILK_DISPLAY_CHICKEN2) | + ILK_DPARB_GATE | ILK_VSDPFD_FULL); + intel_de_write(display, ILK_DSPCLK_GATE_D, + intel_de_read(display, ILK_DSPCLK_GATE_D) | + ILK_DPARBUNIT_CLOCK_GATE_ENABLE | + ILK_DPFDUNIT_CLOCK_GATE_ENABLE); + + intel_display_disable_trickle_feed(display); +} + +void intel_display_ivb_init_clock_gating(struct intel_display *display) +{ + intel_de_write(display, ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); + intel_de_rmw(display, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS); +} + +void intel_display_g4x_init_clock_gating(struct intel_display *display) +{ + u32 dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | + OVRUNIT_CLOCK_GATE_DISABLE | + OVCUNIT_CLOCK_GATE_DISABLE; + + if (display->platform.gm45) + dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; + + intel_de_write(display, DSPCLK_GATE_D, dspclk_gate); + + intel_display_disable_trickle_feed(display); +} + +void intel_display_i965gm_init_clock_gating(struct intel_display *display) +{ + intel_de_write(display, DSPCLK_GATE_D, 0); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h index e0300dc8b041..b6dd34ca92dd 100644 --- a/drivers/gpu/drm/i915/display/intel_display_clock_gating.h +++ b/drivers/gpu/drm/i915/display/intel_display_clock_gating.h @@ -17,5 +17,11 @@ void intel_display_bdw_clock_gating_disable_fbcq(struct intel_display *display); void intel_display_bdw_clock_gating_vblank_in_srd(struct intel_display *display); void intel_display_bdw_clock_gating_kvm_notif(struct intel_display *display); void intel_display_hsw_init_clock_gating(struct intel_display *display); +void intel_display_disable_trickle_feed(struct intel_display *display); +void intel_display_ilk_init_clock_gating(struct intel_display *display); +void intel_display_gen6_init_clock_gating(struct intel_display *display); +void intel_display_ivb_init_clock_gating(struct intel_display *display); +void intel_display_g4x_init_clock_gating(struct intel_display *display); +void intel_display_i965gm_init_clock_gating(struct intel_display *display); #endif /* __INTEL_DISPLAY_CLOCK_GATING_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h index 1cb87ba0ebeb..bc508995ad8b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_regs.h +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h @@ -217,6 +217,34 @@ # define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 915-945 */ # define OVFUNIT_CLOCK_GATE_DISABLE (1 << 5) # define OVBUNIT_CLOCK_GATE_DISABLE (1 << 4) + +#define ILK_DISPLAY_CHICKEN1 _MMIO(0x42000) +#define ILK_FBCQ_DIS REG_BIT(22) +#define ILK_PABSTRETCH_DIS REG_BIT(21) +#define ILK_SABSTRETCH_DIS REG_BIT(20) +#define IVB_PRI_STRETCH_MAX_MASK REG_GENMASK(21, 20) +#define IVB_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 0) +#define IVB_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 1) +#define IVB_PRI_STRETCH_MAX_X2 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 2) +#define IVB_PRI_STRETCH_MAX_X1 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 3) +#define IVB_SPR_STRETCH_MAX_MASK REG_GENMASK(19, 18) +#define IVB_SPR_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 0) +#define IVB_SPR_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 1) +#define IVB_SPR_STRETCH_MAX_X2 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 2) +#define IVB_SPR_STRETCH_MAX_X1 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 3) + +#define ILK_DISPLAY_CHICKEN2 _MMIO(0x42004) +/* Required on all Ironlake and Sandybridge according to the B-Spec. */ +#define ILK_ELPIN_409_SELECT REG_BIT(25) +#define ILK_DPARB_GATE REG_BIT(22) +#define ILK_VSDPFD_FULL REG_BIT(21) + +#define ILK_DSPCLK_GATE_D _MMIO(0x42020) +#define ILK_VRHUNIT_CLOCK_GATE_DISABLE REG_BIT(28) +#define ILK_DPFCUNIT_CLOCK_GATE_DISABLE REG_BIT(9) +#define ILK_DPFCRUNIT_CLOCK_GATE_DISABLE REG_BIT(8) +#define ILK_DPFDUNIT_CLOCK_GATE_ENABLE REG_BIT(7) +#define ILK_DPARBUNIT_CLOCK_GATE_ENABLE REG_BIT(5) /* * This bit must be set on the 830 to prevent hangs when turning off the * overlay scaler. diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e9d7f1c3a288..64e906380131 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -494,21 +494,6 @@ #define GEN7_FF_DS_SCHED_LOAD_BALANCE (0x1 << 4) /* Default */ #define GEN7_FF_DS_SCHED_HW (0x0 << 4) -#define ILK_DISPLAY_CHICKEN1 _MMIO(0x42000) -#define ILK_FBCQ_DIS REG_BIT(22) -#define ILK_PABSTRETCH_DIS REG_BIT(21) -#define ILK_SABSTRETCH_DIS REG_BIT(20) -#define IVB_PRI_STRETCH_MAX_MASK REG_GENMASK(21, 20) -#define IVB_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 0) -#define IVB_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 1) -#define IVB_PRI_STRETCH_MAX_X2 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 2) -#define IVB_PRI_STRETCH_MAX_X1 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 3) -#define IVB_SPR_STRETCH_MAX_MASK REG_GENMASK(19, 18) -#define IVB_SPR_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 0) -#define IVB_SPR_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 1) -#define IVB_SPR_STRETCH_MAX_X2 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 2) -#define IVB_SPR_STRETCH_MAX_X1 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 3) - #define DPLL_TEST _MMIO(0x606c) #define DPLLB_TEST_SDVO_DIV_1 (0 << 22) #define DPLLB_TEST_SDVO_DIV_2 (1 << 22) @@ -700,19 +685,6 @@ #define DG1_MSTR_IRQ REG_BIT(31) #define DG1_MSTR_TILE(t) REG_BIT(t) -#define ILK_DISPLAY_CHICKEN2 _MMIO(0x42004) -/* Required on all Ironlake and Sandybridge according to the B-Spec. */ -#define ILK_ELPIN_409_SELECT REG_BIT(25) -#define ILK_DPARB_GATE REG_BIT(22) -#define ILK_VSDPFD_FULL REG_BIT(21) - -#define ILK_DSPCLK_GATE_D _MMIO(0x42020) -#define ILK_VRHUNIT_CLOCK_GATE_DISABLE REG_BIT(28) -#define ILK_DPFCUNIT_CLOCK_GATE_DISABLE REG_BIT(9) -#define ILK_DPFCRUNIT_CLOCK_GATE_DISABLE REG_BIT(8) -#define ILK_DPFDUNIT_CLOCK_GATE_ENABLE REG_BIT(7) -#define ILK_DPARBUNIT_CLOCK_GATE_ENABLE REG_BIT(5) - #define IVB_CHICKEN3 _MMIO(0x4200c) #define CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE REG_BIT(5) #define CHICKEN3_DGMG_DONE_FIX_DISABLE REG_BIT(2) diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 10aa00e003be..c27b6f9266b1 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -30,11 +30,8 @@ #include #include -#include "display/i9xx_plane_regs.h" -#include "display/intel_display.h" #include "display/intel_display_clock_gating.h" #include "display/intel_display_core.h" -#include "display/intel_display_regs.h" #include "gt/intel_engine_regs.h" #include "gt/intel_gt.h" #include "gt/intel_gt_mcr.h" @@ -68,74 +65,15 @@ static void glk_init_clock_gating(struct drm_i915_private *i915) intel_display_glk_init_clock_gating(i915->display); } -static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv) -{ - struct intel_display *display = dev_priv->display; - enum pipe pipe; - - for_each_pipe(display, pipe) { - intel_uncore_rmw(&dev_priv->uncore, DSPCNTR(display, pipe), - 0, DISP_TRICKLE_FEED_DISABLE); - - intel_uncore_rmw(&dev_priv->uncore, DSPSURF(display, pipe), - 0, 0); - intel_uncore_posting_read(&dev_priv->uncore, - DSPSURF(display, pipe)); - } -} - static void ilk_init_clock_gating(struct drm_i915_private *i915) { - u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; - - /* - * Required for FBC - * WaFbcDisableDpfcClockGating:ilk - */ - dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE | - ILK_DPFCUNIT_CLOCK_GATE_DISABLE | - ILK_DPFDUNIT_CLOCK_GATE_ENABLE; - intel_uncore_write(&i915->uncore, PCH_3DCGDIS0, MARIUNIT_CLOCK_GATE_DISABLE | SVSMUNIT_CLOCK_GATE_DISABLE); intel_uncore_write(&i915->uncore, PCH_3DCGDIS1, VFMUNIT_CLOCK_GATE_DISABLE); - /* - * According to the spec the following bits should be set in - * order to enable memory self-refresh - * The bit 22/21 of 0x42004 - * The bit 5 of 0x42020 - * The bit 15 of 0x45000 - */ - intel_uncore_write(&i915->uncore, ILK_DISPLAY_CHICKEN2, - (intel_uncore_read(&i915->uncore, ILK_DISPLAY_CHICKEN2) | - ILK_DPARB_GATE | ILK_VSDPFD_FULL)); - dspclk_gate |= ILK_DPARBUNIT_CLOCK_GATE_ENABLE; - intel_uncore_write(&i915->uncore, DISP_ARB_CTL, - (intel_uncore_read(&i915->uncore, DISP_ARB_CTL) | - DISP_FBC_WM_DIS)); - - /* - * Based on the document from hardware guys the following bits - * should be set unconditionally in order to enable FBC. - * The bit 22 of 0x42000 - * The bit 22 of 0x42004 - * The bit 7,8,9 of 0x42020. - */ - if (IS_IRONLAKE_M(i915)) { - /* WaFbcAsynchFlipDisableFbcQueue:ilk */ - intel_uncore_rmw(&i915->uncore, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS); - intel_uncore_rmw(&i915->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_DPARB_GATE); - } - - intel_uncore_write(&i915->uncore, ILK_DSPCLK_GATE_D, dspclk_gate); - - intel_uncore_rmw(&i915->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT); - - g4x_disable_trickle_feed(i915); - + intel_display_ilk_init_clock_gating(i915->display); intel_pch_init_clock_gating(i915->display); } @@ -152,11 +90,7 @@ static void gen6_check_mch_setup(struct drm_i915_private *i915) static void gen6_init_clock_gating(struct drm_i915_private *i915) { - u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; - - intel_uncore_write(&i915->uncore, ILK_DSPCLK_GATE_D, dspclk_gate); - - intel_uncore_rmw(&i915->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT); + intel_display_gen6_init_clock_gating(i915->display); intel_uncore_write(&i915->uncore, GEN6_UCGCTL1, intel_uncore_read(&i915->uncore, GEN6_UCGCTL1) | @@ -191,19 +125,6 @@ static void gen6_init_clock_gating(struct drm_i915_private *i915) * * WaFbcAsynchFlipDisableFbcQueue:snb */ - intel_uncore_write(&i915->uncore, ILK_DISPLAY_CHICKEN1, - intel_uncore_read(&i915->uncore, ILK_DISPLAY_CHICKEN1) | - ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS); - intel_uncore_write(&i915->uncore, ILK_DISPLAY_CHICKEN2, - intel_uncore_read(&i915->uncore, ILK_DISPLAY_CHICKEN2) | - ILK_DPARB_GATE | ILK_VSDPFD_FULL); - intel_uncore_write(&i915->uncore, ILK_DSPCLK_GATE_D, - intel_uncore_read(&i915->uncore, ILK_DSPCLK_GATE_D) | - ILK_DPARBUNIT_CLOCK_GATE_ENABLE | - ILK_DPFDUNIT_CLOCK_GATE_ENABLE); - - g4x_disable_trickle_feed(i915); - intel_pch_init_clock_gating(i915->display); gen6_check_mch_setup(i915); @@ -335,10 +256,7 @@ static void ivb_init_clock_gating(struct drm_i915_private *i915) { struct intel_display *display = i915->display; - intel_uncore_write(&i915->uncore, ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); - - /* WaFbcAsynchFlipDisableFbcQueue:ivb */ - intel_uncore_rmw(&i915->uncore, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS); + intel_display_ivb_init_clock_gating(display); /* WaDisableBackToBackFlipFix:ivb */ intel_uncore_write(&i915->uncore, IVB_CHICKEN3, @@ -367,7 +285,7 @@ static void ivb_init_clock_gating(struct drm_i915_private *i915) intel_uncore_rmw(&i915->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); - g4x_disable_trickle_feed(i915); + intel_display_disable_trickle_feed(display); intel_uncore_rmw(&i915->uncore, GEN6_MBCUNIT_SNPCR, GEN6_MBC_SNPCR_MASK, GEN6_MBC_SNPCR_MED); @@ -440,21 +358,12 @@ static void chv_init_clock_gating(struct drm_i915_private *i915) static void g4x_init_clock_gating(struct drm_i915_private *i915) { - u32 dspclk_gate; - intel_uncore_write(&i915->uncore, RENCLK_GATE_D1, 0); intel_uncore_write(&i915->uncore, RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE | GS_UNIT_CLOCK_GATE_DISABLE | CL_UNIT_CLOCK_GATE_DISABLE); intel_uncore_write(&i915->uncore, RAMCLK_GATE_D, 0); - dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | - OVRUNIT_CLOCK_GATE_DISABLE | - OVCUNIT_CLOCK_GATE_DISABLE; - if (IS_GM45(i915)) - dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; - intel_uncore_write(&i915->uncore, DSPCLK_GATE_D, dspclk_gate); - - g4x_disable_trickle_feed(i915); + intel_display_g4x_init_clock_gating(i915->display); } static void i965gm_init_clock_gating(struct drm_i915_private *i915) @@ -463,7 +372,7 @@ static void i965gm_init_clock_gating(struct drm_i915_private *i915) intel_uncore_write(uncore, RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); intel_uncore_write(uncore, RENCLK_GATE_D2, 0); - intel_uncore_write(uncore, DSPCLK_GATE_D, 0); + intel_display_i965gm_init_clock_gating(i915->display); intel_uncore_write(uncore, RAMCLK_GATE_D, 0); intel_uncore_write16(uncore, DEUC, 0); intel_uncore_write(uncore, From ec8ed54295b7abe431dce248bdcea1bda6c23219 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 28 Apr 2026 12:48:26 +0300 Subject: [PATCH 143/144] drm/i915: remove HAS_PCH_NOP() dependency from clock gating intel_pch_init_clock_gating() already handles unsupported PCH types, including PCH_NOP, by doing nothing. Drop the explicit HAS_PCH_NOP() check from the IVB clock gating path and always call the display helper directly. This removes one more direct dependency on display-side PCH macros from intel_clock_gating.c. Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260428095104.818360-9-luciano.coelho@intel.com Signed-off-by: Luca Coelho --- drivers/gpu/drm/i915/intel_clock_gating.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index c27b6f9266b1..86bdeb20f427 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -31,7 +31,7 @@ #include #include "display/intel_display_clock_gating.h" -#include "display/intel_display_core.h" +#include "display/intel_pch.h" #include "gt/intel_engine_regs.h" #include "gt/intel_gt.h" #include "gt/intel_gt_mcr.h" @@ -290,8 +290,7 @@ static void ivb_init_clock_gating(struct drm_i915_private *i915) intel_uncore_rmw(&i915->uncore, GEN6_MBCUNIT_SNPCR, GEN6_MBC_SNPCR_MASK, GEN6_MBC_SNPCR_MED); - if (!HAS_PCH_NOP(display)) - intel_pch_init_clock_gating(display); + intel_pch_init_clock_gating(display); gen6_check_mch_setup(i915); } From 025f89b01ed8d5e65d87ed54f231e10c6ac08188 Mon Sep 17 00:00:00 2001 From: Julian Braha Date: Sat, 2 May 2026 20:19:32 +0100 Subject: [PATCH 144/144] drm/i915: replace select with dependency for visible DEBUG_OBJECTS DRM_I915_SW_FENCE_DEBUG_OBJECTS currently selects DEBUG_OBJECTS even though DEBUG_OBJECTS is visible to users. Other config options use 'depends on' for DEBUG_OBJECTS, so let's do the same here. This select-visible Kconfig misusage was detected by Kconfirm, a static analysis tool for Kconfig. Signed-off-by: Julian Braha Link: https://patch.msgid.link/20260502191932.4491-1-julianbraha@gmail.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 3562a02ef7ad..9a2a49284876 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -153,7 +153,7 @@ config DRM_I915_TRACE_GTT config DRM_I915_SW_FENCE_DEBUG_OBJECTS bool "Enable additional driver debugging for fence objects" depends on DRM_I915 - select DEBUG_OBJECTS + depends on DEBUG_OBJECTS default n help Choose this option to turn on extra driver debugging that may affect