From 0e8e272f1368b26053440fcf3b0ef0693f9e706e Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Fri, 30 Oct 2020 14:15:43 -0700 Subject: [PATCH 01/66] drm/i915/ehl: Remove invalid PCI ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the EHL PCI IDs from BSpec. Remove the invalid ones. Cc: Ville Syrjälä Signed-off-by: Anusha Srivatsa Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201102193034.28055-1-anusha.srivatsa@intel.com --- include/drm/i915_pciids.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 3b5ed1e4f3ec..28428e08a8d3 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -584,7 +584,6 @@ /* EHL */ #define INTEL_EHL_IDS(info) \ - INTEL_VGA_DEVICE(0x4500, info), \ INTEL_VGA_DEVICE(0x4571, info), \ INTEL_VGA_DEVICE(0x4551, info), \ INTEL_VGA_DEVICE(0x4541, info), \ From ba8a5cb234ba3bf0a585fd38e5f36d7e7ce33661 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 4 Nov 2020 03:00:00 +0200 Subject: [PATCH 02/66] drm/i915/tgl: Fix typo during output setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a typo that led to some MST short pulse event handling issue (the short pulse event was handled for both encoder instances, each having its own state). Fixes: 1d8ca002456b6 ("drm/i915: Add PORT_TCn aliases to enum port") Cc: Ville Syrjälä Cc: Lucas De Marchi Signed-off-by: Imre Deak Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20201104010000.4165574-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 81305c6483c7..6b224d3f34a8 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -17229,7 +17229,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv) intel_ddi_init(dev_priv, PORT_B); intel_ddi_init(dev_priv, PORT_TC1); intel_ddi_init(dev_priv, PORT_TC2); - intel_ddi_init(dev_priv, PORT_TC2); + intel_ddi_init(dev_priv, PORT_TC3); intel_ddi_init(dev_priv, PORT_TC4); intel_ddi_init(dev_priv, PORT_TC5); intel_ddi_init(dev_priv, PORT_TC6); From 66186acbd94c4fdd43012a1f075ca381ada56150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Mon, 2 Nov 2020 14:10:48 -0800 Subject: [PATCH 03/66] drm/i915/display: Use initial_fastset_check() to compute and apply the initial PSR state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the previous approach to force compute the initial PSR state after i915 take over from firmware by the better and recently added initial_fastset_check() hook. Cc: Imre Deak Signed-off-by: José Roberto de Souza Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20201102221048.104294-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_atomic.c | 1 - drivers/gpu/drm/i915/display/intel_display.c | 2 - drivers/gpu/drm/i915/display/intel_dp.c | 6 +++ drivers/gpu/drm/i915/display/intel_psr.c | 41 -------------------- drivers/gpu/drm/i915/display/intel_psr.h | 4 -- drivers/gpu/drm/i915/i915_drv.h | 1 - 6 files changed, 6 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 86be032bcf96..63d8d6840655 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -133,7 +133,6 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn, struct drm_crtc_state *crtc_state; intel_hdcp_atomic_check(conn, old_state, new_state); - intel_psr_atomic_check(conn, old_state, new_state); if (!new_state->crtc) return 0; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 19a4d81558c5..8c4687b19814 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -18373,8 +18373,6 @@ int intel_modeset_init(struct drm_i915_private *i915) intel_init_ipc(i915); - intel_psr_set_force_mode_changed(i915->psr.dp); - return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index cf09aca7607b..3b0dbda5919a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3778,6 +3778,12 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, return false; } + if (CAN_PSR(i915) && intel_dp_is_edp(intel_dp)) { + drm_dbg_kms(&i915->drm, "Forcing full modeset to compute PSR state\n"); + crtc_state->uapi.mode_changed = true; + return false; + } + return true; } diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 1576c3722d0b..b3631b722de3 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1024,8 +1024,6 @@ void intel_psr_enable(struct intel_dp *intel_dp, if (!CAN_PSR(dev_priv) || dev_priv->psr.dp != intel_dp) return; - dev_priv->psr.force_mode_changed = false; - if (!crtc_state->has_psr) return; @@ -1334,8 +1332,6 @@ void intel_psr_update(struct intel_dp *intel_dp, if (!CAN_PSR(dev_priv) || READ_ONCE(psr->dp) != intel_dp) return; - dev_priv->psr.force_mode_changed = false; - mutex_lock(&dev_priv->psr.lock); enable = crtc_state->has_psr; @@ -1869,40 +1865,3 @@ bool intel_psr_enabled(struct intel_dp *intel_dp) return ret; } - -void intel_psr_atomic_check(struct drm_connector *connector, - struct drm_connector_state *old_state, - struct drm_connector_state *new_state) -{ - struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_connector *intel_connector; - struct intel_digital_port *dig_port; - struct drm_crtc_state *crtc_state; - - if (!CAN_PSR(dev_priv) || !new_state->crtc || - !dev_priv->psr.force_mode_changed) - return; - - intel_connector = to_intel_connector(connector); - dig_port = enc_to_dig_port(to_intel_encoder(new_state->best_encoder)); - if (dev_priv->psr.dp != &dig_port->dp) - return; - - crtc_state = drm_atomic_get_new_crtc_state(new_state->state, - new_state->crtc); - crtc_state->mode_changed = true; -} - -void intel_psr_set_force_mode_changed(struct intel_dp *intel_dp) -{ - struct drm_i915_private *dev_priv; - - if (!intel_dp) - return; - - dev_priv = dp_to_i915(intel_dp); - if (!CAN_PSR(dev_priv) || intel_dp != dev_priv->psr.dp) - return; - - dev_priv->psr.force_mode_changed = true; -} diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index 3eca9dcec3c0..0a517978e8af 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -43,10 +43,6 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp); int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state, u32 *out_value); bool intel_psr_enabled(struct intel_dp *intel_dp); -void intel_psr_atomic_check(struct drm_connector *connector, - struct drm_connector_state *old_state, - struct drm_connector_state *new_state); -void intel_psr_set_force_mode_changed(struct intel_dp *intel_dp); int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d7765b31fbef..80940887d250 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -508,7 +508,6 @@ struct i915_psr { bool dc3co_enabled; u32 dc3co_exit_delay; struct delayed_work dc3co_work; - bool force_mode_changed; struct drm_dp_vsc_sdp vsc; }; From fcc6aa8f3e9695a4dfb6e3c4c3002adba21a2ced Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Wed, 4 Nov 2020 10:36:55 +0530 Subject: [PATCH 04/66] drm/i915/ehl: Implement W/A 22010492432 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per W/A implemented for TGL to program half of the nominal DCO divider fraction value which is also applicable on EHL. Changes since V2: - Apply stepping B0 till FOREVER - B0 - revid update as per Bspec 29153 Changes since V1: - ehl_ used as to keep earliest platform prefix - WA required B0 stepping onwards Cc: Deak Imre Signed-off-by: Tejas Upadhyay Reviewed-by: Imre Deak Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20201104050655.171185-1-tejaskumarx.surendrakumar.upadhyay@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 13 ++++++++----- drivers/gpu/drm/i915/i915_drv.h | 1 + 2 files changed, 9 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 eaef7a2d041f..a95e6a2ac698 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2636,13 +2636,16 @@ static bool cnl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state) } /* - * Display WA #22010492432: tgl + * Display WA #22010492432: ehl, tgl * Program half of the nominal DCO divider fraction value. */ static bool -tgl_combo_pll_div_frac_wa_needed(struct drm_i915_private *i915) +ehl_combo_pll_div_frac_wa_needed(struct drm_i915_private *i915) { - return IS_TIGERLAKE(i915) && i915->dpll.ref_clks.nssc == 38400; + return ((IS_PLATFORM(i915, INTEL_ELKHARTLAKE) && + IS_JSL_EHL_REVID(i915, EHL_REVID_B0, REVID_FOREVER)) || + IS_TIGERLAKE(i915)) && + i915->dpll.ref_clks.nssc == 38400; } static int __cnl_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, @@ -2696,7 +2699,7 @@ static int __cnl_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, dco_fraction = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >> DPLL_CFGCR0_DCO_FRACTION_SHIFT; - if (tgl_combo_pll_div_frac_wa_needed(dev_priv)) + if (ehl_combo_pll_div_frac_wa_needed(dev_priv)) dco_fraction *= 2; dco_freq += (dco_fraction * ref_clock) / 0x8000; @@ -3086,7 +3089,7 @@ static void icl_calc_dpll_state(struct drm_i915_private *i915, memset(pll_state, 0, sizeof(*pll_state)); - if (tgl_combo_pll_div_frac_wa_needed(i915)) + if (ehl_combo_pll_div_frac_wa_needed(i915)) dco_fraction = DIV_ROUND_CLOSEST(dco_fraction, 2); pll_state->cfgcr0 = DPLL_CFGCR0_DCO_FRACTION(dco_fraction) | diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 80940887d250..bfc8e4575e69 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1559,6 +1559,7 @@ extern const struct i915_rev_steppings kbl_revids[]; (IS_ICELAKE(p) && IS_REVID(p, since, until)) #define EHL_REVID_A0 0x0 +#define EHL_REVID_B0 0x1 #define IS_JSL_EHL_REVID(p, since, until) \ (IS_JSL_EHL(p) && IS_REVID(p, since, until)) From 04057a1afc756a95143695b7e35420ee0f540c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 30 Oct 2020 18:41:24 +0200 Subject: [PATCH 05/66] drm/i915: Sort EHL/JSL PCI IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sort the EHL/JSL PCI IDs numerically. Some order seems better than randomness. v2: Deal with the JSL vs. EHL split v3: Rebase due to 0x4500 removal Reviewed-by: Anusha Srivatsa #v1 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201030164124.16922-1-ville.syrjala@linux.intel.com --- include/drm/i915_pciids.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 28428e08a8d3..931e46191047 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -584,19 +584,19 @@ /* EHL */ #define INTEL_EHL_IDS(info) \ - INTEL_VGA_DEVICE(0x4571, info), \ - INTEL_VGA_DEVICE(0x4551, info), \ INTEL_VGA_DEVICE(0x4541, info), \ + INTEL_VGA_DEVICE(0x4551, info), \ + INTEL_VGA_DEVICE(0x4555, info), \ INTEL_VGA_DEVICE(0x4557, info), \ - INTEL_VGA_DEVICE(0x4555, info) + INTEL_VGA_DEVICE(0x4571, info) /* JSL */ #define INTEL_JSL_IDS(info) \ - INTEL_VGA_DEVICE(0x4E71, info), \ - INTEL_VGA_DEVICE(0x4E61, info), \ - INTEL_VGA_DEVICE(0x4E57, info), \ + INTEL_VGA_DEVICE(0x4E51, info), \ INTEL_VGA_DEVICE(0x4E55, info), \ - INTEL_VGA_DEVICE(0x4E51, info) + INTEL_VGA_DEVICE(0x4E57, info), \ + INTEL_VGA_DEVICE(0x4E61, info), \ + INTEL_VGA_DEVICE(0x4E71, info) /* TGL */ #define INTEL_TGL_12_GT1_IDS(info) \ From 54defc10c4d973d610431e02794bc77405d06e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 3 Nov 2020 17:30:26 +0200 Subject: [PATCH 06/66] drm/i915: Include fb modifier in state dumps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To help diagnose modifier related issues let's include that information in the various state dumps. Cc: Simon Ser Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201103153026.16566-1-ville.syrjala@linux.intel.com Acked-by: Simon Ser --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8c4687b19814..6faca1e739c8 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -13218,11 +13218,11 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state) } drm_dbg_kms(&i915->drm, - "[PLANE:%d:%s] fb: [FB:%d] %ux%u format = %s, visible: %s\n", + "[PLANE:%d:%s] fb: [FB:%d] %ux%u format = %s modifier = 0x%llx, visible: %s\n", plane->base.base.id, plane->base.name, fb->base.id, fb->width, fb->height, drm_get_format_name(fb->format->format, &format_name), - yesno(plane_state->uapi.visible)); + fb->modifier, yesno(plane_state->uapi.visible)); drm_dbg_kms(&i915->drm, "\trotation: 0x%x, scaler: %d\n", plane_state->hw.rotation, plane_state->scaler_id); if (plane_state->uapi.visible) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index cfb4c1474982..00b79593bcef 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -773,8 +773,9 @@ static void intel_plane_uapi_info(struct seq_file *m, struct intel_plane *plane) plane_rotation(rot_str, sizeof(rot_str), plane_state->uapi.rotation); - seq_printf(m, "\t\tuapi: fb=%d,%s,%dx%d, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", + seq_printf(m, "\t\tuapi: [FB:%d] %s,0x%llx,%dx%d, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", fb ? fb->base.id : 0, fb ? format_name.str : "n/a", + fb ? fb->modifier : 0, fb ? fb->width : 0, fb ? fb->height : 0, DRM_RECT_FP_ARG(&src), DRM_RECT_ARG(&dst), @@ -797,9 +798,9 @@ static void intel_plane_hw_info(struct seq_file *m, struct intel_plane *plane) plane_rotation(rot_str, sizeof(rot_str), plane_state->hw.rotation); - seq_printf(m, "\t\thw: fb=%d,%s,%dx%d, visible=%s, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", + seq_printf(m, "\t\thw: [FB:%d] %s,0x%llx,%dx%d, visible=%s, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", fb->base.id, format_name.str, - fb->width, fb->height, + fb->modifier, fb->width, fb->height, yesno(plane_state->uapi.visible), DRM_RECT_FP_ARG(&plane_state->uapi.src), DRM_RECT_ARG(&plane_state->uapi.dst), From 11ffe972479e015d6e36017b6d51707cf746a798 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 6 Nov 2020 13:00:06 -0800 Subject: [PATCH 07/66] drm/i915/dg1: map/unmap pll clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DG1 uses 2 registers for the ddi clock mapping, with PHY A and B using DPCLKA_CFGCR0 and PHY C and D using DPCLKA1_CFGCR0. Hide this behind a single macro that chooses the correct register according to the phy being accessed, use the correct bitfields for each pll/phy and implement separate functions for DG1 since it doesn't share much with ICL/TGL anymore. The previous values were correct for PHY A and B since they were using the same register as before and the bitfields were matching. v2: Add comment and try to simplify DG1_DPCLKA* macros by reusing previous ones v3: - Fix DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK() after wrong macro reuse - Move phy -> id map to a separate macro (Aditya) - Remove DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK where not required (Aditya) - Use drm_WARN_ON Cc: José Roberto de Souza Cc: Clinton Taylor Cc: Matt Roper Cc: Aditya Swarup Signed-off-by: Lucas De Marchi Reviewed-by: Aditya Swarup Link: https://patchwork.freedesktop.org/patch/msgid/20201106210006.837953-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 91 +++++++++++++++++++- drivers/gpu/drm/i915/display/intel_display.c | 24 +++++- drivers/gpu/drm/i915/i915_reg.h | 24 ++++++ 3 files changed, 135 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 19b16517a502..36a4a1f4d775 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2970,6 +2970,40 @@ static u32 icl_dpclka_cfgcr0_clk_off(struct drm_i915_private *dev_priv, return 0; } +static void dg1_map_plls_to_ports(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_shared_dpll *pll = crtc_state->shared_dpll; + enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + u32 val; + + /* + * If we fail this, something went very wrong: first 2 PLLs should be + * used by first 2 phys and last 2 PLLs by last phys + */ + if (drm_WARN_ON(&dev_priv->drm, + (pll->info->id < DPLL_ID_DG1_DPLL2 && phy >= PHY_C) || + (pll->info->id >= DPLL_ID_DG1_DPLL2 && phy < PHY_C))) + return; + + mutex_lock(&dev_priv->dpll.lock); + + val = intel_de_read(dev_priv, DG1_DPCLKA_CFGCR0(phy)); + drm_WARN_ON(&dev_priv->drm, + (val & DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)) == 0); + + val &= ~DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + val |= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy); + intel_de_write(dev_priv, DG1_DPCLKA_CFGCR0(phy), val); + intel_de_posting_read(dev_priv, DG1_DPCLKA_CFGCR0(phy)); + + val &= ~DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); + intel_de_write(dev_priv, DG1_DPCLKA_CFGCR0(phy), val); + + mutex_unlock(&dev_priv->dpll.lock); +} + static void icl_map_plls_to_ports(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { @@ -3017,6 +3051,19 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder, mutex_unlock(&dev_priv->dpll.lock); } +static void dg1_unmap_plls_to_ports(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + + mutex_lock(&dev_priv->dpll.lock); + + intel_de_rmw(dev_priv, DG1_DPCLKA_CFGCR0(phy), 0, + DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); + + mutex_unlock(&dev_priv->dpll.lock); +} + static void icl_unmap_plls_to_ports(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); @@ -3032,6 +3079,37 @@ static void icl_unmap_plls_to_ports(struct intel_encoder *encoder) mutex_unlock(&dev_priv->dpll.lock); } +static void dg1_sanitize_port_clk_off(struct drm_i915_private *dev_priv, + u32 port_mask, bool ddi_clk_needed) +{ + enum port port; + u32 val; + + for_each_port_masked(port, port_mask) { + enum phy phy = intel_port_to_phy(dev_priv, port); + bool ddi_clk_off; + + val = intel_de_read(dev_priv, DG1_DPCLKA_CFGCR0(phy)); + ddi_clk_off = val & DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); + + if (ddi_clk_needed == !ddi_clk_off) + continue; + + /* + * Punt on the case now where clock is gated, but it would + * be needed by the port. Something else is really broken then. + */ + if (drm_WARN_ON(&dev_priv->drm, ddi_clk_needed)) + continue; + + drm_notice(&dev_priv->drm, + "PHY %c is disabled with an ungated DDI clock, gate it\n", + phy_name(phy)); + val |= DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); + intel_de_write(dev_priv, DG1_DPCLKA_CFGCR0(phy), val); + } +} + static void icl_sanitize_port_clk_off(struct drm_i915_private *dev_priv, u32 port_mask, bool ddi_clk_needed) { @@ -3114,7 +3192,10 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder) ddi_clk_needed = false; } - icl_sanitize_port_clk_off(dev_priv, port_mask, ddi_clk_needed); + if (IS_DG1(dev_priv)) + dg1_sanitize_port_clk_off(dev_priv, port_mask, ddi_clk_needed); + else + icl_sanitize_port_clk_off(dev_priv, port_mask, ddi_clk_needed); } static void intel_ddi_clk_select(struct intel_encoder *encoder, @@ -3666,7 +3747,9 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state, drm_WARN_ON(&dev_priv->drm, crtc_state->has_pch_encoder); - if (INTEL_GEN(dev_priv) >= 11) + if (IS_DG1(dev_priv)) + dg1_map_plls_to_ports(encoder, crtc_state); + else if (INTEL_GEN(dev_priv) >= 11) icl_map_plls_to_ports(encoder, crtc_state); intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); @@ -3848,7 +3931,9 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state, intel_ddi_post_disable_dp(state, encoder, old_crtc_state, old_conn_state); - if (INTEL_GEN(dev_priv) >= 11) + if (IS_DG1(dev_priv)) + dg1_unmap_plls_to_ports(encoder); + else if (INTEL_GEN(dev_priv) >= 11) icl_unmap_plls_to_ports(encoder); if (intel_crtc_has_dp_encoder(old_crtc_state) || is_tc_port) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6faca1e739c8..2729c852c668 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -11003,6 +11003,26 @@ static int hsw_crtc_compute_clock(struct intel_crtc *crtc, return 0; } +static void dg1_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, + struct intel_crtc_state *pipe_config) +{ + enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT; + enum phy phy = intel_port_to_phy(dev_priv, port); + enum intel_dpll_id id; + u32 clk_sel; + + clk_sel = intel_de_read(dev_priv, DG1_DPCLKA_CFGCR0(phy)) & DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + id = DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_DPLL_MAP(clk_sel, phy); + + if (WARN_ON(id > DPLL_ID_DG1_DPLL3)) + return; + + pipe_config->icl_port_dplls[port_dpll_id].pll = + intel_get_shared_dpll_by_id(dev_priv, id); + + icl_set_active_port_dpll(pipe_config, port_dpll_id); +} + static void cnl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) { @@ -11311,7 +11331,9 @@ static void hsw_get_ddi_port_state(struct intel_crtc *crtc, port = TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); } - if (INTEL_GEN(dev_priv) >= 11) + if (IS_DG1(dev_priv)) + dg1_get_ddi_pll(dev_priv, port, pipe_config); + else if (INTEL_GEN(dev_priv) >= 11) icl_get_ddi_pll(dev_priv, port, pipe_config); else if (IS_CANNONLAKE(dev_priv)) cnl_get_ddi_pll(dev_priv, port, pipe_config); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bb0656875697..39664ba553ec 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -230,12 +230,14 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define _TRANS(tran, a, b) _PICK_EVEN(tran, a, b) #define _PORT(port, a, b) _PICK_EVEN(port, a, b) #define _PLL(pll, a, b) _PICK_EVEN(pll, a, b) +#define _PHY(phy, a, b) _PICK_EVEN(phy, a, b) #define _MMIO_PIPE(pipe, a, b) _MMIO(_PIPE(pipe, a, b)) #define _MMIO_PLANE(plane, a, b) _MMIO(_PLANE(plane, a, b)) #define _MMIO_TRANS(tran, a, b) _MMIO(_TRANS(tran, a, b)) #define _MMIO_PORT(port, a, b) _MMIO(_PORT(port, a, b)) #define _MMIO_PLL(pll, a, b) _MMIO(_PLL(pll, a, b)) +#define _MMIO_PHY(phy, a, b) _MMIO(_PHY(phy, a, b)) #define _PHY3(phy, ...) _PICK(phy, __VA_ARGS__) @@ -10300,6 +10302,7 @@ enum skl_power_gate { #define DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port) (3 << DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port)) #define DPCLKA_CFGCR0_DDI_CLK_SEL(pll, port) ((pll) << DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port)) +/* ICL Clocks */ #define ICL_DPCLKA_CFGCR0 _MMIO(0x164280) #define ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) (1 << _PICK(phy, 10, 11, 24)) #define RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) REG_BIT((phy) + 10) @@ -10315,6 +10318,27 @@ enum skl_power_gate { #define RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) \ ((pll) << RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +/* + * DG1 Clocks + * First registers controls the first A and B, while the second register + * controls the phy C and D. The bits on these registers are the + * same, but refer to different phys + */ +#define _DG1_DPCLKA_CFGCR0 0x164280 +#define _DG1_DPCLKA1_CFGCR0 0x16C280 +#define _DG1_DPCLKA_PHY_IDX(phy) ((phy) % 2) +#define _DG1_DPCLKA_PLL_IDX(pll) ((pll) % 2) +#define _DG1_PHY_DPLL_MAP(phy) ((phy) >= PHY_C ? DPLL_ID_DG1_DPLL2 : DPLL_ID_DG1_DPLL0) +#define DG1_DPCLKA_CFGCR0(phy) _MMIO_PHY((phy) / 2, \ + _DG1_DPCLKA_CFGCR0, \ + _DG1_DPCLKA1_CFGCR0) +#define DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) REG_BIT(_DG1_DPCLKA_PHY_IDX(phy) + 10) +#define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy) (_DG1_DPCLKA_PHY_IDX(phy) * 2) +#define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) (_DG1_DPCLKA_PLL_IDX(pll) << DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +#define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy) (0x3 << DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +#define DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_DPLL_MAP(clk_sel, phy) \ + (((clk_sel) >> DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) + _DG1_PHY_DPLL_MAP(phy)) + /* CNL PLL */ #define DPLL0_ENABLE 0x46010 #define DPLL1_ENABLE 0x46014 From 1ba1014db2586bdfe0a9680a00613e2089586c46 Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Tue, 20 Oct 2020 11:06:57 +0530 Subject: [PATCH 08/66] drm/i915/edp/jsl: Update vswing table for HBR and HBR2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JSL has update in vswing table for eDP. BSpec: 21257 Changes since V1: - Fixed few checkpatch errors Cc: Souza Jose Signed-off-by: Tejas Upadhyay Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20201020053657.99890-1-tejaskumarx.surendrakumar.upadhyay@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 87 +++++++++++++++++++++++- 1 file changed, 85 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 36a4a1f4d775..d4b1b73c7aab 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -582,6 +582,34 @@ static const struct cnl_ddi_buf_trans ehl_combo_phy_ddi_translations_dp[] = { { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */ }; +static const struct cnl_ddi_buf_trans jsl_combo_phy_ddi_translations_edp_hbr[] = { + /* NT mV Trans mV db */ + { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 200 200 0.0 */ + { 0x8, 0x7F, 0x38, 0x00, 0x07 }, /* 200 250 1.9 */ + { 0x1, 0x7F, 0x33, 0x00, 0x0C }, /* 200 300 3.5 */ + { 0xA, 0x35, 0x36, 0x00, 0x09 }, /* 200 350 4.9 */ + { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 250 250 0.0 */ + { 0x1, 0x7F, 0x38, 0x00, 0x07 }, /* 250 300 1.6 */ + { 0xA, 0x35, 0x35, 0x00, 0x0A }, /* 250 350 2.9 */ + { 0x1, 0x7F, 0x3F, 0x00, 0x00 }, /* 300 300 0.0 */ + { 0xA, 0x35, 0x38, 0x00, 0x07 }, /* 300 350 1.3 */ + { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */ +}; + +static const struct cnl_ddi_buf_trans jsl_combo_phy_ddi_translations_edp_hbr2[] = { + /* NT mV Trans mV db */ + { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 200 200 0.0 */ + { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 200 250 1.9 */ + { 0x1, 0x7F, 0x3D, 0x00, 0x02 }, /* 200 300 3.5 */ + { 0xA, 0x35, 0x38, 0x00, 0x07 }, /* 200 350 4.9 */ + { 0x8, 0x7F, 0x3F, 0x00, 0x00 }, /* 250 250 0.0 */ + { 0x1, 0x7F, 0x3F, 0x00, 0x00 }, /* 250 300 1.6 */ + { 0xA, 0x35, 0x3A, 0x00, 0x05 }, /* 250 350 2.9 */ + { 0x1, 0x7F, 0x3F, 0x00, 0x00 }, /* 300 300 0.0 */ + { 0xA, 0x35, 0x38, 0x00, 0x07 }, /* 300 350 1.3 */ + { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */ +}; + struct icl_mg_phy_ddi_buf_trans { u32 cri_txdeemph_override_11_6; u32 cri_txdeemph_override_5_0; @@ -1162,6 +1190,57 @@ ehl_get_combo_buf_trans(struct intel_encoder *encoder, return ehl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries); } +static const struct cnl_ddi_buf_trans * +jsl_get_combo_buf_trans_hdmi(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi); + return icl_combo_phy_ddi_translations_hdmi; +} + +static const struct cnl_ddi_buf_trans * +jsl_get_combo_buf_trans_dp(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2); + return icl_combo_phy_ddi_translations_dp_hbr2; +} + +static const struct cnl_ddi_buf_trans * +jsl_get_combo_buf_trans_edp(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + if (dev_priv->vbt.edp.low_vswing) { + if (crtc_state->port_clock > 270000) { + *n_entries = ARRAY_SIZE(jsl_combo_phy_ddi_translations_edp_hbr2); + return jsl_combo_phy_ddi_translations_edp_hbr2; + } else { + *n_entries = ARRAY_SIZE(jsl_combo_phy_ddi_translations_edp_hbr); + return jsl_combo_phy_ddi_translations_edp_hbr; + } + } + + return jsl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries); +} + +static const struct cnl_ddi_buf_trans * +jsl_get_combo_buf_trans(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries) +{ + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + return jsl_get_combo_buf_trans_hdmi(encoder, crtc_state, n_entries); + else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) + return jsl_get_combo_buf_trans_edp(encoder, crtc_state, n_entries); + else + return jsl_get_combo_buf_trans_dp(encoder, crtc_state, n_entries); +} + static const struct cnl_ddi_buf_trans * tgl_get_combo_buf_trans_hdmi(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, @@ -2363,7 +2442,9 @@ static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp, else tgl_get_dkl_buf_trans(encoder, crtc_state, &n_entries); } else if (INTEL_GEN(dev_priv) == 11) { - if (IS_JSL_EHL(dev_priv)) + if (IS_PLATFORM(dev_priv, INTEL_JASPERLAKE)) + jsl_get_combo_buf_trans(encoder, crtc_state, &n_entries); + else if (IS_PLATFORM(dev_priv, INTEL_ELKHARTLAKE)) ehl_get_combo_buf_trans(encoder, crtc_state, &n_entries); else if (intel_phy_is_combo(dev_priv, phy)) icl_get_combo_buf_trans(encoder, crtc_state, &n_entries); @@ -2544,7 +2625,9 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, if (INTEL_GEN(dev_priv) >= 12) ddi_translations = tgl_get_combo_buf_trans(encoder, crtc_state, &n_entries); - else if (IS_JSL_EHL(dev_priv)) + else if (IS_PLATFORM(dev_priv, INTEL_JASPERLAKE)) + ddi_translations = jsl_get_combo_buf_trans(encoder, crtc_state, &n_entries); + else if (IS_PLATFORM(dev_priv, INTEL_ELKHARTLAKE)) ddi_translations = ehl_get_combo_buf_trans(encoder, crtc_state, &n_entries); else ddi_translations = icl_get_combo_buf_trans(encoder, crtc_state, &n_entries); From 6594094f819e0020e926e137e47e2edb97ba500b Mon Sep 17 00:00:00 2001 From: Yan Zhao Date: Thu, 10 Sep 2020 11:54:05 +0800 Subject: [PATCH 09/66] drm/i915/gvt: correct a false comment of flag F_UNALIGN Correct falsely removed comment of flag F_UNALIGN. Fixes: a6c5817a38cf ("drm/i915/gvt: remove flag F_CMD_ACCESSED") Reviewed-by: Zhenyu Wang Signed-off-by: Yan Zhao Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20200910035405.20273-1-yan.y.zhao@intel.com --- drivers/gpu/drm/i915/gvt/gvt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 9831361f181e..a81cf0f01e78 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -255,7 +255,7 @@ struct intel_gvt_mmio { #define F_CMD_ACCESS (1 << 3) /* This reg has been accessed by a VM */ #define F_ACCESSED (1 << 4) -/* This reg has been accessed through GPU commands */ +/* This reg could be accessed by unaligned address */ #define F_UNALIGN (1 << 6) /* This reg is in GVT's mmio save-restor list and in hardware * logical context image From 5f60b12edcd0c2e83650a6f9aa4a969bd9fc5732 Mon Sep 17 00:00:00 2001 From: Colin Xu Date: Tue, 27 Oct 2020 12:53:08 +0800 Subject: [PATCH 10/66] drm/i915/gvt: Save/restore HW status to support GVT suspend/resume This patch save/restore necessary GVT info during i915 suspend/resume so that GVT enabled QEMU VM can continue running. Only GGTT and fence regs are saved/restored now. GVT will save GGTT entries on each host_entry update, restore the saved dirty entries and re-init fence regs in resume routine. V2: - Change kzalloc/kfree to vzalloc/vfree since the space allocated from kmalloc may not enough for all saved GGTT entries. - Keep gvt suspend/resume wrapper in intel_gvt.h/intel_gvt.c and move the actual implementation to gvt.h/gvt.c. (zhenyu) - Check gvt config on and active with intel_gvt_active(). (zhenyu) V3: (zhenyu) - Incorrect copy length. Should be num entries * entry size. - Use memcpy_toio()/memcpy_fromio() instead of memcpy for iomem. - Add F_PM_SAVE flags to indicate which MMIOs to save/restore for PM. V4: Rebase. V5: Fail intel_gvt_save_ggtt as -ENOMEM if fail to alloc memory to save ggtt. Free allocated ggtt_entries on failure. V6: Save host entry to per-vGPU gtt.ggtt_mm on each host_entry update. V7: Restore GGTT entry based on present bit. Split fence restore and mmio restore in different functions. Reviewed-by: Zhenyu Wang Signed-off-by: Hang Yuan Signed-off-by: Colin Xu Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20201027045308.158955-1-colin.xu@intel.com --- drivers/gpu/drm/i915/gvt/gtt.c | 64 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/gtt.h | 4 ++ drivers/gpu/drm/i915/gvt/gvt.c | 9 ++++ drivers/gpu/drm/i915/gvt/gvt.h | 3 ++ drivers/gpu/drm/i915/gvt/handlers.c | 44 ++++++++++++++++++-- drivers/gpu/drm/i915/gvt/mmio.h | 4 ++ drivers/gpu/drm/i915/intel_gvt.c | 15 +++++++ drivers/gpu/drm/i915/intel_gvt.h | 5 +++ 8 files changed, 145 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index a3a4305eda01..897c007ea96a 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -636,9 +636,18 @@ static void ggtt_set_host_entry(struct intel_vgpu_mm *mm, struct intel_gvt_gtt_entry *entry, unsigned long index) { struct intel_gvt_gtt_pte_ops *pte_ops = mm->vgpu->gvt->gtt.pte_ops; + unsigned long offset = index; GEM_BUG_ON(mm->type != INTEL_GVT_MM_GGTT); + if (vgpu_gmadr_is_aperture(mm->vgpu, index << I915_GTT_PAGE_SHIFT)) { + offset -= (vgpu_aperture_gmadr_base(mm->vgpu) >> PAGE_SHIFT); + mm->ggtt_mm.host_ggtt_aperture[offset] = entry->val64; + } else if (vgpu_gmadr_is_hidden(mm->vgpu, index << I915_GTT_PAGE_SHIFT)) { + offset -= (vgpu_hidden_gmadr_base(mm->vgpu) >> PAGE_SHIFT); + mm->ggtt_mm.host_ggtt_hidden[offset] = entry->val64; + } + pte_ops->set_entry(NULL, entry, index, false, 0, mm->vgpu); } @@ -1944,6 +1953,21 @@ static struct intel_vgpu_mm *intel_vgpu_create_ggtt_mm(struct intel_vgpu *vgpu) return ERR_PTR(-ENOMEM); } + mm->ggtt_mm.host_ggtt_aperture = vzalloc((vgpu_aperture_sz(vgpu) >> PAGE_SHIFT) * sizeof(u64)); + if (!mm->ggtt_mm.host_ggtt_aperture) { + vfree(mm->ggtt_mm.virtual_ggtt); + vgpu_free_mm(mm); + return ERR_PTR(-ENOMEM); + } + + mm->ggtt_mm.host_ggtt_hidden = vzalloc((vgpu_hidden_sz(vgpu) >> PAGE_SHIFT) * sizeof(u64)); + if (!mm->ggtt_mm.host_ggtt_hidden) { + vfree(mm->ggtt_mm.host_ggtt_aperture); + vfree(mm->ggtt_mm.virtual_ggtt); + vgpu_free_mm(mm); + return ERR_PTR(-ENOMEM); + } + return mm; } @@ -1971,6 +1995,8 @@ void _intel_vgpu_mm_release(struct kref *mm_ref) invalidate_ppgtt_mm(mm); } else { vfree(mm->ggtt_mm.virtual_ggtt); + vfree(mm->ggtt_mm.host_ggtt_aperture); + vfree(mm->ggtt_mm.host_ggtt_hidden); } vgpu_free_mm(mm); @@ -2852,3 +2878,41 @@ void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu) intel_vgpu_destroy_all_ppgtt_mm(vgpu); intel_vgpu_reset_ggtt(vgpu, true); } + +/** + * intel_gvt_restore_ggtt - restore all vGPU's ggtt entries + * @gvt: intel gvt device + * + * This function is called at driver resume stage to restore + * GGTT entries of every vGPU. + * + */ +void intel_gvt_restore_ggtt(struct intel_gvt *gvt) +{ + struct intel_vgpu *vgpu; + struct intel_vgpu_mm *mm; + int id; + gen8_pte_t pte; + u32 idx, num_low, num_hi, offset; + + /* Restore dirty host ggtt for all vGPUs */ + idr_for_each_entry(&(gvt)->vgpu_idr, vgpu, id) { + mm = vgpu->gtt.ggtt_mm; + + num_low = vgpu_aperture_sz(vgpu) >> PAGE_SHIFT; + offset = vgpu_aperture_gmadr_base(vgpu) >> PAGE_SHIFT; + for (idx = 0; idx < num_low; idx++) { + pte = mm->ggtt_mm.host_ggtt_aperture[idx]; + if (pte & _PAGE_PRESENT) + write_pte64(vgpu->gvt->gt->ggtt, offset + idx, pte); + } + + num_hi = vgpu_hidden_sz(vgpu) >> PAGE_SHIFT; + offset = vgpu_hidden_gmadr_base(vgpu) >> PAGE_SHIFT; + for (idx = 0; idx < num_hi; idx++) { + pte = mm->ggtt_mm.host_ggtt_hidden[idx]; + if (pte & _PAGE_PRESENT) + write_pte64(vgpu->gvt->gt->ggtt, offset + idx, pte); + } + } +} diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h index 52d0d88abd86..b0e173f2d990 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.h +++ b/drivers/gpu/drm/i915/gvt/gtt.h @@ -164,6 +164,9 @@ struct intel_vgpu_mm { } ppgtt_mm; struct { void *virtual_ggtt; + /* Save/restore for PM */ + u64 *host_ggtt_aperture; + u64 *host_ggtt_hidden; struct list_head partial_pte_list; } ggtt_mm; }; @@ -280,5 +283,6 @@ int intel_vgpu_emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, void *p_data, unsigned int bytes); void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu); +void intel_gvt_restore_ggtt(struct intel_gvt *gvt); #endif /* _GVT_GTT_H_ */ diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index c7c561237883..495b6afd6571 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -405,6 +405,15 @@ out_clean_idr: return ret; } +int +intel_gvt_pm_resume(struct intel_gvt *gvt) +{ + intel_gvt_restore_fence(gvt); + intel_gvt_restore_mmio(gvt); + intel_gvt_restore_ggtt(gvt); + return 0; +} + int intel_gvt_register_hypervisor(struct intel_gvt_mpt *m) { diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index a81cf0f01e78..b3d6355dd797 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -255,6 +255,8 @@ struct intel_gvt_mmio { #define F_CMD_ACCESS (1 << 3) /* This reg has been accessed by a VM */ #define F_ACCESSED (1 << 4) +/* This reg requires save & restore during host PM suspend/resume */ +#define F_PM_SAVE (1 << 5) /* This reg could be accessed by unaligned address */ #define F_UNALIGN (1 << 6) /* This reg is in GVT's mmio save-restor list and in hardware @@ -685,6 +687,7 @@ void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu); void intel_gvt_debugfs_init(struct intel_gvt *gvt); void intel_gvt_debugfs_clean(struct intel_gvt *gvt); +int intel_gvt_pm_resume(struct intel_gvt *gvt); #include "trace.h" #include "mpt.h" diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index c7cf15fe9ef6..62b49c72a7d0 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -3091,9 +3091,10 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_DFH(TRVATTL3PTRDW(2), D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(TRVATTL3PTRDW(3), D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(TRVADR, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); - MMIO_DFH(TRTTE, D_SKL_PLUS, F_CMD_ACCESS, - NULL, gen9_trtte_write); - MMIO_DH(_MMIO(0x4dfc), D_SKL_PLUS, NULL, gen9_trtt_chicken_write); + MMIO_DFH(TRTTE, D_SKL_PLUS, F_CMD_ACCESS | F_PM_SAVE, + NULL, gen9_trtte_write); + MMIO_DFH(_MMIO(0x4dfc), D_SKL_PLUS, F_PM_SAVE, + NULL, gen9_trtt_chicken_write); MMIO_D(_MMIO(0x46430), D_SKL_PLUS); @@ -3630,3 +3631,40 @@ default_rw: intel_vgpu_default_mmio_read(vgpu, offset, pdata, bytes) : intel_vgpu_default_mmio_write(vgpu, offset, pdata, bytes); } + +void intel_gvt_restore_fence(struct intel_gvt *gvt) +{ + struct intel_vgpu *vgpu; + int i, id; + + idr_for_each_entry(&(gvt)->vgpu_idr, vgpu, id) { + mmio_hw_access_pre(gvt->gt); + for (i = 0; i < vgpu_fence_sz(vgpu); i++) + intel_vgpu_write_fence(vgpu, i, vgpu_vreg64(vgpu, fence_num_to_offset(i))); + mmio_hw_access_post(gvt->gt); + } +} + +static inline int mmio_pm_restore_handler(struct intel_gvt *gvt, + u32 offset, void *data) +{ + struct intel_vgpu *vgpu = data; + struct drm_i915_private *dev_priv = gvt->gt->i915; + + if (gvt->mmio.mmio_attribute[offset >> 2] & F_PM_SAVE) + I915_WRITE(_MMIO(offset), vgpu_vreg(vgpu, offset)); + + return 0; +} + +void intel_gvt_restore_mmio(struct intel_gvt *gvt) +{ + struct intel_vgpu *vgpu; + int id; + + idr_for_each_entry(&(gvt)->vgpu_idr, vgpu, id) { + mmio_hw_access_pre(gvt->gt); + intel_gvt_for_each_tracked_mmio(gvt, mmio_pm_restore_handler, vgpu); + mmio_hw_access_post(gvt->gt); + } +} diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h index cc4812648bf4..9e862dc73579 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.h +++ b/drivers/gpu/drm/i915/gvt/mmio.h @@ -104,4 +104,8 @@ int intel_vgpu_mmio_reg_rw(struct intel_vgpu *vgpu, unsigned int offset, int intel_vgpu_mask_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes); + +void intel_gvt_restore_fence(struct intel_gvt *gvt); +void intel_gvt_restore_mmio(struct intel_gvt *gvt); + #endif diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index 99fe8aef1c67..4e70c1a9ef2e 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c @@ -24,6 +24,7 @@ #include "i915_drv.h" #include "i915_vgpu.h" #include "intel_gvt.h" +#include "gvt/gvt.h" /** * DOC: Intel GVT-g host support @@ -147,3 +148,17 @@ void intel_gvt_driver_remove(struct drm_i915_private *dev_priv) intel_gvt_clean_device(dev_priv); } + +/** + * intel_gvt_resume - GVT resume routine wapper + * + * @dev_priv: drm i915 private * + * + * This function is called at the i915 driver resume stage to restore required + * HW status for GVT so that vGPU can continue running after resumed. + */ +void intel_gvt_resume(struct drm_i915_private *dev_priv) +{ + if (intel_gvt_active(dev_priv)) + intel_gvt_pm_resume(dev_priv->gvt); +} diff --git a/drivers/gpu/drm/i915/intel_gvt.h b/drivers/gpu/drm/i915/intel_gvt.h index 502fad8a8652..d7d3fb6186fd 100644 --- a/drivers/gpu/drm/i915/intel_gvt.h +++ b/drivers/gpu/drm/i915/intel_gvt.h @@ -33,6 +33,7 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv); void intel_gvt_clean_device(struct drm_i915_private *dev_priv); int intel_gvt_init_host(void); void intel_gvt_sanitize_options(struct drm_i915_private *dev_priv); +void intel_gvt_resume(struct drm_i915_private *dev_priv); #else static inline int intel_gvt_init(struct drm_i915_private *dev_priv) { @@ -46,6 +47,10 @@ static inline void intel_gvt_driver_remove(struct drm_i915_private *dev_priv) static inline void intel_gvt_sanitize_options(struct drm_i915_private *dev_priv) { } + +static inline void intel_gvt_resume(struct drm_i915_private *dev_priv) +{ +} #endif #endif /* _INTEL_GVT_H_ */ From 385fc38c1f97387c47113254d8de2cb0dbf133bd Mon Sep 17 00:00:00 2001 From: Colin Xu Date: Tue, 27 Oct 2020 12:54:06 +0800 Subject: [PATCH 11/66] drm/i915: Add GVT resume routine to i915 This patch add gvt resume wrapper into i915_drm_resume(). GVT relies on i915 so resume gvt at last. V2: - Direct call into gvt suspend/resume wrapper in intel_gvt.h/intel_gvt.c. The wrapper and implementation will check and call gvt routine. (zhenyu) V3: Refresh. V4: Rebase. V5: Fail intel_gvt_suspend() if fail to save GGTT. V6: Save host entry to per-vGPU gtt.ggtt_mm on each host_entry update so only need the resume routine. V7: Refresh. Reviewed-by: Zhenyu Wang Signed-off-by: Hang Yuan Signed-off-by: Colin Xu Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20201027045406.159566-1-colin.xu@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e1e056ffff29..751e258d2103 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1271,6 +1271,8 @@ static int i915_drm_resume(struct drm_device *dev) intel_power_domains_enable(dev_priv); + intel_gvt_resume(dev_priv); + enable_rpm_wakeref_asserts(&dev_priv->runtime_pm); return 0; From a5a8ef937cfa79167f4b2a5602092b8d14fd6b9a Mon Sep 17 00:00:00 2001 From: Colin Xu Date: Mon, 9 Nov 2020 15:39:22 +0800 Subject: [PATCH 12/66] drm/i915/gvt: Fix virtual display setup for BXT/APL Program display related vregs to proper value at initialization, setup virtual monitor and hotplug. vGPU virtual display vregs inherit the value from pregs. The virtual DP monitor is always setup on PORT_B for BXT/APL. However the host may connect monitor on other PORT or without any monitor connected. Without properly setup PIPE/DDI/PLL related vregs, guest driver may not setup the virutal display as expected, and the guest desktop may not be created. Since only one virtual display is supported, enable PIPE_A only. And enable transcoder/DDI/PLL based on which port is setup for BXT/APL. V2: Revise commit message. V3: set_edid should on PORT_B for BXT. Inject hpd event for BXT. V4: Temporarily disable vfio edid on BXT/APL until issue fixed. V5: Rebase to use new HPD define GEN8_DE_PORT_HOTPLUG for BXT. Put vfio edid disabling on BXT/APL to a separate patch. Acked-by: Zhenyu Wang Signed-off-by: Colin Xu Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20201109073922.757759-1-colin.xu@intel.com --- drivers/gpu/drm/i915/gvt/display.c | 179 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/mmio.c | 5 + 2 files changed, 184 insertions(+) diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 5b5c71a0b4af..5c1fcac260d3 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -173,22 +173,162 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu) int pipe; if (IS_BROXTON(dev_priv)) { + enum transcoder trans; + enum port port; + + /* Clear PIPE, DDI, PHY, HPD before setting new */ vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &= ~(GEN8_DE_PORT_HOTPLUG(HPD_PORT_A) | GEN8_DE_PORT_HOTPLUG(HPD_PORT_B) | GEN8_DE_PORT_HOTPLUG(HPD_PORT_C)); + for_each_pipe(dev_priv, pipe) { + vgpu_vreg_t(vgpu, PIPECONF(pipe)) &= + ~(PIPECONF_ENABLE | I965_PIPECONF_ACTIVE); + vgpu_vreg_t(vgpu, DSPCNTR(pipe)) &= ~DISPLAY_PLANE_ENABLE; + vgpu_vreg_t(vgpu, SPRCTL(pipe)) &= ~SPRITE_ENABLE; + vgpu_vreg_t(vgpu, CURCNTR(pipe)) &= ~MCURSOR_MODE; + vgpu_vreg_t(vgpu, CURCNTR(pipe)) |= MCURSOR_MODE_DISABLE; + } + + for (trans = TRANSCODER_A; trans <= TRANSCODER_EDP; trans++) { + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(trans)) &= + ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | + TRANS_DDI_PORT_MASK | TRANS_DDI_FUNC_ENABLE); + } + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &= + ~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK | + TRANS_DDI_PORT_MASK); + + for (port = PORT_A; port <= PORT_C; port++) { + vgpu_vreg_t(vgpu, BXT_PHY_CTL(port)) &= + ~BXT_PHY_LANE_ENABLED; + vgpu_vreg_t(vgpu, BXT_PHY_CTL(port)) |= + (BXT_PHY_CMNLANE_POWERDOWN_ACK | + BXT_PHY_LANE_POWERDOWN_ACK); + + vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(port)) &= + ~(PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE | + PORT_PLL_REF_SEL | PORT_PLL_LOCK | + PORT_PLL_ENABLE); + + vgpu_vreg_t(vgpu, DDI_BUF_CTL(port)) &= + ~(DDI_INIT_DISPLAY_DETECTED | + DDI_BUF_CTL_ENABLE); + vgpu_vreg_t(vgpu, DDI_BUF_CTL(port)) |= DDI_BUF_IS_IDLE; + } + + vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) &= ~(BIT(0) | BIT(1)); + vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) &= + ~PHY_POWER_GOOD; + vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY1)) &= + ~PHY_POWER_GOOD; + vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) &= ~BIT(30); + vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY1)) &= ~BIT(30); + + vgpu_vreg_t(vgpu, SFUSE_STRAP) &= ~SFUSE_STRAP_DDIB_DETECTED; + vgpu_vreg_t(vgpu, SFUSE_STRAP) &= ~SFUSE_STRAP_DDIC_DETECTED; + + /* + * Only 1 PIPE enabled in current vGPU display and PIPE_A is + * tied to TRANSCODER_A in HW, so it's safe to assume PIPE_A, + * TRANSCODER_A can be enabled. PORT_x depends on the input of + * setup_virtual_dp_monitor. + */ + vgpu_vreg_t(vgpu, PIPECONF(PIPE_A)) |= PIPECONF_ENABLE; + vgpu_vreg_t(vgpu, PIPECONF(PIPE_A)) |= I965_PIPECONF_ACTIVE; + + /* + * Golden M/N are calculated based on: + * 24 bpp, 4 lanes, 154000 pixel clk (from virtual EDID), + * DP link clk 1620 MHz and non-constant_n. + * TODO: calculate DP link symbol clk and stream clk m/n. + */ + vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) = 63 << TU_SIZE_SHIFT; + vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) |= 0x5b425e; + vgpu_vreg_t(vgpu, PIPE_DATA_N1(TRANSCODER_A)) = 0x800000; + vgpu_vreg_t(vgpu, PIPE_LINK_M1(TRANSCODER_A)) = 0x3cd6e; + vgpu_vreg_t(vgpu, PIPE_LINK_N1(TRANSCODER_A)) = 0x80000; + + /* Enable per-DDI/PORT vreg */ if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) { + vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(1); + vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY1)) |= + PHY_POWER_GOOD; + vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY1)) |= + BIT(30); + vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_A)) |= + BXT_PHY_LANE_ENABLED; + vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_A)) &= + ~(BXT_PHY_CMNLANE_POWERDOWN_ACK | + BXT_PHY_LANE_POWERDOWN_ACK); + vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_A)) |= + (PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE | + PORT_PLL_REF_SEL | PORT_PLL_LOCK | + PORT_PLL_ENABLE); + vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_A)) |= + (DDI_BUF_CTL_ENABLE | DDI_INIT_DISPLAY_DETECTED); + vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_A)) &= + ~DDI_BUF_IS_IDLE; + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)) |= + (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | + TRANS_DDI_FUNC_ENABLE); vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |= GEN8_DE_PORT_HOTPLUG(HPD_PORT_A); } if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) { + vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIB_DETECTED; + vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(0); + vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) |= + PHY_POWER_GOOD; + vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) |= + BIT(30); + vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_B)) |= + BXT_PHY_LANE_ENABLED; + vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_B)) &= + ~(BXT_PHY_CMNLANE_POWERDOWN_ACK | + BXT_PHY_LANE_POWERDOWN_ACK); + vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_B)) |= + (PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE | + PORT_PLL_REF_SEL | PORT_PLL_LOCK | + PORT_PLL_ENABLE); + vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) |= + DDI_BUF_CTL_ENABLE; + vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) &= + ~DDI_BUF_IS_IDLE; + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= + (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | + (PORT_B << TRANS_DDI_PORT_SHIFT) | + TRANS_DDI_FUNC_ENABLE); vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |= GEN8_DE_PORT_HOTPLUG(HPD_PORT_B); } if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) { + vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIC_DETECTED; + vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(0); + vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) |= + PHY_POWER_GOOD; + vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) |= + BIT(30); + vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) |= + BXT_PHY_LANE_ENABLED; + vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) &= + ~(BXT_PHY_CMNLANE_POWERDOWN_ACK | + BXT_PHY_LANE_POWERDOWN_ACK); + vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_C)) |= + (PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE | + PORT_PLL_REF_SEL | PORT_PLL_LOCK | + PORT_PLL_ENABLE); + vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) |= + DDI_BUF_CTL_ENABLE; + vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) &= + ~DDI_BUF_IS_IDLE; + vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |= + (TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST | + (PORT_B << TRANS_DDI_PORT_SHIFT) | + TRANS_DDI_FUNC_ENABLE); vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |= GEN8_DE_PORT_HOTPLUG(HPD_PORT_C); } @@ -520,6 +660,45 @@ void intel_vgpu_emulate_hotplug(struct intel_vgpu *vgpu, bool connected) vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |= PORTD_HOTPLUG_STATUS_MASK; intel_vgpu_trigger_virtual_event(vgpu, DP_D_HOTPLUG); + } else if (IS_BROXTON(i915)) { + if (connected) { + if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) { + vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |= + GEN8_DE_PORT_HOTPLUG(HPD_PORT_A); + } + if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) { + vgpu_vreg_t(vgpu, SFUSE_STRAP) |= + SFUSE_STRAP_DDIB_DETECTED; + vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |= + GEN8_DE_PORT_HOTPLUG(HPD_PORT_B); + } + if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) { + vgpu_vreg_t(vgpu, SFUSE_STRAP) |= + SFUSE_STRAP_DDIC_DETECTED; + vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |= + GEN8_DE_PORT_HOTPLUG(HPD_PORT_C); + } + } else { + if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) { + vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &= + ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_A); + } + if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) { + vgpu_vreg_t(vgpu, SFUSE_STRAP) &= + ~SFUSE_STRAP_DDIB_DETECTED; + vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &= + ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_B); + } + if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) { + vgpu_vreg_t(vgpu, SFUSE_STRAP) &= + ~SFUSE_STRAP_DDIC_DETECTED; + vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &= + ~GEN8_DE_PORT_HOTPLUG(HPD_PORT_C); + } + } + vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |= + PORTB_HOTPLUG_STATUS_MASK; + intel_vgpu_trigger_virtual_event(vgpu, DP_B_HOTPLUG); } } diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index b6811f6a230d..24210b1eaec5 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -280,6 +280,11 @@ void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu, bool dmlr) vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) |= BXT_PHY_CMNLANE_POWERDOWN_ACK | BXT_PHY_LANE_POWERDOWN_ACK; + vgpu_vreg_t(vgpu, SKL_FUSE_STATUS) |= + SKL_FUSE_DOWNLOAD_STATUS | + SKL_FUSE_PG_DIST_STATUS(SKL_PG0) | + SKL_FUSE_PG_DIST_STATUS(SKL_PG1) | + SKL_FUSE_PG_DIST_STATUS(SKL_PG2); } } else { #define GVT_GEN8_MMIO_RESET_OFFSET (0x44200) From 230edf78ed4b96224802a9b2bfde4bc9996f84a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 24 Sep 2020 21:51:13 +0300 Subject: [PATCH 13/66] drm/i915: Add plane .{min,max}_width() and .max_height() vfuncs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce this maintenance nightmare a bit by converting the plane min/max width/height stuff into vfuncs. Now, if I could just think of a nice way to also use this for intel_mode_valid_max_plane_size()... Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200924185113.30849-1-ville.syrjala@linux.intel.com Reviewed-by: Aditya Swarup --- drivers/gpu/drm/i915/display/intel_display.c | 194 +++++------------- .../drm/i915/display/intel_display_types.h | 9 + drivers/gpu/drm/i915/display/intel_sprite.c | 140 +++++++++++++ 3 files changed, 196 insertions(+), 147 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2729c852c668..63bf3761befc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3719,127 +3719,6 @@ valid_fb: &to_intel_frontbuffer(fb)->bits); } -static int skl_max_plane_width(const struct drm_framebuffer *fb, - int color_plane, - unsigned int rotation) -{ - int cpp = fb->format->cpp[color_plane]; - - switch (fb->modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - /* - * Validated limit is 4k, but has 5k should - * work apart from the following features: - * - Ytile (already limited to 4k) - * - FP16 (already limited to 4k) - * - render compression (already limited to 4k) - * - KVMR sprite and cursor (don't care) - * - horizontal panning (TODO verify this) - * - pipe and plane scaling (TODO verify this) - */ - if (cpp == 8) - return 4096; - else - return 5120; - case I915_FORMAT_MOD_Y_TILED_CCS: - case I915_FORMAT_MOD_Yf_TILED_CCS: - case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: - /* FIXME AUX plane? */ - case I915_FORMAT_MOD_Y_TILED: - case I915_FORMAT_MOD_Yf_TILED: - if (cpp == 8) - return 2048; - else - return 4096; - default: - MISSING_CASE(fb->modifier); - return 2048; - } -} - -static int glk_max_plane_width(const struct drm_framebuffer *fb, - int color_plane, - unsigned int rotation) -{ - int cpp = fb->format->cpp[color_plane]; - - switch (fb->modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - if (cpp == 8) - return 4096; - else - return 5120; - case I915_FORMAT_MOD_Y_TILED_CCS: - case I915_FORMAT_MOD_Yf_TILED_CCS: - /* FIXME AUX plane? */ - case I915_FORMAT_MOD_Y_TILED: - case I915_FORMAT_MOD_Yf_TILED: - if (cpp == 8) - return 2048; - else - return 5120; - default: - MISSING_CASE(fb->modifier); - return 2048; - } -} - -static int icl_min_plane_width(const struct drm_framebuffer *fb) -{ - /* Wa_14011264657, Wa_14011050563: gen11+ */ - switch (fb->format->format) { - case DRM_FORMAT_C8: - return 18; - case DRM_FORMAT_RGB565: - return 10; - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_XVYU2101010: - case DRM_FORMAT_Y212: - case DRM_FORMAT_Y216: - return 6; - case DRM_FORMAT_NV12: - return 20; - case DRM_FORMAT_P010: - case DRM_FORMAT_P012: - case DRM_FORMAT_P016: - return 12; - case DRM_FORMAT_XRGB16161616F: - case DRM_FORMAT_XBGR16161616F: - case DRM_FORMAT_ARGB16161616F: - case DRM_FORMAT_ABGR16161616F: - case DRM_FORMAT_XVYU12_16161616: - case DRM_FORMAT_XVYU16161616: - return 4; - default: - return 1; - } -} - -static int icl_max_plane_width(const struct drm_framebuffer *fb, - int color_plane, - unsigned int rotation) -{ - return 5120; -} - -static int skl_max_plane_height(void) -{ - return 4096; -} - -static int icl_max_plane_height(void) -{ - return 4320; -} static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, @@ -3897,35 +3776,55 @@ intel_plane_fence_y_offset(const struct intel_plane_state *plane_state) return y; } +static int intel_plane_min_width(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + if (plane->min_width) + return plane->min_width(fb, color_plane, rotation); + else + return 1; +} + +static int intel_plane_max_width(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + if (plane->max_width) + return plane->max_width(fb, color_plane, rotation); + else + return INT_MAX; +} + +static int intel_plane_max_height(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + if (plane->max_height) + return plane->max_height(fb, color_plane, rotation); + else + return INT_MAX; +} + static int skl_check_main_surface(struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; int x = plane_state->uapi.src.x1 >> 16; int y = plane_state->uapi.src.y1 >> 16; int w = drm_rect_width(&plane_state->uapi.src) >> 16; int h = drm_rect_height(&plane_state->uapi.src) >> 16; - int max_width, min_width, max_height; - u32 alignment, offset; + int min_width = intel_plane_min_width(plane, fb, 0, rotation); + int max_width = intel_plane_max_width(plane, fb, 0, rotation); + int max_height = intel_plane_max_height(plane, fb, 0, rotation); int aux_plane = intel_main_to_aux_plane(fb, 0); u32 aux_offset = plane_state->color_plane[aux_plane].offset; - - if (INTEL_GEN(dev_priv) >= 11) { - max_width = icl_max_plane_width(fb, 0, rotation); - min_width = icl_min_plane_width(fb); - } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { - max_width = glk_max_plane_width(fb, 0, rotation); - min_width = 1; - } else { - max_width = skl_max_plane_width(fb, 0, rotation); - min_width = 1; - } - - if (INTEL_GEN(dev_priv) >= 11) - max_height = icl_max_plane_height(); - else - max_height = skl_max_plane_height(); + u32 alignment, offset; if (w > max_width || w < min_width || h > max_height) { drm_dbg_kms(&dev_priv->drm, @@ -4008,22 +3907,19 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + struct drm_i915_private *i915 = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; int uv_plane = 1; - int max_width = skl_max_plane_width(fb, uv_plane, rotation); - int max_height = 4096; + int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation); + int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation); int x = plane_state->uapi.src.x1 >> 17; int y = plane_state->uapi.src.y1 >> 17; int w = drm_rect_width(&plane_state->uapi.src) >> 17; int h = drm_rect_height(&plane_state->uapi.src) >> 17; u32 offset; - intel_add_fb_offsets(&x, &y, plane_state, uv_plane); - offset = intel_plane_compute_aligned_offset(&x, &y, - plane_state, uv_plane); - /* FIXME not quite sure how/if these apply to the chroma plane */ if (w > max_width || h > max_height) { drm_dbg_kms(&i915->drm, @@ -4032,6 +3928,10 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) return -EINVAL; } + intel_add_fb_offsets(&x, &y, plane_state, uv_plane); + offset = intel_plane_compute_aligned_offset(&x, &y, + plane_state, uv_plane); + if (is_ccs_modifier(fb->modifier)) { int ccs_plane = main_to_ccs_plane(fb, uv_plane); u32 aux_offset = plane_state->color_plane[ccs_plane].offset; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f6f0626649e0..6e72c9d52843 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1189,6 +1189,15 @@ struct intel_plane { * the intel_plane_state structure and accessed via plane_state. */ + int (*min_width)(const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation); + int (*max_width)(const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation); + int (*max_height)(const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation); unsigned int (*max_stride)(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation); diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index b6deeb338477..a3ab44694118 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -408,6 +408,134 @@ static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state, return DIV_ROUND_UP(pixel_rate * num, den); } +static int skl_plane_max_width(const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + int cpp = fb->format->cpp[color_plane]; + + switch (fb->modifier) { + case DRM_FORMAT_MOD_LINEAR: + case I915_FORMAT_MOD_X_TILED: + /* + * Validated limit is 4k, but has 5k should + * work apart from the following features: + * - Ytile (already limited to 4k) + * - FP16 (already limited to 4k) + * - render compression (already limited to 4k) + * - KVMR sprite and cursor (don't care) + * - horizontal panning (TODO verify this) + * - pipe and plane scaling (TODO verify this) + */ + if (cpp == 8) + return 4096; + else + return 5120; + case I915_FORMAT_MOD_Y_TILED_CCS: + case I915_FORMAT_MOD_Yf_TILED_CCS: + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: + /* FIXME AUX plane? */ + case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_Yf_TILED: + if (cpp == 8) + return 2048; + else + return 4096; + default: + MISSING_CASE(fb->modifier); + return 2048; + } +} + +static int glk_plane_max_width(const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + int cpp = fb->format->cpp[color_plane]; + + switch (fb->modifier) { + case DRM_FORMAT_MOD_LINEAR: + case I915_FORMAT_MOD_X_TILED: + if (cpp == 8) + return 4096; + else + return 5120; + case I915_FORMAT_MOD_Y_TILED_CCS: + case I915_FORMAT_MOD_Yf_TILED_CCS: + /* FIXME AUX plane? */ + case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_Yf_TILED: + if (cpp == 8) + return 2048; + else + return 5120; + default: + MISSING_CASE(fb->modifier); + return 2048; + } +} + +static int icl_plane_min_width(const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + /* Wa_14011264657, Wa_14011050563: gen11+ */ + switch (fb->format->format) { + case DRM_FORMAT_C8: + return 18; + case DRM_FORMAT_RGB565: + return 10; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XVYU2101010: + case DRM_FORMAT_Y212: + case DRM_FORMAT_Y216: + return 6; + case DRM_FORMAT_NV12: + return 20; + case DRM_FORMAT_P010: + case DRM_FORMAT_P012: + case DRM_FORMAT_P016: + return 12; + case DRM_FORMAT_XRGB16161616F: + case DRM_FORMAT_XBGR16161616F: + case DRM_FORMAT_ARGB16161616F: + case DRM_FORMAT_ABGR16161616F: + case DRM_FORMAT_XVYU12_16161616: + case DRM_FORMAT_XVYU16161616: + return 4; + default: + return 1; + } +} + +static int icl_plane_max_width(const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + return 5120; +} + +static int skl_plane_max_height(const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + return 4096; +} + +static int icl_plane_max_height(const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + return 4320; +} + static unsigned int skl_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, @@ -3133,6 +3261,18 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; } + if (INTEL_GEN(dev_priv) >= 11) { + plane->min_width = icl_plane_min_width; + plane->max_width = icl_plane_max_width; + plane->max_height = icl_plane_max_height; + } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { + plane->max_width = glk_plane_max_width; + plane->max_height = skl_plane_max_height; + } else { + plane->max_width = skl_plane_max_width; + plane->max_height = skl_plane_max_height; + } + plane->max_stride = skl_plane_max_stride; plane->update_plane = skl_update_plane; plane->disable_plane = skl_disable_plane; From 64e65f443a43c35967242fd13b494c251bc5d7ee Mon Sep 17 00:00:00 2001 From: Deepak R Varma Date: Wed, 4 Nov 2020 17:45:32 +0530 Subject: [PATCH 14/66] drm/i915/gvt: replace idr_init() by idr_init_base() idr_init() uses base 0 which is an invalid identifier. The new function idr_init_base allows IDR to set the ID lookup from base 1. This avoids all lookups that otherwise starts from 0 since 0 is always unused. References: commit 6ce711f27500 ("idr: Make 1-based IDRs more efficient") Reviewed-by: Zhenyu Wang Signed-off-by: Deepak R Varma Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20201104121532.GA48202@localhost --- drivers/gpu/drm/i915/gvt/gvt.c | 2 +- drivers/gpu/drm/i915/gvt/vgpu.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 495b6afd6571..0262a6fa3a6c 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -312,7 +312,7 @@ int intel_gvt_init_device(struct drm_i915_private *i915) gvt_dbg_core("init gvt device\n"); - idr_init(&gvt->vgpu_idr); + idr_init_base(&gvt->vgpu_idr, 1); spin_lock_init(&gvt->scheduler.mmio_context_lock); mutex_init(&gvt->lock); mutex_init(&gvt->sched_lock); diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 8fa9b31a2484..85bfcc15385f 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -392,7 +392,7 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, mutex_init(&vgpu->dmabuf_lock); INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head); INIT_RADIX_TREE(&vgpu->page_track_tree, GFP_KERNEL); - idr_init(&vgpu->object_idr); + idr_init_base(&vgpu->object_idr, 1); intel_vgpu_init_cfg_space(vgpu, param->primary); vgpu->d3_entered = false; From 87ebfaab7f97a02c2a76623c9741eee42c16fecd Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 6 Nov 2020 14:55:24 -0800 Subject: [PATCH 15/66] drm/i915/display: add namespace to intel_prepare_reset Rename intel_prepare_reset to intel_display_prepare_reset, so it's clear from gt/ that we are calling out the display code. Signed-off-by: Lucas De Marchi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20201106225531.920641-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_display.h | 2 +- drivers/gpu/drm/i915/gt/intel_reset.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 63bf3761befc..99f2dacede9d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4851,7 +4851,7 @@ static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv) intel_has_gpu_reset(&dev_priv->gt)); } -void intel_prepare_reset(struct drm_i915_private *dev_priv) +void intel_display_prepare_reset(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index be774f216065..30960cc8b8a6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -590,7 +590,7 @@ void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe); int lpt_get_iclkip(struct drm_i915_private *dev_priv); bool intel_fuzzy_clock_check(int clock1, int clock2); -void intel_prepare_reset(struct drm_i915_private *dev_priv); +void intel_display_prepare_reset(struct drm_i915_private *dev_priv); void intel_finish_reset(struct drm_i915_private *dev_priv); void intel_dp_get_m_n(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index ac36b67fb46b..2d9d449cecba 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1190,7 +1190,7 @@ static void intel_gt_reset_global(struct intel_gt *gt, /* Use a watchdog to ensure that our reset completes */ intel_wedge_on_timeout(&w, gt, 5 * HZ) { - intel_prepare_reset(gt->i915); + intel_display_prepare_reset(gt->i915); /* Flush everyone using a resource about to be clobbered */ synchronize_srcu_expedited(>->reset.backoff_srcu); From e669ad6f1cef3f2b582ab7cab64cc90fd327348d Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 6 Nov 2020 14:55:25 -0800 Subject: [PATCH 16/66] drm/i915/display: add namespace to intel_finish_reset Rename intel_finish_reset to intel_display_finish_reset, so it's clear from gt/ that we are calling out the display code. Signed-off-by: Lucas De Marchi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20201106225531.920641-2-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_display.h | 2 +- drivers/gpu/drm/i915/gt/intel_reset.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 99f2dacede9d..3e0b2849ec2a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4911,7 +4911,7 @@ void intel_display_prepare_reset(struct drm_i915_private *dev_priv) state->acquire_ctx = ctx; } -void intel_finish_reset(struct drm_i915_private *dev_priv) +void intel_display_finish_reset(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 30960cc8b8a6..a988f9518ece 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -591,7 +591,7 @@ int lpt_get_iclkip(struct drm_i915_private *dev_priv); bool intel_fuzzy_clock_check(int clock1, int clock2); void intel_display_prepare_reset(struct drm_i915_private *dev_priv); -void intel_finish_reset(struct drm_i915_private *dev_priv); +void intel_display_finish_reset(struct drm_i915_private *dev_priv); void intel_dp_get_m_n(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); void intel_dp_set_m_n(const struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 2d9d449cecba..75817d0bbd08 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1197,7 +1197,7 @@ static void intel_gt_reset_global(struct intel_gt *gt, intel_gt_reset(gt, engine_mask, reason); - intel_finish_reset(gt->i915); + intel_display_finish_reset(gt->i915); } if (!test_bit(I915_WEDGED, >->reset.flags)) From 2c5688057f7011a0d75b2e1189695912e232b64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Fri, 6 Nov 2020 14:55:26 -0800 Subject: [PATCH 17/66] drm/i915/display: Do not reset display when there is none MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Display is always disabled and enabled when resetting any engine, but if there is no display it should not do anything with display and only reset the needed engines. Cc: Jani Nikula Signed-off-by: José Roberto de Souza Signed-off-by: Lucas De Marchi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20201106225531.920641-3-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 3e0b2849ec2a..3bf3088b0091 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4858,6 +4858,9 @@ void intel_display_prepare_reset(struct drm_i915_private *dev_priv) struct drm_atomic_state *state; int ret; + if (!HAS_DISPLAY(dev_priv)) + return; + /* reset doesn't touch the display */ if (!dev_priv->params.force_reset_modeset_test && !gpu_reset_clobbers_display(dev_priv)) @@ -4918,6 +4921,9 @@ void intel_display_finish_reset(struct drm_i915_private *dev_priv) struct drm_atomic_state *state; int ret; + if (!HAS_DISPLAY(dev_priv)) + return; + /* reset doesn't touch the display */ if (!test_bit(I915_RESET_MODESET, &dev_priv->gt.reset.flags)) return; From 71c8415d0daa78ef1295743d0e11ba0214d0a9b9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 6 Nov 2020 14:55:27 -0800 Subject: [PATCH 18/66] drm/i915/display: return earlier from intel_modeset_init() without display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit !HAS_DISPLAY() implies !HAS_OVERLAY(), skipping overlay setup anyway, so return earlier from intel_modeset_init() for clarity. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Signed-off-by: Lucas De Marchi Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20201106225531.920641-4-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 3bf3088b0091..9566a8d1f470 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -18286,11 +18286,11 @@ int intel_modeset_init(struct drm_i915_private *i915) { int ret; - intel_overlay_setup(i915); - if (!HAS_DISPLAY(i915)) return 0; + intel_overlay_setup(i915); + ret = intel_fbdev_init(&i915->drm); if (ret) return ret; From 794d61a190905ea2951f4d7d565d1375d7a0de67 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 6 Nov 2020 14:55:29 -0800 Subject: [PATCH 19/66] drm/i915: re-order if/else ladder for hpd_irq_setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the convention of new platforms first. No need to special case HAS_GMCH() since that stopped being true at the lattest on gen8 (for cherryview). Signed-off-by: Lucas De Marchi Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20201106225531.920641-6-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e0eb32bd9607..2ab4edf7f25c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -4237,21 +4237,18 @@ void intel_irq_init(struct drm_i915_private *dev_priv) */ dev_priv->hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv); - if (HAS_GMCH(dev_priv)) { - if (I915_HAS_HOTPLUG(dev_priv)) - dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; - } else { - if (HAS_PCH_DG1(dev_priv)) - dev_priv->display.hpd_irq_setup = dg1_hpd_irq_setup; - else if (INTEL_GEN(dev_priv) >= 11) - dev_priv->display.hpd_irq_setup = gen11_hpd_irq_setup; - else if (IS_GEN9_LP(dev_priv)) - dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; - else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) - dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; - else - dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; - } + if (HAS_PCH_DG1(dev_priv)) + dev_priv->display.hpd_irq_setup = dg1_hpd_irq_setup; + else if (INTEL_GEN(dev_priv) >= 11) + dev_priv->display.hpd_irq_setup = gen11_hpd_irq_setup; + else if (IS_GEN9_LP(dev_priv)) + dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; + else if (INTEL_PCH_TYPE(dev_priv) >= PCH_SPT) + dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; + else if (HAS_GMCH(dev_priv) && I915_HAS_HOTPLUG(dev_priv)) + dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; + else + dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; } /** From 96bd87b7c2216e5656476ea216b8ca64fe1a26fd Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 6 Nov 2020 14:55:30 -0800 Subject: [PATCH 20/66] drm/i915: move display-related to the end of intel_irq_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In intel_irq_init() move what's display/hpd related after what is gt and guc. This makes it easier to support !HAS_DISPLAY() in future. Signed-off-by: Lucas De Marchi Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20201106225531.920641-7-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2ab4edf7f25c..4faf7cb9c158 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -4204,10 +4204,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv) struct drm_device *dev = &dev_priv->drm; int i; - intel_hpd_init_pins(dev_priv); - - intel_hpd_init_work(dev_priv); - INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work); for (i = 0; i < MAX_L3_SLICES; ++i) dev_priv->l3_parity.remap_info[i] = NULL; @@ -4216,6 +4212,10 @@ void intel_irq_init(struct drm_i915_private *dev_priv) if (HAS_GT_UC(dev_priv) && INTEL_GEN(dev_priv) < 11) dev_priv->gt.pm_guc_events = GUC_INTR_GUC2HOST << 16; + intel_hpd_init_pins(dev_priv); + + intel_hpd_init_work(dev_priv); + dev->vblank_disable_immediate = true; /* Most platforms treat the display irq block as an always-on From 9a450b68fef7f482b334f900d9ae6d23261b17c1 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 6 Nov 2020 14:55:31 -0800 Subject: [PATCH 21/66] drm/i915: Do not setup hpd without display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that hpd/display related calls are split from the rest in intel_irq_init(), skip all of that in case we don't have display. Cc: José Roberto de Souza Cc: Jani Nikula Signed-off-by: Lucas De Marchi Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20201106225531.920641-8-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4faf7cb9c158..01f5749a5905 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -4212,6 +4212,9 @@ void intel_irq_init(struct drm_i915_private *dev_priv) if (HAS_GT_UC(dev_priv) && INTEL_GEN(dev_priv) < 11) dev_priv->gt.pm_guc_events = GUC_INTR_GUC2HOST << 16; + if (!HAS_DISPLAY(dev_priv)) + return; + intel_hpd_init_pins(dev_priv); intel_hpd_init_work(dev_priv); From 02d794a34c0083057bdfd576e2f6e75b54f31e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Wed, 11 Nov 2020 08:24:07 -0800 Subject: [PATCH 22/66] drm/i915/display: Group DC9 mask set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DC9 has a separate HW flow from the rest of the DC states and it is available in GEN9 LP platforms and on GEN11 and newer, so here moving the assignment of the mask to a single conditional block to simplifly code. Cc: Lucas De Marchi Cc: Anusha Srivatsa Signed-off-by: José Roberto de Souza Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20201111162408.98002-1-jose.souza@intel.com --- .../gpu/drm/i915/display/intel_display_power.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 689922480661..48d41a43fbb2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -4497,26 +4497,24 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv, max_dc = 3; else max_dc = 4; - /* - * DC9 has a separate HW flow from the rest of the DC states, - * not depending on the DMC firmware. It's needed by system - * suspend/resume, so allow it unconditionally. - */ - mask = DC_STATE_EN_DC9; } else if (IS_GEN(dev_priv, 11)) { max_dc = 2; - mask = DC_STATE_EN_DC9; } else if (IS_GEN(dev_priv, 10) || IS_GEN9_BC(dev_priv)) { max_dc = 2; - mask = 0; } else if (IS_GEN9_LP(dev_priv)) { max_dc = 1; - mask = DC_STATE_EN_DC9; } else { max_dc = 0; - mask = 0; } + /* + * DC9 has a separate HW flow from the rest of the DC states, + * not depending on the DMC firmware. It's needed by system + * suspend/resume, so allow it unconditionally. + */ + mask = IS_GEN9_LP(dev_priv) || INTEL_GEN(dev_priv) >= 11 ? + DC_STATE_EN_DC9 : 0; + if (!dev_priv->params.disable_power_well) max_dc = 0; From 0446049432136abb76eb012c3ddd00fce670881b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Wed, 11 Nov 2020 08:24:08 -0800 Subject: [PATCH 23/66] drm/i915/display: Make get_allowed_dc_mask().max_dc set a chain of if and elses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just following what we do in many other places, DG1 is a exception so move it to the top instead of add it inside of INTEL_GEN(dev_priv) >= 12. Cc: Lucas De Marchi Cc: Anusha Srivatsa Signed-off-by: José Roberto de Souza Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20201111162408.98002-2-jose.souza@intel.com --- .../gpu/drm/i915/display/intel_display_power.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 48d41a43fbb2..31cb9ac5c489 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -4492,20 +4492,16 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv, int requested_dc; int max_dc; - if (INTEL_GEN(dev_priv) >= 12) { - if (IS_DG1(dev_priv)) - max_dc = 3; - else - max_dc = 4; - } else if (IS_GEN(dev_priv, 11)) { + if (IS_DG1(dev_priv)) + max_dc = 3; + else if (INTEL_GEN(dev_priv) >= 12) + max_dc = 4; + else if (INTEL_GEN(dev_priv) >= 10 || IS_GEN9_BC(dev_priv)) max_dc = 2; - } else if (IS_GEN(dev_priv, 10) || IS_GEN9_BC(dev_priv)) { - max_dc = 2; - } else if (IS_GEN9_LP(dev_priv)) { + else if (IS_GEN9_LP(dev_priv)) max_dc = 1; - } else { + else max_dc = 0; - } /* * DC9 has a separate HW flow from the rest of the DC states, From 6ec29d2bb060442315f6c11b0af02ad5da085287 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Wed, 11 Nov 2020 18:39:49 -0800 Subject: [PATCH 24/66] drm/i915/dp: Some reshuffling in mode_valid as prep for bigjoiner modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes. This patch just moves some mode checks around to prepare for adding bigjoiner related mode validation Cc: Ville Syrjälä Signed-off-by: Manasi Navare Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201112023954.12301-1-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 3b0dbda5919a..ec8359f03aaf 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -721,6 +721,9 @@ intel_dp_mode_valid(struct drm_connector *connector, if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + return MODE_H_ILLEGAL; + if (intel_dp_is_edp(intel_dp) && fixed_mode) { if (mode->hdisplay > fixed_mode->hdisplay) return MODE_PANEL; @@ -731,6 +734,9 @@ intel_dp_mode_valid(struct drm_connector *connector, target_clock = fixed_mode->clock; } + if (mode->clock < 10000) + return MODE_CLOCK_LOW; + max_link_clock = intel_dp_max_link_rate(intel_dp); max_lanes = intel_dp_max_lane_count(intel_dp); @@ -771,12 +777,6 @@ intel_dp_mode_valid(struct drm_connector *connector, target_clock > max_dotclk) return MODE_CLOCK_HIGH; - if (mode->clock < 10000) - return MODE_CLOCK_LOW; - - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - return MODE_H_ILLEGAL; - status = intel_dp_mode_valid_downstream(intel_connector, mode, target_clock); if (status != MODE_OK) From 65c1ed30b0e617a368b4326f88b668f1ed32a06f Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Thu, 12 Nov 2020 21:17:13 +0200 Subject: [PATCH 25/66] drm/i915: Move encoder->get_config to a new function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes, create a separate intel_encoder_get_config() function that calls encoder->get_config hook. This is needed so that later we can add beigjoienr related readout here. Signed-off-by: Manasi Navare [vsyrjala: Move the code around for the future] Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Reviewed-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20201112191718.16683-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 9566a8d1f470..110d08f2a5c5 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8141,6 +8141,12 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) ilk_pipe_pixel_rate(crtc_state); } +static void intel_encoder_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + encoder->get_config(encoder, crtc_state); +} + static int intel_crtc_compute_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { @@ -12403,7 +12409,7 @@ intel_encoder_current_mode(struct intel_encoder *encoder) return NULL; } - encoder->get_config(encoder, crtc_state); + intel_encoder_get_config(encoder, crtc_state); intel_mode_from_pipe_config(mode, crtc_state); @@ -14448,7 +14454,7 @@ verify_crtc_state(struct intel_crtc *crtc, pipe_name(pipe)); if (active) - encoder->get_config(encoder, pipe_config); + intel_encoder_get_config(encoder, pipe_config); } intel_crtc_compute_pixel_rate(pipe_config); @@ -18761,7 +18767,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) crtc_state = to_intel_crtc_state(crtc->base.state); encoder->base.crtc = &crtc->base; - encoder->get_config(encoder, crtc_state); + intel_encoder_get_config(encoder, crtc_state); if (encoder->sync_state) encoder->sync_state(encoder, crtc_state); } else { From 11f9af1657b167035fee35ef3317ff2fb0406410 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Thu, 12 Nov 2020 21:17:14 +0200 Subject: [PATCH 26/66] drm/i915: Add a wrapper function around get_pipe_config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create a new function intel_crtc_get_pipe_config() that calls platform specific hooks for get_pipe_config() No functional change here. Suggested-by: Ville Syrjälä Signed-off-by: Manasi Navare [vsyrjala: Conform to modern i915 coding style, fix patch subject] Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Reviewed-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20201112191718.16683-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 110d08f2a5c5..a8287414937c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -11407,6 +11407,14 @@ out: return active; } +static bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + return i915->display.get_pipe_config(crtc, crtc_state); +} + static u32 intel_cursor_base(const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = @@ -12403,7 +12411,7 @@ intel_encoder_current_mode(struct intel_encoder *encoder) return NULL; } - if (!dev_priv->display.get_pipe_config(crtc, crtc_state)) { + if (!intel_crtc_get_pipe_config(crtc_state)) { kfree(crtc_state); kfree(mode); return NULL; @@ -14422,8 +14430,7 @@ verify_crtc_state(struct intel_crtc *crtc, pipe_config->hw.enable = new_crtc_state->hw.enable; - pipe_config->hw.active = - dev_priv->display.get_pipe_config(crtc, pipe_config); + pipe_config->hw.active = intel_crtc_get_pipe_config(pipe_config); /* we keep both pipes enabled on 830 */ if (IS_I830(dev_priv) && pipe_config->hw.active) @@ -18736,7 +18743,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) intel_crtc_state_reset(crtc_state, crtc); crtc_state->hw.active = crtc_state->hw.enable = - dev_priv->display.get_pipe_config(crtc, crtc_state); + intel_crtc_get_pipe_config(crtc_state); crtc->base.enabled = crtc_state->hw.enable; crtc->active = crtc_state->hw.active; From 291106cbd6fa5f8daef55f2fbfa905c33ccc03a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 12 Nov 2020 21:17:15 +0200 Subject: [PATCH 27/66] drm/i915: Move hw.active assignment into intel_crtc_get_pipe_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No reason to make the callers of intel_crtc_get_pipe_config() populate hw.active. Let's do it in intel_crtc_get_pipe_config() itself. hw.enable we leave up to the callers since it's slightly different for readout vs. state check. Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201112191718.16683-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a8287414937c..889642bef192 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -11412,7 +11412,12 @@ static bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state) struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); - return i915->display.get_pipe_config(crtc, crtc_state); + if (!i915->display.get_pipe_config(crtc, crtc_state)) + return false; + + crtc_state->hw.active = true; + + return true; } static u32 intel_cursor_base(const struct intel_plane_state *plane_state) @@ -14430,7 +14435,7 @@ verify_crtc_state(struct intel_crtc *crtc, pipe_config->hw.enable = new_crtc_state->hw.enable; - pipe_config->hw.active = intel_crtc_get_pipe_config(pipe_config); + intel_crtc_get_pipe_config(pipe_config); /* we keep both pipes enabled on 830 */ if (IS_I830(dev_priv) && pipe_config->hw.active) @@ -18742,8 +18747,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) intel_crtc_free_hw_state(crtc_state); intel_crtc_state_reset(crtc_state, crtc); - crtc_state->hw.active = crtc_state->hw.enable = - intel_crtc_get_pipe_config(crtc_state); + intel_crtc_get_pipe_config(crtc_state); + + crtc_state->hw.enable = crtc_state->hw.active; crtc->base.enabled = crtc_state->hw.enable; crtc->active = crtc_state->hw.active; From 33574ec9c1ad911871a9ff1ac915fa532557c67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 12 Nov 2020 21:17:16 +0200 Subject: [PATCH 28/66] drm/i915: s/intel_mode_from_pipe_config/intel_mode_from_crtc_timings/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generalize intel_mode_from_pipe_config() to work on any two arbitrary modes. Also relocate the code for the future, and make it static since it's not needed elsewhere. Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201112191718.16683-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 48 ++++++++++---------- drivers/gpu/drm/i915/display/intel_display.h | 2 - 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 889642bef192..ebf621ff7ef6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8128,6 +8128,27 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *crtc_state) pfit_w * pfit_h); } +static void intel_mode_from_crtc_timings(struct drm_display_mode *mode, + const struct drm_display_mode *timings) +{ + mode->hdisplay = timings->crtc_hdisplay; + mode->htotal = timings->crtc_htotal; + mode->hsync_start = timings->crtc_hsync_start; + mode->hsync_end = timings->crtc_hsync_end; + + mode->vdisplay = timings->crtc_vdisplay; + mode->vtotal = timings->crtc_vtotal; + mode->vsync_start = timings->crtc_vsync_start; + mode->vsync_end = timings->crtc_vsync_end; + + mode->flags = timings->flags; + mode->type = DRM_MODE_TYPE_DRIVER; + + mode->clock = timings->crtc_clock; + + drm_mode_set_name(mode); +} + static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); @@ -9030,27 +9051,6 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc, pipe_config->hw.mode.hdisplay = pipe_config->pipe_src_w; } -void intel_mode_from_pipe_config(struct drm_display_mode *mode, - struct intel_crtc_state *pipe_config) -{ - mode->hdisplay = pipe_config->hw.adjusted_mode.crtc_hdisplay; - mode->htotal = pipe_config->hw.adjusted_mode.crtc_htotal; - mode->hsync_start = pipe_config->hw.adjusted_mode.crtc_hsync_start; - mode->hsync_end = pipe_config->hw.adjusted_mode.crtc_hsync_end; - - mode->vdisplay = pipe_config->hw.adjusted_mode.crtc_vdisplay; - mode->vtotal = pipe_config->hw.adjusted_mode.crtc_vtotal; - mode->vsync_start = pipe_config->hw.adjusted_mode.crtc_vsync_start; - mode->vsync_end = pipe_config->hw.adjusted_mode.crtc_vsync_end; - - mode->flags = pipe_config->hw.adjusted_mode.flags; - mode->type = DRM_MODE_TYPE_DRIVER; - - mode->clock = pipe_config->hw.adjusted_mode.crtc_clock; - - drm_mode_set_name(mode); -} - static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -12424,7 +12424,7 @@ intel_encoder_current_mode(struct intel_encoder *encoder) intel_encoder_get_config(encoder, crtc_state); - intel_mode_from_pipe_config(mode, crtc_state); + intel_mode_from_crtc_timings(mode, &crtc_state->hw.adjusted_mode); kfree(crtc_state); @@ -18841,8 +18841,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) if (crtc_state->hw.active) { struct drm_display_mode *mode = &crtc_state->hw.mode; - intel_mode_from_pipe_config(&crtc_state->hw.adjusted_mode, - crtc_state); + intel_mode_from_crtc_timings(&crtc_state->hw.adjusted_mode, + &crtc_state->hw.adjusted_mode); *mode = crtc_state->hw.adjusted_mode; mode->hdisplay = crtc_state->pipe_src_w; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index a988f9518ece..6be14e8571aa 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -609,8 +609,6 @@ enum intel_display_power_domain intel_aux_power_domain(struct intel_digital_port *dig_port); enum intel_display_power_domain intel_legacy_aux_to_power_domain(enum aux_ch aux_ch); -void intel_mode_from_pipe_config(struct drm_display_mode *mode, - struct intel_crtc_state *pipe_config); void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); From c42773b67d82e62e4b30103f26169b3e02ad06ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 12 Nov 2020 21:17:17 +0200 Subject: [PATCH 29/66] drm/i915: Introduce intel_crtc_readout_derived_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Collect up a bunch of derived state "readout" into a common helper, which we can call from both intel_encoder_get_config() and intel_crtc_get_pipe_config(). Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201112191718.16683-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 34 +++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ebf621ff7ef6..07b8d945c41f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8162,10 +8162,26 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) ilk_pipe_pixel_rate(crtc_state); } +static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state) +{ + struct drm_display_mode *mode = &crtc_state->hw.mode; + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + + intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode); + + intel_crtc_compute_pixel_rate(crtc_state); + + drm_mode_copy(mode, adjusted_mode); + mode->hdisplay = crtc_state->pipe_src_w; + mode->vdisplay = crtc_state->pipe_src_h; +} + static void intel_encoder_get_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) { encoder->get_config(encoder, crtc_state); + + intel_crtc_readout_derived_state(crtc_state); } static int intel_crtc_compute_config(struct intel_crtc *crtc, @@ -9046,9 +9062,6 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc, tmp = intel_de_read(dev_priv, PIPESRC(crtc->pipe)); pipe_config->pipe_src_h = (tmp & 0xffff) + 1; pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1; - - pipe_config->hw.mode.vdisplay = pipe_config->pipe_src_h; - pipe_config->hw.mode.hdisplay = pipe_config->pipe_src_w; } static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) @@ -11417,6 +11430,8 @@ static bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state) crtc_state->hw.active = true; + intel_crtc_readout_derived_state(crtc_state); + return true; } @@ -14469,8 +14484,6 @@ verify_crtc_state(struct intel_crtc *crtc, intel_encoder_get_config(encoder, pipe_config); } - intel_crtc_compute_pixel_rate(pipe_config); - if (!new_crtc_state->hw.active) return; @@ -18839,15 +18852,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) int min_cdclk = 0; if (crtc_state->hw.active) { - struct drm_display_mode *mode = &crtc_state->hw.mode; - - intel_mode_from_crtc_timings(&crtc_state->hw.adjusted_mode, - &crtc_state->hw.adjusted_mode); - - *mode = crtc_state->hw.adjusted_mode; - mode->hdisplay = crtc_state->pipe_src_w; - mode->vdisplay = crtc_state->pipe_src_h; - /* * The initial mode needs to be set in order to keep * the atomic core happy. It wants a valid mode if the @@ -18859,8 +18863,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) */ crtc_state->inherited = true; - intel_crtc_compute_pixel_rate(crtc_state); - intel_crtc_update_active_timings(crtc_state); intel_crtc_copy_hw_to_uapi_state(crtc_state); From bafcdad643462471628275a120a9e2b52262559c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 12 Nov 2020 21:17:18 +0200 Subject: [PATCH 30/66] drm/i915: Add hw.pipe_mode to allow bigjoiner pipe/transcoder split MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With bigjoiner, there will be 2 pipes driving 2 halves of 1 transcoder, because of this, we need a pipe_mode for various calculations, including for example watermarks, plane clipping, etc. v10: * remove redundant pipe_mode assignment (Ville) v9: * pipe_mode in state dump nd state check (Ville) v8: * Add pipe_mode in readout in verify_crtc_state (Ville) v7: * Remove redundant comment (Ville) * Just keep mode instead of pipe_mode (Ville) v6: * renaming in separate function, only pipe_mode here (Ville) * Add description (Maarten) v5: * Rebase (Manasi) v4: * Manual rebase (Manasi) v3: * Change state to crtc_state, fix rebase err (Manasi) v2: * Manual Rebase (Manasi) Signed-off-by: Maarten Lankhorst Signed-off-by: Manasi Navare Reviewed-by: Animesh Manna [vsyrjala: * Fix state checker * Fix state dump * Use pipe_mode for linetime watermarks * Make sure pipe_mode normal timings are correct since the silly ddb code uses them * Drop the redundant pipe_mode copies from intel_modeset_pipe_config() and intel_crtc_copy_uapi_to_hw_state() * Use drm_mode_copy() all over] Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201112191718.16683-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 67 ++++++++++------ .../drm/i915/display/intel_display_types.h | 11 ++- drivers/gpu/drm/i915/intel_pm.c | 76 +++++++++---------- 3 files changed, 92 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 07b8d945c41f..03577ee5d9b7 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6073,18 +6073,16 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, static int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state) { - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; int width, height; if (crtc_state->pch_pfit.enabled) { width = drm_rect_width(&crtc_state->pch_pfit.dst); height = drm_rect_height(&crtc_state->pch_pfit.dst); } else { - width = adjusted_mode->crtc_hdisplay; - height = adjusted_mode->crtc_vdisplay; + width = pipe_mode->crtc_hdisplay; + height = pipe_mode->crtc_vdisplay; } - return skl_update_scaler(crtc_state, !crtc_state->hw.active, SKL_CRTC_INDEX, &crtc_state->scaler_state.scaler_id, @@ -8098,7 +8096,7 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc) static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *crtc_state) { - u32 pixel_rate = crtc_state->hw.adjusted_mode.crtc_clock; + u32 pixel_rate = crtc_state->hw.pipe_mode.crtc_clock; unsigned int pipe_w, pipe_h, pfit_w, pfit_h; /* @@ -8156,7 +8154,7 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) if (HAS_GMCH(dev_priv)) /* FIXME calculate proper pipe pixel rate for GMCH pfit */ crtc_state->pixel_rate = - crtc_state->hw.adjusted_mode.crtc_clock; + crtc_state->hw.pipe_mode.crtc_clock; else crtc_state->pixel_rate = ilk_pipe_pixel_rate(crtc_state); @@ -8165,8 +8163,12 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state) { struct drm_display_mode *mode = &crtc_state->hw.mode; + struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + drm_mode_copy(pipe_mode, adjusted_mode); + + intel_mode_from_crtc_timings(pipe_mode, pipe_mode); intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode); intel_crtc_compute_pixel_rate(crtc_state); @@ -8188,9 +8190,12 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; + struct drm_display_mode *pipe_mode = &pipe_config->hw.pipe_mode; int clock_limit = dev_priv->max_dotclk_freq; + drm_mode_copy(pipe_mode, &pipe_config->hw.adjusted_mode); + intel_mode_from_crtc_timings(pipe_mode, pipe_mode); + if (INTEL_GEN(dev_priv) < 4) { clock_limit = dev_priv->max_cdclk_freq * 9 / 10; @@ -8199,16 +8204,16 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, * is > 90% of the (display) core speed. */ if (intel_crtc_supports_double_wide(crtc) && - adjusted_mode->crtc_clock > clock_limit) { + pipe_mode->crtc_clock > clock_limit) { clock_limit = dev_priv->max_dotclk_freq; pipe_config->double_wide = true; } } - if (adjusted_mode->crtc_clock > clock_limit) { + if (pipe_mode->crtc_clock > clock_limit) { drm_dbg_kms(&dev_priv->drm, "requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n", - adjusted_mode->crtc_clock, clock_limit, + pipe_mode->crtc_clock, clock_limit, yesno(pipe_config->double_wide)); return -EINVAL; } @@ -8251,7 +8256,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw. */ if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) && - adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay) + pipe_mode->crtc_hsync_start == pipe_mode->crtc_hdisplay) return -EINVAL; intel_crtc_compute_pixel_rate(pipe_config); @@ -12783,15 +12788,15 @@ static bool c8_planes_changed(const struct intel_crtc_state *new_crtc_state) static u16 hsw_linetime_wm(const struct intel_crtc_state *crtc_state) { - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &crtc_state->hw.pipe_mode; int linetime_wm; if (!crtc_state->hw.enable) return 0; - linetime_wm = DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8, - adjusted_mode->crtc_clock); + linetime_wm = DIV_ROUND_CLOSEST(pipe_mode->crtc_htotal * 1000 * 8, + pipe_mode->crtc_clock); return min(linetime_wm, 0x1ff); } @@ -12799,14 +12804,14 @@ static u16 hsw_linetime_wm(const struct intel_crtc_state *crtc_state) static u16 hsw_ips_linetime_wm(const struct intel_crtc_state *crtc_state, const struct intel_cdclk_state *cdclk_state) { - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &crtc_state->hw.pipe_mode; int linetime_wm; if (!crtc_state->hw.enable) return 0; - linetime_wm = DIV_ROUND_CLOSEST(adjusted_mode->crtc_htotal * 1000 * 8, + linetime_wm = DIV_ROUND_CLOSEST(pipe_mode->crtc_htotal * 1000 * 8, cdclk_state->logical.cdclk); return min(linetime_wm, 0x1ff); @@ -12816,14 +12821,14 @@ static u16 skl_linetime_wm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &crtc_state->hw.pipe_mode; int linetime_wm; if (!crtc_state->hw.enable) return 0; - linetime_wm = DIV_ROUND_UP(adjusted_mode->crtc_htotal * 1000 * 8, + linetime_wm = DIV_ROUND_UP(pipe_mode->crtc_htotal * 1000 * 8, crtc_state->pixel_rate); /* Display WA #1135: BXT:ALL GLK:ALL */ @@ -13279,6 +13284,9 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, drm_dbg_kms(&dev_priv->drm, "adjusted mode:\n"); drm_mode_debug_printmodeline(&pipe_config->hw.adjusted_mode); intel_dump_crtc_timings(dev_priv, &pipe_config->hw.adjusted_mode); + drm_dbg_kms(&dev_priv->drm, "pipe mode:\n"); + drm_mode_debug_printmodeline(&pipe_config->hw.pipe_mode); + intel_dump_crtc_timings(dev_priv, &pipe_config->hw.pipe_mode); drm_dbg_kms(&dev_priv->drm, "port clock: %d, pipe src size: %dx%d, pixel rate %d\n", pipe_config->port_clock, @@ -14027,6 +14035,20 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(output_types); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hdisplay); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_htotal); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_end); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_end); + + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vdisplay); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vtotal); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_end); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay); PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal); PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_start); @@ -14153,6 +14175,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) PIPE_CONF_CHECK_I(pipe_bpp); + PIPE_CONF_CHECK_CLOCK_FUZZY(hw.pipe_mode.crtc_clock); PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock); PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 6e72c9d52843..35ab5944a3f7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -817,15 +817,22 @@ struct intel_crtc_state { * The following members are used to verify the hardware state: * - enable * - active - * - mode / adjusted_mode + * - mode / pipe_mode / adjusted_mode * - color property blobs. * * During initial hw readout, they need to be copied to uapi. + * + * Bigjoiner will allow a transcoder mode that spans 2 pipes; + * Use the pipe_mode for calculations like watermarks, pipe + * scaler, and bandwidth. + * + * Use adjusted_mode for things that need to know the full + * mode on the transcoder, which spans all pipes. */ struct { bool active, enable; struct drm_property_blob *degamma_lut, *gamma_lut, *ctm; - struct drm_display_mode mode, adjusted_mode; + struct drm_display_mode mode, pipe_mode, adjusted_mode; enum drm_scaling_filter scaling_filter; } hw; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f54375b11964..9898c257d3e0 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -899,12 +899,12 @@ static void pnv_update_wm(struct intel_crtc *unused_crtc) crtc = single_enabled_crtc(dev_priv); if (crtc) { - const struct drm_display_mode *adjusted_mode = - &crtc->config->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &crtc->config->hw.pipe_mode; const struct drm_framebuffer *fb = crtc->base.primary->state->fb; int cpp = fb->format->cpp[0]; - int clock = adjusted_mode->crtc_clock; + int clock = pipe_mode->crtc_clock; /* Display SR */ wm = intel_calculate_wm(clock, &pnv_display_wm, @@ -1135,8 +1135,8 @@ static u16 g4x_compute_wm(const struct intel_crtc_state *crtc_state, { struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &crtc_state->hw.pipe_mode; unsigned int latency = dev_priv->wm.pri_latency[level] * 10; unsigned int clock, htotal, cpp, width, wm; @@ -1163,8 +1163,8 @@ static u16 g4x_compute_wm(const struct intel_crtc_state *crtc_state, level != G4X_WM_LEVEL_NORMAL) cpp = max(cpp, 4u); - clock = adjusted_mode->crtc_clock; - htotal = adjusted_mode->crtc_htotal; + clock = pipe_mode->crtc_clock; + htotal = pipe_mode->crtc_htotal; width = drm_rect_width(&plane_state->uapi.dst); @@ -1660,8 +1660,8 @@ static u16 vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, { struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &crtc_state->hw.pipe_mode; unsigned int clock, htotal, cpp, width, wm; if (dev_priv->wm.pri_latency[level] == 0) @@ -1671,8 +1671,8 @@ static u16 vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, return 0; cpp = plane_state->hw.fb->format->cpp[0]; - clock = adjusted_mode->crtc_clock; - htotal = adjusted_mode->crtc_htotal; + clock = pipe_mode->crtc_clock; + htotal = pipe_mode->crtc_htotal; width = crtc_state->pipe_src_w; if (plane->id == PLANE_CURSOR) { @@ -2261,12 +2261,12 @@ static void i965_update_wm(struct intel_crtc *unused_crtc) if (crtc) { /* self-refresh has much higher latency */ static const int sr_latency_ns = 12000; - const struct drm_display_mode *adjusted_mode = - &crtc->config->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &crtc->config->hw.pipe_mode; const struct drm_framebuffer *fb = crtc->base.primary->state->fb; - int clock = adjusted_mode->crtc_clock; - int htotal = adjusted_mode->crtc_htotal; + int clock = pipe_mode->crtc_clock; + int htotal = pipe_mode->crtc_htotal; int hdisplay = crtc->config->pipe_src_w; int cpp = fb->format->cpp[0]; int entries; @@ -2345,8 +2345,8 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) fifo_size = dev_priv->display.get_fifo_size(dev_priv, PLANE_A); crtc = intel_get_crtc_for_plane(dev_priv, PLANE_A); if (intel_crtc_active(crtc)) { - const struct drm_display_mode *adjusted_mode = - &crtc->config->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &crtc->config->hw.pipe_mode; const struct drm_framebuffer *fb = crtc->base.primary->state->fb; int cpp; @@ -2356,7 +2356,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) else cpp = fb->format->cpp[0]; - planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, + planea_wm = intel_calculate_wm(pipe_mode->crtc_clock, wm_info, fifo_size, cpp, pessimal_latency_ns); enabled = crtc; @@ -2372,8 +2372,8 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) fifo_size = dev_priv->display.get_fifo_size(dev_priv, PLANE_B); crtc = intel_get_crtc_for_plane(dev_priv, PLANE_B); if (intel_crtc_active(crtc)) { - const struct drm_display_mode *adjusted_mode = - &crtc->config->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &crtc->config->hw.pipe_mode; const struct drm_framebuffer *fb = crtc->base.primary->state->fb; int cpp; @@ -2383,7 +2383,7 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) else cpp = fb->format->cpp[0]; - planeb_wm = intel_calculate_wm(adjusted_mode->crtc_clock, + planeb_wm = intel_calculate_wm(pipe_mode->crtc_clock, wm_info, fifo_size, cpp, pessimal_latency_ns); if (enabled == NULL) @@ -2421,12 +2421,12 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) if (HAS_FW_BLC(dev_priv) && enabled) { /* self-refresh has much higher latency */ static const int sr_latency_ns = 6000; - const struct drm_display_mode *adjusted_mode = - &enabled->config->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &enabled->config->hw.pipe_mode; const struct drm_framebuffer *fb = enabled->base.primary->state->fb; - int clock = adjusted_mode->crtc_clock; - int htotal = adjusted_mode->crtc_htotal; + int clock = pipe_mode->crtc_clock; + int htotal = pipe_mode->crtc_htotal; int hdisplay = enabled->config->pipe_src_w; int cpp; int entries; @@ -2474,7 +2474,7 @@ static void i845_update_wm(struct intel_crtc *unused_crtc) { struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev); struct intel_crtc *crtc; - const struct drm_display_mode *adjusted_mode; + const struct drm_display_mode *pipe_mode; u32 fwater_lo; int planea_wm; @@ -2482,8 +2482,8 @@ static void i845_update_wm(struct intel_crtc *unused_crtc) if (crtc == NULL) return; - adjusted_mode = &crtc->config->hw.adjusted_mode; - planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, + pipe_mode = &crtc->config->hw.pipe_mode; + planea_wm = intel_calculate_wm(pipe_mode->crtc_clock, &i845_wm_info, dev_priv->display.get_fifo_size(dev_priv, PLANE_A), 4, pessimal_latency_ns); @@ -2573,7 +2573,7 @@ static u32 ilk_compute_pri_wm(const struct intel_crtc_state *crtc_state, return method1; method2 = ilk_wm_method2(crtc_state->pixel_rate, - crtc_state->hw.adjusted_mode.crtc_htotal, + crtc_state->hw.pipe_mode.crtc_htotal, drm_rect_width(&plane_state->uapi.dst), cpp, mem_value); @@ -2601,7 +2601,7 @@ static u32 ilk_compute_spr_wm(const struct intel_crtc_state *crtc_state, method1 = ilk_wm_method1(crtc_state->pixel_rate, cpp, mem_value); method2 = ilk_wm_method2(crtc_state->pixel_rate, - crtc_state->hw.adjusted_mode.crtc_htotal, + crtc_state->hw.pipe_mode.crtc_htotal, drm_rect_width(&plane_state->uapi.dst), cpp, mem_value); return min(method1, method2); @@ -2626,7 +2626,7 @@ static u32 ilk_compute_cur_wm(const struct intel_crtc_state *crtc_state, cpp = plane_state->hw.fb->format->cpp[0]; return ilk_wm_method2(crtc_state->pixel_rate, - crtc_state->hw.adjusted_mode.crtc_htotal, + crtc_state->hw.pipe_mode.crtc_htotal, drm_rect_width(&plane_state->uapi.dst), cpp, mem_value); } @@ -3883,7 +3883,7 @@ static bool skl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) if (!crtc_state->hw.active) return true; - if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) + if (crtc_state->hw.pipe_mode.flags & DRM_MODE_FLAG_INTERLACE) return false; intel_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) { @@ -4174,8 +4174,8 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv, */ total_slice_mask = dbuf_slice_mask; for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) { - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = + &crtc_state->hw.pipe_mode; enum pipe pipe = crtc->pipe; int hdisplay, vdisplay; u32 pipe_dbuf_slice_mask; @@ -4205,7 +4205,7 @@ skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv, if (dbuf_slice_mask != pipe_dbuf_slice_mask) continue; - drm_mode_get_hv_timing(adjusted_mode, &hdisplay, &vdisplay); + drm_mode_get_hv_timing(pipe_mode, &hdisplay, &vdisplay); total_width_in_range += hdisplay; @@ -5093,7 +5093,7 @@ intel_get_linetime_us(const struct intel_crtc_state *crtc_state) if (drm_WARN_ON(&dev_priv->drm, pixel_rate == 0)) return u32_to_fixed16(0); - crtc_htotal = crtc_state->hw.adjusted_mode.crtc_htotal; + crtc_htotal = crtc_state->hw.pipe_mode.crtc_htotal; linetime_us = div_fixed16(crtc_htotal * 1000, pixel_rate); return linetime_us; @@ -5282,14 +5282,14 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, method1 = skl_wm_method1(dev_priv, wp->plane_pixel_rate, wp->cpp, latency, wp->dbuf_block_size); method2 = skl_wm_method2(wp->plane_pixel_rate, - crtc_state->hw.adjusted_mode.crtc_htotal, + crtc_state->hw.pipe_mode.crtc_htotal, latency, wp->plane_blocks_per_line); if (wp->y_tiled) { selected_result = max_fixed16(method2, wp->y_tile_minimum); } else { - if ((wp->cpp * crtc_state->hw.adjusted_mode.crtc_htotal / + if ((wp->cpp * crtc_state->hw.pipe_mode.crtc_htotal / wp->dbuf_block_size < 1) && (wp->plane_bytes_per_line / wp->dbuf_block_size < 1)) { selected_result = method2; From aa07c1d3be699bda5a3e5d94203217a3961b0f9f Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Fri, 13 Nov 2020 07:56:54 -0800 Subject: [PATCH 31/66] drm/i915: Pass intel_atomic_state instead of drm_atomic_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes, to align with previous cleanups pass intel_atomic_state instead of drm_atomic_state. Also pass this intel_atomic_state with crtc_state to some of the atomic_check functions. v2: * Squash some changes from next patch (Ville) Signed-off-by: Manasi Navare Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201113155656.17630-1-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 32 +++++++++++--------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 03577ee5d9b7..ed5ad5371a51 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -12630,7 +12630,7 @@ static bool encoders_cloneable(const struct intel_encoder *a, b->cloneable & (1 << a->type)); } -static bool check_single_encoder_cloning(struct drm_atomic_state *state, +static bool check_single_encoder_cloning(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) { @@ -12639,7 +12639,7 @@ static bool check_single_encoder_cloning(struct drm_atomic_state *state, struct drm_connector_state *connector_state; int i; - for_each_new_connector_in_state(state, connector, connector_state, i) { + for_each_new_connector_in_state(&state->base, connector, connector_state, i) { if (connector_state->crtc != &crtc->base) continue; @@ -13418,20 +13418,23 @@ static bool check_digital_port_conflicts(struct intel_atomic_state *state) } static void -intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_crtc_state *crtc_state) +intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_atomic_state *state, + struct intel_crtc_state *crtc_state) { intel_crtc_copy_color_blobs(crtc_state); } static void -intel_crtc_copy_uapi_to_hw_state(struct intel_crtc_state *crtc_state) +intel_crtc_copy_uapi_to_hw_state(struct intel_atomic_state *state, + struct intel_crtc_state *crtc_state) { crtc_state->hw.enable = crtc_state->uapi.enable; crtc_state->hw.active = crtc_state->uapi.active; crtc_state->hw.mode = crtc_state->uapi.mode; crtc_state->hw.adjusted_mode = crtc_state->uapi.adjusted_mode; crtc_state->hw.scaling_filter = crtc_state->uapi.scaling_filter; - intel_crtc_copy_uapi_to_hw_state_nomodeset(crtc_state); + + intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc_state); } static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state) @@ -13454,7 +13457,8 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state } static int -intel_crtc_prepare_cleared_state(struct intel_crtc_state *crtc_state) +intel_crtc_prepare_cleared_state(struct intel_atomic_state *state, + struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -13486,16 +13490,16 @@ intel_crtc_prepare_cleared_state(struct intel_crtc_state *crtc_state) memcpy(crtc_state, saved_state, sizeof(*crtc_state)); kfree(saved_state); - intel_crtc_copy_uapi_to_hw_state(crtc_state); + intel_crtc_copy_uapi_to_hw_state(state, crtc_state); return 0; } static int -intel_modeset_pipe_config(struct intel_crtc_state *pipe_config) +intel_modeset_pipe_config(struct intel_atomic_state *state, + struct intel_crtc_state *pipe_config) { struct drm_crtc *crtc = pipe_config->uapi.crtc; - struct drm_atomic_state *state = pipe_config->uapi.state; struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev); struct drm_connector *connector; struct drm_connector_state *connector_state; @@ -13537,7 +13541,7 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config) &pipe_config->pipe_src_w, &pipe_config->pipe_src_h); - for_each_new_connector_in_state(state, connector, connector_state, i) { + for_each_new_connector_in_state(&state->base, connector, connector_state, i) { struct intel_encoder *encoder = to_intel_encoder(connector_state->best_encoder); @@ -13575,7 +13579,7 @@ encoder_retry: * adjust it according to limitations or connector properties, and also * a chance to reject the mode entirely. */ - for_each_new_connector_in_state(state, connector, connector_state, i) { + for_each_new_connector_in_state(&state->base, connector, connector_state, i) { struct intel_encoder *encoder = to_intel_encoder(connector_state->best_encoder); @@ -15196,19 +15200,19 @@ static int intel_atomic_check(struct drm_device *dev, new_crtc_state, i) { if (!needs_modeset(new_crtc_state)) { /* Light copy */ - intel_crtc_copy_uapi_to_hw_state_nomodeset(new_crtc_state); + intel_crtc_copy_uapi_to_hw_state_nomodeset(state, new_crtc_state); continue; } - ret = intel_crtc_prepare_cleared_state(new_crtc_state); + ret = intel_crtc_prepare_cleared_state(state, new_crtc_state); if (ret) goto fail; if (!new_crtc_state->hw.enable) continue; - ret = intel_modeset_pipe_config(new_crtc_state); + ret = intel_modeset_pipe_config(state, new_crtc_state); if (ret) goto fail; } From ee230706666c04798e4baeb8f4d2205aa31bda24 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Fri, 13 Nov 2020 07:56:55 -0800 Subject: [PATCH 32/66] drm/i915/dp: Add from_crtc_state to copy color blobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes here, just adds a from_crtc_state as a prep for bigjoiner v2: * More prep with intel_atomic_state (Ville) Cc: Ville Syrjälä Signed-off-by: Manasi Navare Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201113155656.17630-2-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_atomic.c | 9 +++++---- drivers/gpu/drm/i915/display/intel_atomic.h | 3 ++- drivers/gpu/drm/i915/display/intel_display.c | 4 +++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 63d8d6840655..e00fdc47c0eb 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -269,14 +269,15 @@ void intel_crtc_free_hw_state(struct intel_crtc_state *crtc_state) intel_crtc_put_color_blobs(crtc_state); } -void intel_crtc_copy_color_blobs(struct intel_crtc_state *crtc_state) +void intel_crtc_copy_color_blobs(struct intel_crtc_state *crtc_state, + const struct intel_crtc_state *from_crtc_state) { drm_property_replace_blob(&crtc_state->hw.degamma_lut, - crtc_state->uapi.degamma_lut); + from_crtc_state->uapi.degamma_lut); drm_property_replace_blob(&crtc_state->hw.gamma_lut, - crtc_state->uapi.gamma_lut); + from_crtc_state->uapi.gamma_lut); drm_property_replace_blob(&crtc_state->hw.ctm, - crtc_state->uapi.ctm); + from_crtc_state->uapi.ctm); } /** diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h index 285de07011dc..62a3365ed5e6 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.h +++ b/drivers/gpu/drm/i915/display/intel_atomic.h @@ -43,7 +43,8 @@ struct drm_crtc_state *intel_crtc_duplicate_state(struct drm_crtc *crtc); void intel_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state); void intel_crtc_free_hw_state(struct intel_crtc_state *crtc_state); -void intel_crtc_copy_color_blobs(struct intel_crtc_state *crtc_state); +void intel_crtc_copy_color_blobs(struct intel_crtc_state *crtc_state, + const struct intel_crtc_state *from_crtc_state); struct drm_atomic_state *intel_atomic_state_alloc(struct drm_device *dev); void intel_atomic_state_free(struct drm_atomic_state *state); void intel_atomic_state_clear(struct drm_atomic_state *state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ed5ad5371a51..2e1d9f98a4d0 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -13421,7 +13421,9 @@ static void intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) { - intel_crtc_copy_color_blobs(crtc_state); + const struct intel_crtc_state *from_crtc_state = crtc_state; + + intel_crtc_copy_color_blobs(crtc_state, from_crtc_state); } static void From ffc90033dfc1f5a857ac96ca648d1250b3fcccf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 6 Nov 2020 19:30:37 +0200 Subject: [PATCH 33/66] drm/i915: Pass intel_atomic_state around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass the whole intel_atomic_state to skl_build_pipe_wm() and skl_allocate_pipe_ddb() so we can start to iterate stuff containerd in the commit. Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201106173042.7534-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_pm.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9898c257d3e0..a413e4b10e45 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4791,9 +4791,11 @@ skl_plane_wm_level(const struct intel_crtc_state *crtc_state, } static int -skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state) +skl_allocate_pipe_ddb(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct skl_ddb_entry *alloc = &crtc_state->wm.skl.ddb; u16 alloc_size, start = 0; @@ -5583,9 +5585,12 @@ static int icl_build_plane_wm(struct intel_crtc_state *crtc_state, return 0; } -static int skl_build_pipe_wm(struct intel_crtc_state *crtc_state) +static int skl_build_pipe_wm(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; struct intel_plane *plane; const struct intel_plane_state *plane_state; @@ -5794,7 +5799,7 @@ skl_compute_ddb(struct intel_atomic_state *state) for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - ret = skl_allocate_pipe_ddb(new_crtc_state); + ret = skl_allocate_pipe_ddb(state, crtc); if (ret) return ret; @@ -6092,7 +6097,6 @@ skl_compute_wm(struct intel_atomic_state *state) { struct intel_crtc *crtc; struct intel_crtc_state *new_crtc_state; - struct intel_crtc_state *old_crtc_state; int ret, i; ret = skl_ddb_add_affected_pipes(state); @@ -6104,9 +6108,8 @@ skl_compute_wm(struct intel_atomic_state *state) * Note that skl_ddb_add_affected_pipes may have added more CRTC's that * weren't otherwise being modified if pipe allocations had to change. */ - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { - ret = skl_build_pipe_wm(new_crtc_state); + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + ret = skl_build_pipe_wm(state, crtc); if (ret) return ret; } @@ -6124,8 +6127,7 @@ skl_compute_wm(struct intel_atomic_state *state) * based on how much ddb is available. Now we can actually * check if the final watermarks changed. */ - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { ret = skl_wm_add_affected_planes(state, crtc); if (ret) return ret; From dbf71381d73390d1e2cedd84eb04ea9b32fd96b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 6 Nov 2020 19:30:38 +0200 Subject: [PATCH 34/66] drm/i915: Nuke intel_atomic_crtc_state_for_each_plane_state() from skl+ wm code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_atomic_crtc_state_for_each_plane_state() peeks at the plane's current state without holding the plane's mutex, trusting that the crtc's mutex will protect it. In practice that does work since our planes can't move between pipes, but it sets a bad example. intel_atomic_crtc_state_for_each_plane_state() also relies on crtc_state.uapi.plane_mask which may be full of lies when it comes to the bigjoiner stuff, so soon we can't use it as is anyway. So best to just get rid of it entirely. Which we can easily do by switching to the g4x/vlv "raw" watermark approach. Later on we should even be able to move the "raw" watermark computation into the normal .plane_check() code, leaving only the merging/clamping of the final watermarks to the later stages. But that will require adjusting the ilk+ wm code similarly as well. Signed-off-by: Ville Syrjälä Reviewed-by: Stanislav Lisovskiy Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201106173042.7534-3-ville.syrjala@linux.intel.com --- .../drm/i915/display/intel_display_types.h | 2 + drivers/gpu/drm/i915/intel_pm.c | 41 +++++++++++-------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 35ab5944a3f7..3d91b116aadc 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -755,6 +755,8 @@ struct intel_crtc_wm_state { } ilk; struct { + /* "raw" watermarks */ + struct skl_pipe_wm raw; /* gen9+ only needs 1-step wm programming */ struct skl_pipe_wm optimal; struct skl_ddb_entry ddb; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a413e4b10e45..98eec96d5c23 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5480,7 +5480,7 @@ static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state, { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id]; + struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane_id]; struct skl_wm_params wm_params; int ret; @@ -5503,7 +5503,7 @@ static int skl_build_plane_wm_uv(struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state, enum plane_id plane_id) { - struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id]; + struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane_id]; struct skl_wm_params wm_params; int ret; @@ -5524,10 +5524,13 @@ static int skl_build_plane_wm(struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - const struct drm_framebuffer *fb = plane_state->hw.fb; enum plane_id plane_id = plane->id; + struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane_id]; + const struct drm_framebuffer *fb = plane_state->hw.fb; int ret; + memset(wm, 0, sizeof(*wm)); + if (!intel_wm_plane_visible(crtc_state, plane_state)) return 0; @@ -5549,10 +5552,14 @@ static int skl_build_plane_wm(struct intel_crtc_state *crtc_state, static int icl_build_plane_wm(struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - enum plane_id plane_id = to_intel_plane(plane_state->uapi.plane)->id; + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum plane_id plane_id = plane->id; + struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane_id]; int ret; + memset(wm, 0, sizeof(*wm)); + /* Watermarks calculated in master */ if (plane_state->planar_slave) return 0; @@ -5591,19 +5598,18 @@ static int skl_build_pipe_wm(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; - struct intel_plane *plane; const struct intel_plane_state *plane_state; - int ret; + struct intel_plane *plane; + int ret, i; - /* - * We'll only calculate watermarks for planes that are actually - * enabled, so make sure all other planes are set as disabled. - */ - memset(pipe_wm->planes, 0, sizeof(pipe_wm->planes)); - - intel_atomic_crtc_state_for_each_plane_state(plane, plane_state, - crtc_state) { + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + /* + * FIXME should perhaps check {old,new}_plane_crtc->hw.crtc + * instead but we don't populate that correctly for NV12 Y + * planes so for now hack this. + */ + if (plane->pipe != crtc->pipe) + continue; if (INTEL_GEN(dev_priv) >= 11) ret = icl_build_plane_wm(crtc_state, plane_state); @@ -5613,6 +5619,8 @@ static int skl_build_pipe_wm(struct intel_atomic_state *state, return ret; } + crtc_state->wm.skl.optimal = crtc_state->wm.skl.raw; + return 0; } @@ -6273,6 +6281,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv) crtc_state = to_intel_crtc_state(crtc->base.state); skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal); + crtc_state->wm.skl.raw = crtc_state->wm.skl.optimal; } if (dev_priv->active_pipes) { From a582354c92d102616dc890c1ec261a880befae4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 6 Nov 2020 19:30:39 +0200 Subject: [PATCH 35/66] drm/i915: Pimp the watermark documentation a bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document what each of the "raw" vs. "optimal" vs. "intermediate" watermarks do. Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201106173042.7534-4-ville.syrjala@linux.intel.com --- .../drm/i915/display/intel_display_types.h | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 3d91b116aadc..0c1df34a0cce 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -737,25 +737,34 @@ struct g4x_wm_state { struct intel_crtc_wm_state { union { + /* + * raw: + * The "raw" watermark values produced by the formula + * given the plane's current state. They do not consider + * how much FIFO is actually allocated for each plane. + * + * optimal: + * The "optimal" watermark values given the current + * state of the planes and the amount of FIFO + * allocated to each, ignoring any previous state + * of the planes. + * + * intermediate: + * The "intermediate" watermark values when transitioning + * between the old and new "optimal" values. Used when + * the watermark registers are single buffered and hence + * their state changes asynchronously with regards to the + * actual plane registers. These are essentially the + * worst case combination of the old and new "optimal" + * watermarks, which are therefore safe to use when the + * plane is in either its old or new state. + */ struct { - /* - * Intermediate watermarks; these can be - * programmed immediately since they satisfy - * both the current configuration we're - * switching away from and the new - * configuration we're switching to. - */ struct intel_pipe_wm intermediate; - - /* - * Optimal watermarks, programmed post-vblank - * when this state is committed. - */ struct intel_pipe_wm optimal; } ilk; struct { - /* "raw" watermarks */ struct skl_pipe_wm raw; /* gen9+ only needs 1-step wm programming */ struct skl_pipe_wm optimal; @@ -765,22 +774,15 @@ struct intel_crtc_wm_state { } skl; struct { - /* "raw" watermarks (not inverted) */ - struct g4x_pipe_wm raw[NUM_VLV_WM_LEVELS]; - /* intermediate watermarks (inverted) */ - struct vlv_wm_state intermediate; - /* optimal watermarks (inverted) */ - struct vlv_wm_state optimal; - /* display FIFO split */ + struct g4x_pipe_wm raw[NUM_VLV_WM_LEVELS]; /* not inverted */ + struct vlv_wm_state intermediate; /* inverted */ + struct vlv_wm_state optimal; /* inverted */ struct vlv_fifo_state fifo_state; } vlv; struct { - /* "raw" watermarks */ struct g4x_pipe_wm raw[NUM_G4X_WM_LEVELS]; - /* intermediate watermarks */ struct g4x_wm_state intermediate; - /* optimal watermarks */ struct g4x_wm_state optimal; } g4x; }; From 9c31212b247832d71882a9942f37025544264892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 6 Nov 2020 19:30:40 +0200 Subject: [PATCH 36/66] drm/i915: Precompute can_sagv for each wm level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to remove intel_atomic_crtc_state_for_each_plane_state() from skl_crtc_can_enable_sagv() we can simply precompute whether each wm level can tolerate the SAGV block time latency or not. This has the nice side benefit that we remove the duplicated wm level latency calculation. In fact the copy of that code we had in skl_crtc_can_enable_sagv() didn't even handle WaIncreaseLatencyIPCEnabled/Display WA #1141 whereas the copy in skl_compute_plane_wm() did. So now we just have the one copy which handles all the w/as. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201106173042.7534-5-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 21 +++++++------------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 0c1df34a0cce..86de89d621d8 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -686,6 +686,7 @@ struct skl_wm_level { u8 plane_res_l; bool plane_en; bool ignore_lines; + bool can_sagv; }; struct skl_plane_wm { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 98eec96d5c23..7b747088d3da 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3873,9 +3873,7 @@ static bool skl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_plane *plane; - const struct intel_plane_state *plane_state; - int level, latency; + enum plane_id plane_id; if (!intel_has_sagv(dev_priv)) return false; @@ -3886,9 +3884,10 @@ static bool skl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) if (crtc_state->hw.pipe_mode.flags & DRM_MODE_FLAG_INTERLACE) return false; - intel_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) { + for_each_plane_id_on_crtc(crtc, plane_id) { const struct skl_plane_wm *wm = - &crtc_state->wm.skl.optimal.planes[plane->id]; + &crtc_state->wm.skl.optimal.planes[plane_id]; + int level; /* Skip this plane if it's not enabled */ if (!wm->wm[0].plane_en) @@ -3899,19 +3898,12 @@ static bool skl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) !wm->wm[level].plane_en; --level) { } - latency = dev_priv->wm.skl_latency[level]; - - if (skl_needs_memory_bw_wa(dev_priv) && - plane_state->uapi.fb->modifier == - I915_FORMAT_MOD_X_TILED) - latency += 15; - /* * If any of the planes on this pipe don't enable wm levels that * incur memory latencies higher than sagv_block_time_us we * can't enable SAGV. */ - if (latency < dev_priv->sagv_block_time_us) + if (!wm->wm[level].can_sagv) return false; } @@ -5375,6 +5367,9 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, /* Bspec says: value >= plane ddb allocation -> invalid, hence the +1 here */ result->min_ddb_alloc = max(min_ddb_alloc, res_blocks) + 1; result->plane_en = true; + + if (INTEL_GEN(dev_priv) < 12) + result->can_sagv = latency >= dev_priv->sagv_block_time_us; } static void From ab01630b64ce19e1b845a4d83879eb9727306aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 6 Nov 2020 19:30:41 +0200 Subject: [PATCH 37/66] drm/i915: Store plane relative data rate in crtc_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store the relative data rate for planes in the crtc state so that we don't have to use intel_atomic_crtc_state_for_each_plane_state() to compute it even for the planes that are no part of the current state. Should probably just nuke this stuff entirely an use the normal plane data rate instead. The two are slightly different since this relative data rate doesn't factor in the actual pixel clock, so it's a bit odd thing to even call a "data rate". And since the watermarks are computed based on the actual data rate anyway I don't really see what the point of this relative data rate is. But that's for the future... Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201106173042.7534-6-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- .../drm/i915/display/intel_display_types.h | 4 + drivers/gpu/drm/i915/intel_pm.c | 83 ++++++++++--------- 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 86de89d621d8..5bb7adc1ff3e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1031,6 +1031,10 @@ struct intel_crtc_state { u32 data_rate[I915_MAX_PLANES]; + /* FIXME unify with data_rate[] */ + u64 plane_data_rate[I915_MAX_PLANES]; + u64 uv_plane_data_rate[I915_MAX_PLANES]; + /* Gamma mode programmed on the pipe */ u32 gamma_mode; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7b747088d3da..e5ebaec434f4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4696,50 +4696,63 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state, } static u64 -skl_get_total_relative_data_rate(struct intel_crtc_state *crtc_state, - u64 *plane_data_rate, - u64 *uv_plane_data_rate) +skl_get_total_relative_data_rate(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_plane *plane; + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); const struct intel_plane_state *plane_state; + struct intel_plane *plane; u64 total_data_rate = 0; + enum plane_id plane_id; + int i; /* Calculate and cache data rate for each plane */ - intel_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) { - enum plane_id plane_id = plane->id; - u64 rate; + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + if (plane->pipe != crtc->pipe) + continue; + + plane_id = plane->id; /* packed/y */ - rate = skl_plane_relative_data_rate(crtc_state, plane_state, 0); - plane_data_rate[plane_id] = rate; - total_data_rate += rate; + crtc_state->plane_data_rate[plane_id] = + skl_plane_relative_data_rate(crtc_state, plane_state, 0); /* uv-plane */ - rate = skl_plane_relative_data_rate(crtc_state, plane_state, 1); - uv_plane_data_rate[plane_id] = rate; - total_data_rate += rate; + crtc_state->uv_plane_data_rate[plane_id] = + skl_plane_relative_data_rate(crtc_state, plane_state, 1); + } + + for_each_plane_id_on_crtc(crtc, plane_id) { + total_data_rate += crtc_state->plane_data_rate[plane_id]; + total_data_rate += crtc_state->uv_plane_data_rate[plane_id]; } return total_data_rate; } static u64 -icl_get_total_relative_data_rate(struct intel_crtc_state *crtc_state, - u64 *plane_data_rate) +icl_get_total_relative_data_rate(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_plane *plane; + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); const struct intel_plane_state *plane_state; + struct intel_plane *plane; u64 total_data_rate = 0; + enum plane_id plane_id; + int i; /* Calculate and cache data rate for each plane */ - intel_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) { - enum plane_id plane_id = plane->id; - u64 rate; + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + if (plane->pipe != crtc->pipe) + continue; + + plane_id = plane->id; if (!plane_state->planar_linked_plane) { - rate = skl_plane_relative_data_rate(crtc_state, plane_state, 0); - plane_data_rate[plane_id] = rate; - total_data_rate += rate; + crtc_state->plane_data_rate[plane_id] = + skl_plane_relative_data_rate(crtc_state, plane_state, 0); } else { enum plane_id y_plane_id; @@ -4754,17 +4767,18 @@ icl_get_total_relative_data_rate(struct intel_crtc_state *crtc_state, continue; /* Y plane rate is calculated on the slave */ - rate = skl_plane_relative_data_rate(crtc_state, plane_state, 0); y_plane_id = plane_state->planar_linked_plane->id; - plane_data_rate[y_plane_id] = rate; - total_data_rate += rate; + crtc_state->plane_data_rate[y_plane_id] = + skl_plane_relative_data_rate(crtc_state, plane_state, 0); - rate = skl_plane_relative_data_rate(crtc_state, plane_state, 1); - plane_data_rate[plane_id] = rate; - total_data_rate += rate; + crtc_state->plane_data_rate[plane_id] = + skl_plane_relative_data_rate(crtc_state, plane_state, 1); } } + for_each_plane_id_on_crtc(crtc, plane_id) + total_data_rate += crtc_state->plane_data_rate[plane_id]; + return total_data_rate; } @@ -4796,8 +4810,6 @@ skl_allocate_pipe_ddb(struct intel_atomic_state *state, u64 total_data_rate; enum plane_id plane_id; int num_active; - u64 plane_data_rate[I915_MAX_PLANES] = {}; - u64 uv_plane_data_rate[I915_MAX_PLANES] = {}; u32 blocks; int level; int ret; @@ -4837,13 +4849,10 @@ skl_allocate_pipe_ddb(struct intel_atomic_state *state, if (INTEL_GEN(dev_priv) >= 11) total_data_rate = - icl_get_total_relative_data_rate(crtc_state, - plane_data_rate); + icl_get_total_relative_data_rate(state, crtc); else total_data_rate = - skl_get_total_relative_data_rate(crtc_state, - plane_data_rate, - uv_plane_data_rate); + skl_get_total_relative_data_rate(state, crtc); ret = skl_ddb_get_pipe_allocation_limits(dev_priv, crtc_state, total_data_rate, @@ -4924,7 +4933,7 @@ skl_allocate_pipe_ddb(struct intel_atomic_state *state, if (total_data_rate == 0) break; - rate = plane_data_rate[plane_id]; + rate = crtc_state->plane_data_rate[plane_id]; extra = min_t(u16, alloc_size, DIV64_U64_ROUND_UP(alloc_size * rate, total_data_rate)); @@ -4935,7 +4944,7 @@ skl_allocate_pipe_ddb(struct intel_atomic_state *state, if (total_data_rate == 0) break; - rate = uv_plane_data_rate[plane_id]; + rate = crtc_state->uv_plane_data_rate[plane_id]; extra = min_t(u16, alloc_size, DIV64_U64_ROUND_UP(alloc_size * rate, total_data_rate)); From 3df3fe2412000fec34f9185f67f7c63d37b615ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 6 Nov 2020 19:30:42 +0200 Subject: [PATCH 38/66] drm/i915: Remove skl_adjusted_plane_pixel_rate() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace skl_adjusted_plane_pixel_rate() with the generic intel_plane_pixel_rate(). The two should produce identical results. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201106173042.7534-7-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/intel_pm.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e5ebaec434f4..ad76e0a835d4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -33,6 +33,7 @@ #include #include "display/intel_atomic.h" +#include "display/intel_atomic_plane.h" #include "display/intel_bw.h" #include "display/intel_display_types.h" #include "display/intel_fbc.h" @@ -5102,30 +5103,6 @@ intel_get_linetime_us(const struct intel_crtc_state *crtc_state) return linetime_us; } -static u32 -skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - u64 adjusted_pixel_rate; - uint_fixed_16_16_t downscale_amount; - - /* Shouldn't reach here on disabled planes... */ - if (drm_WARN_ON(&dev_priv->drm, - !intel_wm_plane_visible(crtc_state, plane_state))) - return 0; - - /* - * Adjusted plane pixel rate is just the pipe's adjusted pixel rate - * with additional adjustments for plane-specific scaling. - */ - adjusted_pixel_rate = crtc_state->pixel_rate; - downscale_amount = skl_plane_downscale_amount(crtc_state, plane_state); - - return mul_round_up_u32_fixed16(adjusted_pixel_rate, - downscale_amount); -} - static int skl_compute_wm_params(const struct intel_crtc_state *crtc_state, int width, const struct drm_format_info *format, @@ -5238,7 +5215,7 @@ skl_compute_plane_wm_params(const struct intel_crtc_state *crtc_state, return skl_compute_wm_params(crtc_state, width, fb->format, fb->modifier, plane_state->hw.rotation, - skl_adjusted_plane_pixel_rate(crtc_state, plane_state), + intel_plane_pixel_rate(crtc_state, plane_state), wp, color_plane); } From fdbc5d682e75ed53e923627d7aa79ff0cb134d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 10 Nov 2020 01:12:36 +0200 Subject: [PATCH 39/66] drm/i915: Introduce intel_dpll_get_hw_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a wrapper for the pll .get_hw_state() vfunc. Makes life a bit less miserable when you don't have to worry where the function pointer is stored. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201109231239.17002-1-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/display/intel_display.c | 14 +++++++------ drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 20 ++++++++++++++++--- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 3 +++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2e1d9f98a4d0..56d68e78f058 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10857,6 +10857,7 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc, if (intel_de_read(dev_priv, PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { struct intel_shared_dpll *pll; enum intel_dpll_id pll_id; + bool pll_active; pipe_config->has_pch_encoder = true; @@ -10884,8 +10885,9 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc, intel_get_shared_dpll_by_id(dev_priv, pll_id); pll = pipe_config->shared_dpll; - drm_WARN_ON(dev, !pll->info->funcs->get_hw_state(dev_priv, pll, - &pipe_config->dpll_hw_state)); + pll_active = intel_dpll_get_hw_state(dev_priv, pll, + &pipe_config->dpll_hw_state); + drm_WARN_ON(dev, !pll_active); tmp = pipe_config->dpll_hw_state.dpll; pipe_config->pixel_multiplier = @@ -11276,9 +11278,9 @@ static void hsw_get_ddi_port_state(struct intel_crtc *crtc, pll = pipe_config->shared_dpll; if (pll) { - drm_WARN_ON(&dev_priv->drm, - !pll->info->funcs->get_hw_state(dev_priv, pll, - &pipe_config->dpll_hw_state)); + bool pll_active = intel_dpll_get_hw_state(dev_priv, pll, + &pipe_config->dpll_hw_state); + drm_WARN_ON(&dev_priv->drm, !pll_active); } /* @@ -14553,7 +14555,7 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv, drm_dbg_kms(&dev_priv->drm, "%s\n", pll->info->name); - active = pll->info->funcs->get_hw_state(dev_priv, pll, &dpll_hw_state); + active = intel_dpll_get_hw_state(dev_priv, pll, &dpll_hw_state); if (!(pll->info->flags & INTEL_DPLL_ALWAYS_ON)) { I915_STATE_WARN(!pll->on && pll->active_mask, diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index a95e6a2ac698..1604c20bac33 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -141,7 +141,7 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, "asserting DPLL %s with no DPLL\n", onoff(state))) return; - cur_state = pll->info->funcs->get_hw_state(dev_priv, pll, &hw_state); + cur_state = intel_dpll_get_hw_state(dev_priv, pll, &hw_state); I915_STATE_WARN(cur_state != state, "%s assertion failure (expected %s, current %s)\n", pll->info->name, onoff(state), onoff(cur_state)); @@ -4527,13 +4527,27 @@ int intel_dpll_get_freq(struct drm_i915_private *i915, return pll->info->funcs->get_freq(i915, pll); } +/** + * intel_dpll_get_hw_state - readout the DPLL's hardware state + * @i915: i915 device + * @pll: DPLL for which to calculate the output frequency + * @hw_state: DPLL's hardware state + * + * Read out @pll's hardware state into @hw_state. + */ +bool intel_dpll_get_hw_state(struct drm_i915_private *i915, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + return pll->info->funcs->get_hw_state(i915, pll, hw_state); +} + static void readout_dpll_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll) { struct intel_crtc *crtc; - pll->on = pll->info->funcs->get_hw_state(i915, pll, - &pll->state.hw_state); + pll->on = intel_dpll_get_hw_state(i915, pll, &pll->state.hw_state); if (IS_JSL_EHL(i915) && pll->on && pll->info->id == DPLL_ID_EHL_DPLL4) { diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 205542fb8dc7..4357f92eafd6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -400,6 +400,9 @@ void intel_update_active_dpll(struct intel_atomic_state *state, struct intel_encoder *encoder); int intel_dpll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll); +bool intel_dpll_get_hw_state(struct drm_i915_private *i915, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state); void intel_prepare_shared_dpll(const struct intel_crtc_state *crtc_state); void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state); void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state); From b97fcaeee23c1db1dbfffbfb946a5cceeede5958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 10 Nov 2020 01:12:37 +0200 Subject: [PATCH 40/66] drm/i915: Move intel_dpll_get_hw_state() into the hsw+ platform specific functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On icl+ we want to populate both crtc_state.{shared_dpll,dpll_hw_state} and crtc_state.port_dplls[] during readout, whereas on pre-icl we want to leave the latter stuff untouched. Rather than adding more ifs into hsw_get_ddi_port_state() to copy the DPLL hw state around let's just move the whole dpll readout into hsw_get_ddi_dpll() & co. Slightly repetitive, but meh. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201109231239.17002-2-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/display/intel_display.c | 68 +++++++++++++++----- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 56d68e78f058..f6732b737670 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10940,7 +10940,10 @@ static void dg1_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, { enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT; enum phy phy = intel_port_to_phy(dev_priv, port); + struct icl_port_dpll *port_dpll; + struct intel_shared_dpll *pll; enum intel_dpll_id id; + bool pll_active; u32 clk_sel; clk_sel = intel_de_read(dev_priv, DG1_DPCLKA_CFGCR0(phy)) & DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); @@ -10949,8 +10952,13 @@ static void dg1_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, if (WARN_ON(id > DPLL_ID_DG1_DPLL3)) return; - pipe_config->icl_port_dplls[port_dpll_id].pll = - intel_get_shared_dpll_by_id(dev_priv, id); + pll = intel_get_shared_dpll_by_id(dev_priv, id); + port_dpll = &pipe_config->icl_port_dplls[port_dpll_id]; + + port_dpll->pll = pll; + pll_active = intel_dpll_get_hw_state(dev_priv, pll, + &port_dpll->hw_state); + drm_WARN_ON(&dev_priv->drm, !pll_active); icl_set_active_port_dpll(pipe_config, port_dpll_id); } @@ -10958,7 +10966,9 @@ static void dg1_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, static void cnl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) { + struct intel_shared_dpll *pll; enum intel_dpll_id id; + bool pll_active; u32 temp; temp = intel_de_read(dev_priv, DPCLKA_CFGCR0) & DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); @@ -10967,7 +10977,12 @@ static void cnl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, if (drm_WARN_ON(&dev_priv->drm, id < SKL_DPLL0 || id > SKL_DPLL2)) return; - pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); + pll = intel_get_shared_dpll_by_id(dev_priv, id); + + pipe_config->shared_dpll = pll; + pll_active = intel_dpll_get_hw_state(dev_priv, pll, + &pipe_config->dpll_hw_state); + drm_WARN_ON(&dev_priv->drm, !pll_active); } static void icl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, @@ -10975,7 +10990,10 @@ static void icl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, { enum phy phy = intel_port_to_phy(dev_priv, port); enum icl_port_dpll_id port_dpll_id; + struct icl_port_dpll *port_dpll; + struct intel_shared_dpll *pll; enum intel_dpll_id id; + bool pll_active; u32 temp; if (intel_phy_is_combo(dev_priv, phy)) { @@ -11010,8 +11028,13 @@ static void icl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, return; } - pipe_config->icl_port_dplls[port_dpll_id].pll = - intel_get_shared_dpll_by_id(dev_priv, id); + pll = intel_get_shared_dpll_by_id(dev_priv, id); + port_dpll = &pipe_config->icl_port_dplls[port_dpll_id]; + + port_dpll->pll = pll; + pll_active = intel_dpll_get_hw_state(dev_priv, pll, + &port_dpll->hw_state); + drm_WARN_ON(&dev_priv->drm, !pll_active); icl_set_active_port_dpll(pipe_config, port_dpll_id); } @@ -11020,7 +11043,9 @@ static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) { + struct intel_shared_dpll *pll; enum intel_dpll_id id; + bool pll_active; switch (port) { case PORT_A: @@ -11037,13 +11062,20 @@ static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv, return; } - pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); + pll = intel_get_shared_dpll_by_id(dev_priv, id); + + pipe_config->shared_dpll = pll; + pll_active = intel_dpll_get_hw_state(dev_priv, pll, + &pipe_config->dpll_hw_state); + drm_WARN_ON(&dev_priv->drm, !pll_active); } static void skl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) { + struct intel_shared_dpll *pll; enum intel_dpll_id id; + bool pll_active; u32 temp; temp = intel_de_read(dev_priv, DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); @@ -11052,14 +11084,21 @@ static void skl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, if (drm_WARN_ON(&dev_priv->drm, id < SKL_DPLL0 || id > SKL_DPLL3)) return; - pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); + pll = intel_get_shared_dpll_by_id(dev_priv, id); + + pipe_config->shared_dpll = pll; + pll_active = intel_dpll_get_hw_state(dev_priv, pll, + &pipe_config->dpll_hw_state); + drm_WARN_ON(&dev_priv->drm, !pll_active); } static void hsw_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) { + struct intel_shared_dpll *pll; enum intel_dpll_id id; u32 ddi_pll_sel = intel_de_read(dev_priv, PORT_CLK_SEL(port)); + bool pll_active; switch (ddi_pll_sel) { case PORT_CLK_SEL_WRPLL1: @@ -11087,7 +11126,12 @@ static void hsw_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, return; } - pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); + pll = intel_get_shared_dpll_by_id(dev_priv, id); + + pipe_config->shared_dpll = pll; + pll_active = intel_dpll_get_hw_state(dev_priv, pll, + &pipe_config->dpll_hw_state); + drm_WARN_ON(&dev_priv->drm, !pll_active); } static bool hsw_get_transcoder_state(struct intel_crtc *crtc, @@ -11247,7 +11291,6 @@ static void hsw_get_ddi_port_state(struct intel_crtc *crtc, { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; - struct intel_shared_dpll *pll; enum port port; u32 tmp; @@ -11276,13 +11319,6 @@ static void hsw_get_ddi_port_state(struct intel_crtc *crtc, else hsw_get_ddi_pll(dev_priv, port, pipe_config); - pll = pipe_config->shared_dpll; - if (pll) { - bool pll_active = intel_dpll_get_hw_state(dev_priv, pll, - &pipe_config->dpll_hw_state); - drm_WARN_ON(&dev_priv->drm, !pll_active); - } - /* * Haswell has only FDI/PCH transcoder A. It is which is connected to * DDI E. So just check whether this pipe is wired to DDI E and whether From 3749de07bb11b1cc5ad7ec993d879446adae9505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 10 Nov 2020 01:12:38 +0200 Subject: [PATCH 41/66] drm/i915: Use actual readout results for .get_freq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the DPLL .get_freq() uses pll->state.hw_state which is not the thing we actually read out (except during driver load/resume). Outside of that pll->state.hw_state is just the thing we committed last time around. During state check we just read the thing into crtc_state->dpll_hw_state, so that is what we should use for calculating the DPLL output frequency. I think we used to do this so that the results of the readout were actually used, but somehow it got changed when the .get_freq() refactoring happened. Cc: Imre Deak Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201109231239.17002-3-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/display/icl_dsi.c | 3 +- drivers/gpu/drm/i915/display/intel_ddi.c | 3 +- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 78 +++++++++++-------- drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 8 +- 4 files changed, 54 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 096652921453..769bb1b0d543 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1496,7 +1496,8 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder, /* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */ pipe_config->port_clock = intel_dpll_get_freq(i915, - pipe_config->shared_dpll); + pipe_config->shared_dpll, + &pipe_config->dpll_hw_state); pipe_config->hw.adjusted_mode.crtc_clock = intel_dsi->pclk; if (intel_dsi->dual_link) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index d4b1b73c7aab..9d80e47e9558 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1755,7 +1755,8 @@ static void intel_ddi_clock_get(struct intel_encoder *encoder, encoder->port); else pipe_config->port_clock = - intel_dpll_get_freq(dev_priv, pipe_config->shared_dpll); + intel_dpll_get_freq(dev_priv, pipe_config->shared_dpll, + &pipe_config->dpll_hw_state); ddi_dotclock_get(pipe_config); } diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 1604c20bac33..0f14c4dee02c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -891,11 +891,12 @@ hsw_ddi_wrpll_get_dpll(struct intel_atomic_state *state, } static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { int refclk; int n, p, r; - u32 wrpll = pll->state.hw_state.wrpll; + u32 wrpll = pll_state->wrpll; switch (wrpll & WRPLL_REF_MASK) { case WRPLL_REF_SPECIAL_HSW: @@ -962,7 +963,8 @@ hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) } static int hsw_ddi_lcpll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { int link_clock = 0; @@ -1002,11 +1004,12 @@ hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, } static int hsw_ddi_spll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { int link_clock = 0; - switch (pll->state.hw_state.spll & SPLL_FREQ_MASK) { + switch (pll_state->spll & SPLL_FREQ_MASK) { case SPLL_FREQ_810MHz: link_clock = 81000; break; @@ -1577,9 +1580,9 @@ static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state) } static int skl_ddi_wrpll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { - const struct intel_dpll_hw_state *pll_state = &pll->state.hw_state; int ref_clock = i915->dpll.ref_clks.nssc; u32 p0, p1, p2, dco_freq; @@ -1688,12 +1691,12 @@ skl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) } static int skl_ddi_lcpll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { int link_clock = 0; - switch ((pll->state.hw_state.ctrl1 & - DPLL_CTRL1_LINK_RATE_MASK(0)) >> + switch ((pll_state->ctrl1 & DPLL_CTRL1_LINK_RATE_MASK(0)) >> DPLL_CTRL1_LINK_RATE_SHIFT(0)) { case DPLL_CTRL1_LINK_RATE_810: link_clock = 81000; @@ -1771,16 +1774,17 @@ static bool skl_get_dpll(struct intel_atomic_state *state, } static int skl_ddi_pll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { /* * ctrl1 register is already shifted for each pll, just use 0 to get * the internal shift for each field */ - if (pll->state.hw_state.ctrl1 & DPLL_CTRL1_HDMI_MODE(0)) - return skl_ddi_wrpll_get_freq(i915, pll); + if (pll_state->ctrl1 & DPLL_CTRL1_HDMI_MODE(0)) + return skl_ddi_wrpll_get_freq(i915, pll, pll_state); else - return skl_ddi_lcpll_get_freq(i915, pll); + return skl_ddi_lcpll_get_freq(i915, pll, pll_state); } static void skl_update_dpll_ref_clks(struct drm_i915_private *i915) @@ -2218,9 +2222,9 @@ bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc_state *crtc_state) } static int bxt_ddi_pll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { - const struct intel_dpll_hw_state *pll_state = &pll->state.hw_state; struct dpll clock; clock.m1 = 2; @@ -2650,9 +2654,9 @@ ehl_combo_pll_div_frac_wa_needed(struct drm_i915_private *i915) static int __cnl_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state, int ref_clock) { - const struct intel_dpll_hw_state *pll_state = &pll->state.hw_state; u32 dco_fraction; u32 p0, p1, p2, dco_freq; @@ -2711,9 +2715,11 @@ static int __cnl_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, } static int cnl_ddi_wrpll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { - return __cnl_ddi_wrpll_get_freq(i915, pll, i915->dpll.ref_clks.nssc); + return __cnl_ddi_wrpll_get_freq(i915, pll, pll_state, + i915->dpll.ref_clks.nssc); } static bool @@ -2762,11 +2768,12 @@ cnl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) } static int cnl_ddi_lcpll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { int link_clock = 0; - switch (pll->state.hw_state.cfgcr0 & DPLL_CFGCR0_LINK_RATE_MASK) { + switch (pll_state->cfgcr0 & DPLL_CFGCR0_LINK_RATE_MASK) { case DPLL_CFGCR0_LINK_RATE_810: link_clock = 81000; break; @@ -2849,12 +2856,13 @@ static bool cnl_get_dpll(struct intel_atomic_state *state, } static int cnl_ddi_pll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { - if (pll->state.hw_state.cfgcr0 & DPLL_CFGCR0_HDMI_MODE) - return cnl_ddi_wrpll_get_freq(i915, pll); + if (pll_state->cfgcr0 & DPLL_CFGCR0_HDMI_MODE) + return cnl_ddi_wrpll_get_freq(i915, pll, pll_state); else - return cnl_ddi_lcpll_get_freq(i915, pll); + return cnl_ddi_lcpll_get_freq(i915, pll, pll_state); } static void cnl_update_dpll_ref_clks(struct drm_i915_private *i915) @@ -3039,7 +3047,8 @@ static bool icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, } static int icl_ddi_tbt_pll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { /* * The PLL outputs multiple frequencies at the same time, selection is @@ -3075,9 +3084,10 @@ icl_calc_wrpll(struct intel_crtc_state *crtc_state, } static int icl_ddi_combo_pll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { - return __cnl_ddi_wrpll_get_freq(i915, pll, + return __cnl_ddi_wrpll_get_freq(i915, pll, pll_state, icl_wrpll_ref_clock(i915)); } @@ -3402,9 +3412,9 @@ static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, } static int icl_ddi_mg_pll_get_freq(struct drm_i915_private *dev_priv, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { - const struct intel_dpll_hw_state *pll_state = &pll->state.hw_state; u32 m1, m2_int, m2_frac, div1, div2, ref_clock; u64 tmp; @@ -4515,16 +4525,18 @@ void intel_update_active_dpll(struct intel_atomic_state *state, * intel_dpll_get_freq - calculate the DPLL's output frequency * @i915: i915 device * @pll: DPLL for which to calculate the output frequency + * @pll_state: DPLL state from which to calculate the output frequency * - * Return the output frequency corresponding to @pll's current state. + * Return the output frequency corresponding to @pll's passed in @pll_state. */ int intel_dpll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll) + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { if (drm_WARN_ON(&i915->drm, !pll->info->funcs->get_freq)) return 0; - return pll->info->funcs->get_freq(i915, pll); + return pll->info->funcs->get_freq(i915, pll, pll_state); } /** diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index 4357f92eafd6..2eb7618ef957 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -300,10 +300,11 @@ struct intel_shared_dpll_funcs { * @get_freq: * * Hook for calculating the pll's output frequency based on its - * current state. + * passed in state. */ int (*get_freq)(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll); + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state); }; /** @@ -399,7 +400,8 @@ void intel_update_active_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder); int intel_dpll_get_freq(struct drm_i915_private *i915, - const struct intel_shared_dpll *pll); + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state); bool intel_dpll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, struct intel_dpll_hw_state *hw_state); From c9afbf586e4f5a7e681aef38b6f1279fbabc368c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 10 Nov 2020 01:12:39 +0200 Subject: [PATCH 42/66] drm/i915: Relocate cnl_get_ddi_pll() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move cnl_get_ddi_pll() into a better spot from between icl_get_ddi_pll() and dg1_get_ddi_pll(). Also reorder the calls to the skl and bxt functions because ocd. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201109231239.17002-4-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/display/intel_display.c | 48 ++++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index f6732b737670..9e4f2575ecf5 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10963,28 +10963,6 @@ static void dg1_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, icl_set_active_port_dpll(pipe_config, port_dpll_id); } -static void cnl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, - struct intel_crtc_state *pipe_config) -{ - struct intel_shared_dpll *pll; - enum intel_dpll_id id; - bool pll_active; - u32 temp; - - temp = intel_de_read(dev_priv, DPCLKA_CFGCR0) & DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); - id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port); - - if (drm_WARN_ON(&dev_priv->drm, id < SKL_DPLL0 || id > SKL_DPLL2)) - return; - - pll = intel_get_shared_dpll_by_id(dev_priv, id); - - pipe_config->shared_dpll = pll; - pll_active = intel_dpll_get_hw_state(dev_priv, pll, - &pipe_config->dpll_hw_state); - drm_WARN_ON(&dev_priv->drm, !pll_active); -} - static void icl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) { @@ -11039,6 +11017,28 @@ static void icl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, icl_set_active_port_dpll(pipe_config, port_dpll_id); } +static void cnl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, + struct intel_crtc_state *pipe_config) +{ + struct intel_shared_dpll *pll; + enum intel_dpll_id id; + bool pll_active; + u32 temp; + + temp = intel_de_read(dev_priv, DPCLKA_CFGCR0) & DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); + id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port); + + if (drm_WARN_ON(&dev_priv->drm, id < SKL_DPLL0 || id > SKL_DPLL2)) + return; + + pll = intel_get_shared_dpll_by_id(dev_priv, id); + + pipe_config->shared_dpll = pll; + pll_active = intel_dpll_get_hw_state(dev_priv, pll, + &pipe_config->dpll_hw_state); + drm_WARN_ON(&dev_priv->drm, !pll_active); +} + static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) @@ -11312,10 +11312,10 @@ static void hsw_get_ddi_port_state(struct intel_crtc *crtc, icl_get_ddi_pll(dev_priv, port, pipe_config); else if (IS_CANNONLAKE(dev_priv)) cnl_get_ddi_pll(dev_priv, port, pipe_config); - else if (IS_GEN9_BC(dev_priv)) - skl_get_ddi_pll(dev_priv, port, pipe_config); else if (IS_GEN9_LP(dev_priv)) bxt_get_ddi_pll(dev_priv, port, pipe_config); + else if (IS_GEN9_BC(dev_priv)) + skl_get_ddi_pll(dev_priv, port, pipe_config); else hsw_get_ddi_pll(dev_priv, port, pipe_config); From 2ca5a7b85b0c2b97ef08afbd7799b022e29f192e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 10 Nov 2020 23:04:47 +0200 Subject: [PATCH 43/66] drm/i915: Handle max_bpc==16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EDID can declare the maximum supported bpc up to 16, and apparently there are displays that do so. Currently we assume 12 bpc is tha max. Fix the assumption and toss in a MISSING_CASE() for any other value we don't expect to see. This fixes modesets with a display with EDID max bpc > 12. Previously any modeset would just silently fail on platforms that didn't otherwise limit this via the max_bpc property. In particular we don't add the max_bpc property to HDMI ports on gmch platforms, and thus we would see the raw max_bpc coming from the EDID. I suppose we could already adjust this to also allow 16bpc, but seeing as no current platform supports that there is little point. Cc: stable@vger.kernel.org Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2632 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201110210447.27454-1-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 9e4f2575ecf5..bc532711470b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -13043,10 +13043,11 @@ compute_sink_pipe_bpp(const struct drm_connector_state *conn_state, case 10 ... 11: bpp = 10 * 3; break; - case 12: + case 12 ... 16: bpp = 12 * 3; break; default: + MISSING_CASE(conn_state->max_bpc); return -EINVAL; } From b896898c73696a7bbe6af36e8d5e8f394a5013f2 Mon Sep 17 00:00:00 2001 From: Bob Paauwe Date: Tue, 10 Nov 2020 17:47:00 +0530 Subject: [PATCH 44/66] drm/i915: Tweaked Wa_14010685332 for PCHs used on gen11 platforms The WA specifies that we need to toggle a SDE chicken bit on and then off as the final step in preparation for s0ix entry. Bspec: 33450 Bspec: 8402 However, something is happening after we toggle the bit that causes the WA to be invalidated. This makes dispcnlunit1_cp_xosc_clkreq active being already in s0ix state i.e SLP_S0 counter incremented. Tweaking the Wa_14010685332 by setting the bit on suspend and clearing it on resume turns down the dispcnlunit1_cp_xosc_clkreq. B.Spec has Documented this tweaked sequence of WA as an alternative. Let keep this tweaked WA for Gen11 platforms and keep untweaked WA for other platforms which never observed this issue. v2 (MattR): - Change the comment on the workaround to give PCH names rather than platform names. Although the bspec is setup to list workarounds by platform, the hardware team has confirmed that the actual issue being worked around here is something that was introduced back in the Cannon Lake PCH and carried forward to subsequent PCH's. - Extend the untweaked version of the workaround to include PCH_CNP as well. Note that since PCH_CNP is used to represent CMP, this will apply on CML and some variants of RKL too. - Cap the untweaked version of the workaround so that it won't apply to "fake" PCH's (i.e., DG1). The issue we're working around really is an issue in the PCH itself, not the South Display, so it shouldn't apply when there isn't a real PCH. v3: - use intel_de_rmw(). [Rodrigo] Cc: Rodrigo Vivi Signed-off-by: Bob Paauwe Signed-off-by: Anshuman Gupta Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20201110121700.4338-1-anshuman.gupta@intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display_power.c | 13 +++++++++++-- drivers/gpu/drm/i915/i915_irq.c | 6 ++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 31cb9ac5c489..fe2d90bba536 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5852,10 +5852,15 @@ static void intel_power_domains_verify_state(struct drm_i915_private *i915) void intel_display_power_suspend_late(struct drm_i915_private *i915) { - if (INTEL_GEN(i915) >= 11 || IS_GEN9_LP(i915)) + if (INTEL_GEN(i915) >= 11 || IS_GEN9_LP(i915)) { bxt_enable_dc9(i915); - else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) + /* Tweaked Wa_14010685332:icp,jsp,mcc */ + if (INTEL_PCH_TYPE(i915) >= PCH_ICP && INTEL_PCH_TYPE(i915) <= PCH_MCC) + intel_de_rmw(i915, SOUTH_CHICKEN1, + SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS); + } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) { hsw_enable_pc8(i915); + } } void intel_display_power_resume_early(struct drm_i915_private *i915) @@ -5863,6 +5868,10 @@ void intel_display_power_resume_early(struct drm_i915_private *i915) if (INTEL_GEN(i915) >= 11 || IS_GEN9_LP(i915)) { gen9_sanitize_dc_state(i915); bxt_disable_dc9(i915); + /* Tweaked Wa_14010685332:icp,jsp,mcc */ + if (INTEL_PCH_TYPE(i915) >= PCH_ICP && INTEL_PCH_TYPE(i915) <= PCH_MCC) + intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0); + } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) { hsw_disable_pc8(i915); } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 01f5749a5905..dc6febc63f1c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3058,8 +3058,10 @@ static void gen11_display_irq_reset(struct drm_i915_private *dev_priv) if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) GEN3_IRQ_RESET(uncore, SDE); - /* Wa_14010685332:icl,jsl,ehl,tgl,rkl */ - if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) { + /* Wa_14010685332:cnp/cmp,tgp,adp */ + if (INTEL_PCH_TYPE(dev_priv) == PCH_CNP || + (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP && + INTEL_PCH_TYPE(dev_priv) < PCH_DG1)) { intel_uncore_rmw(uncore, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS); intel_uncore_rmw(uncore, SOUTH_CHICKEN1, From 83566d13704a2bfe75d0700a445d4ea30de60673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 17 Nov 2020 17:40:28 +0200 Subject: [PATCH 45/66] drm/i915: Fix the DDI encoder names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I totally fumbled the ?: usage when generating the DDI encoder names. Reverse the things that need reversing, and to make it a bit less messy add a few macros to hide the arithmetic on the port enums. Cc: Jani Nikula Fixes: 2d709a5a624c ("drm/i915: Give DDI encoders even better names") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201117154028.8516-1-ville.syrjala@linux.intel.com Reviewed-by: Lucas De Marchi --- drivers/gpu/drm/i915/display/intel_ddi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 9d80e47e9558..2de2c69db7f2 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -5295,6 +5295,9 @@ static enum hpd_pin cnl_hpd_pin(struct drm_i915_private *dev_priv, return HPD_PORT_A + port - PORT_A; } +#define port_tc_name(port) ((port) - PORT_TC1 + '1') +#define tc_port_name(tc_port) ((tc_port) - TC_PORT_1 + '1') + void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) { struct intel_digital_port *dig_port; @@ -5350,9 +5353,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) DRM_MODE_ENCODER_TMDS, "DDI %s%c/PHY %s%c", port >= PORT_TC1 ? "TC" : "", - port >= PORT_TC1 ? port_name(port) : port - PORT_TC1 + '1', + port >= PORT_TC1 ? port_tc_name(port) : port_name(port), tc_port != TC_PORT_NONE ? "TC" : "", - tc_port != TC_PORT_NONE ? phy_name(phy) : tc_port - TC_PORT_1 + '1'); + tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy)); } else if (INTEL_GEN(dev_priv) >= 11) { enum tc_port tc_port = intel_port_to_tc(dev_priv, port); @@ -5362,7 +5365,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) port_name(port), port >= PORT_C ? " (TC)" : "", tc_port != TC_PORT_NONE ? "TC" : "", - tc_port != TC_PORT_NONE ? phy_name(phy) : tc_port - TC_PORT_1 + '1'); + tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy)); } else { drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs, DRM_MODE_ENCODER_TMDS, From e85e7458298783fe3b3a43383090df1a0de1bfa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 17 Nov 2020 11:47:04 -0800 Subject: [PATCH 46/66] drm/i915: Copy the plane hw state directly for Y planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When doing the plane state copy from the UV plane to the Y plane let's just copy the hw state directly instead of using the original uapi state. The UV plane has already had its uapi state copied into its hw state, so this extra detour via the uapi state for the Y plane is pointless. Signed-off-by: Ville Syrjälä Reviewed-by: Stanislav Lisovskiy Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-2-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_atomic_plane.c | 12 ++++++++++++ drivers/gpu/drm/i915/display/intel_atomic_plane.h | 2 ++ drivers/gpu/drm/i915/display/intel_display.c | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 3334ff253600..f47558efb3c2 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -265,6 +265,18 @@ void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, plane_state->hw.scaling_filter = from_plane_state->uapi.scaling_filter; } +void intel_plane_copy_hw_state(struct intel_plane_state *plane_state, + const struct intel_plane_state *from_plane_state) +{ + intel_plane_clear_hw_state(plane_state); + + memcpy(&plane_state->hw, &from_plane_state->hw, + sizeof(plane_state->hw)); + + if (plane_state->hw.fb) + drm_framebuffer_get(plane_state->hw.fb); +} + void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index 59dd1fbb02ea..24a3a148aa62 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -25,6 +25,8 @@ unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, const struct intel_plane_state *from_plane_state); +void intel_plane_copy_hw_state(struct intel_plane_state *plane_state, + const struct intel_plane_state *from_plane_state); void intel_update_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index bc532711470b..a1b975ab3bb0 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -12792,7 +12792,7 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) memcpy(linked_state->color_plane, plane_state->color_plane, sizeof(linked_state->color_plane)); - intel_plane_copy_uapi_to_hw_state(linked_state, plane_state); + intel_plane_copy_hw_state(linked_state, plane_state); linked_state->uapi.src = plane_state->uapi.src; linked_state->uapi.dst = plane_state->uapi.dst; From 63dc014e37b97e2f5fad6ab3e68c876e4a0f9886 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 17 Nov 2020 11:47:05 -0800 Subject: [PATCH 47/66] drm/i915/dp: Allow big joiner modes in intel_dp_mode_valid(), v3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Small changes to intel_dp_mode_valid(), allow listing modes that can only be supported in the bigjoiner configuration, which is not supported yet. v13: * Allow bigjoiner if hdisplay >5120 v12: * slice_count logic simplify (Ville) * Fix unnecessary changes in downstream_mode_valid (Ville) v11: * Make intel_dp_can_bigjoiner non static so it can be used in intel_display (Manasi) v10: * Simplify logic (Ville) * Allow bigjoiner on edp (Ville) v9: * Restric Bigjoiner on PORT A (Ville) v8: * use source dotclock for max dotclock (Manasi) v7: * Add can_bigjoiner() helper (Ville) * Pass bigjoiner to plane_size validation (Ville) v6: * Rebase after dp_downstream mode valid changes (Manasi) v5: * Increase max plane width to support 8K with bigjoiner (Maarten) v4: * Rebase (Manasi) Changes since v1: - Disallow bigjoiner on eDP. Changes since v2: - Rename intel_dp_downstream_max_dotclock to intel_dp_max_dotclock, and split off the downstream and source checking to its own function. (Ville) v3: * Rebase (Manasi) Signed-off-by: Manasi Navare Signed-off-by: Maarten Lankhorst [vsyrjala: * Keep bigjoiner disabled until everything is ready * Appease checkpatch] Signed-off-by: Ville Syrjälä Reviewed-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-3-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 5 +- drivers/gpu/drm/i915/display/intel_display.h | 3 +- drivers/gpu/drm/i915/display/intel_dp.c | 81 ++++++++++++++++---- drivers/gpu/drm/i915/display/intel_dp.h | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- drivers/gpu/drm/i915/display/intel_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 2 +- 7 files changed, 76 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index a1b975ab3bb0..16c55d8fe4dc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -17780,7 +17780,8 @@ intel_mode_valid(struct drm_device *dev, enum drm_mode_status intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv, - const struct drm_display_mode *mode) + const struct drm_display_mode *mode, + bool bigjoiner) { int plane_width_max, plane_height_max; @@ -17797,7 +17798,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv, * too big for that. */ if (INTEL_GEN(dev_priv) >= 11) { - plane_width_max = 5120; + plane_width_max = 5120 << bigjoiner; plane_height_max = 4320; } else { plane_width_max = 5120; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 6be14e8571aa..5e0d42d82c11 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -513,7 +513,8 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv, bool intel_plane_can_remap(const struct intel_plane_state *plane_state); enum drm_mode_status intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv, - const struct drm_display_mode *mode); + const struct drm_display_mode *mode, + bool bigjoiner); enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port); bool is_trans_port_sync_mode(const struct intel_crtc_state *state); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ec8359f03aaf..5ad59610eb12 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -254,6 +254,20 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) return max_link_clock * max_lanes; } +bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *encoder = &intel_dig_port->base; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + /* FIXME remove once everything is in place */ + return false; + + return INTEL_GEN(dev_priv) >= 12 || + (INTEL_GEN(dev_priv) == 11 && + encoder->port != PORT_A); +} + static int cnl_max_source_rate(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -519,7 +533,8 @@ small_joiner_ram_size_bits(struct drm_i915_private *i915) static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, u32 link_clock, u32 lane_count, - u32 mode_clock, u32 mode_hdisplay) + u32 mode_clock, u32 mode_hdisplay, + bool bigjoiner) { u32 bits_per_pixel, max_bpp_small_joiner_ram; int i; @@ -537,6 +552,10 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */ max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / mode_hdisplay; + + if (bigjoiner) + max_bpp_small_joiner_ram *= 2; + drm_dbg_kms(&i915->drm, "Max small joiner bpp: %u\n", max_bpp_small_joiner_ram); @@ -546,6 +565,15 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, */ bits_per_pixel = min(bits_per_pixel, max_bpp_small_joiner_ram); + if (bigjoiner) { + u32 max_bpp_bigjoiner = + i915->max_cdclk_freq * 48 / + intel_dp_mode_to_fec_clock(mode_clock); + + DRM_DEBUG_KMS("Max big joiner bpp: %u\n", max_bpp_bigjoiner); + bits_per_pixel = min(bits_per_pixel, max_bpp_bigjoiner); + } + /* Error out if the max bpp is less than smallest allowed valid bpp */ if (bits_per_pixel < valid_dsc_bpp[0]) { drm_dbg_kms(&i915->drm, "Unsupported BPP %u, min %u\n", @@ -568,7 +596,8 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915, } static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, - int mode_clock, int mode_hdisplay) + int mode_clock, int mode_hdisplay, + bool bigjoiner) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); u8 min_slice_count, i; @@ -595,12 +624,18 @@ static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, /* Find the closest match to the valid slice count values */ for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) { - if (valid_dsc_slicecount[i] > - drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd, - false)) + u8 test_slice_count = valid_dsc_slicecount[i] << bigjoiner; + + if (test_slice_count > + drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd, false)) break; - if (min_slice_count <= valid_dsc_slicecount[i]) - return valid_dsc_slicecount[i]; + + /* big joiner needs small joiner to be enabled */ + if (bigjoiner && test_slice_count < 4) + continue; + + if (min_slice_count <= test_slice_count) + return test_slice_count; } drm_dbg_kms(&i915->drm, "Unsupported Slice Count %d\n", @@ -717,6 +752,7 @@ intel_dp_mode_valid(struct drm_connector *connector, u16 dsc_max_output_bpp = 0; u8 dsc_slice_count = 0; enum drm_mode_status status; + bool dsc = false, bigjoiner = false; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; @@ -737,6 +773,14 @@ intel_dp_mode_valid(struct drm_connector *connector, if (mode->clock < 10000) return MODE_CLOCK_LOW; + if ((target_clock > max_dotclk || mode->hdisplay > 5120) && + intel_dp_can_bigjoiner(intel_dp)) { + bigjoiner = true; + max_dotclk *= 2; + } + if (target_clock > max_dotclk) + return MODE_CLOCK_HIGH; + max_link_clock = intel_dp_max_link_rate(intel_dp); max_lanes = intel_dp_max_lane_count(intel_dp); @@ -765,16 +809,23 @@ intel_dp_mode_valid(struct drm_connector *connector, max_link_clock, max_lanes, target_clock, - mode->hdisplay) >> 4; + mode->hdisplay, + bigjoiner) >> 4; dsc_slice_count = intel_dp_dsc_get_slice_count(intel_dp, target_clock, - mode->hdisplay); + mode->hdisplay, + bigjoiner); } + + dsc = dsc_max_output_bpp && dsc_slice_count; } - if ((mode_rate > max_rate && !(dsc_max_output_bpp && dsc_slice_count)) || - target_clock > max_dotclk) + /* big joiner configuration needs DSC */ + if (bigjoiner && !dsc) + return MODE_CLOCK_HIGH; + + if (mode_rate > max_rate && !dsc) return MODE_CLOCK_HIGH; status = intel_dp_mode_valid_downstream(intel_connector, @@ -782,7 +833,7 @@ intel_dp_mode_valid(struct drm_connector *connector, if (status != MODE_OK) return status; - return intel_mode_valid_max_plane_size(dev_priv, mode); + return intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner); } u32 intel_dp_pack_aux(const u8 *src, int src_bytes) @@ -2351,11 +2402,13 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, pipe_config->port_clock, pipe_config->lane_count, adjusted_mode->crtc_clock, - adjusted_mode->crtc_hdisplay); + adjusted_mode->crtc_hdisplay, + false); dsc_dp_slice_count = intel_dp_dsc_get_slice_count(intel_dp, adjusted_mode->crtc_clock, - adjusted_mode->crtc_hdisplay); + adjusted_mode->crtc_hdisplay, + false); if (!dsc_max_output_bpp || !dsc_dp_slice_count) { drm_dbg_kms(&dev_priv->drm, "Compressed BPP/Slice Count not supported\n"); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 3f862b4fd34f..b871a09b6901 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -106,6 +106,7 @@ bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp); bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp); int intel_dp_link_required(int pixel_clock, int bpp); int intel_dp_max_data_rate(int max_link_clock, int max_lanes); +bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp); bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); void intel_dp_compute_psr_vsc_sdp(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index c8fcec4d0788..0c8684634fca 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -714,7 +714,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, return 0; } - *status = intel_mode_valid_max_plane_size(dev_priv, mode); + *status = intel_mode_valid_max_plane_size(dev_priv, mode, false); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c index afa4e6817e8c..f453ceb8d149 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.c +++ b/drivers/gpu/drm/i915/display/intel_dsi.c @@ -75,7 +75,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector, return MODE_CLOCK_HIGH; } - return intel_mode_valid_max_plane_size(dev_priv, mode); + return intel_mode_valid_max_plane_size(dev_priv, mode, false); } struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi, diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index f90838bc74fb..82674a8853c6 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2274,7 +2274,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, if (status != MODE_OK) return status; - return intel_mode_valid_max_plane_size(dev_priv, mode); + return intel_mode_valid_max_plane_size(dev_priv, mode, false); } bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, From 19f65a3dbf75b820914ab2fd58a90fa2ce37dc60 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 17 Nov 2020 11:47:06 -0800 Subject: [PATCH 48/66] drm/i915: Try to make bigjoiner work in atomic check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the clock is higher than the dotclock, try with 2 pipes enabled. If we can enable 2, then we will go into big joiner mode, and steal the adjacent crtc. This only links the crtc's in software, no hardware or plane programming is done yet. Blobs are also copied from the master's crtc_state, so it doesn't depend at commit time on the other crtc_state. v6: * Enable dSC for any mode->hdisplay > 5120 v5: * Remove intel_dp_max_dotclock (Manasi) v4: * Fixes in intel_crtc_compute_config (Ville) v3: * Manual Rebase (Manasi) Changes since v1: - Rename pipe timings to transcoder timings, as they are now different. Changes since v2: - Rework bigjoiner checks; always disable slave when recalculating master. No need to have a separate bigjoiner pass any more. - Use pipe_mode instead of transcoder_mode, to clean up the code. Signed-off-by: Maarten Lankhorst Signed-off-by: Manasi Navare [vsyrjala: * hskew isn't a thing * Do the dsc compute if bigjoiner is enabled, not the other way around] Signed-off-by: Ville Syrjälä Reviewed-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-4-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 156 +++++++++++++++++- .../drm/i915/display/intel_display_types.h | 9 + drivers/gpu/drm/i915/display/intel_dp.c | 20 ++- 3 files changed, 175 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 16c55d8fe4dc..70c68082f7fc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8194,6 +8194,19 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, int clock_limit = dev_priv->max_dotclk_freq; drm_mode_copy(pipe_mode, &pipe_config->hw.adjusted_mode); + + /* Adjust pipe_mode for bigjoiner, with half the horizontal mode */ + if (pipe_config->bigjoiner) { + pipe_mode->crtc_clock /= 2; + pipe_mode->crtc_hdisplay /= 2; + pipe_mode->crtc_hblank_start /= 2; + pipe_mode->crtc_hblank_end /= 2; + pipe_mode->crtc_hsync_start /= 2; + pipe_mode->crtc_hsync_end /= 2; + pipe_mode->crtc_htotal /= 2; + pipe_config->pipe_src_w /= 2; + } + intel_mode_from_crtc_timings(pipe_mode, pipe_mode); if (INTEL_GEN(dev_priv) < 4) { @@ -12917,6 +12930,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, if (mode_changed && crtc_state->hw.enable && dev_priv->display.crtc_compute_clock && + !crtc_state->bigjoiner_slave && !drm_WARN_ON(&dev_priv->drm, crtc_state->shared_dpll)) { ret = dev_priv->display.crtc_compute_clock(crtc, crtc_state); if (ret) @@ -13462,6 +13476,15 @@ intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_atomic_state *state, { const struct intel_crtc_state *from_crtc_state = crtc_state; + if (crtc_state->bigjoiner_slave) { + from_crtc_state = intel_atomic_get_new_crtc_state(state, + crtc_state->bigjoiner_linked_crtc); + + /* No need to copy state if the master state is unchanged */ + if (!from_crtc_state) + return; + } + intel_crtc_copy_color_blobs(crtc_state, from_crtc_state); } @@ -13497,6 +13520,47 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state crtc_state->hw.ctm); } +static int +copy_bigjoiner_crtc_state(struct intel_crtc_state *crtc_state, + const struct intel_crtc_state *from_crtc_state) +{ + struct intel_crtc_state *saved_state; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + saved_state = kmemdup(from_crtc_state, sizeof(*saved_state), GFP_KERNEL); + if (!saved_state) + return -ENOMEM; + + saved_state->uapi = crtc_state->uapi; + saved_state->scaler_state = crtc_state->scaler_state; + saved_state->shared_dpll = crtc_state->shared_dpll; + saved_state->dpll_hw_state = crtc_state->dpll_hw_state; + saved_state->crc_enabled = crtc_state->crc_enabled; + + intel_crtc_free_hw_state(crtc_state); + memcpy(crtc_state, saved_state, sizeof(*crtc_state)); + kfree(saved_state); + + /* Re-init hw state */ + memset(&crtc_state->hw, 0, sizeof(saved_state->hw)); + crtc_state->hw.enable = from_crtc_state->hw.enable; + crtc_state->hw.active = from_crtc_state->hw.active; + crtc_state->hw.pipe_mode = from_crtc_state->hw.pipe_mode; + crtc_state->hw.adjusted_mode = from_crtc_state->hw.adjusted_mode; + + /* Some fixups */ + crtc_state->uapi.mode_changed = from_crtc_state->uapi.mode_changed; + crtc_state->uapi.connectors_changed = from_crtc_state->uapi.connectors_changed; + crtc_state->uapi.active_changed = from_crtc_state->uapi.active_changed; + crtc_state->nv12_planes = crtc_state->c8_planes = crtc_state->update_planes = 0; + crtc_state->bigjoiner_linked_crtc = to_intel_crtc(from_crtc_state->uapi.crtc); + crtc_state->bigjoiner_slave = true; + crtc_state->cpu_transcoder = (enum transcoder)crtc->pipe; + crtc_state->has_audio = false; + + return 0; +} + static int intel_crtc_prepare_cleared_state(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state) @@ -15079,6 +15143,75 @@ static bool intel_cpu_transcoders_need_modeset(struct intel_atomic_state *state, return false; } +static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_crtc_state *old_crtc_state, + struct intel_crtc_state *new_crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_crtc_state *slave_crtc_state, *master_crtc_state; + struct intel_crtc *slave, *master; + + /* slave being enabled, is master is still claiming this crtc? */ + if (old_crtc_state->bigjoiner_slave) { + slave = crtc; + master = old_crtc_state->bigjoiner_linked_crtc; + master_crtc_state = intel_atomic_get_new_crtc_state(state, master); + if (!master_crtc_state || !needs_modeset(master_crtc_state)) + goto claimed; + } + + if (!new_crtc_state->bigjoiner) + return 0; + + if (1 + crtc->pipe >= INTEL_NUM_PIPES(dev_priv)) { + DRM_DEBUG_KMS("[CRTC:%d:%s] Big joiner configuration requires " + "CRTC + 1 to be used, doesn't exist\n", + crtc->base.base.id, crtc->base.name); + return -EINVAL; + } + + slave = new_crtc_state->bigjoiner_linked_crtc = + intel_get_crtc_for_pipe(dev_priv, crtc->pipe + 1); + slave_crtc_state = intel_atomic_get_crtc_state(&state->base, slave); + master = crtc; + if (IS_ERR(slave_crtc_state)) + return PTR_ERR(slave_crtc_state); + + /* master being enabled, slave was already configured? */ + if (slave_crtc_state->uapi.enable) + goto claimed; + + DRM_DEBUG_KMS("[CRTC:%d:%s] Used as slave for big joiner\n", + slave->base.base.id, slave->base.name); + + return copy_bigjoiner_crtc_state(slave_crtc_state, new_crtc_state); + +claimed: + DRM_DEBUG_KMS("[CRTC:%d:%s] Slave is enabled as normal CRTC, but " + "[CRTC:%d:%s] claiming this CRTC for bigjoiner.\n", + slave->base.base.id, slave->base.name, + master->base.base.id, master->base.name); + return -EINVAL; +} + +static int kill_bigjoiner_slave(struct intel_atomic_state *state, + struct intel_crtc_state *master_crtc_state) +{ + struct intel_crtc_state *slave_crtc_state = + intel_atomic_get_crtc_state(&state->base, + master_crtc_state->bigjoiner_linked_crtc); + + if (IS_ERR(slave_crtc_state)) + return PTR_ERR(slave_crtc_state); + + slave_crtc_state->bigjoiner = master_crtc_state->bigjoiner = false; + slave_crtc_state->bigjoiner_slave = master_crtc_state->bigjoiner_slave = false; + slave_crtc_state->bigjoiner_linked_crtc = master_crtc_state->bigjoiner_linked_crtc = NULL; + intel_crtc_copy_uapi_to_hw_state(state, slave_crtc_state); + return 0; +} + /** * DOC: asynchronous flip implementation * @@ -15246,16 +15379,33 @@ static int intel_atomic_check(struct drm_device *dev, continue; } + /* Kill old bigjoiner link, we may re-establish afterwards */ + if (old_crtc_state->bigjoiner && !old_crtc_state->bigjoiner_slave) { + ret = kill_bigjoiner_slave(state, new_crtc_state); + if (ret) + goto fail; + } + + if (!new_crtc_state->uapi.enable) { + if (!new_crtc_state->bigjoiner_slave) { + intel_crtc_copy_uapi_to_hw_state(state, new_crtc_state); + any_ms = true; + } + continue; + } + ret = intel_crtc_prepare_cleared_state(state, new_crtc_state); if (ret) goto fail; - if (!new_crtc_state->hw.enable) - continue; - ret = intel_modeset_pipe_config(state, new_crtc_state); if (ret) goto fail; + + ret = intel_atomic_check_bigjoiner(state, crtc, old_crtc_state, + new_crtc_state); + if (ret) + goto fail; } for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 5bb7adc1ff3e..b3d94e6cd7c5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1079,6 +1079,15 @@ struct intel_crtc_state { /* enable pipe csc? */ bool csc_enable; + /* enable pipe big joiner? */ + bool bigjoiner; + + /* big joiner slave crtc? */ + bool bigjoiner_slave; + + /* linked crtc for bigjoiner, either slave or master */ + struct intel_crtc *bigjoiner_linked_crtc; + /* Display Stream compression state */ struct { bool compression_enable; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 5ad59610eb12..9430caf053cd 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2403,12 +2403,12 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, pipe_config->lane_count, adjusted_mode->crtc_clock, adjusted_mode->crtc_hdisplay, - false); + pipe_config->bigjoiner); dsc_dp_slice_count = intel_dp_dsc_get_slice_count(intel_dp, adjusted_mode->crtc_clock, adjusted_mode->crtc_hdisplay, - false); + pipe_config->bigjoiner); if (!dsc_max_output_bpp || !dsc_dp_slice_count) { drm_dbg_kms(&dev_priv->drm, "Compressed BPP/Slice Count not supported\n"); @@ -2424,14 +2424,15 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, * is greater than the maximum Cdclock and if slice count is even * then we need to use 2 VDSC instances. */ - if (adjusted_mode->crtc_clock > dev_priv->max_cdclk_freq) { - if (pipe_config->dsc.slice_count > 1) { - pipe_config->dsc.dsc_split = true; - } else { + if (adjusted_mode->crtc_clock > dev_priv->max_cdclk_freq || + pipe_config->bigjoiner) { + if (pipe_config->dsc.slice_count < 2) { drm_dbg_kms(&dev_priv->drm, "Cannot split stream to use 2 VDSC instances\n"); return -EINVAL; } + + pipe_config->dsc.dsc_split = true; } ret = intel_dp_dsc_compute_params(&dig_port->base, pipe_config); @@ -2502,6 +2503,11 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, intel_dp->common_rates[limits.max_clock], limits.max_bpp, adjusted_mode->crtc_clock); + if ((adjusted_mode->crtc_clock > i915->max_dotclk_freq || + adjusted_mode->crtc_hdisplay > 5120) && + intel_dp_can_bigjoiner(intel_dp)) + pipe_config->bigjoiner = true; + /* * Optimize for slow and wide. This is the place to add alternative * optimization policy. @@ -2510,7 +2516,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, /* enable compression if the mode doesn't fit available BW */ drm_dbg_kms(&i915->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en); - if (ret || intel_dp->force_dsc_en) { + if (ret || intel_dp->force_dsc_en || pipe_config->bigjoiner) { ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, conn_state, &limits); if (ret < 0) From 8a029c113b179188ed74d3624bf10d56f8a98aa9 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Tue, 17 Nov 2020 11:47:07 -0800 Subject: [PATCH 49/66] drm/i915/dp: Modify VDSC helpers to configure DSC for Bigjoiner slave Make vdsc work when no output is enabled. The big joiner needs VDSC on the slave, so enable it and set the appropriate bits. So remove encoder usage from dsc functions. Signed-off-by: Manasi Navare Reviewed-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-5-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_ddi.c | 9 +- drivers/gpu/drm/i915/display/intel_display.c | 3 + drivers/gpu/drm/i915/display/intel_dp.c | 6 +- drivers/gpu/drm/i915/display/intel_vdsc.c | 203 ++++++++++--------- drivers/gpu/drm/i915/display/intel_vdsc.h | 6 +- 6 files changed, 111 insertions(+), 118 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 769bb1b0d543..e83364b5774f 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1492,7 +1492,7 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder, struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - intel_dsc_get_config(encoder, pipe_config); + intel_dsc_get_config(pipe_config); /* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */ pipe_config->port_clock = intel_dpll_get_freq(i915, diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 2de2c69db7f2..055fc5c58ef6 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2296,13 +2296,6 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder, intel_phy_is_tc(dev_priv, phy)) intel_display_power_get(dev_priv, intel_ddi_main_link_aux_domain(dig_port)); - - /* - * VDSC power is needed when DSC is enabled - */ - if (crtc_state->dsc.compression_enable) - intel_display_power_get(dev_priv, - intel_dsc_power_domain(crtc_state)); } void intel_ddi_enable_pipe_clock(struct intel_encoder *encoder, @@ -4577,7 +4570,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder))) return; - intel_dsc_get_config(encoder, pipe_config); + intel_dsc_get_config(pipe_config); temp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (temp & TRANS_DDI_PHSYNC) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 70c68082f7fc..36c780a67721 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7508,6 +7508,9 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state) if (crtc_state->shared_dpll) mask |= BIT_ULL(POWER_DOMAIN_DISPLAY_CORE); + if (crtc_state->dsc.compression_enable) + mask |= BIT_ULL(intel_dsc_power_domain(crtc_state)); + return mask; } diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9430caf053cd..857f39779654 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2103,12 +2103,10 @@ static bool intel_dp_supports_fec(struct intel_dp *intel_dp, static bool intel_dp_supports_dsc(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { - struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - - if (!intel_dp_is_edp(intel_dp) && !crtc_state->fec_enable) + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP) && !crtc_state->fec_enable) return false; - return intel_dsc_source_support(encoder, crtc_state) && + return intel_dsc_source_support(crtc_state) && drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd); } diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index c5735c365659..e2716a67b281 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -332,11 +332,10 @@ static const struct rc_parameters *get_rc_params(u16 compressed_bpp, return &rc_parameters[row_index][column_index]; } -bool intel_dsc_source_support(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state) { const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; enum pipe pipe = crtc->pipe; @@ -490,11 +489,10 @@ intel_dsc_power_domain(const struct intel_crtc_state *crtc_state) return POWER_DOMAIN_TRANSCODER_VDSC_PW2; } -static void intel_dsc_pps_configure(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; enum pipe pipe = crtc->pipe; u32 pps_val = 0; @@ -503,6 +501,9 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, u8 num_vdsc_instances = (crtc_state->dsc.dsc_split) ? 2 : 1; int i = 0; + if (crtc_state->bigjoiner) + num_vdsc_instances *= 2; + /* Populate PICTURE_PARAMETER_SET_0 registers */ pps_val = DSC_VER_MAJ | vdsc_cfg->dsc_version_minor << DSC_VER_MIN_SHIFT | @@ -973,55 +974,6 @@ static void intel_dsc_pps_configure(struct intel_encoder *encoder, } } -void intel_dsc_get_config(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - enum pipe pipe = crtc->pipe; - enum intel_display_power_domain power_domain; - intel_wakeref_t wakeref; - u32 dss_ctl1, dss_ctl2, val; - - if (!intel_dsc_source_support(encoder, crtc_state)) - return; - - power_domain = intel_dsc_power_domain(crtc_state); - - wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); - if (!wakeref) - return; - - if (!is_pipe_dsc(crtc_state)) { - dss_ctl1 = intel_de_read(dev_priv, DSS_CTL1); - dss_ctl2 = intel_de_read(dev_priv, DSS_CTL2); - } else { - dss_ctl1 = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe)); - dss_ctl2 = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL2(pipe)); - } - - crtc_state->dsc.compression_enable = dss_ctl2 & LEFT_BRANCH_VDSC_ENABLE; - if (!crtc_state->dsc.compression_enable) - goto out; - - crtc_state->dsc.dsc_split = (dss_ctl2 & RIGHT_BRANCH_VDSC_ENABLE) && - (dss_ctl1 & JOINER_ENABLE); - - /* FIXME: add more state readout as needed */ - - /* PPS1 */ - if (!is_pipe_dsc(crtc_state)) - val = intel_de_read(dev_priv, DSCA_PICTURE_PARAMETER_SET_1); - else - val = intel_de_read(dev_priv, - ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe)); - vdsc_cfg->bits_per_pixel = val; - crtc_state->dsc.compressed_bpp = vdsc_cfg->bits_per_pixel >> 4; -out: - intel_display_power_put(dev_priv, power_domain, wakeref); -} - static void intel_dsc_dsi_pps_write(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { @@ -1060,77 +1012,126 @@ static void intel_dsc_dp_pps_write(struct intel_encoder *encoder, sizeof(dp_dsc_pps_sdp)); } +static i915_reg_t dss_ctl1_reg(const struct intel_crtc_state *crtc_state) +{ + enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; + + if (crtc_state->cpu_transcoder == TRANSCODER_EDP) + return DSS_CTL1; + + return ICL_PIPE_DSS_CTL1(pipe); +} + +static i915_reg_t dss_ctl2_reg(const struct intel_crtc_state *crtc_state) +{ + enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; + + if (crtc_state->cpu_transcoder == TRANSCODER_EDP) + return DSS_CTL2; + + return ICL_PIPE_DSS_CTL2(pipe); +} + void intel_dsc_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum pipe pipe = crtc->pipe; - i915_reg_t dss_ctl1_reg, dss_ctl2_reg; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dss_ctl1_val = 0; u32 dss_ctl2_val = 0; if (!crtc_state->dsc.compression_enable) return; - /* Enable Power wells for VDSC/joining */ - intel_display_power_get(dev_priv, - intel_dsc_power_domain(crtc_state)); + intel_dsc_pps_configure(crtc_state); - intel_dsc_pps_configure(encoder, crtc_state); - - if (encoder->type == INTEL_OUTPUT_DSI) - intel_dsc_dsi_pps_write(encoder, crtc_state); - else - intel_dsc_dp_pps_write(encoder, crtc_state); - - if (!is_pipe_dsc(crtc_state)) { - dss_ctl1_reg = DSS_CTL1; - dss_ctl2_reg = DSS_CTL2; - } else { - dss_ctl1_reg = ICL_PIPE_DSS_CTL1(pipe); - dss_ctl2_reg = ICL_PIPE_DSS_CTL2(pipe); + if (!crtc_state->bigjoiner_slave) { + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) + intel_dsc_dsi_pps_write(encoder, crtc_state); + else + intel_dsc_dp_pps_write(encoder, crtc_state); } + dss_ctl2_val |= LEFT_BRANCH_VDSC_ENABLE; if (crtc_state->dsc.dsc_split) { dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE; dss_ctl1_val |= JOINER_ENABLE; } - intel_de_write(dev_priv, dss_ctl1_reg, dss_ctl1_val); - intel_de_write(dev_priv, dss_ctl2_reg, dss_ctl2_val); + if (crtc_state->bigjoiner) { + dss_ctl1_val |= BIG_JOINER_ENABLE; + if (!crtc_state->bigjoiner_slave) + dss_ctl1_val |= MASTER_BIG_JOINER_ENABLE; + } + intel_de_write(dev_priv, dss_ctl1_reg(crtc_state), dss_ctl1_val); + intel_de_write(dev_priv, dss_ctl2_reg(crtc_state), dss_ctl2_val); } void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - i915_reg_t dss_ctl1_reg, dss_ctl2_reg; - u32 dss_ctl1_val = 0, dss_ctl2_val = 0; if (!old_crtc_state->dsc.compression_enable) return; - if (!is_pipe_dsc(old_crtc_state)) { - dss_ctl1_reg = DSS_CTL1; - dss_ctl2_reg = DSS_CTL2; - } else { - dss_ctl1_reg = ICL_PIPE_DSS_CTL1(pipe); - dss_ctl2_reg = ICL_PIPE_DSS_CTL2(pipe); - } - dss_ctl1_val = intel_de_read(dev_priv, dss_ctl1_reg); - if (dss_ctl1_val & JOINER_ENABLE) - dss_ctl1_val &= ~JOINER_ENABLE; - intel_de_write(dev_priv, dss_ctl1_reg, dss_ctl1_val); - - dss_ctl2_val = intel_de_read(dev_priv, dss_ctl2_reg); - if (dss_ctl2_val & LEFT_BRANCH_VDSC_ENABLE || - dss_ctl2_val & RIGHT_BRANCH_VDSC_ENABLE) - dss_ctl2_val &= ~(LEFT_BRANCH_VDSC_ENABLE | - RIGHT_BRANCH_VDSC_ENABLE); - intel_de_write(dev_priv, dss_ctl2_reg, dss_ctl2_val); - - /* Disable Power wells for VDSC/joining */ - intel_display_power_put_unchecked(dev_priv, - intel_dsc_power_domain(old_crtc_state)); + intel_de_write(dev_priv, dss_ctl1_reg(old_crtc_state), 0); + intel_de_write(dev_priv, dss_ctl2_reg(old_crtc_state), 0); +} + +void intel_dsc_get_config(struct intel_crtc_state *crtc_state) +{ + struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + enum intel_display_power_domain power_domain; + intel_wakeref_t wakeref; + u32 dss_ctl1, dss_ctl2, val; + + if (!intel_dsc_source_support(crtc_state)) + return; + + power_domain = intel_dsc_power_domain(crtc_state); + + wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); + if (!wakeref) + return; + + dss_ctl1 = intel_de_read(dev_priv, dss_ctl1_reg(crtc_state)); + dss_ctl2 = intel_de_read(dev_priv, dss_ctl2_reg(crtc_state)); + + crtc_state->dsc.compression_enable = dss_ctl2 & LEFT_BRANCH_VDSC_ENABLE; + if (!crtc_state->dsc.compression_enable) + goto out; + + crtc_state->dsc.dsc_split = (dss_ctl2 & RIGHT_BRANCH_VDSC_ENABLE) && + (dss_ctl1 & JOINER_ENABLE); + + if (dss_ctl1 & BIG_JOINER_ENABLE) { + crtc_state->bigjoiner = true; + + if (!(dss_ctl1 & MASTER_BIG_JOINER_ENABLE)) { + crtc_state->bigjoiner_slave = true; + if (!WARN_ON(crtc->pipe == PIPE_A)) + crtc_state->bigjoiner_linked_crtc = + intel_get_crtc_for_pipe(dev_priv, crtc->pipe - 1); + } else { + if (!WARN_ON(INTEL_NUM_PIPES(dev_priv) == crtc->pipe + 1)) + crtc_state->bigjoiner_linked_crtc = + intel_get_crtc_for_pipe(dev_priv, crtc->pipe + 1); + } + } + + /* FIXME: add more state readout as needed */ + + /* PPS1 */ + if (!is_pipe_dsc(crtc_state)) + val = intel_de_read(dev_priv, DSCA_PICTURE_PARAMETER_SET_1); + else + val = intel_de_read(dev_priv, + ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe)); + vdsc_cfg->bits_per_pixel = val; + crtc_state->dsc.compressed_bpp = vdsc_cfg->bits_per_pixel >> 4; +out: + intel_display_power_put(dev_priv, power_domain, wakeref); } diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h index e56a3254c214..65d301c23580 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc.h @@ -11,15 +11,13 @@ struct intel_encoder; struct intel_crtc_state; -bool intel_dsc_source_support(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state); +bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state); void intel_dsc_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_dsc_disable(const struct intel_crtc_state *crtc_state); int intel_dsc_compute_params(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); -void intel_dsc_get_config(struct intel_encoder *encoder, - struct intel_crtc_state *crtc_state); +void intel_dsc_get_config(struct intel_crtc_state *crtc_state); enum intel_display_power_domain intel_dsc_power_domain(const struct intel_crtc_state *crtc_state); From 4e3cdb4535e7cbc860c0cf91df95b7f3a9c84578 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Tue, 17 Nov 2020 11:47:08 -0800 Subject: [PATCH 50/66] drm/i915/dp: Master/Slave enable/disable sequence for bigjoiner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enabling is done in a special sequence and so should plane updates be. Ideally the end user never notices the second pipe is used. This way ideally everything will be tear free, and updates are really atomic as userspace expects it. This uses generic modeset_enables() calls like trans port sync but still has special handling for disable since for slave we should not disable things like encoder, plls that are not enabled for slave. Signed-off-by: Manasi Navare [vsyrjala: Appease checkpatch] Signed-off-by: Ville Syrjälä Reviewed-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-6-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 25 +++- drivers/gpu/drm/i915/display/intel_display.c | 126 +++++++++++++++---- 2 files changed, 122 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 055fc5c58ef6..3a7b8df50c31 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -28,6 +28,7 @@ #include #include "i915_drv.h" +#include "i915_trace.h" #include "intel_audio.h" #include "intel_combo_phy.h" #include "intel_connector.h" @@ -3665,7 +3666,8 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state, /* 7.l Configure and enable FEC if needed */ intel_ddi_enable_fec(encoder, crtc_state); - intel_dsc_enable(encoder, crtc_state); + if (!crtc_state->bigjoiner) + intel_dsc_enable(encoder, crtc_state); } static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state, @@ -3737,7 +3739,8 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state, if (!is_mst) intel_ddi_enable_pipe_clock(encoder, crtc_state); - intel_dsc_enable(encoder, crtc_state); + if (!crtc_state->bigjoiner) + intel_dsc_enable(encoder, crtc_state); } static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state, @@ -3988,6 +3991,21 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state, ilk_pfit_disable(old_crtc_state); } + if (old_crtc_state->bigjoiner_linked_crtc) { + struct intel_atomic_state *state = + to_intel_atomic_state(old_crtc_state->uapi.state); + struct intel_crtc *slave = + old_crtc_state->bigjoiner_linked_crtc; + const struct intel_crtc_state *old_slave_crtc_state = + intel_atomic_get_old_crtc_state(state, slave); + + intel_crtc_vblank_off(old_slave_crtc_state); + trace_intel_pipe_disable(slave); + + intel_dsc_disable(old_slave_crtc_state); + skl_scaler_disable(old_slave_crtc_state); + } + /* * When called from DP MST code: * - old_conn_state will be NULL @@ -4206,7 +4224,8 @@ static void intel_enable_ddi(struct intel_atomic_state *state, { drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder); - intel_ddi_enable_transcoder_func(encoder, crtc_state); + if (!crtc_state->bigjoiner_slave) + intel_ddi_enable_transcoder_func(encoder, crtc_state); intel_enable_pipe(crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 36c780a67721..e5a56904f33f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7138,6 +7138,45 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, reg, val); } +static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state, + const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *master = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc_state *master_crtc_state; + struct drm_connector_state *conn_state; + struct drm_connector *conn; + struct intel_encoder *encoder = NULL; + int i; + + if (crtc_state->bigjoiner_slave) + master = crtc_state->bigjoiner_linked_crtc; + + master_crtc_state = intel_atomic_get_new_crtc_state(state, master); + + for_each_new_connector_in_state(&state->base, conn, conn_state, i) { + if (conn_state->crtc != &master->base) + continue; + + encoder = to_intel_encoder(conn_state->best_encoder); + break; + } + + if (!crtc_state->bigjoiner_slave) { + /* need to enable VDSC, which we skipped in pre-enable */ + intel_dsc_enable(encoder, crtc_state); + } else { + /* + * Enable sequence steps 1-7 on bigjoiner master + */ + intel_encoders_pre_pll_enable(state, master); + intel_enable_shared_dpll(master_crtc_state); + intel_encoders_pre_enable(state, master); + + /* and DSC on slave */ + intel_dsc_enable(NULL, crtc_state); + } +} + static void hsw_crtc_enable(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -7151,35 +7190,40 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (drm_WARN_ON(&dev_priv->drm, crtc->active)) return; - intel_encoders_pre_pll_enable(state, crtc); + if (!new_crtc_state->bigjoiner) { + intel_encoders_pre_pll_enable(state, crtc); - if (new_crtc_state->shared_dpll) - intel_enable_shared_dpll(new_crtc_state); + if (new_crtc_state->shared_dpll) + intel_enable_shared_dpll(new_crtc_state); - intel_encoders_pre_enable(state, crtc); - - if (!transcoder_is_dsi(cpu_transcoder)) - intel_set_transcoder_timings(new_crtc_state); - - intel_set_pipe_src_size(new_crtc_state); - - if (cpu_transcoder != TRANSCODER_EDP && - !transcoder_is_dsi(cpu_transcoder)) - intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder), - new_crtc_state->pixel_multiplier - 1); - - if (new_crtc_state->has_pch_encoder) - intel_cpu_transcoder_set_m_n(new_crtc_state, - &new_crtc_state->fdi_m_n, NULL); - - if (!transcoder_is_dsi(cpu_transcoder)) { - hsw_set_frame_start_delay(new_crtc_state); - hsw_set_pipeconf(new_crtc_state); + intel_encoders_pre_enable(state, crtc); + } else { + icl_ddi_bigjoiner_pre_enable(state, new_crtc_state); } + intel_set_pipe_src_size(new_crtc_state); if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) bdw_set_pipemisc(new_crtc_state); + if (!new_crtc_state->bigjoiner_slave || !transcoder_is_dsi(cpu_transcoder)) { + if (!transcoder_is_dsi(cpu_transcoder)) + intel_set_transcoder_timings(new_crtc_state); + + if (cpu_transcoder != TRANSCODER_EDP && + !transcoder_is_dsi(cpu_transcoder)) + intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder), + new_crtc_state->pixel_multiplier - 1); + + if (new_crtc_state->has_pch_encoder) + intel_cpu_transcoder_set_m_n(new_crtc_state, + &new_crtc_state->fdi_m_n, NULL); + + hsw_set_frame_start_delay(new_crtc_state); + } + + if (!transcoder_is_dsi(cpu_transcoder)) + hsw_set_pipeconf(new_crtc_state); + crtc->active = true; /* Display WA #1180: WaDisableScalarClockGating: glk, cnl */ @@ -7214,6 +7258,11 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (INTEL_GEN(dev_priv) >= 11) icl_pipe_mbus_enable(crtc); + if (new_crtc_state->bigjoiner_slave) { + trace_intel_pipe_enable(crtc); + intel_crtc_vblank_on(new_crtc_state); + } + intel_encoders_enable(state, crtc); if (psl_clkgate_wa) { @@ -15708,6 +15757,9 @@ static void intel_enable_crtc(struct intel_atomic_state *state, dev_priv->display.crtc_enable(state, crtc); + if (new_crtc_state->bigjoiner_slave) + return; + /* vblanks work again, re-enable pipe CRC. */ intel_crtc_enable_pipe_crc(crtc); } @@ -15770,8 +15822,21 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, { struct drm_i915_private *dev_priv = to_i915(state->base.dev); + drm_WARN_ON(&dev_priv->drm, old_crtc_state->bigjoiner_slave); + intel_crtc_disable_planes(state, crtc); + /* + * We still need special handling for disabling bigjoiner master + * and slaves since for slave we do not have encoder or plls + * so we dont need to disable those. + */ + if (old_crtc_state->bigjoiner) { + intel_crtc_disable_planes(state, + old_crtc_state->bigjoiner_linked_crtc); + old_crtc_state->bigjoiner_linked_crtc->active = false; + } + /* * We need to disable pipe CRC before disabling the pipe, * or we race against vblank off. @@ -15800,7 +15865,7 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) /* Only disable port sync and MST slaves */ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - if (!needs_modeset(new_crtc_state)) + if (!needs_modeset(new_crtc_state) || old_crtc_state->bigjoiner) continue; if (!old_crtc_state->hw.active) @@ -15825,10 +15890,18 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!needs_modeset(new_crtc_state) || - (handled & BIT(crtc->pipe))) + (handled & BIT(crtc->pipe)) || + old_crtc_state->bigjoiner_slave) continue; intel_pre_plane_update(state, crtc); + if (old_crtc_state->bigjoiner) { + struct intel_crtc *slave = + old_crtc_state->bigjoiner_linked_crtc; + + intel_pre_plane_update(state, slave); + } + if (old_crtc_state->hw.active) intel_old_crtc_state_disables(state, old_crtc_state, new_crtc_state, crtc); @@ -15926,7 +15999,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) continue; if (intel_dp_mst_is_slave_trans(new_crtc_state) || - is_trans_port_sync_master(new_crtc_state)) + is_trans_port_sync_master(new_crtc_state) || + (new_crtc_state->bigjoiner && !new_crtc_state->bigjoiner_slave)) continue; modeset_pipes &= ~BIT(pipe); @@ -15936,7 +16010,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) /* * Then we enable all remaining pipes that depend on other - * pipes: MST slaves and port sync masters. + * pipes: MST slaves and port sync masters, big joiner master */ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { enum pipe pipe = crtc->pipe; From 0385ecead5178fffb11c89c3c84a7804a3b42690 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Tue, 17 Nov 2020 11:47:09 -0800 Subject: [PATCH 51/66] drm/i915: HW state readout for Bigjoiner case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skip iterating over bigjoiner slaves, only the master has the state we care about. Add the width of the bigjoiner slave to the reconstructed fb. Hide the bigjoiner slave to userspace, and double the mode on bigjoiner master. And last, disable bigjoiner slave from primary if reconstruction fails. v3: * Fix the ddi_get_config slave error (Ankit Nautiyal) v2: * Unsupported bigjoiner config for initial fb (Ville) Signed-off-by: Manasi Navare [vsyrjala: * Don't do any hw->uapi state copy for bigjoiner slave * We still have hw.mode so no need to pass it in * Appease checkpatch] Signed-off-by: Ville Syrjälä Reviewed-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-7-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/icl_dsi.c | 2 - drivers/gpu/drm/i915/display/intel_ddi.c | 37 ++- drivers/gpu/drm/i915/display/intel_display.c | 291 ++++++++++++------ .../drm/i915/display/intel_display_types.h | 1 + 4 files changed, 230 insertions(+), 101 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index e83364b5774f..a9439b415603 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1492,8 +1492,6 @@ static void gen11_dsi_get_config(struct intel_encoder *encoder, struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - intel_dsc_get_config(pipe_config); - /* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */ pipe_config->port_clock = intel_dpll_get_freq(i915, pipe_config->shared_dpll, diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 3a7b8df50c31..92940a0c5ef8 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4577,20 +4577,14 @@ static void bdw_get_trans_port_sync_config(struct intel_crtc_state *crtc_state) crtc_state->sync_mode_slaves_mask); } -void intel_ddi_get_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config) +static void intel_ddi_read_func_ctl(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc); enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; u32 temp, flags = 0; - /* XXX: DSI transcoder paranoia */ - if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder))) - return; - - intel_dsc_get_config(pipe_config); - temp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (temp & TRANS_DDI_PHSYNC) flags |= DRM_MODE_FLAG_PHSYNC; @@ -4684,6 +4678,30 @@ void intel_ddi_get_config(struct intel_encoder *encoder, default: break; } +} + +void intel_ddi_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; + + /* XXX: DSI transcoder paranoia */ + if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder))) + return; + + if (pipe_config->bigjoiner_slave) { + /* read out pipe settings from master */ + enum transcoder save = pipe_config->cpu_transcoder; + + /* Our own transcoder needs to be disabled when reading it in intel_ddi_read_func_ctl() */ + WARN_ON(pipe_config->output_types); + pipe_config->cpu_transcoder = (enum transcoder)pipe_config->bigjoiner_linked_crtc->pipe; + intel_ddi_read_func_ctl(encoder, pipe_config); + pipe_config->cpu_transcoder = save; + } else { + intel_ddi_read_func_ctl(encoder, pipe_config); + } pipe_config->has_audio = intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder); @@ -4709,7 +4727,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder, dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp; } - intel_ddi_clock_get(encoder, pipe_config); + if (!pipe_config->bigjoiner_slave) + intel_ddi_clock_get(encoder, pipe_config); if (IS_GEN9_LP(dev_priv)) pipe_config->lane_lat_optim_mask = diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e5a56904f33f..68c4f6cca82d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3631,6 +3631,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, struct intel_plane *intel_plane = to_intel_plane(primary); struct intel_plane_state *intel_state = to_intel_plane_state(plane_state); + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(intel_crtc->base.state); struct drm_framebuffer *fb; struct i915_vma *vma; @@ -3653,7 +3655,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, if (c == &intel_crtc->base) continue; - if (!to_intel_crtc(c)->active) + if (!to_intel_crtc_state(c->state)->uapi.active) continue; state = to_intel_plane_state(c->primary->state); @@ -3675,6 +3677,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, * pretend the BIOS never had it enabled. */ intel_plane_disable_noatomic(intel_crtc, intel_plane); + if (crtc_state->bigjoiner) { + struct intel_crtc *slave = + crtc_state->bigjoiner_linked_crtc; + intel_plane_disable_noatomic(slave, to_intel_plane(slave->base.primary)); + } return; @@ -8220,13 +8227,27 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state drm_mode_copy(pipe_mode, adjusted_mode); + if (crtc_state->bigjoiner) { + /* + * transcoder is programmed to the full mode, + * but pipe timings are half of the transcoder mode + */ + pipe_mode->crtc_hdisplay /= 2; + pipe_mode->crtc_hblank_start /= 2; + pipe_mode->crtc_hblank_end /= 2; + pipe_mode->crtc_hsync_start /= 2; + pipe_mode->crtc_hsync_end /= 2; + pipe_mode->crtc_htotal /= 2; + pipe_mode->crtc_clock /= 2; + } + intel_mode_from_crtc_timings(pipe_mode, pipe_mode); intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode); intel_crtc_compute_pixel_rate(crtc_state); drm_mode_copy(mode, adjusted_mode); - mode->hdisplay = crtc_state->pipe_src_w; + mode->hdisplay = crtc_state->pipe_src_w << crtc_state->bigjoiner; mode->vdisplay = crtc_state->pipe_src_h; } @@ -10698,6 +10719,7 @@ static void skl_get_initial_plane_config(struct intel_crtc *crtc, struct intel_initial_plane_config *plane_config) { + struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane *plane = to_intel_plane(crtc->base.primary); @@ -10714,6 +10736,12 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, drm_WARN_ON(dev, pipe != crtc->pipe); + if (crtc_state->bigjoiner) { + drm_dbg_kms(&dev_priv->drm, + "Unsupported bigjoiner configuration for initial FB\n"); + return; + } + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); if (!intel_fb) { drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n"); @@ -11365,6 +11393,8 @@ static void hsw_get_ddi_port_state(struct intel_crtc *crtc, } else { tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); + if (!(tmp & TRANS_DDI_FUNC_ENABLE)) + return; if (INTEL_GEN(dev_priv) >= 12) port = TGL_TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp); else @@ -11433,10 +11463,19 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, active = true; } - if (!active) - goto out; + intel_dsc_get_config(pipe_config); - if (!transcoder_is_dsi(pipe_config->cpu_transcoder) || + if (!active) { + /* bigjoiner slave doesn't enable transcoder */ + if (!pipe_config->bigjoiner_slave) + goto out; + + active = true; + pipe_config->pixel_multiplier = 1; + + /* we cannot read out most state, so don't bother.. */ + pipe_config->quirks |= PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE; + } else if (!transcoder_is_dsi(pipe_config->cpu_transcoder) || INTEL_GEN(dev_priv) >= 11) { hsw_get_ddi_port_state(crtc, pipe_config); intel_get_transcoder_timings(crtc, pipe_config); @@ -11511,7 +11550,10 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, } } - if (pipe_config->cpu_transcoder != TRANSCODER_EDP && + if (pipe_config->bigjoiner_slave) { + /* Cannot be read out as a slave, set to 0. */ + pipe_config->pixel_multiplier = 0; + } else if (pipe_config->cpu_transcoder != TRANSCODER_EDP && !transcoder_is_dsi(pipe_config->cpu_transcoder)) { pipe_config->pixel_multiplier = intel_de_read(dev_priv, @@ -13555,6 +13597,9 @@ intel_crtc_copy_uapi_to_hw_state(struct intel_atomic_state *state, static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state) { + if (crtc_state->bigjoiner_slave) + return; + crtc_state->uapi.enable = crtc_state->hw.enable; crtc_state->uapi.active = crtc_state->hw.active; drm_WARN_ON(crtc_state->uapi.crtc->dev, @@ -14196,35 +14241,53 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(output_types); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hdisplay); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_htotal); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_end); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_end); + /* FIXME do the readout properly and get rid of this quirk */ + if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) { + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hdisplay); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_htotal); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_end); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hsync_end); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vdisplay); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vtotal); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_end); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_start); - PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_end); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vdisplay); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vtotal); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vblank_end); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_start); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_vsync_end); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_end); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_end); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vdisplay); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vtotal); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_end); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_start); - PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vdisplay); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vtotal); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_end); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_start); + PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_end); + + PIPE_CONF_CHECK_I(pixel_multiplier); + + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, + DRM_MODE_FLAG_INTERLACE); + + if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) { + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, + DRM_MODE_FLAG_PHSYNC); + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, + DRM_MODE_FLAG_NHSYNC); + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, + DRM_MODE_FLAG_PVSYNC); + PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, + DRM_MODE_FLAG_NVSYNC); + } + } - PIPE_CONF_CHECK_I(pixel_multiplier); PIPE_CONF_CHECK_I(output_format); PIPE_CONF_CHECK_BOOL(has_hdmi_sink); if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) || @@ -14234,24 +14297,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(hdmi_scrambling); PIPE_CONF_CHECK_BOOL(hdmi_high_tmds_clock_ratio); PIPE_CONF_CHECK_BOOL(has_infoframe); - PIPE_CONF_CHECK_BOOL(fec_enable); + /* FIXME do the readout properly and get rid of this quirk */ + if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) + PIPE_CONF_CHECK_BOOL(fec_enable); PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio); - PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, - DRM_MODE_FLAG_INTERLACE); - - if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) { - PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, - DRM_MODE_FLAG_PHSYNC); - PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, - DRM_MODE_FLAG_NHSYNC); - PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, - DRM_MODE_FLAG_PVSYNC); - PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags, - DRM_MODE_FLAG_NVSYNC); - } - PIPE_CONF_CHECK_X(gmch_pfit.control); /* pfit ratios are autocomputed by the hw on gen4+ */ if (INTEL_GEN(dev_priv) < 4) @@ -14277,7 +14328,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } PIPE_CONF_CHECK_I(scaler_state.scaler_id); - PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate); + /* FIXME do the readout properly and get rid of this quirk */ + if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) + PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate); PIPE_CONF_CHECK_X(gamma_mode); if (IS_CHERRYVIEW(dev_priv)) @@ -14298,49 +14351,53 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(double_wide); PIPE_CONF_CHECK_P(shared_dpll); - PIPE_CONF_CHECK_X(dpll_hw_state.dpll); - PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md); - PIPE_CONF_CHECK_X(dpll_hw_state.fp0); - PIPE_CONF_CHECK_X(dpll_hw_state.fp1); - PIPE_CONF_CHECK_X(dpll_hw_state.wrpll); - PIPE_CONF_CHECK_X(dpll_hw_state.spll); - PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1); - PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1); - PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2); - PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr0); - PIPE_CONF_CHECK_X(dpll_hw_state.ebb0); - PIPE_CONF_CHECK_X(dpll_hw_state.ebb4); - PIPE_CONF_CHECK_X(dpll_hw_state.pll0); - PIPE_CONF_CHECK_X(dpll_hw_state.pll1); - PIPE_CONF_CHECK_X(dpll_hw_state.pll2); - PIPE_CONF_CHECK_X(dpll_hw_state.pll3); - PIPE_CONF_CHECK_X(dpll_hw_state.pll6); - PIPE_CONF_CHECK_X(dpll_hw_state.pll8); - PIPE_CONF_CHECK_X(dpll_hw_state.pll9); - PIPE_CONF_CHECK_X(dpll_hw_state.pll10); - PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias); - PIPE_CONF_CHECK_X(dsi_pll.ctrl); - PIPE_CONF_CHECK_X(dsi_pll.div); + /* FIXME do the readout properly and get rid of this quirk */ + if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE)) { + PIPE_CONF_CHECK_X(dpll_hw_state.dpll); + PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md); + PIPE_CONF_CHECK_X(dpll_hw_state.fp0); + PIPE_CONF_CHECK_X(dpll_hw_state.fp1); + PIPE_CONF_CHECK_X(dpll_hw_state.wrpll); + PIPE_CONF_CHECK_X(dpll_hw_state.spll); + PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1); + PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1); + PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2); + PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr0); + PIPE_CONF_CHECK_X(dpll_hw_state.ebb0); + PIPE_CONF_CHECK_X(dpll_hw_state.ebb4); + PIPE_CONF_CHECK_X(dpll_hw_state.pll0); + PIPE_CONF_CHECK_X(dpll_hw_state.pll1); + PIPE_CONF_CHECK_X(dpll_hw_state.pll2); + PIPE_CONF_CHECK_X(dpll_hw_state.pll3); + PIPE_CONF_CHECK_X(dpll_hw_state.pll6); + PIPE_CONF_CHECK_X(dpll_hw_state.pll8); + PIPE_CONF_CHECK_X(dpll_hw_state.pll9); + PIPE_CONF_CHECK_X(dpll_hw_state.pll10); + PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12); + PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl); + PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1); + PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl); + PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0); + PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1); + PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf); + PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock); + PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc); + PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias); + PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias); - if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) - PIPE_CONF_CHECK_I(pipe_bpp); + PIPE_CONF_CHECK_X(dsi_pll.ctrl); + PIPE_CONF_CHECK_X(dsi_pll.div); - PIPE_CONF_CHECK_CLOCK_FUZZY(hw.pipe_mode.crtc_clock); - PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock); - PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); + if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) + PIPE_CONF_CHECK_I(pipe_bpp); - PIPE_CONF_CHECK_I(min_voltage_level); + PIPE_CONF_CHECK_CLOCK_FUZZY(hw.pipe_mode.crtc_clock); + PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock); + PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); + + PIPE_CONF_CHECK_I(min_voltage_level); + } PIPE_CONF_CHECK_X(infoframes.enable); PIPE_CONF_CHECK_X(infoframes.gcp); @@ -14352,6 +14409,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(sync_mode_slaves_mask); PIPE_CONF_CHECK_I(master_transcoder); + PIPE_CONF_CHECK_BOOL(bigjoiner); + PIPE_CONF_CHECK_BOOL(bigjoiner_slave); + PIPE_CONF_CHECK_P(bigjoiner_linked_crtc); PIPE_CONF_CHECK_I(dsc.compression_enable); PIPE_CONF_CHECK_I(dsc.dsc_split); @@ -14623,6 +14683,7 @@ verify_crtc_state(struct intel_crtc *crtc, struct intel_encoder *encoder; struct intel_crtc_state *pipe_config = old_crtc_state; struct drm_atomic_state *state = old_crtc_state->uapi.state; + struct intel_crtc *master = crtc; __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi); intel_crtc_free_hw_state(old_crtc_state); @@ -14650,7 +14711,10 @@ verify_crtc_state(struct intel_crtc *crtc, "(expected %i, found %i)\n", new_crtc_state->hw.active, crtc->active); - for_each_encoder_on_crtc(dev, &crtc->base, encoder) { + if (new_crtc_state->bigjoiner_slave) + master = new_crtc_state->bigjoiner_linked_crtc; + + for_each_encoder_on_crtc(dev, &master->base, encoder) { enum pipe pipe; bool active; @@ -14660,7 +14724,7 @@ verify_crtc_state(struct intel_crtc *crtc, encoder->base.base.id, active, new_crtc_state->hw.active); - I915_STATE_WARN(active && crtc->pipe != pipe, + I915_STATE_WARN(active && master->pipe != pipe, "Encoder connected to wrong pipe %c\n", pipe_name(pipe)); @@ -18566,7 +18630,7 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915) for_each_intel_crtc(dev, crtc) { struct intel_initial_plane_config plane_config = {}; - if (!crtc->active) + if (!to_intel_crtc_state(crtc->base.state)->uapi.active) continue; /* @@ -18877,7 +18941,8 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, /* Adjust the state of the output pipe according to whether we * have active connectors/encoders. */ - if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc)) + if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc) && + !crtc_state->bigjoiner_slave) intel_crtc_disable_noatomic(crtc, ctx); if (crtc_state->hw.active || HAS_GMCH(dev_priv)) { @@ -19092,6 +19157,16 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) intel_encoder_get_config(encoder, crtc_state); if (encoder->sync_state) encoder->sync_state(encoder, crtc_state); + + /* read out to slave crtc as well for bigjoiner */ + if (crtc_state->bigjoiner) { + /* encoder should read be linked to bigjoiner master */ + WARN_ON(crtc_state->bigjoiner_slave); + + crtc = crtc_state->bigjoiner_linked_crtc; + crtc_state = to_intel_crtc_state(crtc->base.state); + intel_encoder_get_config(encoder, crtc_state); + } } else { encoder->base.crtc = NULL; } @@ -19147,6 +19222,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) struct intel_plane *plane; int min_cdclk = 0; + if (crtc_state->bigjoiner_slave) + continue; + if (crtc_state->hw.active) { /* * The initial mode needs to be set in order to keep @@ -19207,6 +19285,39 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) intel_bw_crtc_update(bw_state, crtc_state); intel_pipe_config_sanity_check(dev_priv, crtc_state); + + /* discard our incomplete slave state, copy it from master */ + if (crtc_state->bigjoiner && crtc_state->hw.active) { + struct intel_crtc *slave = crtc_state->bigjoiner_linked_crtc; + struct intel_crtc_state *slave_crtc_state = + to_intel_crtc_state(slave->base.state); + + copy_bigjoiner_crtc_state(slave_crtc_state, crtc_state); + slave->base.mode = crtc->base.mode; + + cdclk_state->min_cdclk[slave->pipe] = min_cdclk; + cdclk_state->min_voltage_level[slave->pipe] = + crtc_state->min_voltage_level; + + for_each_intel_plane_on_crtc(&dev_priv->drm, slave, plane) { + const struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + + /* + * FIXME don't have the fb yet, so can't + * use intel_plane_data_rate() :( + */ + if (plane_state->uapi.visible) + crtc_state->data_rate[plane->id] = + 4 * crtc_state->pixel_rate; + else + crtc_state->data_rate[plane->id] = 0; + } + + intel_bw_crtc_update(bw_state, slave_crtc_state); + drm_calc_timestamping_constants(&slave->base, + &slave_crtc_state->hw.adjusted_mode); + } } } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index b3d94e6cd7c5..ce82d654d0f2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -850,6 +850,7 @@ struct intel_crtc_state { * accordingly. */ #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ +#define PIPE_CONFIG_QUIRK_BIGJOINER_SLAVE (1<<1) /* bigjoiner slave, partial readout */ unsigned long quirks; unsigned fb_bits; /* framebuffers to flip */ From d321634bd7cf7643cddacf84f300f2a194fee201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 17 Nov 2020 11:47:10 -0800 Subject: [PATCH 52/66] drm/i915: Add crtcs affected by bigjoiner to the state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure both crtcs participating in the bigjoiner stuff are in the state. Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-8-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 68c4f6cca82d..0784495e2310 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -15461,6 +15461,27 @@ static int intel_atomic_check_async(struct intel_atomic_state *state) return 0; } +static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state) +{ + const struct intel_crtc_state *crtc_state; + struct intel_crtc *crtc; + int i; + + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + struct intel_crtc_state *linked_crtc_state; + + if (!crtc_state->bigjoiner) + continue; + + linked_crtc_state = intel_atomic_get_crtc_state(&state->base, + crtc_state->bigjoiner_linked_crtc); + if (IS_ERR(linked_crtc_state)) + return PTR_ERR(linked_crtc_state); + } + + return 0; +} + /** * intel_atomic_check - validate state object * @dev: drm device @@ -15486,6 +15507,10 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; + ret = intel_bigjoiner_add_affected_crtcs(state); + if (ret) + goto fail; + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!needs_modeset(new_crtc_state)) { From 1cf6adb70dedcce139f8b7d94abda9eefb243ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 17 Nov 2020 11:47:11 -0800 Subject: [PATCH 53/66] drm/i915: Add planes affected by bigjoiner to the state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure both the bigjoiner "master" and "slave" plane are in the state whenever either of them is in the state. Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-9-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 42 ++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0784495e2310..78f89ecdda79 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -15108,6 +15108,44 @@ static bool active_planes_affects_min_cdclk(struct drm_i915_private *dev_priv) IS_IVYBRIDGE(dev_priv) || (INTEL_GEN(dev_priv) >= 11); } +static int intel_crtc_add_bigjoiner_planes(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_crtc *other) +{ + const struct intel_plane_state *plane_state; + struct intel_plane *plane; + u8 plane_ids = 0; + int i; + + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + if (plane->pipe == crtc->pipe) + plane_ids |= BIT(plane->id); + } + + return intel_crtc_add_planes_to_state(state, other, plane_ids); +} + +static int intel_bigjoiner_add_affected_planes(struct intel_atomic_state *state) +{ + const struct intel_crtc_state *crtc_state; + struct intel_crtc *crtc; + int i; + + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + int ret; + + if (!crtc_state->bigjoiner) + continue; + + ret = intel_crtc_add_bigjoiner_planes(state, crtc, + crtc_state->bigjoiner_linked_crtc); + if (ret) + return ret; + } + + return 0; +} + static int intel_atomic_check_planes(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); @@ -15121,6 +15159,10 @@ static int intel_atomic_check_planes(struct intel_atomic_state *state) if (ret) return ret; + ret = intel_bigjoiner_add_affected_planes(state); + if (ret) + return ret; + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { ret = intel_plane_atomic_check(state, plane); if (ret) { From 8246d9c7ea5e8a1ad66ce7e17184096f51d93912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 17 Nov 2020 11:47:12 -0800 Subject: [PATCH 54/66] drm/i915: Get the uapi state from the correct plane when bigjoiner is used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using bigjoiner userspace is only controlling the "master" plane, so use its uapi state for the "slave" plane as well. hw.crtc needs a bit of magic since we don't want to copy that from the uapi state (as it points to the wrong pipe for the "slave " plane). Instead we pass the right crtc in explicitly but only assign it when the uapi state indicates the plane to be logically enabled (ie. uapi.crtc != NULL). Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-10-manasi.d.navare@intel.com --- .../gpu/drm/i915/display/intel_atomic_plane.c | 59 +++++++++++++------ .../gpu/drm/i915/display/intel_atomic_plane.h | 3 +- drivers/gpu/drm/i915/display/intel_display.c | 5 +- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index f47558efb3c2..7abb0e3d6c0b 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -247,11 +247,19 @@ static void intel_plane_clear_hw_state(struct intel_plane_state *plane_state) } void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, - const struct intel_plane_state *from_plane_state) + const struct intel_plane_state *from_plane_state, + struct intel_crtc *crtc) { intel_plane_clear_hw_state(plane_state); - plane_state->hw.crtc = from_plane_state->uapi.crtc; + /* + * For the bigjoiner slave uapi.crtc will point at + * the master crtc. So we explicitly assign the right + * slave crtc to hw.crtc. uapi.crtc!=NULL simply indicates + * the plane is logically enabled on the uapi level. + */ + plane_state->hw.crtc = from_plane_state->uapi.crtc ? &crtc->base : NULL; + plane_state->hw.fb = from_plane_state->uapi.fb; if (plane_state->hw.fb) drm_framebuffer_get(plane_state->hw.fb); @@ -331,15 +339,16 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ old_plane_state, new_plane_state); } -static struct intel_crtc * -get_crtc_from_states(const struct intel_plane_state *old_plane_state, - const struct intel_plane_state *new_plane_state) +static struct intel_plane * +intel_crtc_get_plane(struct intel_crtc *crtc, enum plane_id plane_id) { - if (new_plane_state->uapi.crtc) - return to_intel_crtc(new_plane_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_plane *plane; - if (old_plane_state->uapi.crtc) - return to_intel_crtc(old_plane_state->uapi.crtc); + for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { + if (plane->id == plane_id) + return plane; + } return NULL; } @@ -347,23 +356,37 @@ get_crtc_from_states(const struct intel_plane_state *old_plane_state, int intel_plane_atomic_check(struct intel_atomic_state *state, struct intel_plane *plane) { + struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane); const struct intel_plane_state *old_plane_state = intel_atomic_get_old_plane_state(state, plane); - struct intel_crtc *crtc = - get_crtc_from_states(old_plane_state, new_plane_state); - const struct intel_crtc_state *old_crtc_state; - struct intel_crtc_state *new_crtc_state; + const struct intel_plane_state *new_master_plane_state; + struct intel_crtc *crtc = intel_get_crtc_for_pipe(i915, plane->pipe); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + + if (new_crtc_state && new_crtc_state->bigjoiner_slave) { + struct intel_plane *master_plane = + intel_crtc_get_plane(new_crtc_state->bigjoiner_linked_crtc, + plane->id); + + new_master_plane_state = + intel_atomic_get_new_plane_state(state, master_plane); + } else { + new_master_plane_state = new_plane_state; + } + + intel_plane_copy_uapi_to_hw_state(new_plane_state, + new_master_plane_state, + crtc); - intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state); new_plane_state->uapi.visible = false; - if (!crtc) + if (!new_crtc_state) return 0; - old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); - new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - return intel_plane_atomic_check_with_state(old_crtc_state, new_crtc_state, old_plane_state, diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index 24a3a148aa62..5cae9db41062 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -24,7 +24,8 @@ unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state, unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, - const struct intel_plane_state *from_plane_state); + const struct intel_plane_state *from_plane_state, + struct intel_crtc *crtc); void intel_plane_copy_hw_state(struct intel_plane_state *plane_state, const struct intel_plane_state *from_plane_state); void intel_update_plane(struct intel_plane *plane, diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 78f89ecdda79..e1ed65127647 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3718,7 +3718,8 @@ valid_fb: drm_framebuffer_get(fb); plane_state->crtc = &intel_crtc->base; - intel_plane_copy_uapi_to_hw_state(intel_state, intel_state); + intel_plane_copy_uapi_to_hw_state(intel_state, intel_state, + intel_crtc); intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB); @@ -16981,7 +16982,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane, new_plane_state->uapi.crtc_w = crtc_w; new_plane_state->uapi.crtc_h = crtc_h; - intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state); + intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc); ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state, old_plane_state, new_plane_state); From 9f05a7c0adb9ee26dffb8de74b8acfd829629e4a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 17 Nov 2020 11:47:13 -0800 Subject: [PATCH 55/66] drm/i915: Add bigjoiner aware plane clipping checks We need to look at hw.fb for the framebuffer, and add the translation for the slave_plane_state. With these changes we set the correct rectangle on the bigjoiner slave, and don't set incorrect src/dst/visibility on the slave plane. v2: * Manual rebase (Manasi) v3: * hw.rotation instead of uapi.rotation (Ville) Signed-off-by: Maarten Lankhorst Signed-off-by: Manasi Navare Reviewed-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-11-manasi.d.navare@intel.com --- .../gpu/drm/i915/display/intel_atomic_plane.c | 60 +++++++++++++++++++ .../gpu/drm/i915/display/intel_atomic_plane.h | 4 ++ drivers/gpu/drm/i915/display/intel_display.c | 19 +++--- drivers/gpu/drm/i915/display/intel_sprite.c | 21 +++---- 4 files changed, 80 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 7abb0e3d6c0b..7e9f84b00859 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -271,6 +271,9 @@ void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, plane_state->hw.color_encoding = from_plane_state->uapi.color_encoding; plane_state->hw.color_range = from_plane_state->uapi.color_range; plane_state->hw.scaling_filter = from_plane_state->uapi.scaling_filter; + + plane_state->uapi.src = drm_plane_state_src(&from_plane_state->uapi); + plane_state->uapi.dst = drm_plane_state_dest(&from_plane_state->uapi); } void intel_plane_copy_hw_state(struct intel_plane_state *plane_state, @@ -514,6 +517,63 @@ void i9xx_update_planes_on_crtc(struct intel_atomic_state *state, } } +int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, + struct intel_crtc_state *crtc_state, + int min_scale, int max_scale, + bool can_position) +{ + struct drm_framebuffer *fb = plane_state->hw.fb; + struct drm_rect *src = &plane_state->uapi.src; + struct drm_rect *dst = &plane_state->uapi.dst; + unsigned int rotation = plane_state->hw.rotation; + struct drm_rect clip = {}; + int hscale, vscale; + + if (!fb) { + plane_state->uapi.visible = false; + return 0; + } + + drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation); + + /* Check scaling */ + hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); + vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); + if (hscale < 0 || vscale < 0) { + DRM_DEBUG_KMS("Invalid scaling of plane\n"); + drm_rect_debug_print("src: ", src, true); + drm_rect_debug_print("dst: ", dst, false); + return -ERANGE; + } + + if (crtc_state->hw.enable) { + clip.x2 = crtc_state->pipe_src_w; + clip.y2 = crtc_state->pipe_src_h; + } + + /* right side of the image is on the slave crtc, adjust dst to match */ + if (crtc_state->bigjoiner_slave) + drm_rect_translate(dst, -crtc_state->pipe_src_w, 0); + + /* + * FIXME: This might need further adjustment for seamless scaling + * with phase information, for the 2p2 and 2p1 scenarios. + */ + plane_state->uapi.visible = drm_rect_clip_scaled(src, dst, &clip); + + drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation); + + if (!can_position && plane_state->uapi.visible && + !drm_rect_equals(dst, &clip)) { + DRM_DEBUG_KMS("Plane must cover entire CRTC\n"); + drm_rect_debug_print("dst: ", dst, false); + drm_rect_debug_print("clip: ", &clip, false); + return -EINVAL; + } + + return 0; +} + const struct drm_plane_helper_funcs intel_plane_helper_funcs = { .prepare_fb = intel_prepare_plane_fb, .cleanup_fb = intel_cleanup_plane_fb, diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index 5cae9db41062..5c78a087ed86 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -55,6 +55,10 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat int intel_plane_calc_min_cdclk(struct intel_atomic_state *state, struct intel_plane *plane, bool *need_cdclk_calc); +int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, + struct intel_crtc_state *crtc_state, + int min_scale, int max_scale, + bool can_position); void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e1ed65127647..22224b8c4998 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -4315,12 +4315,10 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state, if (ret) return ret; - ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, - &crtc_state->uapi, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - i9xx_plane_has_windowing(plane), - true); + ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + i9xx_plane_has_windowing(plane)); if (ret) return ret; @@ -11698,11 +11696,10 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, return -EINVAL; } - ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, - &crtc_state->uapi, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - true, true); + ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index a3ab44694118..019a2d6d807a 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -2187,10 +2187,8 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state, } } - ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, - &crtc_state->uapi, - min_scale, max_scale, - true, true); + ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, + min_scale, max_scale, true); if (ret) return ret; @@ -2245,11 +2243,10 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state, if (ret) return ret; - ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, - &crtc_state->uapi, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - true, true); + ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true); if (ret) return ret; @@ -2456,10 +2453,8 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state, max_scale = skl_plane_max_scale(dev_priv, fb); } - ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, - &crtc_state->uapi, - min_scale, max_scale, - true, true); + ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, + min_scale, max_scale, true); if (ret) return ret; From 498fab06f65816650f8eb9e4297c49f945058710 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 17 Nov 2020 11:47:14 -0800 Subject: [PATCH 56/66] drm/i915: Add debugfs dumping for bigjoiner, v3. Dump debugfs and planar links as well, this will make it easier to debug when things go wrong. v4: * Rebase Changes since v1: - Report planar slaves as such, now that we have the plane_state switch. Changes since v2: - Rebase on top of the new plane format dumping Signed-off-by: Maarten Lankhorst Signed-off-by: Manasi Navare Reviewed-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-12-manasi.d.navare@intel.com --- .../drm/i915/display/intel_display_debugfs.c | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 00b79593bcef..ca41e8c00ad7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -755,6 +755,17 @@ static void plane_rotation(char *buf, size_t bufsize, unsigned int rotation) rotation); } +static const char *plane_visibility(const struct intel_plane_state *plane_state) +{ + if (plane_state->uapi.visible) + return "visible"; + + if (plane_state->planar_slave) + return "planar-slave"; + + return "hidden"; +} + static void intel_plane_uapi_info(struct seq_file *m, struct intel_plane *plane) { const struct intel_plane_state *plane_state = @@ -773,13 +784,19 @@ static void intel_plane_uapi_info(struct seq_file *m, struct intel_plane *plane) plane_rotation(rot_str, sizeof(rot_str), plane_state->uapi.rotation); - seq_printf(m, "\t\tuapi: [FB:%d] %s,0x%llx,%dx%d, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", + seq_printf(m, "\t\tuapi: [FB:%d] %s,0x%llx,%dx%d, visible=%s, src=" DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", fb ? fb->base.id : 0, fb ? format_name.str : "n/a", fb ? fb->modifier : 0, fb ? fb->width : 0, fb ? fb->height : 0, + plane_visibility(plane_state), DRM_RECT_FP_ARG(&src), DRM_RECT_ARG(&dst), rot_str); + + if (plane_state->planar_linked_plane) + seq_printf(m, "\t\tplanar: Linked to [PLANE:%d:%s] as a %s\n", + plane_state->planar_linked_plane->base.base.id, plane_state->planar_linked_plane->base.name, + plane_state->planar_slave ? "slave" : "master"); } static void intel_plane_hw_info(struct seq_file *m, struct intel_plane *plane) @@ -875,6 +892,12 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) intel_scaler_info(m, crtc); } + if (crtc_state->bigjoiner) + seq_printf(m, "\tLinked to [CRTC:%d:%s] as a %s\n", + crtc_state->bigjoiner_linked_crtc->base.base.id, + crtc_state->bigjoiner_linked_crtc->base.name, + crtc_state->bigjoiner_slave ? "slave" : "master"); + for_each_intel_encoder_mask(&dev_priv->drm, encoder, crtc_state->uapi.encoder_mask) intel_encoder_info(m, crtc, encoder); From 756c1b8767a54a270f60c00a7d95a2cdd67d70f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 17 Nov 2020 11:47:15 -0800 Subject: [PATCH 57/66] drm/i915: Disable legacy cursor fastpath for bigjoiner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The legacy cursor fastpath code doesn't deal with bigjoiner. Disable the fastpath for now. Signed-off-by: Ville Syrjälä Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-13-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 22224b8c4998..4d11d5b0606b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -16931,9 +16931,11 @@ intel_legacy_cursor_update(struct drm_plane *_plane, /* * When crtc is inactive or there is a modeset pending, * wait for it to complete in the slowpath + * + * FIXME bigjoiner fastpath would be good */ if (!crtc_state->hw.active || needs_modeset(crtc_state) || - crtc_state->update_pipe) + crtc_state->update_pipe || crtc_state->bigjoiner) goto slow; /* From bf473cb531d9eb47d445ae4a5650bac28537b65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 17 Nov 2020 11:47:16 -0800 Subject: [PATCH 58/66] drm/i915: Fix cursor src/dst rectangle with bigjoiner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can't call drm_plane_state_src() this late for the slave plane since it would consult the wrong uapi state. We've alreayd done the correct uapi->hw copy earlier, so let's just preserve the unclipped src/dst rects using a temp copy across the intel_atomic_plane_check_clipping() call. Signed-off-by: Ville Syrjälä Signed-off-by: Manasi Navare Reviewed-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-14-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 4d11d5b0606b..acd64e788a36 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -11689,6 +11689,8 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, { const struct drm_framebuffer *fb = plane_state->hw.fb; struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + const struct drm_rect src = plane_state->uapi.src; + const struct drm_rect dst = plane_state->uapi.dst; int ret; if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) { @@ -11704,8 +11706,8 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, return ret; /* Use the unclipped src/dst rectangles, which we program to hw */ - plane_state->uapi.src = drm_plane_state_src(&plane_state->uapi); - plane_state->uapi.dst = drm_plane_state_dest(&plane_state->uapi); + plane_state->uapi.src = src; + plane_state->uapi.dst = dst; ret = intel_cursor_check_surface(plane_state); if (ret) From 75c4fa30f92272df6ac13cccf46f8397b0fcb169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 17 Nov 2020 11:47:17 -0800 Subject: [PATCH 59/66] drm/i915: Add bigjoiner state dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a big of bigjoiner information to the state dump. Signed-off-by: Ville Syrjälä Signed-off-by: Manasi Navare Reviewed-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-15-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index acd64e788a36..5c07c74d4397 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -13384,6 +13384,10 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, transcoder_name(pipe_config->master_transcoder), pipe_config->sync_mode_slaves_mask); + drm_dbg_kms(&dev_priv->drm, "bigjoiner: %s\n", + pipe_config->bigjoiner_slave ? "slave" : + pipe_config->bigjoiner ? "master" : "no"); + if (pipe_config->has_pch_encoder) intel_dump_m_n_config(pipe_config, "fdi", pipe_config->fdi_lanes, From 919c2299a8930229f2c56a2de27dcacdae0a373f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 17 Nov 2020 11:47:18 -0800 Subject: [PATCH 60/66] drm/i915: Enable bigjoiner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enough plumbing should be in place to throw the bigjoiner switch. Signed-off-by: Ville Syrjälä Signed-off-by: Manasi Navare Reviewed-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201117194718.11462-16-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 857f39779654..3896d08c4177 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -260,9 +260,6 @@ bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp) struct intel_encoder *encoder = &intel_dig_port->base; struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - /* FIXME remove once everything is in place */ - return false; - return INTEL_GEN(dev_priv) >= 12 || (INTEL_GEN(dev_priv) == 11 && encoder->port != PORT_A); From 059a0beb486344a577ff476acce75e69eab704be Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Tue, 17 Nov 2020 15:01:24 +0200 Subject: [PATCH 61/66] drm/i915/perf: workaround register corruption in OATAILPTR After having written the entire OA buffer with reports, the HW will write again at the beginning of the OA buffer. It'll indicate it by setting the WRAP bits in the OASTATUS register. When a wrap happens and that at the end of the read vfunc we write the OASTATUS register back to clear the REPORT_LOST bit, we sometimes see that the OATAILPTR register is reset to a previous position on Gen8/9 (apparently not the case on Gen11+). This leads the next call to the read vfunc to process reports we've already read. Because we've marked those as read by clearing the reason & timestamp dwords, they're discarded and a "Skipping spurious, invalid OA report" message is emitted. The workaround to avoid this OATAILPTR value reset seems to be to set the wrap bits when writing back OASTATUS. This change has no impact on userspace, it only avoids a bunch of DRM_NOTE("Skipping spurious, invalid OA report\n") messages. Signed-off-by: Lionel Landwerlin Fixes: 19f81df2859eb1 ("drm/i915/perf: Add OA unit support for Gen 8+") Reviewed-by: Umesh Nerlige Ramappa Link: https://patchwork.freedesktop.org/patch/msgid/20201117130124.829979-1-lionel.g.landwerlin@intel.com --- drivers/gpu/drm/i915/i915_perf.c | 9 +++++++-- drivers/gpu/drm/i915/i915_reg.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index e94976976571..3640d0e229d2 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -909,8 +909,13 @@ static int gen8_oa_read(struct i915_perf_stream *stream, DRM_I915_PERF_RECORD_OA_REPORT_LOST); if (ret) return ret; - intel_uncore_write(uncore, oastatus_reg, - oastatus & ~GEN8_OASTATUS_REPORT_LOST); + + intel_uncore_rmw(uncore, oastatus_reg, + GEN8_OASTATUS_COUNTER_OVERFLOW | + GEN8_OASTATUS_REPORT_LOST, + IS_GEN_RANGE(uncore->i915, 8, 10) ? + (GEN8_OASTATUS_HEAD_POINTER_WRAP | + GEN8_OASTATUS_TAIL_POINTER_WRAP) : 0); } return gen8_append_oa_reports(stream, buf, count, offset); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 39664ba553ec..fe1b3692d6ca 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -679,6 +679,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define GEN7_OASTATUS2_MEM_SELECT_GGTT (1 << 0) /* 0: PPGTT, 1: GGTT */ #define GEN8_OASTATUS _MMIO(0x2b08) +#define GEN8_OASTATUS_TAIL_POINTER_WRAP (1 << 17) +#define GEN8_OASTATUS_HEAD_POINTER_WRAP (1 << 16) #define GEN8_OASTATUS_OVERRUN_STATUS (1 << 3) #define GEN8_OASTATUS_COUNTER_OVERFLOW (1 << 2) #define GEN8_OASTATUS_OABUFFER_OVERFLOW (1 << 1) From afd4cf78a189fa3376fe0f6ceddb91be17a2ba68 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 19 Nov 2020 09:07:17 +0000 Subject: [PATCH 62/66] drm/i915/display: Whitespace cleanups drivers/gpu/drm/i915/display/intel_display.c:3634 intel_find_initial_plane_obj() warn: inconsistent indenting drivers/gpu/drm/i915/display/intel_display.c:15367 kill_bigjoiner_slave() warn: inconsistent indenting Signed-off-by: Chris Wilson Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20201119090717.30687-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/display/intel_display.c | 23 ++++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5c07c74d4397..1a0f00f37ca9 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3631,8 +3631,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, struct intel_plane *intel_plane = to_intel_plane(primary); struct intel_plane_state *intel_state = to_intel_plane_state(plane_state); - struct intel_crtc_state *crtc_state = - to_intel_crtc_state(intel_crtc->base.state); + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(intel_crtc->base.state); struct drm_framebuffer *fb; struct i915_vma *vma; @@ -15361,17 +15361,17 @@ static int kill_bigjoiner_slave(struct intel_atomic_state *state, struct intel_crtc_state *master_crtc_state) { struct intel_crtc_state *slave_crtc_state = - intel_atomic_get_crtc_state(&state->base, - master_crtc_state->bigjoiner_linked_crtc); + intel_atomic_get_crtc_state(&state->base, + master_crtc_state->bigjoiner_linked_crtc); - if (IS_ERR(slave_crtc_state)) - return PTR_ERR(slave_crtc_state); + if (IS_ERR(slave_crtc_state)) + return PTR_ERR(slave_crtc_state); - slave_crtc_state->bigjoiner = master_crtc_state->bigjoiner = false; - slave_crtc_state->bigjoiner_slave = master_crtc_state->bigjoiner_slave = false; - slave_crtc_state->bigjoiner_linked_crtc = master_crtc_state->bigjoiner_linked_crtc = NULL; - intel_crtc_copy_uapi_to_hw_state(state, slave_crtc_state); - return 0; + slave_crtc_state->bigjoiner = master_crtc_state->bigjoiner = false; + slave_crtc_state->bigjoiner_slave = master_crtc_state->bigjoiner_slave = false; + slave_crtc_state->bigjoiner_linked_crtc = master_crtc_state->bigjoiner_linked_crtc = NULL; + intel_crtc_copy_uapi_to_hw_state(state, slave_crtc_state); + return 0; } /** @@ -15949,7 +15949,6 @@ static void intel_update_crtc(struct intel_atomic_state *state, intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); } - static void intel_old_crtc_state_disables(struct intel_atomic_state *state, struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *new_crtc_state, From 9533fd8019fba6c59bb90313d2664a53160e007e Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Thu, 19 Nov 2020 15:26:15 -0800 Subject: [PATCH 63/66] drm/i915: Do not call hsw_set_frame_start_delay for dsi This should fix the boot oops for dsi v2: * Fix indent (Manasi) v3: * Remove redundant condition (Matt Roper) Fixes: 4e3cdb4535e7 ("drm/i915/dp: Master/Slave enable/disable sequence for bigjoiner") Signed-off-by: Manasi Navare Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20201119232615.23231-1-manasi.d.navare@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 1a0f00f37ca9..0038f14c8bfb 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7211,12 +7211,10 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) bdw_set_pipemisc(new_crtc_state); - if (!new_crtc_state->bigjoiner_slave || !transcoder_is_dsi(cpu_transcoder)) { - if (!transcoder_is_dsi(cpu_transcoder)) - intel_set_transcoder_timings(new_crtc_state); + if (!new_crtc_state->bigjoiner_slave && !transcoder_is_dsi(cpu_transcoder)) { + intel_set_transcoder_timings(new_crtc_state); - if (cpu_transcoder != TRANSCODER_EDP && - !transcoder_is_dsi(cpu_transcoder)) + if (cpu_transcoder != TRANSCODER_EDP) intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder), new_crtc_state->pixel_multiplier - 1); From f287c536d9431f5788916b204febab8d27a5ce55 Mon Sep 17 00:00:00 2001 From: Aditya Swarup Date: Tue, 17 Nov 2020 00:48:36 -0800 Subject: [PATCH 64/66] drm/i915/dg1: Enable ports For DG1 we have a little of mix up wrt to DDI/port names and indexes. Bspec refers to the ports as DDIA, DDIB, DDI USBC1 and DDI USBC2 (besides the DDIA, DDIB, DDIC, DDID), but the previous naming is the most unambiguous one. This means that for any register on Display Engine we should use the index of A, B, D and E. However in some places this is not true: - VBT: uses C and D and have to be mapped to D/E - IO/Combo: uses C and D, but we already differentiate those when we created the phy vs port distinction. This additional mapping for VBT and phy are already covered in previous patches, so now we can initialize all the DDIs as A, B, D and E. v2: Squash previous patch enabling just ports A and B since most of the pumbling code is already merged now Cc: Matt Roper Cc: Clinton Taylor Signed-off-by: Aditya Swarup Reviewed-by: Lucas De Marchi Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20201117084836.2318234-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0038f14c8bfb..595183f7b60f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7396,7 +7396,7 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy) { if (phy == PHY_NONE) return false; - else if (IS_ROCKETLAKE(dev_priv)) + else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) return phy <= PHY_D; else if (IS_JSL_EHL(dev_priv)) return phy <= PHY_C; @@ -7408,7 +7408,7 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy) bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy) { - if (IS_ROCKETLAKE(dev_priv)) + if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) return false; else if (INTEL_GEN(dev_priv) >= 12) return phy >= PHY_D && phy <= PHY_I; @@ -7420,7 +7420,7 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy) enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port) { - if (IS_ROCKETLAKE(i915) && port >= PORT_TC1) + if ((IS_DG1(i915) || IS_ROCKETLAKE(i915)) && port >= PORT_TC1) return PHY_C + port - PORT_TC1; else if (IS_JSL_EHL(i915) && port == PORT_D) return PHY_A; @@ -17601,7 +17601,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; - if (IS_ROCKETLAKE(dev_priv)) { + if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) { intel_ddi_init(dev_priv, PORT_A); intel_ddi_init(dev_priv, PORT_B); intel_ddi_init(dev_priv, PORT_TC1); From 9a3a238b3de97b4210c6de66aa88b2d7021ac086 Mon Sep 17 00:00:00 2001 From: Julian Stecklina Date: Wed, 11 Nov 2020 18:28:11 +0100 Subject: [PATCH 65/66] drm/i915/gvt: treat intel_gvt_mpt as const in gvt code The current interface of intel_gvt_register_hypervisor() expects a non-const pointer to struct intel_gvt_mpt, even though the mediator never modifies (or should modifiy) the content of this struct. Change the function signature and relevant struct members to const to properly express the API's intent and allow instances of intel_gvt_mpt to be allocated as const. While I was here, I also made KVM's instance of this struct const to reduce the number of writable function pointers in the kernel. Cc: Zhenyu Wang Cc: intel-gvt-dev@lists.freedesktop.org Reviewed-by: Zhenyu Wang Signed-off-by: Julian Stecklina Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20201111172811.558443-1-julian.stecklina@cyberus-technology.de --- drivers/gpu/drm/i915/gvt/gvt.c | 2 +- drivers/gpu/drm/i915/gvt/gvt.h | 2 +- drivers/gpu/drm/i915/gvt/kvmgt.c | 2 +- drivers/gpu/drm/i915/gvt/mpt.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 0262a6fa3a6c..d1d8ee4a5f16 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -415,7 +415,7 @@ intel_gvt_pm_resume(struct intel_gvt *gvt) } int -intel_gvt_register_hypervisor(struct intel_gvt_mpt *m) +intel_gvt_register_hypervisor(const struct intel_gvt_mpt *m) { int ret; void *gvt; diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index b3d6355dd797..cf3578e3f4dd 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -56,7 +56,7 @@ struct intel_gvt_host { struct device *dev; bool initialized; int hypervisor_type; - struct intel_gvt_mpt *mpt; + const struct intel_gvt_mpt *mpt; }; extern struct intel_gvt_host intel_gvt_host; diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index ad8a9df49f29..d830b6c65284 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -2099,7 +2099,7 @@ static bool kvmgt_is_valid_gfn(unsigned long handle, unsigned long gfn) return ret; } -static struct intel_gvt_mpt kvmgt_mpt = { +static const struct intel_gvt_mpt kvmgt_mpt = { .type = INTEL_GVT_HYPERVISOR_KVM, .host_init = kvmgt_host_init, .host_exit = kvmgt_host_exit, diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h index 9ad224df9c68..6f92cde71971 100644 --- a/drivers/gpu/drm/i915/gvt/mpt.h +++ b/drivers/gpu/drm/i915/gvt/mpt.h @@ -392,7 +392,7 @@ static inline bool intel_gvt_hypervisor_is_valid_gfn( return intel_gvt_host.mpt->is_valid_gfn(vgpu->handle, gfn); } -int intel_gvt_register_hypervisor(struct intel_gvt_mpt *); +int intel_gvt_register_hypervisor(const struct intel_gvt_mpt *); void intel_gvt_unregister_hypervisor(void); #endif /* _GVT_MPT_H_ */ From b3bf99daaee96a141536ce5c60a0d6dba6ec1d23 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 25 Nov 2020 19:30:32 +0000 Subject: [PATCH 66/66] drm/i915/display: Defer initial modeset until after GGTT is initialised MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior to sanitizing the GGTT, the only operations allowed in intel_display_init_nogem() are those to reserve the preallocated (and active) regions in the GGTT leftover from the BIOS. Trying to allocate a GGTT vma (such as intel_pin_and_fence_fb_obj during the initial modeset) may then conflict with other preallocated regions that have not yet been protected. Move the initial modesetting from the end of init_nogem to the beginning of init so that any vma pinning (either framebuffers or DSB, for example), is after the GGTT is ready to handle it. This will prevent the DSB object from being destroyed too early: [ 53.449241] BUG: KASAN: use-after-free in i915_init_ggtt+0x324/0x9e0 [i915] [ 53.449309] Read of size 8 at addr ffff88811b1e8070 by task systemd-udevd/345 [ 53.449399] CPU: 1 PID: 345 Comm: systemd-udevd Tainted: G W 5.10.0-rc5+ #12 [ 53.449409] Call Trace: [ 53.449418] dump_stack+0x9a/0xcc [ 53.449558] ? i915_init_ggtt+0x324/0x9e0 [i915] [ 53.449565] print_address_description.constprop.0+0x3e/0x60 [ 53.449577] ? _raw_spin_lock_irqsave+0x4e/0x50 [ 53.449718] ? i915_init_ggtt+0x324/0x9e0 [i915] [ 53.449849] ? i915_init_ggtt+0x324/0x9e0 [i915] [ 53.449857] kasan_report.cold+0x1f/0x37 [ 53.449993] ? i915_init_ggtt+0x324/0x9e0 [i915] [ 53.450130] i915_init_ggtt+0x324/0x9e0 [i915] [ 53.450273] ? i915_ggtt_suspend+0x1f0/0x1f0 [i915] [ 53.450281] ? static_obj+0x69/0x80 [ 53.450289] ? lockdep_init_map_waits+0xa9/0x310 [ 53.450431] ? intel_wopcm_init+0x96/0x3d0 [i915] [ 53.450581] ? i915_gem_init+0x75/0x2d0 [i915] [ 53.450720] i915_gem_init+0x75/0x2d0 [i915] [ 53.450852] i915_driver_probe+0x8c2/0x1210 [i915] [ 53.450993] ? i915_pm_prepare+0x630/0x630 [i915] [ 53.451006] ? check_chain_key+0x1e7/0x2e0 [ 53.451025] ? __pm_runtime_resume+0x58/0xb0 [ 53.451157] i915_pci_probe+0xa6/0x2b0 [i915] [ 53.451285] ? i915_pci_remove+0x40/0x40 [i915] [ 53.451295] ? lockdep_hardirqs_on_prepare+0x124/0x230 [ 53.451302] ? _raw_spin_unlock_irqrestore+0x42/0x50 [ 53.451309] ? lockdep_hardirqs_on+0xbf/0x130 [ 53.451315] ? preempt_count_sub+0xf/0xb0 [ 53.451321] ? _raw_spin_unlock_irqrestore+0x2f/0x50 [ 53.451335] pci_device_probe+0xf9/0x190 [ 53.451350] really_probe+0x17f/0x5b0 [ 53.451365] driver_probe_device+0x13a/0x1c0 [ 53.451376] device_driver_attach+0x82/0x90 [ 53.451386] ? device_driver_attach+0x90/0x90 [ 53.451391] __driver_attach+0xab/0x190 [ 53.451401] ? device_driver_attach+0x90/0x90 [ 53.451407] bus_for_each_dev+0xe4/0x140 [ 53.451414] ? subsys_dev_iter_exit+0x10/0x10 [ 53.451423] ? __list_add_valid+0x2b/0xa0 [ 53.451440] bus_add_driver+0x227/0x2e0 [ 53.451454] driver_register+0xd3/0x150 [ 53.451585] i915_init+0x92/0xac [i915] [ 53.451592] ? 0xffffffffa0a20000 [ 53.451598] do_one_initcall+0xb6/0x3b0 [ 53.451606] ? trace_event_raw_event_initcall_finish+0x150/0x150 [ 53.451614] ? __kasan_kmalloc.constprop.0+0xc2/0xd0 [ 53.451627] ? kmem_cache_alloc_trace+0x4a4/0x8e0 [ 53.451634] ? kasan_unpoison_shadow+0x33/0x40 [ 53.451649] do_init_module+0xf8/0x350 [ 53.451662] load_module+0x43de/0x47f0 [ 53.451716] ? module_frob_arch_sections+0x20/0x20 [ 53.451731] ? rw_verify_area+0x5f/0x130 [ 53.451780] ? __do_sys_finit_module+0x10d/0x1a0 [ 53.451785] __do_sys_finit_module+0x10d/0x1a0 [ 53.451792] ? __ia32_sys_init_module+0x40/0x40 [ 53.451800] ? seccomp_do_user_notification.isra.0+0x5c0/0x5c0 [ 53.451829] ? rcu_read_lock_bh_held+0xb0/0xb0 [ 53.451835] ? mark_held_locks+0x24/0x90 [ 53.451856] do_syscall_64+0x33/0x80 [ 53.451863] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 53.451868] RIP: 0033:0x7fde09b4470d [ 53.451875] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 53 f7 0c 00 f7 d8 64 89 01 48 [ 53.451880] RSP: 002b:00007ffd6abc1718 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 53.451890] RAX: ffffffffffffffda RBX: 000056444e528150 RCX: 00007fde09b4470d [ 53.451895] RDX: 0000000000000000 RSI: 00007fde09a21ded RDI: 000000000000000f [ 53.451899] RBP: 0000000000020000 R08: 0000000000000000 R09: 0000000000000000 [ 53.451904] R10: 000000000000000f R11: 0000000000000246 R12: 00007fde09a21ded [ 53.451909] R13: 0000000000000000 R14: 000056444e329200 R15: 000056444e528150 [ 53.451957] Allocated by task 345: [ 53.451995] kasan_save_stack+0x1b/0x40 [ 53.452001] __kasan_kmalloc.constprop.0+0xc2/0xd0 [ 53.452006] kmem_cache_alloc+0x1cd/0x8d0 [ 53.452146] i915_vma_instance+0x126/0xb70 [i915] [ 53.452304] i915_gem_object_ggtt_pin_ww+0x222/0x3f0 [i915] [ 53.452446] intel_dsb_prepare+0x14f/0x230 [i915] [ 53.452588] intel_atomic_commit+0x183/0x690 [i915] [ 53.452730] intel_initial_commit+0x2bc/0x2f0 [i915] [ 53.452871] intel_modeset_init_nogem+0xa02/0x2af0 [i915] [ 53.452995] i915_driver_probe+0x8af/0x1210 [i915] [ 53.453120] i915_pci_probe+0xa6/0x2b0 [i915] [ 53.453125] pci_device_probe+0xf9/0x190 [ 53.453131] really_probe+0x17f/0x5b0 [ 53.453136] driver_probe_device+0x13a/0x1c0 [ 53.453142] device_driver_attach+0x82/0x90 [ 53.453148] __driver_attach+0xab/0x190 [ 53.453153] bus_for_each_dev+0xe4/0x140 [ 53.453158] bus_add_driver+0x227/0x2e0 [ 53.453164] driver_register+0xd3/0x150 [ 53.453286] i915_init+0x92/0xac [i915] [ 53.453292] do_one_initcall+0xb6/0x3b0 [ 53.453297] do_init_module+0xf8/0x350 [ 53.453302] load_module+0x43de/0x47f0 [ 53.453307] __do_sys_finit_module+0x10d/0x1a0 [ 53.453312] do_syscall_64+0x33/0x80 [ 53.453318] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 53.453345] Freed by task 82: [ 53.453379] kasan_save_stack+0x1b/0x40 [ 53.453384] kasan_set_track+0x1c/0x30 [ 53.453389] kasan_set_free_info+0x1b/0x30 [ 53.453394] __kasan_slab_free+0x112/0x160 [ 53.453399] kmem_cache_free+0xb2/0x3f0 [ 53.453536] i915_gem_flush_free_objects+0x31a/0x3b0 [i915] [ 53.453542] process_one_work+0x519/0x9f0 [ 53.453547] worker_thread+0x75/0x5c0 [ 53.453552] kthread+0x1da/0x230 [ 53.453557] ret_from_fork+0x22/0x30 [ 53.453584] The buggy address belongs to the object at ffff88811b1e8040 which belongs to the cache i915_vma of size 968 [ 53.453692] The buggy address is located 48 bytes inside of 968-byte region [ffff88811b1e8040, ffff88811b1e8408) [ 53.453792] The buggy address belongs to the page: [ 53.453842] page:00000000b35f7048 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff88811b1ef940 pfn:0x11b1e8 [ 53.453847] head:00000000b35f7048 order:3 compound_mapcount:0 compound_pincount:0 [ 53.453853] flags: 0x8000000000010200(slab|head) [ 53.453860] raw: 8000000000010200 ffff888115596248 ffff888115596248 ffff8881155b6340 [ 53.453866] raw: ffff88811b1ef940 0000000000170001 00000001ffffffff 0000000000000000 [ 53.453870] page dumped because: kasan: bad access detected [ 53.453895] Memory state around the buggy address: [ 53.453944] ffff88811b1e7f00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 53.454011] ffff88811b1e7f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 53.454079] >ffff88811b1e8000: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb [ 53.454146] ^ [ 53.454211] ffff88811b1e8080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 53.454279] ffff88811b1e8100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 53.454347] ================================================================== [ 53.454414] Disabling lock debugging due to kernel taint [ 53.454434] general protection fault, probably for non-canonical address 0xdead0000000000d0: 0000 [#1] PREEMPT SMP KASAN PTI [ 53.454446] CPU: 1 PID: 345 Comm: systemd-udevd Tainted: G B W 5.10.0-rc5+ #12 [ 53.454592] RIP: 0010:i915_init_ggtt+0x26f/0x9e0 [i915] [ 53.454602] Code: 89 8d 48 ff ff ff 4c 8d 60 d0 49 39 c7 0f 84 37 02 00 00 4c 89 b5 40 ff ff ff 4d 8d bc 24 90 00 00 00 4c 89 ff e8 c1 97 f8 e0 <49> 83 bc 24 90 00 00 00 00 0f 84 0f 02 00 00 49 8d 7c 24 08 e8 a8 [ 53.454618] RSP: 0018:ffff88812247f430 EFLAGS: 00010286 [ 53.454625] RAX: 0000000000000000 RBX: ffff888136440000 RCX: ffffffffa03fb78f [ 53.454633] RDX: 0000000000000000 RSI: 0000000000000008 RDI: dead000000000160 [ 53.454641] RBP: ffff88812247f500 R08: ffffffff8113589f R09: 0000000000000000 [ 53.454648] R10: ffffffff83063843 R11: fffffbfff060c708 R12: dead0000000000d0 [ 53.454656] R13: ffff888136449ba0 R14: 0000000000002000 R15: dead000000000160 [ 53.454664] FS: 00007fde095c4880(0000) GS:ffff88840c880000(0000) knlGS:0000000000000000 [ 53.454672] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 53.454679] CR2: 00007fef132b4f28 CR3: 000000012245c002 CR4: 00000000003706e0 [ 53.454686] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 53.454693] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 53.454700] Call Trace: [ 53.454833] ? i915_ggtt_suspend+0x1f0/0x1f0 [i915] Reported-by: Matthew Auld Fixes: afeda4f3b1c8 ("drm/i915/dsb: Pre allocate and late cleanup of cmd buffer") Signed-off-by: Chris Wilson Cc: Ville Syrjälä Cc: Matthew Auld Cc: Lucas De Marchi Tested-by: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20201125193032.29282-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/display/intel_display.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 595183f7b60f..ba26545392bc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -18729,16 +18729,6 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915) if (!HAS_GMCH(i915)) sanitize_watermarks(i915); - /* - * Force all active planes to recompute their states. So that on - * mode_setcrtc after probe, all the intel_plane_state variables - * are already calculated and there is no assert_plane warnings - * during bootup. - */ - ret = intel_initial_commit(dev); - if (ret) - drm_dbg_kms(&i915->drm, "Initial commit in probe failed.\n"); - return 0; } @@ -18750,6 +18740,16 @@ int intel_modeset_init(struct drm_i915_private *i915) if (!HAS_DISPLAY(i915)) return 0; + /* + * Force all active planes to recompute their states. So that on + * mode_setcrtc after probe, all the intel_plane_state variables + * are already calculated and there is no assert_plane warnings + * during bootup. + */ + ret = intel_initial_commit(&i915->drm); + if (ret) + return ret; + intel_overlay_setup(i915); ret = intel_fbdev_init(&i915->drm);