From 2063174c22da83e9440466cf496ad3b20f85f5c8 Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Wed, 23 Apr 2025 14:53:32 +0530 Subject: [PATCH 01/16] drm/i915/lobf: Check for sink error and disable LOBF MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Disable LOBF/ALPM for any erroneous condition from sink side. v1: Initial version. v2: Add centralized alpm error handling. [Jouni] v3: Improve debug print. [Jouni] v4: Disable alpm permanently for sink error. [Jouni] Signed-off-by: Animesh Manna Reviewed-by: Jouni Högander Link: https://lore.kernel.org/r/20250423092334.2294483-10-animesh.manna@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 28 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_alpm.h | 1 + .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 5 ++++ drivers/gpu/drm/i915/display/intel_psr.c | 18 ++---------- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index 606cb3e5f30d..24b666e6d8f9 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -284,6 +284,9 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp, return; } + if (intel_dp->alpm_parameters.sink_alpm_error) + return; + if (!intel_dp_is_edp(intel_dp)) return; @@ -546,5 +549,30 @@ void intel_alpm_disable(struct intel_dp *intel_dp) PORT_ALPM_CTL(cpu_transcoder), PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0); + drm_dbg_kms(display->drm, "Disabling ALPM\n"); mutex_unlock(&intel_dp->alpm_parameters.lock); } + +bool intel_alpm_get_error(struct intel_dp *intel_dp) +{ + struct intel_display *display = to_intel_display(intel_dp); + struct drm_dp_aux *aux = &intel_dp->aux; + u8 val; + int r; + + r = drm_dp_dpcd_readb(aux, DP_RECEIVER_ALPM_STATUS, &val); + if (r != 1) { + drm_err(display->drm, "Error reading ALPM status\n"); + return true; + } + + if (val & DP_ALPM_LOCK_TIMEOUT_ERROR) { + drm_dbg_kms(display->drm, "ALPM lock timeout error\n"); + + /* Clearing error */ + drm_dp_dpcd_writeb(aux, DP_RECEIVER_ALPM_STATUS, val); + return true; + } + + return false; +} diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h index c043a071f84f..d7126d65b60f 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.h +++ b/drivers/gpu/drm/i915/display/intel_alpm.h @@ -31,4 +31,5 @@ void intel_alpm_lobf_debugfs_add(struct intel_connector *connector); bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp); bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp); void intel_alpm_disable(struct intel_dp *intel_dp); +bool intel_alpm_get_error(struct intel_dp *intel_dp); #endif diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 878f378577ab..7415564d058a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1817,6 +1817,7 @@ struct intel_dp { u8 silence_period_sym_clocks; u8 lfps_half_cycle_num_of_syms; bool lobf_disable_debug; + bool sink_alpm_error; } alpm_parameters; u8 alpm_dpcd; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ece787bb3335..607aea1bf6fa 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5392,6 +5392,11 @@ intel_dp_short_pulse(struct intel_dp *intel_dp) intel_psr_short_pulse(intel_dp); + if (intel_alpm_get_error(intel_dp)) { + intel_alpm_disable(intel_dp); + intel_dp->alpm_parameters.sink_alpm_error = true; + } + if (intel_dp_test_short_pulse(intel_dp)) reprobe_needed = true; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index b3d324bd5eff..a6b925d2b7b4 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -3465,29 +3465,15 @@ static int psr_get_status_and_error_status(struct intel_dp *intel_dp, static void psr_alpm_check(struct intel_dp *intel_dp) { - struct intel_display *display = to_intel_display(intel_dp); - struct drm_dp_aux *aux = &intel_dp->aux; struct intel_psr *psr = &intel_dp->psr; - u8 val; - int r; if (!psr->sel_update_enabled) return; - r = drm_dp_dpcd_readb(aux, DP_RECEIVER_ALPM_STATUS, &val); - if (r != 1) { - drm_err(display->drm, "Error reading ALPM status\n"); - return; - } - - if (val & DP_ALPM_LOCK_TIMEOUT_ERROR) { + if (intel_alpm_get_error(intel_dp)) { intel_psr_disable_locked(intel_dp); psr->sink_not_reliable = true; - drm_dbg_kms(display->drm, - "ALPM lock timeout error, disabling PSR\n"); - - /* Clearing error */ - drm_dp_dpcd_writeb(aux, DP_RECEIVER_ALPM_STATUS, val); + intel_alpm_disable(intel_dp); } } -- 2.51.0 From 554698b826a1d0535faa707cf737bdc988068454 Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Wed, 23 Apr 2025 14:53:33 +0530 Subject: [PATCH 02/16] drm/i915/alpm: Add intel_psr_need_alpm() to simplify alpm check MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Simplify the alpm check which will be used multiple places like source configuration, sink enablement etc. Signed-off-by: Animesh Manna Reviewed-by: Jouni Högander Link: https://lore.kernel.org/r/20250423092334.2294483-11-animesh.manna@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 5 +++-- drivers/gpu/drm/i915/display/intel_psr.c | 6 ++++++ drivers/gpu/drm/i915/display/intel_psr.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index 24b666e6d8f9..c4b6da2e6ccf 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -13,6 +13,7 @@ #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dp_aux.h" +#include "intel_psr.h" #include "intel_psr_regs.h" bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp) @@ -331,8 +332,8 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp, enum port port = dp_to_dig_port(intel_dp)->base.port; u32 alpm_ctl; - if (DISPLAY_VER(display) < 20 || - (!crtc_state->has_sel_update && !intel_dp_is_edp(intel_dp))) + if (DISPLAY_VER(display) < 20 || (!intel_psr_needs_alpm(intel_dp, crtc_state) && + !crtc_state->has_lobf)) return; mutex_lock(&intel_dp->alpm_parameters.lock); diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index a6b925d2b7b4..53366663b58b 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -4192,3 +4192,9 @@ void intel_psr_connector_debugfs_add(struct intel_connector *connector) debugfs_create_file("i915_psr_status", 0444, root, connector, &i915_psr_status_fops); } + +bool intel_psr_needs_alpm(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) +{ + return intel_dp_is_edp(intel_dp) && (crtc_state->has_sel_update || + crtc_state->has_panel_replay); +} diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index c61384bb7382..601e47ad3297 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -75,5 +75,6 @@ void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb, struct intel_crtc *crtc); void intel_psr_connector_debugfs_add(struct intel_connector *connector); void intel_psr_debugfs_register(struct intel_display *display); +bool intel_psr_needs_alpm(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); #endif /* __INTEL_PSR_H__ */ -- 2.51.0 From 93d33af699f271b908d3eacf7e5872a8784e5a6d Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Wed, 23 Apr 2025 14:53:34 +0530 Subject: [PATCH 03/16] drm/i915/display: Disintegrate sink alpm enable from psr with lobf MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Make a generic alpm enable function for sink which can be used for PSR2/PR/Lobf. v1: Initial version. v2: Move code comment to intel_psr_needs_alpm(). [Jouni] Signed-off-by: Animesh Manna Reviewed-by: Jouni Högander Link: https://lore.kernel.org/r/20250423092334.2294483-12-animesh.manna@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 21 +++++++++++++++++- drivers/gpu/drm/i915/display/intel_psr.c | 27 ++++------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index c4b6da2e6ccf..482dd192d47d 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -426,6 +426,23 @@ void intel_alpm_pre_plane_update(struct intel_atomic_state *state, } } +static void intel_alpm_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + u8 val; + + if (!intel_psr_needs_alpm(intel_dp, crtc_state) && !crtc_state->has_lobf) + return; + + val = DP_ALPM_ENABLE | DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE; + + if (crtc_state->has_panel_replay || (crtc_state->has_lobf && + intel_alpm_aux_less_wake_supported(intel_dp))) + val |= DP_ALPM_MODE_AUX_LESS; + + drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val); +} + void intel_alpm_post_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -449,8 +466,10 @@ void intel_alpm_post_plane_update(struct intel_atomic_state *state, intel_dp = enc_to_intel_dp(encoder); - if (intel_dp_is_edp(intel_dp)) + if (intel_dp_is_edp(intel_dp)) { + intel_alpm_enable_sink(intel_dp, crtc_state); intel_alpm_configure(intel_dp, crtc_state); + } } } diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 53366663b58b..cc0cec0e85e9 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -796,32 +796,9 @@ static void _psr_enable_sink(struct intel_dp *intel_dp, drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val); } -static void intel_psr_enable_sink_alpm(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - u8 val; - - /* - * eDP Panel Replay uses always ALPM - * PSR2 uses ALPM but PSR1 doesn't - */ - if (!intel_dp_is_edp(intel_dp) || (!crtc_state->has_panel_replay && - !crtc_state->has_sel_update)) - return; - - val = DP_ALPM_ENABLE | DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE; - - if (crtc_state->has_panel_replay) - val |= DP_ALPM_MODE_AUX_LESS; - - drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val); -} - static void intel_psr_enable_sink(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { - intel_psr_enable_sink_alpm(intel_dp, crtc_state); - crtc_state->has_panel_replay ? _panel_replay_enable_sink(intel_dp, crtc_state) : _psr_enable_sink(intel_dp, crtc_state); @@ -4195,6 +4172,10 @@ void intel_psr_connector_debugfs_add(struct intel_connector *connector) bool intel_psr_needs_alpm(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { + /* + * eDP Panel Replay uses always ALPM + * PSR2 uses ALPM but PSR1 doesn't + */ return intel_dp_is_edp(intel_dp) && (crtc_state->has_sel_update || crtc_state->has_panel_replay); } -- 2.51.0 From e7bf2f608172ac8aefe0fa5f4ebca7da3538f2a6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 17 Apr 2025 14:44:49 +0300 Subject: [PATCH 04/16] drm/i915/vga: Clean up VGACNTRL bits MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Use REG_BIT() & co. for the VGACNTRL register bits. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250417114454.12836-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/i915_reg.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 88c46a7c948f..5430fb0be033 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1777,9 +1777,10 @@ /* VBIOS regs */ #define VGACNTRL _MMIO(0x71400) -# define VGA_DISP_DISABLE (1 << 31) -# define VGA_2X_MODE (1 << 30) -# define VGA_PIPE_B_SELECT (1 << 29) +#define VGA_DISP_DISABLE REG_BIT(31) +#define VGA_2X_MODE REG_BIT(30) +#define VGA_PIPE_SEL_MASK REG_BIT(29) +#define VGA_PIPE_SEL(pipe) REG_FIELD_PREP(VGA_PIPE_SEL_MASK, (pipe)) #define VLV_VGACNTRL _MMIO(VLV_DISPLAY_BASE + 0x71400) -- 2.51.0 From cfd045f73f0abc78adc143e7ce17b063428e15cb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 17 Apr 2025 14:44:50 +0300 Subject: [PATCH 05/16] drm/i915/vga: Add more VGACNTRL bits MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Define a pile of extra VGACNTRL bits. We don't really have any real use for most of these but nicer to have them all in one place rather than trawling the specs when one wants to know what's in there. I will have some real use for the CHV pipe select bits later. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250417114454.12836-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/i915_reg.h | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5430fb0be033..e9491f12876f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1778,9 +1778,26 @@ /* VBIOS regs */ #define VGACNTRL _MMIO(0x71400) #define VGA_DISP_DISABLE REG_BIT(31) -#define VGA_2X_MODE REG_BIT(30) -#define VGA_PIPE_SEL_MASK REG_BIT(29) +#define VGA_2X_MODE REG_BIT(30) /* pre-ilk */ +#define VGA_PIPE_SEL_MASK REG_BIT(29) /* pre-ivb */ #define VGA_PIPE_SEL(pipe) REG_FIELD_PREP(VGA_PIPE_SEL_MASK, (pipe)) +#define VGA_PIPE_SEL_MASK_CHV REG_GENMASK(29, 28) /* chv */ +#define VGA_PIPE_SEL_CHV(pipe) REG_FIELD_PREP(VGA_PIPE_SEL_MASK_CHV, (pipe)) +#define VGA_BORDER_ENABLE REG_BIT(26) +#define VGA_PIPE_CSC_ENABLE REG_BIT(24) /* ilk+ */ +#define VGA_CENTERING_ENABLE_MASK REG_GENMASK(25, 24) /* pre-ilk */ +#define VGA_PALETTE_READ_SEL REG_BIT(23) /* pre-ivb */ +#define VGA_PALETTE_A_WRITE_DISABLE REG_BIT(22) /* pre-ivb */ +#define VGA_PALETTE_B_WRITE_DISABLE REG_BIT(21) /* pre-ivb */ +#define VGA_LEGACY_8BIT_PALETTE_ENABLE REG_BIT(20) +#define VGA_PALETTE_BYPASS REG_BIT(19) +#define VGA_NINE_DOT_DISABLE REG_BIT(18) +#define VGA_PALETTE_READ_SEL_HI_CHV REG_BIT(15) /* chv */ +#define VGA_PALETTE_C_WRITE_DISABLE_CHV REG_BIT(14) /* chv */ +#define VGA_ACTIVE_THROTTLING_MASK REG_GENMASK(15, 12) /* ilk+ */ +#define VGA_BLANK_THROTTLING_MASK REG_GENMASK(11, 8) /* ilk+ */ +#define VGA_BLINK_DUTY_CYCLE_MASK REG_GENMASK(7, 6) +#define VGA_VSYNC_BLINK_RATE_MASK REG_GENMASK(5, 0) #define VLV_VGACNTRL _MMIO(VLV_DISPLAY_BASE + 0x71400) -- 2.51.0 From 00efddc6082478566dc32d0d7fcb232723102183 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 17 Apr 2025 14:44:51 +0300 Subject: [PATCH 06/16] drm/i915/vga: Extract intel_vga_regs.h MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Extract the VGACNTR register definitions into their own header file, to declutter i915_reg.h a bit. v2: Group the register offst definitions together (Jani) Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250417114454.12836-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_vga.c | 1 + drivers/gpu/drm/i915/display/intel_vga_regs.h | 36 +++++++++++++++++++ drivers/gpu/drm/i915/gvt/handlers.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 30 ---------------- drivers/gpu/drm/i915/intel_gvt_mmio_table.c | 1 + 5 files changed, 39 insertions(+), 30 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_vga_regs.h diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index 6426ac6b8c51..335e6c45deb2 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -16,6 +16,7 @@ #include "i915_reg.h" #include "intel_de.h" #include "intel_vga.h" +#include "intel_vga_regs.h" static i915_reg_t intel_vga_cntrl_reg(struct intel_display *display) { diff --git a/drivers/gpu/drm/i915/display/intel_vga_regs.h b/drivers/gpu/drm/i915/display/intel_vga_regs.h new file mode 100644 index 000000000000..cbacced1a69f --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_vga_regs.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2025 Intel Corporation + */ + +#ifndef __INTEL_VGA_REGS_H__ +#define __INTEL_VGA_REGS_H__ + +#include "intel_display_reg_defs.h" + +#define VGACNTRL _MMIO(0x71400) +#define VLV_VGACNTRL _MMIO(VLV_DISPLAY_BASE + 0x71400) +#define CPU_VGACNTRL _MMIO(0x41000) +#define VGA_DISP_DISABLE REG_BIT(31) +#define VGA_2X_MODE REG_BIT(30) /* pre-ilk */ +#define VGA_PIPE_SEL_MASK REG_BIT(29) /* pre-ivb */ +#define VGA_PIPE_SEL(pipe) REG_FIELD_PREP(VGA_PIPE_SEL_MASK, (pipe)) +#define VGA_PIPE_SEL_MASK_CHV REG_GENMASK(29, 28) /* chv */ +#define VGA_PIPE_SEL_CHV(pipe) REG_FIELD_PREP(VGA_PIPE_SEL_MASK_CHV, (pipe)) +#define VGA_BORDER_ENABLE REG_BIT(26) +#define VGA_PIPE_CSC_ENABLE REG_BIT(24) /* ilk+ */ +#define VGA_CENTERING_ENABLE_MASK REG_GENMASK(25, 24) /* pre-ilk */ +#define VGA_PALETTE_READ_SEL REG_BIT(23) /* pre-ivb */ +#define VGA_PALETTE_A_WRITE_DISABLE REG_BIT(22) /* pre-ivb */ +#define VGA_PALETTE_B_WRITE_DISABLE REG_BIT(21) /* pre-ivb */ +#define VGA_LEGACY_8BIT_PALETTE_ENABLE REG_BIT(20) +#define VGA_PALETTE_BYPASS REG_BIT(19) +#define VGA_NINE_DOT_DISABLE REG_BIT(18) +#define VGA_PALETTE_READ_SEL_HI_CHV REG_BIT(15) /* chv */ +#define VGA_PALETTE_C_WRITE_DISABLE_CHV REG_BIT(14) /* chv */ +#define VGA_ACTIVE_THROTTLING_MASK REG_GENMASK(15, 12) /* ilk+ */ +#define VGA_BLANK_THROTTLING_MASK REG_GENMASK(11, 8) /* ilk+ */ +#define VGA_BLINK_DUTY_CYCLE_MASK REG_GENMASK(7, 6) +#define VGA_VSYNC_BLINK_RATE_MASK REG_GENMASK(5, 0) + +#endif /* __INTEL_VGA_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index e6e9010462e3..1344e6d20a34 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -56,6 +56,7 @@ #include "display/intel_pps_regs.h" #include "display/intel_psr_regs.h" #include "display/intel_sprite_regs.h" +#include "display/intel_vga_regs.h" #include "display/skl_universal_plane_regs.h" #include "display/skl_watermark_regs.h" #include "display/vlv_dsi_pll_regs.h" diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e9491f12876f..2e4190da3e0d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1775,36 +1775,6 @@ #define SWF3(dev_priv, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x72414 + (i) * 4) #define SWF_ILK(i) _MMIO(0x4F000 + (i) * 4) -/* VBIOS regs */ -#define VGACNTRL _MMIO(0x71400) -#define VGA_DISP_DISABLE REG_BIT(31) -#define VGA_2X_MODE REG_BIT(30) /* pre-ilk */ -#define VGA_PIPE_SEL_MASK REG_BIT(29) /* pre-ivb */ -#define VGA_PIPE_SEL(pipe) REG_FIELD_PREP(VGA_PIPE_SEL_MASK, (pipe)) -#define VGA_PIPE_SEL_MASK_CHV REG_GENMASK(29, 28) /* chv */ -#define VGA_PIPE_SEL_CHV(pipe) REG_FIELD_PREP(VGA_PIPE_SEL_MASK_CHV, (pipe)) -#define VGA_BORDER_ENABLE REG_BIT(26) -#define VGA_PIPE_CSC_ENABLE REG_BIT(24) /* ilk+ */ -#define VGA_CENTERING_ENABLE_MASK REG_GENMASK(25, 24) /* pre-ilk */ -#define VGA_PALETTE_READ_SEL REG_BIT(23) /* pre-ivb */ -#define VGA_PALETTE_A_WRITE_DISABLE REG_BIT(22) /* pre-ivb */ -#define VGA_PALETTE_B_WRITE_DISABLE REG_BIT(21) /* pre-ivb */ -#define VGA_LEGACY_8BIT_PALETTE_ENABLE REG_BIT(20) -#define VGA_PALETTE_BYPASS REG_BIT(19) -#define VGA_NINE_DOT_DISABLE REG_BIT(18) -#define VGA_PALETTE_READ_SEL_HI_CHV REG_BIT(15) /* chv */ -#define VGA_PALETTE_C_WRITE_DISABLE_CHV REG_BIT(14) /* chv */ -#define VGA_ACTIVE_THROTTLING_MASK REG_GENMASK(15, 12) /* ilk+ */ -#define VGA_BLANK_THROTTLING_MASK REG_GENMASK(11, 8) /* ilk+ */ -#define VGA_BLINK_DUTY_CYCLE_MASK REG_GENMASK(7, 6) -#define VGA_VSYNC_BLINK_RATE_MASK REG_GENMASK(5, 0) - -#define VLV_VGACNTRL _MMIO(VLV_DISPLAY_BASE + 0x71400) - -/* Ironlake */ - -#define CPU_VGACNTRL _MMIO(0x41000) - #define DIGITAL_PORT_HOTPLUG_CNTRL _MMIO(0x44030) #define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4) #define DIGITAL_PORTA_PULSE_DURATION_2ms (0 << 2) /* pre-HSW */ diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index 76d84cbb8361..d581a9d2c063 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -21,6 +21,7 @@ #include "display/intel_pfit_regs.h" #include "display/intel_psr_regs.h" #include "display/intel_sprite_regs.h" +#include "display/intel_vga_regs.h" #include "display/skl_universal_plane_regs.h" #include "display/skl_watermark_regs.h" #include "display/vlv_dsi_pll_regs.h" -- 2.51.0 From 0c80d60ae63461c33293859fc41ba57654dc863a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 17 Apr 2025 14:44:52 +0300 Subject: [PATCH 07/16] drm/i915/vga: Include the current pipe in the VGA disable debug message MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add some debugs to the VGA plane disable so that we can at least see from the logs when it happens (and on which pipe). I was curious about this at some point when I was seeing some random underruns near the time when we disable the VGA plane, but I think in the end that turned out to be a red herring. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250417114454.12836-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_vga.c | 29 +++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index 335e6c45deb2..508c69b91a76 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -15,6 +15,7 @@ #include "i915_reg.h" #include "intel_de.h" +#include "intel_display.h" #include "intel_vga.h" #include "intel_vga_regs.h" @@ -28,16 +29,42 @@ static i915_reg_t intel_vga_cntrl_reg(struct intel_display *display) return VGACNTRL; } +static bool has_vga_pipe_sel(struct intel_display *display) +{ + if (display->platform.i845g || + display->platform.i865g) + return false; + + if (display->platform.valleyview || + display->platform.cherryview) + return true; + + return DISPLAY_VER(display) < 7; +} + /* Disable the VGA plane that we never use */ void intel_vga_disable(struct intel_display *display) { struct pci_dev *pdev = to_pci_dev(display->drm->dev); i915_reg_t vga_reg = intel_vga_cntrl_reg(display); + enum pipe pipe; + u32 tmp; u8 sr1; - if (intel_de_read(display, vga_reg) & VGA_DISP_DISABLE) + tmp = intel_de_read(display, vga_reg); + if (tmp & VGA_DISP_DISABLE) return; + if (display->platform.cherryview) + pipe = REG_FIELD_GET(VGA_PIPE_SEL_MASK_CHV, tmp); + else if (has_vga_pipe_sel(display)) + pipe = REG_FIELD_GET(VGA_PIPE_SEL_MASK, tmp); + else + pipe = PIPE_A; + + drm_dbg_kms(display->drm, "Disabling VGA plane on pipe %c\n", + pipe_name(pipe)); + /* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */ vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); outb(0x01, VGA_SEQ_I); -- 2.51.0 From a1b3a81bf7365bb2270756e906b4011faa9afbe5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 17 Apr 2025 14:44:53 +0300 Subject: [PATCH 08/16] drm/i915/vga: Nuke vga_redisable_power_on() MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Now that intel_vga_disable() itself will print a debug message, intel_vga_redisable_power_on() is completely redundant. Get rid of it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250417114454.12836-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_power_well.c | 2 +- drivers/gpu/drm/i915/display/intel_vga.c | 13 +------------ drivers/gpu/drm/i915/display/intel_vga.h | 1 - 3 files changed, 2 insertions(+), 14 deletions(-) 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 563a468f4537..6335fa909a7b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -1256,7 +1256,7 @@ static void vlv_display_power_well_init(struct intel_display *display) intel_crt_reset(&encoder->base); } - intel_vga_redisable_power_on(display); + intel_vga_disable(display); intel_pps_unlock_regs_wa(display); } diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index 508c69b91a76..21c1dbaf652d 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -77,17 +77,6 @@ void intel_vga_disable(struct intel_display *display) intel_de_posting_read(display, vga_reg); } -void intel_vga_redisable_power_on(struct intel_display *display) -{ - i915_reg_t vga_reg = intel_vga_cntrl_reg(display); - - if (!(intel_de_read(display, vga_reg) & VGA_DISP_DISABLE)) { - drm_dbg_kms(display->drm, - "Something enabled VGA plane, disabling it\n"); - intel_vga_disable(display); - } -} - void intel_vga_redisable(struct intel_display *display) { intel_wakeref_t wakeref; @@ -105,7 +94,7 @@ void intel_vga_redisable(struct intel_display *display) if (!wakeref) return; - intel_vga_redisable_power_on(display); + intel_vga_disable(display); intel_display_power_put(display, POWER_DOMAIN_VGA, wakeref); } diff --git a/drivers/gpu/drm/i915/display/intel_vga.h b/drivers/gpu/drm/i915/display/intel_vga.h index 824dfc32a199..d0716782c1f9 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.h +++ b/drivers/gpu/drm/i915/display/intel_vga.h @@ -11,7 +11,6 @@ struct intel_display; void intel_vga_reset_io_mem(struct intel_display *display); void intel_vga_disable(struct intel_display *display); void intel_vga_redisable(struct intel_display *display); -void intel_vga_redisable_power_on(struct intel_display *display); int intel_vga_register(struct intel_display *display); void intel_vga_unregister(struct intel_display *display); -- 2.51.0 From fcd95af591e8cd5880c0c553641beb0e97ba92f6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 17 Apr 2025 14:44:54 +0300 Subject: [PATCH 09/16] drm/i915/vga: Consolidate intel_vga_disable() calls MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Currently we disable the VGA plane from various places, sometimes multiple times in the same init/resume sequence. Get rid of all this mess and do it just once. The most correct place seems to be just after intel_early_display_was() as that one applies various workarounds that need to be in place before we touch any planes (including the VGA plane). Actually, we do still have a second caller in vlv_display_power_well_init(). I think we still need that as the reset value of VGACNTR is 0x0 and thus technically the VGA plane will be (at least partially) enabled after the power well has been toggled. In both cases we have the necessary power reference already held (INIT power domain for load/resume case, and the display power well itself being what we need for vlv_display_power_well_init()). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250417114454.12836-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- .../drm/i915/display/intel_display_driver.c | 3 --- .../drm/i915/display/intel_modeset_setup.c | 3 +++ drivers/gpu/drm/i915/display/intel_vga.c | 22 ------------------- drivers/gpu/drm/i915/display/intel_vga.h | 1 - drivers/gpu/drm/i915/i915_driver.c | 3 --- 5 files changed, 3 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 69678e758c46..5c74ab5fd1aa 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -458,8 +458,6 @@ int intel_display_driver_probe_nogem(struct intel_display *display) intel_hti_init(display); - /* Just disable it once at startup */ - intel_vga_disable(display); intel_setup_outputs(display); ret = intel_dp_tunnel_mgr_init(display); @@ -696,7 +694,6 @@ __intel_display_driver_resume(struct intel_display *display, int ret, i; intel_modeset_setup_hw_state(display, ctx); - intel_vga_redisable(display); if (!state) return 0; diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 5d5ade7fdd77..0325b0c9506d 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -31,6 +31,7 @@ #include "intel_pmdemand.h" #include "intel_tc.h" #include "intel_vblank.h" +#include "intel_vga.h" #include "intel_wm.h" #include "skl_watermark.h" @@ -935,6 +936,8 @@ void intel_modeset_setup_hw_state(struct intel_display *display, wakeref = intel_display_power_get(display, POWER_DOMAIN_INIT); intel_early_display_was(display); + intel_vga_disable(display); + intel_modeset_readout_hw_state(display); /* HW state is read out, now we need to sanitize this mess. */ diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index 21c1dbaf652d..05d140c8032d 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -77,28 +77,6 @@ void intel_vga_disable(struct intel_display *display) intel_de_posting_read(display, vga_reg); } -void intel_vga_redisable(struct intel_display *display) -{ - intel_wakeref_t wakeref; - - /* - * This function can be called both from intel_modeset_setup_hw_state or - * at a very early point in our resume sequence, where the power well - * structures are not yet restored. Since this function is at a very - * paranoid "someone might have enabled VGA while we were not looking" - * level, just check if the power well is enabled instead of trying to - * follow the "don't touch the power well if we don't need it" policy - * the rest of the driver uses. - */ - wakeref = intel_display_power_get_if_enabled(display, POWER_DOMAIN_VGA); - if (!wakeref) - return; - - intel_vga_disable(display); - - intel_display_power_put(display, POWER_DOMAIN_VGA, wakeref); -} - void intel_vga_reset_io_mem(struct intel_display *display) { struct pci_dev *pdev = to_pci_dev(display->drm->dev); diff --git a/drivers/gpu/drm/i915/display/intel_vga.h b/drivers/gpu/drm/i915/display/intel_vga.h index d0716782c1f9..16d699f3b641 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.h +++ b/drivers/gpu/drm/i915/display/intel_vga.h @@ -10,7 +10,6 @@ struct intel_display; void intel_vga_reset_io_mem(struct intel_display *display); void intel_vga_disable(struct intel_display *display); -void intel_vga_redisable(struct intel_display *display); int intel_vga_register(struct intel_display *display); void intel_vga_unregister(struct intel_display *display); diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 97ff9855b5de..96a52f963475 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -62,7 +62,6 @@ #include "display/intel_pch_refclk.h" #include "display/intel_pps.h" #include "display/intel_sprite_uapi.h" -#include "display/intel_vga.h" #include "display/skl_watermark.h" #include "gem/i915_gem_context.h" @@ -1202,8 +1201,6 @@ static int i915_drm_resume(struct drm_device *dev) i9xx_display_sr_restore(display); - intel_vga_redisable(display); - intel_gmbus_reset(display); intel_pps_unlock_regs_wa(display); -- 2.51.0 From 8ff377ae3100791aeb9ae801c0fea7e9558dee8c Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Fri, 25 Apr 2025 18:51:07 +0530 Subject: [PATCH 10/16] drm/i915/alpm: Check for alpm support before accessing alpm register Currently, only EDP supports alpm. So, check for alpm support and prevent the DP connector from accessing the alpm register if doing so is unsupported. Fixes: acff6d6bded3 ("drm/i915/lobf: Add mutex for alpm update") Signed-off-by: Animesh Manna Reviewed-by: Jonathan Cavitt Link: https://lore.kernel.org/r/20250425132107.2926759-1-animesh.manna@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index 482dd192d47d..1bf08b80c23f 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -556,7 +556,7 @@ void intel_alpm_disable(struct intel_dp *intel_dp) struct intel_display *display = to_intel_display(intel_dp); enum transcoder cpu_transcoder = intel_dp->alpm_parameters.transcoder; - if (DISPLAY_VER(display) < 20) + if (DISPLAY_VER(display) < 20 || !intel_dp->alpm_dpcd) return; mutex_lock(&intel_dp->alpm_parameters.lock); -- 2.51.0 From 2930db123f510651752b50db2d30d60fc965a472 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jouni=20H=C3=B6gander?= Date: Wed, 23 Apr 2025 13:27:03 +0300 Subject: [PATCH 11/16] drm/i915/display: Ensure enough lines between delayed VBlank and VBlank MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit To deterministically capture the transition of the state machine going from SRDOFFACK to IDLE, the delayed V. Blank should be at least one line after the non-delayed V. Blank. Ensure this by adding new interface into intel_psr to query number of lines needed for vblank delay and call it from intel_crtc_vblank_delay. v3: use existing intel_crtc_vblank_delay mechanism v2: apply limits only when needed (VRR TG vs. Legacy TG) Bspec: 69897 Signed-off-by: Jouni Högander Reviewed-by: Arun R Murthy Link: https://lore.kernel.org/r/20250423102704.1368310-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 + drivers/gpu/drm/i915/display/intel_psr.c | 39 ++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_psr.h | 1 + 3 files changed, 42 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 58845b74f17d..a4445a29927c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2426,6 +2426,8 @@ static int intel_crtc_vblank_delay(const struct intel_crtc_state *crtc_state) if (intel_crtc_needs_wa_14015401596(crtc_state)) vblank_delay = max(vblank_delay, 1); + vblank_delay = max(vblank_delay, intel_psr_min_vblank_delay(crtc_state)); + return vblank_delay; } diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index cc0cec0e85e9..af76c1db86cd 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -2348,6 +2348,45 @@ void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb, CURSURFLIVE(display, crtc->pipe), 0); } +/** + * intel_psr_min_vblank_delay - Minimum vblank delay needed by PSR + * @crtc_state: the crtc state + * + * Return minimum vblank delay needed by PSR. + */ +int intel_psr_min_vblank_delay(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + + if (!crtc_state->has_psr || DISPLAY_VER(display) < 20) + return 0; + + /* + * Comment on SRD_STATUS register in Bspec for LunarLake and onwards: + * + * To deterministically capture the transition of the state machine + * going from SRDOFFACK to IDLE, the delayed V. Blank should be at least + * one line after the non-delayed V. Blank. + * + * Legacy TG: TRANS_SET_CONTEXT_LATENCY > 0 + * VRR TG: TRANS_VRR_CTL[ VRR Guardband ] < (TRANS_VRR_VMAX[ VRR Vmax ] + * - TRANS_VTOTAL[ Vertical Active ]) + * + * SRD_STATUS is used only by PSR1 on PantherLake. + * SRD_STATUS is used by PSR1 and Panel Replay DP on LunarLake. + */ + + if (DISPLAY_VER(display) >= 30 && (crtc_state->has_panel_replay || + crtc_state->has_sel_update)) + return 0; + else if (DISPLAY_VER(display) < 30 && (crtc_state->has_sel_update || + intel_crtc_has_type(crtc_state, + INTEL_OUTPUT_EDP))) + return 0; + else + return 1; +} + static u32 man_trk_ctl_enable_bit_get(struct intel_display *display) { return display->platform.alderlake_p || DISPLAY_VER(display) >= 14 ? 0 : diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index 601e47ad3297..73c3fa40844b 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -73,6 +73,7 @@ void intel_psr_unlock(const struct intel_crtc_state *crtc_state); void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb, struct intel_atomic_state *state, struct intel_crtc *crtc); +int intel_psr_min_vblank_delay(const struct intel_crtc_state *crtc_state); void intel_psr_connector_debugfs_add(struct intel_connector *connector); void intel_psr_debugfs_register(struct intel_display *display); bool intel_psr_needs_alpm(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); -- 2.51.0 From 2af5615a5ba1aac2a356aa4cd9fc02e78c037092 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jouni=20H=C3=B6gander?= Date: Wed, 23 Apr 2025 13:27:04 +0300 Subject: [PATCH 12/16] drm/i915/psr: Move PSR workaround to intel_psr.c MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Logical place for PSR workaround needing vblank delay is in intel_psr_min_vblank_delay. Move it there. Signed-off-by: Jouni Högander Reviewed-by: Arun R Murthy Link: https://lore.kernel.org/r/20250423102704.1368310-2-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 12 ------------ drivers/gpu/drm/i915/display/intel_psr.c | 11 ++++++++++- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a4445a29927c..b4ddffe53e23 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2406,14 +2406,6 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state) return 0; } -static bool intel_crtc_needs_wa_14015401596(const struct intel_crtc_state *crtc_state) -{ - struct intel_display *display = to_intel_display(crtc_state); - - return intel_vrr_possible(crtc_state) && crtc_state->has_psr && - IS_DISPLAY_VER(display, 13, 14); -} - static int intel_crtc_vblank_delay(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); @@ -2422,10 +2414,6 @@ static int intel_crtc_vblank_delay(const struct intel_crtc_state *crtc_state) if (!HAS_DSB(display)) return 0; - /* Wa_14015401596 */ - if (intel_crtc_needs_wa_14015401596(crtc_state)) - vblank_delay = max(vblank_delay, 1); - vblank_delay = max(vblank_delay, intel_psr_min_vblank_delay(crtc_state)); return vblank_delay; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index af76c1db86cd..ccd66bbc72f7 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -48,6 +48,7 @@ #include "intel_psr_regs.h" #include "intel_snps_phy.h" #include "intel_vblank.h" +#include "intel_vrr.h" #include "skl_universal_plane.h" /** @@ -2358,7 +2359,15 @@ int intel_psr_min_vblank_delay(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); - if (!crtc_state->has_psr || DISPLAY_VER(display) < 20) + if (!crtc_state->has_psr) + return 0; + + /* Wa_14015401596 */ + if (intel_vrr_possible(crtc_state) && IS_DISPLAY_VER(display, 13, 14)) + return 1; + + /* Rest is for SRD_STATUS needed on LunarLake and onwards */ + if (DISPLAY_VER(display) < 20) return 0; /* -- 2.51.0 From bb633ff493bfc27505003dc8ac1e06e8c5d6e076 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 28 Apr 2025 16:47:15 +0300 Subject: [PATCH 13/16] drm/i915/dp: Use an intel_connector pointer everywhere Following the convention, convert intel_dp.c to use an intel_connector pointer everywhere, calling this pointer connector. If the intel connector must be casted from a drm_connector, call this pointer _connector and use this pointer only for the casting. v2: Use for_each_intel_connector_iter(). (Jani) Cc: Jani Nikula Reviewed-by: Jani Nikula Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250428134716.3396802-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 105 +++++++++++++----------- 1 file changed, 56 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 607aea1bf6fa..213bb92f3fff 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5832,20 +5832,21 @@ out_vdd_off: } static void -intel_dp_force(struct drm_connector *connector) +intel_dp_force(struct drm_connector *_connector) { - struct intel_display *display = to_intel_display(connector->dev); - struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector)); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); + struct intel_dp *intel_dp = intel_attached_dp(connector); drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); + connector->base.base.id, connector->base.name); if (!intel_display_driver_check_access(display)) return; intel_dp_unset_edid(intel_dp); - if (connector->status != connector_status_connected) + if (connector->base.status != connector_status_connected) return; intel_dp_set_edid(intel_dp); @@ -5884,24 +5885,25 @@ static int intel_dp_get_modes(struct drm_connector *_connector) } static int -intel_dp_connector_register(struct drm_connector *connector) +intel_dp_connector_register(struct drm_connector *_connector) { - struct intel_display *display = to_intel_display(connector->dev); - struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector)); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); + struct intel_dp *intel_dp = intel_attached_dp(connector); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); int ret; - ret = intel_connector_register(connector); + ret = intel_connector_register(&connector->base); if (ret) return ret; drm_dbg_kms(display->drm, "registering %s bus for %s\n", - intel_dp->aux.name, connector->kdev->kobj.name); + intel_dp->aux.name, connector->base.kdev->kobj.name); - intel_dp->aux.dev = connector->kdev; + intel_dp->aux.dev = connector->base.kdev; ret = drm_dp_aux_register(&intel_dp->aux); if (!ret) - drm_dp_cec_register_connector(&intel_dp->aux, connector); + drm_dp_cec_register_connector(&intel_dp->aux, &connector->base); if (!intel_bios_encoder_is_lspcon(dig_port->base.devdata)) return ret; @@ -5912,20 +5914,21 @@ intel_dp_connector_register(struct drm_connector *connector) */ if (intel_lspcon_init(dig_port)) { if (intel_lspcon_detect_hdr_capability(dig_port)) - drm_connector_attach_hdr_output_metadata_property(connector); + drm_connector_attach_hdr_output_metadata_property(&connector->base); } return ret; } static void -intel_dp_connector_unregister(struct drm_connector *connector) +intel_dp_connector_unregister(struct drm_connector *_connector) { - struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector)); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_dp *intel_dp = intel_attached_dp(connector); drm_dp_cec_unregister_connector(&intel_dp->aux); drm_dp_aux_unregister(&intel_dp->aux); - intel_connector_unregister(connector); + intel_connector_unregister(&connector->base); } void intel_dp_connector_sync_state(struct intel_connector *connector, @@ -5986,21 +5989,21 @@ static int intel_modeset_tile_group(struct intel_atomic_state *state, { struct intel_display *display = to_intel_display(state); struct drm_connector_list_iter conn_iter; - struct drm_connector *connector; + struct intel_connector *connector; int ret = 0; drm_connector_list_iter_begin(display->drm, &conn_iter); - drm_for_each_connector_iter(connector, &conn_iter) { + for_each_intel_connector_iter(connector, &conn_iter) { struct drm_connector_state *conn_state; struct intel_crtc_state *crtc_state; struct intel_crtc *crtc; - if (!connector->has_tile || - connector->tile_group->id != tile_group_id) + if (!connector->base.has_tile || + connector->base.tile_group->id != tile_group_id) continue; conn_state = drm_atomic_get_connector_state(&state->base, - connector); + &connector->base); if (IS_ERR(conn_state)) { ret = PTR_ERR(conn_state); break; @@ -6064,10 +6067,11 @@ static int intel_modeset_affected_transcoders(struct intel_atomic_state *state, } static int intel_modeset_synced_crtcs(struct intel_atomic_state *state, - struct drm_connector *connector) + struct drm_connector *_connector) { + struct intel_connector *connector = to_intel_connector(_connector); const struct drm_connector_state *old_conn_state = - drm_atomic_get_old_connector_state(&state->base, connector); + drm_atomic_get_old_connector_state(&state->base, &connector->base); const struct intel_crtc_state *old_crtc_state; struct intel_crtc *crtc; u8 transcoders; @@ -6089,17 +6093,18 @@ static int intel_modeset_synced_crtcs(struct intel_atomic_state *state, transcoders); } -static int intel_dp_connector_atomic_check(struct drm_connector *conn, +static int intel_dp_connector_atomic_check(struct drm_connector *_connector, struct drm_atomic_state *_state) { - struct intel_display *display = to_intel_display(conn->dev); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); struct intel_atomic_state *state = to_intel_atomic_state(_state); - struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(_state, conn); - struct intel_connector *intel_conn = to_intel_connector(conn); - struct intel_dp *intel_dp = enc_to_intel_dp(intel_conn->encoder); + struct drm_connector_state *conn_state = + drm_atomic_get_new_connector_state(_state, &connector->base); + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); int ret; - ret = intel_digital_connector_atomic_check(conn, &state->base); + ret = intel_digital_connector_atomic_check(&connector->base, &state->base); if (ret) return ret; @@ -6109,12 +6114,12 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn, return ret; } - if (!intel_connector_needs_modeset(state, conn)) + if (!intel_connector_needs_modeset(state, &connector->base)) return 0; ret = intel_dp_tunnel_atomic_check_state(state, intel_dp, - intel_conn); + connector); if (ret) return ret; @@ -6125,21 +6130,22 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn, if (DISPLAY_VER(display) < 9) return 0; - if (conn->has_tile) { - ret = intel_modeset_tile_group(state, conn->tile_group->id); + if (connector->base.has_tile) { + ret = intel_modeset_tile_group(state, connector->base.tile_group->id); if (ret) return ret; } - return intel_modeset_synced_crtcs(state, conn); + return intel_modeset_synced_crtcs(state, &connector->base); } -static void intel_dp_oob_hotplug_event(struct drm_connector *connector, +static void intel_dp_oob_hotplug_event(struct drm_connector *_connector, enum drm_connector_status hpd_state) { - struct intel_display *display = to_intel_display(connector->dev); - struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector)); - struct drm_i915_private *i915 = to_i915(connector->dev); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); + struct intel_encoder *encoder = intel_attached_encoder(connector); + struct drm_i915_private *i915 = to_i915(display->drm); bool hpd_high = hpd_state == connector_status_connected; unsigned int hpd_pin = encoder->hpd_pin; bool need_work = false; @@ -6285,36 +6291,37 @@ intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder) } static void -intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector) +intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *_connector) { + struct intel_connector *connector = to_intel_connector(_connector); struct intel_display *display = to_intel_display(intel_dp); enum port port = dp_to_dig_port(intel_dp)->base.port; if (!intel_dp_is_edp(intel_dp)) - drm_connector_attach_dp_subconnector_property(connector); + drm_connector_attach_dp_subconnector_property(&connector->base); if (!display->platform.g4x && port != PORT_A) - intel_attach_force_audio_property(connector); + intel_attach_force_audio_property(&connector->base); - intel_attach_broadcast_rgb_property(connector); + intel_attach_broadcast_rgb_property(&connector->base); if (HAS_GMCH(display)) - drm_connector_attach_max_bpc_property(connector, 6, 10); + drm_connector_attach_max_bpc_property(&connector->base, 6, 10); else if (DISPLAY_VER(display) >= 5) - drm_connector_attach_max_bpc_property(connector, 6, 12); + drm_connector_attach_max_bpc_property(&connector->base, 6, 12); /* Register HDMI colorspace for case of lspcon */ if (intel_bios_encoder_is_lspcon(dp_to_dig_port(intel_dp)->base.devdata)) { - drm_connector_attach_content_type_property(connector); - intel_attach_hdmi_colorspace_property(connector); + drm_connector_attach_content_type_property(&connector->base); + intel_attach_hdmi_colorspace_property(&connector->base); } else { - intel_attach_dp_colorspace_property(connector); + intel_attach_dp_colorspace_property(&connector->base); } if (intel_dp_has_gamut_metadata_dip(&dp_to_dig_port(intel_dp)->base)) - drm_connector_attach_hdr_output_metadata_property(connector); + drm_connector_attach_hdr_output_metadata_property(&connector->base); if (HAS_VRR(display)) - drm_connector_attach_vrr_capable_property(connector); + drm_connector_attach_vrr_capable_property(&connector->base); } static void -- 2.51.0 From 506f254e362b7a7045ed3ccba2a8f4bedb3fd3d6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 28 Apr 2025 16:47:16 +0300 Subject: [PATCH 14/16] drm/i915/hdmi: Use an intel_connector pointer everywhere Following the convention, convert intel_hdmi.c to use an intel_connector pointer everywhere, calling this pointer connector. If the intel connector must be casted from a drm_connector, call this pointer _connector and use this pointer only for the casting. v2: Use for_each_new_intel_connector_in_state(). (Jani) Cc: Jani Nikula Reviewed-by: Jani Nikula Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250428134716.3396802-3-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_hdmi.c | 189 ++++++++++++---------- 1 file changed, 103 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index e08c01e5b9d3..37f0fbaf3145 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -715,7 +715,7 @@ intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder, struct hdmi_avi_infoframe *frame = &crtc_state->infoframes.avi.avi; const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - struct drm_connector *connector = conn_state->connector; + struct intel_connector *connector = to_intel_connector(conn_state->connector); int ret; if (!crtc_state->has_infoframe) @@ -724,7 +724,7 @@ intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder, crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI); - ret = drm_hdmi_avi_infoframe_from_display_mode(frame, connector, + ret = drm_hdmi_avi_infoframe_from_display_mode(frame, &connector->base, adjusted_mode); if (ret) return false; @@ -743,7 +743,7 @@ intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder, crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB); if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_RGB) { - drm_hdmi_avi_infoframe_quant_range(frame, connector, + drm_hdmi_avi_infoframe_quant_range(frame, &connector->base, adjusted_mode, crtc_state->limited_color_range ? HDMI_QUANTIZATION_RANGE_LIMITED : @@ -1938,11 +1938,12 @@ static bool intel_hdmi_source_bpc_possible(struct intel_display *display, int bp } } -static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector, +static bool intel_hdmi_sink_bpc_possible(struct drm_connector *_connector, int bpc, bool has_hdmi_sink, enum intel_output_format sink_format) { - const struct drm_display_info *info = &connector->display_info; + struct intel_connector *connector = to_intel_connector(_connector); + const struct drm_display_info *info = &connector->base.display_info; const struct drm_hdmi_info *hdmi = &info->hdmi; switch (bpc) { @@ -1971,12 +1972,13 @@ static bool intel_hdmi_sink_bpc_possible(struct drm_connector *connector, } static enum drm_mode_status -intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock, +intel_hdmi_mode_clock_valid(struct drm_connector *_connector, int clock, bool has_hdmi_sink, enum intel_output_format sink_format) { - struct intel_display *display = to_intel_display(connector->dev); - struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); + struct intel_hdmi *hdmi = intel_attached_hdmi(connector); enum drm_mode_status status = MODE_OK; int bpc; @@ -1991,7 +1993,8 @@ intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock, if (!intel_hdmi_source_bpc_possible(display, bpc)) continue; - if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, sink_format)) + if (!intel_hdmi_sink_bpc_possible(&connector->base, bpc, has_hdmi_sink, + sink_format)) continue; status = hdmi_port_clock_valid(hdmi, tmds_clock, true, has_hdmi_sink); @@ -2006,15 +2009,16 @@ intel_hdmi_mode_clock_valid(struct drm_connector *connector, int clock, } static enum drm_mode_status -intel_hdmi_mode_valid(struct drm_connector *connector, +intel_hdmi_mode_valid(struct drm_connector *_connector, const struct drm_display_mode *mode) { - struct intel_display *display = to_intel_display(connector->dev); - struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); + struct intel_hdmi *hdmi = intel_attached_hdmi(connector); enum drm_mode_status status; int clock = mode->clock; - int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq; - bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state); + int max_dotclk = display->cdclk.max_dotclk_freq; + bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->base.state); bool ycbcr_420_only; enum intel_output_format sink_format; @@ -2043,22 +2047,23 @@ intel_hdmi_mode_valid(struct drm_connector *connector, if (clock > 600000) return MODE_CLOCK_HIGH; - ycbcr_420_only = drm_mode_is_420_only(&connector->display_info, mode); + ycbcr_420_only = drm_mode_is_420_only(&connector->base.display_info, mode); if (ycbcr_420_only) sink_format = INTEL_OUTPUT_FORMAT_YCBCR420; else sink_format = INTEL_OUTPUT_FORMAT_RGB; - status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, sink_format); + status = intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink, sink_format); if (status != MODE_OK) { if (ycbcr_420_only || - !connector->ycbcr_420_allowed || - !drm_mode_is_420_also(&connector->display_info, mode)) + !connector->base.ycbcr_420_allowed || + !drm_mode_is_420_also(&connector->base.display_info, mode)) return status; sink_format = INTEL_OUTPUT_FORMAT_YCBCR420; - status = intel_hdmi_mode_clock_valid(connector, clock, has_hdmi_sink, sink_format); + status = intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink, + sink_format); if (status != MODE_OK) return status; } @@ -2069,16 +2074,16 @@ intel_hdmi_mode_valid(struct drm_connector *connector, bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state, int bpc, bool has_hdmi_sink) { - struct drm_atomic_state *state = crtc_state->uapi.state; - struct drm_connector_state *connector_state; - struct drm_connector *connector; + struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); + struct intel_digital_connector_state *connector_state; + struct intel_connector *connector; int i; - for_each_new_connector_in_state(state, connector, connector_state, i) { - if (connector_state->crtc != crtc_state->uapi.crtc) + for_each_new_intel_connector_in_state(state, connector, connector_state, i) { + if (connector_state->base.crtc != crtc_state->uapi.crtc) continue; - if (!intel_hdmi_sink_bpc_possible(connector, bpc, has_hdmi_sink, + if (!intel_hdmi_sink_bpc_possible(&connector->base, bpc, has_hdmi_sink, crtc_state->sink_format)) return false; } @@ -2206,7 +2211,7 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct drm_connector *connector = conn_state->connector; + struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct intel_digital_connector_state *intel_conn_state = to_intel_digital_connector_state(conn_state); @@ -2214,7 +2219,7 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder, return false; if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) - return connector->display_info.has_audio; + return connector->base.display_info.has_audio; else return intel_conn_state->force_audio == HDMI_AUDIO_ON; } @@ -2318,14 +2323,14 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, { struct intel_display *display = to_intel_display(encoder); struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; - struct drm_connector *connector = conn_state->connector; - struct drm_scdc *scdc = &connector->display_info.hdmi.scdc; + struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct drm_scdc *scdc = &connector->base.display_info.hdmi.scdc; int ret; if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; - if (!connector->interlace_allowed && + if (!connector->base.interlace_allowed && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) return -EINVAL; @@ -2420,24 +2425,26 @@ void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder) } static void -intel_hdmi_unset_edid(struct drm_connector *connector) +intel_hdmi_unset_edid(struct drm_connector *_connector) { - struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; intel_hdmi->dp_dual_mode.max_tmds_clock = 0; - drm_edid_free(to_intel_connector(connector)->detect_edid); - to_intel_connector(connector)->detect_edid = NULL; + drm_edid_free(connector->detect_edid); + connector->detect_edid = NULL; } static void -intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector) +intel_hdmi_dp_dual_mode_detect(struct drm_connector *_connector) { - struct intel_display *display = to_intel_display(connector->dev); - struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); + struct intel_hdmi *hdmi = intel_attached_hdmi(connector); struct intel_encoder *encoder = &hdmi_to_dig_port(hdmi)->base; - struct i2c_adapter *ddc = connector->ddc; + struct i2c_adapter *ddc = connector->base.ddc; enum drm_dp_dual_mode_type type; type = drm_dp_dual_mode_detect(display->drm, ddc); @@ -2452,7 +2459,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector) * if the port is a dual mode capable DP port. */ if (type == DRM_DP_DUAL_MODE_UNKNOWN) { - if (!connector->force && + if (!connector->base.force && intel_bios_encoder_supports_dp_dual_mode(encoder->devdata)) { drm_dbg_kms(display->drm, "Assuming DP dual mode adaptor presence based on VBT\n"); @@ -2484,34 +2491,35 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector) } static bool -intel_hdmi_set_edid(struct drm_connector *connector) +intel_hdmi_set_edid(struct drm_connector *_connector) { - struct intel_display *display = to_intel_display(connector->dev); - struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)); - struct i2c_adapter *ddc = connector->ddc; + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); + struct i2c_adapter *ddc = connector->base.ddc; intel_wakeref_t wakeref; const struct drm_edid *drm_edid; bool connected = false; wakeref = intel_display_power_get(display, POWER_DOMAIN_GMBUS); - drm_edid = drm_edid_read_ddc(connector, ddc); + drm_edid = drm_edid_read_ddc(&connector->base, ddc); if (!drm_edid && !intel_gmbus_is_forced_bit(ddc)) { drm_dbg_kms(display->drm, "HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n"); intel_gmbus_force_bit(ddc, true); - drm_edid = drm_edid_read_ddc(connector, ddc); + drm_edid = drm_edid_read_ddc(&connector->base, ddc); intel_gmbus_force_bit(ddc, false); } /* Below we depend on display info having been updated */ - drm_edid_connector_update(connector, drm_edid); + drm_edid_connector_update(&connector->base, drm_edid); - to_intel_connector(connector)->detect_edid = drm_edid; + connector->detect_edid = drm_edid; if (drm_edid_is_digital(drm_edid)) { - intel_hdmi_dp_dual_mode_detect(connector); + intel_hdmi_dp_dual_mode_detect(&connector->base); connected = true; } @@ -2519,28 +2527,29 @@ intel_hdmi_set_edid(struct drm_connector *connector) intel_display_power_put(display, POWER_DOMAIN_GMBUS, wakeref); cec_notifier_set_phys_addr(intel_hdmi->cec_notifier, - connector->display_info.source_physical_address); + connector->base.display_info.source_physical_address); return connected; } static enum drm_connector_status -intel_hdmi_detect(struct drm_connector *connector, bool force) +intel_hdmi_detect(struct drm_connector *_connector, bool force) { - struct intel_display *display = to_intel_display(connector->dev); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); enum drm_connector_status status = connector_status_disconnected; - struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)); + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base; intel_wakeref_t wakeref; drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); + connector->base.base.id, connector->base.name); if (!intel_display_device_enabled(display)) return connector_status_disconnected; if (!intel_display_driver_check_access(display)) - return connector->status; + return connector->base.status; wakeref = intel_display_power_get(display, POWER_DOMAIN_GMBUS); @@ -2548,9 +2557,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) !intel_digital_port_connected(encoder)) goto out; - intel_hdmi_unset_edid(connector); + intel_hdmi_unset_edid(&connector->base); - if (intel_hdmi_set_edid(connector)) + if (intel_hdmi_set_edid(&connector->base)) status = connector_status_connected; out: @@ -2563,49 +2572,54 @@ out: } static void -intel_hdmi_force(struct drm_connector *connector) +intel_hdmi_force(struct drm_connector *_connector) { - struct intel_display *display = to_intel_display(connector->dev); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); + connector->base.base.id, connector->base.name); if (!intel_display_driver_check_access(display)) return; - intel_hdmi_unset_edid(connector); + intel_hdmi_unset_edid(&connector->base); - if (connector->status != connector_status_connected) + if (connector->base.status != connector_status_connected) return; - intel_hdmi_set_edid(connector); + intel_hdmi_set_edid(&connector->base); } -static int intel_hdmi_get_modes(struct drm_connector *connector) +static int intel_hdmi_get_modes(struct drm_connector *_connector) { + struct intel_connector *connector = to_intel_connector(_connector); + /* drm_edid_connector_update() done in ->detect() or ->force() */ - return drm_edid_connector_add_modes(connector); + return drm_edid_connector_add_modes(&connector->base); } static int -intel_hdmi_connector_register(struct drm_connector *connector) +intel_hdmi_connector_register(struct drm_connector *_connector) { + struct intel_connector *connector = to_intel_connector(_connector); int ret; - ret = intel_connector_register(connector); + ret = intel_connector_register(&connector->base); if (ret) return ret; return ret; } -static void intel_hdmi_connector_unregister(struct drm_connector *connector) +static void intel_hdmi_connector_unregister(struct drm_connector *_connector) { - struct cec_notifier *n = intel_attached_hdmi(to_intel_connector(connector))->cec_notifier; + struct intel_connector *connector = to_intel_connector(_connector); + struct cec_notifier *n = intel_attached_hdmi(connector)->cec_notifier; cec_notifier_conn_unregister(n); - intel_connector_unregister(connector); + intel_connector_unregister(&connector->base); } static const struct drm_connector_funcs intel_hdmi_connector_funcs = { @@ -2621,15 +2635,16 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = { .atomic_duplicate_state = intel_digital_connector_duplicate_state, }; -static int intel_hdmi_connector_atomic_check(struct drm_connector *connector, +static int intel_hdmi_connector_atomic_check(struct drm_connector *_connector, struct drm_atomic_state *state) { - struct intel_display *display = to_intel_display(connector->dev); + struct intel_connector *connector = to_intel_connector(_connector); + struct intel_display *display = to_intel_display(connector); if (HAS_DDI(display)) - return intel_digital_connector_atomic_check(connector, state); + return intel_digital_connector_atomic_check(&connector->base, state); else - return g4x_hdmi_connector_atomic_check(connector, state); + return g4x_hdmi_connector_atomic_check(&connector->base, state); } static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { @@ -2639,22 +2654,23 @@ static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs }; static void -intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) +intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *_connector) { + struct intel_connector *connector = to_intel_connector(_connector); struct intel_display *display = to_intel_display(intel_hdmi); - intel_attach_force_audio_property(connector); - intel_attach_broadcast_rgb_property(connector); - intel_attach_aspect_ratio_property(connector); + intel_attach_force_audio_property(&connector->base); + intel_attach_broadcast_rgb_property(&connector->base); + intel_attach_aspect_ratio_property(&connector->base); - intel_attach_hdmi_colorspace_property(connector); - drm_connector_attach_content_type_property(connector); + intel_attach_hdmi_colorspace_property(&connector->base); + drm_connector_attach_content_type_property(&connector->base); if (DISPLAY_VER(display) >= 10) - drm_connector_attach_hdr_output_metadata_property(connector); + drm_connector_attach_hdr_output_metadata_property(&connector->base); if (!HAS_GMCH(display)) - drm_connector_attach_max_bpc_property(connector, 8, 12); + drm_connector_attach_max_bpc_property(&connector->base, 8, 12); } /* @@ -2676,25 +2692,26 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c * True on success, false on failure. */ bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, - struct drm_connector *connector, + struct drm_connector *_connector, bool high_tmds_clock_ratio, bool scrambling) { + struct intel_connector *connector = to_intel_connector(_connector); struct intel_display *display = to_intel_display(encoder); struct drm_scrambling *sink_scrambling = - &connector->display_info.hdmi.scdc.scrambling; + &connector->base.display_info.hdmi.scdc.scrambling; if (!sink_scrambling->supported) return true; drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n", - connector->base.id, connector->name, + connector->base.base.id, connector->base.name, str_yes_no(scrambling), high_tmds_clock_ratio ? 40 : 10); /* Set TMDS bit clock ratio to 1/40 or 1/10, and enable/disable scrambling */ - return drm_scdc_set_high_tmds_clock_ratio(connector, high_tmds_clock_ratio) && - drm_scdc_set_scrambling(connector, scrambling); + return drm_scdc_set_high_tmds_clock_ratio(&connector->base, high_tmds_clock_ratio) && + drm_scdc_set_scrambling(&connector->base, scrambling); } static u8 chv_encoder_to_ddc_pin(struct intel_encoder *encoder) -- 2.51.0 From 090a47b4cd2800164c4e6f3b333e8534736960c0 Mon Sep 17 00:00:00 2001 From: Jiajia Liu Date: Wed, 23 Apr 2025 15:37:30 +0800 Subject: [PATCH 15/16] drm/i915/pch: fix warning for coffeelake on SunrisePoint PCH i915/pch reports a warning on a mini PC which has a CoffeeLake-S GT2 [UHD Graphics 630] [8086:3e92] and an ISA bridge - H110 LPC Controller [8086:a143]. [5.608723] i915 0000:00:02.0: [drm] Found coffeelake (device ID 3e92) integrated display version 9.00 stepping N/A [5.608969] ------------[ cut here ]------------ [5.608972] i915 0000:00:02.0: [drm] drm_WARN_ON(!display->platform.skylake && !display->platform.kabylake) [5.608995] WARNING: CPU: 3 PID: 440 at drivers/gpu/drm/i915/display/intel_pch.c:126 intel_pch_type+0x1af/0xae0 [i915] [5.609317] CPU: 3 UID: 0 PID: 440 Comm: (udev-worker) Not tainted 6.15.0-rc3-drm-tip-2fa6469c618d #3 PREEMPT(voluntary) Signed-off-by: Jiajia Liu Reviewed-by: Rodrigo Vivi Link: https://lore.kernel.org/r/20250423073730.585181-1-liujiajia@kylinos.cn Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_pch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_pch.c b/drivers/gpu/drm/i915/display/intel_pch.c index 5035b63a4889..469e8a3cfb49 100644 --- a/drivers/gpu/drm/i915/display/intel_pch.c +++ b/drivers/gpu/drm/i915/display/intel_pch.c @@ -125,7 +125,8 @@ intel_pch_type(const struct intel_display *display, unsigned short id) drm_dbg_kms(display->drm, "Found SunrisePoint PCH\n"); drm_WARN_ON(display->drm, !display->platform.skylake && - !display->platform.kabylake); + !display->platform.kabylake && + !display->platform.coffeelake); return PCH_SPT; case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE: drm_dbg_kms(display->drm, "Found SunrisePoint LP PCH\n"); -- 2.51.0 From 7d585426a6538a717f55a1bb0b614d465bd03805 Mon Sep 17 00:00:00 2001 From: Arun R Murthy Date: Thu, 24 Apr 2025 20:45:14 +0530 Subject: [PATCH 16/16] drm/display/dp: Export fn to calculate link symbol cycles Unify the function to calculate the link symbol cycles for both dsc and non-dsc case and export the function so that it can be used in the respective platform display drivers for other calculations. v2: unify the fn for both dsc and non-dsc case (Imre) v3: rename drm_dp_link_symbol_cycles to drm_dp_link_data_symbol_cycles retain slice_eoc_cycles as is (Imre) v4: Expose only drm_dp_link_symbol_cycles() (Imre) v6: Add slice pixels which was removed unknowingly (Vinod) Signed-off-by: Arun R Murthy Reviewed-by: Imre Deak Reviewed-by: Vinod Govindapillai Acked-by: Maarten Lankhorst Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250424-hblank-v7-1-8b002f1506cc@intel.com --- drivers/gpu/drm/display/drm_dp_helper.c | 52 ++++++++++++++++--------- include/drm/display/drm_dp_helper.h | 2 + 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index f5c596234729..8f774221eeb3 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -4324,8 +4324,9 @@ EXPORT_SYMBOL(drm_panel_dp_aux_backlight); #endif /* See DP Standard v2.1 2.6.4.4.1.1, 2.8.4.4, 2.8.7 */ -static int drm_dp_link_symbol_cycles(int lane_count, int pixels, int bpp_x16, - int symbol_size, bool is_mst) +static int drm_dp_link_data_symbol_cycles(int lane_count, int pixels, + int bpp_x16, int symbol_size, + bool is_mst) { int cycles = DIV_ROUND_UP(pixels * bpp_x16, 16 * symbol_size * lane_count); int align = is_mst ? 4 / lane_count : 1; @@ -4333,22 +4334,42 @@ static int drm_dp_link_symbol_cycles(int lane_count, int pixels, int bpp_x16, return ALIGN(cycles, align); } -static int drm_dp_link_dsc_symbol_cycles(int lane_count, int pixels, int slice_count, - int bpp_x16, int symbol_size, bool is_mst) +/** + * drm_dp_link_symbol_cycles - calculate the link symbol count with/without dsc + * @lane_count: DP link lane count + * @pixels: number of pixels in a scanline + * @dsc_slice_count: number of slices for DSC or '0' for non-DSC + * @bpp_x16: bits per pixel in .4 binary fixed format + * @symbol_size: DP symbol size + * @is_mst: %true for MST and %false for SST + * + * Calculate the link symbol cycles for both DSC (@dsc_slice_count !=0) and + * non-DSC case (@dsc_slice_count == 0) and return the count. + */ +int drm_dp_link_symbol_cycles(int lane_count, int pixels, int dsc_slice_count, + int bpp_x16, int symbol_size, bool is_mst) { + int slice_count = dsc_slice_count ? : 1; int slice_pixels = DIV_ROUND_UP(pixels, slice_count); - int slice_data_cycles = drm_dp_link_symbol_cycles(lane_count, slice_pixels, - bpp_x16, symbol_size, is_mst); - int slice_eoc_cycles = is_mst ? 4 / lane_count : 1; + int slice_data_cycles = drm_dp_link_data_symbol_cycles(lane_count, + slice_pixels, + bpp_x16, + symbol_size, + is_mst); + int slice_eoc_cycles = 0; + + if (dsc_slice_count) + slice_eoc_cycles = is_mst ? 4 / lane_count : 1; return slice_count * (slice_data_cycles + slice_eoc_cycles); } +EXPORT_SYMBOL(drm_dp_link_symbol_cycles); /** * drm_dp_bw_overhead - Calculate the BW overhead of a DP link stream * @lane_count: DP link lane count * @hactive: pixel count of the active period in one scanline of the stream - * @dsc_slice_count: DSC slice count if @flags/DRM_DP_LINK_BW_OVERHEAD_DSC is set + * @dsc_slice_count: number of slices for DSC or '0' for non-DSC * @bpp_x16: bits per pixel in .4 binary fixed point * @flags: DRM_DP_OVERHEAD_x flags * @@ -4362,7 +4383,7 @@ static int drm_dp_link_dsc_symbol_cycles(int lane_count, int pixels, int slice_c * as well as the stream's * - @hactive timing * - @bpp_x16 color depth - * - compression mode (@flags / %DRM_DP_OVERHEAD_DSC). + * - compression mode (@dsc_slice_count != 0) * Note that this overhead doesn't account for the 8b/10b, 128b/132b * channel coding efficiency, for that see * @drm_dp_link_bw_channel_coding_efficiency(). @@ -4417,15 +4438,10 @@ int drm_dp_bw_overhead(int lane_count, int hactive, WARN_ON((flags & DRM_DP_BW_OVERHEAD_UHBR) && (flags & DRM_DP_BW_OVERHEAD_FEC)); - if (flags & DRM_DP_BW_OVERHEAD_DSC) - symbol_cycles = drm_dp_link_dsc_symbol_cycles(lane_count, hactive, - dsc_slice_count, - bpp_x16, symbol_size, - is_mst); - else - symbol_cycles = drm_dp_link_symbol_cycles(lane_count, hactive, - bpp_x16, symbol_size, - is_mst); + symbol_cycles = drm_dp_link_symbol_cycles(lane_count, hactive, + dsc_slice_count, + bpp_x16, symbol_size, + is_mst); return DIV_ROUND_UP_ULL(mul_u32_u32(symbol_cycles * symbol_size * lane_count, overhead * 16), diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h index 89a34dff85a4..36ca21d6a399 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -879,5 +879,7 @@ int drm_dp_bw_channel_coding_efficiency(bool is_uhbr); int drm_dp_max_dprx_data_rate(int max_link_rate, int max_lanes); ssize_t drm_dp_vsc_sdp_pack(const struct drm_dp_vsc_sdp *vsc, struct dp_sdp *sdp); +int drm_dp_link_symbol_cycles(int lane_count, int pixels, int dsc_slice_count, + int bpp_x16, int symbol_size, bool is_mst); #endif /* _DRM_DP_HELPER_H_ */ -- 2.51.0