mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-08 11:41:37 -04:00
Merge tag 'drm-intel-next-fixes-2025-05-22' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next
- Fix for Thunderbolt sink disconnect on MTL/ARL/LNL - Fix for DDI port clock select mask on PTL+ - Add error checks for alloc_ordered_workqueue() and alloc_workqueue() in display Signed-off-by: Dave Airlie <airlied@redhat.com> From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://lore.kernel.org/r/aC7LQUtxXKgOVTVt@jlahtine-mobl
This commit is contained in:
@@ -2763,9 +2763,9 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
|
||||
val |= XELPDP_FORWARD_CLOCK_UNGATE;
|
||||
|
||||
if (!is_dp && is_hdmi_frl(port_clock))
|
||||
val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_DIV18CLK);
|
||||
val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_DIV18CLK);
|
||||
else
|
||||
val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
|
||||
val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
|
||||
|
||||
/* TODO: HDMI FRL */
|
||||
/* DP2.0 10G and 20G rates enable MPLLA*/
|
||||
@@ -2776,7 +2776,7 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
|
||||
|
||||
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
|
||||
XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE |
|
||||
XELPDP_DDI_CLOCK_SELECT_MASK | XELPDP_SSC_ENABLE_PLLA |
|
||||
XELPDP_DDI_CLOCK_SELECT_MASK(display) | XELPDP_SSC_ENABLE_PLLA |
|
||||
XELPDP_SSC_ENABLE_PLLB, val);
|
||||
}
|
||||
|
||||
@@ -3099,10 +3099,7 @@ int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
|
||||
|
||||
val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port));
|
||||
|
||||
if (DISPLAY_VER(display) >= 30)
|
||||
clock = REG_FIELD_GET(XE3_DDI_CLOCK_SELECT_MASK, val);
|
||||
else
|
||||
clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
|
||||
clock = XELPDP_DDI_CLOCK_SELECT_GET(display, val);
|
||||
|
||||
drm_WARN_ON(display->drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE));
|
||||
drm_WARN_ON(display->drm, !(val & XELPDP_TBT_CLOCK_REQUEST));
|
||||
@@ -3170,13 +3167,9 @@ static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
|
||||
* clock muxes, gating and SSC
|
||||
*/
|
||||
|
||||
if (DISPLAY_VER(display) >= 30) {
|
||||
mask = XE3_DDI_CLOCK_SELECT_MASK;
|
||||
val |= XE3_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(display, crtc_state->port_clock));
|
||||
} else {
|
||||
mask = XELPDP_DDI_CLOCK_SELECT_MASK;
|
||||
val |= XELPDP_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(display, crtc_state->port_clock));
|
||||
}
|
||||
mask = XELPDP_DDI_CLOCK_SELECT_MASK(display);
|
||||
val |= XELPDP_DDI_CLOCK_SELECT_PREP(display,
|
||||
intel_mtl_tbt_clock_select(display, crtc_state->port_clock));
|
||||
|
||||
mask |= XELPDP_FORWARD_CLOCK_UNGATE;
|
||||
val |= XELPDP_FORWARD_CLOCK_UNGATE;
|
||||
@@ -3289,7 +3282,7 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder)
|
||||
|
||||
/* 7. Program PORT_CLOCK_CTL register to disable and gate clocks. */
|
||||
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
|
||||
XELPDP_DDI_CLOCK_SELECT_MASK, 0);
|
||||
XELPDP_DDI_CLOCK_SELECT_MASK(display), 0);
|
||||
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
|
||||
XELPDP_FORWARD_CLOCK_UNGATE, 0);
|
||||
|
||||
@@ -3338,7 +3331,7 @@ static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder)
|
||||
* 5. Program PORT CLOCK CTRL register to disable and gate clocks
|
||||
*/
|
||||
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port),
|
||||
XELPDP_DDI_CLOCK_SELECT_MASK |
|
||||
XELPDP_DDI_CLOCK_SELECT_MASK(display) |
|
||||
XELPDP_FORWARD_CLOCK_UNGATE, 0);
|
||||
|
||||
/* 6. Program DDI_CLK_VALFREQ to 0. */
|
||||
@@ -3367,7 +3360,7 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder,
|
||||
* handling is done via the standard shared DPLL framework.
|
||||
*/
|
||||
val = intel_de_read(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port));
|
||||
clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
|
||||
clock = XELPDP_DDI_CLOCK_SELECT_GET(display, val);
|
||||
|
||||
if (clock == XELPDP_DDI_CLOCK_SELECT_MAXPCLK ||
|
||||
clock == XELPDP_DDI_CLOCK_SELECT_DIV18CLK)
|
||||
|
||||
@@ -192,10 +192,17 @@
|
||||
|
||||
#define XELPDP_TBT_CLOCK_REQUEST REG_BIT(19)
|
||||
#define XELPDP_TBT_CLOCK_ACK REG_BIT(18)
|
||||
#define XELPDP_DDI_CLOCK_SELECT_MASK REG_GENMASK(15, 12)
|
||||
#define XE3_DDI_CLOCK_SELECT_MASK REG_GENMASK(16, 12)
|
||||
#define XELPDP_DDI_CLOCK_SELECT(val) REG_FIELD_PREP(XELPDP_DDI_CLOCK_SELECT_MASK, val)
|
||||
#define XE3_DDI_CLOCK_SELECT(val) REG_FIELD_PREP(XE3_DDI_CLOCK_SELECT_MASK, val)
|
||||
#define _XELPDP_DDI_CLOCK_SELECT_MASK REG_GENMASK(15, 12)
|
||||
#define _XE3_DDI_CLOCK_SELECT_MASK REG_GENMASK(16, 12)
|
||||
#define XELPDP_DDI_CLOCK_SELECT_MASK(display) (DISPLAY_VER(display) >= 30 ? \
|
||||
_XE3_DDI_CLOCK_SELECT_MASK : _XELPDP_DDI_CLOCK_SELECT_MASK)
|
||||
#define XELPDP_DDI_CLOCK_SELECT_PREP(display, val) (DISPLAY_VER(display) >= 30 ? \
|
||||
REG_FIELD_PREP(_XE3_DDI_CLOCK_SELECT_MASK, (val)) : \
|
||||
REG_FIELD_PREP(_XELPDP_DDI_CLOCK_SELECT_MASK, (val)))
|
||||
#define XELPDP_DDI_CLOCK_SELECT_GET(display, val) (DISPLAY_VER(display) >= 30 ? \
|
||||
REG_FIELD_GET(_XE3_DDI_CLOCK_SELECT_MASK, (val)) : \
|
||||
REG_FIELD_GET(_XELPDP_DDI_CLOCK_SELECT_MASK, (val)))
|
||||
|
||||
#define XELPDP_DDI_CLOCK_SELECT_NONE 0x0
|
||||
#define XELPDP_DDI_CLOCK_SELECT_MAXPCLK 0x8
|
||||
#define XELPDP_DDI_CLOCK_SELECT_DIV18CLK 0x9
|
||||
|
||||
@@ -244,31 +244,45 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
|
||||
intel_dmc_init(display);
|
||||
|
||||
display->wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
|
||||
if (!display->wq.modeset) {
|
||||
ret = -ENOMEM;
|
||||
goto cleanup_vga_client_pw_domain_dmc;
|
||||
}
|
||||
|
||||
display->wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
|
||||
WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);
|
||||
if (!display->wq.flip) {
|
||||
ret = -ENOMEM;
|
||||
goto cleanup_wq_modeset;
|
||||
}
|
||||
|
||||
display->wq.cleanup = alloc_workqueue("i915_cleanup", WQ_HIGHPRI, 0);
|
||||
if (!display->wq.cleanup) {
|
||||
ret = -ENOMEM;
|
||||
goto cleanup_wq_flip;
|
||||
}
|
||||
|
||||
intel_mode_config_init(display);
|
||||
|
||||
ret = intel_cdclk_init(display);
|
||||
if (ret)
|
||||
goto cleanup_vga_client_pw_domain_dmc;
|
||||
goto cleanup_wq_cleanup;
|
||||
|
||||
ret = intel_color_init(display);
|
||||
if (ret)
|
||||
goto cleanup_vga_client_pw_domain_dmc;
|
||||
goto cleanup_wq_cleanup;
|
||||
|
||||
ret = intel_dbuf_init(display);
|
||||
if (ret)
|
||||
goto cleanup_vga_client_pw_domain_dmc;
|
||||
goto cleanup_wq_cleanup;
|
||||
|
||||
ret = intel_bw_init(display);
|
||||
if (ret)
|
||||
goto cleanup_vga_client_pw_domain_dmc;
|
||||
goto cleanup_wq_cleanup;
|
||||
|
||||
ret = intel_pmdemand_init(display);
|
||||
if (ret)
|
||||
goto cleanup_vga_client_pw_domain_dmc;
|
||||
goto cleanup_wq_cleanup;
|
||||
|
||||
intel_init_quirks(display);
|
||||
|
||||
@@ -276,6 +290,12 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_wq_cleanup:
|
||||
destroy_workqueue(display->wq.cleanup);
|
||||
cleanup_wq_flip:
|
||||
destroy_workqueue(display->wq.flip);
|
||||
cleanup_wq_modeset:
|
||||
destroy_workqueue(display->wq.modeset);
|
||||
cleanup_vga_client_pw_domain_dmc:
|
||||
intel_dmc_fini(display);
|
||||
intel_power_domains_driver_remove(display);
|
||||
|
||||
@@ -4532,6 +4532,23 @@ intel_dp_mst_disconnect(struct intel_dp *intel_dp)
|
||||
static bool
|
||||
intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *esi)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(intel_dp);
|
||||
|
||||
/*
|
||||
* Display WA for HSD #13013007775: mtl/arl/lnl
|
||||
* Read the sink count and link service IRQ registers in separate
|
||||
* transactions to prevent disconnecting the sink on a TBT link
|
||||
* inadvertently.
|
||||
*/
|
||||
if (IS_DISPLAY_VER(display, 14, 20) && !display->platform.battlemage) {
|
||||
if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 3) != 3)
|
||||
return false;
|
||||
|
||||
/* DP_SINK_COUNT_ESI + 3 == DP_LINK_SERVICE_IRQ_VECTOR_ESI0 */
|
||||
return drm_dp_dpcd_readb(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0,
|
||||
&esi[3]) == 1;
|
||||
}
|
||||
|
||||
return drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 4) == 4;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user