From de72d9df4f453c08da3d4a15ce75fbd5f891bd2e Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Tue, 11 Nov 2025 14:46:06 +0200 Subject: drm/i915/fbc: Apply Wa_15018326506 Disable FBC in bmg as per the wa recommendation. v2: use the bmg platform instead of a specific stepping v3: wa to Wa Bspec: 74212 Signed-off-by: Vinod Govindapillai Reviewed-by: Mika Kahola Acked-by: Uma Shankar Link: https://patch.msgid.link/20251111124606.402380-1-vinod.govindapillai@intel.com Signed-off-by: Vinod Govindapillai --- drivers/gpu/drm/i915/display/intel_display_wa.c | 2 ++ drivers/gpu/drm/i915/display/intel_display_wa.h | 1 + drivers/gpu/drm/i915/display/intel_fbc.c | 10 ++++++++++ 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c b/drivers/gpu/drm/i915/display/intel_display_wa.c index e38e5e87877c..b2e71fa61c0a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.c +++ b/drivers/gpu/drm/i915/display/intel_display_wa.c @@ -70,6 +70,8 @@ bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, return DISPLAY_VER(display) == 13; case INTEL_DISPLAY_WA_22014263786: return IS_DISPLAY_VERx100(display, 1100, 1400); + case INTEL_DISPLAY_WA_15018326506: + return display->platform.battlemage; default: drm_WARN(display->drm, 1, "Missing Wa number: %s\n", name); break; diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.h b/drivers/gpu/drm/i915/display/intel_display_wa.h index 3644e8e2b724..f648b00cb97d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.h +++ b/drivers/gpu/drm/i915/display/intel_display_wa.h @@ -26,6 +26,7 @@ enum intel_display_wa { INTEL_DISPLAY_WA_16025573575, INTEL_DISPLAY_WA_14011503117, INTEL_DISPLAY_WA_22014263786, + INTEL_DISPLAY_WA_15018326506, }; bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, const char *name); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 437d2fda20a7..205c7266af43 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1521,6 +1521,16 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } + /* + * Wa_15018326506: + * Fixes: Underrun during media decode + * Workaround: Do not enable FBC + */ + if (intel_display_wa(display, 15018326506)) { + plane_state->no_fbc_reason = "Wa_15018326506"; + return 0; + } + /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */ if (intel_display_vtd_active(display) && (display->platform.skylake || display->platform.broxton)) { -- cgit v1.2.3 From 37fc7b7b3ab0e3bb900657199cd3770a4fda03fb Mon Sep 17 00:00:00 2001 From: Dibin Moolakadan Subrahmanian Date: Tue, 11 Nov 2025 19:24:03 +0530 Subject: drm/i915/fbdev: Hold runtime PM ref during fbdev BO creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During fbdev probe, the xe driver allocates and pins a framebuffer BO (via xe_bo_create_pin_map_novm() → xe_ggtt_insert_bo()). Without a runtime PM reference, xe_pm_runtime_get_noresume() warns about missing outer PM protection as below: xe 0000:03:00.0: [drm] Missing outer runtime PM protection Acquire a runtime PM reference before framebuffer allocation to ensure xe_ggtt_insert_bo() executes under active runtime PM context. Changes in v2: - Update commit message to add Fixes tag (Jani Nikula) Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/6350 Fixes: 44e694958b95 ("drm/xe/display: Implement display support") Cc: Jani Nikula Signed-off-by: Dibin Moolakadan Subrahmanian Reviewed-by: Jouni Högander Signed-off-by: Ankit Nautiyal Link: https://patch.msgid.link/20251111135403.3415947-1-dibin.moolakadan.subrahmanian@intel.com --- drivers/gpu/drm/i915/display/intel_fbdev.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index e5449c41cfa1..7173bd1cbffd 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -288,13 +288,18 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, drm_framebuffer_put(&fb->base); fb = NULL; } + + wakeref = intel_display_rpm_get(display); + if (!fb || drm_WARN_ON(display->drm, !intel_fb_bo(&fb->base))) { drm_dbg_kms(display->drm, "no BIOS fb, allocating a new one\n"); fb = __intel_fbdev_fb_alloc(display, sizes); - if (IS_ERR(fb)) - return PTR_ERR(fb); + if (IS_ERR(fb)) { + ret = PTR_ERR(fb); + goto out_unlock; + } } else { drm_dbg_kms(display->drm, "re-using BIOS fb\n"); prealloc = true; @@ -302,8 +307,6 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, sizes->fb_height = fb->base.height; } - wakeref = intel_display_rpm_get(display); - /* 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. -- cgit v1.2.3 From d7e7a0048f6aceaadd19bda66de496c60b741cb1 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:31 +0200 Subject: drm/i915/cx0: Rename TBT functions to be ICL specific Rename pll functions to include ICL platform as these are used from ICL onwards. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-2-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 9c7cf03cf022..8c345e1bdd94 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -3753,9 +3753,9 @@ static bool combo_pll_get_hw_state(struct intel_display *display, return icl_pll_get_hw_state(display, pll, dpll_hw_state, enable_reg); } -static bool tbt_pll_get_hw_state(struct intel_display *display, - struct intel_dpll *pll, - struct intel_dpll_hw_state *dpll_hw_state) +static bool icl_tbt_pll_get_hw_state(struct intel_display *display, + struct intel_dpll *pll, + struct intel_dpll_hw_state *dpll_hw_state) { return icl_pll_get_hw_state(display, pll, dpll_hw_state, TBT_PLL_ENABLE); } @@ -3984,9 +3984,9 @@ static void combo_pll_enable(struct intel_display *display, /* DVFS post sequence would be here. See the comment above. */ } -static void tbt_pll_enable(struct intel_display *display, - struct intel_dpll *pll, - const struct intel_dpll_hw_state *dpll_hw_state) +static void icl_tbt_pll_enable(struct intel_display *display, + struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; @@ -4069,8 +4069,8 @@ static void combo_pll_disable(struct intel_display *display, icl_pll_disable(display, pll, enable_reg); } -static void tbt_pll_disable(struct intel_display *display, - struct intel_dpll *pll) +static void icl_tbt_pll_disable(struct intel_display *display, + struct intel_dpll *pll) { icl_pll_disable(display, pll, TBT_PLL_ENABLE); } @@ -4142,10 +4142,10 @@ static const struct intel_dpll_funcs combo_pll_funcs = { .get_freq = icl_ddi_combo_pll_get_freq, }; -static const struct intel_dpll_funcs tbt_pll_funcs = { - .enable = tbt_pll_enable, - .disable = tbt_pll_disable, - .get_hw_state = tbt_pll_get_hw_state, +static const struct intel_dpll_funcs icl_tbt_pll_funcs = { + .enable = icl_tbt_pll_enable, + .disable = icl_tbt_pll_disable, + .get_hw_state = icl_tbt_pll_get_hw_state, .get_freq = icl_ddi_tbt_pll_get_freq, }; @@ -4159,7 +4159,7 @@ static const struct intel_dpll_funcs mg_pll_funcs = { static const struct dpll_info icl_plls[] = { { .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, }, { .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, }, - { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, + { .name = "TBT PLL", .funcs = &icl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, .is_alt_port_dpll = true, }, { .name = "MG PLL 1", .funcs = &mg_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, }, { .name = "MG PLL 2", .funcs = &mg_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, }, @@ -4207,7 +4207,7 @@ static const struct intel_dpll_funcs dkl_pll_funcs = { static const struct dpll_info tgl_plls[] = { { .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, }, { .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, }, - { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, + { .name = "TBT PLL", .funcs = &icl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, .is_alt_port_dpll = true, }, { .name = "TC PLL 1", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, }, { .name = "TC PLL 2", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, }, @@ -4285,7 +4285,7 @@ static const struct intel_dpll_mgr adls_pll_mgr = { static const struct dpll_info adlp_plls[] = { { .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, }, { .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, }, - { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, + { .name = "TBT PLL", .funcs = &icl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, .is_alt_port_dpll = true, }, { .name = "TC PLL 1", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, }, { .name = "TC PLL 2", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, }, -- cgit v1.2.3 From dca0eb029f5770e18308db966cdeec4bb4b5a659 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:32 +0200 Subject: drm/i915/cx0: Factor out C10 msgbus access start/end helpers Factor out functions to begin and complete C10 PHY programming sequences to make the code more concise. v2: Rename msgbus_update_config() to more descriptive msg_bus_access_commit() (Jani) Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-3-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 62 ++++++++++++++++------------ 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index d98b4cf6b60e..e130c96d0018 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -444,6 +444,31 @@ static u8 intel_c10_get_tx_term_ctl(const struct intel_crtc_state *crtc_state) } } +static void intel_c10_msgbus_access_begin(struct intel_encoder *encoder, + u8 lane_mask) +{ + if (!intel_encoder_is_c10phy(encoder)) + return; + + intel_cx0_rmw(encoder, lane_mask, PHY_C10_VDR_CONTROL(1), + 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); +} + +static void intel_c10_msgbus_access_commit(struct intel_encoder *encoder, + u8 lane_mask, bool master_lane) +{ + u8 val = C10_VDR_CTRL_UPDATE_CFG; + + if (!intel_encoder_is_c10phy(encoder)) + return; + + if (master_lane) + val |= C10_VDR_CTRL_MASTER_LANE; + + intel_cx0_rmw(encoder, lane_mask, PHY_C10_VDR_CONTROL(1), + 0, val, MB_WRITE_COMMITTED); +} + void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { @@ -467,9 +492,9 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, return; } + intel_c10_msgbus_access_begin(encoder, owned_lane_mask); + if (intel_encoder_is_c10phy(encoder)) { - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), - 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CMN(3), C10_CMN3_TXVBOOST_MASK, C10_CMN3_TXVBOOST(intel_c10_get_tx_vboost_lvl(crtc_state)), @@ -508,9 +533,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, 0, PHY_C10_VDR_OVRD_TX1 | PHY_C10_VDR_OVRD_TX2, MB_WRITE_COMMITTED); - if (intel_encoder_is_c10phy(encoder)) - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), - 0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED); + intel_c10_msgbus_access_commit(encoder, owned_lane_mask, false); intel_cx0_phy_transaction_end(encoder, wakeref); } @@ -2114,9 +2137,7 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, * According to C10 VDR Register programming Sequence we need * to do this to read PHY internal registers from MsgBus. */ - intel_cx0_rmw(encoder, lane, PHY_C10_VDR_CONTROL(1), - 0, C10_VDR_CTRL_MSGBUS_ACCESS, - MB_WRITE_COMMITTED); + intel_c10_msgbus_access_begin(encoder, lane); for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++) pll_state->pll[i] = intel_cx0_read(encoder, lane, PHY_C10_VDR_PLL(i)); @@ -2135,9 +2156,7 @@ static void intel_c10_pll_program(struct intel_display *display, { int i; - intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1), - 0, C10_VDR_CTRL_MSGBUS_ACCESS, - MB_WRITE_COMMITTED); + intel_c10_msgbus_access_begin(encoder, INTEL_CX0_BOTH_LANES); /* Program the pll values only for the master lane */ for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++) @@ -2152,9 +2171,8 @@ static void intel_c10_pll_program(struct intel_display *display, intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH, C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10, MB_WRITE_COMMITTED); - intel_cx0_rmw(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CONTROL(1), - 0, C10_VDR_CTRL_MASTER_LANE | C10_VDR_CTRL_UPDATE_CFG, - MB_WRITE_COMMITTED); + + intel_c10_msgbus_access_commit(encoder, INTEL_CX0_LANE0, true); } static void intel_c10pll_dump_hw_state(struct intel_display *display, @@ -2938,11 +2956,7 @@ static void intel_cx0_program_phy_lane(struct intel_encoder *encoder, int lane_c bool dp_alt_mode = intel_tc_port_in_dp_alt_mode(enc_to_dig_port(encoder)); u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); - if (intel_encoder_is_c10phy(encoder)) - intel_cx0_rmw(encoder, owned_lane_mask, - PHY_C10_VDR_CONTROL(1), 0, - C10_VDR_CTRL_MSGBUS_ACCESS, - MB_WRITE_COMMITTED); + intel_c10_msgbus_access_begin(encoder, owned_lane_mask); if (lane_reversal) disables = REG_GENMASK8(3, 0) >> lane_count; @@ -2967,11 +2981,7 @@ static void intel_cx0_program_phy_lane(struct intel_encoder *encoder, int lane_c MB_WRITE_COMMITTED); } - if (intel_encoder_is_c10phy(encoder)) - intel_cx0_rmw(encoder, owned_lane_mask, - PHY_C10_VDR_CONTROL(1), 0, - C10_VDR_CTRL_UPDATE_CFG, - MB_WRITE_COMMITTED); + intel_c10_msgbus_access_commit(encoder, owned_lane_mask, false); } static u32 intel_cx0_get_pclk_pll_request(u8 lane_mask) @@ -3236,9 +3246,7 @@ void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder, wakeref = intel_cx0_phy_transaction_begin(encoder); - if (intel_encoder_is_c10phy(encoder)) - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), 0, - C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); + intel_c10_msgbus_access_begin(encoder, owned_lane_mask); for (i = 0; i < 4; i++) { int tx = i % 2 + 1; -- cgit v1.2.3 From 1cefc3ac7d8451cebcfce209c53933fb6309e4e5 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:33 +0200 Subject: drm/i915/cx0: Sanitize setting the Cx0 PLL use_c10 flag Sanitize setting the Cx0 PLL use_c10 flag during state computation and HW readout, making sure they happen the same way in the intel_c{10,20}pll_calc_state() and intel_c{10,20}pll_readout_hw_state() functions. Follow-up changes will add more state computation/HW readout, this change prepares for those as well. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-4-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index e130c96d0018..93b18dc49ee5 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2125,12 +2125,15 @@ static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, const struct intel_c10pll_state *pll_state); static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, - struct intel_c10pll_state *pll_state) + struct intel_cx0pll_state *cx0pll_state) { + struct intel_c10pll_state *pll_state = &cx0pll_state->c10; u8 lane = INTEL_CX0_LANE0; intel_wakeref_t wakeref; int i; + cx0pll_state->use_c10 = true; + wakeref = intel_cx0_phy_transaction_begin(encoder); /* @@ -2356,6 +2359,8 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, const struct intel_c20pll_state * const *tables; int i; + crtc_state->dpll_hw_state.cx0pll.use_c10 = false; + /* try computed C20 HDMI tables before using consolidated tables */ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { if (intel_c20_compute_hdmi_tmds_pll(crtc_state) == 0) @@ -2372,7 +2377,6 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, intel_cx0pll_update_ssc(encoder, &crtc_state->dpll_hw_state.cx0pll, intel_crtc_has_dp_encoder(crtc_state)); - crtc_state->dpll_hw_state.cx0pll.use_c10 = false; return 0; } } @@ -2439,13 +2443,16 @@ static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder, } static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, - struct intel_c20pll_state *pll_state) + struct intel_cx0pll_state *cx0pll_state) { + struct intel_c20pll_state *pll_state = &cx0pll_state->c20; struct intel_display *display = to_intel_display(encoder); bool cntx; intel_wakeref_t wakeref; int i; + cx0pll_state->use_c10 = false; + wakeref = intel_cx0_phy_transaction_begin(encoder); /* 1. Read current context selection */ @@ -3444,12 +3451,10 @@ void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, if (pll_state->tbt_mode) return; - if (intel_encoder_is_c10phy(encoder)) { - intel_c10pll_readout_hw_state(encoder, &pll_state->c10); - pll_state->use_c10 = true; - } else { - intel_c20pll_readout_hw_state(encoder, &pll_state->c20); - } + if (intel_encoder_is_c10phy(encoder)) + intel_c10pll_readout_hw_state(encoder, pll_state); + else + intel_c20pll_readout_hw_state(encoder, pll_state); } static bool mtl_compare_hw_state_c10(const struct intel_c10pll_state *a, -- cgit v1.2.3 From 5050d4a0af1e3b4970adf321f4a9296fe2ac532f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:34 +0200 Subject: drm/i915/cx0: Sanitize calculating C20 PLL state from tables A follow up change adds a computation for the C20 PLL VDR state, which is common to both the HDMI algorithmic and DP/HDMI table based method. To prepare for that streamline the code. The C10 counterpart would benefit from the same change, leave that for later adding a TODO comment. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-5-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 68 +++++++++++++++++++--------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 93b18dc49ee5..a1f2272fed14 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2072,6 +2072,10 @@ static void intel_c10pll_update_pll(struct intel_encoder *encoder, pll_state->c10.pll[i] = 0; } +/* + * TODO: Convert the following to align with intel_c20pll_find_table() and + * intel_c20pll_calc_state_from_table(). + */ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, const struct intel_c10pll_state * const *tables, bool is_dp, int port_clock, @@ -2325,7 +2329,7 @@ static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) } static const struct intel_c20pll_state * const * -intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state, +intel_c20_pll_tables_get(const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(crtc_state); @@ -2353,35 +2357,57 @@ intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state, return NULL; } -static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static const struct intel_c20pll_state * +intel_c20_pll_find_table(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) { const struct intel_c20pll_state * const *tables; int i; - crtc_state->dpll_hw_state.cx0pll.use_c10 = false; - - /* try computed C20 HDMI tables before using consolidated tables */ - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { - if (intel_c20_compute_hdmi_tmds_pll(crtc_state) == 0) - return 0; - } - tables = intel_c20_pll_tables_get(crtc_state, encoder); if (!tables) + return NULL; + + for (i = 0; tables[i]; i++) + if (crtc_state->port_clock == tables[i]->clock) + return tables[i]; + + return NULL; +} + +static int intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) +{ + const struct intel_c20pll_state *table; + + table = intel_c20_pll_find_table(crtc_state, encoder); + if (!table) return -EINVAL; - for (i = 0; tables[i]; i++) { - if (crtc_state->port_clock == tables[i]->clock) { - crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i]; - intel_cx0pll_update_ssc(encoder, - &crtc_state->dpll_hw_state.cx0pll, - intel_crtc_has_dp_encoder(crtc_state)); - return 0; - } - } + crtc_state->dpll_hw_state.cx0pll.c20 = *table; - return -EINVAL; + intel_cx0pll_update_ssc(encoder, &crtc_state->dpll_hw_state.cx0pll, + intel_crtc_has_dp_encoder(crtc_state)); + + return 0; +} + +static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) +{ + int err = -ENOENT; + + crtc_state->dpll_hw_state.cx0pll.use_c10 = false; + + /* try computed C20 HDMI tables before using consolidated tables */ + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + /* TODO: Update SSC state for HDMI as well */ + err = intel_c20_compute_hdmi_tmds_pll(crtc_state); + + if (err) + err = intel_c20pll_calc_state_from_table(crtc_state, encoder); + + return err; } int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, -- cgit v1.2.3 From 201c902870ec7b4141e4f403612a289701fafb80 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:35 +0200 Subject: drm/i915/cx0: Track the C20 PHY VDR state in the PLL state The Cx0 PLL enable programming needs to know if the PLL is in DP or HDMI mode. The PLL manager framework doesn't pass the CRTC state to the PLL's enable hook, so prepare here for the conversion to use the PLL manager for Cx0 PHY PLLs by tracking the DP/HDMI mode in the PLL state. This change has the advantage, that the VDR HW/SW state can be verified now. A follow up change will convert the PLL enable function to retrieve the DP/HDMI mode parameter from the PLL state. This also allows dropping the is_dp and port clock params from the intel_c20_pll_program() function, since it can retrieve these now from the PLL state. v2: Fix comment to under same multicomment line (Suraj) Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-6-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 119 +++++++++++++++++++------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 5 ++ 2 files changed, 92 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index a1f2272fed14..fd0409565c68 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2357,6 +2357,75 @@ intel_c20_pll_tables_get(const struct intel_crtc_state *crtc_state, return NULL; } +static u8 intel_c20_get_dp_rate(u32 clock); +static u8 intel_c20_get_hdmi_rate(u32 clock); +static int intel_get_c20_custom_width(u32 clock, bool dp); + +static void intel_c20_calc_vdr_params(struct intel_c20pll_vdr_state *vdr, bool is_dp, + int port_clock) +{ + vdr->custom_width = intel_get_c20_custom_width(port_clock, is_dp); + + vdr->serdes_rate = 0; + vdr->hdmi_rate = 0; + + if (is_dp) { + vdr->serdes_rate = PHY_C20_IS_DP | + PHY_C20_DP_RATE(intel_c20_get_dp_rate(port_clock)); + } else { + if (intel_hdmi_is_frl(port_clock)) + vdr->serdes_rate = PHY_C20_IS_HDMI_FRL; + + vdr->hdmi_rate = intel_c20_get_hdmi_rate(port_clock); + } +} + +#define PHY_C20_SERDES_RATE_MASK (PHY_C20_IS_DP | PHY_C20_DP_RATE_MASK | PHY_C20_IS_HDMI_FRL) + +static void intel_c20_readout_vdr_params(struct intel_encoder *encoder, + struct intel_c20pll_vdr_state *vdr, bool *cntx) +{ + u8 serdes; + + serdes = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE); + *cntx = serdes & PHY_C20_CONTEXT_TOGGLE; + + vdr->custom_width = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_WIDTH) & + PHY_C20_CUSTOM_WIDTH_MASK; + + vdr->serdes_rate = serdes & PHY_C20_SERDES_RATE_MASK; + if (!(vdr->serdes_rate & PHY_C20_IS_DP)) + vdr->hdmi_rate = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_HDMI_RATE) & + PHY_C20_HDMI_RATE_MASK; + else + vdr->hdmi_rate = 0; +} + +static void intel_c20_program_vdr_params(struct intel_encoder *encoder, + const struct intel_c20pll_vdr_state *vdr, + u8 owned_lane_mask) +{ + struct intel_display *display = to_intel_display(encoder); + + drm_WARN_ON(display->drm, vdr->custom_width & ~PHY_C20_CUSTOM_WIDTH_MASK); + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_WIDTH, + PHY_C20_CUSTOM_WIDTH_MASK, vdr->custom_width, + MB_WRITE_COMMITTED); + + drm_WARN_ON(display->drm, vdr->serdes_rate & ~PHY_C20_SERDES_RATE_MASK); + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, + PHY_C20_SERDES_RATE_MASK, vdr->serdes_rate, + MB_WRITE_COMMITTED); + + if (vdr->serdes_rate & PHY_C20_IS_DP) + return; + + drm_WARN_ON(display->drm, vdr->hdmi_rate & ~PHY_C20_HDMI_RATE_MASK); + intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE, + PHY_C20_HDMI_RATE_MASK, vdr->hdmi_rate, + MB_WRITE_COMMITTED); +} + static const struct intel_c20pll_state * intel_c20_pll_find_table(const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) @@ -2395,19 +2464,26 @@ static int intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_stat static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { + bool is_dp = intel_crtc_has_dp_encoder(crtc_state); int err = -ENOENT; crtc_state->dpll_hw_state.cx0pll.use_c10 = false; /* try computed C20 HDMI tables before using consolidated tables */ - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + if (!is_dp) /* TODO: Update SSC state for HDMI as well */ err = intel_c20_compute_hdmi_tmds_pll(crtc_state); if (err) err = intel_c20pll_calc_state_from_table(crtc_state, encoder); - return err; + if (err) + return err; + + intel_c20_calc_vdr_params(&crtc_state->dpll_hw_state.cx0pll.c20.vdr, + is_dp, crtc_state->port_clock); + + return 0; } int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, @@ -2481,8 +2557,8 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, wakeref = intel_cx0_phy_transaction_begin(encoder); - /* 1. Read current context selection */ - cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & PHY_C20_CONTEXT_TOGGLE; + /* 1. Read VDR params and current context selection */ + intel_c20_readout_vdr_params(encoder, &pll_state->vdr, &cntx); /* Read Tx configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) { @@ -2657,11 +2733,9 @@ static int intel_get_c20_custom_width(u32 clock, bool dp) static void intel_c20_pll_program(struct intel_display *display, struct intel_encoder *encoder, - const struct intel_c20pll_state *pll_state, - bool is_dp, int port_clock) + const struct intel_c20pll_state *pll_state) { u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); - u8 serdes; bool cntx; int i; @@ -2730,30 +2804,11 @@ static void intel_c20_pll_program(struct intel_display *display, } } - /* 4. Program custom width to match the link protocol */ - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_WIDTH, - PHY_C20_CUSTOM_WIDTH_MASK, - PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(port_clock, is_dp)), - MB_WRITE_COMMITTED); - - /* 5. For DP or 6. For HDMI */ - serdes = 0; - if (is_dp) - serdes = PHY_C20_IS_DP | - PHY_C20_DP_RATE(intel_c20_get_dp_rate(port_clock)); - else if (intel_hdmi_is_frl(port_clock)) - serdes = PHY_C20_IS_HDMI_FRL; - - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, - PHY_C20_IS_DP | PHY_C20_DP_RATE_MASK | PHY_C20_IS_HDMI_FRL, - serdes, - MB_WRITE_COMMITTED); - - if (!is_dp) - intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE, - PHY_C20_HDMI_RATE_MASK, - intel_c20_get_hdmi_rate(port_clock), - MB_WRITE_COMMITTED); + /* + * 4. Program custom width to match the link protocol. + * 5. For DP or 6. For HDMI + */ + intel_c20_program_vdr_params(encoder, &pll_state->vdr, owned_lane_mask); /* * 7. Write Vendor specific registers to toggle context setting to load @@ -3077,7 +3132,7 @@ static void __intel_cx0pll_enable(struct intel_encoder *encoder, if (intel_encoder_is_c10phy(encoder)) intel_c10_pll_program(display, encoder, &pll_state->c10); else - intel_c20_pll_program(display, encoder, &pll_state->c20, is_dp, port_clock); + intel_c20_pll_program(display, encoder, &pll_state->c20); /* * 6. Program the enabled and disabled owned PHY lane diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 6183da90b28d..a0238a3e7288 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -255,6 +255,11 @@ struct intel_c20pll_state { u16 mplla[10]; u16 mpllb[11]; }; + struct intel_c20pll_vdr_state { + u8 custom_width; + u8 serdes_rate; + u8 hdmi_rate; + } vdr; }; struct intel_cx0pll_state { -- cgit v1.2.3 From 7c3342213a8b73f3100e3462074f5ded4fd9d675 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:36 +0200 Subject: drm/i915/cx0: Move definition of Cx0 PHY functions earlier Move the definitions of the intel_c10pll_calc_port_clock() intel_c20_get_dp_rate() intel_c20_get_hdmi_rate() is_hdmi_frl() is_dp2() intel_get_c20_custom_width() functions earlier to avoid the forward declarations. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-7-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 203 +++++++++++++-------------- 1 file changed, 98 insertions(+), 105 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index fd0409565c68..9515157ee6b3 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2126,7 +2126,31 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, } static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, - const struct intel_c10pll_state *pll_state); + const struct intel_c10pll_state *pll_state) +{ + unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1; + unsigned int multiplier, tx_clk_div, hdmi_div, refclk = 38400; + int tmpclk = 0; + + if (pll_state->pll[0] & C10_PLL0_FRACEN) { + frac_quot = pll_state->pll[12] << 8 | pll_state->pll[11]; + frac_rem = pll_state->pll[14] << 8 | pll_state->pll[13]; + frac_den = pll_state->pll[10] << 8 | pll_state->pll[9]; + } + + multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, pll_state->pll[3]) << 8 | + pll_state->pll[2]) / 2 + 16; + + tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, pll_state->pll[15]); + hdmi_div = REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]); + + tmpclk = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) + + DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den), + 10 << (tx_clk_div + 16)); + tmpclk *= (hdmi_div ? 2 : 1); + + return tmpclk; +} static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *cx0pll_state) @@ -2357,9 +2381,79 @@ intel_c20_pll_tables_get(const struct intel_crtc_state *crtc_state, return NULL; } -static u8 intel_c20_get_dp_rate(u32 clock); -static u8 intel_c20_get_hdmi_rate(u32 clock); -static int intel_get_c20_custom_width(u32 clock, bool dp); +static u8 intel_c20_get_dp_rate(u32 clock) +{ + switch (clock) { + case 162000: /* 1.62 Gbps DP1.4 */ + return 0; + case 270000: /* 2.7 Gbps DP1.4 */ + return 1; + case 540000: /* 5.4 Gbps DP 1.4 */ + return 2; + case 810000: /* 8.1 Gbps DP1.4 */ + return 3; + case 216000: /* 2.16 Gbps eDP */ + return 4; + case 243000: /* 2.43 Gbps eDP */ + return 5; + case 324000: /* 3.24 Gbps eDP */ + return 6; + case 432000: /* 4.32 Gbps eDP */ + return 7; + case 1000000: /* 10 Gbps DP2.0 */ + return 8; + case 1350000: /* 13.5 Gbps DP2.0 */ + return 9; + case 2000000: /* 20 Gbps DP2.0 */ + return 10; + case 648000: /* 6.48 Gbps eDP*/ + return 11; + case 675000: /* 6.75 Gbps eDP*/ + return 12; + default: + MISSING_CASE(clock); + return 0; + } +} + +static u8 intel_c20_get_hdmi_rate(u32 clock) +{ + if (clock >= 25175 && clock <= 600000) + return 0; + + switch (clock) { + case 300000: /* 3 Gbps */ + case 600000: /* 6 Gbps */ + case 1200000: /* 12 Gbps */ + return 1; + case 800000: /* 8 Gbps */ + return 2; + case 1000000: /* 10 Gbps */ + return 3; + default: + MISSING_CASE(clock); + return 0; + } +} + +static bool is_dp2(u32 clock) +{ + /* DP2.0 clock rates */ + if (clock == 1000000 || clock == 1350000 || clock == 2000000) + return true; + + return false; +} + +static int intel_get_c20_custom_width(u32 clock, bool dp) +{ + if (dp && is_dp2(clock)) + return 2; + else if (intel_hdmi_is_frl(clock)) + return 1; + else + return 0; +} static void intel_c20_calc_vdr_params(struct intel_c20pll_vdr_state *vdr, bool is_dp, int port_clock) @@ -2648,70 +2742,6 @@ void intel_cx0pll_dump_hw_state(struct intel_display *display, intel_c20pll_dump_hw_state(display, &hw_state->c20); } -static u8 intel_c20_get_dp_rate(u32 clock) -{ - switch (clock) { - case 162000: /* 1.62 Gbps DP1.4 */ - return 0; - case 270000: /* 2.7 Gbps DP1.4 */ - return 1; - case 540000: /* 5.4 Gbps DP 1.4 */ - return 2; - case 810000: /* 8.1 Gbps DP1.4 */ - return 3; - case 216000: /* 2.16 Gbps eDP */ - return 4; - case 243000: /* 2.43 Gbps eDP */ - return 5; - case 324000: /* 3.24 Gbps eDP */ - return 6; - case 432000: /* 4.32 Gbps eDP */ - return 7; - case 1000000: /* 10 Gbps DP2.0 */ - return 8; - case 1350000: /* 13.5 Gbps DP2.0 */ - return 9; - case 2000000: /* 20 Gbps DP2.0 */ - return 10; - case 648000: /* 6.48 Gbps eDP*/ - return 11; - case 675000: /* 6.75 Gbps eDP*/ - return 12; - default: - MISSING_CASE(clock); - return 0; - } -} - -static u8 intel_c20_get_hdmi_rate(u32 clock) -{ - if (clock >= 25175 && clock <= 600000) - return 0; - - switch (clock) { - case 300000: /* 3 Gbps */ - case 600000: /* 6 Gbps */ - case 1200000: /* 12 Gbps */ - return 1; - case 800000: /* 8 Gbps */ - return 2; - case 1000000: /* 10 Gbps */ - return 3; - default: - MISSING_CASE(clock); - return 0; - } -} - -static bool is_dp2(u32 clock) -{ - /* DP2.0 clock rates */ - if (clock == 1000000 || clock == 1350000 || clock == 2000000) - return true; - - return false; -} - static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder) { struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); @@ -2721,16 +2751,6 @@ static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder) return intel_tc_port_in_legacy_mode(intel_dig_port); } -static int intel_get_c20_custom_width(u32 clock, bool dp) -{ - if (dp && is_dp2(clock)) - return 2; - else if (intel_hdmi_is_frl(clock)) - return 1; - else - return 0; -} - static void intel_c20_pll_program(struct intel_display *display, struct intel_encoder *encoder, const struct intel_c20pll_state *pll_state) @@ -2819,33 +2839,6 @@ static void intel_c20_pll_program(struct intel_display *display, MB_WRITE_COMMITTED); } -static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, - const struct intel_c10pll_state *pll_state) -{ - unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1; - unsigned int multiplier, tx_clk_div, hdmi_div, refclk = 38400; - int tmpclk = 0; - - if (pll_state->pll[0] & C10_PLL0_FRACEN) { - frac_quot = pll_state->pll[12] << 8 | pll_state->pll[11]; - frac_rem = pll_state->pll[14] << 8 | pll_state->pll[13]; - frac_den = pll_state->pll[10] << 8 | pll_state->pll[9]; - } - - multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, pll_state->pll[3]) << 8 | - pll_state->pll[2]) / 2 + 16; - - tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, pll_state->pll[15]); - hdmi_div = REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]); - - tmpclk = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, (multiplier << 16) + frac_quot) + - DIV_ROUND_CLOSEST(refclk * frac_rem, frac_den), - 10 << (tx_clk_div + 16)); - tmpclk *= (hdmi_div ? 2 : 1); - - return tmpclk; -} - static void intel_program_port_clock_ctl(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state, bool is_dp, int port_clock, -- cgit v1.2.3 From 4f8b1e08c28945427a46b98144c20c22d0578885 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:37 +0200 Subject: drm/i915/cx0: Add macro to get DDI port width from a register value A follow-up change will need to retrieve the DDI port field from the register value, add a macro for this. Make things symmetric with setting the field in the register. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-8-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_display_regs.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h index 9d71e26a4fa2..c14d3caa73a7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_regs.h +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h @@ -2349,8 +2349,13 @@ enum skl_power_gate { #define DDI_BUF_CTL_TC_PHY_OWNERSHIP REG_BIT(6) #define DDI_A_4_LANES REG_BIT(4) #define DDI_PORT_WIDTH_MASK REG_GENMASK(3, 1) +#define DDI_PORT_WIDTH_ENCODE(width) ((width) == 3 ? 4 : (width) - 1) +#define DDI_PORT_WIDTH_DECODE(regval) ((regval) == 4 ? 3 : (regval) + 1) #define DDI_PORT_WIDTH(width) REG_FIELD_PREP(DDI_PORT_WIDTH_MASK, \ - ((width) == 3 ? 4 : (width) - 1)) + DDI_PORT_WIDTH_ENCODE(width)) +#define DDI_PORT_WIDTH_GET(regval) DDI_PORT_WIDTH_DECODE(REG_FIELD_GET(DDI_PORT_WIDTH_MASK, \ + (regval))) + #define DDI_PORT_WIDTH_SHIFT 1 #define DDI_INIT_DISPLAY_DETECTED REG_BIT(0) -- cgit v1.2.3 From 230d4c748113d83931a5b57c844fb71faf9eebe3 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:38 +0200 Subject: drm/i915/cx0: Track the Cx0 PHY enabled lane count in the PLL state The Cx0 PLL enable programming requires the enabled lane count. The PLL manager framework doesn't pass the CRTC state to the PLL's enable hook, so prepare here for the conversion to use the PLL manager, by tracking the enabled lane count in the PLL state as well. This has the advantage, that the enabled lane count can be verified against the PHY/PLL's enabled TX lanes. This also allows dropping the lane count param from the __intel_cx0pll_enable() function, since it can retrieve this now from the PLL state. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-9-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 55 +++++++++++++++++++++++---- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 1 + 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 9515157ee6b3..2ab93d02fdf1 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -11,6 +11,7 @@ #include "intel_alpm.h" #include "intel_cx0_phy.h" #include "intel_cx0_phy_regs.h" +#include "intel_display_regs.h" #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" #include "intel_de.h" @@ -2078,7 +2079,7 @@ static void intel_c10pll_update_pll(struct intel_encoder *encoder, */ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, const struct intel_c10pll_state * const *tables, - bool is_dp, int port_clock, + bool is_dp, int port_clock, int lane_count, struct intel_cx0pll_state *pll_state) { int i; @@ -2088,7 +2089,9 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, pll_state->c10 = *tables[i]; intel_cx0pll_update_ssc(encoder, pll_state, is_dp); intel_c10pll_update_pll(encoder, pll_state); + pll_state->use_c10 = true; + pll_state->lane_count = lane_count; return 0; } @@ -2109,7 +2112,7 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, err = intel_c10pll_calc_state_from_table(encoder, tables, intel_crtc_has_dp_encoder(crtc_state), - crtc_state->port_clock, + crtc_state->port_clock, crtc_state->lane_count, &crtc_state->dpll_hw_state.cx0pll); if (err == 0 || !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) @@ -2121,6 +2124,7 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, intel_c10pll_update_pll(encoder, &crtc_state->dpll_hw_state.cx0pll); crtc_state->dpll_hw_state.cx0pll.use_c10 = true; + crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count; return 0; } @@ -2152,6 +2156,37 @@ static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, return tmpclk; } +static int readout_enabled_lane_count(struct intel_encoder *encoder) +{ + struct intel_display *display = to_intel_display(encoder); + u8 enabled_tx_lane_count = 0; + int max_tx_lane_count; + int tx_lane; + + /* + * TODO: also check inactive TX lanes in all PHY lanes owned by the + * display. For now checking only those PHY lane(s) which are owned + * based on the active TX lane count (i.e. + * 1,2 active TX lanes -> PHY lane#0 + * 3,4 active TX lanes -> PHY lane#0 and PHY lane#1). + */ + max_tx_lane_count = DDI_PORT_WIDTH_GET(intel_de_read(display, DDI_BUF_CTL(encoder->port))); + if (!drm_WARN_ON(display->drm, max_tx_lane_count == 0)) + max_tx_lane_count = roundup_pow_of_two(max_tx_lane_count); + + for (tx_lane = 0; tx_lane < max_tx_lane_count; tx_lane++) { + u8 phy_lane_mask = tx_lane < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1; + int tx = tx_lane % 2 + 1; + u8 val; + + val = intel_cx0_read(encoder, phy_lane_mask, PHY_CX0_TX_CONTROL(tx, 2)); + if (!(val & CONTROL2_DISABLE_SINGLE_TX)) + enabled_tx_lane_count++; + } + + return enabled_tx_lane_count; +} + static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *cx0pll_state) { @@ -2170,6 +2205,8 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, */ intel_c10_msgbus_access_begin(encoder, lane); + cx0pll_state->lane_count = readout_enabled_lane_count(encoder); + for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++) pll_state->pll[i] = intel_cx0_read(encoder, lane, PHY_C10_VDR_PLL(i)); @@ -2562,6 +2599,7 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, int err = -ENOENT; crtc_state->dpll_hw_state.cx0pll.use_c10 = false; + crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count; /* try computed C20 HDMI tables before using consolidated tables */ if (!is_dp) @@ -2651,6 +2689,8 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, wakeref = intel_cx0_phy_transaction_begin(encoder); + cx0pll_state->lane_count = readout_enabled_lane_count(encoder); + /* 1. Read VDR params and current context selection */ intel_c20_readout_vdr_params(encoder, &pll_state->vdr, &cntx); @@ -3089,7 +3129,7 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask) static void __intel_cx0pll_enable(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state, - bool is_dp, int port_clock, int lane_count) + bool is_dp, int port_clock) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -3131,7 +3171,7 @@ static void __intel_cx0pll_enable(struct intel_encoder *encoder, * 6. Program the enabled and disabled owned PHY lane * transmitters over message bus */ - intel_cx0_program_phy_lane(encoder, lane_count, lane_reversal); + intel_cx0_program_phy_lane(encoder, pll_state->lane_count, lane_reversal); /* * 7. Follow the Display Voltage Frequency Switching - Sequence @@ -3174,7 +3214,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, { __intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll, intel_crtc_has_dp_encoder(crtc_state), - crtc_state->port_clock, crtc_state->lane_count); + crtc_state->port_clock); } int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder) @@ -3700,6 +3740,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) for_each_intel_encoder(display->drm, encoder) { struct intel_cx0pll_state pll_state = {}; int port_clock = 162000; + int lane_count = 4; if (!intel_encoder_is_dig_port(encoder)) continue; @@ -3712,7 +3753,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) if (intel_c10pll_calc_state_from_table(encoder, mtl_c10_edp_tables, - true, port_clock, + true, port_clock, lane_count, &pll_state) < 0) { drm_WARN_ON(display->drm, "Unable to calc C10 state from the tables\n"); @@ -3723,7 +3764,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) "[ENCODER:%d:%s] Applying power saving workaround on disabled PLL\n", encoder->base.base.id, encoder->base.name); - __intel_cx0pll_enable(encoder, &pll_state, true, port_clock, 4); + __intel_cx0pll_enable(encoder, &pll_state, true, port_clock); intel_cx0pll_disable(encoder); } } diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index a0238a3e7288..a7946ff13cb6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -267,6 +267,7 @@ struct intel_cx0pll_state { struct intel_c10pll_state c10; struct intel_c20pll_state c20; }; + int lane_count; bool ssc_enabled; bool use_c10; bool tbt_mode; -- cgit v1.2.3 From 5df82b17928b8f14d7167a5e199b4cb58bfe39e1 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:39 +0200 Subject: drm/i915/cx0: Sanitize C10 PHY PLL SSC register setup Define the C10 PLL SSC register range via macros, so the HW/SW state of these register can be verified by a follow-up change, reusing these macros. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-10-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 2ab93d02fdf1..f190762e4871 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2059,6 +2059,9 @@ static void intel_cx0pll_update_ssc(struct intel_encoder *encoder, } } +#define C10_PLL_SSC_REG_START_IDX 4 +#define C10_PLL_SSC_REG_COUNT 5 + static void intel_c10pll_update_pll(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { @@ -2068,8 +2071,11 @@ static void intel_c10pll_update_pll(struct intel_encoder *encoder, if (pll_state->ssc_enabled) return; - drm_WARN_ON(display->drm, ARRAY_SIZE(pll_state->c10.pll) < 9); - for (i = 4; i < 9; i++) + drm_WARN_ON(display->drm, ARRAY_SIZE(pll_state->c10.pll) < + C10_PLL_SSC_REG_START_IDX + C10_PLL_SSC_REG_COUNT); + for (i = C10_PLL_SSC_REG_START_IDX; + i < C10_PLL_SSC_REG_START_IDX + C10_PLL_SSC_REG_COUNT; + i++) pll_state->c10.pll[i] = 0; } -- cgit v1.2.3 From 8ad92b0733030841d5a728178f5c8a6f2c3e8f78 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:40 +0200 Subject: drm/i915/cx0: Read out the Cx0 PHY SSC enabled state Read out the C10, C20 PHY PLLs SSC enabled state, so the PLL HW/SW state verification can check this state as well. C10 PHY PLLs program some PLL registers zeroed out for the non-SSC case, while programming non-zero values to the same registers for the SSC case, so check that these PLL registers being zero or non-zero matches the PLL's overall SSC-enabled state (stored in the intel_c10pll_state::ssc_enabled flag). Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-11-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index f190762e4871..4562e47042d2 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2062,6 +2062,12 @@ static void intel_cx0pll_update_ssc(struct intel_encoder *encoder, #define C10_PLL_SSC_REG_START_IDX 4 #define C10_PLL_SSC_REG_COUNT 5 +static bool intel_c10pll_ssc_enabled(const struct intel_c10pll_state *pll_state) +{ + return memchr_inv(&pll_state->pll[C10_PLL_SSC_REG_START_IDX], + 0, sizeof(pll_state->pll[0]) * C10_PLL_SSC_REG_COUNT); +} + static void intel_c10pll_update_pll(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { @@ -2193,10 +2199,20 @@ static int readout_enabled_lane_count(struct intel_encoder *encoder) return enabled_tx_lane_count; } +static bool readout_ssc_state(struct intel_encoder *encoder, bool is_mpll_b) +{ + struct intel_display *display = to_intel_display(encoder); + + return intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port)) & + (is_mpll_b ? XELPDP_SSC_ENABLE_PLLB : XELPDP_SSC_ENABLE_PLLA); +} + static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *cx0pll_state) { struct intel_c10pll_state *pll_state = &cx0pll_state->c10; + struct intel_display *display = to_intel_display(encoder); + enum phy phy = intel_encoder_to_phy(encoder); u8 lane = INTEL_CX0_LANE0; intel_wakeref_t wakeref; int i; @@ -2222,6 +2238,13 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, intel_cx0_phy_transaction_end(encoder, wakeref); pll_state->clock = intel_c10pll_calc_port_clock(encoder, pll_state); + + cx0pll_state->ssc_enabled = readout_ssc_state(encoder, true); + drm_WARN(display->drm, + cx0pll_state->ssc_enabled != intel_c10pll_ssc_enabled(pll_state), + "PHY %c: SSC enabled state (%s), doesn't match PLL configuration (%s)\n", + phy_name(phy), str_yes_no(cx0pll_state->ssc_enabled), + intel_c10pll_ssc_enabled(pll_state) ? "SSC-enabled" : "SSC-disabled"); } static void intel_c10_pll_program(struct intel_display *display, @@ -2753,6 +2776,8 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, pll_state->clock = intel_c20pll_calc_port_clock(encoder, pll_state); intel_cx0_phy_transaction_end(encoder, wakeref); + + cx0pll_state->ssc_enabled = readout_ssc_state(encoder, intel_c20phy_use_mpllb(pll_state)); } static void intel_c20pll_dump_hw_state(struct intel_display *display, -- cgit v1.2.3 From 90fd33c2626008b8c5e6c30c44b480c21ea41c2d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:41 +0200 Subject: drm/i915/cx0: Determine Cx0 PLL DP mode from PLL state The Cx0 PLL enable programming needs to know if the PLL is in DP or HDMI mode. The PLL manager framework doesn't pass the CRTC state to the PLL's enable hook, so prepare here for the conversion to use the PLL manager for Cx0 PHY PLLs by determining the DP/HDMI mode from the PLL state. For C10 PHYs use the fact that the HDMI divider value in the PLL registers are set if and only if the PLL is in HDMI mode. For C20 PHYs use the DP mode flag programmed to the VDR SERDES register, which is set if and only if the PLL is in DP mode. Assert that the above PLL/VDR SERDES register values match the DP/HDMI mode being configured already during state computation. This also allows dropping the is_dp param from the __intel_cx0pll_enable() function, since it can retrieve this now from the PLL state. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-12-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 43 +++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 4562e47042d2..29dfbd60c7ce 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2085,6 +2085,24 @@ static void intel_c10pll_update_pll(struct intel_encoder *encoder, pll_state->c10.pll[i] = 0; } +static bool c10pll_state_is_dp(const struct intel_c10pll_state *pll_state) +{ + return !REG_FIELD_GET8(C10_PLL15_HDMIDIV_MASK, pll_state->pll[15]); +} + +static bool c20pll_state_is_dp(const struct intel_c20pll_state *pll_state) +{ + return pll_state->vdr.serdes_rate & PHY_C20_IS_DP; +} + +static bool cx0pll_state_is_dp(const struct intel_cx0pll_state *pll_state) +{ + if (pll_state->use_c10) + return c10pll_state_is_dp(&pll_state->c10); + + return c20pll_state_is_dp(&pll_state->c20); +} + /* * TODO: Convert the following to align with intel_c20pll_find_table() and * intel_c20pll_calc_state_from_table(). @@ -2094,6 +2112,7 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, bool is_dp, int port_clock, int lane_count, struct intel_cx0pll_state *pll_state) { + struct intel_display *display = to_intel_display(encoder); int i; for (i = 0; tables[i]; i++) { @@ -2105,6 +2124,8 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, pll_state->use_c10 = true; pll_state->lane_count = lane_count; + drm_WARN_ON(display->drm, is_dp != c10pll_state_is_dp(&pll_state->c10)); + return 0; } } @@ -2115,6 +2136,8 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); + bool is_dp = intel_crtc_has_dp_encoder(crtc_state); const struct intel_c10pll_state * const *tables; int err; @@ -2122,8 +2145,7 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, if (!tables) return -EINVAL; - err = intel_c10pll_calc_state_from_table(encoder, tables, - intel_crtc_has_dp_encoder(crtc_state), + err = intel_c10pll_calc_state_from_table(encoder, tables, is_dp, crtc_state->port_clock, crtc_state->lane_count, &crtc_state->dpll_hw_state.cx0pll); @@ -2138,6 +2160,9 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, crtc_state->dpll_hw_state.cx0pll.use_c10 = true; crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count; + drm_WARN_ON(display->drm, + is_dp != c10pll_state_is_dp(&crtc_state->dpll_hw_state.cx0pll.c10)); + return 0; } @@ -2624,6 +2649,7 @@ static int intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_stat static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); bool is_dp = intel_crtc_has_dp_encoder(crtc_state); int err = -ENOENT; @@ -2644,6 +2670,9 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, intel_c20_calc_vdr_params(&crtc_state->dpll_hw_state.cx0pll.c20.vdr, is_dp, crtc_state->port_clock); + drm_WARN_ON(display->drm, + is_dp != c20pll_state_is_dp(&crtc_state->dpll_hw_state.cx0pll.c20)); + return 0; } @@ -2912,10 +2941,11 @@ static void intel_c20_pll_program(struct intel_display *display, static void intel_program_port_clock_ctl(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state, - bool is_dp, int port_clock, + int port_clock, bool lane_reversal) { struct intel_display *display = to_intel_display(encoder); + bool is_dp = cx0pll_state_is_dp(pll_state); u32 val = 0; intel_de_rmw(display, XELPDP_PORT_BUF_CTL1(display, encoder->port), @@ -3160,7 +3190,7 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask) static void __intel_cx0pll_enable(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state, - bool is_dp, int port_clock) + int port_clock) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -3174,7 +3204,7 @@ static void __intel_cx0pll_enable(struct intel_encoder *encoder, * 1. Program PORT_CLOCK_CTL REGISTER to configure * clock muxes, gating and SSC */ - intel_program_port_clock_ctl(encoder, pll_state, is_dp, port_clock, lane_reversal); + intel_program_port_clock_ctl(encoder, pll_state, port_clock, lane_reversal); /* 2. Bring PHY out of reset. */ intel_cx0_phy_lane_reset(encoder, lane_reversal); @@ -3244,7 +3274,6 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { __intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll, - intel_crtc_has_dp_encoder(crtc_state), crtc_state->port_clock); } @@ -3795,7 +3824,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) "[ENCODER:%d:%s] Applying power saving workaround on disabled PLL\n", encoder->base.base.id, encoder->base.name); - __intel_cx0pll_enable(encoder, &pll_state, true, port_clock); + __intel_cx0pll_enable(encoder, &pll_state, port_clock); intel_cx0pll_disable(encoder); } } -- cgit v1.2.3 From 538187f17acd4bf94dfc98cdd8630559324fad43 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:42 +0200 Subject: drm/i915/cx0: Determine Cx0 PLL port clock from PLL state The port clock is tracked in the PLL state, so there is no need to pass it separately to __intel_cx0pll_enable(). Drop the port clock function param accordingly. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-13-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 29dfbd60c7ce..0ad9fae230c9 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3188,10 +3188,10 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask) return val; } -static void __intel_cx0pll_enable(struct intel_encoder *encoder, - const struct intel_cx0pll_state *pll_state, - int port_clock) +static void intel_cx0pll_enable(struct intel_encoder *encoder, + const struct intel_cx0pll_state *pll_state) { + int port_clock = pll_state->use_c10 ? pll_state->c10.clock : pll_state->c20.clock; struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); @@ -3270,13 +3270,6 @@ static void __intel_cx0pll_enable(struct intel_encoder *encoder, intel_cx0_phy_transaction_end(encoder, wakeref); } -static void intel_cx0pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) -{ - __intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll, - crtc_state->port_clock); -} - int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); @@ -3403,7 +3396,7 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder, if (intel_tc_port_in_tbt_alt_mode(dig_port)) intel_mtl_tbt_pll_enable(encoder, crtc_state); else - intel_cx0pll_enable(encoder, crtc_state); + intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll); } /* @@ -3824,7 +3817,7 @@ void intel_cx0_pll_power_save_wa(struct intel_display *display) "[ENCODER:%d:%s] Applying power saving workaround on disabled PLL\n", encoder->base.base.id, encoder->base.name); - __intel_cx0pll_enable(encoder, &pll_state, port_clock); + intel_cx0pll_enable(encoder, &pll_state); intel_cx0pll_disable(encoder); } } -- cgit v1.2.3 From 36a3efb32ed2eb3986be4bb02e2f298d0ff055e8 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:43 +0200 Subject: drm/i915/cx0: Zero Cx0 PLL state before compute and HW readout Ensure Cx0 pll state is initialized to zero before any computation or HW readouts, to prevent leaving some parameter in the state uninitialized in the actual compute/HW readout functions later. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-14-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 0ad9fae230c9..df3daa81a698 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2679,6 +2679,8 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { + memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); + if (intel_encoder_is_c10phy(encoder)) return intel_c10pll_calc_state(crtc_state, encoder); return intel_c20pll_calc_state(crtc_state, encoder); @@ -3612,7 +3614,7 @@ static void intel_c10pll_state_verify(const struct intel_crtc_state *state, void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { - pll_state->use_c10 = false; + memset(pll_state, 0, sizeof(*pll_state)); pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)); if (pll_state->tbt_mode) -- cgit v1.2.3 From fb1dc1eab618f24ead88e2ea7ac057679eac4faf Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:44 +0200 Subject: drm/i915/cx0: Print additional Cx0 PLL HW state Print all the Cx0 PLL state in the PLL state dumper. v2: Use BUILD_BUG_ON() instead of WARN_ON() (Jani) Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-15-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index df3daa81a698..763546fe152b 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2306,8 +2306,8 @@ static void intel_c10pll_dump_hw_state(struct intel_display *display, unsigned int multiplier, tx_clk_div; fracen = hw_state->pll[0] & C10_PLL0_FRACEN; - drm_dbg_kms(display->drm, "c10pll_hw_state: fracen: %s, ", - str_yes_no(fracen)); + drm_dbg_kms(display->drm, "c10pll_hw_state: clock: %d, fracen: %s, ", + hw_state->clock, str_yes_no(fracen)); if (fracen) { frac_quot = hw_state->pll[12] << 8 | hw_state->pll[11]; @@ -2816,7 +2816,7 @@ static void intel_c20pll_dump_hw_state(struct intel_display *display, { int i; - drm_dbg_kms(display->drm, "c20pll_hw_state:\n"); + drm_dbg_kms(display->drm, "c20pll_hw_state clock: %d:\n", hw_state->clock); drm_dbg_kms(display->drm, "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n", hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]); @@ -2832,12 +2832,24 @@ static void intel_c20pll_dump_hw_state(struct intel_display *display, for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++) drm_dbg_kms(display->drm, "mplla[%d] = 0x%.4x\n", i, hw_state->mplla[i]); + + /* For full coverage, also print the additional PLL B entry. */ + BUILD_BUG_ON(ARRAY_SIZE(hw_state->mplla) + 1 != ARRAY_SIZE(hw_state->mpllb)); + drm_dbg_kms(display->drm, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]); } + + drm_dbg_kms(display->drm, "vdr: custom width: 0x%02x, serdes rate: 0x%02x, hdmi rate: 0x%02x\n", + hw_state->vdr.custom_width, hw_state->vdr.serdes_rate, hw_state->vdr.hdmi_rate); } void intel_cx0pll_dump_hw_state(struct intel_display *display, const struct intel_cx0pll_state *hw_state) { + drm_dbg_kms(display->drm, + "cx0pll_hw_state: lane_count: %d, ssc_enabled: %s, use_c10: %s, tbt_mode: %s\n", + hw_state->lane_count, str_yes_no(hw_state->ssc_enabled), + str_yes_no(hw_state->use_c10), str_yes_no(hw_state->tbt_mode)); + if (hw_state->use_c10) intel_c10pll_dump_hw_state(display, &hw_state->c10); else -- cgit v1.2.3 From ac3423721117a6ad2e643ba74770e118124eff27 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:45 +0200 Subject: drm/i915/cx0: Remove state verification When pll's are moved to dpll framework we no longer need Cx0 specific state verification as we can rely on dpll state verification instead. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-16-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 114 --------------------- drivers/gpu/drm/i915/display/intel_cx0_phy.h | 2 - .../gpu/drm/i915/display/intel_modeset_verify.c | 1 - 3 files changed, 117 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 763546fe152b..31db79f0636b 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3594,35 +3594,6 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder, return ICL_PORT_DPLL_DEFAULT; } -static void intel_c10pll_state_verify(const struct intel_crtc_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder, - struct intel_c10pll_state *mpllb_hw_state) -{ - struct intel_display *display = to_intel_display(state); - const struct intel_c10pll_state *mpllb_sw_state = &state->dpll_hw_state.cx0pll.c10; - int i; - - for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) { - u8 expected = mpllb_sw_state->pll[i]; - - INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->pll[i] != expected, - "[CRTC:%d:%s] mismatch in C10MPLLB: Register[%d] (expected 0x%02x, found 0x%02x)", - crtc->base.base.id, crtc->base.name, i, - expected, mpllb_hw_state->pll[i]); - } - - INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->tx != mpllb_sw_state->tx, - "[CRTC:%d:%s] mismatch in C10MPLLB: Register TX0 (expected 0x%02x, found 0x%02x)", - crtc->base.base.id, crtc->base.name, - mpllb_sw_state->tx, mpllb_hw_state->tx); - - INTEL_DISPLAY_STATE_WARN(display, mpllb_hw_state->cmn != mpllb_sw_state->cmn, - "[CRTC:%d:%s] mismatch in C10MPLLB: Register CMN0 (expected 0x%02x, found 0x%02x)", - crtc->base.base.id, crtc->base.name, - mpllb_sw_state->cmn, mpllb_hw_state->cmn); -} - void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { @@ -3699,91 +3670,6 @@ int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, return intel_c20pll_calc_port_clock(encoder, &pll_state->c20); } -static void intel_c20pll_state_verify(const struct intel_crtc_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder, - struct intel_c20pll_state *mpll_hw_state) -{ - struct intel_display *display = to_intel_display(state); - const struct intel_c20pll_state *mpll_sw_state = &state->dpll_hw_state.cx0pll.c20; - bool sw_use_mpllb = intel_c20phy_use_mpllb(mpll_sw_state); - bool hw_use_mpllb = intel_c20phy_use_mpllb(mpll_hw_state); - int clock = intel_c20pll_calc_port_clock(encoder, mpll_sw_state); - int i; - - INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->clock != clock, - "[CRTC:%d:%s] mismatch in C20: Register CLOCK (expected %d, found %d)", - crtc->base.base.id, crtc->base.name, - mpll_sw_state->clock, mpll_hw_state->clock); - - INTEL_DISPLAY_STATE_WARN(display, sw_use_mpllb != hw_use_mpllb, - "[CRTC:%d:%s] mismatch in C20: Register MPLLB selection (expected %d, found %d)", - crtc->base.base.id, crtc->base.name, - sw_use_mpllb, hw_use_mpllb); - - if (hw_use_mpllb) { - for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mpllb); i++) { - INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->mpllb[i] != mpll_sw_state->mpllb[i], - "[CRTC:%d:%s] mismatch in C20MPLLB: Register[%d] (expected 0x%04x, found 0x%04x)", - crtc->base.base.id, crtc->base.name, i, - mpll_sw_state->mpllb[i], mpll_hw_state->mpllb[i]); - } - } else { - for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) { - INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->mplla[i] != mpll_sw_state->mplla[i], - "[CRTC:%d:%s] mismatch in C20MPLLA: Register[%d] (expected 0x%04x, found 0x%04x)", - crtc->base.base.id, crtc->base.name, i, - mpll_sw_state->mplla[i], mpll_hw_state->mplla[i]); - } - } - - for (i = 0; i < ARRAY_SIZE(mpll_sw_state->tx); i++) { - INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->tx[i] != mpll_sw_state->tx[i], - "[CRTC:%d:%s] mismatch in C20: Register TX[%i] (expected 0x%04x, found 0x%04x)", - crtc->base.base.id, crtc->base.name, i, - mpll_sw_state->tx[i], mpll_hw_state->tx[i]); - } - - for (i = 0; i < ARRAY_SIZE(mpll_sw_state->cmn); i++) { - INTEL_DISPLAY_STATE_WARN(display, mpll_hw_state->cmn[i] != mpll_sw_state->cmn[i], - "[CRTC:%d:%s] mismatch in C20: Register CMN[%i] (expected 0x%04x, found 0x%04x)", - crtc->base.base.id, crtc->base.name, i, - mpll_sw_state->cmn[i], mpll_hw_state->cmn[i]); - } -} - -void intel_cx0pll_state_verify(struct intel_atomic_state *state, - struct intel_crtc *crtc) -{ - struct intel_display *display = to_intel_display(state); - const struct intel_crtc_state *new_crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); - struct intel_encoder *encoder; - struct intel_cx0pll_state mpll_hw_state = {}; - - if (!IS_DISPLAY_VER(display, 14, 30)) - return; - - if (!new_crtc_state->hw.active) - return; - - /* intel_get_crtc_new_encoder() only works for modeset/fastset commits */ - if (!intel_crtc_needs_modeset(new_crtc_state) && - !intel_crtc_needs_fastset(new_crtc_state)) - return; - - encoder = intel_get_crtc_new_encoder(state, new_crtc_state); - intel_cx0pll_readout_hw_state(encoder, &mpll_hw_state); - - if (mpll_hw_state.tbt_mode) - return; - - if (intel_encoder_is_c10phy(encoder)) - intel_c10pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c10); - else - intel_c20pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c20); -} - /* * WA 14022081154 * The dedicated display PHYs reset to a power state that blocks S0ix, increasing idle diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index 84d334b865f7..0b98892ee8ac 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -40,8 +40,6 @@ int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, void intel_cx0pll_dump_hw_state(struct intel_display *display, const struct intel_cx0pll_state *hw_state); -void intel_cx0pll_state_verify(struct intel_atomic_state *state, - struct intel_crtc *crtc); bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a, const struct intel_cx0pll_state *b); void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c index b361a77cd235..12a00121c274 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c @@ -246,7 +246,6 @@ void intel_modeset_verify_crtc(struct intel_atomic_state *state, verify_crtc_state(state, crtc); intel_dpll_state_verify(state, crtc); intel_mpllb_state_verify(state, crtc); - intel_cx0pll_state_verify(state, crtc); intel_lt_phy_pll_state_verify(state, crtc); } -- cgit v1.2.3 From b5c0256a587eb50920ade41dd1b086039ec6bcfd Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:46 +0200 Subject: drm/i915/cx0: Add PLL information for MTL+ Start bringing MTL+ platforms as part of PLL framework. The work is started by adding PLL information and related function hooks. BSpec: 55726 v2: Revise commit message and add BSpec ID (Suraj) Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-17-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 8c345e1bdd94..23f22c495ec7 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4305,6 +4305,25 @@ static const struct intel_dpll_mgr adlp_pll_mgr = { .compare_hw_state = icl_compare_hw_state, }; +static const struct intel_dpll_funcs mtl_pll_funcs = { +}; + +static const struct dpll_info mtl_plls[] = { + { .name = "DPLL 0", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_DPLL0, }, + { .name = "DPLL 1", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_DPLL1, }, + /* TODO: Add TBT PLL */ + { .name = "TC PLL 1", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, }, + { .name = "TC PLL 2", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, }, + { .name = "TC PLL 3", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL3, }, + { .name = "TC PLL 4", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL4, }, + {} +}; + +__maybe_unused +static const struct intel_dpll_mgr mtl_pll_mgr = { + .dpll_info = mtl_plls, +}; + /** * intel_dpll_init - Initialize DPLLs * @display: intel_display device -- cgit v1.2.3 From d174cfb51dce71778822a8ab2dde772dad947409 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:47 +0200 Subject: drm/i915/cx0: Update C10/C20 state calculation Update several functions in intel_cx0_phy.c to make PLL state management more explicit. Changes include * add 'const' qualifiers to intel_crtc_state parameter for cx0 state calculation functions * refactor C10/C20 PLL state calculations helpers to take explicit hardware state pointers instead of directly modifying 'crtc_state->dpll_hw_state' Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-18-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 68 ++++++++++++++-------------- drivers/gpu/drm/i915/display/intel_cx0_phy.h | 5 +- drivers/gpu/drm/i915/display/intel_dpll.c | 2 +- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 31db79f0636b..de71805a065c 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2029,7 +2029,7 @@ static const struct intel_c20pll_state * const mtl_c20_hdmi_tables[] = { }; static const struct intel_c10pll_state * const * -intel_c10pll_tables_get(struct intel_crtc_state *crtc_state, +intel_c10pll_tables_get(const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { if (intel_crtc_has_dp_encoder(crtc_state)) { @@ -2133,8 +2133,9 @@ static int intel_c10pll_calc_state_from_table(struct intel_encoder *encoder, return -EINVAL; } -static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static int intel_c10pll_calc_state(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder, + struct intel_dpll_hw_state *hw_state) { struct intel_display *display = to_intel_display(encoder); bool is_dp = intel_crtc_has_dp_encoder(crtc_state); @@ -2147,21 +2148,20 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, err = intel_c10pll_calc_state_from_table(encoder, tables, is_dp, crtc_state->port_clock, crtc_state->lane_count, - &crtc_state->dpll_hw_state.cx0pll); + &hw_state->cx0pll); if (err == 0 || !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) return err; /* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */ - intel_snps_hdmi_pll_compute_c10pll(&crtc_state->dpll_hw_state.cx0pll.c10, + intel_snps_hdmi_pll_compute_c10pll(&hw_state->cx0pll.c10, crtc_state->port_clock); - intel_c10pll_update_pll(encoder, - &crtc_state->dpll_hw_state.cx0pll); - crtc_state->dpll_hw_state.cx0pll.use_c10 = true; - crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count; + intel_c10pll_update_pll(encoder, &hw_state->cx0pll); - drm_WARN_ON(display->drm, - is_dp != c10pll_state_is_dp(&crtc_state->dpll_hw_state.cx0pll.c10)); + hw_state->cx0pll.use_c10 = true; + hw_state->cx0pll.lane_count = crtc_state->lane_count; + + drm_WARN_ON(display->drm, is_dp != c10pll_state_is_dp(&hw_state->cx0pll.c10)); return 0; } @@ -2350,7 +2350,7 @@ static bool is_arrowlake_s_by_host_bridge(void) return pdev && IS_ARROWLAKE_S_BY_HOST_BRIDGE_ID(host_bridge_pci_dev_id); } -static u16 intel_c20_hdmi_tmds_tx_cgf_1(struct intel_crtc_state *crtc_state) +static u16 intel_c20_hdmi_tmds_tx_cgf_1(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); u16 tx_misc; @@ -2374,9 +2374,9 @@ static u16 intel_c20_hdmi_tmds_tx_cgf_1(struct intel_crtc_state *crtc_state) C20_PHY_TX_DCC_BYPASS | C20_PHY_TX_TERM_CTL(tx_term_ctrl)); } -static int intel_c20_compute_hdmi_tmds_pll(struct intel_crtc_state *crtc_state) +static int intel_c20_compute_hdmi_tmds_pll(const struct intel_crtc_state *crtc_state, + struct intel_c20pll_state *pll_state) { - struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20; u64 datarate; u64 mpll_tx_clk_div; u64 vco_freq_shift; @@ -2629,8 +2629,9 @@ intel_c20_pll_find_table(const struct intel_crtc_state *crtc_state, return NULL; } -static int intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static int intel_c20pll_calc_state_from_table(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder, + struct intel_cx0pll_state *pll_state) { const struct intel_c20pll_state *table; @@ -2638,52 +2639,53 @@ static int intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_stat if (!table) return -EINVAL; - crtc_state->dpll_hw_state.cx0pll.c20 = *table; + pll_state->c20 = *table; - intel_cx0pll_update_ssc(encoder, &crtc_state->dpll_hw_state.cx0pll, - intel_crtc_has_dp_encoder(crtc_state)); + intel_cx0pll_update_ssc(encoder, pll_state, intel_crtc_has_dp_encoder(crtc_state)); return 0; } -static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static int intel_c20pll_calc_state(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder, + struct intel_dpll_hw_state *hw_state) { struct intel_display *display = to_intel_display(encoder); bool is_dp = intel_crtc_has_dp_encoder(crtc_state); int err = -ENOENT; - crtc_state->dpll_hw_state.cx0pll.use_c10 = false; - crtc_state->dpll_hw_state.cx0pll.lane_count = crtc_state->lane_count; + hw_state->cx0pll.use_c10 = false; + hw_state->cx0pll.lane_count = crtc_state->lane_count; /* try computed C20 HDMI tables before using consolidated tables */ if (!is_dp) /* TODO: Update SSC state for HDMI as well */ - err = intel_c20_compute_hdmi_tmds_pll(crtc_state); + err = intel_c20_compute_hdmi_tmds_pll(crtc_state, &hw_state->cx0pll.c20); if (err) - err = intel_c20pll_calc_state_from_table(crtc_state, encoder); + err = intel_c20pll_calc_state_from_table(crtc_state, encoder, + &hw_state->cx0pll); if (err) return err; - intel_c20_calc_vdr_params(&crtc_state->dpll_hw_state.cx0pll.c20.vdr, + intel_c20_calc_vdr_params(&hw_state->cx0pll.c20.vdr, is_dp, crtc_state->port_clock); - drm_WARN_ON(display->drm, - is_dp != c20pll_state_is_dp(&crtc_state->dpll_hw_state.cx0pll.c20)); + drm_WARN_ON(display->drm, is_dp != c20pll_state_is_dp(&hw_state->cx0pll.c20)); return 0; } -int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +int intel_cx0pll_calc_state(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder, + struct intel_dpll_hw_state *hw_state) { - memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); + memset(hw_state, 0, sizeof(*hw_state)); if (intel_encoder_is_c10phy(encoder)) - return intel_c10pll_calc_state(crtc_state, encoder); - return intel_c20pll_calc_state(crtc_state, encoder); + return intel_c10pll_calc_state(crtc_state, encoder, hw_state); + return intel_c20pll_calc_state(crtc_state, encoder, hw_state); } static bool intel_c20phy_use_mpllb(const struct intel_c20pll_state *state) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index 0b98892ee8ac..d52e864f5e19 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -19,6 +19,7 @@ struct intel_crtc; struct intel_crtc_state; struct intel_cx0pll_state; struct intel_display; +struct intel_dpll_hw_state; struct intel_encoder; struct intel_hdmi; @@ -32,7 +33,9 @@ enum icl_port_dpll_id intel_mtl_port_pll_type(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); -int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder); +int intel_cx0pll_calc_state(const struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder, + struct intel_dpll_hw_state *hw_state); void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state); int intel_cx0pll_calc_port_clock(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 4f1db8493a2e..342d46b7b1af 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1221,7 +1221,7 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state, intel_get_crtc_new_encoder(state, crtc_state); int ret; - ret = intel_cx0pll_calc_state(crtc_state, encoder); + ret = intel_cx0pll_calc_state(crtc_state, encoder, &crtc_state->dpll_hw_state); if (ret) return ret; -- cgit v1.2.3 From 28d5533f2787c67fbfdb29018c8ef56ba964147f Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:48 +0200 Subject: drm/i915/cx0: Compute plls for MTL+ platform To bring MTL+ platform aligned call and calculate PLL state from dpll framework. v2: Rename mtl_compute_c10phy_dpll() to mtl_compute_non_tc_phy_dpll(). The state is computed either for a C10 or on the PTL port B eDP over TypeC PHY case for a C20 PHY PLL. Hence refer to this case as "non_tc_phy" instead of "c10phy". Rename mtl_compute_c20phy_dplls() to mtl_compute_tc_phy_dplls() for symmetry with mtl_compute_non_tc_phy_dpll(). v3: Reword commit message (Suraj) Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-19-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 69 +++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 23f22c495ec7..20f940110faa 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4319,9 +4319,78 @@ static const struct dpll_info mtl_plls[] = { {} }; +/* + * Compute the state for either a C10 PHY PLL, or in the case of the PTL port B, + * eDP on TypeC PHY case for a C20 PHY PLL. + */ +static int mtl_compute_non_tc_phy_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + struct icl_port_dpll *port_dpll = + &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; + int ret; + + ret = intel_cx0pll_calc_state(crtc_state, encoder, &port_dpll->hw_state); + if (ret) + return ret; + + /* this is mainly for the fastset check */ + icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT); + + crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, + &port_dpll->hw_state.cx0pll); + + return 0; +} + +static int mtl_compute_tc_phy_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + struct icl_port_dpll *port_dpll; + int ret; + + /* TODO: Add state calculation for TBT PLL */ + + port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; + ret = intel_cx0pll_calc_state(crtc_state, encoder, &port_dpll->hw_state); + if (ret) + return ret; + + /* this is mainly for the fastset check */ + if (old_crtc_state->intel_dpll && + old_crtc_state->intel_dpll->info->id == DPLL_ID_ICL_TBTPLL) + icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT); + else + icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_MG_PHY); + + crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, + &port_dpll->hw_state.cx0pll); + + return 0; +} + +static int mtl_compute_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + if (intel_encoder_is_tc(encoder)) + return mtl_compute_tc_phy_dplls(state, crtc, encoder); + else + return mtl_compute_non_tc_phy_dpll(state, crtc, encoder); +} + __maybe_unused static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, + .compute_dplls = mtl_compute_dplls, }; /** -- cgit v1.2.3 From ca1eda5cd476ca5c948e697af528694071f0f92a Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:49 +0200 Subject: drm/i915/cx0: Add MTL+ .get_dplls hook Add .get_dplls function pointer for MTL+ platforms to support dpll framework. Reuse the ICL function pointer. v2: Getting configuration either for a C10 or on the PTL port B eDP on TypeC PHY case for a C20 PHY PLL. Hence refer to this case as "non_tc_phy" instead of "c10phy". v3: Fix comment to "eDP over TypeC" (Suraj) Fix pll id as separate variable (Suraj) Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-20-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 57 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 1 + 2 files changed, 58 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 20f940110faa..313cb244d5d6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -203,6 +203,22 @@ enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port) return tc_port - TC_PORT_1 + DPLL_ID_ICL_MGPLL1; } +enum intel_dpll_id mtl_port_to_pll_id(struct intel_display *display, enum port port) +{ + if (port >= PORT_TC1) + return icl_tc_port_to_pll_id(intel_port_to_tc(display, port)); + + switch (port) { + case PORT_A: + return DPLL_ID_ICL_DPLL0; + case PORT_B: + return DPLL_ID_ICL_DPLL1; + default: + MISSING_CASE(port); + return DPLL_ID_ICL_DPLL0; + } +} + static i915_reg_t intel_combo_pll_enable_reg(struct intel_display *display, struct intel_dpll *pll) @@ -3490,6 +3506,36 @@ err_unreference_tbt_pll: return ret; } +/* + * Get the PLL for either a port using a C10 PHY PLL, or in the + * PTL port B eDP over TypeC PHY case, the PLL for a port using + * a C20 PHY PLL. + */ +static int mtl_get_non_tc_phy_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct intel_display *display = to_intel_display(crtc); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + struct icl_port_dpll *port_dpll = + &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; + enum intel_dpll_id pll_id = mtl_port_to_pll_id(display, encoder->port); + + port_dpll->pll = intel_find_dpll(state, crtc, + &port_dpll->hw_state, + BIT(pll_id)); + if (!port_dpll->pll) + return -EINVAL; + + intel_reference_dpll(state, crtc, + port_dpll->pll, &port_dpll->hw_state); + + icl_update_active_dpll(state, crtc, encoder); + + return 0; +} + static int icl_compute_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) @@ -4387,10 +4433,21 @@ static int mtl_compute_dplls(struct intel_atomic_state *state, return mtl_compute_non_tc_phy_dpll(state, crtc, encoder); } +static int mtl_get_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + if (intel_encoder_is_tc(encoder)) + return icl_get_tc_phy_dplls(state, crtc, encoder); + else + return mtl_get_non_tc_phy_dpll(state, crtc, encoder); +} + __maybe_unused static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, .compute_dplls = mtl_compute_dplls, + .get_dplls = mtl_get_dplls, }; /** diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index a7946ff13cb6..322af5c55d7c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -450,6 +450,7 @@ bool intel_dpll_compare_hw_state(struct intel_display *display, const struct intel_dpll_hw_state *a, const struct intel_dpll_hw_state *b); enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port); +enum intel_dpll_id mtl_port_to_pll_id(struct intel_display *display, enum port port); bool intel_dpll_is_combophy(enum intel_dpll_id id); void intel_dpll_state_verify(struct intel_atomic_state *state, -- cgit v1.2.3 From 051964d94adc7b2f16921c1fc1969f7910d7129c Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:50 +0200 Subject: drm/i915/cx0: Add MTL+ .put_dplls hook Add .put_dplls function pointer to support MTL+ platforms on dpll framework. Reuse ICL function pointer. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-21-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 313cb244d5d6..c45f18201ee8 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4448,6 +4448,7 @@ static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, .compute_dplls = mtl_compute_dplls, .get_dplls = mtl_get_dplls, + .put_dplls = icl_put_dplls, }; /** -- cgit v1.2.3 From 4fcefdf990cb14a3586e622ded7a18c287cf51e4 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Tue, 18 Nov 2025 15:28:30 +0200 Subject: drm/i915/cx0: Add MTL+ .update_active_dpll hook Add .update_active_dpll function pointer to support dpll framework. Reuse ICL function pointer. v2: Add check for !HAS_LT_PHY (Suraj) v3: Remove the incorrect !HAS_LT_PHY condition and check for existing dpll_mgr Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal # v1 Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251118132830.2584422-1-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 4 ++-- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 002ccd47856d..39d87bc91571 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3667,8 +3667,8 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct intel_crtc *pipe_crtc; - /* FIXME: Add MTL pll_mgr */ - if (DISPLAY_VER(display) >= 14 || !intel_encoder_is_tc(encoder)) + /* FIXME: Add NVL+ and DG2 pll_mgr */ + if (!intel_encoder_is_tc(encoder) || !display->dpll.mgr) return; for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index c45f18201ee8..e6dd6f1123d6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4449,6 +4449,7 @@ static const struct intel_dpll_mgr mtl_pll_mgr = { .compute_dplls = mtl_compute_dplls, .get_dplls = mtl_get_dplls, .put_dplls = icl_put_dplls, + .update_active_dpll = icl_update_active_dpll, }; /** -- cgit v1.2.3 From dc3fdd4ade8763aac3546835909b70c298b8e8f4 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:52 +0200 Subject: drm/i915/cx0: Add MTL+ .update_dpll_ref_clks hook Add .update_dpll_ref_clks function pointer to MTL+ platforms to support dpll framework. Reuse ICL function pointer. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-23-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index e6dd6f1123d6..32e52babf265 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4450,6 +4450,7 @@ static const struct intel_dpll_mgr mtl_pll_mgr = { .get_dplls = mtl_get_dplls, .put_dplls = icl_put_dplls, .update_active_dpll = icl_update_active_dpll, + .update_ref_clks = icl_update_dpll_ref_clks, }; /** -- cgit v1.2.3 From 2e129889622c391d4d1204a0da16e278d585124b Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:53 +0200 Subject: drm/i915/cx0: Add MTL+ .dump_hw_state hook Add .dump_hw_state function pointer for MTL+ platforms to support dpll framework. While at it, switch to use drm_printer structure to print hw state information. v2: Keep debug messages on one line if they not necessarily needed to split into two or more lines (Suraj) Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-24-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 70 +++++++++++++-------------- drivers/gpu/drm/i915/display/intel_cx0_phy.h | 3 +- drivers/gpu/drm/i915/display/intel_display.c | 5 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 7 +++ 4 files changed, 45 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index de71805a065c..a88169b76cfa 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2297,7 +2297,7 @@ static void intel_c10_pll_program(struct intel_display *display, intel_c10_msgbus_access_commit(encoder, INTEL_CX0_LANE0, true); } -static void intel_c10pll_dump_hw_state(struct intel_display *display, +static void intel_c10pll_dump_hw_state(struct drm_printer *p, const struct intel_c10pll_state *hw_state) { bool fracen; @@ -2306,33 +2306,32 @@ static void intel_c10pll_dump_hw_state(struct intel_display *display, unsigned int multiplier, tx_clk_div; fracen = hw_state->pll[0] & C10_PLL0_FRACEN; - drm_dbg_kms(display->drm, "c10pll_hw_state: clock: %d, fracen: %s, ", - hw_state->clock, str_yes_no(fracen)); + drm_printf(p, "c10pll_hw_state: clock: %d, fracen: %s, ", + hw_state->clock, str_yes_no(fracen)); if (fracen) { frac_quot = hw_state->pll[12] << 8 | hw_state->pll[11]; frac_rem = hw_state->pll[14] << 8 | hw_state->pll[13]; frac_den = hw_state->pll[10] << 8 | hw_state->pll[9]; - drm_dbg_kms(display->drm, "quot: %u, rem: %u, den: %u,\n", - frac_quot, frac_rem, frac_den); + drm_printf(p, "quot: %u, rem: %u, den: %u,\n", + frac_quot, frac_rem, frac_den); } multiplier = (REG_FIELD_GET8(C10_PLL3_MULTIPLIERH_MASK, hw_state->pll[3]) << 8 | hw_state->pll[2]) / 2 + 16; tx_clk_div = REG_FIELD_GET8(C10_PLL15_TXCLKDIV_MASK, hw_state->pll[15]); - drm_dbg_kms(display->drm, - "multiplier: %u, tx_clk_div: %u.\n", multiplier, tx_clk_div); + drm_printf(p, + "multiplier: %u, tx_clk_div: %u.\n", multiplier, tx_clk_div); - drm_dbg_kms(display->drm, "c10pll_rawhw_state:"); - drm_dbg_kms(display->drm, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx, - hw_state->cmn); + drm_printf(p, "c10pll_rawhw_state:"); + drm_printf(p, "tx: 0x%x, cmn: 0x%x\n", hw_state->tx, hw_state->cmn); BUILD_BUG_ON(ARRAY_SIZE(hw_state->pll) % 4); for (i = 0; i < ARRAY_SIZE(hw_state->pll); i = i + 4) - drm_dbg_kms(display->drm, - "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n", - i, hw_state->pll[i], i + 1, hw_state->pll[i + 1], - i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]); + drm_printf(p, + "pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x, pll[%d] = 0x%x\n", + i, hw_state->pll[i], i + 1, hw_state->pll[i + 1], + i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i + 3]); } /* @@ -2813,49 +2812,48 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, cx0pll_state->ssc_enabled = readout_ssc_state(encoder, intel_c20phy_use_mpllb(pll_state)); } -static void intel_c20pll_dump_hw_state(struct intel_display *display, +static void intel_c20pll_dump_hw_state(struct drm_printer *p, const struct intel_c20pll_state *hw_state) { int i; - drm_dbg_kms(display->drm, "c20pll_hw_state clock: %d:\n", hw_state->clock); - drm_dbg_kms(display->drm, - "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n", - hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]); - drm_dbg_kms(display->drm, - "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n", - hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], hw_state->cmn[3]); + drm_printf(p, "c20pll_hw_state: clock: %d\n", hw_state->clock); + drm_printf(p, + "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 0x%.4x\n", + hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]); + drm_printf(p, + "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 0x%.4x, cmn[3] = 0x%.4x\n", + hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], hw_state->cmn[3]); if (intel_c20phy_use_mpllb(hw_state)) { for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++) - drm_dbg_kms(display->drm, "mpllb[%d] = 0x%.4x\n", i, - hw_state->mpllb[i]); + drm_printf(p, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]); } else { for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++) - drm_dbg_kms(display->drm, "mplla[%d] = 0x%.4x\n", i, - hw_state->mplla[i]); + drm_printf(p, "mplla[%d] = 0x%.4x\n", i, hw_state->mplla[i]); /* For full coverage, also print the additional PLL B entry. */ BUILD_BUG_ON(ARRAY_SIZE(hw_state->mplla) + 1 != ARRAY_SIZE(hw_state->mpllb)); - drm_dbg_kms(display->drm, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]); + drm_printf(p, "mpllb[%d] = 0x%.4x\n", i, hw_state->mpllb[i]); } - drm_dbg_kms(display->drm, "vdr: custom width: 0x%02x, serdes rate: 0x%02x, hdmi rate: 0x%02x\n", - hw_state->vdr.custom_width, hw_state->vdr.serdes_rate, hw_state->vdr.hdmi_rate); + drm_printf(p, + "vdr: custom width: 0x%02x, serdes rate: 0x%02x, hdmi rate: 0x%02x\n", + hw_state->vdr.custom_width, hw_state->vdr.serdes_rate, hw_state->vdr.hdmi_rate); } -void intel_cx0pll_dump_hw_state(struct intel_display *display, +void intel_cx0pll_dump_hw_state(struct drm_printer *p, const struct intel_cx0pll_state *hw_state) { - drm_dbg_kms(display->drm, - "cx0pll_hw_state: lane_count: %d, ssc_enabled: %s, use_c10: %s, tbt_mode: %s\n", - hw_state->lane_count, str_yes_no(hw_state->ssc_enabled), - str_yes_no(hw_state->use_c10), str_yes_no(hw_state->tbt_mode)); + drm_printf(p, + "cx0pll_hw_state: lane_count: %d, ssc_enabled: %s, use_c10: %s, tbt_mode: %s\n", + hw_state->lane_count, str_yes_no(hw_state->ssc_enabled), + str_yes_no(hw_state->use_c10), str_yes_no(hw_state->tbt_mode)); if (hw_state->use_c10) - intel_c10pll_dump_hw_state(display, &hw_state->c10); + intel_c10pll_dump_hw_state(p, &hw_state->c10); else - intel_c20pll_dump_hw_state(display, &hw_state->c20); + intel_c20pll_dump_hw_state(p, &hw_state->c20); } static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index d52e864f5e19..acfbaced22f5 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -11,6 +11,7 @@ #define MB_WRITE_COMMITTED true #define MB_WRITE_UNCOMMITTED false +struct drm_printer; enum icl_port_dpll_id; struct intel_atomic_state; struct intel_c10pll_state; @@ -41,7 +42,7 @@ void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state); -void intel_cx0pll_dump_hw_state(struct intel_display *display, +void intel_cx0pll_dump_hw_state(struct drm_printer *p, const struct intel_cx0pll_state *hw_state); bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a, const struct intel_cx0pll_state *b); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 069967114bd9..e7bb8ec0d6bb 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4984,15 +4984,14 @@ pipe_config_cx0pll_mismatch(struct drm_printer *p, bool fastset, const struct intel_cx0pll_state *a, const struct intel_cx0pll_state *b) { - struct intel_display *display = to_intel_display(crtc); char *chipname = a->use_c10 ? "C10" : "C20"; pipe_config_mismatch(p, fastset, crtc, name, chipname); drm_printf(p, "expected:\n"); - intel_cx0pll_dump_hw_state(display, a); + intel_cx0pll_dump_hw_state(p, a); drm_printf(p, "found:\n"); - intel_cx0pll_dump_hw_state(display, b); + intel_cx0pll_dump_hw_state(p, b); } static bool allow_vblank_delay_fastset(const struct intel_crtc_state *old_crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 32e52babf265..aee8f1a5848a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4443,6 +4443,12 @@ static int mtl_get_dplls(struct intel_atomic_state *state, return mtl_get_non_tc_phy_dpll(state, crtc, encoder); } +static void mtl_dump_hw_state(struct drm_printer *p, + const struct intel_dpll_hw_state *dpll_hw_state) +{ + intel_cx0pll_dump_hw_state(p, &dpll_hw_state->cx0pll); +} + __maybe_unused static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, @@ -4451,6 +4457,7 @@ static const struct intel_dpll_mgr mtl_pll_mgr = { .put_dplls = icl_put_dplls, .update_active_dpll = icl_update_active_dpll, .update_ref_clks = icl_update_dpll_ref_clks, + .dump_hw_state = mtl_dump_hw_state, }; /** -- cgit v1.2.3 From 9b5f839e14a52c67492830b718d4ac8dddf04688 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:54 +0200 Subject: drm/i915/cx0: Add .compare_hw_state hook Add .compare_hw_state function pointer for MTL+ platforms to support dpll framework. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-25-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index aee8f1a5848a..c0ba269dc714 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4449,6 +4449,15 @@ static void mtl_dump_hw_state(struct drm_printer *p, intel_cx0pll_dump_hw_state(p, &dpll_hw_state->cx0pll); } +static bool mtl_compare_hw_state(const struct intel_dpll_hw_state *_a, + const struct intel_dpll_hw_state *_b) +{ + const struct intel_cx0pll_state *a = &_a->cx0pll; + const struct intel_cx0pll_state *b = &_b->cx0pll; + + return intel_cx0pll_compare_hw_state(a, b); +} + __maybe_unused static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, @@ -4458,6 +4467,7 @@ static const struct intel_dpll_mgr mtl_pll_mgr = { .update_active_dpll = icl_update_active_dpll, .update_ref_clks = icl_update_dpll_ref_clks, .dump_hw_state = mtl_dump_hw_state, + .compare_hw_state = mtl_compare_hw_state, }; /** -- cgit v1.2.3 From 685f36534968467a37ee7319673633b82dcebe09 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:55 +0200 Subject: drm/i915/cx0: Add MTL+ .get_hw_state hook Add .get_hw_state hook to MTL+ platforms for dpll framework. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-26-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 9 +++++++-- drivers/gpu/drm/i915/display/intel_cx0_phy.h | 2 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 29 +++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index a88169b76cfa..bde461878647 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3594,19 +3594,24 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder, return ICL_PORT_DPLL_DEFAULT; } -void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, +bool intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { memset(pll_state, 0, sizeof(*pll_state)); pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)); if (pll_state->tbt_mode) - return; + return true; + + if (!intel_cx0_pll_is_enabled(encoder)) + return false; if (intel_encoder_is_c10phy(encoder)) intel_c10pll_readout_hw_state(encoder, pll_state); else intel_c20pll_readout_hw_state(encoder, pll_state); + + return true; } static bool mtl_compare_hw_state_c10(const struct intel_c10pll_state *a, diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index acfbaced22f5..37b53faa5e78 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -37,7 +37,7 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder, int intel_cx0pll_calc_state(const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder, struct intel_dpll_hw_state *hw_state); -void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, +bool intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state); int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index c0ba269dc714..beaf270294ca 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4351,7 +4351,36 @@ static const struct intel_dpll_mgr adlp_pll_mgr = { .compare_hw_state = icl_compare_hw_state, }; +static struct intel_encoder *get_intel_encoder(struct intel_display *display, + const struct intel_dpll *pll) +{ + struct intel_encoder *encoder; + enum intel_dpll_id mtl_id; + + for_each_intel_encoder(display->drm, encoder) { + mtl_id = mtl_port_to_pll_id(display, encoder->port); + + if (mtl_id == pll->info->id) + return encoder; + } + + return NULL; +} + +static bool mtl_pll_get_hw_state(struct intel_display *display, + struct intel_dpll *pll, + struct intel_dpll_hw_state *dpll_hw_state) +{ + struct intel_encoder *encoder = get_intel_encoder(display, pll); + + if (!encoder) + return false; + + return intel_cx0pll_readout_hw_state(encoder, &dpll_hw_state->cx0pll); +} + static const struct intel_dpll_funcs mtl_pll_funcs = { + .get_hw_state = mtl_pll_get_hw_state, }; static const struct dpll_info mtl_plls[] = { -- cgit v1.2.3 From 57cf9d5e45a88a4d3543dfd32c78f9bedca1b110 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:56 +0200 Subject: drm/i915/cx0: Add MTL+ .get_freq hook Add .get_freq hook to support dpll framework for MTL+ platforms. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-27-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index beaf270294ca..85b3fee2d9b6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4379,8 +4379,21 @@ static bool mtl_pll_get_hw_state(struct intel_display *display, return intel_cx0pll_readout_hw_state(encoder, &dpll_hw_state->cx0pll); } +static int mtl_pll_get_freq(struct intel_display *display, + const struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) +{ + struct intel_encoder *encoder = get_intel_encoder(display, pll); + + if (drm_WARN_ON(display->drm, !encoder)) + return -EINVAL; + + return intel_cx0pll_calc_port_clock(encoder, &dpll_hw_state->cx0pll); +} + static const struct intel_dpll_funcs mtl_pll_funcs = { .get_hw_state = mtl_pll_get_hw_state, + .get_freq = mtl_pll_get_freq, }; static const struct dpll_info mtl_plls[] = { -- cgit v1.2.3 From f3b04e27f7e5cf2af91d73112d9f81296ddad156 Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:57 +0200 Subject: drm/i915/cx0: Add MTL+ .crtc_get_dpll hook Add .crtc_get_dpll function pointer to support MTL+ platforms. Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-28-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 342d46b7b1af..2da65bb20f1c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1720,6 +1720,7 @@ static const struct intel_dpll_global_funcs xe3plpd_dpll_funcs = { static const struct intel_dpll_global_funcs mtl_dpll_funcs = { .crtc_compute_clock = mtl_crtc_compute_clock, + .crtc_get_dpll = hsw_crtc_get_dpll, }; static const struct intel_dpll_global_funcs dg2_dpll_funcs = { -- cgit v1.2.3 From b800af732c6b844c8fe6465edf39c437f4a760e3 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:45:58 +0200 Subject: drm/i915/cx0: PLL verify debug state print Print out hw and sw pll states for better debugging support. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-29-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 85b3fee2d9b6..463677014199 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4882,11 +4882,18 @@ verify_single_dpll_state(struct intel_display *display, "%s: pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n", pll->info->name, pipe_mask, pll->state.pipe_mask); - INTEL_DISPLAY_STATE_WARN(display, - pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state, - sizeof(dpll_hw_state)), - "%s: pll hw state mismatch\n", - pll->info->name); + if (INTEL_DISPLAY_STATE_WARN(display, + pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state, + sizeof(dpll_hw_state)), + "%s: pll hw state mismatch\n", + pll->info->name)) { + struct drm_printer p = drm_dbg_printer(display->drm, DRM_UT_KMS, NULL); + + drm_printf(&p, "PLL %s HW state:\n", pll->info->name); + intel_dpll_dump_hw_state(display, &p, &dpll_hw_state); + drm_printf(&p, "PLL %s SW state:\n", pll->info->name); + intel_dpll_dump_hw_state(display, &p, &pll->state.hw_state); + } } static bool has_alt_port_dpll(const struct intel_dpll *old_pll, -- cgit v1.2.3 From e32518d012ed9abd97b33832fc82fafdab40c12d Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:45:59 +0200 Subject: drm/i915/cx0: Add MTL+ .enable_clock/.disable clock hooks on DDI To enable pll clock on DDI move part of the pll enabling sequence into a ddi clock enabling function. Simililarly, do the same for pll disabling sequence. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-30-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 34 ++++++++++++++++++--------- drivers/gpu/drm/i915/display/intel_cx0_phy.h | 11 ++++++++- drivers/gpu/drm/i915/display/intel_ddi.c | 6 +++-- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 25 ++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_lt_phy.c | 4 ++-- 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index bde461878647..79be234780ba 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3280,7 +3280,6 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, * Frequency Change. We handle this step in bxt_set_cdclk(). */ - /* TODO: enable TBT-ALT mode */ intel_cx0_phy_transaction_end(encoder, wakeref); } @@ -3346,8 +3345,7 @@ static int intel_mtl_tbt_clock_select(struct intel_display *display, } } -void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +void intel_mtl_tbt_pll_enable_clock(struct intel_encoder *encoder, int port_clock) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -3361,7 +3359,7 @@ void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, mask = XELPDP_DDI_CLOCK_SELECT_MASK(display); val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, - intel_mtl_tbt_clock_select(display, crtc_state->port_clock)); + intel_mtl_tbt_clock_select(display, port_clock)); mask |= XELPDP_FORWARD_CLOCK_UNGATE; val |= XELPDP_FORWARD_CLOCK_UNGATE; @@ -3399,18 +3397,26 @@ void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, * clock frequency. */ intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), - crtc_state->port_clock); + port_clock); } void intel_mtl_pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) + struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) +{ + intel_cx0pll_enable(encoder, &dpll_hw_state->cx0pll); +} + +void intel_mtl_pll_enable_clock(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { struct intel_digital_port *dig_port = enc_to_dig_port(encoder); if (intel_tc_port_in_tbt_alt_mode(dig_port)) - intel_mtl_tbt_pll_enable(encoder, crtc_state); + intel_mtl_tbt_pll_enable_clock(encoder, crtc_state->port_clock); else - intel_cx0pll_enable(encoder, &crtc_state->dpll_hw_state.cx0pll); + /* TODO: remove when PLL mgr is in place. */ + intel_mtl_pll_enable(encoder, NULL, &crtc_state->dpll_hw_state); } /* @@ -3525,7 +3531,7 @@ static bool intel_cx0_pll_is_enabled(struct intel_encoder *encoder) intel_cx0_get_pclk_pll_request(lane); } -void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) +void intel_mtl_tbt_pll_disable_clock(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); enum phy phy = intel_encoder_to_phy(encoder); @@ -3564,13 +3570,19 @@ void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) } void intel_mtl_pll_disable(struct intel_encoder *encoder) +{ + intel_cx0pll_disable(encoder); +} + +void intel_mtl_pll_disable_clock(struct intel_encoder *encoder) { struct intel_digital_port *dig_port = enc_to_dig_port(encoder); if (intel_tc_port_in_tbt_alt_mode(dig_port)) - intel_mtl_tbt_pll_disable(encoder); + intel_mtl_tbt_pll_disable_clock(encoder); else - intel_cx0pll_disable(encoder); + /* TODO: remove when PLL mgr is in place. */ + intel_mtl_pll_disable(encoder); } enum icl_port_dpll_id diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index 37b53faa5e78..3745d7081ac7 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -20,6 +20,7 @@ struct intel_crtc; struct intel_crtc_state; struct intel_cx0pll_state; struct intel_display; +struct intel_dpll; struct intel_dpll_hw_state; struct intel_encoder; struct intel_hdmi; @@ -28,11 +29,19 @@ void intel_clear_response_ready_flag(struct intel_encoder *encoder, int lane); bool intel_encoder_is_c10phy(struct intel_encoder *encoder); void intel_mtl_pll_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state); + struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state); void intel_mtl_pll_disable(struct intel_encoder *encoder); enum icl_port_dpll_id intel_mtl_port_pll_type(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); +void intel_mtl_pll_enable_clock(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state); +void intel_mtl_pll_disable_clock(struct intel_encoder *encoder); +void intel_mtl_pll_disable_clock(struct intel_encoder *encoder); +void intel_mtl_tbt_pll_enable_clock(struct intel_encoder *encoder, + int port_clock); +void intel_mtl_tbt_pll_disable_clock(struct intel_encoder *encoder); int intel_cx0pll_calc_state(const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 39d87bc91571..7f8e1ebb27b9 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -89,6 +89,8 @@ #include "skl_scaler.h" #include "skl_universal_plane.h" +struct intel_dpll; + static const u8 index_to_dp_signal_levels[] = { [0] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0, [1] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1, @@ -5252,8 +5254,8 @@ void intel_ddi_init(struct intel_display *display, encoder->port_pll_type = intel_mtl_port_pll_type; encoder->get_config = xe3plpd_ddi_get_config; } else if (DISPLAY_VER(display) >= 14) { - encoder->enable_clock = intel_mtl_pll_enable; - encoder->disable_clock = intel_mtl_pll_disable; + encoder->enable_clock = intel_mtl_pll_enable_clock; + encoder->disable_clock = intel_mtl_pll_disable_clock; encoder->port_pll_type = intel_mtl_port_pll_type; encoder->get_config = mtl_ddi_get_config; } else if (display->platform.dg2) { diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 463677014199..ecb7e3761a5b 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4391,7 +4391,32 @@ static int mtl_pll_get_freq(struct intel_display *display, return intel_cx0pll_calc_port_clock(encoder, &dpll_hw_state->cx0pll); } +static void mtl_pll_enable(struct intel_display *display, + struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) +{ + struct intel_encoder *encoder = get_intel_encoder(display, pll); + + if (drm_WARN_ON(display->drm, !encoder)) + return; + + intel_mtl_pll_enable(encoder, pll, dpll_hw_state); +} + +static void mtl_pll_disable(struct intel_display *display, + struct intel_dpll *pll) +{ + struct intel_encoder *encoder = get_intel_encoder(display, pll); + + if (drm_WARN_ON(display->drm, !encoder)) + return; + + intel_mtl_pll_disable(encoder); +} + static const struct intel_dpll_funcs mtl_pll_funcs = { + .enable = mtl_pll_enable, + .disable = mtl_pll_disable, .get_hw_state = mtl_pll_get_hw_state, .get_freq = mtl_pll_get_freq, }; diff --git a/drivers/gpu/drm/i915/display/intel_lt_phy.c b/drivers/gpu/drm/i915/display/intel_lt_phy.c index a67eb4f7f897..aaf5a2433690 100644 --- a/drivers/gpu/drm/i915/display/intel_lt_phy.c +++ b/drivers/gpu/drm/i915/display/intel_lt_phy.c @@ -2310,7 +2310,7 @@ void intel_xe3plpd_pll_enable(struct intel_encoder *encoder, struct intel_digital_port *dig_port = enc_to_dig_port(encoder); if (intel_tc_port_in_tbt_alt_mode(dig_port)) - intel_mtl_tbt_pll_enable(encoder, crtc_state); + intel_mtl_tbt_pll_enable_clock(encoder, crtc_state->port_clock); else intel_lt_phy_pll_enable(encoder, crtc_state); } @@ -2320,7 +2320,7 @@ void intel_xe3plpd_pll_disable(struct intel_encoder *encoder) struct intel_digital_port *dig_port = enc_to_dig_port(encoder); if (intel_tc_port_in_tbt_alt_mode(dig_port)) - intel_mtl_tbt_pll_disable(encoder); + intel_mtl_tbt_pll_disable_clock(encoder); else intel_lt_phy_pll_disable(encoder); -- cgit v1.2.3 From 6b566d066c823a9ad1ec5a7043955349a71ce42b Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 17 Nov 2025 12:46:00 +0200 Subject: drm/i915/cx0: Get encoder configuration for C10 and C20 PHY PLLs For DDI initialization get encoder configuration for C10 and C20 chips. v2: Get configuration either for a C10 or on the PTL port B eDP on TypeC PHY case for a C20 PHY PLL. Hence refer to this case as "non_tc_phy" instead of "c10phy". Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-31-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 81 +++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 7f8e1ebb27b9..e7abc3dee017 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4270,6 +4270,77 @@ static void mtl_ddi_get_config(struct intel_encoder *encoder, intel_ddi_get_config(encoder, crtc_state); } +static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll) +{ + return pll->info->id == DPLL_ID_ICL_TBTPLL; +} + +static void mtl_ddi_cx0_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + enum icl_port_dpll_id port_dpll_id, + enum intel_dpll_id pll_id) +{ + struct intel_display *display = to_intel_display(encoder); + struct icl_port_dpll *port_dpll; + struct intel_dpll *pll; + bool pll_active; + + port_dpll = &crtc_state->icl_port_dplls[port_dpll_id]; + pll = intel_get_dpll_by_id(display, pll_id); + + if (drm_WARN_ON(display->drm, !pll)) + return; + + port_dpll->pll = pll; + pll_active = intel_dpll_get_hw_state(display, pll, &port_dpll->hw_state); + drm_WARN_ON(display->drm, !pll_active); + + icl_set_active_port_dpll(crtc_state, port_dpll_id); + + if (icl_ddi_tc_pll_is_tbt(crtc_state->intel_dpll)) + crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder); + else + crtc_state->port_clock = intel_dpll_get_freq(display, crtc_state->intel_dpll, + &crtc_state->dpll_hw_state); + + intel_ddi_get_config(encoder, crtc_state); +} + +/* + * Get the configuration for either a port using a C10 PHY PLL, or in the case of + * the PTL port B eDP on TypeC PHY case the configuration of a port using a C20 + * PHY PLL. + */ +static void mtl_ddi_non_tc_phy_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(encoder); + + /* TODO: Remove when the PLL manager is in place. */ + mtl_ddi_get_config(encoder, crtc_state); + return; + + mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_DEFAULT, + mtl_port_to_pll_id(display, encoder->port)); +} + +static void mtl_ddi_tc_phy_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(encoder); + + /* TODO: Remove when the PLL manager is in place. */ + mtl_ddi_get_config(encoder, crtc_state); + return; + + if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder))) + mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_DEFAULT, + DPLL_ID_ICL_TBTPLL); + else + mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_MG_PHY, + mtl_port_to_pll_id(display, encoder->port)); +} + static void dg2_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) { @@ -4307,11 +4378,6 @@ static void icl_ddi_combo_get_config(struct intel_encoder *encoder, intel_ddi_get_config(encoder, crtc_state); } -static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll) -{ - return pll->info->id == DPLL_ID_ICL_TBTPLL; -} - static enum icl_port_dpll_id icl_ddi_tc_port_pll_type(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) @@ -5257,7 +5323,10 @@ void intel_ddi_init(struct intel_display *display, encoder->enable_clock = intel_mtl_pll_enable_clock; encoder->disable_clock = intel_mtl_pll_disable_clock; encoder->port_pll_type = intel_mtl_port_pll_type; - encoder->get_config = mtl_ddi_get_config; + if (intel_encoder_is_tc(encoder)) + encoder->get_config = mtl_ddi_tc_phy_get_config; + else + encoder->get_config = mtl_ddi_non_tc_phy_get_config; } else if (display->platform.dg2) { encoder->enable_clock = intel_mpllb_enable; encoder->disable_clock = intel_mpllb_disable; -- cgit v1.2.3 From 2a6e417907593e908d164c743f812ad6413f3d7b Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 17 Nov 2025 12:46:01 +0200 Subject: drm/i915/cx0: Add MTL+ Thunderbolt PLL hooks Add the PLL hooks for the TBT PLL on MTL+. These are simple stubs similarly to the TBT PLL on earlier platforms, since this PLL is always on from the display POV - so no PLL enable/disable programming is required as opposed to the non-TBT PLLs - and the clocks for different link rates are enabled/disabled at a different level, via the intel_encoder::enable_clock()/disable_clock() interface. Signed-off-by: Imre Deak Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251117104602.2363671-32-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 18 +++++++++++++ drivers/gpu/drm/i915/display/intel_cx0_phy.h | 6 +++++ drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 37 +++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 79be234780ba..9d96e8940838 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3283,6 +3283,24 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, intel_cx0_phy_transaction_end(encoder, wakeref); } +void intel_mtl_tbt_pll_calc_state(struct intel_dpll_hw_state *hw_state) +{ + memset(hw_state, 0, sizeof(*hw_state)); + + hw_state->cx0pll.tbt_mode = true; +} + +bool intel_mtl_tbt_pll_readout_hw_state(struct intel_display *display, + struct intel_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + memset(hw_state, 0, sizeof(*hw_state)); + + hw_state->cx0pll.tbt_mode = true; + + return true; +} + int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index 3745d7081ac7..9f10113e2d18 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -70,7 +70,13 @@ void intel_cx0_write(struct intel_encoder *encoder, int intel_cx0_wait_for_ack(struct intel_encoder *encoder, int command, int lane, u32 *val); void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane); + +void intel_mtl_tbt_pll_calc_state(struct intel_dpll_hw_state *hw_state); +bool intel_mtl_tbt_pll_readout_hw_state(struct intel_display *display, + struct intel_dpll *pll, + struct intel_dpll_hw_state *hw_state); int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder); + void intel_cx0_pll_power_save_wa(struct intel_display *display); void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index ecb7e3761a5b..8fd3b06f393d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4421,10 +4421,42 @@ static const struct intel_dpll_funcs mtl_pll_funcs = { .get_freq = mtl_pll_get_freq, }; +static void mtl_tbt_pll_enable(struct intel_display *display, + struct intel_dpll *pll, + const struct intel_dpll_hw_state *hw_state) +{ +} + +static void mtl_tbt_pll_disable(struct intel_display *display, + struct intel_dpll *pll) +{ +} + +static int mtl_tbt_pll_get_freq(struct intel_display *display, + const struct intel_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) +{ + /* + * The PLL outputs multiple frequencies at the same time, selection is + * made at DDI clock mux level. + */ + drm_WARN_ON(display->drm, 1); + + return 0; +} + +static const struct intel_dpll_funcs mtl_tbt_pll_funcs = { + .enable = mtl_tbt_pll_enable, + .disable = mtl_tbt_pll_disable, + .get_hw_state = intel_mtl_tbt_pll_readout_hw_state, + .get_freq = mtl_tbt_pll_get_freq, +}; + static const struct dpll_info mtl_plls[] = { { .name = "DPLL 0", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_DPLL0, }, { .name = "DPLL 1", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_DPLL1, }, - /* TODO: Add TBT PLL */ + { .name = "TBT PLL", .funcs = &mtl_tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, + .is_alt_port_dpll = true, .always_on = true }, { .name = "TC PLL 1", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, }, { .name = "TC PLL 2", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, }, { .name = "TC PLL 3", .funcs = &mtl_pll_funcs, .id = DPLL_ID_ICL_MGPLL3, }, @@ -4470,7 +4502,8 @@ static int mtl_compute_tc_phy_dplls(struct intel_atomic_state *state, struct icl_port_dpll *port_dpll; int ret; - /* TODO: Add state calculation for TBT PLL */ + port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; + intel_mtl_tbt_pll_calc_state(&port_dpll->hw_state); port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; ret = intel_cx0pll_calc_state(crtc_state, encoder, &port_dpll->hw_state); -- cgit v1.2.3 From 1a7fad2aea74065dcd81821c681103813fd0772b Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Tue, 18 Nov 2025 15:28:59 +0200 Subject: drm/i915/cx0: Enable dpll framework for MTL+ MTL+ platforms are supported by dpll framework remove a separate check for hw comparison and rely solely on dpll framework hw comparison. Finally, all required hooks are now in place so initialize PLL manager for MTL+ platforms and remove the redirections to the legacy code paths from the following interfaces: * intel_encoder::clock_enable/disable() * intel_encoder::get_config() * intel_dpll_funcs::get_hw_state() * intel_ddi_update_active_dpll() * pipe_config_pll_mismatch() v2: Rebase on !HAS_LT_PHY check in intel_ddi_update_active_dpll() v3: Rebase on !display->dpll.mgr check in intel_ddi_update_active_dpll() Add check for NVL as the platform is not part of pll framework (Suraj) Signed-off-by: Mika Kahola Reviewed-by: Suraj Kandpal Link: https://lore.kernel.org/r/20251118132859.2584452-1-mika.kahola@intel.com --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 10 --------- drivers/gpu/drm/i915/display/intel_ddi.c | 23 +-------------------- drivers/gpu/drm/i915/display/intel_display.c | 29 --------------------------- drivers/gpu/drm/i915/display/intel_dpll.c | 23 +-------------------- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 7 ++++--- 5 files changed, 6 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 9d96e8940838..96ab7f3b5539 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -3432,9 +3432,6 @@ void intel_mtl_pll_enable_clock(struct intel_encoder *encoder, if (intel_tc_port_in_tbt_alt_mode(dig_port)) intel_mtl_tbt_pll_enable_clock(encoder, crtc_state->port_clock); - else - /* TODO: remove when PLL mgr is in place. */ - intel_mtl_pll_enable(encoder, NULL, &crtc_state->dpll_hw_state); } /* @@ -3598,9 +3595,6 @@ void intel_mtl_pll_disable_clock(struct intel_encoder *encoder) if (intel_tc_port_in_tbt_alt_mode(dig_port)) intel_mtl_tbt_pll_disable_clock(encoder); - else - /* TODO: remove when PLL mgr is in place. */ - intel_mtl_pll_disable(encoder); } enum icl_port_dpll_id @@ -3629,10 +3623,6 @@ bool intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, { memset(pll_state, 0, sizeof(*pll_state)); - pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)); - if (pll_state->tbt_mode) - return true; - if (!intel_cx0_pll_is_enabled(encoder)) return false; diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index e7abc3dee017..96fcad6dbb2f 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4257,19 +4257,6 @@ static void xe3plpd_ddi_get_config(struct intel_encoder *encoder, intel_ddi_get_config(encoder, crtc_state); } -static void mtl_ddi_get_config(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state) -{ - intel_cx0pll_readout_hw_state(encoder, &crtc_state->dpll_hw_state.cx0pll); - - if (crtc_state->dpll_hw_state.cx0pll.tbt_mode) - crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder); - else - crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); - - intel_ddi_get_config(encoder, crtc_state); -} - static bool icl_ddi_tc_pll_is_tbt(const struct intel_dpll *pll) { return pll->info->id == DPLL_ID_ICL_TBTPLL; @@ -4316,10 +4303,6 @@ static void mtl_ddi_non_tc_phy_get_config(struct intel_encoder *encoder, { struct intel_display *display = to_intel_display(encoder); - /* TODO: Remove when the PLL manager is in place. */ - mtl_ddi_get_config(encoder, crtc_state); - return; - mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_DEFAULT, mtl_port_to_pll_id(display, encoder->port)); } @@ -4329,10 +4312,6 @@ static void mtl_ddi_tc_phy_get_config(struct intel_encoder *encoder, { struct intel_display *display = to_intel_display(encoder); - /* TODO: Remove when the PLL manager is in place. */ - mtl_ddi_get_config(encoder, crtc_state); - return; - if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder))) mtl_ddi_cx0_get_config(encoder, crtc_state, ICL_PORT_DPLL_DEFAULT, DPLL_ID_ICL_TBTPLL); @@ -5322,7 +5301,7 @@ void intel_ddi_init(struct intel_display *display, } else if (DISPLAY_VER(display) >= 14) { encoder->enable_clock = intel_mtl_pll_enable_clock; encoder->disable_clock = intel_mtl_pll_disable_clock; - encoder->port_pll_type = intel_mtl_port_pll_type; + encoder->port_pll_type = icl_ddi_tc_port_pll_type; if (intel_encoder_is_tc(encoder)) encoder->get_config = mtl_ddi_tc_phy_get_config; else diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e7bb8ec0d6bb..6c8a7f63111e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4977,23 +4977,6 @@ pipe_config_pll_mismatch(struct drm_printer *p, bool fastset, intel_dpll_dump_hw_state(display, p, b); } -static void -pipe_config_cx0pll_mismatch(struct drm_printer *p, bool fastset, - const struct intel_crtc *crtc, - const char *name, - const struct intel_cx0pll_state *a, - const struct intel_cx0pll_state *b) -{ - char *chipname = a->use_c10 ? "C10" : "C20"; - - pipe_config_mismatch(p, fastset, crtc, name, chipname); - - drm_printf(p, "expected:\n"); - intel_cx0pll_dump_hw_state(p, a); - drm_printf(p, "found:\n"); - intel_cx0pll_dump_hw_state(p, b); -} - static bool allow_vblank_delay_fastset(const struct intel_crtc_state *old_crtc_state) { struct intel_display *display = to_intel_display(old_crtc_state); @@ -5145,16 +5128,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) -#define PIPE_CONF_CHECK_PLL_CX0(name) do { \ - if (!intel_cx0pll_compare_hw_state(¤t_config->name, \ - &pipe_config->name)) { \ - pipe_config_cx0pll_mismatch(&p, fastset, crtc, __stringify(name), \ - ¤t_config->name, \ - &pipe_config->name); \ - ret = false; \ - } \ -} while (0) - #define PIPE_CONF_CHECK_PLL_LT(name) do { \ if (!intel_lt_phy_pll_compare_hw_state(¤t_config->name, \ &pipe_config->name)) { \ @@ -5394,8 +5367,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, /* FIXME convert MTL+ platforms over to dpll_mgr */ if (HAS_LT_PHY(display)) PIPE_CONF_CHECK_PLL_LT(dpll_hw_state.ltpll); - else if (DISPLAY_VER(display) >= 14) - PIPE_CONF_CHECK_PLL_CX0(dpll_hw_state.cx0pll); PIPE_CONF_CHECK_X(dsi_pll.ctrl); PIPE_CONF_CHECK_X(dsi_pll.div); diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 2da65bb20f1c..a4f372c9e6fc 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1212,27 +1212,6 @@ static int dg2_crtc_compute_clock(struct intel_atomic_state *state, return 0; } -static int mtl_crtc_compute_clock(struct intel_atomic_state *state, - struct intel_crtc *crtc) -{ - struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); - struct intel_encoder *encoder = - intel_get_crtc_new_encoder(state, crtc_state); - int ret; - - ret = intel_cx0pll_calc_state(crtc_state, encoder, &crtc_state->dpll_hw_state); - if (ret) - return ret; - - /* TODO: Do the readback via intel_dpll_compute() */ - crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); - - crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state); - - return 0; -} - static int xe3plpd_crtc_compute_clock(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -1719,7 +1698,7 @@ static const struct intel_dpll_global_funcs xe3plpd_dpll_funcs = { }; static const struct intel_dpll_global_funcs mtl_dpll_funcs = { - .crtc_compute_clock = mtl_crtc_compute_clock, + .crtc_compute_clock = hsw_crtc_compute_clock, .crtc_get_dpll = hsw_crtc_get_dpll, }; diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 8fd3b06f393d..6d7d5394713d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -4558,7 +4558,6 @@ static bool mtl_compare_hw_state(const struct intel_dpll_hw_state *_a, return intel_cx0pll_compare_hw_state(a, b); } -__maybe_unused static const struct intel_dpll_mgr mtl_pll_mgr = { .dpll_info = mtl_plls, .compute_dplls = mtl_compute_dplls, @@ -4584,9 +4583,11 @@ void intel_dpll_init(struct intel_display *display) mutex_init(&display->dpll.lock); - if (DISPLAY_VER(display) >= 14 || display->platform.dg2) - /* No shared DPLLs on DG2; port PLLs are part of the PHY */ + if (DISPLAY_VER(display) >= 35 || display->platform.dg2) + /* No shared DPLLs on NVL or DG2; port PLLs are part of the PHY */ dpll_mgr = NULL; + else if (DISPLAY_VER(display) >= 14) + dpll_mgr = &mtl_pll_mgr; else if (display->platform.alderlake_p) dpll_mgr = &adlp_pll_mgr; else if (display->platform.alderlake_s) -- cgit v1.2.3 From 5b23aa423a637358a4b98cd18a4da020ca8398bc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Oct 2025 22:42:13 +0200 Subject: drm/i915/dram: Use REG_GENMASK() & co. for the SKL+ DIMM regs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modernize the SKL/ICL DIMM registers with REG_GENMASK() & co. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20251029204215.12292-2-ville.syrjala@linux.intel.com Reviewed-by: Lucas De Marchi --- drivers/gpu/drm/i915/intel_mchbar_regs.h | 51 ++++++++++++++------------------ drivers/gpu/drm/i915/soc/intel_dram.c | 12 ++++---- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_mchbar_regs.h b/drivers/gpu/drm/i915/intel_mchbar_regs.h index dc2477179c3e..378dc7c69f7d 100644 --- a/drivers/gpu/drm/i915/intel_mchbar_regs.h +++ b/drivers/gpu/drm/i915/intel_mchbar_regs.h @@ -130,11 +130,11 @@ #define DG1_DRAM_T_RAS_MASK REG_GENMASK(8, 1) #define SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5000) -#define SKL_DRAM_DDR_TYPE_MASK (0x3 << 0) -#define SKL_DRAM_DDR_TYPE_DDR4 (0 << 0) -#define SKL_DRAM_DDR_TYPE_DDR3 (1 << 0) -#define SKL_DRAM_DDR_TYPE_LPDDR3 (2 << 0) -#define SKL_DRAM_DDR_TYPE_LPDDR4 (3 << 0) +#define SKL_DRAM_DDR_TYPE_MASK REG_GENMASK(1, 0) +#define SKL_DRAM_DDR_TYPE_DDR4 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 0) +#define SKL_DRAM_DDR_TYPE_DDR3 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 1) +#define SKL_DRAM_DDR_TYPE_LPDDR3 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 2) +#define SKL_DRAM_DDR_TYPE_LPDDR4 REG_FIELD_PREP(SKL_DRAM_DDR_TYPE_MASK, 3) /* snb MCH registers for reading the DRAM channel configuration */ #define MAD_DIMM_C0 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5004) @@ -161,29 +161,24 @@ #define SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C) #define SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5010) #define SKL_DRAM_S_SHIFT 16 -#define SKL_DRAM_SIZE_MASK 0x3F -#define SKL_DRAM_WIDTH_MASK (0x3 << 8) -#define SKL_DRAM_WIDTH_SHIFT 8 -#define SKL_DRAM_WIDTH_X8 (0x0 << 8) -#define SKL_DRAM_WIDTH_X16 (0x1 << 8) -#define SKL_DRAM_WIDTH_X32 (0x2 << 8) -#define SKL_DRAM_RANK_MASK (0x1 << 10) -#define SKL_DRAM_RANK_SHIFT 10 -#define SKL_DRAM_RANK_1 (0x0 << 10) -#define SKL_DRAM_RANK_2 (0x1 << 10) -#define SKL_DRAM_RANK_MASK (0x1 << 10) -#define ICL_DRAM_SIZE_MASK 0x7F -#define ICL_DRAM_WIDTH_MASK (0x3 << 7) -#define ICL_DRAM_WIDTH_SHIFT 7 -#define ICL_DRAM_WIDTH_X8 (0x0 << 7) -#define ICL_DRAM_WIDTH_X16 (0x1 << 7) -#define ICL_DRAM_WIDTH_X32 (0x2 << 7) -#define ICL_DRAM_RANK_MASK (0x3 << 9) -#define ICL_DRAM_RANK_SHIFT 9 -#define ICL_DRAM_RANK_1 (0x0 << 9) -#define ICL_DRAM_RANK_2 (0x1 << 9) -#define ICL_DRAM_RANK_3 (0x2 << 9) -#define ICL_DRAM_RANK_4 (0x3 << 9) +#define SKL_DRAM_SIZE_MASK REG_GENMASK(5, 0) +#define SKL_DRAM_WIDTH_MASK REG_GENMASK(9, 8) +#define SKL_DRAM_WIDTH_X8 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 0) +#define SKL_DRAM_WIDTH_X16 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 1) +#define SKL_DRAM_WIDTH_X32 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 2) +#define SKL_DRAM_RANK_MASK REG_GENMASK(10, 10) +#define SKL_DRAM_RANK_1 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 0) +#define SKL_DRAM_RANK_2 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 1) +#define ICL_DRAM_SIZE_MASK REG_GENMASK(6, 0) +#define ICL_DRAM_WIDTH_MASK REG_GENMASK(8, 7) +#define ICL_DRAM_WIDTH_X8 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 0) +#define ICL_DRAM_WIDTH_X16 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 1) +#define ICL_DRAM_WIDTH_X32 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 2) +#define ICL_DRAM_RANK_MASK REG_GENMASK(10, 9) +#define ICL_DRAM_RANK_1 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 0) +#define ICL_DRAM_RANK_2 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 1) +#define ICL_DRAM_RANK_3 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 2) +#define ICL_DRAM_RANK_4 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 3) #define SA_PERF_STATUS_0_0_0_MCHBAR_PC _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5918) #define DG1_QCLK_RATIO_MASK REG_GENMASK(9, 2) diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 3e588762709a..4925d73d49e1 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -269,7 +269,7 @@ static int intel_dimm_num_devices(const struct dram_dimm_info *dimm) /* Returns total Gb for the whole DIMM */ static int skl_get_dimm_size(u16 val) { - return (val & SKL_DRAM_SIZE_MASK) * 8; + return REG_FIELD_GET(SKL_DRAM_SIZE_MASK, val) * 8; } static int skl_get_dimm_width(u16 val) @@ -281,7 +281,7 @@ static int skl_get_dimm_width(u16 val) case SKL_DRAM_WIDTH_X8: case SKL_DRAM_WIDTH_X16: case SKL_DRAM_WIDTH_X32: - val = (val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT; + val = REG_FIELD_GET(SKL_DRAM_WIDTH_MASK, val); return 8 << val; default: MISSING_CASE(val); @@ -294,7 +294,7 @@ static int skl_get_dimm_ranks(u16 val) if (skl_get_dimm_size(val) == 0) return 0; - val = (val & SKL_DRAM_RANK_MASK) >> SKL_DRAM_RANK_SHIFT; + val = REG_FIELD_GET(SKL_DRAM_RANK_MASK, val); return val + 1; } @@ -302,7 +302,7 @@ static int skl_get_dimm_ranks(u16 val) /* Returns total Gb for the whole DIMM */ static int icl_get_dimm_size(u16 val) { - return (val & ICL_DRAM_SIZE_MASK) * 8 / 2; + return REG_FIELD_GET(ICL_DRAM_SIZE_MASK, val) * 8 / 2; } static int icl_get_dimm_width(u16 val) @@ -314,7 +314,7 @@ static int icl_get_dimm_width(u16 val) case ICL_DRAM_WIDTH_X8: case ICL_DRAM_WIDTH_X16: case ICL_DRAM_WIDTH_X32: - val = (val & ICL_DRAM_WIDTH_MASK) >> ICL_DRAM_WIDTH_SHIFT; + val = REG_FIELD_GET(ICL_DRAM_WIDTH_MASK, val); return 8 << val; default: MISSING_CASE(val); @@ -327,7 +327,7 @@ static int icl_get_dimm_ranks(u16 val) if (icl_get_dimm_size(val) == 0) return 0; - val = (val & ICL_DRAM_RANK_MASK) >> ICL_DRAM_RANK_SHIFT; + val = REG_FIELD_GET(ICL_DRAM_RANK_MASK, val); return val + 1; } -- cgit v1.2.3 From 8c171a9b8c4cb10b1942d3094f94e27c65232cf7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Oct 2025 22:42:14 +0200 Subject: drm/i915/dram: Sort SKL+ DIMM register bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the customary big endian order when defining the SKL/ICL DIMM registers. Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20251029204215.12292-3-ville.syrjala@linux.intel.com Reviewed-by: Lucas De Marchi --- drivers/gpu/drm/i915/intel_mchbar_regs.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_mchbar_regs.h b/drivers/gpu/drm/i915/intel_mchbar_regs.h index 378dc7c69f7d..a46a45b9d2e1 100644 --- a/drivers/gpu/drm/i915/intel_mchbar_regs.h +++ b/drivers/gpu/drm/i915/intel_mchbar_regs.h @@ -161,24 +161,24 @@ #define SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C) #define SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5010) #define SKL_DRAM_S_SHIFT 16 -#define SKL_DRAM_SIZE_MASK REG_GENMASK(5, 0) +#define SKL_DRAM_RANK_MASK REG_GENMASK(10, 10) +#define SKL_DRAM_RANK_1 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 0) +#define SKL_DRAM_RANK_2 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 1) #define SKL_DRAM_WIDTH_MASK REG_GENMASK(9, 8) #define SKL_DRAM_WIDTH_X8 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 0) #define SKL_DRAM_WIDTH_X16 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 1) #define SKL_DRAM_WIDTH_X32 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 2) -#define SKL_DRAM_RANK_MASK REG_GENMASK(10, 10) -#define SKL_DRAM_RANK_1 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 0) -#define SKL_DRAM_RANK_2 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 1) -#define ICL_DRAM_SIZE_MASK REG_GENMASK(6, 0) -#define ICL_DRAM_WIDTH_MASK REG_GENMASK(8, 7) -#define ICL_DRAM_WIDTH_X8 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 0) -#define ICL_DRAM_WIDTH_X16 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 1) -#define ICL_DRAM_WIDTH_X32 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 2) +#define SKL_DRAM_SIZE_MASK REG_GENMASK(5, 0) #define ICL_DRAM_RANK_MASK REG_GENMASK(10, 9) #define ICL_DRAM_RANK_1 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 0) #define ICL_DRAM_RANK_2 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 1) #define ICL_DRAM_RANK_3 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 2) #define ICL_DRAM_RANK_4 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 3) +#define ICL_DRAM_WIDTH_MASK REG_GENMASK(8, 7) +#define ICL_DRAM_WIDTH_X8 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 0) +#define ICL_DRAM_WIDTH_X16 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 1) +#define ICL_DRAM_WIDTH_X32 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 2) +#define ICL_DRAM_SIZE_MASK REG_GENMASK(6, 0) #define SA_PERF_STATUS_0_0_0_MCHBAR_PC _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5918) #define DG1_QCLK_RATIO_MASK REG_GENMASK(9, 2) -- cgit v1.2.3 From 7e2d78535432e44f908c6c44f73828cfd9c12aee Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Oct 2025 22:42:15 +0200 Subject: drm/i915/dram: Fix ICL DIMM_S decoding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unfortunately the MAD_DIMM DIMM_S and DIMM_L bits on ICL are not idential, so we are currently decoding DIMM_S incorrectly. Fix the problem by defining the DIMM_S and DIMM_L bits separately. And for consistency do that same for SKL, even though there the bits do match between the two DIMMs. The result is rather repetitive in places, but I didn't feel like obfuscatign things with cpp macros/etc. Broken decoding on Dell XPS 13 7390 2-in-1: CH0 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH0 DIMM S size: 32 Gb, width: X32, ranks: 3, 16Gb+ DIMMs: no CH0 ranks: 2, 16Gb+ DIMMs: no CH1 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH1 DIMM S size: 32 Gb, width: X32, ranks: 3, 16Gb+ DIMMs: no CH1 ranks: 2, 16Gb+ DIMMs: no Memory configuration is symmetric? no Fixed decoding on Dell XPS 13 7390 2-in-1: CH0 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH0 DIMM S size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH0 ranks: 2, 16Gb+ DIMMs: no CH1 DIMM L size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH1 DIMM S size: 32 Gb, width: X16, ranks: 2, 16Gb+ DIMMs: no CH1 ranks: 2, 16Gb+ DIMMs: no Memory configuration is symmetric? yes Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20251029204215.12292-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/intel_mchbar_regs.h | 53 ++++++---- drivers/gpu/drm/i915/soc/intel_dram.c | 166 ++++++++++++++++++++++--------- 2 files changed, 155 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_mchbar_regs.h b/drivers/gpu/drm/i915/intel_mchbar_regs.h index a46a45b9d2e1..614d4017b57b 100644 --- a/drivers/gpu/drm/i915/intel_mchbar_regs.h +++ b/drivers/gpu/drm/i915/intel_mchbar_regs.h @@ -160,25 +160,40 @@ #define SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C) #define SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5010) -#define SKL_DRAM_S_SHIFT 16 -#define SKL_DRAM_RANK_MASK REG_GENMASK(10, 10) -#define SKL_DRAM_RANK_1 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 0) -#define SKL_DRAM_RANK_2 REG_FIELD_PREP(SKL_DRAM_RANK_MASK, 1) -#define SKL_DRAM_WIDTH_MASK REG_GENMASK(9, 8) -#define SKL_DRAM_WIDTH_X8 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 0) -#define SKL_DRAM_WIDTH_X16 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 1) -#define SKL_DRAM_WIDTH_X32 REG_FIELD_PREP(SKL_DRAM_WIDTH_MASK, 2) -#define SKL_DRAM_SIZE_MASK REG_GENMASK(5, 0) -#define ICL_DRAM_RANK_MASK REG_GENMASK(10, 9) -#define ICL_DRAM_RANK_1 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 0) -#define ICL_DRAM_RANK_2 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 1) -#define ICL_DRAM_RANK_3 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 2) -#define ICL_DRAM_RANK_4 REG_FIELD_PREP(ICL_DRAM_RANK_MASK, 3) -#define ICL_DRAM_WIDTH_MASK REG_GENMASK(8, 7) -#define ICL_DRAM_WIDTH_X8 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 0) -#define ICL_DRAM_WIDTH_X16 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 1) -#define ICL_DRAM_WIDTH_X32 REG_FIELD_PREP(ICL_DRAM_WIDTH_MASK, 2) -#define ICL_DRAM_SIZE_MASK REG_GENMASK(6, 0) +#define SKL_DIMM_S_RANK_MASK REG_GENMASK(26, 26) +#define SKL_DIMM_S_RANK_1 REG_FIELD_PREP(SKL_DIMM_S_RANK_MASK, 0) +#define SKL_DIMM_S_RANK_2 REG_FIELD_PREP(SKL_DIMM_S_RANK_MASK, 1) +#define SKL_DIMM_S_WIDTH_MASK REG_GENMASK(25, 24) +#define SKL_DIMM_S_WIDTH_X8 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 0) +#define SKL_DIMM_S_WIDTH_X16 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 1) +#define SKL_DIMM_S_WIDTH_X32 REG_FIELD_PREP(SKL_DIMM_S_WIDTH_MASK, 2) +#define SKL_DIMM_S_SIZE_MASK REG_GENMASK(21, 16) +#define SKL_DIMM_L_RANK_MASK REG_GENMASK(10, 10) +#define SKL_DIMM_L_RANK_1 REG_FIELD_PREP(SKL_DIMM_L_RANK_MASK, 0) +#define SKL_DIMM_L_RANK_2 REG_FIELD_PREP(SKL_DIMM_L_RANK_MASK, 1) +#define SKL_DIMM_L_WIDTH_MASK REG_GENMASK(9, 8) +#define SKL_DIMM_L_WIDTH_X8 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 0) +#define SKL_DIMM_L_WIDTH_X16 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 1) +#define SKL_DIMM_L_WIDTH_X32 REG_FIELD_PREP(SKL_DIMM_L_WIDTH_MASK, 2) +#define SKL_DIMM_L_SIZE_MASK REG_GENMASK(5, 0) +#define ICL_DIMM_S_RANK_MASK REG_GENMASK(27, 26) +#define ICL_DIMM_S_RANK_1 REG_FIELD_PREP(ICL_DIMM_S_RANK_MASK, 0) +#define ICL_DIMM_S_RANK_2 REG_FIELD_PREP(ICL_DIMM_S_RANK_MASK, 1) +#define ICL_DIMM_S_WIDTH_MASK REG_GENMASK(25, 24) +#define ICL_DIMM_S_WIDTH_X8 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 0) +#define ICL_DIMM_S_WIDTH_X16 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 1) +#define ICL_DIMM_S_WIDTH_X32 REG_FIELD_PREP(ICL_DIMM_S_WIDTH_MASK, 2) +#define ICL_DIMM_S_SIZE_MASK REG_GENMASK(22, 16) +#define ICL_DIMM_L_RANK_MASK REG_GENMASK(10, 9) +#define ICL_DIMM_L_RANK_1 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 0) +#define ICL_DIMM_L_RANK_2 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 1) +#define ICL_DIMM_L_RANK_3 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 2) +#define ICL_DIMM_L_RANK_4 REG_FIELD_PREP(ICL_DIMM_L_RANK_MASK, 3) +#define ICL_DIMM_L_WIDTH_MASK REG_GENMASK(8, 7) +#define ICL_DIMM_L_WIDTH_X8 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 0) +#define ICL_DIMM_L_WIDTH_X16 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 1) +#define ICL_DIMM_L_WIDTH_X32 REG_FIELD_PREP(ICL_DIMM_L_WIDTH_MASK, 2) +#define ICL_DIMM_L_SIZE_MASK REG_GENMASK(6, 0) #define SA_PERF_STATUS_0_0_0_MCHBAR_PC _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5918) #define DG1_QCLK_RATIO_MASK REG_GENMASK(9, 2) diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 4925d73d49e1..739cfe48f6db 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -267,69 +267,121 @@ static int intel_dimm_num_devices(const struct dram_dimm_info *dimm) } /* Returns total Gb for the whole DIMM */ -static int skl_get_dimm_size(u16 val) +static int skl_get_dimm_s_size(u32 val) { - return REG_FIELD_GET(SKL_DRAM_SIZE_MASK, val) * 8; + return REG_FIELD_GET(SKL_DIMM_S_SIZE_MASK, val) * 8; } -static int skl_get_dimm_width(u16 val) +static int skl_get_dimm_l_size(u32 val) { - if (skl_get_dimm_size(val) == 0) + return REG_FIELD_GET(SKL_DIMM_L_SIZE_MASK, val) * 8; +} + +static int skl_get_dimm_s_width(u32 val) +{ + if (skl_get_dimm_s_size(val) == 0) return 0; - switch (val & SKL_DRAM_WIDTH_MASK) { - case SKL_DRAM_WIDTH_X8: - case SKL_DRAM_WIDTH_X16: - case SKL_DRAM_WIDTH_X32: - val = REG_FIELD_GET(SKL_DRAM_WIDTH_MASK, val); - return 8 << val; + switch (val & SKL_DIMM_S_WIDTH_MASK) { + case SKL_DIMM_S_WIDTH_X8: + case SKL_DIMM_S_WIDTH_X16: + case SKL_DIMM_S_WIDTH_X32: + return 8 << REG_FIELD_GET(SKL_DIMM_S_WIDTH_MASK, val); default: MISSING_CASE(val); return 0; } } -static int skl_get_dimm_ranks(u16 val) +static int skl_get_dimm_l_width(u32 val) { - if (skl_get_dimm_size(val) == 0) + if (skl_get_dimm_l_size(val) == 0) + return 0; + + switch (val & SKL_DIMM_L_WIDTH_MASK) { + case SKL_DIMM_L_WIDTH_X8: + case SKL_DIMM_L_WIDTH_X16: + case SKL_DIMM_L_WIDTH_X32: + return 8 << REG_FIELD_GET(SKL_DIMM_L_WIDTH_MASK, val); + default: + MISSING_CASE(val); return 0; + } +} + +static int skl_get_dimm_s_ranks(u32 val) +{ + if (skl_get_dimm_s_size(val) == 0) + return 0; + + return REG_FIELD_GET(SKL_DIMM_S_RANK_MASK, val) + 1; +} - val = REG_FIELD_GET(SKL_DRAM_RANK_MASK, val); +static int skl_get_dimm_l_ranks(u32 val) +{ + if (skl_get_dimm_l_size(val) == 0) + return 0; - return val + 1; + return REG_FIELD_GET(SKL_DIMM_L_RANK_MASK, val) + 1; } /* Returns total Gb for the whole DIMM */ -static int icl_get_dimm_size(u16 val) +static int icl_get_dimm_s_size(u32 val) { - return REG_FIELD_GET(ICL_DRAM_SIZE_MASK, val) * 8 / 2; + return REG_FIELD_GET(ICL_DIMM_S_SIZE_MASK, val) * 8 / 2; +} + +static int icl_get_dimm_l_size(u32 val) +{ + return REG_FIELD_GET(ICL_DIMM_L_SIZE_MASK, val) * 8 / 2; +} + +static int icl_get_dimm_s_width(u32 val) +{ + if (icl_get_dimm_s_size(val) == 0) + return 0; + + switch (val & ICL_DIMM_S_WIDTH_MASK) { + case ICL_DIMM_S_WIDTH_X8: + case ICL_DIMM_S_WIDTH_X16: + case ICL_DIMM_S_WIDTH_X32: + return 8 << REG_FIELD_GET(ICL_DIMM_S_WIDTH_MASK, val); + default: + MISSING_CASE(val); + return 0; + } } -static int icl_get_dimm_width(u16 val) +static int icl_get_dimm_l_width(u32 val) { - if (icl_get_dimm_size(val) == 0) + if (icl_get_dimm_l_size(val) == 0) return 0; - switch (val & ICL_DRAM_WIDTH_MASK) { - case ICL_DRAM_WIDTH_X8: - case ICL_DRAM_WIDTH_X16: - case ICL_DRAM_WIDTH_X32: - val = REG_FIELD_GET(ICL_DRAM_WIDTH_MASK, val); - return 8 << val; + switch (val & ICL_DIMM_L_WIDTH_MASK) { + case ICL_DIMM_L_WIDTH_X8: + case ICL_DIMM_L_WIDTH_X16: + case ICL_DIMM_L_WIDTH_X32: + return 8 << REG_FIELD_GET(ICL_DIMM_L_WIDTH_MASK, val); default: MISSING_CASE(val); return 0; } } -static int icl_get_dimm_ranks(u16 val) +static int icl_get_dimm_s_ranks(u32 val) { - if (icl_get_dimm_size(val) == 0) + if (icl_get_dimm_s_size(val) == 0) return 0; - val = REG_FIELD_GET(ICL_DRAM_RANK_MASK, val); + return REG_FIELD_GET(ICL_DIMM_S_RANK_MASK, val) + 1; +} - return val + 1; +static int icl_get_dimm_l_ranks(u32 val) +{ + if (icl_get_dimm_l_size(val) == 0) + return 0; + + return REG_FIELD_GET(ICL_DIMM_L_RANK_MASK, val) + 1; } static bool @@ -340,35 +392,59 @@ skl_is_16gb_dimm(const struct dram_dimm_info *dimm) } static void -skl_dram_get_dimm_info(struct drm_i915_private *i915, - struct dram_dimm_info *dimm, - int channel, char dimm_name, u16 val) +skl_dram_print_dimm_info(struct drm_i915_private *i915, + struct dram_dimm_info *dimm, + int channel, char dimm_name) { - if (GRAPHICS_VER(i915) >= 11) { - dimm->size = icl_get_dimm_size(val); - dimm->width = icl_get_dimm_width(val); - dimm->ranks = icl_get_dimm_ranks(val); - } else { - dimm->size = skl_get_dimm_size(val); - dimm->width = skl_get_dimm_width(val); - dimm->ranks = skl_get_dimm_ranks(val); - } - drm_dbg_kms(&i915->drm, "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb+ DIMMs: %s\n", channel, dimm_name, dimm->size, dimm->width, dimm->ranks, str_yes_no(skl_is_16gb_dimm(dimm))); } +static void +skl_dram_get_dimm_l_info(struct drm_i915_private *i915, + struct dram_dimm_info *dimm, + int channel, u32 val) +{ + if (GRAPHICS_VER(i915) >= 11) { + dimm->size = icl_get_dimm_l_size(val); + dimm->width = icl_get_dimm_l_width(val); + dimm->ranks = icl_get_dimm_l_ranks(val); + } else { + dimm->size = skl_get_dimm_l_size(val); + dimm->width = skl_get_dimm_l_width(val); + dimm->ranks = skl_get_dimm_l_ranks(val); + } + + skl_dram_print_dimm_info(i915, dimm, channel, 'L'); +} + +static void +skl_dram_get_dimm_s_info(struct drm_i915_private *i915, + struct dram_dimm_info *dimm, + int channel, u32 val) +{ + if (GRAPHICS_VER(i915) >= 11) { + dimm->size = icl_get_dimm_s_size(val); + dimm->width = icl_get_dimm_s_width(val); + dimm->ranks = icl_get_dimm_s_ranks(val); + } else { + dimm->size = skl_get_dimm_s_size(val); + dimm->width = skl_get_dimm_s_width(val); + dimm->ranks = skl_get_dimm_s_ranks(val); + } + + skl_dram_print_dimm_info(i915, dimm, channel, 'S'); +} + static int skl_dram_get_channel_info(struct drm_i915_private *i915, struct dram_channel_info *ch, int channel, u32 val) { - skl_dram_get_dimm_info(i915, &ch->dimm_l, - channel, 'L', val & 0xffff); - skl_dram_get_dimm_info(i915, &ch->dimm_s, - channel, 'S', val >> 16); + skl_dram_get_dimm_l_info(i915, &ch->dimm_l, channel, val); + skl_dram_get_dimm_s_info(i915, &ch->dimm_s, channel, val); if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) { drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel); -- cgit v1.2.3 From b9241d0ed9cefc7f9b9bb65533494d7776964d79 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:08 +0200 Subject: drm/{i915, xe}/display: duplicate gen2 irq/error init/reset in display irq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Duplicate gen2_irq_reset(), gen2_assert_iir_is_zero(), gen2_irq_init(), gen2_error_reset(), and gen2_error_init() in intel_display_irq.c. This allows us to drop the duplicates from xe, and prepares for future cleanups. Although duplication is undesirable in general, in this case the local duplicates lead to a cleaner end result. There's a slight wrinkle in gen2_assert_iir_is_zero(). We need to use non-device based logging until we pass in struct intel_display in a separate change. v2: - Keep xe compat stuff due to series reorder and rebase - Keep the WARN as regular WARN - Rename the functions in the same go Suggested-by: Ville Syrjala Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/296d74731cce57ab7534c57969d3146294adda57.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_irq.c | 82 +++++++++++++++++++++--- drivers/gpu/drm/xe/display/ext/i915_irq.c | 67 ------------------- 2 files changed, 73 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index 43b27deb4a26..acfaff13c3ba 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -33,6 +33,72 @@ #include "intel_psr_regs.h" #include "intel_uncore.h" +static void irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs) +{ + intel_uncore_write(uncore, regs.imr, 0xffffffff); + intel_uncore_posting_read(uncore, regs.imr); + + intel_uncore_write(uncore, regs.ier, 0); + + /* IIR can theoretically queue up two events. Be paranoid. */ + intel_uncore_write(uncore, regs.iir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.iir); + intel_uncore_write(uncore, regs.iir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.iir); +} + +/* + * We should clear IMR at preinstall/uninstall, and just check at postinstall. + */ +static void assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) +{ + u32 val = intel_uncore_read(uncore, reg); + + if (val == 0) + return; + + WARN(1, + "Interrupt register 0x%x is not zero: 0x%08x\n", + i915_mmio_reg_offset(reg), val); + intel_uncore_write(uncore, reg, 0xffffffff); + intel_uncore_posting_read(uncore, reg); + intel_uncore_write(uncore, reg, 0xffffffff); + intel_uncore_posting_read(uncore, reg); +} + +static void irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs, + u32 imr_val, u32 ier_val) +{ + assert_iir_is_zero(uncore, regs.iir); + + intel_uncore_write(uncore, regs.ier, ier_val); + intel_uncore_write(uncore, regs.imr, imr_val); + intel_uncore_posting_read(uncore, regs.imr); +} + +static void error_reset(struct intel_uncore *uncore, struct i915_error_regs regs) +{ + intel_uncore_write(uncore, regs.emr, 0xffffffff); + intel_uncore_posting_read(uncore, regs.emr); + + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); +} + +static void error_init(struct intel_uncore *uncore, struct i915_error_regs regs, + u32 emr_val) +{ + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); + intel_uncore_write(uncore, regs.eir, 0xffffffff); + intel_uncore_posting_read(uncore, regs.eir); + + intel_uncore_write(uncore, regs.emr, emr_val); + intel_uncore_posting_read(uncore, regs.emr); +} + static void intel_display_irq_regs_init(struct intel_display *display, struct i915_irq_regs regs, u32 imr_val, u32 ier_val) @@ -41,7 +107,7 @@ intel_display_irq_regs_init(struct intel_display *display, struct i915_irq_regs intel_dmc_wl_get(display, regs.ier); intel_dmc_wl_get(display, regs.iir); - gen2_irq_init(to_intel_uncore(display->drm), regs, imr_val, ier_val); + irq_init(to_intel_uncore(display->drm), regs, imr_val, ier_val); intel_dmc_wl_put(display, regs.iir); intel_dmc_wl_put(display, regs.ier); @@ -55,7 +121,7 @@ intel_display_irq_regs_reset(struct intel_display *display, struct i915_irq_regs intel_dmc_wl_get(display, regs.ier); intel_dmc_wl_get(display, regs.iir); - gen2_irq_reset(to_intel_uncore(display->drm), regs); + irq_reset(to_intel_uncore(display->drm), regs); intel_dmc_wl_put(display, regs.iir); intel_dmc_wl_put(display, regs.ier); @@ -67,7 +133,7 @@ intel_display_irq_regs_assert_irr_is_zero(struct intel_display *display, i915_re { intel_dmc_wl_get(display, reg); - gen2_assert_iir_is_zero(to_intel_uncore(display->drm), reg); + assert_iir_is_zero(to_intel_uncore(display->drm), reg); intel_dmc_wl_put(display, reg); } @@ -1918,8 +1984,7 @@ static void _vlv_display_irq_reset(struct intel_display *display) else intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); - gen2_error_reset(to_intel_uncore(display->drm), - VLV_ERROR_REGS); + error_reset(to_intel_uncore(display->drm), VLV_ERROR_REGS); i915_hotplug_interrupt_update_locked(display, 0xffffffff, 0); intel_de_rmw(display, PORT_HOTPLUG_STAT(display), 0, 0); @@ -2014,8 +2079,7 @@ static void _vlv_display_irq_postinstall(struct intel_display *display) DPINVGTT_STATUS_MASK_VLV | DPINVGTT_EN_MASK_VLV); - gen2_error_init(to_intel_uncore(display->drm), - VLV_ERROR_REGS, ~vlv_error_mask()); + error_init(to_intel_uncore(display->drm), VLV_ERROR_REGS, ~vlv_error_mask()); pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; @@ -2054,7 +2118,7 @@ static void ibx_display_irq_reset(struct intel_display *display) if (HAS_PCH_NOP(display)) return; - gen2_irq_reset(to_intel_uncore(display->drm), SDE_IRQ_REGS); + irq_reset(to_intel_uncore(display->drm), SDE_IRQ_REGS); if (HAS_PCH_CPT(display) || HAS_PCH_LPT(display)) intel_de_write(display, SERR_INT, 0xffffffff); @@ -2064,7 +2128,7 @@ void ilk_display_irq_reset(struct intel_display *display) { struct intel_uncore *uncore = to_intel_uncore(display->drm); - gen2_irq_reset(uncore, DE_IRQ_REGS); + irq_reset(uncore, DE_IRQ_REGS); display->irq.ilk_de_imr_mask = ~0u; if (DISPLAY_VER(display) == 7) diff --git a/drivers/gpu/drm/xe/display/ext/i915_irq.c b/drivers/gpu/drm/xe/display/ext/i915_irq.c index 3c6bca66ddab..1011c1c754d0 100644 --- a/drivers/gpu/drm/xe/display/ext/i915_irq.c +++ b/drivers/gpu/drm/xe/display/ext/i915_irq.c @@ -7,73 +7,6 @@ #include "i915_reg.h" #include "intel_uncore.h" -void gen2_irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs) -{ - intel_uncore_write(uncore, regs.imr, 0xffffffff); - intel_uncore_posting_read(uncore, regs.imr); - - intel_uncore_write(uncore, regs.ier, 0); - - /* IIR can theoretically queue up two events. Be paranoid. */ - intel_uncore_write(uncore, regs.iir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.iir); - intel_uncore_write(uncore, regs.iir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.iir); -} - -/* - * We should clear IMR at preinstall/uninstall, and just check at postinstall. - */ -void gen2_assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) -{ - struct xe_device *xe = container_of(uncore, struct xe_device, uncore); - u32 val = intel_uncore_read(uncore, reg); - - if (val == 0) - return; - - drm_WARN(&xe->drm, 1, - "Interrupt register 0x%x is not zero: 0x%08x\n", - i915_mmio_reg_offset(reg), val); - intel_uncore_write(uncore, reg, 0xffffffff); - intel_uncore_posting_read(uncore, reg); - intel_uncore_write(uncore, reg, 0xffffffff); - intel_uncore_posting_read(uncore, reg); -} - -void gen2_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs, - u32 imr_val, u32 ier_val) -{ - gen2_assert_iir_is_zero(uncore, regs.iir); - - intel_uncore_write(uncore, regs.ier, ier_val); - intel_uncore_write(uncore, regs.imr, imr_val); - intel_uncore_posting_read(uncore, regs.imr); -} - -void gen2_error_reset(struct intel_uncore *uncore, struct i915_error_regs regs) -{ - intel_uncore_write(uncore, regs.emr, 0xffffffff); - intel_uncore_posting_read(uncore, regs.emr); - - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); -} - -void gen2_error_init(struct intel_uncore *uncore, struct i915_error_regs regs, - u32 emr_val) -{ - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); - - intel_uncore_write(uncore, regs.emr, emr_val); - intel_uncore_posting_read(uncore, regs.emr); -} - bool intel_irqs_enabled(struct xe_device *xe) { return atomic_read(&xe->irq.enabled); -- cgit v1.2.3 From a651be53c42ae1cd44d51a7e7913edbbee976c99 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:09 +0200 Subject: drm/i915/display: convert the display irq interfaces to struct intel_display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the irq/error init/reset interfaces from struct intel_uncore to struct intel_display, and drop the dependency on intel_uncore.h. Since the intel_de_*() calls handle the DMC wakelock internally, we can drop the wrappers handling wakelocks completely. v2: Drop the wakelock wrappers (Ville) Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/710e03906da91244208839b357fe9171e37441ba.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_irq.c | 184 +++++++++-------------- 1 file changed, 68 insertions(+), 116 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index acfaff13c3ba..2a92ca6c2f82 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -19,7 +19,6 @@ #include "intel_display_trace.h" #include "intel_display_types.h" #include "intel_dmc.h" -#include "intel_dmc_wl.h" #include "intel_dp_aux.h" #include "intel_dsb.h" #include "intel_fdi_regs.h" @@ -31,111 +30,71 @@ #include "intel_pmdemand.h" #include "intel_psr.h" #include "intel_psr_regs.h" -#include "intel_uncore.h" -static void irq_reset(struct intel_uncore *uncore, struct i915_irq_regs regs) +static void irq_reset(struct intel_display *display, struct i915_irq_regs regs) { - intel_uncore_write(uncore, regs.imr, 0xffffffff); - intel_uncore_posting_read(uncore, regs.imr); + intel_de_write(display, regs.imr, 0xffffffff); + intel_de_posting_read(display, regs.imr); - intel_uncore_write(uncore, regs.ier, 0); + intel_de_write(display, regs.ier, 0); /* IIR can theoretically queue up two events. Be paranoid. */ - intel_uncore_write(uncore, regs.iir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.iir); - intel_uncore_write(uncore, regs.iir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.iir); + intel_de_write(display, regs.iir, 0xffffffff); + intel_de_posting_read(display, regs.iir); + intel_de_write(display, regs.iir, 0xffffffff); + intel_de_posting_read(display, regs.iir); } /* * We should clear IMR at preinstall/uninstall, and just check at postinstall. */ -static void assert_iir_is_zero(struct intel_uncore *uncore, i915_reg_t reg) +static void assert_iir_is_zero(struct intel_display *display, i915_reg_t reg) { - u32 val = intel_uncore_read(uncore, reg); + u32 val = intel_de_read(display, reg); if (val == 0) return; - WARN(1, + drm_WARN(display->drm, 1, "Interrupt register 0x%x is not zero: 0x%08x\n", i915_mmio_reg_offset(reg), val); - intel_uncore_write(uncore, reg, 0xffffffff); - intel_uncore_posting_read(uncore, reg); - intel_uncore_write(uncore, reg, 0xffffffff); - intel_uncore_posting_read(uncore, reg); + intel_de_write(display, reg, 0xffffffff); + intel_de_posting_read(display, reg); + intel_de_write(display, reg, 0xffffffff); + intel_de_posting_read(display, reg); } -static void irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs, +static void irq_init(struct intel_display *display, struct i915_irq_regs regs, u32 imr_val, u32 ier_val) { - assert_iir_is_zero(uncore, regs.iir); + assert_iir_is_zero(display, regs.iir); - intel_uncore_write(uncore, regs.ier, ier_val); - intel_uncore_write(uncore, regs.imr, imr_val); - intel_uncore_posting_read(uncore, regs.imr); + intel_de_write(display, regs.ier, ier_val); + intel_de_write(display, regs.imr, imr_val); + intel_de_posting_read(display, regs.imr); } -static void error_reset(struct intel_uncore *uncore, struct i915_error_regs regs) +static void error_reset(struct intel_display *display, struct i915_error_regs regs) { - intel_uncore_write(uncore, regs.emr, 0xffffffff); - intel_uncore_posting_read(uncore, regs.emr); + intel_de_write(display, regs.emr, 0xffffffff); + intel_de_posting_read(display, regs.emr); - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); + intel_de_write(display, regs.eir, 0xffffffff); + intel_de_posting_read(display, regs.eir); + intel_de_write(display, regs.eir, 0xffffffff); + intel_de_posting_read(display, regs.eir); } -static void error_init(struct intel_uncore *uncore, struct i915_error_regs regs, +static void error_init(struct intel_display *display, struct i915_error_regs regs, u32 emr_val) { - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); - intel_uncore_write(uncore, regs.eir, 0xffffffff); - intel_uncore_posting_read(uncore, regs.eir); + intel_de_write(display, regs.eir, 0xffffffff); + intel_de_posting_read(display, regs.eir); + intel_de_write(display, regs.eir, 0xffffffff); + intel_de_posting_read(display, regs.eir); - intel_uncore_write(uncore, regs.emr, emr_val); - intel_uncore_posting_read(uncore, regs.emr); -} - -static void -intel_display_irq_regs_init(struct intel_display *display, struct i915_irq_regs regs, - u32 imr_val, u32 ier_val) -{ - intel_dmc_wl_get(display, regs.imr); - intel_dmc_wl_get(display, regs.ier); - intel_dmc_wl_get(display, regs.iir); - - irq_init(to_intel_uncore(display->drm), regs, imr_val, ier_val); - - intel_dmc_wl_put(display, regs.iir); - intel_dmc_wl_put(display, regs.ier); - intel_dmc_wl_put(display, regs.imr); -} - -static void -intel_display_irq_regs_reset(struct intel_display *display, struct i915_irq_regs regs) -{ - intel_dmc_wl_get(display, regs.imr); - intel_dmc_wl_get(display, regs.ier); - intel_dmc_wl_get(display, regs.iir); - - irq_reset(to_intel_uncore(display->drm), regs); - - intel_dmc_wl_put(display, regs.iir); - intel_dmc_wl_put(display, regs.ier); - intel_dmc_wl_put(display, regs.imr); -} - -static void -intel_display_irq_regs_assert_irr_is_zero(struct intel_display *display, i915_reg_t reg) -{ - intel_dmc_wl_get(display, reg); - - assert_iir_is_zero(to_intel_uncore(display->drm), reg); - - intel_dmc_wl_put(display, reg); + intel_de_write(display, regs.emr, emr_val); + intel_de_posting_read(display, regs.emr); } struct pipe_fault_handler { @@ -1984,14 +1943,14 @@ static void _vlv_display_irq_reset(struct intel_display *display) else intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_VLV); - error_reset(to_intel_uncore(display->drm), VLV_ERROR_REGS); + error_reset(display, VLV_ERROR_REGS); i915_hotplug_interrupt_update_locked(display, 0xffffffff, 0); intel_de_rmw(display, PORT_HOTPLUG_STAT(display), 0, 0); i9xx_pipestat_irq_reset(display); - intel_display_irq_regs_reset(display, VLV_IRQ_REGS); + irq_reset(display, VLV_IRQ_REGS); display->irq.vlv_imr_mask = ~0u; } @@ -2079,7 +2038,7 @@ static void _vlv_display_irq_postinstall(struct intel_display *display) DPINVGTT_STATUS_MASK_VLV | DPINVGTT_EN_MASK_VLV); - error_init(to_intel_uncore(display->drm), VLV_ERROR_REGS, ~vlv_error_mask()); + error_init(display, VLV_ERROR_REGS, ~vlv_error_mask()); pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; @@ -2102,7 +2061,7 @@ static void _vlv_display_irq_postinstall(struct intel_display *display) display->irq.vlv_imr_mask = ~enable_mask; - intel_display_irq_regs_init(display, VLV_IRQ_REGS, display->irq.vlv_imr_mask, enable_mask); + irq_init(display, VLV_IRQ_REGS, display->irq.vlv_imr_mask, enable_mask); } void vlv_display_irq_postinstall(struct intel_display *display) @@ -2118,7 +2077,7 @@ static void ibx_display_irq_reset(struct intel_display *display) if (HAS_PCH_NOP(display)) return; - irq_reset(to_intel_uncore(display->drm), SDE_IRQ_REGS); + irq_reset(display, SDE_IRQ_REGS); if (HAS_PCH_CPT(display) || HAS_PCH_LPT(display)) intel_de_write(display, SERR_INT, 0xffffffff); @@ -2126,9 +2085,7 @@ static void ibx_display_irq_reset(struct intel_display *display) void ilk_display_irq_reset(struct intel_display *display) { - struct intel_uncore *uncore = to_intel_uncore(display->drm); - - irq_reset(uncore, DE_IRQ_REGS); + irq_reset(display, DE_IRQ_REGS); display->irq.ilk_de_imr_mask = ~0u; if (DISPLAY_VER(display) == 7) @@ -2155,10 +2112,10 @@ void gen8_display_irq_reset(struct intel_display *display) for_each_pipe(display, pipe) if (intel_display_power_is_enabled(display, POWER_DOMAIN_PIPE(pipe))) - intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); + irq_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); - intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS); - intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS); + irq_reset(display, GEN8_DE_PORT_IRQ_REGS); + irq_reset(display, GEN8_DE_MISC_IRQ_REGS); if (HAS_PCH_SPLIT(display)) ibx_display_irq_reset(display); @@ -2200,18 +2157,18 @@ void gen11_display_irq_reset(struct intel_display *display) for_each_pipe(display, pipe) if (intel_display_power_is_enabled(display, POWER_DOMAIN_PIPE(pipe))) - intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); + irq_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); - intel_display_irq_regs_reset(display, GEN8_DE_PORT_IRQ_REGS); - intel_display_irq_regs_reset(display, GEN8_DE_MISC_IRQ_REGS); + irq_reset(display, GEN8_DE_PORT_IRQ_REGS); + irq_reset(display, GEN8_DE_MISC_IRQ_REGS); if (DISPLAY_VER(display) >= 14) - intel_display_irq_regs_reset(display, PICAINTERRUPT_IRQ_REGS); + irq_reset(display, PICAINTERRUPT_IRQ_REGS); else - intel_display_irq_regs_reset(display, GEN11_DE_HPD_IRQ_REGS); + irq_reset(display, GEN11_DE_HPD_IRQ_REGS); if (INTEL_PCH_TYPE(display) >= PCH_ICP) - intel_display_irq_regs_reset(display, SDE_IRQ_REGS); + irq_reset(display, SDE_IRQ_REGS); } void gen8_irq_power_well_post_enable(struct intel_display *display, @@ -2230,9 +2187,9 @@ void gen8_irq_power_well_post_enable(struct intel_display *display, } for_each_pipe_masked(display, pipe, pipe_mask) - intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), - display->irq.de_pipe_imr_mask[pipe], - ~display->irq.de_pipe_imr_mask[pipe] | extra_ier); + irq_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), + display->irq.de_pipe_imr_mask[pipe], + ~display->irq.de_pipe_imr_mask[pipe] | extra_ier); spin_unlock_irq(&display->irq.lock); } @@ -2251,7 +2208,7 @@ void gen8_irq_power_well_pre_disable(struct intel_display *display, } for_each_pipe_masked(display, pipe, pipe_mask) - intel_display_irq_regs_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); + irq_reset(display, GEN8_DE_PIPE_IRQ_REGS(pipe)); spin_unlock_irq(&display->irq.lock); @@ -2284,7 +2241,7 @@ static void ibx_irq_postinstall(struct intel_display *display) else mask = SDE_GMBUS_CPT; - intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); + irq_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); } void valleyview_enable_display_irqs(struct intel_display *display) @@ -2350,7 +2307,7 @@ void ilk_de_irq_postinstall(struct intel_display *display) } if (display->platform.haswell) { - intel_display_irq_regs_assert_irr_is_zero(display, EDP_PSR_IIR); + assert_iir_is_zero(display, EDP_PSR_IIR); display_mask |= DE_EDP_PSR_INT_HSW; } @@ -2361,8 +2318,8 @@ void ilk_de_irq_postinstall(struct intel_display *display) ibx_irq_postinstall(display); - intel_display_irq_regs_init(display, DE_IRQ_REGS, display->irq.ilk_de_imr_mask, - display_mask | extra_mask); + irq_init(display, DE_IRQ_REGS, display->irq.ilk_de_imr_mask, + display_mask | extra_mask); } static void mtp_irq_postinstall(struct intel_display *display); @@ -2438,11 +2395,10 @@ void gen8_de_irq_postinstall(struct intel_display *display) if (!intel_display_power_is_enabled(display, domain)) continue; - intel_display_irq_regs_assert_irr_is_zero(display, - TRANS_PSR_IIR(display, trans)); + assert_iir_is_zero(display, TRANS_PSR_IIR(display, trans)); } } else { - intel_display_irq_regs_assert_irr_is_zero(display, EDP_PSR_IIR); + assert_iir_is_zero(display, EDP_PSR_IIR); } for_each_pipe(display, pipe) { @@ -2450,23 +2406,20 @@ void gen8_de_irq_postinstall(struct intel_display *display) if (intel_display_power_is_enabled(display, POWER_DOMAIN_PIPE(pipe))) - intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), - display->irq.de_pipe_imr_mask[pipe], - de_pipe_enables); + irq_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), + display->irq.de_pipe_imr_mask[pipe], + de_pipe_enables); } - intel_display_irq_regs_init(display, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, - de_port_enables); - intel_display_irq_regs_init(display, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, - de_misc_masked); + irq_init(display, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, de_port_enables); + irq_init(display, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, de_misc_masked); if (IS_DISPLAY_VER(display, 11, 13)) { u32 de_hpd_masked = 0; u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK; - intel_display_irq_regs_init(display, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked, - de_hpd_enables); + irq_init(display, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked, de_hpd_enables); } } @@ -2477,17 +2430,16 @@ static void mtp_irq_postinstall(struct intel_display *display) u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK | XELPDP_TBT_HOTPLUG_MASK; - intel_display_irq_regs_init(display, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask, - de_hpd_enables); + irq_init(display, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask, de_hpd_enables); - intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~sde_mask, 0xffffffff); + irq_init(display, SDE_IRQ_REGS, ~sde_mask, 0xffffffff); } static void icp_irq_postinstall(struct intel_display *display) { u32 mask = SDE_GMBUS_ICP; - intel_display_irq_regs_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); + irq_init(display, SDE_IRQ_REGS, ~mask, 0xffffffff); } void gen11_de_irq_postinstall(struct intel_display *display) -- cgit v1.2.3 From 3815e8f2ffe44396d10b100fbd38f511dfefbbc7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:10 +0200 Subject: drm/{i915,xe}/display: move irq calls to parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an irq parent driver interface for the .enabled and .synchronize calls. This lets us drop the dependency on i915_drv.h and i915_irq.h in multiple places, and subsequently remove the compat i915_irq.h and i915_irq.c files along with the display/ext directory from xe altogether. Introduce new intel_parent.[ch] as the wrapper layer to chase the function pointers and convert between generic and more specific display types. v2: Keep static wrappers in intel_display_irq.c (Ville) v3: Full blown wrappers in intel_parent.[ch] (Ville) Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/dd62dd52ef10d9ecf77da3bdf6a70f71193d141c.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_display_irq.c | 37 +++++++--------------- drivers/gpu/drm/i915/display/intel_display_power.c | 5 ++- .../drm/i915/display/intel_display_power_well.c | 15 +++------ drivers/gpu/drm/i915/display/intel_gmbus.c | 6 ++-- drivers/gpu/drm/i915/display/intel_hotplug.c | 6 ++-- drivers/gpu/drm/i915/display/intel_lpe_audio.c | 1 - drivers/gpu/drm/i915/display/intel_parent.c | 33 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_parent.h | 14 ++++++++ drivers/gpu/drm/i915/display/intel_pipe_crc.c | 6 ++-- drivers/gpu/drm/i915/i915_driver.c | 1 + drivers/gpu/drm/i915/i915_irq.c | 16 ++++++++++ drivers/gpu/drm/i915/i915_irq.h | 2 ++ drivers/gpu/drm/xe/Makefile | 5 ++- drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h | 6 ---- drivers/gpu/drm/xe/display/ext/i915_irq.c | 18 ----------- drivers/gpu/drm/xe/display/xe_display.c | 18 +++++++++++ include/drm/intel/display_parent_interface.h | 8 +++++ 18 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_parent.c create mode 100644 drivers/gpu/drm/i915/display/intel_parent.h delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h delete mode 100644 drivers/gpu/drm/xe/display/ext/i915_irq.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 49c86a0d44f9..477278aee831 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -292,6 +292,7 @@ i915-y += \ display/intel_modeset_verify.o \ display/intel_overlay.o \ display/intel_panic.o \ + display/intel_parent.o \ display/intel_pch.o \ display/intel_pch_display.o \ display/intel_pch_refclk.o \ diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index 2a92ca6c2f82..d2933ac3acb4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -6,8 +6,6 @@ #include #include -#include "i915_drv.h" -#include "i915_irq.h" #include "i915_reg.h" #include "icl_dsi_regs.h" #include "intel_crtc.h" @@ -25,6 +23,7 @@ #include "intel_fifo_underrun.h" #include "intel_gmbus.h" #include "intel_hotplug_irq.h" +#include "intel_parent.h" #include "intel_pipe_crc_regs.h" #include "intel_plane.h" #include "intel_pmdemand.h" @@ -160,7 +159,6 @@ intel_handle_vblank(struct intel_display *display, enum pipe pipe) void ilk_update_display_irq(struct intel_display *display, u32 interrupt_mask, u32 enabled_irq_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 new_val; lockdep_assert_held(&display->irq.lock); @@ -171,7 +169,7 @@ void ilk_update_display_irq(struct intel_display *display, new_val |= (~enabled_irq_mask & interrupt_mask); if (new_val != display->irq.ilk_de_imr_mask && - !drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) { + !drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display))) { display->irq.ilk_de_imr_mask = new_val; intel_de_write(display, DEIMR, display->irq.ilk_de_imr_mask); intel_de_posting_read(display, DEIMR); @@ -197,7 +195,6 @@ void ilk_disable_display_irq(struct intel_display *display, u32 bits) void bdw_update_port_irq(struct intel_display *display, u32 interrupt_mask, u32 enabled_irq_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 new_val; u32 old_val; @@ -205,7 +202,7 @@ void bdw_update_port_irq(struct intel_display *display, drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask); - if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) + if (drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display))) return; old_val = intel_de_read(display, GEN8_DE_PORT_IMR); @@ -231,14 +228,13 @@ static void bdw_update_pipe_irq(struct intel_display *display, enum pipe pipe, u32 interrupt_mask, u32 enabled_irq_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 new_val; lockdep_assert_held(&display->irq.lock); drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask); - if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) + if (drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display))) return; new_val = display->irq.de_pipe_imr_mask[pipe]; @@ -274,7 +270,6 @@ void ibx_display_interrupt_update(struct intel_display *display, u32 interrupt_mask, u32 enabled_irq_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 sdeimr = intel_de_read(display, SDEIMR); sdeimr &= ~interrupt_mask; @@ -284,7 +279,7 @@ void ibx_display_interrupt_update(struct intel_display *display, lockdep_assert_held(&display->irq.lock); - if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) + if (drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display))) return; intel_de_write(display, SDEIMR, sdeimr); @@ -348,7 +343,6 @@ out: void i915_enable_pipestat(struct intel_display *display, enum pipe pipe, u32 status_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); i915_reg_t reg = PIPESTAT(display, pipe); u32 enable_mask; @@ -357,7 +351,7 @@ void i915_enable_pipestat(struct intel_display *display, pipe_name(pipe), status_mask); lockdep_assert_held(&display->irq.lock); - drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv)); + drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display)); if ((display->irq.pipestat_irq_mask[pipe] & status_mask) == status_mask) return; @@ -372,7 +366,6 @@ void i915_enable_pipestat(struct intel_display *display, void i915_disable_pipestat(struct intel_display *display, enum pipe pipe, u32 status_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); i915_reg_t reg = PIPESTAT(display, pipe); u32 enable_mask; @@ -381,7 +374,7 @@ void i915_disable_pipestat(struct intel_display *display, pipe_name(pipe), status_mask); lockdep_assert_held(&display->irq.lock); - drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv)); + drm_WARN_ON(display->drm, !intel_parent_irq_enabled(display)); if ((display->irq.pipestat_irq_mask[pipe] & status_mask) == 0) return; @@ -2174,14 +2167,13 @@ void gen11_display_irq_reset(struct intel_display *display) void gen8_irq_power_well_post_enable(struct intel_display *display, u8 pipe_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN | gen8_de_pipe_flip_done_mask(display); enum pipe pipe; spin_lock_irq(&display->irq.lock); - if (!intel_irqs_enabled(dev_priv)) { + if (!intel_parent_irq_enabled(display)) { spin_unlock_irq(&display->irq.lock); return; } @@ -2197,12 +2189,11 @@ void gen8_irq_power_well_post_enable(struct intel_display *display, void gen8_irq_power_well_pre_disable(struct intel_display *display, u8 pipe_mask) { - struct drm_i915_private *dev_priv = to_i915(display->drm); enum pipe pipe; spin_lock_irq(&display->irq.lock); - if (!intel_irqs_enabled(dev_priv)) { + if (!intel_parent_irq_enabled(display)) { spin_unlock_irq(&display->irq.lock); return; } @@ -2213,7 +2204,7 @@ void gen8_irq_power_well_pre_disable(struct intel_display *display, spin_unlock_irq(&display->irq.lock); /* make sure we're done processing display irqs */ - intel_synchronize_irq(dev_priv); + intel_parent_irq_synchronize(display); } /* @@ -2246,8 +2237,6 @@ static void ibx_irq_postinstall(struct intel_display *display) void valleyview_enable_display_irqs(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - spin_lock_irq(&display->irq.lock); if (display->irq.vlv_display_irqs_enabled) @@ -2255,7 +2244,7 @@ void valleyview_enable_display_irqs(struct intel_display *display) display->irq.vlv_display_irqs_enabled = true; - if (intel_irqs_enabled(dev_priv)) { + if (intel_parent_irq_enabled(display)) { _vlv_display_irq_reset(display); _vlv_display_irq_postinstall(display); } @@ -2266,8 +2255,6 @@ out: void valleyview_disable_display_irqs(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - spin_lock_irq(&display->irq.lock); if (!display->irq.vlv_display_irqs_enabled) @@ -2275,7 +2262,7 @@ void valleyview_disable_display_irqs(struct intel_display *display) display->irq.vlv_display_irqs_enabled = false; - if (intel_irqs_enabled(dev_priv)) + if (intel_parent_irq_enabled(display)) _vlv_display_irq_reset(display); out: spin_unlock_irq(&display->irq.lock); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 2a4cc1dcc293..a383ef23391d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -11,7 +11,6 @@ #include "soc/intel_dram.h" #include "i915_drv.h" -#include "i915_irq.h" #include "i915_reg.h" #include "intel_backlight_regs.h" #include "intel_cdclk.h" @@ -27,6 +26,7 @@ #include "intel_display_utils.h" #include "intel_dmc.h" #include "intel_mchbar_regs.h" +#include "intel_parent.h" #include "intel_pch_refclk.h" #include "intel_pcode.h" #include "intel_pmdemand.h" @@ -1202,7 +1202,6 @@ static void hsw_assert_cdclk(struct intel_display *display) static void assert_can_disable_lcpll(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_crtc *crtc; for_each_intel_crtc(display->drm, crtc) @@ -1247,7 +1246,7 @@ static void assert_can_disable_lcpll(struct intel_display *display) * gen-specific and since we only disable LCPLL after we fully disable * the interrupts, the check below should be enough. */ - INTEL_DISPLAY_STATE_WARN(display, intel_irqs_enabled(dev_priv), + INTEL_DISPLAY_STATE_WARN(display, intel_parent_irq_enabled(display), "IRQs enabled\n"); } 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 f4f7e73acc87..719f58e43269 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -7,8 +7,6 @@ #include -#include "i915_drv.h" -#include "i915_irq.h" #include "i915_reg.h" #include "intel_backlight_regs.h" #include "intel_combo_phy.h" @@ -28,6 +26,7 @@ #include "intel_dpio_phy.h" #include "intel_dpll.h" #include "intel_hotplug.h" +#include "intel_parent.h" #include "intel_pcode.h" #include "intel_pps.h" #include "intel_psr.h" @@ -628,8 +627,6 @@ static bool hsw_power_well_enabled(struct intel_display *display, static void assert_can_enable_dc9(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - drm_WARN_ONCE(display->drm, (intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_DC9), "DC9 already programmed to be enabled.\n"); @@ -641,7 +638,7 @@ static void assert_can_enable_dc9(struct intel_display *display) intel_de_read(display, HSW_PWR_WELL_CTL2) & HSW_PWR_WELL_CTL_REQ(SKL_PW_CTL_IDX_PW_2), "Power well 2 on.\n"); - drm_WARN_ONCE(display->drm, intel_irqs_enabled(dev_priv), + drm_WARN_ONCE(display->drm, intel_parent_irq_enabled(display), "Interrupts not disabled yet.\n"); /* @@ -655,9 +652,7 @@ static void assert_can_enable_dc9(struct intel_display *display) static void assert_can_disable_dc9(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - - drm_WARN_ONCE(display->drm, intel_irqs_enabled(dev_priv), + drm_WARN_ONCE(display->drm, intel_parent_irq_enabled(display), "Interrupts not disabled yet.\n"); drm_WARN_ONCE(display->drm, intel_de_read(display, DC_STATE_EN) & @@ -1281,12 +1276,10 @@ static void vlv_display_power_well_init(struct intel_display *display) static void vlv_display_power_well_deinit(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); - valleyview_disable_display_irqs(display); /* make sure we're done processing display irqs */ - intel_synchronize_irq(dev_priv); + intel_parent_irq_synchronize(display); vlv_pps_reset_all(display); diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 795012d7c24c..acc85853b2a7 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -35,8 +35,6 @@ #include #include -#include "i915_drv.h" -#include "i915_irq.h" #include "i915_reg.h" #include "intel_de.h" #include "intel_display_regs.h" @@ -44,6 +42,7 @@ #include "intel_display_wa.h" #include "intel_gmbus.h" #include "intel_gmbus_regs.h" +#include "intel_parent.h" struct intel_gmbus { struct i2c_adapter adapter; @@ -391,12 +390,11 @@ intel_gpio_setup(struct intel_gmbus *bus, i915_reg_t gpio_reg) static bool has_gmbus_irq(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); /* * encoder->shutdown() may want to use GMBUS * after irqs have already been disabled. */ - return HAS_GMBUS_IRQ(display) && intel_irqs_enabled(i915); + return HAS_GMBUS_IRQ(display) && intel_parent_irq_enabled(display); } static int gmbus_wait(struct intel_display *display, u32 status, u32 irq_en) diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 235706229ffb..7575a063f7be 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -27,8 +27,6 @@ #include #include -#include "i915_drv.h" -#include "i915_irq.h" #include "intel_connector.h" #include "intel_display_core.h" #include "intel_display_power.h" @@ -39,6 +37,7 @@ #include "intel_hdcp.h" #include "intel_hotplug.h" #include "intel_hotplug_irq.h" +#include "intel_parent.h" /** * DOC: Hotplug @@ -1177,13 +1176,12 @@ bool intel_hpd_schedule_detection(struct intel_display *display) static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data) { struct intel_display *display = m->private; - struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_hotplug *hotplug = &display->hotplug; /* Synchronize with everything first in case there's been an HPD * storm, but we haven't finished handling it in the kernel yet */ - intel_synchronize_irq(dev_priv); + intel_parent_irq_synchronize(display); flush_work(&display->hotplug.dig_port_work); flush_delayed_work(&display->hotplug.hotplug_work); diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c index 42284e9928f2..5b41abe1c64d 100644 --- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c @@ -71,7 +71,6 @@ #include #include -#include "i915_irq.h" #include "intel_audio_regs.h" #include "intel_de.h" #include "intel_lpe_audio.h" diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c new file mode 100644 index 000000000000..375713f6f411 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2025 Intel Corporation */ + +/* + * Convenience wrapper functions to call the parent interface functions: + * + * - display->parent->SUBSTRUCT->FUNCTION() + * - display->parent->FUNCTION() + * + * All functions here should be named accordingly: + * + * - intel_parent_SUBSTRUCT_FUNCTION() + * - intel_parent_FUNCTION() + * + * These functions may use display driver specific types for parameters and + * return values, translating them to and from the generic types used in the + * function pointer interface. + */ + +#include + +#include "intel_display_core.h" +#include "intel_parent.h" + +bool intel_parent_irq_enabled(struct intel_display *display) +{ + return display->parent->irq->enabled(display->drm); +} + +void intel_parent_irq_synchronize(struct intel_display *display) +{ + display->parent->irq->synchronize(display->drm); +} diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h new file mode 100644 index 000000000000..3ade493f1008 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __INTEL_PARENT_H__ +#define __INTEL_PARENT_H__ + +#include + +struct intel_display; + +bool intel_parent_irq_enabled(struct intel_display *display); +void intel_parent_irq_synchronize(struct intel_display *display); + +#endif /* __INTEL_PARENT_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c index 1f27643412f1..71cb0178c8b1 100644 --- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c @@ -30,13 +30,12 @@ #include -#include "i915_drv.h" -#include "i915_irq.h" #include "intel_atomic.h" #include "intel_de.h" #include "intel_display_irq.h" #include "intel_display_regs.h" #include "intel_display_types.h" +#include "intel_parent.h" #include "intel_pipe_crc.h" #include "intel_pipe_crc_regs.h" @@ -658,7 +657,6 @@ void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc) void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(crtc); - struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc; enum pipe pipe = crtc->pipe; @@ -669,5 +667,5 @@ void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc) intel_de_write(display, PIPE_CRC_CTL(display, pipe), 0); intel_de_posting_read(display, PIPE_CRC_CTL(display, pipe)); - intel_synchronize_irq(dev_priv); + intel_parent_irq_synchronize(display); } diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index c97b76771917..07715aef62d3 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -741,6 +741,7 @@ static void i915_welcome_messages(struct drm_i915_private *dev_priv) static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, + .irq = &i915_display_irq_interface, }; const struct intel_display_parent_interface *i915_driver_parent_interface(void) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1898be4ddc8b..3fe978d4ea53 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -33,6 +33,7 @@ #include #include +#include #include "display/intel_display_irq.h" #include "display/intel_hotplug.h" @@ -1252,3 +1253,18 @@ void intel_synchronize_hardirq(struct drm_i915_private *i915) { synchronize_hardirq(to_pci_dev(i915->drm.dev)->irq); } + +static bool _intel_irq_enabled(struct drm_device *drm) +{ + return intel_irqs_enabled(to_i915(drm)); +} + +static void _intel_irq_synchronize(struct drm_device *drm) +{ + return intel_synchronize_irq(to_i915(drm)); +} + +const struct intel_display_irq_interface i915_display_irq_interface = { + .enabled = _intel_irq_enabled, + .synchronize = _intel_irq_synchronize, +}; diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h index 58789b264575..5c87d6d41c74 100644 --- a/drivers/gpu/drm/i915/i915_irq.h +++ b/drivers/gpu/drm/i915/i915_irq.h @@ -51,4 +51,6 @@ void gen2_error_reset(struct intel_uncore *uncore, struct i915_error_regs regs); void gen2_error_init(struct intel_uncore *uncore, struct i915_error_regs regs, u32 emr_val); +extern const struct intel_display_irq_interface i915_display_irq_interface; + #endif /* __I915_IRQ_H__ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index f8a3a1bfe42e..8967f874280e 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -187,7 +187,6 @@ endif # i915 Display compat #defines and #includes subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \ - -I$(src)/display/ext \ -I$(src)/compat-i915-headers \ -I$(srctree)/drivers/gpu/drm/i915/display/ \ -Ddrm_i915_private=xe_device @@ -204,7 +203,6 @@ $(obj)/i915-display/%.o: $(srctree)/drivers/gpu/drm/i915/display/%.c FORCE # Display code specific to xe xe-$(CONFIG_DRM_XE_DISPLAY) += \ - display/ext/i915_irq.o \ display/intel_bo.o \ display/intel_fb_bo.o \ display/intel_fbdev_fb.o \ @@ -300,10 +298,11 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_modeset_setup.o \ i915-display/intel_modeset_verify.o \ i915-display/intel_panel.o \ + i915-display/intel_parent.o \ + i915-display/intel_pch.o \ i915-display/intel_pfit.o \ i915-display/intel_plane.o \ i915-display/intel_pmdemand.o \ - i915-display/intel_pch.o \ i915-display/intel_pps.o \ i915-display/intel_psr.o \ i915-display/intel_qp_tables.o \ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h deleted file mode 100644 index 61707a07f91f..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_irq.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#include "../../i915/i915_irq.h" diff --git a/drivers/gpu/drm/xe/display/ext/i915_irq.c b/drivers/gpu/drm/xe/display/ext/i915_irq.c deleted file mode 100644 index 1011c1c754d0..000000000000 --- a/drivers/gpu/drm/xe/display/ext/i915_irq.c +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2023 Intel Corporation - */ - -#include "i915_irq.h" -#include "i915_reg.h" -#include "intel_uncore.h" - -bool intel_irqs_enabled(struct xe_device *xe) -{ - return atomic_read(&xe->irq.enabled); -} - -void intel_synchronize_irq(struct xe_device *xe) -{ - synchronize_irq(to_pci_dev(xe->drm.dev)->irq); -} diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 8b0afa270216..e3320d9e6314 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -516,8 +516,26 @@ static void display_device_remove(struct drm_device *dev, void *arg) intel_display_device_remove(display); } +static bool irq_enabled(struct drm_device *drm) +{ + struct xe_device *xe = to_xe_device(drm); + + return atomic_read(&xe->irq.enabled); +} + +static void irq_synchronize(struct drm_device *drm) +{ + synchronize_irq(to_pci_dev(drm->dev)->irq); +} + +static const struct intel_display_irq_interface xe_display_irq_interface = { + .enabled = irq_enabled, + .synchronize = irq_synchronize, +}; + static const struct intel_display_parent_interface parent = { .rpm = &xe_display_rpm_interface, + .irq = &xe_display_irq_interface, }; /** diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 26bedc360044..3a008a18eb65 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -25,6 +25,11 @@ struct intel_display_rpm_interface { void (*assert_unblock)(const struct drm_device *drm); }; +struct intel_display_irq_interface { + bool (*enabled)(struct drm_device *drm); + void (*synchronize)(struct drm_device *drm); +}; + /** * struct intel_display_parent_interface - services parent driver provides to display * @@ -40,6 +45,9 @@ struct intel_display_rpm_interface { struct intel_display_parent_interface { /** @rpm: Runtime PM functions */ const struct intel_display_rpm_interface *rpm; + + /** @irq: IRQ interface */ + const struct intel_display_irq_interface *irq; }; #endif -- cgit v1.2.3 From e8916738977e29a6f1e8edc593ee336f2bcf1b7d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:11 +0200 Subject: drm/i915: add .vgpu_active to parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add .vgpu_active() to display parent interface, removing more dependencies on struct drm_i915_private, i915_drv.h, and i915_vgpu.h. This also allows us to remove the xe compat i915_vgpu.h. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/a2d4043ebaaf8f69bb738d5d1332afd2847550ad.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_crtc.c | 6 ++---- drivers/gpu/drm/i915/display/intel_fbc.c | 5 ++--- drivers/gpu/drm/i915/display/intel_parent.c | 5 +++++ drivers/gpu/drm/i915/display/intel_parent.h | 2 ++ drivers/gpu/drm/i915/i915_driver.c | 6 ++++++ drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h | 18 ------------------ include/drm/intel/display_parent_interface.h | 3 +++ 7 files changed, 20 insertions(+), 25 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 9d2a23c96c61..153ff4b4b52c 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -13,8 +13,6 @@ #include #include -#include "i915_drv.h" -#include "i915_vgpu.h" #include "i9xx_plane.h" #include "icl_dsi.h" #include "intel_atomic.h" @@ -28,6 +26,7 @@ #include "intel_drrs.h" #include "intel_dsi.h" #include "intel_fifo_underrun.h" +#include "intel_parent.h" #include "intel_pipe_crc.h" #include "intel_plane.h" #include "intel_psr.h" @@ -671,7 +670,6 @@ void intel_pipe_update_end(struct intel_atomic_state *state, int scanline_end = intel_get_crtc_scanline(crtc); u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc); ktime_t end_vbl_time = ktime_get(); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); drm_WARN_ON(display->drm, new_crtc_state->use_dsb); @@ -737,7 +735,7 @@ void intel_pipe_update_end(struct intel_atomic_state *state, local_irq_enable(); - if (intel_vgpu_active(dev_priv)) + if (intel_parent_vgpu_active(display)) goto out; if (crtc->debug.start_vbl_count && diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 205c7266af43..cfadc69010a4 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -50,7 +50,6 @@ #include "gt/intel_gt_types.h" #include "i915_drv.h" -#include "i915_vgpu.h" #include "i915_vma.h" #include "i9xx_plane_regs.h" #include "intel_de.h" @@ -64,6 +63,7 @@ #include "intel_fbc.h" #include "intel_fbc_regs.h" #include "intel_frontbuffer.h" +#include "intel_parent.h" #define for_each_fbc_id(__display, __fbc_id) \ for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \ @@ -1485,7 +1485,6 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, struct intel_plane *plane) { struct intel_display *display = to_intel_display(state->base.dev); - struct drm_i915_private *i915 = to_i915(display->drm); struct intel_plane_state *plane_state = intel_atomic_get_new_plane_state(state, plane); const struct drm_framebuffer *fb = plane_state->hw.fb; @@ -1501,7 +1500,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } - if (intel_vgpu_active(i915)) { + if (intel_parent_vgpu_active(display)) { plane_state->no_fbc_reason = "VGPU active"; return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 375713f6f411..3786fd42827d 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -31,3 +31,8 @@ void intel_parent_irq_synchronize(struct intel_display *display) { display->parent->irq->synchronize(display->drm); } + +bool intel_parent_vgpu_active(struct intel_display *display) +{ + return display->parent->vgpu_active && display->parent->vgpu_active(display->drm); +} diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index 3ade493f1008..222c95836d35 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -11,4 +11,6 @@ struct intel_display; bool intel_parent_irq_enabled(struct intel_display *display); void intel_parent_irq_synchronize(struct intel_display *display); +bool intel_parent_vgpu_active(struct intel_display *display); + #endif /* __INTEL_PARENT_H__ */ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 07715aef62d3..f21f1919a225 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -739,9 +739,15 @@ static void i915_welcome_messages(struct drm_i915_private *dev_priv) "DRM_I915_DEBUG_RUNTIME_PM enabled\n"); } +static bool vgpu_active(struct drm_device *drm) +{ + return intel_vgpu_active(to_i915(drm)); +} + static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, .irq = &i915_display_irq_interface, + .vgpu_active = vgpu_active, }; const struct intel_display_parent_interface *i915_driver_parent_interface(void) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h deleted file mode 100644 index 4931c7198f13..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_vgpu.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef _I915_VGPU_H_ -#define _I915_VGPU_H_ - -#include - -struct drm_i915_private; - -static inline bool intel_vgpu_active(struct drm_i915_private *i915) -{ - return false; -} - -#endif /* _I915_VGPU_H_ */ diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 3a008a18eb65..f3834f36ce74 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -48,6 +48,9 @@ struct intel_display_parent_interface { /** @irq: IRQ interface */ const struct intel_display_irq_interface *irq; + + /** @vgpu_active: Is vGPU active? Optional. */ + bool (*vgpu_active)(struct drm_device *drm); }; #endif -- cgit v1.2.3 From 4799ff418f9a68361331fdc7fc01f66dc314adb9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:12 +0200 Subject: drm/i915: add .has_fenced_regions to parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add .has_fenced_regions() to display parent interface, removing more dependencies on struct drm_i915_private, i915_drv.h, and gt/intel_gt_types.h. This allows us to remove the xe compat gt/intel_gt_types.h. v2: s/fence_support_legacy/has_fenced_regions/ (Ville) Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/309f61a8742c3bf731c820b2f9e1024143db8598.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fbc.c | 8 ++------ drivers/gpu/drm/i915/display/intel_parent.c | 5 +++++ drivers/gpu/drm/i915/display/intel_parent.h | 2 ++ drivers/gpu/drm/i915/i915_driver.c | 6 ++++++ drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h | 11 ----------- include/drm/intel/display_parent_interface.h | 3 +++ 6 files changed, 18 insertions(+), 17 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index cfadc69010a4..d9cab25d414a 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -47,9 +47,6 @@ #include "gem/i915_gem_stolen.h" -#include "gt/intel_gt_types.h" - -#include "i915_drv.h" #include "i915_vma.h" #include "i9xx_plane_regs.h" #include "intel_de.h" @@ -64,6 +61,7 @@ #include "intel_fbc_regs.h" #include "intel_frontbuffer.h" #include "intel_parent.h" +#include "intel_step.h" #define for_each_fbc_id(__display, __fbc_id) \ for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \ @@ -267,9 +265,7 @@ static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_s static bool intel_fbc_has_fences(struct intel_display *display) { - struct drm_i915_private __maybe_unused *i915 = to_i915(display->drm); - - return intel_gt_support_legacy_fencing(to_gt(i915)); + return intel_parent_has_fenced_regions(display); } static u32 i8xx_fbc_ctl(struct intel_fbc *fbc) diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 3786fd42827d..535065e57213 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -36,3 +36,8 @@ bool intel_parent_vgpu_active(struct intel_display *display) { return display->parent->vgpu_active && display->parent->vgpu_active(display->drm); } + +bool intel_parent_has_fenced_regions(struct intel_display *display) +{ + return display->parent->has_fenced_regions && display->parent->has_fenced_regions(display->drm); +} diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index 222c95836d35..04320d937777 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -13,4 +13,6 @@ void intel_parent_irq_synchronize(struct intel_display *display); bool intel_parent_vgpu_active(struct intel_display *display); +bool intel_parent_has_fenced_regions(struct intel_display *display); + #endif /* __INTEL_PARENT_H__ */ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index f21f1919a225..9ba46850da72 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -744,10 +744,16 @@ static bool vgpu_active(struct drm_device *drm) return intel_vgpu_active(to_i915(drm)); } +static bool has_fenced_regions(struct drm_device *drm) +{ + return intel_gt_support_legacy_fencing(to_gt(to_i915(drm))); +} + static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, .irq = &i915_display_irq_interface, .vgpu_active = vgpu_active, + .has_fenced_regions = has_fenced_regions, }; const struct intel_display_parent_interface *i915_driver_parent_interface(void) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h b/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h deleted file mode 100644 index c15806d6c4f7..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/gt/intel_gt_types.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef __INTEL_GT_TYPES__ -#define __INTEL_GT_TYPES__ - -#define intel_gt_support_legacy_fencing(gt) 0 - -#endif diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index f3834f36ce74..927d964f2071 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -51,6 +51,9 @@ struct intel_display_parent_interface { /** @vgpu_active: Is vGPU active? Optional. */ bool (*vgpu_active)(struct drm_device *drm); + + /** @has_fenced_regions: Support legacy fencing? Optional. */ + bool (*has_fenced_regions)(struct drm_device *drm); }; #endif -- cgit v1.2.3 From 95c04f442941cb9829e791d0bef460317a17819c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:13 +0200 Subject: drm/i915/rps: store struct dma_fence in struct wait_rps_boost MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer the more generic pointer rather than i915 specific data type. Also use dma_fence_put() for symmetry with the dma_fence_get() Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/950948ae6d3d5fbc4af3401ea77e609945b73a77.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_rps.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.c b/drivers/gpu/drm/i915/display/intel_display_rps.c index 82ea1ec482e4..b6720f7c09d9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.c +++ b/drivers/gpu/drm/i915/display/intel_display_rps.c @@ -18,14 +18,14 @@ struct wait_rps_boost { struct wait_queue_entry wait; struct drm_crtc *crtc; - struct i915_request *request; + struct dma_fence *fence; }; static int do_rps_boost(struct wait_queue_entry *_wait, unsigned mode, int sync, void *key) { struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait); - struct i915_request *rq = wait->request; + struct i915_request *rq = to_request(wait->fence); /* * If we missed the vblank, but the request is already running it @@ -34,7 +34,7 @@ static int do_rps_boost(struct wait_queue_entry *_wait, */ if (!i915_request_started(rq)) intel_rps_boost(rq); - i915_request_put(rq); + dma_fence_put(wait->fence); drm_crtc_vblank_put(wait->crtc); @@ -64,7 +64,7 @@ void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, return; } - wait->request = to_request(dma_fence_get(fence)); + wait->fence = dma_fence_get(fence); wait->crtc = crtc; wait->wait.func = do_rps_boost; -- cgit v1.2.3 From 1314027632ae2d98ec7ba250495d1a6084caafc6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:14 +0200 Subject: drm/i915/rps: call RPS functions via the parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add struct intel_display_rps_interface to the display parent interface, and call the RPS functions through it. The RPS interface is optional. v2: s/boost/boost_if_not_started/ and keep comment in caller (Ville) Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/6a6c4420d9f2d9a545ee6df4cad5fdc32a86636b.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_rps.c | 27 +++++++++++++--------- drivers/gpu/drm/i915/display/intel_parent.c | 23 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_parent.h | 6 +++++ drivers/gpu/drm/i915/gt/intel_rps.c | 29 ++++++++++++++++++++++++ drivers/gpu/drm/i915/gt/intel_rps.h | 2 ++ drivers/gpu/drm/i915/i915_driver.c | 2 ++ include/drm/intel/display_parent_interface.h | 10 ++++++++ 7 files changed, 88 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.c b/drivers/gpu/drm/i915/display/intel_display_rps.c index b6720f7c09d9..d639d9152bf5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.c +++ b/drivers/gpu/drm/i915/display/intel_display_rps.c @@ -3,16 +3,18 @@ * Copyright © 2023 Intel Corporation */ +#include + #include #include -#include "gt/intel_rps.h" -#include "i915_drv.h" #include "i915_reg.h" +#include "i915_request.h" #include "intel_display_core.h" #include "intel_display_irq.h" #include "intel_display_rps.h" #include "intel_display_types.h" +#include "intel_parent.h" struct wait_rps_boost { struct wait_queue_entry wait; @@ -25,15 +27,15 @@ static int do_rps_boost(struct wait_queue_entry *_wait, unsigned mode, int sync, void *key) { struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait); - struct i915_request *rq = to_request(wait->fence); + struct intel_display *display = to_intel_display(wait->crtc->dev); /* * If we missed the vblank, but the request is already running it * is reasonable to assume that it will complete before the next - * vblank without our intervention, so leave RPS alone. + * vblank without our intervention, so leave RPS alone if not started. */ - if (!i915_request_started(rq)) - intel_rps_boost(rq); + intel_parent_rps_boost_if_not_started(display, wait->fence); + dma_fence_put(wait->fence); drm_crtc_vblank_put(wait->crtc); @@ -49,6 +51,9 @@ void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, struct intel_display *display = to_intel_display(crtc->dev); struct wait_rps_boost *wait; + if (!intel_parent_rps_available(display)) + return; + if (!dma_fence_is_i915(fence)) return; @@ -77,12 +82,14 @@ void intel_display_rps_mark_interactive(struct intel_display *display, struct intel_atomic_state *state, bool interactive) { - struct drm_i915_private *i915 = to_i915(display->drm); + if (!intel_parent_rps_available(display)) + return; if (state->rps_interactive == interactive) return; - intel_rps_mark_interactive(&to_gt(i915)->rps, interactive); + intel_parent_rps_mark_interactive(display, interactive); + state->rps_interactive = interactive; } @@ -102,7 +109,5 @@ void ilk_display_rps_disable(struct intel_display *display) void ilk_display_rps_irq_handler(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - gen5_rps_irq_handler(&to_gt(i915)->rps); + intel_parent_rps_ilk_irq_handler(display); } diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 535065e57213..6c131196718e 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -32,6 +32,29 @@ void intel_parent_irq_synchronize(struct intel_display *display) display->parent->irq->synchronize(display->drm); } +bool intel_parent_rps_available(struct intel_display *display) +{ + return display->parent->rps; +} + +void intel_parent_rps_boost_if_not_started(struct intel_display *display, struct dma_fence *fence) +{ + if (display->parent->rps) + display->parent->rps->boost_if_not_started(fence); +} + +void intel_parent_rps_mark_interactive(struct intel_display *display, bool interactive) +{ + if (display->parent->rps) + display->parent->rps->mark_interactive(display->drm, interactive); +} + +void intel_parent_rps_ilk_irq_handler(struct intel_display *display) +{ + if (display->parent->rps) + display->parent->rps->ilk_irq_handler(display->drm); +} + bool intel_parent_vgpu_active(struct intel_display *display) { return display->parent->vgpu_active && display->parent->vgpu_active(display->drm); diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index 04320d937777..12cfbea95aa1 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -6,11 +6,17 @@ #include +struct dma_fence; struct intel_display; bool intel_parent_irq_enabled(struct intel_display *display); void intel_parent_irq_synchronize(struct intel_display *display); +bool intel_parent_rps_available(struct intel_display *display); +void intel_parent_rps_boost_if_not_started(struct intel_display *display, struct dma_fence *fence); +void intel_parent_rps_mark_interactive(struct intel_display *display, bool interactive); +void intel_parent_rps_ilk_irq_handler(struct intel_display *display); + bool intel_parent_vgpu_active(struct intel_display *display); bool intel_parent_has_fenced_regions(struct intel_display *display); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index b01c837ab646..c42a1ee42b58 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -6,6 +6,7 @@ #include #include +#include #include "display/intel_display_rps.h" #include "display/vlv_clock.h" @@ -2914,6 +2915,34 @@ bool i915_gpu_turbo_disable(void) } EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); +static void boost_if_not_started(struct dma_fence *fence) +{ + struct i915_request *rq = to_request(fence); + + if (!i915_request_started(rq)) + intel_rps_boost(rq); +} + +static void mark_interactive(struct drm_device *drm, bool interactive) +{ + struct drm_i915_private *i915 = to_i915(drm); + + intel_rps_mark_interactive(&to_gt(i915)->rps, interactive); +} + +static void ilk_irq_handler(struct drm_device *drm) +{ + struct drm_i915_private *i915 = to_i915(drm); + + gen5_rps_irq_handler(&to_gt(i915)->rps); +} + +const struct intel_display_rps_interface i915_display_rps_interface = { + .boost_if_not_started = boost_if_not_started, + .mark_interactive = mark_interactive, + .ilk_irq_handler = ilk_irq_handler, +}; + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftest_rps.c" #include "selftest_slpc.c" diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h index 92fb01f5a452..5dbcebd7d4a5 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.h +++ b/drivers/gpu/drm/i915/gt/intel_rps.h @@ -128,4 +128,6 @@ static inline void intel_rps_clear_timer(struct intel_rps *rps) clear_bit(INTEL_RPS_TIMER, &rps->flags); } +extern const struct intel_display_rps_interface i915_display_rps_interface; + #endif /* INTEL_RPS_H */ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 9ba46850da72..7e1dedabf0ee 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -81,6 +81,7 @@ #include "gt/intel_gt_pm.h" #include "gt/intel_gt_print.h" #include "gt/intel_rc6.h" +#include "gt/intel_rps.h" #include "pxp/intel_pxp.h" #include "pxp/intel_pxp_debugfs.h" @@ -752,6 +753,7 @@ static bool has_fenced_regions(struct drm_device *drm) static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, .irq = &i915_display_irq_interface, + .rps = &i915_display_rps_interface, .vgpu_active = vgpu_active, .has_fenced_regions = has_fenced_regions, }; diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 927d964f2071..0a6a26234fbe 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -6,6 +6,7 @@ #include +struct dma_fence; struct drm_device; struct ref_tracker; @@ -30,6 +31,12 @@ struct intel_display_irq_interface { void (*synchronize)(struct drm_device *drm); }; +struct intel_display_rps_interface { + void (*boost_if_not_started)(struct dma_fence *fence); + void (*mark_interactive)(struct drm_device *drm, bool interactive); + void (*ilk_irq_handler)(struct drm_device *drm); +}; + /** * struct intel_display_parent_interface - services parent driver provides to display * @@ -49,6 +56,9 @@ struct intel_display_parent_interface { /** @irq: IRQ interface */ const struct intel_display_irq_interface *irq; + /** @rpm: RPS interface. Optional. */ + const struct intel_display_rps_interface *rps; + /** @vgpu_active: Is vGPU active? Optional. */ bool (*vgpu_active)(struct drm_device *drm); -- cgit v1.2.3 From 69c9b1861e827a45021a0a10c1d0276a896dd0c2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:15 +0200 Subject: drm/i915/rps: postpone i915 fence check to boost MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the RPS boost code independent of i915 request code by moving the dma_fence_is_i915() check to the RPS boost call. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/2653395523ee04c9ca3216f197f08c25a9f7716d.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_rps.c | 4 ---- drivers/gpu/drm/i915/gt/intel_rps.c | 7 ++++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.c b/drivers/gpu/drm/i915/display/intel_display_rps.c index d639d9152bf5..e77811396474 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.c +++ b/drivers/gpu/drm/i915/display/intel_display_rps.c @@ -9,7 +9,6 @@ #include #include "i915_reg.h" -#include "i915_request.h" #include "intel_display_core.h" #include "intel_display_irq.h" #include "intel_display_rps.h" @@ -54,9 +53,6 @@ void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, if (!intel_parent_rps_available(display)) return; - if (!dma_fence_is_i915(fence)) - return; - if (DISPLAY_VER(display) < 6) return; diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index c42a1ee42b58..d233dc122bd7 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -2917,7 +2917,12 @@ EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); static void boost_if_not_started(struct dma_fence *fence) { - struct i915_request *rq = to_request(fence); + struct i915_request *rq; + + if (!dma_fence_is_i915(fence)) + return; + + rq = to_request(fence); if (!i915_request_started(rq)) intel_rps_boost(rq); -- cgit v1.2.3 From 55fc11ce96e92dbae2aab1d692735f7a9b96fefd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:16 +0200 Subject: drm/i915: add .fence_priority_display to parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add .fence_priority_display() to display parent interface, removing a display dependency on gem/i915_gem_object.h. This allows us to remove the xe compat gem/i915_gem_object.h. v2: Don't mix this with the rps interface (Ville) v3: Rebase Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/c7782862956e3aa59eaeb6dcf80906c1fc063ae1.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_parent.c | 6 ++++++ drivers/gpu/drm/i915/display/intel_parent.h | 2 ++ drivers/gpu/drm/i915/display/intel_plane.c | 5 ++--- drivers/gpu/drm/i915/i915_driver.c | 7 +++++++ .../gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h | 13 ------------- include/drm/intel/display_parent_interface.h | 3 +++ 6 files changed, 20 insertions(+), 16 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 6c131196718e..27c7ef34ce48 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -64,3 +64,9 @@ bool intel_parent_has_fenced_regions(struct intel_display *display) { return display->parent->has_fenced_regions && display->parent->has_fenced_regions(display->drm); } + +void intel_parent_fence_priority_display(struct intel_display *display, struct dma_fence *fence) +{ + if (display->parent->fence_priority_display) + display->parent->fence_priority_display(fence); +} diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index 12cfbea95aa1..a8ca40b57ea9 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -21,4 +21,6 @@ bool intel_parent_vgpu_active(struct intel_display *display); bool intel_parent_has_fenced_regions(struct intel_display *display); +void intel_parent_fence_priority_display(struct intel_display *display, struct dma_fence *fence); + #endif /* __INTEL_PARENT_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c index 5105e3278bc4..a7fec5ba6ac0 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.c +++ b/drivers/gpu/drm/i915/display/intel_plane.c @@ -45,7 +45,6 @@ #include #include -#include "gem/i915_gem_object.h" #include "i9xx_plane_regs.h" #include "intel_cdclk.h" #include "intel_cursor.h" @@ -56,6 +55,7 @@ #include "intel_fb_pin.h" #include "intel_fbdev.h" #include "intel_panic.h" +#include "intel_parent.h" #include "intel_plane.h" #include "intel_psr.h" #include "skl_scaler.h" @@ -1180,8 +1180,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane, goto unpin_fb; if (new_plane_state->uapi.fence) { - i915_gem_fence_wait_priority_display(new_plane_state->uapi.fence); - + intel_parent_fence_priority_display(display, new_plane_state->uapi.fence); intel_display_rps_boost_after_vblank(new_plane_state->hw.crtc, new_plane_state->uapi.fence); } diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 7e1dedabf0ee..7c60b6873934 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -750,12 +750,19 @@ static bool has_fenced_regions(struct drm_device *drm) return intel_gt_support_legacy_fencing(to_gt(to_i915(drm))); } +static void fence_priority_display(struct dma_fence *fence) +{ + if (dma_fence_is_i915(fence)) + i915_gem_fence_wait_priority_display(fence); +} + static const struct intel_display_parent_interface parent = { .rpm = &i915_display_rpm_interface, .irq = &i915_display_irq_interface, .rps = &i915_display_rps_interface, .vgpu_active = vgpu_active, .has_fenced_regions = has_fenced_regions, + .fence_priority_display = fence_priority_display, }; const struct intel_display_parent_interface *i915_driver_parent_interface(void) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h deleted file mode 100644 index 0548b2e0316f..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* Copyright © 2025 Intel Corporation */ - -#ifndef __I915_GEM_OBJECT_H__ -#define __I915_GEM_OBJECT_H__ - -struct dma_fence; - -static inline void i915_gem_fence_wait_priority_display(struct dma_fence *fence) -{ -} - -#endif diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 0a6a26234fbe..4135d1e1a67e 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -64,6 +64,9 @@ struct intel_display_parent_interface { /** @has_fenced_regions: Support legacy fencing? Optional. */ bool (*has_fenced_regions)(struct drm_device *drm); + + /** @fence_priority_display: Set display priority. Optional. */ + void (*fence_priority_display)(struct dma_fence *fence); }; #endif -- cgit v1.2.3 From e4c8fde0bf2004fcd9c9dc8e3bc9bf6545a21a3e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 17 Nov 2025 11:16:17 +0200 Subject: drm/xe/rps: build RPS as part of xe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the conditional compilation in i915 by building intel_display_rps.c as part of the xe module. This doesn't actually enable RPS on xe, because there's no parent interface implementation on xe side, but it's a step in the right direction. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/93df0bb727fce14aa9a542dbd2c0826a0fa0a16f.1763370931.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_rps.h | 21 --------------------- drivers/gpu/drm/xe/Makefile | 1 + 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_rps.h b/drivers/gpu/drm/i915/display/intel_display_rps.h index 183d154f2c7c..96b1fd00ead4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rps.h +++ b/drivers/gpu/drm/i915/display/intel_display_rps.h @@ -13,7 +13,6 @@ struct drm_crtc; struct intel_atomic_state; struct intel_display; -#ifdef I915 void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, struct dma_fence *fence); void intel_display_rps_mark_interactive(struct intel_display *display, @@ -22,25 +21,5 @@ void intel_display_rps_mark_interactive(struct intel_display *display, void ilk_display_rps_enable(struct intel_display *display); void ilk_display_rps_disable(struct intel_display *display); void ilk_display_rps_irq_handler(struct intel_display *display); -#else -static inline void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc, - struct dma_fence *fence) -{ -} -static inline void intel_display_rps_mark_interactive(struct intel_display *display, - struct intel_atomic_state *state, - bool interactive) -{ -} -static inline void ilk_display_rps_enable(struct intel_display *display) -{ -} -static inline void ilk_display_rps_disable(struct intel_display *display) -{ -} -static inline void ilk_display_rps_irq_handler(struct intel_display *display) -{ -} -#endif #endif /* __INTEL_DISPLAY_RPS_H__ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 8967f874280e..8b60fc72fe50 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -255,6 +255,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_display_power_map.o \ i915-display/intel_display_power_well.o \ i915-display/intel_display_rpm.o \ + i915-display/intel_display_rps.o \ i915-display/intel_display_trace.o \ i915-display/intel_display_utils.o \ i915-display/intel_display_wa.o \ -- cgit v1.2.3 From e2b1c3a127665fbca7099c886e4f755785ea1118 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:40 +0200 Subject: drm/i915/edram: extract i915_edram.[ch] for edram detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While edram detection ostensibly belongs with the rest of the dram stuff in soc/intel_dram.c, it's only required by i915 core, not display. Extract it to a separate i915_edram.[ch] file. This allows us to drop the edram_size_mb member from struct xe_device. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/612edb7b70755655fbf193ba8af1c539fb93b698.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_driver.c | 3 ++- drivers/gpu/drm/i915/i915_edram.c | 44 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_edram.h | 11 +++++++++ drivers/gpu/drm/i915/soc/intel_dram.c | 36 ---------------------------- drivers/gpu/drm/i915/soc/intel_dram.h | 1 - drivers/gpu/drm/xe/xe_device_types.h | 6 ----- 7 files changed, 58 insertions(+), 44 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_edram.c create mode 100644 drivers/gpu/drm/i915/i915_edram.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 477278aee831..4e263ab520c1 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -27,6 +27,7 @@ i915-y += \ i915_config.o \ i915_driver.o \ i915_drm_client.o \ + i915_edram.o \ i915_getparam.o \ i915_ioctl.o \ i915_irq.o \ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 7c60b6873934..44a17ffc3058 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -94,6 +94,7 @@ #include "i915_driver.h" #include "i915_drm_client.h" #include "i915_drv.h" +#include "i915_edram.h" #include "i915_file_private.h" #include "i915_getparam.h" #include "i915_hwmon.h" @@ -493,7 +494,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) } /* needs to be done before ggtt probe */ - intel_dram_edram_detect(dev_priv); + i915_edram_detect(dev_priv); ret = i915_set_dma_info(dev_priv); if (ret) diff --git a/drivers/gpu/drm/i915/i915_edram.c b/drivers/gpu/drm/i915/i915_edram.c new file mode 100644 index 000000000000..5818ec396d1e --- /dev/null +++ b/drivers/gpu/drm/i915/i915_edram.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2025 Intel Corporation */ + +#include + +#include "i915_drv.h" +#include "i915_edram.h" +#include "i915_reg.h" + +static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap) +{ + static const u8 ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 }; + static const u8 sets[4] = { 1, 1, 2, 2 }; + + return EDRAM_NUM_BANKS(cap) * + ways[EDRAM_WAYS_IDX(cap)] * + sets[EDRAM_SETS_IDX(cap)]; +} + +void i915_edram_detect(struct drm_i915_private *i915) +{ + u32 edram_cap = 0; + + if (!(IS_HASWELL(i915) || IS_BROADWELL(i915) || GRAPHICS_VER(i915) >= 9)) + return; + + edram_cap = intel_uncore_read_fw(&i915->uncore, HSW_EDRAM_CAP); + + /* NB: We can't write IDICR yet because we don't have gt funcs set up */ + + if (!(edram_cap & EDRAM_ENABLED)) + return; + + /* + * The needed capability bits for size calculation are not there with + * pre gen9 so return 128MB always. + */ + if (GRAPHICS_VER(i915) < 9) + i915->edram_size_mb = 128; + else + i915->edram_size_mb = gen9_edram_size_mb(i915, edram_cap); + + drm_info(&i915->drm, "Found %uMB of eDRAM\n", i915->edram_size_mb); +} diff --git a/drivers/gpu/drm/i915/i915_edram.h b/drivers/gpu/drm/i915/i915_edram.h new file mode 100644 index 000000000000..8319422ace9d --- /dev/null +++ b/drivers/gpu/drm/i915/i915_edram.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __I915_DRAM_H__ +#define __I915_DRAM_H__ + +struct drm_i915_private; + +void i915_edram_detect(struct drm_i915_private *i915); + +#endif /* __I915_DRAM_H__ */ diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 739cfe48f6db..cfe96c3c1b1a 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -861,39 +861,3 @@ const struct dram_info *intel_dram_info(struct drm_device *drm) return i915->dram_info; } - -static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap) -{ - static const u8 ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 }; - static const u8 sets[4] = { 1, 1, 2, 2 }; - - return EDRAM_NUM_BANKS(cap) * - ways[EDRAM_WAYS_IDX(cap)] * - sets[EDRAM_SETS_IDX(cap)]; -} - -void intel_dram_edram_detect(struct drm_i915_private *i915) -{ - u32 edram_cap = 0; - - if (!(IS_HASWELL(i915) || IS_BROADWELL(i915) || GRAPHICS_VER(i915) >= 9)) - return; - - edram_cap = intel_uncore_read_fw(&i915->uncore, HSW_EDRAM_CAP); - - /* NB: We can't write IDICR yet because we don't have gt funcs set up */ - - if (!(edram_cap & EDRAM_ENABLED)) - return; - - /* - * The needed capability bits for size calculation are not there with - * pre gen9 so return 128MB always. - */ - if (GRAPHICS_VER(i915) < 9) - i915->edram_size_mb = 128; - else - i915->edram_size_mb = gen9_edram_size_mb(i915, edram_cap); - - drm_info(&i915->drm, "Found %uMB of eDRAM\n", i915->edram_size_mb); -} diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/soc/intel_dram.h index 8475ee379daa..58aaf2f91afe 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.h +++ b/drivers/gpu/drm/i915/soc/intel_dram.h @@ -35,7 +35,6 @@ struct dram_info { bool has_16gb_dimms; }; -void intel_dram_edram_detect(struct drm_i915_private *i915); int intel_dram_detect(struct drm_i915_private *i915); unsigned int intel_fsb_freq(struct drm_i915_private *i915); unsigned int intel_mem_freq(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index e772851c08e9..430ac085c22b 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -639,12 +639,6 @@ struct xe_device { */ const struct dram_info *dram_info; - /* - * edram size in MB. - * Cannot be determined by PCIID. You must always read a register. - */ - u32 edram_size_mb; - struct intel_uncore { spinlock_t lock; } uncore; -- cgit v1.2.3 From 2d74a09360a920d87a4e9538797068a0f9e5e2e1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:41 +0200 Subject: drm/i915: split out i915_freq.[ch] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The i915 core only needs three rather specific functions from soc/intel_dram.[ch]: i9xx_fsb_freq(), ilk_fsb_freq(), and ilk_mem_freq(). Add new i915_freq.[ch] and duplicate those functions for i915 to reduce the dependency on soc/ code. Wile duplication in general is bad, here it's a tradeoff to simplify the i915, xe and display interactions. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/7bac1b194afdc20cd45e625a0a32fcbcd0b1136e.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c | 4 +- drivers/gpu/drm/i915/gt/intel_rps.c | 6 +- drivers/gpu/drm/i915/i915_freq.c | 111 +++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_freq.h | 13 +++ 5 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_freq.c create mode 100644 drivers/gpu/drm/i915/i915_freq.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 4e263ab520c1..8dc75174fcbc 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -28,6 +28,7 @@ i915-y += \ i915_driver.o \ i915_drm_client.o \ i915_edram.o \ + i915_freq.o \ i915_getparam.o \ i915_ioctl.o \ i915_irq.o \ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c index c90b35881a26..aecd120972ea 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c @@ -4,12 +4,12 @@ */ #include "i915_drv.h" +#include "i915_freq.h" #include "i915_reg.h" #include "intel_gt.h" #include "intel_gt_clock_utils.h" #include "intel_gt_print.h" #include "intel_gt_regs.h" -#include "soc/intel_dram.h" static u32 read_reference_ts_freq(struct intel_uncore *uncore) { @@ -148,7 +148,7 @@ static u32 gen4_read_clock_frequency(struct intel_uncore *uncore) * * Testing on actual hardware has shown there is no /16. */ - return DIV_ROUND_CLOSEST(intel_fsb_freq(uncore->i915), 4) * 1000; + return DIV_ROUND_CLOSEST(i9xx_fsb_freq(uncore->i915), 4) * 1000; } static u32 read_clock_frequency(struct intel_uncore *uncore) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index d233dc122bd7..90b7eee78f1f 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -10,9 +10,9 @@ #include "display/intel_display_rps.h" #include "display/vlv_clock.h" -#include "soc/intel_dram.h" #include "i915_drv.h" +#include "i915_freq.h" #include "i915_irq.h" #include "i915_reg.h" #include "i915_wait_util.h" @@ -285,8 +285,8 @@ static void gen5_rps_init(struct intel_rps *rps) u32 rgvmodectl; int c_m, i; - fsb_freq = intel_fsb_freq(i915); - mem_freq = intel_mem_freq(i915); + fsb_freq = ilk_fsb_freq(i915); + mem_freq = ilk_mem_freq(i915); if (fsb_freq <= 3200000) c_m = 0; diff --git a/drivers/gpu/drm/i915/i915_freq.c b/drivers/gpu/drm/i915/i915_freq.c new file mode 100644 index 000000000000..9bdaea34aef9 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_freq.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2025 Intel Corporation */ + +#include + +#include "i915_drv.h" +#include "i915_freq.h" +#include "intel_mchbar_regs.h" + +unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) +{ + u32 fsb; + + /* + * Note that this only reads the state of the FSB + * straps, not the actual FSB frequency. Some BIOSen + * let you configure each independently. Ideally we'd + * read out the actual FSB frequency but sadly we + * don't know which registers have that information, + * and all the relevant docs have gone to bit heaven :( + */ + fsb = intel_uncore_read(&i915->uncore, CLKCFG) & CLKCFG_FSB_MASK; + + if (IS_PINEVIEW(i915) || IS_MOBILE(i915)) { + switch (fsb) { + case CLKCFG_FSB_400: + return 400000; + case CLKCFG_FSB_533: + return 533333; + case CLKCFG_FSB_667: + return 666667; + case CLKCFG_FSB_800: + return 800000; + case CLKCFG_FSB_1067: + return 1066667; + case CLKCFG_FSB_1333: + return 1333333; + default: + MISSING_CASE(fsb); + return 1333333; + } + } else { + switch (fsb) { + case CLKCFG_FSB_400_ALT: + return 400000; + case CLKCFG_FSB_533: + return 533333; + case CLKCFG_FSB_667: + return 666667; + case CLKCFG_FSB_800: + return 800000; + case CLKCFG_FSB_1067_ALT: + return 1066667; + case CLKCFG_FSB_1333_ALT: + return 1333333; + case CLKCFG_FSB_1600_ALT: + return 1600000; + default: + MISSING_CASE(fsb); + return 1333333; + } + } +} + +unsigned int ilk_fsb_freq(struct drm_i915_private *i915) +{ + u16 fsb; + + fsb = intel_uncore_read16(&i915->uncore, CSIPLL0) & 0x3ff; + + switch (fsb) { + case 0x00c: + return 3200000; + case 0x00e: + return 3733333; + case 0x010: + return 4266667; + case 0x012: + return 4800000; + case 0x014: + return 5333333; + case 0x016: + return 5866667; + case 0x018: + return 6400000; + default: + drm_dbg(&i915->drm, "unknown fsb frequency 0x%04x\n", fsb); + return 0; + } +} + +unsigned int ilk_mem_freq(struct drm_i915_private *i915) +{ + u16 ddrpll; + + ddrpll = intel_uncore_read16(&i915->uncore, DDRMPLL1); + switch (ddrpll & 0xff) { + case 0xc: + return 800000; + case 0x10: + return 1066667; + case 0x14: + return 1333333; + case 0x18: + return 1600000; + default: + drm_dbg(&i915->drm, "unknown memory frequency 0x%02x\n", + ddrpll & 0xff); + return 0; + } +} diff --git a/drivers/gpu/drm/i915/i915_freq.h b/drivers/gpu/drm/i915/i915_freq.h new file mode 100644 index 000000000000..53b0ecb95440 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_freq.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __I915_FREQ_H__ +#define __I915_FREQ_H__ + +struct drm_i915_private; + +unsigned int i9xx_fsb_freq(struct drm_i915_private *i915); +unsigned int ilk_fsb_freq(struct drm_i915_private *i915); +unsigned int ilk_mem_freq(struct drm_i915_private *i915); + +#endif /* __I915_FREQ_H__ */ -- cgit v1.2.3 From ed46f724b725e7692cee18f26901c6dbde33dff1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:42 +0200 Subject: drm/i915: move intel_dram.[ch] from soc/ to display/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The remaining users of intel_dram.[ch] are all in display. Move them under display. This allows us to remove the compat soc/intel_dram.h from xe. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/4c0fbdab989a70d287536a7eafb002dc836ced12.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 2 +- drivers/gpu/drm/i915/display/i9xx_wm.c | 3 +- drivers/gpu/drm/i915/display/intel_bw.c | 3 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 3 +- drivers/gpu/drm/i915/display/intel_display_power.c | 3 +- drivers/gpu/drm/i915/display/intel_dram.c | 862 ++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dram.h | 44 ++ drivers/gpu/drm/i915/display/skl_watermark.c | 2 +- drivers/gpu/drm/i915/i915_driver.c | 2 +- drivers/gpu/drm/i915/soc/intel_dram.c | 863 --------------------- drivers/gpu/drm/i915/soc/intel_dram.h | 44 -- drivers/gpu/drm/xe/Makefile | 2 +- .../drm/xe/compat-i915-headers/soc/intel_dram.h | 6 - drivers/gpu/drm/xe/display/xe_display.c | 2 +- 14 files changed, 915 insertions(+), 926 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_dram.c create mode 100644 drivers/gpu/drm/i915/display/intel_dram.h delete mode 100644 drivers/gpu/drm/i915/soc/intel_dram.c delete mode 100644 drivers/gpu/drm/i915/soc/intel_dram.h delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 8dc75174fcbc..57d150765784 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -58,7 +58,6 @@ i915-y += \ # core peripheral code i915-y += \ - soc/intel_dram.o \ soc/intel_gmch.o \ soc/intel_rom.o @@ -268,6 +267,7 @@ i915-y += \ display/intel_dpll_mgr.o \ display/intel_dpt.o \ display/intel_dpt_common.o \ + display/intel_dram.o \ display/intel_drrs.o \ display/intel_dsb.o \ display/intel_dsb_buffer.o \ diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 01f3803fa09f..27e2d73bc505 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -7,8 +7,6 @@ #include -#include "soc/intel_dram.h" - #include "i915_drv.h" #include "i915_reg.h" #include "i9xx_wm.h" @@ -19,6 +17,7 @@ #include "intel_display.h" #include "intel_display_regs.h" #include "intel_display_trace.h" +#include "intel_dram.h" #include "intel_fb.h" #include "intel_mchbar_regs.h" #include "intel_wm.h" diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 1f6461be50ef..957c90e62569 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -6,8 +6,6 @@ #include #include -#include "soc/intel_dram.h" - #include "i915_drv.h" #include "i915_reg.h" #include "intel_bw.h" @@ -16,6 +14,7 @@ #include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_display_utils.h" +#include "intel_dram.h" #include "intel_mchbar_regs.h" #include "intel_pcode.h" #include "intel_uncore.h" diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 37801c744b05..531819391c8c 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -28,8 +28,6 @@ #include #include -#include "soc/intel_dram.h" - #include "hsw_ips.h" #include "i915_drv.h" #include "i915_reg.h" @@ -42,6 +40,7 @@ #include "intel_display_regs.h" #include "intel_display_types.h" #include "intel_display_utils.h" +#include "intel_dram.h" #include "intel_mchbar_regs.h" #include "intel_pci_config.h" #include "intel_pcode.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index a383ef23391d..9c5f0277d8c2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -8,8 +8,6 @@ #include -#include "soc/intel_dram.h" - #include "i915_drv.h" #include "i915_reg.h" #include "intel_backlight_regs.h" @@ -25,6 +23,7 @@ #include "intel_display_types.h" #include "intel_display_utils.h" #include "intel_dmc.h" +#include "intel_dram.h" #include "intel_mchbar_regs.h" #include "intel_parent.h" #include "intel_pch_refclk.h" diff --git a/drivers/gpu/drm/i915/display/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c new file mode 100644 index 000000000000..7142772f2a6e --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dram.c @@ -0,0 +1,862 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2020 Intel Corporation + */ + +#include + +#include +#include + +#include "i915_drv.h" +#include "i915_reg.h" +#include "intel_display_core.h" +#include "intel_display_utils.h" +#include "intel_dram.h" +#include "intel_mchbar_regs.h" +#include "intel_pcode.h" +#include "intel_uncore.h" +#include "vlv_iosf_sb.h" + +struct dram_dimm_info { + u16 size; + u8 width, ranks; +}; + +struct dram_channel_info { + struct dram_dimm_info dimm_l, dimm_s; + u8 ranks; + bool is_16gb_dimm; +}; + +#define DRAM_TYPE_STR(type) [INTEL_DRAM_ ## type] = #type + +const char *intel_dram_type_str(enum intel_dram_type type) +{ + static const char * const str[] = { + DRAM_TYPE_STR(UNKNOWN), + DRAM_TYPE_STR(DDR2), + DRAM_TYPE_STR(DDR3), + DRAM_TYPE_STR(DDR4), + DRAM_TYPE_STR(LPDDR3), + DRAM_TYPE_STR(LPDDR4), + DRAM_TYPE_STR(DDR5), + DRAM_TYPE_STR(LPDDR5), + DRAM_TYPE_STR(GDDR), + DRAM_TYPE_STR(GDDR_ECC), + }; + + BUILD_BUG_ON(ARRAY_SIZE(str) != __INTEL_DRAM_TYPE_MAX); + + if (type >= ARRAY_SIZE(str)) + type = INTEL_DRAM_UNKNOWN; + + return str[type]; +} + +#undef DRAM_TYPE_STR + +static enum intel_dram_type pnv_dram_type(struct drm_i915_private *i915) +{ + return intel_uncore_read(&i915->uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ? + INTEL_DRAM_DDR3 : INTEL_DRAM_DDR2; +} + +static unsigned int pnv_mem_freq(struct drm_i915_private *dev_priv) +{ + u32 tmp; + + tmp = intel_uncore_read(&dev_priv->uncore, CLKCFG); + + switch (tmp & CLKCFG_MEM_MASK) { + case CLKCFG_MEM_533: + return 533333; + case CLKCFG_MEM_667: + return 666667; + case CLKCFG_MEM_800: + return 800000; + } + + return 0; +} + +static unsigned int ilk_mem_freq(struct drm_i915_private *dev_priv) +{ + u16 ddrpll; + + ddrpll = intel_uncore_read16(&dev_priv->uncore, DDRMPLL1); + switch (ddrpll & 0xff) { + case 0xc: + return 800000; + case 0x10: + return 1066667; + case 0x14: + return 1333333; + case 0x18: + return 1600000; + default: + drm_dbg(&dev_priv->drm, "unknown memory frequency 0x%02x\n", + ddrpll & 0xff); + return 0; + } +} + +static unsigned int chv_mem_freq(struct drm_i915_private *i915) +{ + u32 val; + + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_CCK)); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_CCK)); + + switch ((val >> 2) & 0x7) { + case 3: + return 2000000; + default: + return 1600000; + } +} + +static unsigned int vlv_mem_freq(struct drm_i915_private *i915) +{ + u32 val; + + vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + + switch ((val >> 6) & 3) { + case 0: + case 1: + return 800000; + case 2: + return 1066667; + case 3: + return 1333333; + } + + return 0; +} + +unsigned int intel_mem_freq(struct drm_i915_private *i915) +{ + if (IS_PINEVIEW(i915)) + return pnv_mem_freq(i915); + else if (GRAPHICS_VER(i915) == 5) + return ilk_mem_freq(i915); + else if (IS_CHERRYVIEW(i915)) + return chv_mem_freq(i915); + else if (IS_VALLEYVIEW(i915)) + return vlv_mem_freq(i915); + else + return 0; +} + +static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) +{ + u32 fsb; + + /* + * Note that this only reads the state of the FSB + * straps, not the actual FSB frequency. Some BIOSen + * let you configure each independently. Ideally we'd + * read out the actual FSB frequency but sadly we + * don't know which registers have that information, + * and all the relevant docs have gone to bit heaven :( + */ + fsb = intel_uncore_read(&i915->uncore, CLKCFG) & CLKCFG_FSB_MASK; + + if (IS_PINEVIEW(i915) || IS_MOBILE(i915)) { + switch (fsb) { + case CLKCFG_FSB_400: + return 400000; + case CLKCFG_FSB_533: + return 533333; + case CLKCFG_FSB_667: + return 666667; + case CLKCFG_FSB_800: + return 800000; + case CLKCFG_FSB_1067: + return 1066667; + case CLKCFG_FSB_1333: + return 1333333; + default: + MISSING_CASE(fsb); + return 1333333; + } + } else { + switch (fsb) { + case CLKCFG_FSB_400_ALT: + return 400000; + case CLKCFG_FSB_533: + return 533333; + case CLKCFG_FSB_667: + return 666667; + case CLKCFG_FSB_800: + return 800000; + case CLKCFG_FSB_1067_ALT: + return 1066667; + case CLKCFG_FSB_1333_ALT: + return 1333333; + case CLKCFG_FSB_1600_ALT: + return 1600000; + default: + MISSING_CASE(fsb); + return 1333333; + } + } +} + +static unsigned int ilk_fsb_freq(struct drm_i915_private *dev_priv) +{ + u16 fsb; + + fsb = intel_uncore_read16(&dev_priv->uncore, CSIPLL0) & 0x3ff; + + switch (fsb) { + case 0x00c: + return 3200000; + case 0x00e: + return 3733333; + case 0x010: + return 4266667; + case 0x012: + return 4800000; + case 0x014: + return 5333333; + case 0x016: + return 5866667; + case 0x018: + return 6400000; + default: + drm_dbg(&dev_priv->drm, "unknown fsb frequency 0x%04x\n", fsb); + return 0; + } +} + +unsigned int intel_fsb_freq(struct drm_i915_private *i915) +{ + if (GRAPHICS_VER(i915) == 5) + return ilk_fsb_freq(i915); + else if (GRAPHICS_VER(i915) == 3 || GRAPHICS_VER(i915) == 4) + return i9xx_fsb_freq(i915); + else + return 0; +} + +static int i915_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +{ + dram_info->fsb_freq = intel_fsb_freq(i915); + if (dram_info->fsb_freq) + drm_dbg(&i915->drm, "FSB frequency: %d kHz\n", dram_info->fsb_freq); + + dram_info->mem_freq = intel_mem_freq(i915); + if (dram_info->mem_freq) + drm_dbg(&i915->drm, "DDR speed: %d kHz\n", dram_info->mem_freq); + + if (IS_PINEVIEW(i915)) + dram_info->type = pnv_dram_type(i915); + + return 0; +} + +static int intel_dimm_num_devices(const struct dram_dimm_info *dimm) +{ + return dimm->ranks * 64 / (dimm->width ?: 1); +} + +/* Returns total Gb for the whole DIMM */ +static int skl_get_dimm_s_size(u32 val) +{ + return REG_FIELD_GET(SKL_DIMM_S_SIZE_MASK, val) * 8; +} + +static int skl_get_dimm_l_size(u32 val) +{ + return REG_FIELD_GET(SKL_DIMM_L_SIZE_MASK, val) * 8; +} + +static int skl_get_dimm_s_width(u32 val) +{ + if (skl_get_dimm_s_size(val) == 0) + return 0; + + switch (val & SKL_DIMM_S_WIDTH_MASK) { + case SKL_DIMM_S_WIDTH_X8: + case SKL_DIMM_S_WIDTH_X16: + case SKL_DIMM_S_WIDTH_X32: + return 8 << REG_FIELD_GET(SKL_DIMM_S_WIDTH_MASK, val); + default: + MISSING_CASE(val); + return 0; + } +} + +static int skl_get_dimm_l_width(u32 val) +{ + if (skl_get_dimm_l_size(val) == 0) + return 0; + + switch (val & SKL_DIMM_L_WIDTH_MASK) { + case SKL_DIMM_L_WIDTH_X8: + case SKL_DIMM_L_WIDTH_X16: + case SKL_DIMM_L_WIDTH_X32: + return 8 << REG_FIELD_GET(SKL_DIMM_L_WIDTH_MASK, val); + default: + MISSING_CASE(val); + return 0; + } +} + +static int skl_get_dimm_s_ranks(u32 val) +{ + if (skl_get_dimm_s_size(val) == 0) + return 0; + + return REG_FIELD_GET(SKL_DIMM_S_RANK_MASK, val) + 1; +} + +static int skl_get_dimm_l_ranks(u32 val) +{ + if (skl_get_dimm_l_size(val) == 0) + return 0; + + return REG_FIELD_GET(SKL_DIMM_L_RANK_MASK, val) + 1; +} + +/* Returns total Gb for the whole DIMM */ +static int icl_get_dimm_s_size(u32 val) +{ + return REG_FIELD_GET(ICL_DIMM_S_SIZE_MASK, val) * 8 / 2; +} + +static int icl_get_dimm_l_size(u32 val) +{ + return REG_FIELD_GET(ICL_DIMM_L_SIZE_MASK, val) * 8 / 2; +} + +static int icl_get_dimm_s_width(u32 val) +{ + if (icl_get_dimm_s_size(val) == 0) + return 0; + + switch (val & ICL_DIMM_S_WIDTH_MASK) { + case ICL_DIMM_S_WIDTH_X8: + case ICL_DIMM_S_WIDTH_X16: + case ICL_DIMM_S_WIDTH_X32: + return 8 << REG_FIELD_GET(ICL_DIMM_S_WIDTH_MASK, val); + default: + MISSING_CASE(val); + return 0; + } +} + +static int icl_get_dimm_l_width(u32 val) +{ + if (icl_get_dimm_l_size(val) == 0) + return 0; + + switch (val & ICL_DIMM_L_WIDTH_MASK) { + case ICL_DIMM_L_WIDTH_X8: + case ICL_DIMM_L_WIDTH_X16: + case ICL_DIMM_L_WIDTH_X32: + return 8 << REG_FIELD_GET(ICL_DIMM_L_WIDTH_MASK, val); + default: + MISSING_CASE(val); + return 0; + } +} + +static int icl_get_dimm_s_ranks(u32 val) +{ + if (icl_get_dimm_s_size(val) == 0) + return 0; + + return REG_FIELD_GET(ICL_DIMM_S_RANK_MASK, val) + 1; +} + +static int icl_get_dimm_l_ranks(u32 val) +{ + if (icl_get_dimm_l_size(val) == 0) + return 0; + + return REG_FIELD_GET(ICL_DIMM_L_RANK_MASK, val) + 1; +} + +static bool +skl_is_16gb_dimm(const struct dram_dimm_info *dimm) +{ + /* Convert total Gb to Gb per DRAM device */ + return dimm->size / (intel_dimm_num_devices(dimm) ?: 1) >= 16; +} + +static void +skl_dram_print_dimm_info(struct drm_i915_private *i915, + struct dram_dimm_info *dimm, + int channel, char dimm_name) +{ + drm_dbg_kms(&i915->drm, + "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb+ DIMMs: %s\n", + channel, dimm_name, dimm->size, dimm->width, dimm->ranks, + str_yes_no(skl_is_16gb_dimm(dimm))); +} + +static void +skl_dram_get_dimm_l_info(struct drm_i915_private *i915, + struct dram_dimm_info *dimm, + int channel, u32 val) +{ + if (GRAPHICS_VER(i915) >= 11) { + dimm->size = icl_get_dimm_l_size(val); + dimm->width = icl_get_dimm_l_width(val); + dimm->ranks = icl_get_dimm_l_ranks(val); + } else { + dimm->size = skl_get_dimm_l_size(val); + dimm->width = skl_get_dimm_l_width(val); + dimm->ranks = skl_get_dimm_l_ranks(val); + } + + skl_dram_print_dimm_info(i915, dimm, channel, 'L'); +} + +static void +skl_dram_get_dimm_s_info(struct drm_i915_private *i915, + struct dram_dimm_info *dimm, + int channel, u32 val) +{ + if (GRAPHICS_VER(i915) >= 11) { + dimm->size = icl_get_dimm_s_size(val); + dimm->width = icl_get_dimm_s_width(val); + dimm->ranks = icl_get_dimm_s_ranks(val); + } else { + dimm->size = skl_get_dimm_s_size(val); + dimm->width = skl_get_dimm_s_width(val); + dimm->ranks = skl_get_dimm_s_ranks(val); + } + + skl_dram_print_dimm_info(i915, dimm, channel, 'S'); +} + +static int +skl_dram_get_channel_info(struct drm_i915_private *i915, + struct dram_channel_info *ch, + int channel, u32 val) +{ + skl_dram_get_dimm_l_info(i915, &ch->dimm_l, channel, val); + skl_dram_get_dimm_s_info(i915, &ch->dimm_s, channel, val); + + if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) { + drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel); + return -EINVAL; + } + + if (ch->dimm_l.ranks == 2 || ch->dimm_s.ranks == 2) + ch->ranks = 2; + else if (ch->dimm_l.ranks == 1 && ch->dimm_s.ranks == 1) + ch->ranks = 2; + else + ch->ranks = 1; + + ch->is_16gb_dimm = skl_is_16gb_dimm(&ch->dimm_l) || + skl_is_16gb_dimm(&ch->dimm_s); + + drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb+ DIMMs: %s\n", + channel, ch->ranks, str_yes_no(ch->is_16gb_dimm)); + + return 0; +} + +static bool +intel_is_dram_symmetric(const struct dram_channel_info *ch0, + const struct dram_channel_info *ch1) +{ + return !memcmp(ch0, ch1, sizeof(*ch0)) && + (ch0->dimm_s.size == 0 || + !memcmp(&ch0->dimm_l, &ch0->dimm_s, sizeof(ch0->dimm_l))); +} + +static int +skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram_info) +{ + struct dram_channel_info ch0 = {}, ch1 = {}; + u32 val; + int ret; + + /* Assume 16Gb+ DIMMs are present until proven otherwise */ + dram_info->has_16gb_dimms = true; + + val = intel_uncore_read(&i915->uncore, + SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(i915, &ch0, 0, val); + if (ret == 0) + dram_info->num_channels++; + + val = intel_uncore_read(&i915->uncore, + SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(i915, &ch1, 1, val); + if (ret == 0) + dram_info->num_channels++; + + if (dram_info->num_channels == 0) { + drm_info(&i915->drm, "Number of memory channels is zero\n"); + return -EINVAL; + } + + if (ch0.ranks == 0 && ch1.ranks == 0) { + drm_info(&i915->drm, "couldn't get memory rank information\n"); + return -EINVAL; + } + + dram_info->has_16gb_dimms = ch0.is_16gb_dimm || ch1.is_16gb_dimm; + + dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1); + + drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n", + str_yes_no(dram_info->symmetric_memory)); + + drm_dbg_kms(&i915->drm, "16Gb+ DIMMs: %s\n", + str_yes_no(dram_info->has_16gb_dimms)); + + return 0; +} + +static enum intel_dram_type +skl_get_dram_type(struct drm_i915_private *i915) +{ + u32 val; + + val = intel_uncore_read(&i915->uncore, + SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN); + + switch (val & SKL_DRAM_DDR_TYPE_MASK) { + case SKL_DRAM_DDR_TYPE_DDR3: + return INTEL_DRAM_DDR3; + case SKL_DRAM_DDR_TYPE_DDR4: + return INTEL_DRAM_DDR4; + case SKL_DRAM_DDR_TYPE_LPDDR3: + return INTEL_DRAM_LPDDR3; + case SKL_DRAM_DDR_TYPE_LPDDR4: + return INTEL_DRAM_LPDDR4; + default: + MISSING_CASE(val); + return INTEL_DRAM_UNKNOWN; + } +} + +static int +skl_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +{ + int ret; + + dram_info->type = skl_get_dram_type(i915); + + ret = skl_dram_get_channels_info(i915, dram_info); + if (ret) + return ret; + + return 0; +} + +/* Returns Gb per DRAM device */ +static int bxt_get_dimm_size(u32 val) +{ + switch (val & BXT_DRAM_SIZE_MASK) { + case BXT_DRAM_SIZE_4GBIT: + return 4; + case BXT_DRAM_SIZE_6GBIT: + return 6; + case BXT_DRAM_SIZE_8GBIT: + return 8; + case BXT_DRAM_SIZE_12GBIT: + return 12; + case BXT_DRAM_SIZE_16GBIT: + return 16; + default: + MISSING_CASE(val); + return 0; + } +} + +static int bxt_get_dimm_width(u32 val) +{ + if (!bxt_get_dimm_size(val)) + return 0; + + val = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT; + + return 8 << val; +} + +static int bxt_get_dimm_ranks(u32 val) +{ + if (!bxt_get_dimm_size(val)) + return 0; + + switch (val & BXT_DRAM_RANK_MASK) { + case BXT_DRAM_RANK_SINGLE: + return 1; + case BXT_DRAM_RANK_DUAL: + return 2; + default: + MISSING_CASE(val); + return 0; + } +} + +static enum intel_dram_type bxt_get_dimm_type(u32 val) +{ + if (!bxt_get_dimm_size(val)) + return INTEL_DRAM_UNKNOWN; + + switch (val & BXT_DRAM_TYPE_MASK) { + case BXT_DRAM_TYPE_DDR3: + return INTEL_DRAM_DDR3; + case BXT_DRAM_TYPE_LPDDR3: + return INTEL_DRAM_LPDDR3; + case BXT_DRAM_TYPE_DDR4: + return INTEL_DRAM_DDR4; + case BXT_DRAM_TYPE_LPDDR4: + return INTEL_DRAM_LPDDR4; + default: + MISSING_CASE(val); + return INTEL_DRAM_UNKNOWN; + } +} + +static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val) +{ + dimm->width = bxt_get_dimm_width(val); + dimm->ranks = bxt_get_dimm_ranks(val); + + /* + * Size in register is Gb per DRAM device. Convert to total + * Gb to match the way we report this for non-LP platforms. + */ + dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm); +} + +static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +{ + u32 val; + u8 valid_ranks = 0; + int i; + + /* + * Now read each DUNIT8/9/10/11 to check the rank of each dimms. + */ + for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) { + struct dram_dimm_info dimm; + enum intel_dram_type type; + + val = intel_uncore_read(&i915->uncore, BXT_D_CR_DRP0_DUNIT(i)); + if (val == 0xFFFFFFFF) + continue; + + dram_info->num_channels++; + + bxt_get_dimm_info(&dimm, val); + type = bxt_get_dimm_type(val); + + drm_WARN_ON(&i915->drm, type != INTEL_DRAM_UNKNOWN && + dram_info->type != INTEL_DRAM_UNKNOWN && + dram_info->type != type); + + drm_dbg_kms(&i915->drm, + "CH%u DIMM size: %u Gb, width: X%u, ranks: %u\n", + i - BXT_D_CR_DRP0_DUNIT_START, + dimm.size, dimm.width, dimm.ranks); + + if (valid_ranks == 0) + valid_ranks = dimm.ranks; + + if (type != INTEL_DRAM_UNKNOWN) + dram_info->type = type; + } + + if (dram_info->type == INTEL_DRAM_UNKNOWN || valid_ranks == 0) { + drm_info(&i915->drm, "couldn't get memory information\n"); + return -EINVAL; + } + + return 0; +} + +static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv, + struct dram_info *dram_info) +{ + u32 val = 0; + int ret; + + ret = intel_pcode_read(&dev_priv->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO | + ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL); + if (ret) + return ret; + + if (GRAPHICS_VER(dev_priv) == 12) { + switch (val & 0xf) { + case 0: + dram_info->type = INTEL_DRAM_DDR4; + break; + case 1: + dram_info->type = INTEL_DRAM_DDR5; + break; + case 2: + dram_info->type = INTEL_DRAM_LPDDR5; + break; + case 3: + dram_info->type = INTEL_DRAM_LPDDR4; + break; + case 4: + dram_info->type = INTEL_DRAM_DDR3; + break; + case 5: + dram_info->type = INTEL_DRAM_LPDDR3; + break; + default: + MISSING_CASE(val & 0xf); + return -EINVAL; + } + } else { + switch (val & 0xf) { + case 0: + dram_info->type = INTEL_DRAM_DDR4; + break; + case 1: + dram_info->type = INTEL_DRAM_DDR3; + break; + case 2: + dram_info->type = INTEL_DRAM_LPDDR3; + break; + case 3: + dram_info->type = INTEL_DRAM_LPDDR4; + break; + default: + MISSING_CASE(val & 0xf); + return -EINVAL; + } + } + + dram_info->num_channels = (val & 0xf0) >> 4; + dram_info->num_qgv_points = (val & 0xf00) >> 8; + dram_info->num_psf_gv_points = (val & 0x3000) >> 12; + + return 0; +} + +static int gen11_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +{ + int ret; + + ret = skl_dram_get_channels_info(i915, dram_info); + if (ret) + return ret; + + return icl_pcode_read_mem_global_info(i915, dram_info); +} + +static int gen12_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +{ + return icl_pcode_read_mem_global_info(i915, dram_info); +} + +static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +{ + struct intel_display *display = i915->display; + u32 val = intel_uncore_read(&i915->uncore, MTL_MEM_SS_INFO_GLOBAL); + + switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) { + case 0: + dram_info->type = INTEL_DRAM_DDR4; + break; + case 1: + dram_info->type = INTEL_DRAM_DDR5; + break; + case 2: + dram_info->type = INTEL_DRAM_LPDDR5; + break; + case 3: + dram_info->type = INTEL_DRAM_LPDDR4; + break; + case 4: + dram_info->type = INTEL_DRAM_DDR3; + break; + case 5: + dram_info->type = INTEL_DRAM_LPDDR3; + break; + case 8: + drm_WARN_ON(&i915->drm, !IS_DGFX(i915)); + dram_info->type = INTEL_DRAM_GDDR; + break; + case 9: + drm_WARN_ON(&i915->drm, !IS_DGFX(i915)); + dram_info->type = INTEL_DRAM_GDDR_ECC; + break; + default: + MISSING_CASE(val); + return -EINVAL; + } + + dram_info->num_channels = REG_FIELD_GET(MTL_N_OF_POPULATED_CH_MASK, val); + dram_info->num_qgv_points = REG_FIELD_GET(MTL_N_OF_ENABLED_QGV_POINTS_MASK, val); + /* PSF GV points not supported in D14+ */ + + if (DISPLAY_VER(display) >= 35) + dram_info->ecc_impacting_de_bw = REG_FIELD_GET(XE3P_ECC_IMPACTING_DE, val); + + return 0; +} + +int intel_dram_detect(struct drm_i915_private *i915) +{ + struct intel_display *display = i915->display; + struct dram_info *dram_info; + int ret; + + if (IS_DG2(i915) || !intel_display_device_present(display)) + return 0; + + dram_info = drmm_kzalloc(&i915->drm, sizeof(*dram_info), GFP_KERNEL); + if (!dram_info) + return -ENOMEM; + + i915->dram_info = dram_info; + + if (DISPLAY_VER(display) >= 14) + ret = xelpdp_get_dram_info(i915, dram_info); + else if (GRAPHICS_VER(i915) >= 12) + ret = gen12_get_dram_info(i915, dram_info); + else if (GRAPHICS_VER(i915) >= 11) + ret = gen11_get_dram_info(i915, dram_info); + else if (IS_BROXTON(i915) || IS_GEMINILAKE(i915)) + ret = bxt_get_dram_info(i915, dram_info); + else if (GRAPHICS_VER(i915) >= 9) + ret = skl_get_dram_info(i915, dram_info); + else + ret = i915_get_dram_info(i915, dram_info); + + drm_dbg_kms(&i915->drm, "DRAM type: %s\n", + intel_dram_type_str(dram_info->type)); + + drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels); + + drm_dbg_kms(&i915->drm, "Num QGV points %u\n", dram_info->num_qgv_points); + drm_dbg_kms(&i915->drm, "Num PSF GV points %u\n", dram_info->num_psf_gv_points); + + /* TODO: Do we want to abort probe on dram detection failures? */ + if (ret) + return 0; + + return 0; +} + +/* + * Returns NULL for platforms that don't have dram info. Avoid overzealous NULL + * checks, and prefer not dereferencing on platforms that shouldn't look at dram + * info, to catch accidental and incorrect dram info checks. + */ +const struct dram_info *intel_dram_info(struct drm_device *drm) +{ + struct drm_i915_private *i915 = to_i915(drm); + + return i915->dram_info; +} diff --git a/drivers/gpu/drm/i915/display/intel_dram.h b/drivers/gpu/drm/i915/display/intel_dram.h new file mode 100644 index 000000000000..58aaf2f91afe --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dram.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2020 Intel Corporation + */ + +#ifndef __INTEL_DRAM_H__ +#define __INTEL_DRAM_H__ + +#include + +struct drm_i915_private; +struct drm_device; + +struct dram_info { + enum intel_dram_type { + INTEL_DRAM_UNKNOWN, + INTEL_DRAM_DDR2, + INTEL_DRAM_DDR3, + INTEL_DRAM_DDR4, + INTEL_DRAM_LPDDR3, + INTEL_DRAM_LPDDR4, + INTEL_DRAM_DDR5, + INTEL_DRAM_LPDDR5, + INTEL_DRAM_GDDR, + INTEL_DRAM_GDDR_ECC, + __INTEL_DRAM_TYPE_MAX, + } type; + unsigned int fsb_freq; + unsigned int mem_freq; + u8 num_channels; + u8 num_qgv_points; + u8 num_psf_gv_points; + bool ecc_impacting_de_bw; /* Only valid from Xe3p_LPD onward. */ + bool symmetric_memory; + bool has_16gb_dimms; +}; + +int intel_dram_detect(struct drm_i915_private *i915); +unsigned int intel_fsb_freq(struct drm_i915_private *i915); +unsigned int intel_mem_freq(struct drm_i915_private *i915); +const struct dram_info *intel_dram_info(struct drm_device *drm); +const char *intel_dram_type_str(enum intel_dram_type type); + +#endif /* __INTEL_DRAM_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 54e9e0be019d..a33e0cec8cba 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -8,7 +8,6 @@ #include #include -#include "soc/intel_dram.h" #include "i915_reg.h" #include "i9xx_wm.h" #include "intel_atomic.h" @@ -23,6 +22,7 @@ #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_display_utils.h" +#include "intel_dram.h" #include "intel_fb.h" #include "intel_fixed.h" #include "intel_flipq.h" diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 44a17ffc3058..d1f573f1b6cc 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -59,6 +59,7 @@ #include "display/intel_dmc.h" #include "display/intel_dp.h" #include "display/intel_dpt.h" +#include "display/intel_dram.h" #include "display/intel_encoder.h" #include "display/intel_fbdev.h" #include "display/intel_gmbus.h" @@ -87,7 +88,6 @@ #include "pxp/intel_pxp_debugfs.h" #include "pxp/intel_pxp_pm.h" -#include "soc/intel_dram.h" #include "soc/intel_gmch.h" #include "i915_debugfs.h" diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c deleted file mode 100644 index cfe96c3c1b1a..000000000000 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ /dev/null @@ -1,863 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2020 Intel Corporation - */ - -#include - -#include -#include - -#include "../display/intel_display_core.h" /* FIXME */ - -#include "i915_drv.h" -#include "i915_reg.h" -#include "i915_utils.h" -#include "intel_dram.h" -#include "intel_mchbar_regs.h" -#include "intel_pcode.h" -#include "intel_uncore.h" -#include "vlv_iosf_sb.h" - -struct dram_dimm_info { - u16 size; - u8 width, ranks; -}; - -struct dram_channel_info { - struct dram_dimm_info dimm_l, dimm_s; - u8 ranks; - bool is_16gb_dimm; -}; - -#define DRAM_TYPE_STR(type) [INTEL_DRAM_ ## type] = #type - -const char *intel_dram_type_str(enum intel_dram_type type) -{ - static const char * const str[] = { - DRAM_TYPE_STR(UNKNOWN), - DRAM_TYPE_STR(DDR2), - DRAM_TYPE_STR(DDR3), - DRAM_TYPE_STR(DDR4), - DRAM_TYPE_STR(LPDDR3), - DRAM_TYPE_STR(LPDDR4), - DRAM_TYPE_STR(DDR5), - DRAM_TYPE_STR(LPDDR5), - DRAM_TYPE_STR(GDDR), - DRAM_TYPE_STR(GDDR_ECC), - }; - - BUILD_BUG_ON(ARRAY_SIZE(str) != __INTEL_DRAM_TYPE_MAX); - - if (type >= ARRAY_SIZE(str)) - type = INTEL_DRAM_UNKNOWN; - - return str[type]; -} - -#undef DRAM_TYPE_STR - -static enum intel_dram_type pnv_dram_type(struct drm_i915_private *i915) -{ - return intel_uncore_read(&i915->uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ? - INTEL_DRAM_DDR3 : INTEL_DRAM_DDR2; -} - -static unsigned int pnv_mem_freq(struct drm_i915_private *dev_priv) -{ - u32 tmp; - - tmp = intel_uncore_read(&dev_priv->uncore, CLKCFG); - - switch (tmp & CLKCFG_MEM_MASK) { - case CLKCFG_MEM_533: - return 533333; - case CLKCFG_MEM_667: - return 666667; - case CLKCFG_MEM_800: - return 800000; - } - - return 0; -} - -static unsigned int ilk_mem_freq(struct drm_i915_private *dev_priv) -{ - u16 ddrpll; - - ddrpll = intel_uncore_read16(&dev_priv->uncore, DDRMPLL1); - switch (ddrpll & 0xff) { - case 0xc: - return 800000; - case 0x10: - return 1066667; - case 0x14: - return 1333333; - case 0x18: - return 1600000; - default: - drm_dbg(&dev_priv->drm, "unknown memory frequency 0x%02x\n", - ddrpll & 0xff); - return 0; - } -} - -static unsigned int chv_mem_freq(struct drm_i915_private *i915) -{ - u32 val; - - vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_CCK)); - val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG); - vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_CCK)); - - switch ((val >> 2) & 0x7) { - case 3: - return 2000000; - default: - return 1600000; - } -} - -static unsigned int vlv_mem_freq(struct drm_i915_private *i915) -{ - u32 val; - - vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); - - switch ((val >> 6) & 3) { - case 0: - case 1: - return 800000; - case 2: - return 1066667; - case 3: - return 1333333; - } - - return 0; -} - -unsigned int intel_mem_freq(struct drm_i915_private *i915) -{ - if (IS_PINEVIEW(i915)) - return pnv_mem_freq(i915); - else if (GRAPHICS_VER(i915) == 5) - return ilk_mem_freq(i915); - else if (IS_CHERRYVIEW(i915)) - return chv_mem_freq(i915); - else if (IS_VALLEYVIEW(i915)) - return vlv_mem_freq(i915); - else - return 0; -} - -static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) -{ - u32 fsb; - - /* - * Note that this only reads the state of the FSB - * straps, not the actual FSB frequency. Some BIOSen - * let you configure each independently. Ideally we'd - * read out the actual FSB frequency but sadly we - * don't know which registers have that information, - * and all the relevant docs have gone to bit heaven :( - */ - fsb = intel_uncore_read(&i915->uncore, CLKCFG) & CLKCFG_FSB_MASK; - - if (IS_PINEVIEW(i915) || IS_MOBILE(i915)) { - switch (fsb) { - case CLKCFG_FSB_400: - return 400000; - case CLKCFG_FSB_533: - return 533333; - case CLKCFG_FSB_667: - return 666667; - case CLKCFG_FSB_800: - return 800000; - case CLKCFG_FSB_1067: - return 1066667; - case CLKCFG_FSB_1333: - return 1333333; - default: - MISSING_CASE(fsb); - return 1333333; - } - } else { - switch (fsb) { - case CLKCFG_FSB_400_ALT: - return 400000; - case CLKCFG_FSB_533: - return 533333; - case CLKCFG_FSB_667: - return 666667; - case CLKCFG_FSB_800: - return 800000; - case CLKCFG_FSB_1067_ALT: - return 1066667; - case CLKCFG_FSB_1333_ALT: - return 1333333; - case CLKCFG_FSB_1600_ALT: - return 1600000; - default: - MISSING_CASE(fsb); - return 1333333; - } - } -} - -static unsigned int ilk_fsb_freq(struct drm_i915_private *dev_priv) -{ - u16 fsb; - - fsb = intel_uncore_read16(&dev_priv->uncore, CSIPLL0) & 0x3ff; - - switch (fsb) { - case 0x00c: - return 3200000; - case 0x00e: - return 3733333; - case 0x010: - return 4266667; - case 0x012: - return 4800000; - case 0x014: - return 5333333; - case 0x016: - return 5866667; - case 0x018: - return 6400000; - default: - drm_dbg(&dev_priv->drm, "unknown fsb frequency 0x%04x\n", fsb); - return 0; - } -} - -unsigned int intel_fsb_freq(struct drm_i915_private *i915) -{ - if (GRAPHICS_VER(i915) == 5) - return ilk_fsb_freq(i915); - else if (GRAPHICS_VER(i915) == 3 || GRAPHICS_VER(i915) == 4) - return i9xx_fsb_freq(i915); - else - return 0; -} - -static int i915_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) -{ - dram_info->fsb_freq = intel_fsb_freq(i915); - if (dram_info->fsb_freq) - drm_dbg(&i915->drm, "FSB frequency: %d kHz\n", dram_info->fsb_freq); - - dram_info->mem_freq = intel_mem_freq(i915); - if (dram_info->mem_freq) - drm_dbg(&i915->drm, "DDR speed: %d kHz\n", dram_info->mem_freq); - - if (IS_PINEVIEW(i915)) - dram_info->type = pnv_dram_type(i915); - - return 0; -} - -static int intel_dimm_num_devices(const struct dram_dimm_info *dimm) -{ - return dimm->ranks * 64 / (dimm->width ?: 1); -} - -/* Returns total Gb for the whole DIMM */ -static int skl_get_dimm_s_size(u32 val) -{ - return REG_FIELD_GET(SKL_DIMM_S_SIZE_MASK, val) * 8; -} - -static int skl_get_dimm_l_size(u32 val) -{ - return REG_FIELD_GET(SKL_DIMM_L_SIZE_MASK, val) * 8; -} - -static int skl_get_dimm_s_width(u32 val) -{ - if (skl_get_dimm_s_size(val) == 0) - return 0; - - switch (val & SKL_DIMM_S_WIDTH_MASK) { - case SKL_DIMM_S_WIDTH_X8: - case SKL_DIMM_S_WIDTH_X16: - case SKL_DIMM_S_WIDTH_X32: - return 8 << REG_FIELD_GET(SKL_DIMM_S_WIDTH_MASK, val); - default: - MISSING_CASE(val); - return 0; - } -} - -static int skl_get_dimm_l_width(u32 val) -{ - if (skl_get_dimm_l_size(val) == 0) - return 0; - - switch (val & SKL_DIMM_L_WIDTH_MASK) { - case SKL_DIMM_L_WIDTH_X8: - case SKL_DIMM_L_WIDTH_X16: - case SKL_DIMM_L_WIDTH_X32: - return 8 << REG_FIELD_GET(SKL_DIMM_L_WIDTH_MASK, val); - default: - MISSING_CASE(val); - return 0; - } -} - -static int skl_get_dimm_s_ranks(u32 val) -{ - if (skl_get_dimm_s_size(val) == 0) - return 0; - - return REG_FIELD_GET(SKL_DIMM_S_RANK_MASK, val) + 1; -} - -static int skl_get_dimm_l_ranks(u32 val) -{ - if (skl_get_dimm_l_size(val) == 0) - return 0; - - return REG_FIELD_GET(SKL_DIMM_L_RANK_MASK, val) + 1; -} - -/* Returns total Gb for the whole DIMM */ -static int icl_get_dimm_s_size(u32 val) -{ - return REG_FIELD_GET(ICL_DIMM_S_SIZE_MASK, val) * 8 / 2; -} - -static int icl_get_dimm_l_size(u32 val) -{ - return REG_FIELD_GET(ICL_DIMM_L_SIZE_MASK, val) * 8 / 2; -} - -static int icl_get_dimm_s_width(u32 val) -{ - if (icl_get_dimm_s_size(val) == 0) - return 0; - - switch (val & ICL_DIMM_S_WIDTH_MASK) { - case ICL_DIMM_S_WIDTH_X8: - case ICL_DIMM_S_WIDTH_X16: - case ICL_DIMM_S_WIDTH_X32: - return 8 << REG_FIELD_GET(ICL_DIMM_S_WIDTH_MASK, val); - default: - MISSING_CASE(val); - return 0; - } -} - -static int icl_get_dimm_l_width(u32 val) -{ - if (icl_get_dimm_l_size(val) == 0) - return 0; - - switch (val & ICL_DIMM_L_WIDTH_MASK) { - case ICL_DIMM_L_WIDTH_X8: - case ICL_DIMM_L_WIDTH_X16: - case ICL_DIMM_L_WIDTH_X32: - return 8 << REG_FIELD_GET(ICL_DIMM_L_WIDTH_MASK, val); - default: - MISSING_CASE(val); - return 0; - } -} - -static int icl_get_dimm_s_ranks(u32 val) -{ - if (icl_get_dimm_s_size(val) == 0) - return 0; - - return REG_FIELD_GET(ICL_DIMM_S_RANK_MASK, val) + 1; -} - -static int icl_get_dimm_l_ranks(u32 val) -{ - if (icl_get_dimm_l_size(val) == 0) - return 0; - - return REG_FIELD_GET(ICL_DIMM_L_RANK_MASK, val) + 1; -} - -static bool -skl_is_16gb_dimm(const struct dram_dimm_info *dimm) -{ - /* Convert total Gb to Gb per DRAM device */ - return dimm->size / (intel_dimm_num_devices(dimm) ?: 1) >= 16; -} - -static void -skl_dram_print_dimm_info(struct drm_i915_private *i915, - struct dram_dimm_info *dimm, - int channel, char dimm_name) -{ - drm_dbg_kms(&i915->drm, - "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb+ DIMMs: %s\n", - channel, dimm_name, dimm->size, dimm->width, dimm->ranks, - str_yes_no(skl_is_16gb_dimm(dimm))); -} - -static void -skl_dram_get_dimm_l_info(struct drm_i915_private *i915, - struct dram_dimm_info *dimm, - int channel, u32 val) -{ - if (GRAPHICS_VER(i915) >= 11) { - dimm->size = icl_get_dimm_l_size(val); - dimm->width = icl_get_dimm_l_width(val); - dimm->ranks = icl_get_dimm_l_ranks(val); - } else { - dimm->size = skl_get_dimm_l_size(val); - dimm->width = skl_get_dimm_l_width(val); - dimm->ranks = skl_get_dimm_l_ranks(val); - } - - skl_dram_print_dimm_info(i915, dimm, channel, 'L'); -} - -static void -skl_dram_get_dimm_s_info(struct drm_i915_private *i915, - struct dram_dimm_info *dimm, - int channel, u32 val) -{ - if (GRAPHICS_VER(i915) >= 11) { - dimm->size = icl_get_dimm_s_size(val); - dimm->width = icl_get_dimm_s_width(val); - dimm->ranks = icl_get_dimm_s_ranks(val); - } else { - dimm->size = skl_get_dimm_s_size(val); - dimm->width = skl_get_dimm_s_width(val); - dimm->ranks = skl_get_dimm_s_ranks(val); - } - - skl_dram_print_dimm_info(i915, dimm, channel, 'S'); -} - -static int -skl_dram_get_channel_info(struct drm_i915_private *i915, - struct dram_channel_info *ch, - int channel, u32 val) -{ - skl_dram_get_dimm_l_info(i915, &ch->dimm_l, channel, val); - skl_dram_get_dimm_s_info(i915, &ch->dimm_s, channel, val); - - if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) { - drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel); - return -EINVAL; - } - - if (ch->dimm_l.ranks == 2 || ch->dimm_s.ranks == 2) - ch->ranks = 2; - else if (ch->dimm_l.ranks == 1 && ch->dimm_s.ranks == 1) - ch->ranks = 2; - else - ch->ranks = 1; - - ch->is_16gb_dimm = skl_is_16gb_dimm(&ch->dimm_l) || - skl_is_16gb_dimm(&ch->dimm_s); - - drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb+ DIMMs: %s\n", - channel, ch->ranks, str_yes_no(ch->is_16gb_dimm)); - - return 0; -} - -static bool -intel_is_dram_symmetric(const struct dram_channel_info *ch0, - const struct dram_channel_info *ch1) -{ - return !memcmp(ch0, ch1, sizeof(*ch0)) && - (ch0->dimm_s.size == 0 || - !memcmp(&ch0->dimm_l, &ch0->dimm_s, sizeof(ch0->dimm_l))); -} - -static int -skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram_info) -{ - struct dram_channel_info ch0 = {}, ch1 = {}; - u32 val; - int ret; - - /* Assume 16Gb+ DIMMs are present until proven otherwise */ - dram_info->has_16gb_dimms = true; - - val = intel_uncore_read(&i915->uncore, - SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(i915, &ch0, 0, val); - if (ret == 0) - dram_info->num_channels++; - - val = intel_uncore_read(&i915->uncore, - SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(i915, &ch1, 1, val); - if (ret == 0) - dram_info->num_channels++; - - if (dram_info->num_channels == 0) { - drm_info(&i915->drm, "Number of memory channels is zero\n"); - return -EINVAL; - } - - if (ch0.ranks == 0 && ch1.ranks == 0) { - drm_info(&i915->drm, "couldn't get memory rank information\n"); - return -EINVAL; - } - - dram_info->has_16gb_dimms = ch0.is_16gb_dimm || ch1.is_16gb_dimm; - - dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1); - - drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n", - str_yes_no(dram_info->symmetric_memory)); - - drm_dbg_kms(&i915->drm, "16Gb+ DIMMs: %s\n", - str_yes_no(dram_info->has_16gb_dimms)); - - return 0; -} - -static enum intel_dram_type -skl_get_dram_type(struct drm_i915_private *i915) -{ - u32 val; - - val = intel_uncore_read(&i915->uncore, - SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN); - - switch (val & SKL_DRAM_DDR_TYPE_MASK) { - case SKL_DRAM_DDR_TYPE_DDR3: - return INTEL_DRAM_DDR3; - case SKL_DRAM_DDR_TYPE_DDR4: - return INTEL_DRAM_DDR4; - case SKL_DRAM_DDR_TYPE_LPDDR3: - return INTEL_DRAM_LPDDR3; - case SKL_DRAM_DDR_TYPE_LPDDR4: - return INTEL_DRAM_LPDDR4; - default: - MISSING_CASE(val); - return INTEL_DRAM_UNKNOWN; - } -} - -static int -skl_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) -{ - int ret; - - dram_info->type = skl_get_dram_type(i915); - - ret = skl_dram_get_channels_info(i915, dram_info); - if (ret) - return ret; - - return 0; -} - -/* Returns Gb per DRAM device */ -static int bxt_get_dimm_size(u32 val) -{ - switch (val & BXT_DRAM_SIZE_MASK) { - case BXT_DRAM_SIZE_4GBIT: - return 4; - case BXT_DRAM_SIZE_6GBIT: - return 6; - case BXT_DRAM_SIZE_8GBIT: - return 8; - case BXT_DRAM_SIZE_12GBIT: - return 12; - case BXT_DRAM_SIZE_16GBIT: - return 16; - default: - MISSING_CASE(val); - return 0; - } -} - -static int bxt_get_dimm_width(u32 val) -{ - if (!bxt_get_dimm_size(val)) - return 0; - - val = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT; - - return 8 << val; -} - -static int bxt_get_dimm_ranks(u32 val) -{ - if (!bxt_get_dimm_size(val)) - return 0; - - switch (val & BXT_DRAM_RANK_MASK) { - case BXT_DRAM_RANK_SINGLE: - return 1; - case BXT_DRAM_RANK_DUAL: - return 2; - default: - MISSING_CASE(val); - return 0; - } -} - -static enum intel_dram_type bxt_get_dimm_type(u32 val) -{ - if (!bxt_get_dimm_size(val)) - return INTEL_DRAM_UNKNOWN; - - switch (val & BXT_DRAM_TYPE_MASK) { - case BXT_DRAM_TYPE_DDR3: - return INTEL_DRAM_DDR3; - case BXT_DRAM_TYPE_LPDDR3: - return INTEL_DRAM_LPDDR3; - case BXT_DRAM_TYPE_DDR4: - return INTEL_DRAM_DDR4; - case BXT_DRAM_TYPE_LPDDR4: - return INTEL_DRAM_LPDDR4; - default: - MISSING_CASE(val); - return INTEL_DRAM_UNKNOWN; - } -} - -static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val) -{ - dimm->width = bxt_get_dimm_width(val); - dimm->ranks = bxt_get_dimm_ranks(val); - - /* - * Size in register is Gb per DRAM device. Convert to total - * Gb to match the way we report this for non-LP platforms. - */ - dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm); -} - -static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) -{ - u32 val; - u8 valid_ranks = 0; - int i; - - /* - * Now read each DUNIT8/9/10/11 to check the rank of each dimms. - */ - for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) { - struct dram_dimm_info dimm; - enum intel_dram_type type; - - val = intel_uncore_read(&i915->uncore, BXT_D_CR_DRP0_DUNIT(i)); - if (val == 0xFFFFFFFF) - continue; - - dram_info->num_channels++; - - bxt_get_dimm_info(&dimm, val); - type = bxt_get_dimm_type(val); - - drm_WARN_ON(&i915->drm, type != INTEL_DRAM_UNKNOWN && - dram_info->type != INTEL_DRAM_UNKNOWN && - dram_info->type != type); - - drm_dbg_kms(&i915->drm, - "CH%u DIMM size: %u Gb, width: X%u, ranks: %u\n", - i - BXT_D_CR_DRP0_DUNIT_START, - dimm.size, dimm.width, dimm.ranks); - - if (valid_ranks == 0) - valid_ranks = dimm.ranks; - - if (type != INTEL_DRAM_UNKNOWN) - dram_info->type = type; - } - - if (dram_info->type == INTEL_DRAM_UNKNOWN || valid_ranks == 0) { - drm_info(&i915->drm, "couldn't get memory information\n"); - return -EINVAL; - } - - return 0; -} - -static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv, - struct dram_info *dram_info) -{ - u32 val = 0; - int ret; - - ret = intel_pcode_read(&dev_priv->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO | - ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL); - if (ret) - return ret; - - if (GRAPHICS_VER(dev_priv) == 12) { - switch (val & 0xf) { - case 0: - dram_info->type = INTEL_DRAM_DDR4; - break; - case 1: - dram_info->type = INTEL_DRAM_DDR5; - break; - case 2: - dram_info->type = INTEL_DRAM_LPDDR5; - break; - case 3: - dram_info->type = INTEL_DRAM_LPDDR4; - break; - case 4: - dram_info->type = INTEL_DRAM_DDR3; - break; - case 5: - dram_info->type = INTEL_DRAM_LPDDR3; - break; - default: - MISSING_CASE(val & 0xf); - return -EINVAL; - } - } else { - switch (val & 0xf) { - case 0: - dram_info->type = INTEL_DRAM_DDR4; - break; - case 1: - dram_info->type = INTEL_DRAM_DDR3; - break; - case 2: - dram_info->type = INTEL_DRAM_LPDDR3; - break; - case 3: - dram_info->type = INTEL_DRAM_LPDDR4; - break; - default: - MISSING_CASE(val & 0xf); - return -EINVAL; - } - } - - dram_info->num_channels = (val & 0xf0) >> 4; - dram_info->num_qgv_points = (val & 0xf00) >> 8; - dram_info->num_psf_gv_points = (val & 0x3000) >> 12; - - return 0; -} - -static int gen11_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) -{ - int ret; - - ret = skl_dram_get_channels_info(i915, dram_info); - if (ret) - return ret; - - return icl_pcode_read_mem_global_info(i915, dram_info); -} - -static int gen12_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) -{ - return icl_pcode_read_mem_global_info(i915, dram_info); -} - -static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) -{ - struct intel_display *display = i915->display; - u32 val = intel_uncore_read(&i915->uncore, MTL_MEM_SS_INFO_GLOBAL); - - switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) { - case 0: - dram_info->type = INTEL_DRAM_DDR4; - break; - case 1: - dram_info->type = INTEL_DRAM_DDR5; - break; - case 2: - dram_info->type = INTEL_DRAM_LPDDR5; - break; - case 3: - dram_info->type = INTEL_DRAM_LPDDR4; - break; - case 4: - dram_info->type = INTEL_DRAM_DDR3; - break; - case 5: - dram_info->type = INTEL_DRAM_LPDDR3; - break; - case 8: - drm_WARN_ON(&i915->drm, !IS_DGFX(i915)); - dram_info->type = INTEL_DRAM_GDDR; - break; - case 9: - drm_WARN_ON(&i915->drm, !IS_DGFX(i915)); - dram_info->type = INTEL_DRAM_GDDR_ECC; - break; - default: - MISSING_CASE(val); - return -EINVAL; - } - - dram_info->num_channels = REG_FIELD_GET(MTL_N_OF_POPULATED_CH_MASK, val); - dram_info->num_qgv_points = REG_FIELD_GET(MTL_N_OF_ENABLED_QGV_POINTS_MASK, val); - /* PSF GV points not supported in D14+ */ - - if (DISPLAY_VER(display) >= 35) - dram_info->ecc_impacting_de_bw = REG_FIELD_GET(XE3P_ECC_IMPACTING_DE, val); - - return 0; -} - -int intel_dram_detect(struct drm_i915_private *i915) -{ - struct intel_display *display = i915->display; - struct dram_info *dram_info; - int ret; - - if (IS_DG2(i915) || !intel_display_device_present(display)) - return 0; - - dram_info = drmm_kzalloc(&i915->drm, sizeof(*dram_info), GFP_KERNEL); - if (!dram_info) - return -ENOMEM; - - i915->dram_info = dram_info; - - if (DISPLAY_VER(display) >= 14) - ret = xelpdp_get_dram_info(i915, dram_info); - else if (GRAPHICS_VER(i915) >= 12) - ret = gen12_get_dram_info(i915, dram_info); - else if (GRAPHICS_VER(i915) >= 11) - ret = gen11_get_dram_info(i915, dram_info); - else if (IS_BROXTON(i915) || IS_GEMINILAKE(i915)) - ret = bxt_get_dram_info(i915, dram_info); - else if (GRAPHICS_VER(i915) >= 9) - ret = skl_get_dram_info(i915, dram_info); - else - ret = i915_get_dram_info(i915, dram_info); - - drm_dbg_kms(&i915->drm, "DRAM type: %s\n", - intel_dram_type_str(dram_info->type)); - - drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels); - - drm_dbg_kms(&i915->drm, "Num QGV points %u\n", dram_info->num_qgv_points); - drm_dbg_kms(&i915->drm, "Num PSF GV points %u\n", dram_info->num_psf_gv_points); - - /* TODO: Do we want to abort probe on dram detection failures? */ - if (ret) - return 0; - - return 0; -} - -/* - * Returns NULL for platforms that don't have dram info. Avoid overzealous NULL - * checks, and prefer not dereferencing on platforms that shouldn't look at dram - * info, to catch accidental and incorrect dram info checks. - */ -const struct dram_info *intel_dram_info(struct drm_device *drm) -{ - struct drm_i915_private *i915 = to_i915(drm); - - return i915->dram_info; -} diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/soc/intel_dram.h deleted file mode 100644 index 58aaf2f91afe..000000000000 --- a/drivers/gpu/drm/i915/soc/intel_dram.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2020 Intel Corporation - */ - -#ifndef __INTEL_DRAM_H__ -#define __INTEL_DRAM_H__ - -#include - -struct drm_i915_private; -struct drm_device; - -struct dram_info { - enum intel_dram_type { - INTEL_DRAM_UNKNOWN, - INTEL_DRAM_DDR2, - INTEL_DRAM_DDR3, - INTEL_DRAM_DDR4, - INTEL_DRAM_LPDDR3, - INTEL_DRAM_LPDDR4, - INTEL_DRAM_DDR5, - INTEL_DRAM_LPDDR5, - INTEL_DRAM_GDDR, - INTEL_DRAM_GDDR_ECC, - __INTEL_DRAM_TYPE_MAX, - } type; - unsigned int fsb_freq; - unsigned int mem_freq; - u8 num_channels; - u8 num_qgv_points; - u8 num_psf_gv_points; - bool ecc_impacting_de_bw; /* Only valid from Xe3p_LPD onward. */ - bool symmetric_memory; - bool has_16gb_dimms; -}; - -int intel_dram_detect(struct drm_i915_private *i915); -unsigned int intel_fsb_freq(struct drm_i915_private *i915); -unsigned int intel_mem_freq(struct drm_i915_private *i915); -const struct dram_info *intel_dram_info(struct drm_device *drm); -const char *intel_dram_type_str(enum intel_dram_type type); - -#endif /* __INTEL_DRAM_H__ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 8b60fc72fe50..f296a00e4dc9 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -220,7 +220,6 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ # SOC code shared with i915 xe-$(CONFIG_DRM_XE_DISPLAY) += \ - i915-soc/intel_dram.o \ i915-soc/intel_rom.o # Display code shared with i915 @@ -272,6 +271,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_dpll.o \ i915-display/intel_dpll_mgr.o \ i915-display/intel_dpt_common.o \ + i915-display/intel_dram.o \ i915-display/intel_drrs.o \ i915-display/intel_dsb.o \ i915-display/intel_dsi.o \ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h b/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h deleted file mode 100644 index 65707e20c557..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_dram.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#include "../../../i915/soc/intel_dram.h" diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index e3320d9e6314..9b1d21e03df0 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -17,7 +17,6 @@ #include #include -#include "soc/intel_dram.h" #include "intel_acpi.h" #include "intel_audio.h" #include "intel_bw.h" @@ -29,6 +28,7 @@ #include "intel_dmc.h" #include "intel_dmc_wl.h" #include "intel_dp.h" +#include "intel_dram.h" #include "intel_encoder.h" #include "intel_fbdev.h" #include "intel_hdcp.h" -- cgit v1.2.3 From 1178b860605891dc728404dadff4dd6adeadb444 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:43 +0200 Subject: drm/xe: remove MISSING_CASE() from compat i915_utils.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no longer users for MISSING_CASE() in the compat i915_utils.h. Remove it to prevent new users from showing up. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/b967e605ff9d9ad459f3d12a9dfc9244458d83a1.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h index bcd441dc0fce..3639721f0bf8 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h @@ -3,11 +3,5 @@ * Copyright © 2023 Intel Corporation */ -/* for soc/ */ -#ifndef MISSING_CASE -#define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \ - __stringify(x), (long)(x)) -#endif - /* for a couple of users under i915/display */ #define i915_inject_probe_failure(unused) ((unused) && 0) -- cgit v1.2.3 From b8660fa66207ff36efcc0f1747845e423c7ad987 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 20 Nov 2025 18:18:46 +0200 Subject: drm/i915/dram: convert to struct intel_display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert everything except uncore access to struct intel_display. Converting the graphics version checks to display version checks needs a tweak for display version 13, which have graphics version 12. While at it, convert logging to drm_dbg_kms(). v2: Handle display version 13 Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/20251120161846.3128999-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/i9xx_wm.c | 2 +- drivers/gpu/drm/i915/display/intel_bw.c | 2 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 4 +- drivers/gpu/drm/i915/display/intel_display_power.c | 2 +- drivers/gpu/drm/i915/display/intel_dram.c | 205 +++++++++++---------- drivers/gpu/drm/i915/display/intel_dram.h | 11 +- drivers/gpu/drm/i915/display/skl_watermark.c | 4 +- drivers/gpu/drm/i915/i915_driver.c | 2 +- drivers/gpu/drm/xe/display/xe_display.c | 2 +- 9 files changed, 120 insertions(+), 114 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.c b/drivers/gpu/drm/i915/display/i9xx_wm.c index 27e2d73bc505..167277cd8877 100644 --- a/drivers/gpu/drm/i915/display/i9xx_wm.c +++ b/drivers/gpu/drm/i915/display/i9xx_wm.c @@ -90,7 +90,7 @@ static const struct cxsr_latency cxsr_latency_table[] = { static const struct cxsr_latency *pnv_get_cxsr_latency(struct intel_display *display) { - const struct dram_info *dram_info = intel_dram_info(display->drm); + const struct dram_info *dram_info = intel_dram_info(display); bool is_ddr3 = dram_info->type == INTEL_DRAM_DDR3; int i; diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 957c90e62569..d27835ed49c2 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -799,7 +799,7 @@ static unsigned int icl_qgv_bw(struct intel_display *display, void intel_bw_init_hw(struct intel_display *display) { - const struct dram_info *dram_info = intel_dram_info(display->drm); + const struct dram_info *dram_info = intel_dram_info(display); if (!HAS_DISPLAY(display)) return; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 531819391c8c..5c90e53b4e46 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -3737,10 +3737,8 @@ static int pch_rawclk(struct intel_display *display) static int i9xx_hrawclk(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - /* hrawclock is 1/4 the FSB frequency */ - return DIV_ROUND_CLOSEST(intel_fsb_freq(i915), 4); + return DIV_ROUND_CLOSEST(intel_fsb_freq(display), 4); } /** diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 9c5f0277d8c2..08db9bbbfcb1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1616,7 +1616,7 @@ static const struct buddy_page_mask wa_1409767108_buddy_page_masks[] = { static void tgl_bw_buddy_init(struct intel_display *display) { - const struct dram_info *dram_info = intel_dram_info(display->drm); + const struct dram_info *dram_info = intel_dram_info(display); const struct buddy_page_mask *table; unsigned long abox_mask = DISPLAY_INFO(display)->abox_mask; int config, i; diff --git a/drivers/gpu/drm/i915/display/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c index 7142772f2a6e..b4fa1fe8709c 100644 --- a/drivers/gpu/drm/i915/display/intel_dram.c +++ b/drivers/gpu/drm/i915/display/intel_dram.c @@ -56,14 +56,17 @@ const char *intel_dram_type_str(enum intel_dram_type type) #undef DRAM_TYPE_STR -static enum intel_dram_type pnv_dram_type(struct drm_i915_private *i915) +static enum intel_dram_type pnv_dram_type(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); + return intel_uncore_read(&i915->uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ? INTEL_DRAM_DDR3 : INTEL_DRAM_DDR2; } -static unsigned int pnv_mem_freq(struct drm_i915_private *dev_priv) +static unsigned int pnv_mem_freq(struct intel_display *display) { + struct drm_i915_private *dev_priv = to_i915(display->drm); u32 tmp; tmp = intel_uncore_read(&dev_priv->uncore, CLKCFG); @@ -80,8 +83,9 @@ static unsigned int pnv_mem_freq(struct drm_i915_private *dev_priv) return 0; } -static unsigned int ilk_mem_freq(struct drm_i915_private *dev_priv) +static unsigned int ilk_mem_freq(struct intel_display *display) { + struct drm_i915_private *dev_priv = to_i915(display->drm); u16 ddrpll; ddrpll = intel_uncore_read16(&dev_priv->uncore, DDRMPLL1); @@ -95,19 +99,19 @@ static unsigned int ilk_mem_freq(struct drm_i915_private *dev_priv) case 0x18: return 1600000; default: - drm_dbg(&dev_priv->drm, "unknown memory frequency 0x%02x\n", - ddrpll & 0xff); + drm_dbg_kms(display->drm, "unknown memory frequency 0x%02x\n", + ddrpll & 0xff); return 0; } } -static unsigned int chv_mem_freq(struct drm_i915_private *i915) +static unsigned int chv_mem_freq(struct intel_display *display) { u32 val; - vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_CCK)); - val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG); - vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_CCK)); + 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)); switch ((val >> 2) & 0x7) { case 3: @@ -117,13 +121,13 @@ static unsigned int chv_mem_freq(struct drm_i915_private *i915) } } -static unsigned int vlv_mem_freq(struct drm_i915_private *i915) +static unsigned int vlv_mem_freq(struct intel_display *display) { u32 val; - vlv_iosf_sb_get(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); - val = vlv_iosf_sb_read(&i915->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS); - vlv_iosf_sb_put(&i915->drm, BIT(VLV_IOSF_SB_PUNIT)); + 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)); switch ((val >> 6) & 3) { case 0: @@ -138,22 +142,23 @@ static unsigned int vlv_mem_freq(struct drm_i915_private *i915) return 0; } -unsigned int intel_mem_freq(struct drm_i915_private *i915) +unsigned int intel_mem_freq(struct intel_display *display) { - if (IS_PINEVIEW(i915)) - return pnv_mem_freq(i915); - else if (GRAPHICS_VER(i915) == 5) - return ilk_mem_freq(i915); - else if (IS_CHERRYVIEW(i915)) - return chv_mem_freq(i915); - else if (IS_VALLEYVIEW(i915)) - return vlv_mem_freq(i915); + if (display->platform.pineview) + return pnv_mem_freq(display); + else if (DISPLAY_VER(display) == 5) + return ilk_mem_freq(display); + else if (display->platform.cherryview) + return chv_mem_freq(display); + else if (display->platform.valleyview) + return vlv_mem_freq(display); else return 0; } -static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) +static unsigned int i9xx_fsb_freq(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); u32 fsb; /* @@ -166,7 +171,7 @@ static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) */ fsb = intel_uncore_read(&i915->uncore, CLKCFG) & CLKCFG_FSB_MASK; - if (IS_PINEVIEW(i915) || IS_MOBILE(i915)) { + if (display->platform.pineview || display->platform.mobile) { switch (fsb) { case CLKCFG_FSB_400: return 400000; @@ -207,8 +212,9 @@ static unsigned int i9xx_fsb_freq(struct drm_i915_private *i915) } } -static unsigned int ilk_fsb_freq(struct drm_i915_private *dev_priv) +static unsigned int ilk_fsb_freq(struct intel_display *display) { + struct drm_i915_private *dev_priv = to_i915(display->drm); u16 fsb; fsb = intel_uncore_read16(&dev_priv->uncore, CSIPLL0) & 0x3ff; @@ -229,33 +235,33 @@ static unsigned int ilk_fsb_freq(struct drm_i915_private *dev_priv) case 0x018: return 6400000; default: - drm_dbg(&dev_priv->drm, "unknown fsb frequency 0x%04x\n", fsb); + drm_dbg_kms(display->drm, "unknown fsb frequency 0x%04x\n", fsb); return 0; } } -unsigned int intel_fsb_freq(struct drm_i915_private *i915) +unsigned int intel_fsb_freq(struct intel_display *display) { - if (GRAPHICS_VER(i915) == 5) - return ilk_fsb_freq(i915); - else if (GRAPHICS_VER(i915) == 3 || GRAPHICS_VER(i915) == 4) - return i9xx_fsb_freq(i915); + if (DISPLAY_VER(display) == 5) + return ilk_fsb_freq(display); + else if (IS_DISPLAY_VER(display, 3, 4)) + return i9xx_fsb_freq(display); else return 0; } -static int i915_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +static int i915_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { - dram_info->fsb_freq = intel_fsb_freq(i915); + dram_info->fsb_freq = intel_fsb_freq(display); if (dram_info->fsb_freq) - drm_dbg(&i915->drm, "FSB frequency: %d kHz\n", dram_info->fsb_freq); + drm_dbg_kms(display->drm, "FSB frequency: %d kHz\n", dram_info->fsb_freq); - dram_info->mem_freq = intel_mem_freq(i915); + dram_info->mem_freq = intel_mem_freq(display); if (dram_info->mem_freq) - drm_dbg(&i915->drm, "DDR speed: %d kHz\n", dram_info->mem_freq); + drm_dbg_kms(display->drm, "DDR speed: %d kHz\n", dram_info->mem_freq); - if (IS_PINEVIEW(i915)) - dram_info->type = pnv_dram_type(i915); + if (display->platform.pineview) + dram_info->type = pnv_dram_type(display); return 0; } @@ -391,22 +397,22 @@ skl_is_16gb_dimm(const struct dram_dimm_info *dimm) } static void -skl_dram_print_dimm_info(struct drm_i915_private *i915, +skl_dram_print_dimm_info(struct intel_display *display, struct dram_dimm_info *dimm, int channel, char dimm_name) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb+ DIMMs: %s\n", channel, dimm_name, dimm->size, dimm->width, dimm->ranks, str_yes_no(skl_is_16gb_dimm(dimm))); } static void -skl_dram_get_dimm_l_info(struct drm_i915_private *i915, +skl_dram_get_dimm_l_info(struct intel_display *display, struct dram_dimm_info *dimm, int channel, u32 val) { - if (GRAPHICS_VER(i915) >= 11) { + if (DISPLAY_VER(display) >= 11) { dimm->size = icl_get_dimm_l_size(val); dimm->width = icl_get_dimm_l_width(val); dimm->ranks = icl_get_dimm_l_ranks(val); @@ -416,15 +422,15 @@ skl_dram_get_dimm_l_info(struct drm_i915_private *i915, dimm->ranks = skl_get_dimm_l_ranks(val); } - skl_dram_print_dimm_info(i915, dimm, channel, 'L'); + skl_dram_print_dimm_info(display, dimm, channel, 'L'); } static void -skl_dram_get_dimm_s_info(struct drm_i915_private *i915, +skl_dram_get_dimm_s_info(struct intel_display *display, struct dram_dimm_info *dimm, int channel, u32 val) { - if (GRAPHICS_VER(i915) >= 11) { + if (DISPLAY_VER(display) >= 11) { dimm->size = icl_get_dimm_s_size(val); dimm->width = icl_get_dimm_s_width(val); dimm->ranks = icl_get_dimm_s_ranks(val); @@ -434,19 +440,19 @@ skl_dram_get_dimm_s_info(struct drm_i915_private *i915, dimm->ranks = skl_get_dimm_s_ranks(val); } - skl_dram_print_dimm_info(i915, dimm, channel, 'S'); + skl_dram_print_dimm_info(display, dimm, channel, 'S'); } static int -skl_dram_get_channel_info(struct drm_i915_private *i915, +skl_dram_get_channel_info(struct intel_display *display, struct dram_channel_info *ch, int channel, u32 val) { - skl_dram_get_dimm_l_info(i915, &ch->dimm_l, channel, val); - skl_dram_get_dimm_s_info(i915, &ch->dimm_s, channel, val); + skl_dram_get_dimm_l_info(display, &ch->dimm_l, channel, val); + skl_dram_get_dimm_s_info(display, &ch->dimm_s, channel, val); if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) { - drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel); + drm_dbg_kms(display->drm, "CH%u not populated\n", channel); return -EINVAL; } @@ -460,7 +466,7 @@ skl_dram_get_channel_info(struct drm_i915_private *i915, ch->is_16gb_dimm = skl_is_16gb_dimm(&ch->dimm_l) || skl_is_16gb_dimm(&ch->dimm_s); - drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb+ DIMMs: %s\n", + drm_dbg_kms(display->drm, "CH%u ranks: %u, 16Gb+ DIMMs: %s\n", channel, ch->ranks, str_yes_no(ch->is_16gb_dimm)); return 0; @@ -476,8 +482,9 @@ intel_is_dram_symmetric(const struct dram_channel_info *ch0, } static int -skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram_info) +skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram_info) { + struct drm_i915_private *i915 = to_i915(display->drm); struct dram_channel_info ch0 = {}, ch1 = {}; u32 val; int ret; @@ -487,23 +494,23 @@ skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram val = intel_uncore_read(&i915->uncore, SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(i915, &ch0, 0, val); + ret = skl_dram_get_channel_info(display, &ch0, 0, val); if (ret == 0) dram_info->num_channels++; val = intel_uncore_read(&i915->uncore, SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(i915, &ch1, 1, val); + ret = skl_dram_get_channel_info(display, &ch1, 1, val); if (ret == 0) dram_info->num_channels++; if (dram_info->num_channels == 0) { - drm_info(&i915->drm, "Number of memory channels is zero\n"); + drm_info(display->drm, "Number of memory channels is zero\n"); return -EINVAL; } if (ch0.ranks == 0 && ch1.ranks == 0) { - drm_info(&i915->drm, "couldn't get memory rank information\n"); + drm_info(display->drm, "couldn't get memory rank information\n"); return -EINVAL; } @@ -511,18 +518,19 @@ skl_dram_get_channels_info(struct drm_i915_private *i915, struct dram_info *dram dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1); - drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n", + drm_dbg_kms(display->drm, "Memory configuration is symmetric? %s\n", str_yes_no(dram_info->symmetric_memory)); - drm_dbg_kms(&i915->drm, "16Gb+ DIMMs: %s\n", + drm_dbg_kms(display->drm, "16Gb+ DIMMs: %s\n", str_yes_no(dram_info->has_16gb_dimms)); return 0; } static enum intel_dram_type -skl_get_dram_type(struct drm_i915_private *i915) +skl_get_dram_type(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); u32 val; val = intel_uncore_read(&i915->uncore, @@ -544,13 +552,13 @@ skl_get_dram_type(struct drm_i915_private *i915) } static int -skl_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +skl_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { int ret; - dram_info->type = skl_get_dram_type(i915); + dram_info->type = skl_get_dram_type(display); - ret = skl_dram_get_channels_info(i915, dram_info); + ret = skl_dram_get_channels_info(display, dram_info); if (ret) return ret; @@ -635,8 +643,9 @@ static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val) dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm); } -static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +static int bxt_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { + struct drm_i915_private *i915 = to_i915(display->drm); u32 val; u8 valid_ranks = 0; int i; @@ -657,11 +666,11 @@ static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dr bxt_get_dimm_info(&dimm, val); type = bxt_get_dimm_type(val); - drm_WARN_ON(&i915->drm, type != INTEL_DRAM_UNKNOWN && + drm_WARN_ON(display->drm, type != INTEL_DRAM_UNKNOWN && dram_info->type != INTEL_DRAM_UNKNOWN && dram_info->type != type); - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "CH%u DIMM size: %u Gb, width: X%u, ranks: %u\n", i - BXT_D_CR_DRP0_DUNIT_START, dimm.size, dimm.width, dimm.ranks); @@ -674,25 +683,25 @@ static int bxt_get_dram_info(struct drm_i915_private *i915, struct dram_info *dr } if (dram_info->type == INTEL_DRAM_UNKNOWN || valid_ranks == 0) { - drm_info(&i915->drm, "couldn't get memory information\n"); + drm_info(display->drm, "couldn't get memory information\n"); return -EINVAL; } return 0; } -static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv, +static int icl_pcode_read_mem_global_info(struct intel_display *display, struct dram_info *dram_info) { u32 val = 0; int ret; - ret = intel_pcode_read(&dev_priv->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO | + ret = intel_pcode_read(display->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO | ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL); if (ret) return ret; - if (GRAPHICS_VER(dev_priv) == 12) { + if (DISPLAY_VER(display) >= 12) { switch (val & 0xf) { case 0: dram_info->type = INTEL_DRAM_DDR4; @@ -743,25 +752,25 @@ static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv, return 0; } -static int gen11_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +static int gen11_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { int ret; - ret = skl_dram_get_channels_info(i915, dram_info); + ret = skl_dram_get_channels_info(display, dram_info); if (ret) return ret; - return icl_pcode_read_mem_global_info(i915, dram_info); + return icl_pcode_read_mem_global_info(display, dram_info); } -static int gen12_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +static int gen12_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { - return icl_pcode_read_mem_global_info(i915, dram_info); + return icl_pcode_read_mem_global_info(display, dram_info); } -static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info *dram_info) +static int xelpdp_get_dram_info(struct intel_display *display, struct dram_info *dram_info) { - struct intel_display *display = i915->display; + struct drm_i915_private *i915 = to_i915(display->drm); u32 val = intel_uncore_read(&i915->uncore, MTL_MEM_SS_INFO_GLOBAL); switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) { @@ -784,11 +793,11 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info dram_info->type = INTEL_DRAM_LPDDR3; break; case 8: - drm_WARN_ON(&i915->drm, !IS_DGFX(i915)); + drm_WARN_ON(display->drm, !display->platform.dgfx); dram_info->type = INTEL_DRAM_GDDR; break; case 9: - drm_WARN_ON(&i915->drm, !IS_DGFX(i915)); + drm_WARN_ON(display->drm, !display->platform.dgfx); dram_info->type = INTEL_DRAM_GDDR_ECC; break; default: @@ -806,41 +815,41 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915, struct dram_info return 0; } -int intel_dram_detect(struct drm_i915_private *i915) +int intel_dram_detect(struct intel_display *display) { - struct intel_display *display = i915->display; + struct drm_i915_private *i915 = to_i915(display->drm); struct dram_info *dram_info; int ret; - if (IS_DG2(i915) || !intel_display_device_present(display)) + if (display->platform.dg2 || !HAS_DISPLAY(display)) return 0; - dram_info = drmm_kzalloc(&i915->drm, sizeof(*dram_info), GFP_KERNEL); + dram_info = drmm_kzalloc(display->drm, sizeof(*dram_info), GFP_KERNEL); if (!dram_info) return -ENOMEM; i915->dram_info = dram_info; if (DISPLAY_VER(display) >= 14) - ret = xelpdp_get_dram_info(i915, dram_info); - else if (GRAPHICS_VER(i915) >= 12) - ret = gen12_get_dram_info(i915, dram_info); - else if (GRAPHICS_VER(i915) >= 11) - ret = gen11_get_dram_info(i915, dram_info); - else if (IS_BROXTON(i915) || IS_GEMINILAKE(i915)) - ret = bxt_get_dram_info(i915, dram_info); - else if (GRAPHICS_VER(i915) >= 9) - ret = skl_get_dram_info(i915, dram_info); + ret = xelpdp_get_dram_info(display, dram_info); + else if (DISPLAY_VER(display) >= 12) + ret = gen12_get_dram_info(display, dram_info); + else if (DISPLAY_VER(display) >= 11) + ret = gen11_get_dram_info(display, dram_info); + else if (display->platform.broxton || display->platform.geminilake) + ret = bxt_get_dram_info(display, dram_info); + else if (DISPLAY_VER(display) >= 9) + ret = skl_get_dram_info(display, dram_info); else - ret = i915_get_dram_info(i915, dram_info); + ret = i915_get_dram_info(display, dram_info); - drm_dbg_kms(&i915->drm, "DRAM type: %s\n", + drm_dbg_kms(display->drm, "DRAM type: %s\n", intel_dram_type_str(dram_info->type)); - drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels); + drm_dbg_kms(display->drm, "DRAM channels: %u\n", dram_info->num_channels); - drm_dbg_kms(&i915->drm, "Num QGV points %u\n", dram_info->num_qgv_points); - drm_dbg_kms(&i915->drm, "Num PSF GV points %u\n", dram_info->num_psf_gv_points); + drm_dbg_kms(display->drm, "Num QGV points %u\n", dram_info->num_qgv_points); + drm_dbg_kms(display->drm, "Num PSF GV points %u\n", dram_info->num_psf_gv_points); /* TODO: Do we want to abort probe on dram detection failures? */ if (ret) @@ -854,9 +863,9 @@ int intel_dram_detect(struct drm_i915_private *i915) * checks, and prefer not dereferencing on platforms that shouldn't look at dram * info, to catch accidental and incorrect dram info checks. */ -const struct dram_info *intel_dram_info(struct drm_device *drm) +const struct dram_info *intel_dram_info(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(drm); + struct drm_i915_private *i915 = to_i915(display->drm); return i915->dram_info; } diff --git a/drivers/gpu/drm/i915/display/intel_dram.h b/drivers/gpu/drm/i915/display/intel_dram.h index 58aaf2f91afe..5800b7b4e614 100644 --- a/drivers/gpu/drm/i915/display/intel_dram.h +++ b/drivers/gpu/drm/i915/display/intel_dram.h @@ -8,8 +8,7 @@ #include -struct drm_i915_private; -struct drm_device; +struct intel_display; struct dram_info { enum intel_dram_type { @@ -35,10 +34,10 @@ struct dram_info { bool has_16gb_dimms; }; -int intel_dram_detect(struct drm_i915_private *i915); -unsigned int intel_fsb_freq(struct drm_i915_private *i915); -unsigned int intel_mem_freq(struct drm_i915_private *i915); -const struct dram_info *intel_dram_info(struct drm_device *drm); +int intel_dram_detect(struct intel_display *display); +unsigned int intel_fsb_freq(struct intel_display *display); +unsigned int intel_mem_freq(struct intel_display *display); +const struct dram_info *intel_dram_info(struct intel_display *display); const char *intel_dram_type_str(enum intel_dram_type type); #endif /* __INTEL_DRAM_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index a33e0cec8cba..7964cfffdaae 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3125,7 +3125,7 @@ static bool skl_watermark_ipc_can_enable(struct intel_display *display) if (display->platform.kabylake || display->platform.coffeelake || display->platform.cometlake) { - const struct dram_info *dram_info = intel_dram_info(display->drm); + const struct dram_info *dram_info = intel_dram_info(display); return dram_info->symmetric_memory; } @@ -3169,7 +3169,7 @@ static void increase_wm_latency(struct intel_display *display, int inc) static bool need_16gb_dimm_wa(struct intel_display *display) { - const struct dram_info *dram_info = intel_dram_info(display->drm); + const struct dram_info *dram_info = intel_dram_info(display); return (display->platform.skylake || display->platform.kabylake || display->platform.coffeelake || display->platform.cometlake || diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index d1f573f1b6cc..2369e2b55096 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -574,7 +574,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) * Fill the dram structure to get the system dram info. This will be * used for memory latency calculation. */ - ret = intel_dram_detect(dev_priv); + ret = intel_dram_detect(display); if (ret) goto err_opregion; diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 9b1d21e03df0..793115077615 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -122,7 +122,7 @@ int xe_display_init_early(struct xe_device *xe) * Fill the dram structure to get the system dram info. This will be * used for memory latency calculation. */ - err = intel_dram_detect(xe); + err = intel_dram_detect(display); if (err) goto err_opregion; -- cgit v1.2.3 From de4ca6f8e9277fed49192454b7940681977ab1e5 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:45 +0200 Subject: drm/i915: move dram_info to struct intel_display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With all of dram code under display, also move dram_info to struct intel_display. This further cleans up struct xe_device from display related members. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/cbbca93003952ea24ae60e66d79d901dba78ccd8.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_core.h | 4 ++++ drivers/gpu/drm/i915/display/intel_dram.c | 7 ++----- drivers/gpu/drm/i915/i915_drv.h | 3 --- drivers/gpu/drm/xe/xe_device_types.h | 2 -- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 9b8414b77c15..9b36654b593d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -394,6 +394,10 @@ struct intel_display { u32 mmio_base; } dsi; + struct { + const struct dram_info *info; + } dram; + struct { /* list of fbdev register on this device */ struct intel_fbdev *fbdev; diff --git a/drivers/gpu/drm/i915/display/intel_dram.c b/drivers/gpu/drm/i915/display/intel_dram.c index b4fa1fe8709c..019a722a38bf 100644 --- a/drivers/gpu/drm/i915/display/intel_dram.c +++ b/drivers/gpu/drm/i915/display/intel_dram.c @@ -817,7 +817,6 @@ static int xelpdp_get_dram_info(struct intel_display *display, struct dram_info int intel_dram_detect(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); struct dram_info *dram_info; int ret; @@ -828,7 +827,7 @@ int intel_dram_detect(struct intel_display *display) if (!dram_info) return -ENOMEM; - i915->dram_info = dram_info; + display->dram.info = dram_info; if (DISPLAY_VER(display) >= 14) ret = xelpdp_get_dram_info(display, dram_info); @@ -865,7 +864,5 @@ int intel_dram_detect(struct intel_display *display) */ const struct dram_info *intel_dram_info(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - return i915->dram_info; + return display->dram.info; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5381a934a671..96af7776bee5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -60,7 +60,6 @@ #include "intel_step.h" #include "intel_uncore.h" -struct dram_info; struct drm_i915_clock_gating_funcs; struct intel_display; struct intel_pxp; @@ -279,8 +278,6 @@ struct drm_i915_private { u32 suspend_count; struct vlv_s0ix_state *vlv_s0ix_state; - const struct dram_info *dram_info; - struct intel_runtime_pm runtime_pm; struct i915_perf perf; diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 430ac085c22b..10b91dac96ad 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -34,7 +34,6 @@ #define TEST_VM_OPS_ERROR #endif -struct dram_info; struct intel_display; struct intel_dg_nvm_dev; struct xe_ggtt; @@ -637,7 +636,6 @@ struct xe_device { * drm_i915_private during build. After cleanup these should go away, * migrating to the right sub-structs */ - const struct dram_info *dram_info; struct intel_uncore { spinlock_t lock; -- cgit v1.2.3 From b3d3c83e00c7846bfa6c4aa12f64321849dd3819 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:46 +0200 Subject: drm/i915: move intel_rom.[ch] from soc/ to display/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sole user of intel_rom.[ch] has always been in display. Move them under display. This allows us to remove the compat soc/intel_rom.h from xe, as well as the Makefile rules to build anything from soc/. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/352ec255a6e9b81c7d1e35d8fbf7018d4049d4d3.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 4 +- drivers/gpu/drm/i915/display/intel_bios.c | 3 +- drivers/gpu/drm/i915/display/intel_rom.c | 161 +++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_rom.h | 25 ++++ drivers/gpu/drm/i915/soc/intel_rom.c | 161 --------------------- drivers/gpu/drm/i915/soc/intel_rom.h | 25 ---- drivers/gpu/drm/xe/Makefile | 10 +- .../gpu/drm/xe/compat-i915-headers/soc/intel_rom.h | 6 - 8 files changed, 190 insertions(+), 205 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_rom.c create mode 100644 drivers/gpu/drm/i915/display/intel_rom.h delete mode 100644 drivers/gpu/drm/i915/soc/intel_rom.c delete mode 100644 drivers/gpu/drm/i915/soc/intel_rom.h delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 57d150765784..42f2d9294142 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -58,8 +58,7 @@ i915-y += \ # core peripheral code i915-y += \ - soc/intel_gmch.o \ - soc/intel_rom.o + soc/intel_gmch.o # core library code i915-y += \ @@ -303,6 +302,7 @@ i915-y += \ display/intel_pmdemand.o \ display/intel_psr.o \ display/intel_quirks.o \ + display/intel_rom.o \ display/intel_sbi.o \ display/intel_sprite.o \ display/intel_sprite_uapi.o \ diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 4b41068e9e35..a639c5eb3245 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -34,14 +34,13 @@ #include #include -#include "soc/intel_rom.h" - #include "intel_display.h" #include "intel_display_core.h" #include "intel_display_rpm.h" #include "intel_display_types.h" #include "intel_display_utils.h" #include "intel_gmbus.h" +#include "intel_rom.h" #define _INTEL_BIOS_PRIVATE #include "intel_vbt_defs.h" diff --git a/drivers/gpu/drm/i915/display/intel_rom.c b/drivers/gpu/drm/i915/display/intel_rom.c new file mode 100644 index 000000000000..2f17dc856e7f --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_rom.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2024 Intel Corporation + */ + +#include "i915_drv.h" +#include "i915_reg.h" + +#include "intel_rom.h" +#include "intel_uncore.h" + +struct intel_rom { + /* for PCI ROM */ + struct pci_dev *pdev; + void __iomem *oprom; + + /* for SPI */ + struct intel_uncore *uncore; + loff_t offset; + + size_t size; + + u32 (*read32)(struct intel_rom *rom, loff_t offset); + u16 (*read16)(struct intel_rom *rom, loff_t offset); + void (*read_block)(struct intel_rom *rom, void *data, loff_t offset, size_t size); + void (*free)(struct intel_rom *rom); +}; + +static u32 spi_read32(struct intel_rom *rom, loff_t offset) +{ + intel_uncore_write(rom->uncore, PRIMARY_SPI_ADDRESS, + rom->offset + offset); + + return intel_uncore_read(rom->uncore, PRIMARY_SPI_TRIGGER); +} + +static u16 spi_read16(struct intel_rom *rom, loff_t offset) +{ + return spi_read32(rom, offset) & 0xffff; +} + +struct intel_rom *intel_rom_spi(struct drm_device *drm) +{ + struct drm_i915_private *i915 = to_i915(drm); + struct intel_rom *rom; + u32 static_region; + + rom = kzalloc(sizeof(*rom), GFP_KERNEL); + if (!rom) + return NULL; + + rom->uncore = &i915->uncore; + + static_region = intel_uncore_read(rom->uncore, SPI_STATIC_REGIONS); + static_region &= OPTIONROM_SPI_REGIONID_MASK; + intel_uncore_write(rom->uncore, PRIMARY_SPI_REGIONID, static_region); + + rom->offset = intel_uncore_read(rom->uncore, OROM_OFFSET) & OROM_OFFSET_MASK; + + rom->size = 0x200000; + + rom->read32 = spi_read32; + rom->read16 = spi_read16; + + return rom; +} + +static u32 pci_read32(struct intel_rom *rom, loff_t offset) +{ + return ioread32(rom->oprom + offset); +} + +static u16 pci_read16(struct intel_rom *rom, loff_t offset) +{ + return ioread16(rom->oprom + offset); +} + +static void pci_read_block(struct intel_rom *rom, void *data, + loff_t offset, size_t size) +{ + memcpy_fromio(data, rom->oprom + offset, size); +} + +static void pci_free(struct intel_rom *rom) +{ + pci_unmap_rom(rom->pdev, rom->oprom); +} + +struct intel_rom *intel_rom_pci(struct drm_device *drm) +{ + struct intel_rom *rom; + + rom = kzalloc(sizeof(*rom), GFP_KERNEL); + if (!rom) + return NULL; + + rom->pdev = to_pci_dev(drm->dev); + + rom->oprom = pci_map_rom(rom->pdev, &rom->size); + if (!rom->oprom) { + kfree(rom); + return NULL; + } + + rom->read32 = pci_read32; + rom->read16 = pci_read16; + rom->read_block = pci_read_block; + rom->free = pci_free; + + return rom; +} + +u32 intel_rom_read32(struct intel_rom *rom, loff_t offset) +{ + return rom->read32(rom, offset); +} + +u16 intel_rom_read16(struct intel_rom *rom, loff_t offset) +{ + return rom->read16(rom, offset); +} + +void intel_rom_read_block(struct intel_rom *rom, void *data, + loff_t offset, size_t size) +{ + u32 *ptr = data; + loff_t index; + + if (rom->read_block) { + rom->read_block(rom, data, offset, size); + return; + } + + for (index = 0; index < size; index += 4) + *ptr++ = rom->read32(rom, offset + index); +} + +loff_t intel_rom_find(struct intel_rom *rom, u32 needle) +{ + loff_t offset; + + for (offset = 0; offset < rom->size; offset += 4) { + if (rom->read32(rom, offset) == needle) + return offset; + } + + return -ENOENT; +} + +size_t intel_rom_size(struct intel_rom *rom) +{ + return rom->size; +} + +void intel_rom_free(struct intel_rom *rom) +{ + if (rom && rom->free) + rom->free(rom); + + kfree(rom); +} diff --git a/drivers/gpu/drm/i915/display/intel_rom.h b/drivers/gpu/drm/i915/display/intel_rom.h new file mode 100644 index 000000000000..4e59a375787e --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_rom.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __INTEL_ROM_H__ +#define __INTEL_ROM_H__ + +#include + +struct drm_device; +struct intel_rom; + +struct intel_rom *intel_rom_spi(struct drm_device *drm); +struct intel_rom *intel_rom_pci(struct drm_device *drm); + +u32 intel_rom_read32(struct intel_rom *rom, loff_t offset); +u16 intel_rom_read16(struct intel_rom *rom, loff_t offset); +void intel_rom_read_block(struct intel_rom *rom, void *data, + loff_t offset, size_t size); +loff_t intel_rom_find(struct intel_rom *rom, u32 needle); +size_t intel_rom_size(struct intel_rom *rom); +void intel_rom_free(struct intel_rom *rom); + +#endif /* __INTEL_ROM_H__ */ diff --git a/drivers/gpu/drm/i915/soc/intel_rom.c b/drivers/gpu/drm/i915/soc/intel_rom.c deleted file mode 100644 index 2f17dc856e7f..000000000000 --- a/drivers/gpu/drm/i915/soc/intel_rom.c +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright © 2024 Intel Corporation - */ - -#include "i915_drv.h" -#include "i915_reg.h" - -#include "intel_rom.h" -#include "intel_uncore.h" - -struct intel_rom { - /* for PCI ROM */ - struct pci_dev *pdev; - void __iomem *oprom; - - /* for SPI */ - struct intel_uncore *uncore; - loff_t offset; - - size_t size; - - u32 (*read32)(struct intel_rom *rom, loff_t offset); - u16 (*read16)(struct intel_rom *rom, loff_t offset); - void (*read_block)(struct intel_rom *rom, void *data, loff_t offset, size_t size); - void (*free)(struct intel_rom *rom); -}; - -static u32 spi_read32(struct intel_rom *rom, loff_t offset) -{ - intel_uncore_write(rom->uncore, PRIMARY_SPI_ADDRESS, - rom->offset + offset); - - return intel_uncore_read(rom->uncore, PRIMARY_SPI_TRIGGER); -} - -static u16 spi_read16(struct intel_rom *rom, loff_t offset) -{ - return spi_read32(rom, offset) & 0xffff; -} - -struct intel_rom *intel_rom_spi(struct drm_device *drm) -{ - struct drm_i915_private *i915 = to_i915(drm); - struct intel_rom *rom; - u32 static_region; - - rom = kzalloc(sizeof(*rom), GFP_KERNEL); - if (!rom) - return NULL; - - rom->uncore = &i915->uncore; - - static_region = intel_uncore_read(rom->uncore, SPI_STATIC_REGIONS); - static_region &= OPTIONROM_SPI_REGIONID_MASK; - intel_uncore_write(rom->uncore, PRIMARY_SPI_REGIONID, static_region); - - rom->offset = intel_uncore_read(rom->uncore, OROM_OFFSET) & OROM_OFFSET_MASK; - - rom->size = 0x200000; - - rom->read32 = spi_read32; - rom->read16 = spi_read16; - - return rom; -} - -static u32 pci_read32(struct intel_rom *rom, loff_t offset) -{ - return ioread32(rom->oprom + offset); -} - -static u16 pci_read16(struct intel_rom *rom, loff_t offset) -{ - return ioread16(rom->oprom + offset); -} - -static void pci_read_block(struct intel_rom *rom, void *data, - loff_t offset, size_t size) -{ - memcpy_fromio(data, rom->oprom + offset, size); -} - -static void pci_free(struct intel_rom *rom) -{ - pci_unmap_rom(rom->pdev, rom->oprom); -} - -struct intel_rom *intel_rom_pci(struct drm_device *drm) -{ - struct intel_rom *rom; - - rom = kzalloc(sizeof(*rom), GFP_KERNEL); - if (!rom) - return NULL; - - rom->pdev = to_pci_dev(drm->dev); - - rom->oprom = pci_map_rom(rom->pdev, &rom->size); - if (!rom->oprom) { - kfree(rom); - return NULL; - } - - rom->read32 = pci_read32; - rom->read16 = pci_read16; - rom->read_block = pci_read_block; - rom->free = pci_free; - - return rom; -} - -u32 intel_rom_read32(struct intel_rom *rom, loff_t offset) -{ - return rom->read32(rom, offset); -} - -u16 intel_rom_read16(struct intel_rom *rom, loff_t offset) -{ - return rom->read16(rom, offset); -} - -void intel_rom_read_block(struct intel_rom *rom, void *data, - loff_t offset, size_t size) -{ - u32 *ptr = data; - loff_t index; - - if (rom->read_block) { - rom->read_block(rom, data, offset, size); - return; - } - - for (index = 0; index < size; index += 4) - *ptr++ = rom->read32(rom, offset + index); -} - -loff_t intel_rom_find(struct intel_rom *rom, u32 needle) -{ - loff_t offset; - - for (offset = 0; offset < rom->size; offset += 4) { - if (rom->read32(rom, offset) == needle) - return offset; - } - - return -ENOENT; -} - -size_t intel_rom_size(struct intel_rom *rom) -{ - return rom->size; -} - -void intel_rom_free(struct intel_rom *rom) -{ - if (rom && rom->free) - rom->free(rom); - - kfree(rom); -} diff --git a/drivers/gpu/drm/i915/soc/intel_rom.h b/drivers/gpu/drm/i915/soc/intel_rom.h deleted file mode 100644 index 4e59a375787e..000000000000 --- a/drivers/gpu/drm/i915/soc/intel_rom.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2024 Intel Corporation - */ - -#ifndef __INTEL_ROM_H__ -#define __INTEL_ROM_H__ - -#include - -struct drm_device; -struct intel_rom; - -struct intel_rom *intel_rom_spi(struct drm_device *drm); -struct intel_rom *intel_rom_pci(struct drm_device *drm); - -u32 intel_rom_read32(struct intel_rom *rom, loff_t offset); -u16 intel_rom_read16(struct intel_rom *rom, loff_t offset); -void intel_rom_read_block(struct intel_rom *rom, void *data, - loff_t offset, size_t size); -loff_t intel_rom_find(struct intel_rom *rom, u32 needle); -size_t intel_rom_size(struct intel_rom *rom); -void intel_rom_free(struct intel_rom *rom); - -#endif /* __INTEL_ROM_H__ */ diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index f296a00e4dc9..f4315b014826 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -191,11 +191,6 @@ subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \ -I$(srctree)/drivers/gpu/drm/i915/display/ \ -Ddrm_i915_private=xe_device -# Rule to build SOC code shared with i915 -$(obj)/i915-soc/%.o: $(srctree)/drivers/gpu/drm/i915/soc/%.c FORCE - $(call cmd,force_checksrc) - $(call if_changed_rule,cc_o_c) - # Rule to build display code shared with i915 $(obj)/i915-display/%.o: $(srctree)/drivers/gpu/drm/i915/display/%.c FORCE $(call cmd,force_checksrc) @@ -218,10 +213,6 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ display/xe_stolen.o \ display/xe_tdf.o -# SOC code shared with i915 -xe-$(CONFIG_DRM_XE_DISPLAY) += \ - i915-soc/intel_rom.o - # Display code shared with i915 xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/icl_dsi.o \ @@ -308,6 +299,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_psr.o \ i915-display/intel_qp_tables.o \ i915-display/intel_quirks.o \ + i915-display/intel_rom.o \ i915-display/intel_snps_hdmi_pll.o \ i915-display/intel_snps_phy.o \ i915-display/intel_tc.o \ diff --git a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h b/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h deleted file mode 100644 index 05cbfb697b2b..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/soc/intel_rom.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2024 Intel Corporation - */ - -#include "../../../i915/soc/intel_rom.h" -- cgit v1.2.3 From 1807d61541d003eee90f7661d6b40245f6966e3a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:47 +0200 Subject: drm/xe: remove remaining platform checks from compat i915_drv.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With xe no longer building anything from soc/, we can remove the compat platform checks from i915_drv.h, reducing the file to just the to_i915() pointer conversion helper. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/a9947337f81e04db342bae6af727e4f75f9818ae.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h index 3e79a74ff7de..04d1925f9a19 100644 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h +++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h @@ -19,19 +19,4 @@ static inline struct drm_i915_private *to_i915(const struct drm_device *dev) return container_of(dev, struct drm_i915_private, drm); } -/* compat platform checks only for soc/ usage */ -#define IS_PLATFORM(xe, x) ((xe)->info.platform == x) -#define IS_I915G(dev_priv) (dev_priv && 0) -#define IS_I915GM(dev_priv) (dev_priv && 0) -#define IS_PINEVIEW(dev_priv) (dev_priv && 0) -#define IS_VALLEYVIEW(dev_priv) (dev_priv && 0) -#define IS_CHERRYVIEW(dev_priv) (dev_priv && 0) -#define IS_HASWELL(dev_priv) (dev_priv && 0) -#define IS_BROADWELL(dev_priv) (dev_priv && 0) -#define IS_BROXTON(dev_priv) (dev_priv && 0) -#define IS_GEMINILAKE(dev_priv) (dev_priv && 0) -#define IS_DG2(dev_priv) IS_PLATFORM(dev_priv, XE_DG2) - -#define IS_MOBILE(xe) (xe && 0) - #endif -- cgit v1.2.3 From eef67acfffd8debdd8c7a3f08ee759cd6bf58fbe Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:48 +0200 Subject: drm/i915/gmch: split out i915_gmch.[ch] from soc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the soc/intel_gmch.[ch] code is i915 core specific. Split it out to i915_gmch.[ch]. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/f4f8cc931ef2a5958cebe3ca44d40aedad01626f.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_driver.c | 11 ++- drivers/gpu/drm/i915/i915_gmch.c | 141 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gmch.h | 13 ++++ drivers/gpu/drm/i915/soc/intel_gmch.c | 132 ------------------------------- drivers/gpu/drm/i915/soc/intel_gmch.h | 3 - 6 files changed, 160 insertions(+), 141 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gmch.c create mode 100644 drivers/gpu/drm/i915/i915_gmch.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 42f2d9294142..1b169ae8f72c 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -30,6 +30,7 @@ i915-y += \ i915_edram.o \ i915_freq.o \ i915_getparam.o \ + i915_gmch.o \ i915_ioctl.o \ i915_irq.o \ i915_mitigations.o \ diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 2369e2b55096..2e837865f829 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -88,8 +88,6 @@ #include "pxp/intel_pxp_debugfs.h" #include "pxp/intel_pxp_pm.h" -#include "soc/intel_gmch.h" - #include "i915_debugfs.h" #include "i915_driver.h" #include "i915_drm_client.h" @@ -97,6 +95,7 @@ #include "i915_edram.h" #include "i915_file_private.h" #include "i915_getparam.h" +#include "i915_gmch.h" #include "i915_hwmon.h" #include "i915_ioc32.h" #include "i915_ioctl.h" @@ -323,7 +322,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) if (i915_inject_probe_failure(dev_priv)) return -ENODEV; - ret = intel_gmch_bridge_setup(dev_priv); + ret = i915_gmch_bridge_setup(dev_priv); if (ret < 0) return ret; @@ -340,7 +339,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) } /* Try to make sure MCHBAR is enabled before poking at it */ - intel_gmch_bar_setup(dev_priv); + i915_gmch_bar_setup(dev_priv); intel_device_info_runtime_init(dev_priv); intel_display_device_info_runtime_init(display); @@ -356,7 +355,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) return 0; err_uncore: - intel_gmch_bar_teardown(dev_priv); + i915_gmch_bar_teardown(dev_priv); return ret; } @@ -367,7 +366,7 @@ err_uncore: */ static void i915_driver_mmio_release(struct drm_i915_private *dev_priv) { - intel_gmch_bar_teardown(dev_priv); + i915_gmch_bar_teardown(dev_priv); } /** diff --git a/drivers/gpu/drm/i915/i915_gmch.c b/drivers/gpu/drm/i915/i915_gmch.c new file mode 100644 index 000000000000..2d55831b3c58 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gmch.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: MIT +/* Copyright © 2025 Intel Corporation */ + +#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) +{ + pci_dev_put(bridge); +} + +int i915_gmch_bridge_setup(struct drm_i915_private *i915) +{ + int domain = pci_domain_nr(to_pci_dev(i915->drm.dev)->bus); + + i915->gmch.pdev = pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); + if (!i915->gmch.pdev) { + drm_err(&i915->drm, "bridge device not found\n"); + return -EIO; + } + + return drmm_add_action_or_reset(&i915->drm, i915_gmch_bridge_release, + i915->gmch.pdev); +} + +static int mchbar_reg(struct drm_i915_private *i915) +{ + return GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915; +} + +/* Allocate space for the MCH regs if needed, return nonzero on error */ +static int +intel_alloc_mchbar_resource(struct drm_i915_private *i915) +{ + u32 temp_lo, temp_hi = 0; + u64 mchbar_addr; + int ret; + + if (GRAPHICS_VER(i915) >= 4) + pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915) + 4, &temp_hi); + pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp_lo); + mchbar_addr = ((u64)temp_hi << 32) | temp_lo; + + /* If ACPI doesn't have it, assume we need to allocate it ourselves */ + if (IS_ENABLED(CONFIG_PNP) && mchbar_addr && + pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) + return 0; + + /* Get some space for it */ + i915->gmch.mch_res.name = "i915 MCHBAR"; + i915->gmch.mch_res.flags = IORESOURCE_MEM; + ret = pci_bus_alloc_resource(i915->gmch.pdev->bus, + &i915->gmch.mch_res, + MCHBAR_SIZE, MCHBAR_SIZE, + PCIBIOS_MIN_MEM, + 0, pcibios_align_resource, + i915->gmch.pdev); + if (ret) { + drm_dbg(&i915->drm, "failed bus alloc: %d\n", ret); + i915->gmch.mch_res.start = 0; + return ret; + } + + if (GRAPHICS_VER(i915) >= 4) + pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915) + 4, + upper_32_bits(i915->gmch.mch_res.start)); + + pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), + lower_32_bits(i915->gmch.mch_res.start)); + return 0; +} + +/* Setup MCHBAR if possible, return true if we should disable it again */ +void i915_gmch_bar_setup(struct drm_i915_private *i915) +{ + u32 temp; + bool enabled; + + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + return; + + i915->gmch.mchbar_need_disable = false; + + if (IS_I915G(i915) || IS_I915GM(i915)) { + pci_read_config_dword(i915->gmch.pdev, DEVEN, &temp); + enabled = !!(temp & DEVEN_MCHBAR_EN); + } else { + pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp); + enabled = temp & 1; + } + + /* If it's already enabled, don't have to do anything */ + if (enabled) + return; + + if (intel_alloc_mchbar_resource(i915)) + return; + + i915->gmch.mchbar_need_disable = true; + + /* Space is allocated or reserved, so enable it. */ + if (IS_I915G(i915) || IS_I915GM(i915)) { + pci_write_config_dword(i915->gmch.pdev, DEVEN, + temp | DEVEN_MCHBAR_EN); + } else { + pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp); + pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), temp | 1); + } +} + +void i915_gmch_bar_teardown(struct drm_i915_private *i915) +{ + if (i915->gmch.mchbar_need_disable) { + if (IS_I915G(i915) || IS_I915GM(i915)) { + u32 deven_val; + + pci_read_config_dword(i915->gmch.pdev, DEVEN, + &deven_val); + deven_val &= ~DEVEN_MCHBAR_EN; + pci_write_config_dword(i915->gmch.pdev, DEVEN, + deven_val); + } else { + u32 mchbar_val; + + pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), + &mchbar_val); + mchbar_val &= ~1; + pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), + mchbar_val); + } + } + + if (i915->gmch.mch_res.start) + release_resource(&i915->gmch.mch_res); +} diff --git a/drivers/gpu/drm/i915/i915_gmch.h b/drivers/gpu/drm/i915/i915_gmch.h new file mode 100644 index 000000000000..3ae50bef04ea --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gmch.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2025 Intel Corporation */ + +#ifndef __I915_GMCH_H__ +#define __I915_GMCH_H__ + +struct drm_i915_private; + +int i915_gmch_bridge_setup(struct drm_i915_private *i915); +void i915_gmch_bar_setup(struct drm_i915_private *i915); +void i915_gmch_bar_teardown(struct drm_i915_private *i915); + +#endif /* __I915_GMCH_H__ */ diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c index 271da30c8290..30f489417064 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.c +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -4,10 +4,8 @@ */ #include -#include #include -#include #include #include @@ -17,136 +15,6 @@ #include "intel_gmch.h" #include "intel_pci_config.h" -static void intel_gmch_bridge_release(struct drm_device *dev, void *bridge) -{ - pci_dev_put(bridge); -} - -int intel_gmch_bridge_setup(struct drm_i915_private *i915) -{ - int domain = pci_domain_nr(to_pci_dev(i915->drm.dev)->bus); - - i915->gmch.pdev = pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); - if (!i915->gmch.pdev) { - drm_err(&i915->drm, "bridge device not found\n"); - return -EIO; - } - - return drmm_add_action_or_reset(&i915->drm, intel_gmch_bridge_release, - i915->gmch.pdev); -} - -static int mchbar_reg(struct drm_i915_private *i915) -{ - return GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915; -} - -/* Allocate space for the MCH regs if needed, return nonzero on error */ -static int -intel_alloc_mchbar_resource(struct drm_i915_private *i915) -{ - u32 temp_lo, temp_hi = 0; - u64 mchbar_addr; - int ret; - - if (GRAPHICS_VER(i915) >= 4) - pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915) + 4, &temp_hi); - pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp_lo); - mchbar_addr = ((u64)temp_hi << 32) | temp_lo; - - /* If ACPI doesn't have it, assume we need to allocate it ourselves */ - if (IS_ENABLED(CONFIG_PNP) && mchbar_addr && - pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) - return 0; - - /* Get some space for it */ - i915->gmch.mch_res.name = "i915 MCHBAR"; - i915->gmch.mch_res.flags = IORESOURCE_MEM; - ret = pci_bus_alloc_resource(i915->gmch.pdev->bus, - &i915->gmch.mch_res, - MCHBAR_SIZE, MCHBAR_SIZE, - PCIBIOS_MIN_MEM, - 0, pcibios_align_resource, - i915->gmch.pdev); - if (ret) { - drm_dbg(&i915->drm, "failed bus alloc: %d\n", ret); - i915->gmch.mch_res.start = 0; - return ret; - } - - if (GRAPHICS_VER(i915) >= 4) - pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915) + 4, - upper_32_bits(i915->gmch.mch_res.start)); - - pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), - lower_32_bits(i915->gmch.mch_res.start)); - return 0; -} - -/* Setup MCHBAR if possible, return true if we should disable it again */ -void intel_gmch_bar_setup(struct drm_i915_private *i915) -{ - u32 temp; - bool enabled; - - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) - return; - - i915->gmch.mchbar_need_disable = false; - - if (IS_I915G(i915) || IS_I915GM(i915)) { - pci_read_config_dword(i915->gmch.pdev, DEVEN, &temp); - enabled = !!(temp & DEVEN_MCHBAR_EN); - } else { - pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp); - enabled = temp & 1; - } - - /* If it's already enabled, don't have to do anything */ - if (enabled) - return; - - if (intel_alloc_mchbar_resource(i915)) - return; - - i915->gmch.mchbar_need_disable = true; - - /* Space is allocated or reserved, so enable it. */ - if (IS_I915G(i915) || IS_I915GM(i915)) { - pci_write_config_dword(i915->gmch.pdev, DEVEN, - temp | DEVEN_MCHBAR_EN); - } else { - pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), &temp); - pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), temp | 1); - } -} - -void intel_gmch_bar_teardown(struct drm_i915_private *i915) -{ - if (i915->gmch.mchbar_need_disable) { - if (IS_I915G(i915) || IS_I915GM(i915)) { - u32 deven_val; - - pci_read_config_dword(i915->gmch.pdev, DEVEN, - &deven_val); - deven_val &= ~DEVEN_MCHBAR_EN; - pci_write_config_dword(i915->gmch.pdev, DEVEN, - deven_val); - } else { - u32 mchbar_val; - - pci_read_config_dword(i915->gmch.pdev, mchbar_reg(i915), - &mchbar_val); - mchbar_val &= ~1; - pci_write_config_dword(i915->gmch.pdev, mchbar_reg(i915), - mchbar_val); - } - } - - if (i915->gmch.mch_res.start) - release_resource(&i915->gmch.mch_res); -} - int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) { struct intel_display *display = i915->display; diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.h b/drivers/gpu/drm/i915/soc/intel_gmch.h index 23be2d113afd..907e1ae921e0 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.h +++ b/drivers/gpu/drm/i915/soc/intel_gmch.h @@ -11,9 +11,6 @@ struct pci_dev; struct drm_i915_private; -int intel_gmch_bridge_setup(struct drm_i915_private *i915); -void intel_gmch_bar_setup(struct drm_i915_private *i915); -void intel_gmch_bar_teardown(struct drm_i915_private *i915); int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode); unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode); -- cgit v1.2.3 From 3018e582da321c5f6d2f03847f9adb44e44cb0ee Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:49 +0200 Subject: drm/i915/gmch: switch to use pci_bus_{read,write}_config_word() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to use pci_bus_{read,write}_config_word(), and stop using i915->gmch.pdev reference for the bridge. Suggested-by: Ville Syrjälä Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/5c432540e254108bf73dbdec347d69ad87682fc9.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/soc/intel_gmch.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c index 30f489417064..d43b5d89cae7 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.c +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -18,10 +18,11 @@ int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) { struct intel_display *display = i915->display; + struct pci_dev *pdev = to_pci_dev(display->drm->dev); unsigned int reg = DISPLAY_VER(display) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL; u16 gmch_ctrl; - if (pci_read_config_word(i915->gmch.pdev, reg, &gmch_ctrl)) { + if (pci_bus_read_config_word(pdev->bus, PCI_DEVFN(0, 0), reg, &gmch_ctrl)) { drm_err(&i915->drm, "failed to read control word\n"); return -EIO; } @@ -34,7 +35,7 @@ int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) else gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; - if (pci_write_config_word(i915->gmch.pdev, reg, gmch_ctrl)) { + if (pci_bus_write_config_word(pdev->bus, PCI_DEVFN(0, 0), reg, gmch_ctrl)) { drm_err(&i915->drm, "failed to write control word\n"); return -EIO; } -- cgit v1.2.3 From fff15f68eb06af4a77e349d419717bc9a2f4b37b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:50 +0200 Subject: drm/i915/gmch: convert intel_gmch.c to struct intel_display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert intel_gmch.[ch] to struct intel_display. Remove the final dependency on struct drm_i915_private and i915_drv.h. This is in preparation of moving the code under display/. intel_gmch_vga_set_state() is only used internally, make it static while at it. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/a4b317656eef0781d4f53ae337083fb05ce602bc.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/soc/intel_gmch.c | 13 ++++++------- drivers/gpu/drm/i915/soc/intel_gmch.h | 2 -- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c index d43b5d89cae7..4e7abe056551 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.c +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -10,20 +10,19 @@ #include #include "../display/intel_display_core.h" /* FIXME */ +#include "../display/intel_display_types.h" /* FIXME */ -#include "i915_drv.h" #include "intel_gmch.h" #include "intel_pci_config.h" -int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) +static int intel_gmch_vga_set_state(struct intel_display *display, bool enable_decode) { - struct intel_display *display = i915->display; struct pci_dev *pdev = to_pci_dev(display->drm->dev); unsigned int reg = DISPLAY_VER(display) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL; u16 gmch_ctrl; if (pci_bus_read_config_word(pdev->bus, PCI_DEVFN(0, 0), reg, &gmch_ctrl)) { - drm_err(&i915->drm, "failed to read control word\n"); + drm_err(display->drm, "failed to read control word\n"); return -EIO; } @@ -36,7 +35,7 @@ int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; if (pci_bus_write_config_word(pdev->bus, PCI_DEVFN(0, 0), reg, gmch_ctrl)) { - drm_err(&i915->drm, "failed to write control word\n"); + drm_err(display->drm, "failed to write control word\n"); return -EIO; } @@ -45,9 +44,9 @@ int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode) unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode) { - struct drm_i915_private *i915 = pdev_to_i915(pdev); + struct intel_display *display = to_intel_display(pdev); - intel_gmch_vga_set_state(i915, enable_decode); + intel_gmch_vga_set_state(display, enable_decode); if (enable_decode) return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.h b/drivers/gpu/drm/i915/soc/intel_gmch.h index 907e1ae921e0..bc3421ab5ba6 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.h +++ b/drivers/gpu/drm/i915/soc/intel_gmch.h @@ -9,9 +9,7 @@ #include struct pci_dev; -struct drm_i915_private; -int intel_gmch_vga_set_state(struct drm_i915_private *i915, bool enable_decode); unsigned int intel_gmch_vga_set_decode(struct pci_dev *pdev, bool enable_decode); #endif /* __INTEL_GMCH_H__ */ -- cgit v1.2.3 From aa4dc3eeff6d5c47ed08905e5cf7b9b77a646fea Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 19 Nov 2025 20:52:51 +0200 Subject: drm/i915: merge soc/intel_gmch.[ch] to display/intel_vga.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sole user of the remaining functions in intel_gmch.[ch] is in intel_vga.c. Move everything there. Since intel_gmch.c hasn't been part of xe, use a dummy function relocated from xe_display_misc.c, with #ifdef. This is purely to keep this change non-functional. This allows us to remove soc/intel_gmch.[ch] from i915, compat soc/intel_gmch.h from xe, and xe_display_misc.c from xe. Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/b0f853ad7eae686738defa9e8f08a8848df8f226.1763578288.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/Makefile | 4 -- drivers/gpu/drm/i915/display/intel_vga.c | 52 +++++++++++++++++++- drivers/gpu/drm/i915/soc/intel_gmch.c | 56 ---------------------- drivers/gpu/drm/i915/soc/intel_gmch.h | 15 ------ drivers/gpu/drm/xe/Makefile | 1 - .../drm/xe/compat-i915-headers/soc/intel_gmch.h | 6 --- drivers/gpu/drm/xe/display/xe_display_misc.c | 16 ------- 7 files changed, 50 insertions(+), 100 deletions(-) delete mode 100644 drivers/gpu/drm/i915/soc/intel_gmch.c delete mode 100644 drivers/gpu/drm/i915/soc/intel_gmch.h delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/soc/intel_gmch.h delete mode 100644 drivers/gpu/drm/xe/display/xe_display_misc.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 1b169ae8f72c..83d70038c337 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -57,10 +57,6 @@ i915-y += \ vlv_iosf_sb.o \ vlv_suspend.o -# core peripheral code -i915-y += \ - soc/intel_gmch.o - # core library code i915-y += \ i915_memcpy.o \ diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index 6e125564db34..5e516c79e2f7 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -9,12 +9,12 @@ #include #include +#include #include