summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/display
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 17:39:57 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 17:39:57 +0000
commitdc50eab76b709d68175a358d6e23a5a3890764d3 (patch)
treec754d0390db060af0213ff994f0ac310e4cfd6e9 /drivers/gpu/drm/i915/display
parentAdding debian version 6.6.15-2. (diff)
downloadlinux-dc50eab76b709d68175a358d6e23a5a3890764d3.tar.xz
linux-dc50eab76b709d68175a358d6e23a5a3890764d3.zip
Merging upstream version 6.7.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/gpu/drm/i915/display')
-rw-r--r--drivers/gpu/drm/i915/display/g4x_dp.h26
-rw-r--r--drivers/gpu/drm/i915/display/g4x_hdmi.c6
-rw-r--r--drivers/gpu/drm/i915/display/g4x_hdmi.h12
-rw-r--r--drivers/gpu/drm/i915/display/hsw_ips.c1
-rw-r--r--drivers/gpu/drm/i915/display/hsw_ips.h35
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_plane.c1
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_plane.h23
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_wm.h17
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.c13
-rw-r--r--drivers/gpu/drm/i915/display/intel_acpi.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic_plane.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_audio.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_audio.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.c26
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c107
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.c156
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_color_regs.h286
-rw-r--r--drivers/gpu/drm/i915/display/intel_combo_phy.c17
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.c6
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.c64
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.h14
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.c118
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.c214
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.h17
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h13
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c18
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c525
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h8
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_core.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_debugfs.c38
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.c156
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_device.h41
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_driver.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_irq.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c10
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_map.c63
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_well.c52
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_well.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h55
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_wa.c48
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_wa.h13
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c1092
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.h39
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux.c49
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux_regs.h80
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_hdcp.c87
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_link_training.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c222
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpio_phy.h96
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll.c57
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.c987
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.h33
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpt.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_drrs.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.c235
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.h9
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb_regs.h31
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsi_vbt.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_dvo.c13
-rw-r--r--drivers/gpu/drm/i915/display/intel_dvo.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb.c63
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb_pin.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.c181
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.c169
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.h8
-rw-r--r--drivers/gpu/drm/i915/display/intel_frontbuffer.c37
-rw-r--r--drivers/gpu/drm/i915/display/intel_frontbuffer.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.c41
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc.c617
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c590
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.h72
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.c123
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug.c87
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug_irq.c24
-rw-r--r--drivers/gpu/drm/i915/display/intel_link_bw.c212
-rw-r--r--drivers/gpu/drm/i915/display/intel_link_bw.h37
-rw-r--r--drivers/gpu/drm/i915/display/intel_lpe_audio.h18
-rw-r--r--drivers/gpu/drm/i915/display/intel_lspcon.c29
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.c33
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.h19
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_verify.c134
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_verify.h11
-rw-r--r--drivers/gpu/drm/i915/display/intel_overlay.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_overlay.h35
-rw-r--r--drivers/gpu/drm/i915/display/intel_panel.c19
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_display.h53
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_refclk.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_refclk.h23
-rw-r--r--drivers/gpu/drm/i915/display/intel_plane_initial.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_pmdemand.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c72
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.c395
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.h13
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo_regs.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.h8
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.c66
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_tv.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_tv.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_vblank.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_vblank.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c630
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc_regs.h397
-rw-r--r--drivers/gpu/drm/i915/display/intel_vga.c18
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.c18
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_wm.c2
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane.c22
-rw-r--r--drivers/gpu/drm/i915/display/skl_watermark.c40
-rw-r--r--drivers/gpu/drm/i915/display/skl_watermark.h6
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.c130
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.h13
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi_pll.h9
127 files changed, 6543 insertions, 3332 deletions
diff --git a/drivers/gpu/drm/i915/display/g4x_dp.h b/drivers/gpu/drm/i915/display/g4x_dp.h
index a38b3e1e01..a10638ab74 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.h
+++ b/drivers/gpu/drm/i915/display/g4x_dp.h
@@ -17,6 +17,7 @@ struct intel_crtc_state;
struct intel_dp;
struct intel_encoder;
+#ifdef I915
const struct dpll *vlv_get_dpll(struct drm_i915_private *i915);
enum pipe vlv_active_pipe(struct intel_dp *intel_dp);
void g4x_dp_set_clock(struct intel_encoder *encoder,
@@ -26,5 +27,30 @@ bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
enum pipe *pipe);
bool g4x_dp_init(struct drm_i915_private *dev_priv,
i915_reg_t output_reg, enum port port);
+#else
+static inline const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
+{
+ return NULL;
+}
+static inline int vlv_active_pipe(struct intel_dp *intel_dp)
+{
+ return 0;
+}
+static inline void g4x_dp_set_clock(struct intel_encoder *encoder,
+ struct intel_crtc_state *pipe_config)
+{
+}
+static inline bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
+ i915_reg_t dp_reg, int port,
+ enum pipe *pipe)
+{
+ return false;
+}
+static inline bool g4x_dp_init(struct drm_i915_private *dev_priv,
+ i915_reg_t output_reg, int port)
+{
+ return false;
+}
+#endif
#endif
diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
index 634b14116d..45e044b4a8 100644
--- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
@@ -16,6 +16,7 @@
#include "intel_display_types.h"
#include "intel_dp_aux.h"
#include "intel_dpio_phy.h"
+#include "intel_fdi.h"
#include "intel_fifo_underrun.h"
#include "intel_hdmi.h"
#include "intel_hotplug.h"
@@ -133,8 +134,11 @@ static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- if (HAS_PCH_SPLIT(i915))
+ if (HAS_PCH_SPLIT(i915)) {
crtc_state->has_pch_encoder = true;
+ if (!intel_fdi_compute_pipe_bpp(crtc_state))
+ return -EINVAL;
+ }
if (IS_G4X(i915))
crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.h b/drivers/gpu/drm/i915/display/g4x_hdmi.h
index 1e3ea7f3c8..817f55c7a3 100644
--- a/drivers/gpu/drm/i915/display/g4x_hdmi.h
+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.h
@@ -15,9 +15,21 @@ struct drm_atomic_state;
struct drm_connector;
struct drm_i915_private;
+#ifdef I915
void g4x_hdmi_init(struct drm_i915_private *dev_priv,
i915_reg_t hdmi_reg, enum port port);
int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
struct drm_atomic_state *state);
+#else
+static inline void g4x_hdmi_init(struct drm_i915_private *dev_priv,
+ i915_reg_t hdmi_reg, int port)
+{
+}
+static inline int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
+ struct drm_atomic_state *state)
+{
+ return 0;
+}
+#endif
#endif
diff --git a/drivers/gpu/drm/i915/display/hsw_ips.c b/drivers/gpu/drm/i915/display/hsw_ips.c
index 8eca0de065..7dc38ac020 100644
--- a/drivers/gpu/drm/i915/display/hsw_ips.c
+++ b/drivers/gpu/drm/i915/display/hsw_ips.c
@@ -6,6 +6,7 @@
#include "hsw_ips.h"
#include "i915_drv.h"
#include "i915_reg.h"
+#include "intel_color_regs.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_pcode.h"
diff --git a/drivers/gpu/drm/i915/display/hsw_ips.h b/drivers/gpu/drm/i915/display/hsw_ips.h
index 4eb83b3507..35364228e1 100644
--- a/drivers/gpu/drm/i915/display/hsw_ips.h
+++ b/drivers/gpu/drm/i915/display/hsw_ips.h
@@ -12,6 +12,7 @@ struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
+#ifdef I915
bool hsw_ips_disable(const struct intel_crtc_state *crtc_state);
bool hsw_ips_pre_update(struct intel_atomic_state *state,
struct intel_crtc *crtc);
@@ -23,5 +24,39 @@ int hsw_ips_compute_config(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void hsw_ips_get_config(struct intel_crtc_state *crtc_state);
void hsw_ips_crtc_debugfs_add(struct intel_crtc *crtc);
+#else
+static inline bool hsw_ips_disable(const struct intel_crtc_state *crtc_state)
+{
+ return false;
+}
+static inline bool hsw_ips_pre_update(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+ return false;
+}
+static inline void hsw_ips_post_update(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+}
+static inline bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
+{
+ return false;
+}
+static inline bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
+{
+ return false;
+}
+static inline int hsw_ips_compute_config(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+ return 0;
+}
+static inline void hsw_ips_get_config(struct intel_crtc_state *crtc_state)
+{
+}
+static inline void hsw_ips_crtc_debugfs_add(struct intel_crtc *crtc)
+{
+}
+#endif
#endif /* __HSW_IPS_H__ */
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c
index b104883244..91f2bc405c 100644
--- a/drivers/gpu/drm/i915/display/i9xx_plane.c
+++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
@@ -17,6 +17,7 @@
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fbc.h"
+#include "intel_frontbuffer.h"
#include "intel_sprite.h"
/* Primary plane formats for gen <= 3 */
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.h b/drivers/gpu/drm/i915/display/i9xx_plane.h
index 027b660539..b3d724a144 100644
--- a/drivers/gpu/drm/i915/display/i9xx_plane.h
+++ b/drivers/gpu/drm/i915/display/i9xx_plane.h
@@ -15,6 +15,7 @@ struct intel_initial_plane_config;
struct intel_plane;
struct intel_plane_state;
+#ifdef I915
unsigned int i965_plane_max_stride(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation);
@@ -25,4 +26,26 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe);
void i9xx_get_initial_plane_config(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config);
+#else
+static inline unsigned int i965_plane_max_stride(struct intel_plane *plane,
+ u32 pixel_format, u64 modifier,
+ unsigned int rotation)
+{
+ return 0;
+}
+static inline int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
+{
+ return 0;
+}
+static inline struct intel_plane *
+intel_primary_plane_create(struct drm_i915_private *dev_priv, int pipe)
+{
+ return NULL;
+}
+static inline void i9xx_get_initial_plane_config(struct intel_crtc *crtc,
+ struct intel_initial_plane_config *plane_config)
+{
+}
+#endif
+
#endif
diff --git a/drivers/gpu/drm/i915/display/i9xx_wm.h b/drivers/gpu/drm/i915/display/i9xx_wm.h
index b87ae36968..de0920730a 100644
--- a/drivers/gpu/drm/i915/display/i9xx_wm.h
+++ b/drivers/gpu/drm/i915/display/i9xx_wm.h
@@ -12,9 +12,26 @@ struct drm_i915_private;
struct intel_crtc_state;
struct intel_plane_state;
+#ifdef I915
bool ilk_disable_lp_wm(struct drm_i915_private *i915);
void ilk_wm_sanitize(struct drm_i915_private *i915);
bool intel_set_memory_cxsr(struct drm_i915_private *i915, bool enable);
void i9xx_wm_init(struct drm_i915_private *i915);
+#else
+static inline bool ilk_disable_lp_wm(struct drm_i915_private *i915)
+{
+ return false;
+}
+static inline void ilk_wm_sanitize(struct drm_i915_private *i915)
+{
+}
+static inline bool intel_set_memory_cxsr(struct drm_i915_private *i915, bool enable)
+{
+ return false;
+}
+static inline void i9xx_wm_init(struct drm_i915_private *i915)
+{
+}
+#endif
#endif /* __I9XX_WM_H__ */
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index f7113b0321..bf0dbd7d06 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -1828,7 +1828,7 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
u32 ths_prepare_ns, tclk_trail_ns;
u32 hs_zero_cnt;
- u32 tclk_pre_cnt, tclk_post_cnt;
+ u32 tclk_pre_cnt;
tlpx_ns = intel_dsi_tlpx_ns(intel_dsi);
@@ -1875,15 +1875,6 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
tclk_pre_cnt = ICL_TCLK_PRE_CNT_MAX;
}
- /* tclk post count in escape clocks */
- tclk_post_cnt = DIV_ROUND_UP(mipi_config->tclk_post, tlpx_ns);
- if (tclk_post_cnt > ICL_TCLK_POST_CNT_MAX) {
- drm_dbg_kms(&dev_priv->drm,
- "tclk_post_cnt out of range (%d)\n",
- tclk_post_cnt);
- tclk_post_cnt = ICL_TCLK_POST_CNT_MAX;
- }
-
/* hs zero cnt in escape clocks */
hs_zero_cnt = DIV_ROUND_UP(mipi_config->ths_prepare_hszero -
ths_prepare_ns, tlpx_ns);
@@ -1909,8 +1900,6 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
CLK_ZERO(clk_zero_cnt) |
CLK_PRE_OVERRIDE |
CLK_PRE(tclk_pre_cnt) |
- CLK_POST_OVERRIDE |
- CLK_POST(tclk_post_cnt) |
CLK_TRAIL_OVERRIDE |
CLK_TRAIL(trail_cnt));
diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c
index 9df78e7caa..0aa3999374 100644
--- a/drivers/gpu/drm/i915/display/intel_acpi.c
+++ b/drivers/gpu/drm/i915/display/intel_acpi.c
@@ -153,7 +153,7 @@ static acpi_handle intel_dsm_pci_probe(struct pci_dev *pdev)
static bool intel_dsm_detect(void)
{
acpi_handle dhandle = NULL;
- char acpi_method_name[255] = { 0 };
+ char acpi_method_name[255] = {};
struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
struct pci_dev *pdev = NULL;
int vga_count = 0;
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
index 7cf51dd8c0..5d18145da2 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -259,6 +259,8 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
drm_property_blob_get(crtc_state->post_csc_lut);
crtc_state->update_pipe = false;
+ crtc_state->update_m_n = false;
+ crtc_state->update_lrr = false;
crtc_state->disable_lp_wm = false;
crtc_state->disable_cxsr = false;
crtc_state->update_wm_pre = false;
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index 60a492e186..b107435061 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -214,9 +214,6 @@ intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
int width, height;
unsigned int rel_data_rate;
- if (plane->id == PLANE_CURSOR)
- return 0;
-
if (!plane_state->uapi.visible)
return 0;
@@ -244,6 +241,9 @@ intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
rel_data_rate = width * height * fb->format->cpp[color_plane];
+ if (plane->id == PLANE_CURSOR)
+ return rel_data_rate;
+
return intel_adjusted_rate(&plane_state->uapi.src,
&plane_state->uapi.dst,
rel_data_rate);
@@ -981,6 +981,14 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
hsub = 2;
vsub = 2;
+ } else if (DISPLAY_VER(i915) >= 20 &&
+ intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
+ /*
+ * This allows NV12 and P0xx formats to have odd size and/or odd
+ * source coordinates on DISPLAY_VER(i915) >= 20
+ */
+ hsub = 1;
+ vsub = 1;
} else {
hsub = fb->format->hsub;
vsub = fb->format->vsub;
diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c
index 3d9c9b4f27..19605264a3 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_audio.c
@@ -759,10 +759,10 @@ static void ibx_audio_codec_enable(struct intel_encoder *encoder,
mutex_unlock(&i915->display.audio.mutex);
}
-void intel_audio_sdp_split_update(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state)
+void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
enum transcoder trans = crtc_state->cpu_transcoder;
if (HAS_DP20(i915))
diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h
index 07d034a981..9327954b80 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.h
+++ b/drivers/gpu/drm/i915/display/intel_audio.h
@@ -29,7 +29,6 @@ void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv);
void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv);
void intel_audio_init(struct drm_i915_private *dev_priv);
void intel_audio_deinit(struct drm_i915_private *dev_priv);
-void intel_audio_sdp_split_update(struct intel_encoder *encoder,
- const struct intel_crtc_state *crtc_state);
+void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state);
#endif /* __INTEL_AUDIO_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index f735b03543..4e8f1e91bb 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -521,7 +521,8 @@ static void init_bdb_blocks(struct drm_i915_private *i915,
}
static void
-fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
+fill_detail_timing_data(struct drm_i915_private *i915,
+ struct drm_display_mode *panel_fixed_mode,
const struct lvds_dvo_timing *dvo_timing)
{
panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
@@ -561,11 +562,17 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
panel_fixed_mode->height_mm = (dvo_timing->vimage_hi << 8) |
dvo_timing->vimage_lo;
- /* Some VBTs have bogus h/vtotal values */
- if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
- panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
- if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
- panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
+ /* Some VBTs have bogus h/vsync_end values */
+ if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) {
+ drm_dbg_kms(&i915->drm, "reducing hsync_end %d->%d\n",
+ panel_fixed_mode->hsync_end, panel_fixed_mode->htotal);
+ panel_fixed_mode->hsync_end = panel_fixed_mode->htotal;
+ }
+ if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) {
+ drm_dbg_kms(&i915->drm, "reducing vsync_end %d->%d\n",
+ panel_fixed_mode->vsync_end, panel_fixed_mode->vtotal);
+ panel_fixed_mode->vsync_end = panel_fixed_mode->vtotal;
+ }
drm_mode_set_name(panel_fixed_mode);
}
@@ -849,7 +856,7 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
if (!panel_fixed_mode)
return;
- fill_detail_timing_data(panel_fixed_mode, panel_dvo_timing);
+ fill_detail_timing_data(i915, panel_fixed_mode, panel_dvo_timing);
panel->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
@@ -1134,7 +1141,7 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
if (!panel_fixed_mode)
return;
- fill_detail_timing_data(panel_fixed_mode, &dtds->dtds[index]);
+ fill_detail_timing_data(i915, panel_fixed_mode, &dtds->dtds[index]);
panel->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
@@ -2194,7 +2201,8 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin)
const u8 *ddc_pin_map;
int i, n_entries;
- if (HAS_PCH_MTP(i915) || IS_ALDERLAKE_P(i915)) {
+ if (INTEL_PCH_TYPE(i915) >= PCH_LNL || HAS_PCH_MTP(i915) ||
+ IS_ALDERLAKE_P(i915)) {
ddc_pin_map = adlp_ddc_pin_map;
n_entries = ARRAY_SIZE(adlp_ddc_pin_map);
} else if (IS_ALDERLAKE_S(i915)) {
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index f99cf8037b..c4839c67cb 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -32,6 +32,7 @@
#include "intel_cdclk.h"
#include "intel_crtc.h"
#include "intel_de.h"
+#include "intel_dp.h"
#include "intel_display_types.h"
#include "intel_mchbar_regs.h"
#include "intel_pci_config.h"
@@ -1381,6 +1382,31 @@ static const struct intel_cdclk_vals mtl_cdclk_table[] = {
{}
};
+static const struct intel_cdclk_vals lnl_cdclk_table[] = {
+ { .refclk = 38400, .cdclk = 153600, .divider = 2, .ratio = 16, .waveform = 0xaaaa },
+ { .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 16, .waveform = 0xad5a },
+ { .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 16, .waveform = 0xb6b6 },
+ { .refclk = 38400, .cdclk = 211200, .divider = 2, .ratio = 16, .waveform = 0xdbb6 },
+ { .refclk = 38400, .cdclk = 230400, .divider = 2, .ratio = 16, .waveform = 0xeeee },
+ { .refclk = 38400, .cdclk = 249600, .divider = 2, .ratio = 16, .waveform = 0xf7de },
+ { .refclk = 38400, .cdclk = 268800, .divider = 2, .ratio = 16, .waveform = 0xfefe },
+ { .refclk = 38400, .cdclk = 288000, .divider = 2, .ratio = 16, .waveform = 0xfffe },
+ { .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 330000, .divider = 2, .ratio = 25, .waveform = 0xdbb6 },
+ { .refclk = 38400, .cdclk = 360000, .divider = 2, .ratio = 25, .waveform = 0xeeee },
+ { .refclk = 38400, .cdclk = 390000, .divider = 2, .ratio = 25, .waveform = 0xf7de },
+ { .refclk = 38400, .cdclk = 420000, .divider = 2, .ratio = 25, .waveform = 0xfefe },
+ { .refclk = 38400, .cdclk = 450000, .divider = 2, .ratio = 25, .waveform = 0xfffe },
+ { .refclk = 38400, .cdclk = 480000, .divider = 2, .ratio = 25, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 487200, .divider = 2, .ratio = 29, .waveform = 0xfefe },
+ { .refclk = 38400, .cdclk = 522000, .divider = 2, .ratio = 29, .waveform = 0xfffe },
+ { .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29, .waveform = 0xffff },
+ { .refclk = 38400, .cdclk = 571200, .divider = 2, .ratio = 34, .waveform = 0xfefe },
+ { .refclk = 38400, .cdclk = 612000, .divider = 2, .ratio = 34, .waveform = 0xfffe },
+ { .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34, .waveform = 0xffff },
+ {}
+};
+
static int bxt_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk)
{
const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table;
@@ -1840,9 +1866,10 @@ static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i91
static bool pll_enable_wa_needed(struct drm_i915_private *dev_priv)
{
- return ((IS_DG2(dev_priv) || IS_METEORLAKE(dev_priv)) &&
- dev_priv->display.cdclk.hw.vco > 0 &&
- HAS_CDCLK_SQUASH(dev_priv));
+ return (DISPLAY_VER_FULL(dev_priv) == IP_VER(20, 0) ||
+ DISPLAY_VER_FULL(dev_priv) == IP_VER(14, 0) ||
+ IS_DG2(dev_priv)) &&
+ dev_priv->display.cdclk.hw.vco > 0;
}
static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,
@@ -1879,8 +1906,7 @@ static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,
dg2_cdclk_squash_program(dev_priv, waveform);
val = bxt_cdclk_cd2x_div_sel(dev_priv, clock, vco) |
- bxt_cdclk_cd2x_pipe(dev_priv, pipe) |
- skl_cdclk_decimal(cdclk);
+ bxt_cdclk_cd2x_pipe(dev_priv, pipe);
/*
* Disable SSA Precharge when CD clock frequency < 500 MHz,
@@ -1889,6 +1915,12 @@ static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,
if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
cdclk >= 500000)
val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
+
+ if (DISPLAY_VER(dev_priv) >= 20)
+ val |= MDCLK_SOURCE_SEL_CDCLK_PLL;
+ else
+ val |= skl_cdclk_decimal(cdclk);
+
intel_de_write(dev_priv, CDCLK_CTL, val);
if (pipe != INVALID_PIPE)
@@ -2533,6 +2565,48 @@ static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state)
return min_cdclk;
}
+static int intel_vdsc_min_cdclk(const 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);
+ int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
+ int min_cdclk = 0;
+
+ /*
+ * When we decide to use only one VDSC engine, since
+ * each VDSC operates with 1 ppc throughput, pixel clock
+ * cannot be higher than the VDSC clock (cdclk)
+ * If there 2 VDSC engines, then pixel clock can't be higher than
+ * VDSC clock(cdclk) * 2 and so on.
+ */
+ min_cdclk = max_t(int, min_cdclk,
+ DIV_ROUND_UP(crtc_state->pixel_rate, num_vdsc_instances));
+
+ if (crtc_state->bigjoiner_pipes) {
+ int pixel_clock = intel_dp_mode_to_fec_clock(crtc_state->hw.adjusted_mode.clock);
+
+ /*
+ * According to Bigjoiner bw check:
+ * compressed_bpp <= PPC * CDCLK * Big joiner Interface bits / Pixel clock
+ *
+ * We have already computed compressed_bpp, so now compute the min CDCLK that
+ * is required to support this compressed_bpp.
+ *
+ * => CDCLK >= compressed_bpp * Pixel clock / (PPC * Bigjoiner Interface bits)
+ *
+ * Since PPC = 2 with bigjoiner
+ * => CDCLK >= compressed_bpp * Pixel clock / 2 * Bigjoiner Interface bits
+ */
+ int bigjoiner_interface_bits = DISPLAY_VER(i915) > 13 ? 36 : 24;
+ int min_cdclk_bj = (crtc_state->dsc.compressed_bpp * pixel_clock) /
+ (2 * bigjoiner_interface_bits);
+
+ min_cdclk = max(min_cdclk, min_cdclk_bj);
+ }
+
+ return min_cdclk;
+}
+
int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv =
@@ -2604,20 +2678,8 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
/* Account for additional needs from the planes */
min_cdclk = max(intel_planes_min_cdclk(crtc_state), min_cdclk);
- /*
- * When we decide to use only one VDSC engine, since
- * each VDSC operates with 1 ppc throughput, pixel clock
- * cannot be higher than the VDSC clock (cdclk)
- * If there 2 VDSC engines, then pixel clock can't be higher than
- * VDSC clock(cdclk) * 2 and so on.
- */
- if (crtc_state->dsc.compression_enable) {
- int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
-
- min_cdclk = max_t(int, min_cdclk,
- DIV_ROUND_UP(crtc_state->pixel_rate,
- num_vdsc_instances));
- }
+ if (crtc_state->dsc.compression_enable)
+ min_cdclk = max(min_cdclk, intel_vdsc_min_cdclk(crtc_state));
/*
* HACK. Currently for TGL/DG2 platforms we calculate
@@ -3120,7 +3182,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
&new_cdclk_state->actual)) {
/* All pipes must be switched off while we change the cdclk. */
- ret = intel_modeset_all_pipes(state, "CDCLK change");
+ ret = intel_modeset_all_pipes_late(state, "CDCLK change");
if (ret)
return ret;
@@ -3571,7 +3633,10 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = {
*/
void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
{
- if (IS_METEORLAKE(dev_priv)) {
+ if (DISPLAY_VER(dev_priv) >= 20) {
+ dev_priv->display.funcs.cdclk = &mtl_cdclk_funcs;
+ dev_priv->display.cdclk.table = lnl_cdclk_table;
+ } else if (DISPLAY_VER(dev_priv) >= 14) {
dev_priv->display.funcs.cdclk = &mtl_cdclk_funcs;
dev_priv->display.cdclk.table = mtl_cdclk_table;
} else if (IS_DG2(dev_priv)) {
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index 454607b4a0..1d26be54dd 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -24,6 +24,7 @@
#include "i915_reg.h"
#include "intel_color.h"
+#include "intel_color_regs.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dsb.h"
@@ -75,6 +76,10 @@ struct intel_color_funcs {
* software state. Used by eg. the hardware state checker.
*/
void (*read_csc)(struct intel_crtc_state *crtc_state);
+ /*
+ * Read config other than LUTs and CSCs, before them. Optional.
+ */
+ void (*get_config)(struct intel_crtc_state *crtc_state);
};
#define CTM_COEFF_SIGN (1ULL << 63)
@@ -1013,6 +1018,65 @@ static void hsw_color_commit_arm(const struct intel_crtc_state *crtc_state)
crtc_state->csc_mode);
}
+static u32 hsw_read_gamma_mode(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+
+ return intel_de_read(i915, GAMMA_MODE(crtc->pipe));
+}
+
+static u32 ilk_read_csc_mode(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+
+ return intel_de_read(i915, PIPE_CSC_MODE(crtc->pipe));
+}
+
+static void i9xx_get_config(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+ u32 tmp;
+
+ tmp = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
+
+ if (tmp & DISP_PIPE_GAMMA_ENABLE)
+ crtc_state->gamma_enable = true;
+
+ if (!HAS_GMCH(dev_priv) && tmp & DISP_PIPE_CSC_ENABLE)
+ crtc_state->csc_enable = true;
+}
+
+static void hsw_get_config(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ crtc_state->gamma_mode = hsw_read_gamma_mode(crtc);
+ crtc_state->csc_mode = ilk_read_csc_mode(crtc);
+
+ i9xx_get_config(crtc_state);
+}
+
+static void skl_get_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);
+ u32 tmp;
+
+ crtc_state->gamma_mode = hsw_read_gamma_mode(crtc);
+ crtc_state->csc_mode = ilk_read_csc_mode(crtc);
+
+ tmp = intel_de_read(i915, SKL_BOTTOM_COLOR(crtc->pipe));
+
+ if (tmp & SKL_BOTTOM_COLOR_GAMMA_ENABLE)
+ crtc_state->gamma_enable = true;
+
+ if (tmp & SKL_BOTTOM_COLOR_CSC_ENABLE)
+ crtc_state->csc_enable = true;
+}
+
static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -1265,9 +1329,20 @@ static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
lut = blob->data;
+ /*
+ * DSB fails to correctly load the legacy LUT
+ * unless we either write each entry twice,
+ * or use non-posted writes
+ */
+ if (crtc_state->dsb)
+ intel_dsb_nonpost_start(crtc_state->dsb);
+
for (i = 0; i < 256; i++)
ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
i9xx_lut_8(&lut[i]));
+
+ if (crtc_state->dsb)
+ intel_dsb_nonpost_end(crtc_state->dsb);
}
static void ilk_load_lut_10(const struct intel_crtc_state *crtc_state,
@@ -1677,12 +1752,6 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state)
MISSING_CASE(crtc_state->gamma_mode);
break;
}
-
- if (crtc_state->dsb) {
- intel_dsb_finish(crtc_state->dsb);
- intel_dsb_commit(crtc_state->dsb, false);
- intel_dsb_wait(crtc_state->dsb);
- }
}
static void vlv_load_luts(const struct intel_crtc_state *crtc_state)
@@ -1789,6 +1858,9 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ if (crtc_state->dsb)
+ return;
+
i915->display.funcs.color->load_luts(crtc_state);
}
@@ -1805,6 +1877,9 @@ void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
i915->display.funcs.color->color_commit_arm(crtc_state);
+
+ if (crtc_state->dsb)
+ intel_dsb_commit(crtc_state->dsb, true);
}
void intel_color_post_update(const struct intel_crtc_state *crtc_state)
@@ -1818,14 +1893,22 @@ void intel_color_post_update(const struct intel_crtc_state *crtc_state)
void intel_color_prepare_commit(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);
- /* FIXME DSB has issues loading LUTs, disable it for now */
- return;
+ if (!crtc_state->hw.active ||
+ intel_crtc_needs_modeset(crtc_state))
+ return;
if (!crtc_state->pre_csc_lut && !crtc_state->post_csc_lut)
return;
- crtc_state->dsb = intel_dsb_prepare(crtc, 1024);
+ crtc_state->dsb = intel_dsb_prepare(crtc_state, 1024);
+ if (!crtc_state->dsb)
+ return;
+
+ i915->display.funcs.color->load_luts(crtc_state);
+
+ intel_dsb_finish(crtc_state->dsb);
}
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
@@ -1837,6 +1920,17 @@ void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
crtc_state->dsb = NULL;
}
+void intel_color_wait_commit(const struct intel_crtc_state *crtc_state)
+{
+ if (crtc_state->dsb)
+ intel_dsb_wait(crtc_state->dsb);
+}
+
+bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state)
+{
+ return crtc_state->dsb;
+}
+
static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
@@ -1891,6 +1985,9 @@ void intel_color_get_config(struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ if (i915->display.funcs.color->get_config)
+ i915->display.funcs.color->get_config(crtc_state);
+
i915->display.funcs.color->read_luts(crtc_state);
if (i915->display.funcs.color->read_csc)
@@ -2865,16 +2962,16 @@ static int icl_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
return 16;
}
-static bool err_check(struct drm_color_lut *lut1,
- struct drm_color_lut *lut2, u32 err)
+static bool err_check(const struct drm_color_lut *lut1,
+ const struct drm_color_lut *lut2, u32 err)
{
return ((abs((long)lut2->red - lut1->red)) <= err) &&
((abs((long)lut2->blue - lut1->blue)) <= err) &&
((abs((long)lut2->green - lut1->green)) <= err);
}
-static bool intel_lut_entries_equal(struct drm_color_lut *lut1,
- struct drm_color_lut *lut2,
+static bool intel_lut_entries_equal(const struct drm_color_lut *lut1,
+ const struct drm_color_lut *lut2,
int lut_size, u32 err)
{
int i;
@@ -2891,7 +2988,7 @@ static bool intel_lut_equal(const struct drm_property_blob *blob1,
const struct drm_property_blob *blob2,
int check_size, int precision)
{
- struct drm_color_lut *lut1, *lut2;
+ const struct drm_color_lut *lut1, *lut2;
int lut_size1, lut_size2;
u32 err;
@@ -3204,6 +3301,16 @@ static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
return blob;
}
+static void chv_get_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);
+
+ crtc_state->cgm_mode = intel_de_read(i915, CGM_PIPE_MODE(crtc->pipe));
+
+ i9xx_get_config(crtc_state);
+}
+
static void chv_read_luts(struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -3267,6 +3374,15 @@ static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc)
return blob;
}
+static void ilk_get_config(struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+ crtc_state->csc_mode = ilk_read_csc_mode(crtc);
+
+ i9xx_get_config(crtc_state);
+}
+
static void ilk_read_luts(struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -3573,6 +3689,7 @@ static const struct intel_color_funcs chv_color_funcs = {
.read_luts = chv_read_luts,
.lut_equal = chv_lut_equal,
.read_csc = chv_read_csc,
+ .get_config = chv_get_config,
};
static const struct intel_color_funcs vlv_color_funcs = {
@@ -3582,6 +3699,7 @@ static const struct intel_color_funcs vlv_color_funcs = {
.read_luts = i965_read_luts,
.lut_equal = i965_lut_equal,
.read_csc = vlv_read_csc,
+ .get_config = i9xx_get_config,
};
static const struct intel_color_funcs i965_color_funcs = {
@@ -3590,6 +3708,7 @@ static const struct intel_color_funcs i965_color_funcs = {
.load_luts = i965_load_luts,
.read_luts = i965_read_luts,
.lut_equal = i965_lut_equal,
+ .get_config = i9xx_get_config,
};
static const struct intel_color_funcs i9xx_color_funcs = {
@@ -3598,6 +3717,7 @@ static const struct intel_color_funcs i9xx_color_funcs = {
.load_luts = i9xx_load_luts,
.read_luts = i9xx_read_luts,
.lut_equal = i9xx_lut_equal,
+ .get_config = i9xx_get_config,
};
static const struct intel_color_funcs tgl_color_funcs = {
@@ -3608,6 +3728,7 @@ static const struct intel_color_funcs tgl_color_funcs = {
.read_luts = icl_read_luts,
.lut_equal = icl_lut_equal,
.read_csc = icl_read_csc,
+ .get_config = skl_get_config,
};
static const struct intel_color_funcs icl_color_funcs = {
@@ -3619,6 +3740,7 @@ static const struct intel_color_funcs icl_color_funcs = {
.read_luts = icl_read_luts,
.lut_equal = icl_lut_equal,
.read_csc = icl_read_csc,
+ .get_config = skl_get_config,
};
static const struct intel_color_funcs glk_color_funcs = {
@@ -3629,6 +3751,7 @@ static const struct intel_color_funcs glk_color_funcs = {
.read_luts = glk_read_luts,
.lut_equal = glk_lut_equal,
.read_csc = skl_read_csc,
+ .get_config = skl_get_config,
};
static const struct intel_color_funcs skl_color_funcs = {
@@ -3639,6 +3762,7 @@ static const struct intel_color_funcs skl_color_funcs = {
.read_luts = bdw_read_luts,
.lut_equal = ivb_lut_equal,
.read_csc = skl_read_csc,
+ .get_config = skl_get_config,
};
static const struct intel_color_funcs bdw_color_funcs = {
@@ -3649,6 +3773,7 @@ static const struct intel_color_funcs bdw_color_funcs = {
.read_luts = bdw_read_luts,
.lut_equal = ivb_lut_equal,
.read_csc = ilk_read_csc,
+ .get_config = hsw_get_config,
};
static const struct intel_color_funcs hsw_color_funcs = {
@@ -3659,6 +3784,7 @@ static const struct intel_color_funcs hsw_color_funcs = {
.read_luts = ivb_read_luts,
.lut_equal = ivb_lut_equal,
.read_csc = ilk_read_csc,
+ .get_config = hsw_get_config,
};
static const struct intel_color_funcs ivb_color_funcs = {
@@ -3669,6 +3795,7 @@ static const struct intel_color_funcs ivb_color_funcs = {
.read_luts = ivb_read_luts,
.lut_equal = ivb_lut_equal,
.read_csc = ilk_read_csc,
+ .get_config = ilk_get_config,
};
static const struct intel_color_funcs ilk_color_funcs = {
@@ -3679,6 +3806,7 @@ static const struct intel_color_funcs ilk_color_funcs = {
.read_luts = ilk_read_luts,
.lut_equal = ilk_lut_equal,
.read_csc = ilk_read_csc,
+ .get_config = ilk_get_config,
};
void intel_color_crtc_init(struct intel_crtc *crtc)
diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h
index 8002492be7..8ecd36149d 100644
--- a/drivers/gpu/drm/i915/display/intel_color.h
+++ b/drivers/gpu/drm/i915/display/intel_color.h
@@ -19,6 +19,8 @@ void intel_color_crtc_init(struct intel_crtc *crtc);
int intel_color_check(struct intel_crtc_state *crtc_state);
void intel_color_prepare_commit(struct intel_crtc_state *crtc_state);
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state);
+bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state);
+void intel_color_wait_commit(const struct intel_crtc_state *crtc_state);
void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);
void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
void intel_color_post_update(const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_color_regs.h b/drivers/gpu/drm/i915/display/intel_color_regs.h
new file mode 100644
index 0000000000..9f4ae58f3e
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_color_regs.h
@@ -0,0 +1,286 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_COLOR_REGS_H__
+#define __INTEL_COLOR_REGS_H__
+
+#include "intel_display_reg_defs.h"
+
+/* legacy palette */
+#define _LGC_PALETTE_A 0x4a000
+#define _LGC_PALETTE_B 0x4a800
+/* see PALETTE_* for the bits */
+#define LGC_PALETTE(pipe, i) _MMIO(_PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) + (i) * 4)
+
+/* ilk/snb precision palette */
+#define _PREC_PALETTE_A 0x4b000
+#define _PREC_PALETTE_B 0x4c000
+/* 10bit mode */
+#define PREC_PALETTE_10_RED_MASK REG_GENMASK(29, 20)
+#define PREC_PALETTE_10_GREEN_MASK REG_GENMASK(19, 10)
+#define PREC_PALETTE_10_BLUE_MASK REG_GENMASK(9, 0)
+/* 12.4 interpolated mode ldw */
+#define PREC_PALETTE_12P4_RED_LDW_MASK REG_GENMASK(29, 24)
+#define PREC_PALETTE_12P4_GREEN_LDW_MASK REG_GENMASK(19, 14)
+#define PREC_PALETTE_12P4_BLUE_LDW_MASK REG_GENMASK(9, 4)
+/* 12.4 interpolated mode udw */
+#define PREC_PALETTE_12P4_RED_UDW_MASK REG_GENMASK(29, 20)
+#define PREC_PALETTE_12P4_GREEN_UDW_MASK REG_GENMASK(19, 10)
+#define PREC_PALETTE_12P4_BLUE_UDW_MASK REG_GENMASK(9, 0)
+#define PREC_PALETTE(pipe, i) _MMIO(_PIPE(pipe, _PREC_PALETTE_A, _PREC_PALETTE_B) + (i) * 4)
+
+#define _PREC_PIPEAGCMAX 0x4d000
+#define _PREC_PIPEBGCMAX 0x4d010
+#define PREC_PIPEGCMAX(pipe, i) _MMIO(_PIPE(pipe, _PIPEAGCMAX, _PIPEBGCMAX) + (i) * 4) /* u1.16 */
+
+#define _GAMMA_MODE_A 0x4a480
+#define _GAMMA_MODE_B 0x4ac80
+#define GAMMA_MODE(pipe) _MMIO_PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
+#define PRE_CSC_GAMMA_ENABLE REG_BIT(31) /* icl+ */
+#define POST_CSC_GAMMA_ENABLE REG_BIT(30) /* icl+ */
+#define PALETTE_ANTICOL_DISABLE REG_BIT(15) /* skl+ */
+#define GAMMA_MODE_MODE_MASK REG_GENMASK(1, 0)
+#define GAMMA_MODE_MODE_8BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 0)
+#define GAMMA_MODE_MODE_10BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 1)
+#define GAMMA_MODE_MODE_12BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 2)
+#define GAMMA_MODE_MODE_SPLIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 3) /* ivb-bdw */
+#define GAMMA_MODE_MODE_12BIT_MULTI_SEG REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 3) /* icl-tgl */
+
+/* pipe CSC */
+#define _PIPE_A_CSC_COEFF_RY_GY 0x49010
+#define _PIPE_A_CSC_COEFF_BY 0x49014
+#define _PIPE_A_CSC_COEFF_RU_GU 0x49018
+#define _PIPE_A_CSC_COEFF_BU 0x4901c
+#define _PIPE_A_CSC_COEFF_RV_GV 0x49020
+#define _PIPE_A_CSC_COEFF_BV 0x49024
+
+#define _PIPE_A_CSC_MODE 0x49028
+#define ICL_CSC_ENABLE (1 << 31) /* icl+ */
+#define ICL_OUTPUT_CSC_ENABLE (1 << 30) /* icl+ */
+#define CSC_BLACK_SCREEN_OFFSET (1 << 2) /* ilk/snb */
+#define CSC_POSITION_BEFORE_GAMMA (1 << 1) /* pre-glk */
+#define CSC_MODE_YUV_TO_RGB (1 << 0) /* ilk/snb */
+
+#define _PIPE_A_CSC_PREOFF_HI 0x49030
+#define _PIPE_A_CSC_PREOFF_ME 0x49034
+#define _PIPE_A_CSC_PREOFF_LO 0x49038
+#define _PIPE_A_CSC_POSTOFF_HI 0x49040
+#define _PIPE_A_CSC_POSTOFF_ME 0x49044
+#define _PIPE_A_CSC_POSTOFF_LO 0x49048
+
+#define _PIPE_B_CSC_COEFF_RY_GY 0x49110
+#define _PIPE_B_CSC_COEFF_BY 0x49114
+#define _PIPE_B_CSC_COEFF_RU_GU 0x49118
+#define _PIPE_B_CSC_COEFF_BU 0x4911c
+#define _PIPE_B_CSC_COEFF_RV_GV 0x49120
+#define _PIPE_B_CSC_COEFF_BV 0x49124
+#define _PIPE_B_CSC_MODE 0x49128
+#define _PIPE_B_CSC_PREOFF_HI 0x49130
+#define _PIPE_B_CSC_PREOFF_ME 0x49134
+#define _PIPE_B_CSC_PREOFF_LO 0x49138
+#define _PIPE_B_CSC_POSTOFF_HI 0x49140
+#define _PIPE_B_CSC_POSTOFF_ME 0x49144
+#define _PIPE_B_CSC_POSTOFF_LO 0x49148
+
+#define PIPE_CSC_COEFF_RY_GY(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, _PIPE_B_CSC_COEFF_RY_GY)
+#define PIPE_CSC_COEFF_BY(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BY, _PIPE_B_CSC_COEFF_BY)
+#define PIPE_CSC_COEFF_RU_GU(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, _PIPE_B_CSC_COEFF_RU_GU)
+#define PIPE_CSC_COEFF_BU(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BU, _PIPE_B_CSC_COEFF_BU)
+#define PIPE_CSC_COEFF_RV_GV(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_RV_GV, _PIPE_B_CSC_COEFF_RV_GV)
+#define PIPE_CSC_COEFF_BV(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_COEFF_BV, _PIPE_B_CSC_COEFF_BV)
+#define PIPE_CSC_MODE(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_MODE, _PIPE_B_CSC_MODE)
+#define PIPE_CSC_PREOFF_HI(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_HI, _PIPE_B_CSC_PREOFF_HI)
+#define PIPE_CSC_PREOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_ME, _PIPE_B_CSC_PREOFF_ME)
+#define PIPE_CSC_PREOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_PREOFF_LO, _PIPE_B_CSC_PREOFF_LO)
+#define PIPE_CSC_POSTOFF_HI(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_HI, _PIPE_B_CSC_POSTOFF_HI)
+#define PIPE_CSC_POSTOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
+#define PIPE_CSC_POSTOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
+
+/* Pipe Output CSC */
+#define _PIPE_A_OUTPUT_CSC_COEFF_RY_GY 0x49050
+#define _PIPE_A_OUTPUT_CSC_COEFF_BY 0x49054
+#define _PIPE_A_OUTPUT_CSC_COEFF_RU_GU 0x49058
+#define _PIPE_A_OUTPUT_CSC_COEFF_BU 0x4905c
+#define _PIPE_A_OUTPUT_CSC_COEFF_RV_GV 0x49060
+#define _PIPE_A_OUTPUT_CSC_COEFF_BV 0x49064
+#define _PIPE_A_OUTPUT_CSC_PREOFF_HI 0x49068
+#define _PIPE_A_OUTPUT_CSC_PREOFF_ME 0x4906c
+#define _PIPE_A_OUTPUT_CSC_PREOFF_LO 0x49070
+#define _PIPE_A_OUTPUT_CSC_POSTOFF_HI 0x49074
+#define _PIPE_A_OUTPUT_CSC_POSTOFF_ME 0x49078
+#define _PIPE_A_OUTPUT_CSC_POSTOFF_LO 0x4907c
+
+#define _PIPE_B_OUTPUT_CSC_COEFF_RY_GY 0x49150
+#define _PIPE_B_OUTPUT_CSC_COEFF_BY 0x49154
+#define _PIPE_B_OUTPUT_CSC_COEFF_RU_GU 0x49158
+#define _PIPE_B_OUTPUT_CSC_COEFF_BU 0x4915c
+#define _PIPE_B_OUTPUT_CSC_COEFF_RV_GV 0x49160
+#define _PIPE_B_OUTPUT_CSC_COEFF_BV 0x49164
+#define _PIPE_B_OUTPUT_CSC_PREOFF_HI 0x49168
+#define _PIPE_B_OUTPUT_CSC_PREOFF_ME 0x4916c
+#define _PIPE_B_OUTPUT_CSC_PREOFF_LO 0x49170
+#define _PIPE_B_OUTPUT_CSC_POSTOFF_HI 0x49174
+#define _PIPE_B_OUTPUT_CSC_POSTOFF_ME 0x49178
+#define _PIPE_B_OUTPUT_CSC_POSTOFF_LO 0x4917c
+
+#define PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe) _MMIO_PIPE(pipe,\
+ _PIPE_A_OUTPUT_CSC_COEFF_RY_GY,\
+ _PIPE_B_OUTPUT_CSC_COEFF_RY_GY)
+#define PIPE_CSC_OUTPUT_COEFF_BY(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_COEFF_BY, \
+ _PIPE_B_OUTPUT_CSC_COEFF_BY)
+#define PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_COEFF_RU_GU, \
+ _PIPE_B_OUTPUT_CSC_COEFF_RU_GU)
+#define PIPE_CSC_OUTPUT_COEFF_BU(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_COEFF_BU, \
+ _PIPE_B_OUTPUT_CSC_COEFF_BU)
+#define PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_COEFF_RV_GV, \
+ _PIPE_B_OUTPUT_CSC_COEFF_RV_GV)
+#define PIPE_CSC_OUTPUT_COEFF_BV(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_COEFF_BV, \
+ _PIPE_B_OUTPUT_CSC_COEFF_BV)
+#define PIPE_CSC_OUTPUT_PREOFF_HI(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_PREOFF_HI, \
+ _PIPE_B_OUTPUT_CSC_PREOFF_HI)
+#define PIPE_CSC_OUTPUT_PREOFF_ME(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_PREOFF_ME, \
+ _PIPE_B_OUTPUT_CSC_PREOFF_ME)
+#define PIPE_CSC_OUTPUT_PREOFF_LO(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_PREOFF_LO, \
+ _PIPE_B_OUTPUT_CSC_PREOFF_LO)
+#define PIPE_CSC_OUTPUT_POSTOFF_HI(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_POSTOFF_HI, \
+ _PIPE_B_OUTPUT_CSC_POSTOFF_HI)
+#define PIPE_CSC_OUTPUT_POSTOFF_ME(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_POSTOFF_ME, \
+ _PIPE_B_OUTPUT_CSC_POSTOFF_ME)
+#define PIPE_CSC_OUTPUT_POSTOFF_LO(pipe) _MMIO_PIPE(pipe, \
+ _PIPE_A_OUTPUT_CSC_POSTOFF_LO, \
+ _PIPE_B_OUTPUT_CSC_POSTOFF_LO)
+
+/* pipe degamma/gamma LUTs on IVB+ */
+#define _PAL_PREC_INDEX_A 0x4A400
+#define _PAL_PREC_INDEX_B 0x4AC00
+#define _PAL_PREC_INDEX_C 0x4B400
+#define PAL_PREC_SPLIT_MODE REG_BIT(31)
+#define PAL_PREC_AUTO_INCREMENT REG_BIT(15)
+#define PAL_PREC_INDEX_VALUE_MASK REG_GENMASK(9, 0)
+#define PAL_PREC_INDEX_VALUE(x) REG_FIELD_PREP(PAL_PREC_INDEX_VALUE_MASK, (x))
+#define _PAL_PREC_DATA_A 0x4A404
+#define _PAL_PREC_DATA_B 0x4AC04
+#define _PAL_PREC_DATA_C 0x4B404
+/* see PREC_PALETTE_* for the bits */
+#define _PAL_PREC_GC_MAX_A 0x4A410
+#define _PAL_PREC_GC_MAX_B 0x4AC10
+#define _PAL_PREC_GC_MAX_C 0x4B410
+#define _PAL_PREC_EXT_GC_MAX_A 0x4A420
+#define _PAL_PREC_EXT_GC_MAX_B 0x4AC20
+#define _PAL_PREC_EXT_GC_MAX_C 0x4B420
+#define _PAL_PREC_EXT2_GC_MAX_A 0x4A430
+#define _PAL_PREC_EXT2_GC_MAX_B 0x4AC30
+#define _PAL_PREC_EXT2_GC_MAX_C 0x4B430
+
+#define PREC_PAL_INDEX(pipe) _MMIO_PIPE(pipe, _PAL_PREC_INDEX_A, _PAL_PREC_INDEX_B)
+#define PREC_PAL_DATA(pipe) _MMIO_PIPE(pipe, _PAL_PREC_DATA_A, _PAL_PREC_DATA_B)
+#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4) /* u1.16 */
+#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4) /* u3.16 */
+#define PREC_PAL_EXT2_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT2_GC_MAX_A, _PAL_PREC_EXT2_GC_MAX_B) + (i) * 4) /* glk+, u3.16 */
+
+#define _PRE_CSC_GAMC_INDEX_A 0x4A484
+#define _PRE_CSC_GAMC_INDEX_B 0x4AC84
+#define _PRE_CSC_GAMC_INDEX_C 0x4B484
+#define PRE_CSC_GAMC_AUTO_INCREMENT REG_BIT(10)
+#define PRE_CSC_GAMC_INDEX_VALUE_MASK REG_GENMASK(7, 0)
+#define PRE_CSC_GAMC_INDEX_VALUE(x) REG_FIELD_PREP(PRE_CSC_GAMC_INDEX_VALUE_MASK, (x))
+#define _PRE_CSC_GAMC_DATA_A 0x4A488
+#define _PRE_CSC_GAMC_DATA_B 0x4AC88
+#define _PRE_CSC_GAMC_DATA_C 0x4B488
+
+#define PRE_CSC_GAMC_INDEX(pipe) _MMIO_PIPE(pipe, _PRE_CSC_GAMC_INDEX_A, _PRE_CSC_GAMC_INDEX_B)
+#define PRE_CSC_GAMC_DATA(pipe) _MMIO_PIPE(pipe, _PRE_CSC_GAMC_DATA_A, _PRE_CSC_GAMC_DATA_B)
+
+/* ICL Multi segmented gamma */
+#define _PAL_PREC_MULTI_SEG_INDEX_A 0x4A408
+#define _PAL_PREC_MULTI_SEG_INDEX_B 0x4AC08
+#define PAL_PREC_MULTI_SEG_AUTO_INCREMENT REG_BIT(15)
+#define PAL_PREC_MULTI_SEG_INDEX_VALUE_MASK REG_GENMASK(4, 0)
+#define PAL_PREC_MULTI_SEG_INDEX_VALUE(x) REG_FIELD_PREP(PAL_PREC_MULTI_SEG_INDEX_VALUE_MASK, (x))
+
+#define _PAL_PREC_MULTI_SEG_DATA_A 0x4A40C
+#define _PAL_PREC_MULTI_SEG_DATA_B 0x4AC0C
+/* see PREC_PALETTE_12P4_* for the bits */
+
+#define PREC_PAL_MULTI_SEG_INDEX(pipe) _MMIO_PIPE(pipe, \
+ _PAL_PREC_MULTI_SEG_INDEX_A, \
+ _PAL_PREC_MULTI_SEG_INDEX_B)
+#define PREC_PAL_MULTI_SEG_DATA(pipe) _MMIO_PIPE(pipe, \
+ _PAL_PREC_MULTI_SEG_DATA_A, \
+ _PAL_PREC_MULTI_SEG_DATA_B)
+
+#define _PIPE_A_WGC_C01_C00 0x600B0 /* s2.10 */
+#define _PIPE_A_WGC_C02 0x600B4 /* s2.10 */
+#define _PIPE_A_WGC_C11_C10 0x600B8 /* s2.10 */
+#define _PIPE_A_WGC_C12 0x600BC /* s2.10 */
+#define _PIPE_A_WGC_C21_C20 0x600C0 /* s2.10 */
+#define _PIPE_A_WGC_C22 0x600C4 /* s2.10 */
+
+#define PIPE_WGC_C01_C00(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C01_C00)
+#define PIPE_WGC_C02(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C02)
+#define PIPE_WGC_C11_C10(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C11_C10)
+#define PIPE_WGC_C12(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C12)
+#define PIPE_WGC_C21_C20(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C21_C20)
+#define PIPE_WGC_C22(pipe) _MMIO_TRANS2(pipe, _PIPE_A_WGC_C22)
+
+/* pipe CSC & degamma/gamma LUTs on CHV */
+#define _CGM_PIPE_A_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x67900)
+#define _CGM_PIPE_A_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x67904)
+#define _CGM_PIPE_A_CSC_COEFF45 (VLV_DISPLAY_BASE + 0x67908)
+#define _CGM_PIPE_A_CSC_COEFF67 (VLV_DISPLAY_BASE + 0x6790C)
+#define _CGM_PIPE_A_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x67910)
+#define _CGM_PIPE_A_DEGAMMA (VLV_DISPLAY_BASE + 0x66000)
+/* cgm degamma ldw */
+#define CGM_PIPE_DEGAMMA_GREEN_LDW_MASK REG_GENMASK(29, 16)
+#define CGM_PIPE_DEGAMMA_BLUE_LDW_MASK REG_GENMASK(13, 0)
+/* cgm degamma udw */
+#define CGM_PIPE_DEGAMMA_RED_UDW_MASK REG_GENMASK(13, 0)
+#define _CGM_PIPE_A_GAMMA (VLV_DISPLAY_BASE + 0x67000)
+/* cgm gamma ldw */
+#define CGM_PIPE_GAMMA_GREEN_LDW_MASK REG_GENMASK(25, 16)
+#define CGM_PIPE_GAMMA_BLUE_LDW_MASK REG_GENMASK(9, 0)
+/* cgm gamma udw */
+#define CGM_PIPE_GAMMA_RED_UDW_MASK REG_GENMASK(9, 0)
+#define _CGM_PIPE_A_MODE (VLV_DISPLAY_BASE + 0x67A00)
+#define CGM_PIPE_MODE_GAMMA (1 << 2)
+#define CGM_PIPE_MODE_CSC (1 << 1)
+#define CGM_PIPE_MODE_DEGAMMA (1 << 0)
+
+#define _CGM_PIPE_B_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x69900)
+#define _CGM_PIPE_B_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x69904)
+#define _CGM_PIPE_B_CSC_COEFF45 (VLV_DISPLAY_BASE + 0x69908)
+#define _CGM_PIPE_B_CSC_COEFF67 (VLV_DISPLAY_BASE + 0x6990C)
+#define _CGM_PIPE_B_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x69910)
+#define _CGM_PIPE_B_DEGAMMA (VLV_DISPLAY_BASE + 0x68000)
+#define _CGM_PIPE_B_GAMMA (VLV_DISPLAY_BASE + 0x69000)
+#define _CGM_PIPE_B_MODE (VLV_DISPLAY_BASE + 0x69A00)
+
+#define CGM_PIPE_CSC_COEFF01(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF01, _CGM_PIPE_B_CSC_COEFF01)
+#define CGM_PIPE_CSC_COEFF23(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF23, _CGM_PIPE_B_CSC_COEFF23)
+#define CGM_PIPE_CSC_COEFF45(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF45, _CGM_PIPE_B_CSC_COEFF45)
+#define CGM_PIPE_CSC_COEFF67(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF67, _CGM_PIPE_B_CSC_COEFF67)
+#define CGM_PIPE_CSC_COEFF8(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF8, _CGM_PIPE_B_CSC_COEFF8)
+#define CGM_PIPE_DEGAMMA(pipe, i, w) _MMIO(_PIPE(pipe, _CGM_PIPE_A_DEGAMMA, _CGM_PIPE_B_DEGAMMA) + (i) * 8 + (w) * 4)
+#define CGM_PIPE_GAMMA(pipe, i, w) _MMIO(_PIPE(pipe, _CGM_PIPE_A_GAMMA, _CGM_PIPE_B_GAMMA) + (i) * 8 + (w) * 4)
+#define CGM_PIPE_MODE(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_MODE, _CGM_PIPE_B_MODE)
+
+/* Skylake+ pipe bottom (background) color */
+#define _SKL_BOTTOM_COLOR_A 0x70034
+#define _SKL_BOTTOM_COLOR_B 0x71034
+#define SKL_BOTTOM_COLOR_GAMMA_ENABLE REG_BIT(31)
+#define SKL_BOTTOM_COLOR_CSC_ENABLE REG_BIT(30)
+#define SKL_BOTTOM_COLOR(pipe) _MMIO_PIPE(pipe, _SKL_BOTTOM_COLOR_A, _SKL_BOTTOM_COLOR_B)
+
+#endif /* __INTEL_COLOR_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c
index e2a220cf2e..143d669516 100644
--- a/drivers/gpu/drm/i915/display/intel_combo_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c
@@ -114,10 +114,6 @@ static bool icl_verify_procmon_ref_values(struct drm_i915_private *dev_priv,
procmon = icl_get_procmon_ref_values(dev_priv, phy);
- drm_dbg_kms(&dev_priv->drm,
- "Combo PHY %c Voltage/Process Info : %s\n",
- phy_name(phy), procmon->name);
-
ret = check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW1(phy),
(0xff << 16) | 0xff, procmon->dw1);
ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW9(phy),
@@ -312,14 +308,17 @@ static void icl_combo_phys_init(struct drm_i915_private *dev_priv)
enum phy phy;
for_each_combo_phy(dev_priv, phy) {
+ const struct icl_procmon *procmon;
u32 val;
- if (icl_combo_phy_verify_state(dev_priv, phy)) {
- drm_dbg(&dev_priv->drm,
- "Combo PHY %c already enabled, won't reprogram it.\n",
- phy_name(phy));
+ if (icl_combo_phy_verify_state(dev_priv, phy))
continue;
- }
+
+ procmon = icl_get_procmon_ref_values(dev_priv, phy);
+
+ drm_dbg(&dev_priv->drm,
+ "Initializing combo PHY %c (Voltage/Process Info : %s)\n",
+ phy_name(phy), procmon->name);
if (!has_phy_misc(dev_priv, phy))
goto skip_phy_misc;
diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c
index ff3bcadebe..c65887870d 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -192,17 +192,17 @@ int intel_connector_update_modes(struct drm_connector *connector,
/**
* intel_ddc_get_modes - get modelist from monitor
* @connector: DRM connector device to use
- * @adapter: i2c adapter
+ * @ddc: DDC bus i2c adapter
*
* Fetch the EDID information from @connector using the DDC bus.
*/
int intel_ddc_get_modes(struct drm_connector *connector,
- struct i2c_adapter *adapter)
+ struct i2c_adapter *ddc)
{
const struct drm_edid *drm_edid;
int ret;
- drm_edid = drm_edid_read_ddc(connector, adapter);
+ drm_edid = drm_edid_read_ddc(connector, ddc);
if (!drm_edid)
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_connector.h b/drivers/gpu/drm/i915/display/intel_connector.h
index aaf7281462..bafde3f11f 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.h
+++ b/drivers/gpu/drm/i915/display/intel_connector.h
@@ -26,7 +26,7 @@ bool intel_connector_get_hw_state(struct intel_connector *connector);
enum pipe intel_connector_get_pipe(struct intel_connector *connector);
int intel_connector_update_modes(struct drm_connector *connector,
const struct drm_edid *drm_edid);
-int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
+int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *ddc);
void intel_attach_force_audio_property(struct drm_connector *connector);
void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
void intel_attach_aspect_ratio_property(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
index 4352f90177..6f6b348b8a 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -418,6 +418,9 @@ static int pch_crt_compute_config(struct intel_encoder *encoder,
return -EINVAL;
pipe_config->has_pch_encoder = true;
+ if (!intel_fdi_compute_pipe_bpp(pipe_config))
+ return -EINVAL;
+
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
return 0;
@@ -440,10 +443,14 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
return -EINVAL;
pipe_config->has_pch_encoder = true;
+ if (!intel_fdi_compute_pipe_bpp(pipe_config))
+ return -EINVAL;
+
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
/* LPT FDI RX only supports 8bpc. */
if (HAS_PCH_LPT(dev_priv)) {
+ /* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */
if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
drm_dbg_kms(&dev_priv->drm,
"LPT only supports 24bpp\n");
@@ -617,18 +624,18 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
}
static const struct drm_edid *intel_crt_get_edid(struct drm_connector *connector,
- struct i2c_adapter *i2c)
+ struct i2c_adapter *ddc)
{
const struct drm_edid *drm_edid;
- drm_edid = drm_edid_read_ddc(connector, i2c);
+ drm_edid = drm_edid_read_ddc(connector, ddc);
- if (!drm_edid && !intel_gmbus_is_forced_bit(i2c)) {
+ if (!drm_edid && !intel_gmbus_is_forced_bit(ddc)) {
drm_dbg_kms(connector->dev,
"CRT GMBUS EDID read failed, retry using GPIO bit-banging\n");
- intel_gmbus_force_bit(i2c, true);
- drm_edid = drm_edid_read_ddc(connector, i2c);
- intel_gmbus_force_bit(i2c, false);
+ intel_gmbus_force_bit(ddc, true);
+ drm_edid = drm_edid_read_ddc(connector, ddc);
+ intel_gmbus_force_bit(ddc, false);
}
return drm_edid;
@@ -636,12 +643,12 @@ static const struct drm_edid *intel_crt_get_edid(struct drm_connector *connector
/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */
static int intel_crt_ddc_get_modes(struct drm_connector *connector,
- struct i2c_adapter *adapter)
+ struct i2c_adapter *ddc)
{
const struct drm_edid *drm_edid;
int ret;
- drm_edid = intel_crt_get_edid(connector, adapter);
+ drm_edid = intel_crt_get_edid(connector, ddc);
if (!drm_edid)
return 0;
@@ -657,28 +664,23 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(crt->base.base.dev);
const struct drm_edid *drm_edid;
- struct i2c_adapter *i2c;
bool ret = false;
- i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->display.vbt.crt_ddc_pin);
- drm_edid = intel_crt_get_edid(connector, i2c);
+ drm_edid = intel_crt_get_edid(connector, connector->ddc);
if (drm_edid) {
- const struct edid *edid = drm_edid_raw(drm_edid);
- bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
-
/*
* This may be a DVI-I connector with a shared DDC
* link between analog and digital outputs, so we
* have to check the EDID input spec of the attached device.
*/
- if (!is_digital) {
+ if (drm_edid_is_digital(drm_edid)) {
drm_dbg_kms(&dev_priv->drm,
- "CRT detected via DDC:0x50 [EDID]\n");
- ret = true;
+ "CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
} else {
drm_dbg_kms(&dev_priv->drm,
- "CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
+ "CRT detected via DDC:0x50 [EDID]\n");
+ ret = true;
}
} else {
drm_dbg_kms(&dev_priv->drm,
@@ -841,7 +843,7 @@ intel_crt_detect(struct drm_connector *connector,
connector->base.id, connector->name,
force);
- if (!INTEL_DISPLAY_ENABLED(dev_priv))
+ if (!intel_display_device_enabled(dev_priv))
return connector_status_disconnected;
if (dev_priv->params.load_detect_test) {
@@ -914,12 +916,6 @@ load_detect:
out:
intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
- /*
- * Make sure the refs for power wells enabled during detect are
- * dropped to avoid a new detect cycle triggered by HPD polling.
- */
- intel_display_power_flush_work(dev_priv);
-
return status;
}
@@ -930,20 +926,19 @@ static int intel_crt_get_modes(struct drm_connector *connector)
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct intel_encoder *intel_encoder = &crt->base;
intel_wakeref_t wakeref;
- struct i2c_adapter *i2c;
+ struct i2c_adapter *ddc;
int ret;
wakeref = intel_display_power_get(dev_priv,
intel_encoder->power_domain);
- i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->display.vbt.crt_ddc_pin);
- ret = intel_crt_ddc_get_modes(connector, i2c);
+ ret = intel_crt_ddc_get_modes(connector, connector->ddc);
if (ret || !IS_G4X(dev_priv))
goto out;
/* Try to probe digital port for output in DVI-I -> VGA mode. */
- i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPB);
- ret = intel_crt_ddc_get_modes(connector, i2c);
+ ddc = intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPB);
+ ret = intel_crt_ddc_get_modes(connector, ddc);
out:
intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
@@ -1001,6 +996,7 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
struct intel_crt *crt;
struct intel_connector *intel_connector;
i915_reg_t adpa_reg;
+ u8 ddc_pin;
u32 adpa;
if (HAS_PCH_SPLIT(dev_priv))
@@ -1037,10 +1033,14 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
return;
}
+ ddc_pin = dev_priv->display.vbt.crt_ddc_pin;
+
connector = &intel_connector->base;
crt->connector = intel_connector;
- drm_connector_init(&dev_priv->drm, &intel_connector->base,
- &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
+ drm_connector_init_with_ddc(&dev_priv->drm, connector,
+ &intel_crt_connector_funcs,
+ DRM_MODE_CONNECTOR_VGA,
+ intel_gmbus_get_adapter(dev_priv, ddc_pin));
drm_encoder_init(&dev_priv->drm, &crt->base.base, &intel_crt_enc_funcs,
DRM_MODE_ENCODER_DAC, "CRT");
diff --git a/drivers/gpu/drm/i915/display/intel_crt.h b/drivers/gpu/drm/i915/display/intel_crt.h
index c6071efd93..fe7690c2b9 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.h
+++ b/drivers/gpu/drm/i915/display/intel_crt.h
@@ -12,9 +12,23 @@ enum pipe;
struct drm_encoder;
struct drm_i915_private;
+#ifdef I915
bool intel_crt_port_enabled(struct drm_i915_private *dev_priv,
i915_reg_t adpa_reg, enum pipe *pipe);
void intel_crt_init(struct drm_i915_private *dev_priv);
void intel_crt_reset(struct drm_encoder *encoder);
+#else
+static inline bool intel_crt_port_enabled(struct drm_i915_private *dev_priv,
+ i915_reg_t adpa_reg, enum pipe *pipe)
+{
+ return false;
+}
+static inline void intel_crt_init(struct drm_i915_private *dev_priv)
+{
+}
+static inline void intel_crt_reset(struct drm_encoder *encoder)
+{
+}
+#endif
#endif /* __INTEL_CRT_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 182c6dd64f..1fd068e6e2 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -24,6 +24,7 @@
#include "intel_display_trace.h"
#include "intel_display_types.h"
#include "intel_drrs.h"
+#include "intel_dsb.h"
#include "intel_dsi.h"
#include "intel_fifo_underrun.h"
#include "intel_pipe_crc.h"
@@ -175,6 +176,7 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
crtc_state->hsw_workaround_pipe = INVALID_PIPE;
crtc_state->scaler_state.scaler_id = -1;
crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
+ crtc_state->max_link_bpp_x16 = INT_MAX;
}
static struct intel_crtc *intel_crtc_alloc(void)
@@ -394,7 +396,8 @@ static bool intel_crtc_needs_vblank_work(const struct intel_crtc_state *crtc_sta
return crtc_state->hw.active &&
!intel_crtc_needs_modeset(crtc_state) &&
!crtc_state->preload_luts &&
- intel_crtc_needs_color_update(crtc_state);
+ intel_crtc_needs_color_update(crtc_state) &&
+ !intel_color_uses_dsb(crtc_state);
}
static void intel_crtc_vblank_work(struct kthread_work *base)
@@ -468,9 +471,64 @@ static int intel_mode_vblank_start(const struct drm_display_mode *mode)
return vblank_start;
}
+static void intel_crtc_vblank_evade_scanlines(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ int *min, int *max, int *vblank_start)
+{
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
+ const struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_crtc_state *crtc_state;
+ const struct drm_display_mode *adjusted_mode;
+
+ /*
+ * During fastsets/etc. the transcoder is still
+ * running with the old timings at this point.
+ *
+ * TODO: maybe just use the active timings here?
+ */
+ if (intel_crtc_needs_modeset(new_crtc_state))
+ crtc_state = new_crtc_state;
+ else
+ crtc_state = old_crtc_state;
+
+ adjusted_mode = &crtc_state->hw.adjusted_mode;
+
+ if (crtc->mode_flags & I915_MODE_FLAG_VRR) {
+ /* timing changes should happen with VRR disabled */
+ drm_WARN_ON(state->base.dev, intel_crtc_needs_modeset(new_crtc_state) ||
+ new_crtc_state->update_m_n || new_crtc_state->update_lrr);
+
+ if (intel_vrr_is_push_sent(crtc_state))
+ *vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
+ else
+ *vblank_start = intel_vrr_vmax_vblank_start(crtc_state);
+ } else {
+ *vblank_start = intel_mode_vblank_start(adjusted_mode);
+ }
+
+ /* FIXME needs to be calibrated sensibly */
+ *min = *vblank_start - intel_usecs_to_scanlines(adjusted_mode,
+ VBLANK_EVASION_TIME_US);
+ *max = *vblank_start - 1;
+
+ /*
+ * M/N and TRANS_VTOTAL are double buffered on the transcoder's
+ * undelayed vblank, so with seamless M/N and LRR we must evade
+ * both vblanks.
+ *
+ * DSB execution waits for the transcoder's undelayed vblank,
+ * hence we must kick off the commit before that.
+ */
+ if (new_crtc_state->dsb || new_crtc_state->update_m_n || new_crtc_state->update_lrr)
+ *min -= adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay;
+}
+
/**
* intel_pipe_update_start() - start update of a set of display registers
- * @new_crtc_state: the new crtc state
+ * @state: the atomic state
+ * @crtc: the crtc
*
* Mark the start of an update to pipe registers that should be updated
* atomically regarding vblank. If the next vblank will happens within
@@ -480,11 +538,12 @@ static int intel_mode_vblank_start(const struct drm_display_mode *mode)
* until a subsequent call to intel_pipe_update_end(). That is done to
* avoid random delays.
*/
-void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
+void intel_pipe_update_start(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- const struct drm_display_mode *adjusted_mode = &new_crtc_state->hw.adjusted_mode;
+ struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
long timeout = msecs_to_jiffies_timeout(1);
int scanline, min, max, vblank_start;
wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
@@ -500,27 +559,7 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
if (intel_crtc_needs_vblank_work(new_crtc_state))
intel_crtc_vblank_work_init(new_crtc_state);
- if (new_crtc_state->vrr.enable) {
- if (intel_vrr_is_push_sent(new_crtc_state))
- vblank_start = intel_vrr_vmin_vblank_start(new_crtc_state);
- else
- vblank_start = intel_vrr_vmax_vblank_start(new_crtc_state);
- } else {
- vblank_start = intel_mode_vblank_start(adjusted_mode);
- }
-
- /* FIXME needs to be calibrated sensibly */
- min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
- VBLANK_EVASION_TIME_US);
- max = vblank_start - 1;
-
- /*
- * M/N is double buffered on the transcoder's undelayed vblank,
- * so with seamless M/N we must evade both vblanks.
- */
- if (new_crtc_state->seamless_m_n && intel_crtc_needs_fastset(new_crtc_state))
- min -= adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay;
-
+ intel_crtc_vblank_evade_scanlines(state, crtc, &min, &max, &vblank_start);
if (min <= 0 || max <= 0)
goto irq_disable;
@@ -631,25 +670,26 @@ static void dbg_vblank_evade(struct intel_crtc *crtc, ktime_t end) {}
/**
* intel_pipe_update_end() - end update of a set of display registers
- * @new_crtc_state: the new crtc state
+ * @state: the atomic state
+ * @crtc: the crtc
*
* Mark the end of an update started with intel_pipe_update_start(). This
* re-enables interrupts and verifies the update was actually completed
* before a vblank.
*/
-void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
+void intel_pipe_update_end(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
+ struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
enum pipe pipe = crtc->pipe;
int scanline_end = intel_get_crtc_scanline(crtc);
u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
ktime_t end_vbl_time = ktime_get();
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- intel_psr_unlock(new_crtc_state);
-
if (new_crtc_state->do_async_flip)
- return;
+ goto out;
trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end);
@@ -697,19 +737,10 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
*/
intel_vrr_send_push(new_crtc_state);
- /*
- * Seamless M/N update may need to update frame timings.
- *
- * FIXME Should be synchronized with the start of vblank somehow...
- */
- if (new_crtc_state->seamless_m_n && intel_crtc_needs_fastset(new_crtc_state))
- intel_crtc_update_active_timings(new_crtc_state,
- new_crtc_state->vrr.enable);
-
local_irq_enable();
if (intel_vgpu_active(dev_priv))
- return;
+ goto out;
if (crtc->debug.start_vbl_count &&
crtc->debug.start_vbl_count != end_vbl_count) {
@@ -724,4 +755,7 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
}
dbg_vblank_evade(crtc, end_vbl_time);
+
+out:
+ intel_psr_unlock(new_crtc_state);
}
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.h b/drivers/gpu/drm/i915/display/intel_crtc.h
index 51a4c8df9e..22d7993d1f 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.h
+++ b/drivers/gpu/drm/i915/display/intel_crtc.h
@@ -36,8 +36,10 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc);
void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state);
void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state);
-void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state);
-void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state);
+void intel_pipe_update_start(struct intel_atomic_state *state,
+ struct intel_crtc *crtc);
+void intel_pipe_update_end(struct intel_atomic_state *state,
+ struct intel_crtc *crtc);
void intel_wait_for_vblank_workers(struct intel_atomic_state *state);
struct intel_crtc *intel_first_crtc(struct drm_i915_private *i915);
struct intel_crtc *intel_crtc_for_pipe(struct drm_i915_private *i915,
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 048e581fda..ccf225afeb 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -31,7 +31,7 @@
bool intel_is_c10phy(struct drm_i915_private *i915, enum phy phy)
{
- if (IS_METEORLAKE(i915) && (phy < PHY_C))
+ if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0) && phy < PHY_C)
return true;
return false;
@@ -46,6 +46,22 @@ static int lane_mask_to_lane(u8 lane_mask)
return ilog2(lane_mask);
}
+static u8 intel_cx0_get_owned_lane_mask(struct drm_i915_private *i915,
+ struct intel_encoder *encoder)
+{
+ struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+ if (!intel_tc_port_in_dp_alt_mode(dig_port))
+ return INTEL_CX0_BOTH_LANES;
+
+ /*
+ * In DP-alt with pin assignment D, only PHY lane 0 is owned
+ * by display and lane 1 is owned by USB.
+ */
+ return intel_tc_port_max_lane_count(dig_port) > 2
+ ? INTEL_CX0_BOTH_LANES : INTEL_CX0_LANE0;
+}
+
static void
assert_dc_off(struct drm_i915_private *i915)
{
@@ -55,19 +71,38 @@ assert_dc_off(struct drm_i915_private *i915)
drm_WARN_ON(&i915->drm, !enabled);
}
+static void intel_cx0_program_msgbus_timer(struct intel_encoder *encoder)
+{
+ int lane;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ for_each_cx0_lane_in_mask(INTEL_CX0_BOTH_LANES, lane)
+ intel_de_rmw(i915,
+ XELPDP_PORT_MSGBUS_TIMER(encoder->port, lane),
+ XELPDP_PORT_MSGBUS_TIMER_VAL_MASK,
+ XELPDP_PORT_MSGBUS_TIMER_VAL);
+}
+
/*
* Prepare HW for CX0 phy transactions.
*
* It is required that PSR and DC5/6 are disabled before any CX0 message
* bus transaction is executed.
+ *
+ * We also do the msgbus timer programming here to ensure that the timer
+ * is already programmed before any access to the msgbus.
*/
static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder *encoder)
{
+ intel_wakeref_t wakeref;
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_psr_pause(intel_dp);
- return intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
+ wakeref = intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
+ intel_cx0_program_msgbus_timer(encoder);
+
+ return wakeref;
}
static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref)
@@ -116,6 +151,13 @@ static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port,
XELPDP_MSGBUS_TIMEOUT_SLOW, val)) {
drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for message ACK. Status: 0x%x\n",
phy_name(phy), *val);
+
+ if (!(intel_de_read(i915, XELPDP_PORT_MSGBUS_TIMER(port, lane)) &
+ XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT))
+ drm_dbg_kms(&i915->drm,
+ "PHY %c Hardware did not detect a timeout\n",
+ phy_name(phy));
+
intel_cx0_bus_reset(i915, port, lane);
return -ETIMEDOUT;
}
@@ -359,6 +401,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
const struct intel_ddi_buf_trans *trans;
enum phy phy = intel_port_to_phy(i915, encoder->port);
+ u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder);
intel_wakeref_t wakeref;
int n_entries, ln;
@@ -371,13 +414,13 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
}
if (intel_is_c10phy(i915, phy)) {
- intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
+ intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_CONTROL(1),
0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED);
- intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CMN(3),
+ intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_CMN(3),
C10_CMN3_TXVBOOST_MASK,
C10_CMN3_TXVBOOST(intel_c10_get_tx_vboost_lvl(crtc_state)),
MB_WRITE_UNCOMMITTED);
- intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_TX(1),
+ intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_TX(1),
C10_TX1_TERMCTL_MASK,
C10_TX1_TERMCTL(intel_c10_get_tx_term_ctl(crtc_state)),
MB_WRITE_COMMITTED);
@@ -385,32 +428,34 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
for (ln = 0; ln < crtc_state->lane_count; ln++) {
int level = intel_ddi_level(encoder, crtc_state, ln);
- int lane, tx;
+ int lane = ln / 2;
+ int tx = ln % 2;
+ u8 lane_mask = lane == 0 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1;
- lane = ln / 2;
- tx = ln % 2;
+ if (!(lane_mask & owned_lane_mask))
+ continue;
- intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 0),
+ intel_cx0_rmw(i915, encoder->port, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 0),
C10_PHY_OVRD_LEVEL_MASK,
C10_PHY_OVRD_LEVEL(trans->entries[level].snps.pre_cursor),
MB_WRITE_COMMITTED);
- intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 1),
+ intel_cx0_rmw(i915, encoder->port, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 1),
C10_PHY_OVRD_LEVEL_MASK,
C10_PHY_OVRD_LEVEL(trans->entries[level].snps.vswing),
MB_WRITE_COMMITTED);
- intel_cx0_rmw(i915, encoder->port, BIT(lane), PHY_CX0_VDROVRD_CTL(lane, tx, 2),
+ intel_cx0_rmw(i915, encoder->port, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 2),
C10_PHY_OVRD_LEVEL_MASK,
C10_PHY_OVRD_LEVEL(trans->entries[level].snps.post_cursor),
MB_WRITE_COMMITTED);
}
/* Write Override enables in 0xD71 */
- intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_OVRD,
+ intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_OVRD,
0, PHY_C10_VDR_OVRD_TX1 | PHY_C10_VDR_OVRD_TX2,
MB_WRITE_COMMITTED);
if (intel_is_c10phy(i915, phy))
- intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
+ intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_CONTROL(1),
0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED);
intel_cx0_phy_transaction_end(encoder, wakeref);
@@ -2535,17 +2580,15 @@ static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915,
{
enum port port = encoder->port;
enum phy phy = intel_port_to_phy(i915, port);
- bool both_lanes = intel_tc_port_fia_max_lane_count(enc_to_dig_port(encoder)) > 2;
- u8 lane_mask = lane_reversal ? INTEL_CX0_LANE1 :
- INTEL_CX0_LANE0;
- u32 lane_pipe_reset = both_lanes ?
- XELPDP_LANE_PIPE_RESET(0) |
- XELPDP_LANE_PIPE_RESET(1) :
- XELPDP_LANE_PIPE_RESET(0);
- u32 lane_phy_current_status = both_lanes ?
- XELPDP_LANE_PHY_CURRENT_STATUS(0) |
- XELPDP_LANE_PHY_CURRENT_STATUS(1) :
- XELPDP_LANE_PHY_CURRENT_STATUS(0);
+ u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder);
+ u8 lane_mask = lane_reversal ? INTEL_CX0_LANE1 : INTEL_CX0_LANE0;
+ u32 lane_pipe_reset = owned_lane_mask == INTEL_CX0_BOTH_LANES
+ ? XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1)
+ : XELPDP_LANE_PIPE_RESET(0);
+ u32 lane_phy_current_status = owned_lane_mask == INTEL_CX0_BOTH_LANES
+ ? (XELPDP_LANE_PHY_CURRENT_STATUS(0) |
+ XELPDP_LANE_PHY_CURRENT_STATUS(1))
+ : XELPDP_LANE_PHY_CURRENT_STATUS(0);
if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL1(port),
XELPDP_PORT_BUF_SOC_PHY_READY,
@@ -2564,15 +2607,11 @@ static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915,
phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(port),
- intel_cx0_get_pclk_refclk_request(both_lanes ?
- INTEL_CX0_BOTH_LANES :
- INTEL_CX0_LANE0),
+ intel_cx0_get_pclk_refclk_request(owned_lane_mask),
intel_cx0_get_pclk_refclk_request(lane_mask));
if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(port),
- intel_cx0_get_pclk_refclk_ack(both_lanes ?
- INTEL_CX0_BOTH_LANES :
- INTEL_CX0_LANE0),
+ intel_cx0_get_pclk_refclk_ack(owned_lane_mask),
intel_cx0_get_pclk_refclk_ack(lane_mask),
XELPDP_REFCLK_ENABLE_TIMEOUT_US, 0, NULL))
drm_warn(&i915->drm, "PHY %c failed to request refclk after %dus.\n",
@@ -2594,79 +2633,43 @@ static void intel_cx0_program_phy_lane(struct drm_i915_private *i915,
struct intel_encoder *encoder, int lane_count,
bool lane_reversal)
{
- u8 l0t1, l0t2, l1t1, l1t2;
+ int i;
+ u8 disables;
bool dp_alt_mode = intel_tc_port_in_dp_alt_mode(enc_to_dig_port(encoder));
+ u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder);
enum port port = encoder->port;
if (intel_is_c10phy(i915, intel_port_to_phy(i915, port)))
- intel_cx0_rmw(i915, port, INTEL_CX0_BOTH_LANES,
+ intel_cx0_rmw(i915, port, owned_lane_mask,
PHY_C10_VDR_CONTROL(1), 0,
C10_VDR_CTRL_MSGBUS_ACCESS,
MB_WRITE_COMMITTED);
- /* TODO: DP-alt MFD case where only one PHY lane should be programmed. */
- l0t1 = intel_cx0_read(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(1, 2));
- l0t2 = intel_cx0_read(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(2, 2));
- l1t1 = intel_cx0_read(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(1, 2));
- l1t2 = intel_cx0_read(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(2, 2));
-
- l0t1 |= CONTROL2_DISABLE_SINGLE_TX;
- l0t2 |= CONTROL2_DISABLE_SINGLE_TX;
- l1t1 |= CONTROL2_DISABLE_SINGLE_TX;
- l1t2 |= CONTROL2_DISABLE_SINGLE_TX;
-
- if (lane_reversal) {
- switch (lane_count) {
- case 4:
- l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
- fallthrough;
- case 3:
- l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
- fallthrough;
- case 2:
- l1t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
- fallthrough;
- case 1:
- l1t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
- break;
- default:
- MISSING_CASE(lane_count);
- }
- } else {
- switch (lane_count) {
- case 4:
- l1t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
- fallthrough;
- case 3:
- l1t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
- fallthrough;
- case 2:
- l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
- l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
- break;
- case 1:
- if (dp_alt_mode)
- l0t2 &= ~CONTROL2_DISABLE_SINGLE_TX;
- else
- l0t1 &= ~CONTROL2_DISABLE_SINGLE_TX;
- break;
- default:
- MISSING_CASE(lane_count);
- }
+ if (lane_reversal)
+ disables = REG_GENMASK8(3, 0) >> lane_count;
+ else
+ disables = REG_GENMASK8(3, 0) << lane_count;
+
+ if (dp_alt_mode && lane_count == 1) {
+ disables &= ~REG_GENMASK8(1, 0);
+ disables |= REG_FIELD_PREP8(REG_GENMASK8(1, 0), 0x1);
}
- /* disable MLs */
- intel_cx0_write(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(1, 2),
- l0t1, MB_WRITE_COMMITTED);
- intel_cx0_write(i915, port, INTEL_CX0_LANE0, PHY_CX0_TX_CONTROL(2, 2),
- l0t2, MB_WRITE_COMMITTED);
- intel_cx0_write(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(1, 2),
- l1t1, MB_WRITE_COMMITTED);
- intel_cx0_write(i915, port, INTEL_CX0_LANE1, PHY_CX0_TX_CONTROL(2, 2),
- l1t2, MB_WRITE_COMMITTED);
+ for (i = 0; i < 4; i++) {
+ int tx = i % 2 + 1;
+ u8 lane_mask = i < 2 ? INTEL_CX0_LANE0 : INTEL_CX0_LANE1;
+
+ if (!(owned_lane_mask & lane_mask))
+ continue;
+
+ intel_cx0_rmw(i915, port, lane_mask, PHY_CX0_TX_CONTROL(tx, 2),
+ CONTROL2_DISABLE_SINGLE_TX,
+ disables & BIT(i) ? CONTROL2_DISABLE_SINGLE_TX : 0,
+ MB_WRITE_COMMITTED);
+ }
if (intel_is_c10phy(i915, intel_port_to_phy(i915, port)))
- intel_cx0_rmw(i915, port, INTEL_CX0_BOTH_LANES,
+ intel_cx0_rmw(i915, port, owned_lane_mask,
PHY_C10_VDR_CONTROL(1), 0,
C10_VDR_CTRL_UPDATE_CFG,
MB_WRITE_COMMITTED);
@@ -2721,39 +2724,45 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
intel_cx0_powerdown_change_sequence(i915, encoder->port, INTEL_CX0_BOTH_LANES,
CX0_P2_STATE_READY);
- /* 4. Program PHY internal PLL internal registers. */
+ /*
+ * 4. Program PORT_MSGBUS_TIMER register's Message Bus Timer field to 0xA000.
+ * (This is done inside intel_cx0_phy_transaction_begin(), since we would need
+ * the right timer thresholds for readouts too.)
+ */
+
+ /* 5. Program PHY internal PLL internal registers. */
if (intel_is_c10phy(i915, phy))
intel_c10_pll_program(i915, crtc_state, encoder);
else
intel_c20_pll_program(i915, crtc_state, encoder);
/*
- * 5. Program the enabled and disabled owned PHY lane
+ * 6. Program the enabled and disabled owned PHY lane
* transmitters over message bus
*/
intel_cx0_program_phy_lane(i915, encoder, crtc_state->lane_count, lane_reversal);
/*
- * 6. Follow the Display Voltage Frequency Switching - Sequence
+ * 7. Follow the Display Voltage Frequency Switching - Sequence
* Before Frequency Change. We handle this step in bxt_set_cdclk().
*/
/*
- * 7. Program DDI_CLK_VALFREQ to match intended DDI
+ * 8. Program DDI_CLK_VALFREQ to match intended DDI
* clock frequency.
*/
intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
crtc_state->port_clock);
/*
- * 8. Set PORT_CLOCK_CTL register PCLK PLL Request
+ * 9. Set PORT_CLOCK_CTL register PCLK PLL Request
* LN<Lane for maxPCLK> to "1" to enable PLL.
*/
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
intel_cx0_get_pclk_pll_request(INTEL_CX0_BOTH_LANES),
intel_cx0_get_pclk_pll_request(maxpclk_lane));
- /* 9. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */
+ /* 10. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN<Lane for maxPCLK> == "1". */
if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES),
intel_cx0_get_pclk_pll_ack(maxpclk_lane),
@@ -2762,7 +2771,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
phy_name(phy), XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US);
/*
- * 10. Follow the Display Voltage Frequency Switching Sequence After
+ * 11. Follow the Display Voltage Frequency Switching Sequence After
* Frequency Change. We handle this step in bxt_set_cdclk().
*/
@@ -2996,12 +3005,13 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder,
}
void intel_c10pll_state_verify(struct intel_atomic_state *state,
- struct intel_crtc_state *new_crtc_state)
+ struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
- struct intel_c10pll_state mpllb_hw_state = { 0 };
- struct intel_c10pll_state *mpllb_sw_state = &new_crtc_state->cx0pll_state.c10;
- struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
+ const struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ struct intel_c10pll_state mpllb_hw_state = {};
+ const struct intel_c10pll_state *mpllb_sw_state = &new_crtc_state->cx0pll_state.c10;
struct intel_encoder *encoder;
enum phy phy;
int i;
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 4c4db5cdcb..0e0a38dac8 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -10,14 +10,16 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
-#include "i915_drv.h"
-#include "intel_display_types.h"
-
-struct drm_i915_private;
-struct intel_encoder;
-struct intel_crtc_state;
enum icl_port_dpll_id;
enum phy;
+struct drm_i915_private;
+struct intel_atomic_state;
+struct intel_c10pll_state;
+struct intel_c20pll_state;
+struct intel_crtc;
+struct intel_crtc_state;
+struct intel_encoder;
+struct intel_hdmi;
bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy);
void intel_mtl_pll_enable(struct intel_encoder *encoder,
@@ -33,7 +35,7 @@ void intel_c10pll_dump_hw_state(struct drm_i915_private *dev_priv,
int intel_c10pll_calc_port_clock(struct intel_encoder *encoder,
const struct intel_c10pll_state *pll_state);
void intel_c10pll_state_verify(struct intel_atomic_state *state,
- struct intel_crtc_state *new_crtc_state);
+ struct intel_crtc *crtc);
void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
struct intel_c20pll_state *pll_state);
void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
@@ -44,4 +46,5 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock);
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
+
#endif /* __INTEL_CX0_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index cb5d1be2ba..adf8f4ce0d 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -110,6 +110,19 @@
#define CX0_P4PG_STATE_DISABLE 0xC
#define CX0_P2_STATE_RESET 0x2
+#define _XELPDP_PORT_MSGBUS_TIMER_LN0_A 0x640d8
+#define _XELPDP_PORT_MSGBUS_TIMER_LN0_B 0x641d8
+#define _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC1 0x16f258
+#define _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC2 0x16f458
+#define XELPDP_PORT_MSGBUS_TIMER(port, lane) _MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+ _XELPDP_PORT_MSGBUS_TIMER_LN0_A, \
+ _XELPDP_PORT_MSGBUS_TIMER_LN0_B, \
+ _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC1, \
+ _XELPDP_PORT_MSGBUS_TIMER_LN0_USBC2) + (lane) * 4)
+#define XELPDP_PORT_MSGBUS_TIMER_TIMED_OUT REG_BIT(31)
+#define XELPDP_PORT_MSGBUS_TIMER_VAL_MASK REG_GENMASK(23, 0)
+#define XELPDP_PORT_MSGBUS_TIMER_VAL REG_FIELD_PREP(XELPDP_PORT_MSGBUS_TIMER_VAL_MASK, 0xa000)
+
#define _XELPDP_PORT_CLOCK_CTL_A 0x640E0
#define _XELPDP_PORT_CLOCK_CTL_B 0x641E0
#define _XELPDP_PORT_CLOCK_CTL_USBC1 0x16F260
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index c7e00f57cb..9151d5add9 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3248,7 +3248,7 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
intel_ddi_enable_transcoder_func(encoder, crtc_state);
/* Enable/Disable DP2.0 SDP split config before transcoder */
- intel_audio_sdp_split_update(encoder, crtc_state);
+ intel_audio_sdp_split_update(crtc_state);
intel_enable_transcoder(crtc_state);
@@ -3762,6 +3762,11 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
&pipe_config->dp_m_n);
+ if (DISPLAY_VER(dev_priv) >= 11)
+ pipe_config->fec_enable =
+ intel_de_read(dev_priv,
+ dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE;
+
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
break;
@@ -3857,11 +3862,9 @@ static void mtl_ddi_get_config(struct intel_encoder *encoder,
crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
} else if (intel_is_c10phy(i915, phy)) {
intel_c10pll_readout_hw_state(encoder, &crtc_state->cx0pll_state.c10);
- intel_c10pll_dump_hw_state(i915, &crtc_state->cx0pll_state.c10);
crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c10);
} else {
intel_c20pll_readout_hw_state(encoder, &crtc_state->cx0pll_state.c20);
- intel_c20pll_dump_hw_state(i915, &crtc_state->cx0pll_state.c20);
crtc_state->port_clock = intel_c20pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c20);
}
@@ -4173,7 +4176,7 @@ static int intel_ddi_compute_config_late(struct intel_encoder *encoder,
struct drm_connector *connector = conn_state->connector;
u8 port_sync_transcoders = 0;
- drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] [CRTC:%d:%s]",
+ drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] [CRTC:%d:%s]\n",
encoder->base.base.id, encoder->base.name,
crtc_state->uapi.crtc->base.id, crtc_state->uapi.crtc->name);
@@ -4323,15 +4326,14 @@ static int intel_hdmi_reset_link(struct intel_encoder *encoder,
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder);
struct intel_connector *connector = hdmi->attached_connector;
- struct i2c_adapter *adapter =
- intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
+ struct i2c_adapter *ddc = connector->base.ddc;
struct drm_connector_state *conn_state;
struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
u8 config;
int ret;
- if (!connector || connector->base.status != connector_status_connected)
+ if (connector->base.status != connector_status_connected)
return 0;
ret = drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex,
@@ -4365,7 +4367,7 @@ static int intel_hdmi_reset_link(struct intel_encoder *encoder,
!try_wait_for_completion(&conn_state->commit->hw_done))
return 0;
- ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config);
+ ret = drm_scdc_readb(ddc, SCDC_TMDS_CONFIG, &config);
if (ret < 0) {
drm_err(&dev_priv->drm, "[CONNECTOR:%d:%s] Failed to read TMDS config: %d\n",
connector->base.base.id, connector->base.name, ret);
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index a072fbb987..df582ff81b 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -77,6 +77,7 @@
#include "intel_dpll_mgr.h"
#include "intel_dpt.h"
#include "intel_drrs.h"
+#include "intel_dsb.h"
#include "intel_dsi.h"
#include "intel_dvo.h"
#include "intel_fb.h"
@@ -87,6 +88,7 @@
#include "intel_frontbuffer.h"
#include "intel_hdmi.h"
#include "intel_hotplug.h"
+#include "intel_link_bw.h"
#include "intel_lvds.h"
#include "intel_lvds_regs.h"
#include "intel_modeset_setup.h"
@@ -726,7 +728,7 @@ static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state)
tmp |= UNDERRUN_RECOVERY_DISABLE_ADLP;
/* Wa_14010547955:dg2 */
- if (IS_DG2_DISPLAY_STEP(dev_priv, STEP_B0, STEP_FOREVER))
+ if (IS_DG2(dev_priv))
tmp |= DG2_RENDER_CCSTAG_4_3_EN;
intel_de_write(dev_priv, PIPE_CHICKEN(pipe), tmp);
@@ -904,25 +906,53 @@ static bool needs_async_flip_vtd_wa(const struct intel_crtc_state *crtc_state)
static bool planes_enabling(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state)
{
+ if (!new_crtc_state->hw.active)
+ return false;
+
return is_enabling(active_planes, old_crtc_state, new_crtc_state);
}
static bool planes_disabling(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state)
{
+ if (!old_crtc_state->hw.active)
+ return false;
+
return is_disabling(active_planes, old_crtc_state, new_crtc_state);
}
+static bool vrr_params_changed(const struct intel_crtc_state *old_crtc_state,
+ const struct intel_crtc_state *new_crtc_state)
+{
+ return old_crtc_state->vrr.flipline != new_crtc_state->vrr.flipline ||
+ old_crtc_state->vrr.vmin != new_crtc_state->vrr.vmin ||
+ old_crtc_state->vrr.vmax != new_crtc_state->vrr.vmax ||
+ old_crtc_state->vrr.guardband != new_crtc_state->vrr.guardband ||
+ old_crtc_state->vrr.pipeline_full != new_crtc_state->vrr.pipeline_full;
+}
+
static bool vrr_enabling(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state)
{
- return is_enabling(vrr.enable, old_crtc_state, new_crtc_state);
+ if (!new_crtc_state->hw.active)
+ return false;
+
+ return is_enabling(vrr.enable, old_crtc_state, new_crtc_state) ||
+ (new_crtc_state->vrr.enable &&
+ (new_crtc_state->update_m_n || new_crtc_state->update_lrr ||
+ vrr_params_changed(old_crtc_state, new_crtc_state)));
}
static bool vrr_disabling(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state)
{
- return is_disabling(vrr.enable, old_crtc_state, new_crtc_state);
+ if (!old_crtc_state->hw.active)
+ return false;
+
+ return is_disabling(vrr.enable, old_crtc_state, new_crtc_state) ||
+ (old_crtc_state->vrr.enable &&
+ (new_crtc_state->update_m_n || new_crtc_state->update_lrr ||
+ vrr_params_changed(old_crtc_state, new_crtc_state)));
}
#undef is_disabling
@@ -938,6 +968,8 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
enum pipe pipe = crtc->pipe;
+ intel_psr_post_plane_update(state, crtc);
+
intel_frontbuffer_flip(dev_priv, new_crtc_state->fb_bits);
if (new_crtc_state->update_wm_post && new_crtc_state->hw.active)
@@ -1767,7 +1799,7 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy)
if (IS_DG2(dev_priv))
/* DG2's "TC1" output uses a SNPS PHY */
return false;
- else if (IS_ALDERLAKE_P(dev_priv) || IS_METEORLAKE(dev_priv))
+ else if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER_FULL(dev_priv) == IP_VER(14, 0))
return phy >= PHY_F && phy <= PHY_I;
else if (IS_TIGERLAKE(dev_priv))
return phy >= PHY_D && phy <= PHY_I;
@@ -2570,6 +2602,37 @@ static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_sta
VTOTAL(crtc_vtotal - 1));
}
+static void intel_set_transcoder_timings_lrr(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);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+ const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ u32 crtc_vdisplay, crtc_vtotal, crtc_vblank_start, crtc_vblank_end;
+
+ crtc_vdisplay = adjusted_mode->crtc_vdisplay;
+ crtc_vtotal = adjusted_mode->crtc_vtotal;
+ crtc_vblank_start = adjusted_mode->crtc_vblank_start;
+ crtc_vblank_end = adjusted_mode->crtc_vblank_end;
+
+ drm_WARN_ON(&dev_priv->drm, adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE);
+
+ /*
+ * The hardware actually ignores TRANS_VBLANK.VBLANK_END in DP mode.
+ * But let's write it anyway to keep the state checker happy.
+ */
+ intel_de_write(dev_priv, TRANS_VBLANK(cpu_transcoder),
+ VBLANK_START(crtc_vblank_start - 1) |
+ VBLANK_END(crtc_vblank_end - 1));
+ /*
+ * The double buffer latch point for TRANS_VTOTAL
+ * is the transcoder's undelayed vblank.
+ */
+ intel_de_write(dev_priv, TRANS_VTOTAL(cpu_transcoder),
+ VACTIVE(crtc_vdisplay - 1) |
+ VTOTAL(crtc_vtotal - 1));
+}
+
static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -2869,24 +2932,6 @@ bdw_get_pipe_misc_output_format(struct intel_crtc *crtc)
}
}
-static void i9xx_get_pipe_color_config(struct intel_crtc_state *crtc_state)
-{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct intel_plane *plane = to_intel_plane(crtc->base.primary);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
- u32 tmp;
-
- tmp = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
-
- if (tmp & DISP_PIPE_GAMMA_ENABLE)
- crtc_state->gamma_enable = true;
-
- if (!HAS_GMCH(dev_priv) &&
- tmp & DISP_PIPE_CSC_ENABLE)
- crtc_state->csc_enable = true;
-}
-
static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
@@ -2942,11 +2987,6 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
(tmp & TRANSCONF_WGC_ENABLE))
pipe_config->wgc_enable = true;
- if (IS_CHERRYVIEW(dev_priv))
- pipe_config->cgm_mode = intel_de_read(dev_priv,
- CGM_PIPE_MODE(crtc->pipe));
-
- i9xx_get_pipe_color_config(pipe_config);
intel_color_get_config(pipe_config);
if (DISPLAY_VER(dev_priv) < 4)
@@ -3344,10 +3384,6 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc,
pipe_config->msa_timing_delay = REG_FIELD_GET(TRANSCONF_MSA_TIMING_DELAY_MASK, tmp);
- pipe_config->csc_mode = intel_de_read(dev_priv,
- PIPE_CSC_MODE(crtc->pipe));
-
- i9xx_get_pipe_color_config(pipe_config);
intel_color_get_config(pipe_config);
pipe_config->pixel_multiplier = 1;
@@ -3711,8 +3747,8 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
if (!active)
goto out;
- intel_dsc_get_config(pipe_config);
intel_bigjoiner_get_config(pipe_config);
+ intel_dsc_get_config(pipe_config);
if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||
DISPLAY_VER(dev_priv) >= 11)
@@ -3738,24 +3774,6 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
pipe_config->sink_format = pipe_config->output_format;
- pipe_config->gamma_mode = intel_de_read(dev_priv,
- GAMMA_MODE(crtc->pipe));
-
- pipe_config->csc_mode = intel_de_read(dev_priv,
- PIPE_CSC_MODE(crtc->pipe));
-
- if (DISPLAY_VER(dev_priv) >= 9) {
- tmp = intel_de_read(dev_priv, SKL_BOTTOM_COLOR(crtc->pipe));
-
- if (tmp & SKL_BOTTOM_COLOR_GAMMA_ENABLE)
- pipe_config->gamma_enable = true;
-
- if (tmp & SKL_BOTTOM_COLOR_CSC_ENABLE)
- pipe_config->csc_enable = true;
- } else {
- i9xx_get_pipe_color_config(pipe_config);
- }
-
intel_color_get_config(pipe_config);
tmp = intel_de_read(dev_priv, WM_LINETIME(crtc->pipe));
@@ -3993,7 +4011,7 @@ intel_encoder_current_mode(struct intel_encoder *encoder)
}
if (!intel_crtc_get_pipe_config(crtc_state)) {
- kfree(crtc_state);
+ intel_crtc_destroy_state(&crtc->base, &crtc_state->uapi);
kfree(mode);
return NULL;
}
@@ -4002,7 +4020,7 @@ intel_encoder_current_mode(struct intel_encoder *encoder)
intel_mode_from_crtc_timings(mode, &crtc_state->hw.adjusted_mode);
- kfree(crtc_state);
+ intel_crtc_destroy_state(&crtc->base, &crtc_state->uapi);
return mode;
}
@@ -4641,7 +4659,8 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
static int
intel_modeset_pipe_config(struct intel_atomic_state *state,
- struct intel_crtc *crtc)
+ struct intel_crtc *crtc,
+ const struct intel_link_bw_limits *limits)
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_crtc_state *crtc_state =
@@ -4650,7 +4669,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
struct drm_connector_state *connector_state;
int pipe_src_w, pipe_src_h;
int base_bpp, ret, i;
- bool retry = true;
crtc_state->cpu_transcoder = (enum transcoder) crtc->pipe;
@@ -4673,6 +4691,16 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
if (ret)
return ret;
+ crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe];
+
+ if (crtc_state->pipe_bpp > to_bpp_int(crtc_state->max_link_bpp_x16)) {
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] Link bpp limited to " BPP_X16_FMT "\n",
+ crtc->base.base.id, crtc->base.name,
+ BPP_X16_ARGS(crtc_state->max_link_bpp_x16));
+ crtc_state->bw_constrained = true;
+ }
+
base_bpp = crtc_state->pipe_bpp;
/*
@@ -4714,7 +4742,6 @@ intel_modeset_pipe_config(struct intel_atomic_state *state,
crtc_state->output_types |= BIT(encoder->type);
}
-encoder_retry:
/* Ensure the port clock defaults are reset when retrying. */
crtc_state->port_clock = 0;
crtc_state->pixel_multiplier = 1;
@@ -4754,17 +4781,6 @@ encoder_retry:
ret = intel_crtc_compute_config(state, crtc);
if (ret == -EDEADLK)
return ret;
- if (ret == -EAGAIN) {
- if (drm_WARN(&i915->drm, !retry,
- "[CRTC:%d:%s] loop in pipe configuration computation\n",
- crtc->base.base.id, crtc->base.name))
- return -EINVAL;
-
- drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] bw constrained, retrying\n",
- crtc->base.base.id, crtc->base.name);
- retry = false;
- goto encoder_retry;
- }
if (ret < 0) {
drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] config failure: %d\n",
crtc->base.base.id, crtc->base.name, ret);
@@ -4984,9 +5000,6 @@ pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc,
static bool fastboot_enabled(struct drm_i915_private *dev_priv)
{
- if (dev_priv->params.fastboot != -1)
- return dev_priv->params.fastboot;
-
/* Enable fastboot by default on Skylake and newer */
if (DISPLAY_VER(dev_priv) >= 9)
return true;
@@ -5111,11 +5124,13 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(name.crtc_hsync_start); \
PIPE_CONF_CHECK_I(name.crtc_hsync_end); \
PIPE_CONF_CHECK_I(name.crtc_vdisplay); \
- PIPE_CONF_CHECK_I(name.crtc_vtotal); \
PIPE_CONF_CHECK_I(name.crtc_vblank_start); \
- PIPE_CONF_CHECK_I(name.crtc_vblank_end); \
PIPE_CONF_CHECK_I(name.crtc_vsync_start); \
PIPE_CONF_CHECK_I(name.crtc_vsync_end); \
+ if (!fastset || !pipe_config->update_lrr) { \
+ PIPE_CONF_CHECK_I(name.crtc_vtotal); \
+ PIPE_CONF_CHECK_I(name.crtc_vblank_end); \
+ } \
} while (0)
#define PIPE_CONF_CHECK_RECT(name) do { \
@@ -5215,7 +5230,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_X(lane_lat_optim_mask);
if (HAS_DOUBLE_BUFFERED_M_N(dev_priv)) {
- if (!fastset || !pipe_config->seamless_m_n)
+ if (!fastset || !pipe_config->update_m_n)
PIPE_CONF_CHECK_M_N(dp_m_n);
} else {
PIPE_CONF_CHECK_M_N(dp_m_n);
@@ -5353,7 +5368,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
if (IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) >= 5)
PIPE_CONF_CHECK_I(pipe_bpp);
- if (!fastset || !pipe_config->seamless_m_n) {
+ if (!fastset || !pipe_config->update_m_n) {
PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_clock);
PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_clock);
}
@@ -5378,6 +5393,37 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(master_transcoder);
PIPE_CONF_CHECK_X(bigjoiner_pipes);
+ PIPE_CONF_CHECK_BOOL(dsc.config.block_pred_enable);
+ PIPE_CONF_CHECK_BOOL(dsc.config.convert_rgb);
+ PIPE_CONF_CHECK_BOOL(dsc.config.simple_422);
+ PIPE_CONF_CHECK_BOOL(dsc.config.native_422);
+ PIPE_CONF_CHECK_BOOL(dsc.config.native_420);
+ PIPE_CONF_CHECK_BOOL(dsc.config.vbr_enable);
+ PIPE_CONF_CHECK_I(dsc.config.line_buf_depth);
+ PIPE_CONF_CHECK_I(dsc.config.bits_per_component);
+ PIPE_CONF_CHECK_I(dsc.config.pic_width);
+ PIPE_CONF_CHECK_I(dsc.config.pic_height);
+ PIPE_CONF_CHECK_I(dsc.config.slice_width);
+ PIPE_CONF_CHECK_I(dsc.config.slice_height);
+ PIPE_CONF_CHECK_I(dsc.config.initial_dec_delay);
+ PIPE_CONF_CHECK_I(dsc.config.initial_xmit_delay);
+ PIPE_CONF_CHECK_I(dsc.config.scale_decrement_interval);
+ PIPE_CONF_CHECK_I(dsc.config.scale_increment_interval);
+ PIPE_CONF_CHECK_I(dsc.config.initial_scale_value);
+ PIPE_CONF_CHECK_I(dsc.config.first_line_bpg_offset);
+ PIPE_CONF_CHECK_I(dsc.config.flatness_min_qp);
+ PIPE_CONF_CHECK_I(dsc.config.flatness_max_qp);
+ PIPE_CONF_CHECK_I(dsc.config.slice_bpg_offset);
+ PIPE_CONF_CHECK_I(dsc.config.nfl_bpg_offset);
+ PIPE_CONF_CHECK_I(dsc.config.initial_offset);
+ PIPE_CONF_CHECK_I(dsc.config.final_offset);
+ PIPE_CONF_CHECK_I(dsc.config.rc_model_size);
+ PIPE_CONF_CHECK_I(dsc.config.rc_quant_incr_limit0);
+ PIPE_CONF_CHECK_I(dsc.config.rc_quant_incr_limit1);
+ PIPE_CONF_CHECK_I(dsc.config.slice_chunk_size);
+ PIPE_CONF_CHECK_I(dsc.config.second_line_bpg_offset);
+ PIPE_CONF_CHECK_I(dsc.config.nsl_bpg_offset);
+
PIPE_CONF_CHECK_I(dsc.compression_enable);
PIPE_CONF_CHECK_I(dsc.dsc_split);
PIPE_CONF_CHECK_I(dsc.compressed_bpp);
@@ -5386,13 +5432,14 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(splitter.link_count);
PIPE_CONF_CHECK_I(splitter.pixel_overlap);
- if (!fastset)
+ if (!fastset) {
PIPE_CONF_CHECK_BOOL(vrr.enable);
- PIPE_CONF_CHECK_I(vrr.vmin);
- PIPE_CONF_CHECK_I(vrr.vmax);
- PIPE_CONF_CHECK_I(vrr.flipline);
- PIPE_CONF_CHECK_I(vrr.pipeline_full);
- PIPE_CONF_CHECK_I(vrr.guardband);
+ PIPE_CONF_CHECK_I(vrr.vmin);
+ PIPE_CONF_CHECK_I(vrr.vmax);
+ PIPE_CONF_CHECK_I(vrr.flipline);
+ PIPE_CONF_CHECK_I(vrr.pipeline_full);
+ PIPE_CONF_CHECK_I(vrr.guardband);
+ }
#undef PIPE_CONF_CHECK_X
#undef PIPE_CONF_CHECK_I
@@ -5421,17 +5468,54 @@ intel_verify_planes(struct intel_atomic_state *state)
plane_state->uapi.visible);
}
-int intel_modeset_all_pipes(struct intel_atomic_state *state,
- const char *reason)
+static int intel_modeset_pipe(struct intel_atomic_state *state,
+ struct intel_crtc_state *crtc_state,
+ const char *reason)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ int ret;
+
+ drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
+ crtc->base.base.id, crtc->base.name, reason);
+
+ ret = drm_atomic_add_affected_connectors(&state->base,
+ &crtc->base);
+ if (ret)
+ return ret;
+
+ ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
+ if (ret)
+ return ret;
+
+ ret = intel_atomic_add_affected_planes(state, crtc);
+ if (ret)
+ return ret;
+
+ crtc_state->uapi.mode_changed = true;
+
+ return 0;
+}
+
+/**
+ * intel_modeset_pipes_in_mask_early - force a full modeset on a set of pipes
+ * @state: intel atomic state
+ * @reason: the reason for the full modeset
+ * @mask: mask of pipes to modeset
+ *
+ * Add pipes in @mask to @state and force a full modeset on the enabled ones
+ * due to the description in @reason.
+ * This function can be called only before new plane states are computed.
+ *
+ * Returns 0 in case of success, negative error code otherwise.
+ */
+int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
+ const char *reason, u8 mask)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_crtc *crtc;
- /*
- * Add all pipes to the state, and force
- * a modeset on all the active ones.
- */
- for_each_intel_crtc(&dev_priv->drm, crtc) {
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, mask) {
struct intel_crtc_state *crtc_state;
int ret;
@@ -5439,29 +5523,54 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state,
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
- if (!crtc_state->hw.active ||
+ if (!crtc_state->hw.enable ||
intel_crtc_needs_modeset(crtc_state))
continue;
- drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
- crtc->base.base.id, crtc->base.name, reason);
-
- crtc_state->uapi.mode_changed = true;
- crtc_state->update_pipe = false;
-
- ret = drm_atomic_add_affected_connectors(&state->base,
- &crtc->base);
+ ret = intel_modeset_pipe(state, crtc_state, reason);
if (ret)
return ret;
+ }
- ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc);
- if (ret)
- return ret;
+ return 0;
+}
- ret = intel_atomic_add_affected_planes(state, crtc);
+/**
+ * intel_modeset_all_pipes_late - force a full modeset on all pipes
+ * @state: intel atomic state
+ * @reason: the reason for the full modeset
+ *
+ * Add all pipes to @state and force a full modeset on the active ones due to
+ * the description in @reason.
+ * This function can be called only after new plane states are computed already.
+ *
+ * Returns 0 in case of success, negative error code otherwise.
+ */
+int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
+ const char *reason)
+{
+ struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct intel_crtc *crtc;
+
+ for_each_intel_crtc(&dev_priv->drm, crtc) {
+ struct intel_crtc_state *crtc_state;
+ int ret;
+
+ crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ if (!crtc_state->hw.active ||
+ intel_crtc_needs_modeset(crtc_state))
+ continue;
+
+ ret = intel_modeset_pipe(state, crtc_state, reason);
if (ret)
return ret;
+ crtc_state->update_pipe = false;
+ crtc_state->update_m_n = false;
+ crtc_state->update_lrr = false;
crtc_state->update_planes |= crtc_state->active_planes;
crtc_state->async_flip_planes = 0;
crtc_state->do_async_flip = false;
@@ -5565,13 +5674,25 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta
{
struct drm_i915_private *i915 = to_i915(old_crtc_state->uapi.crtc->dev);
- if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true)) {
+ /* only allow LRR when the timings stay within the VRR range */
+ if (old_crtc_state->vrr.in_range != new_crtc_state->vrr.in_range)
+ new_crtc_state->update_lrr = false;
+
+ if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true))
drm_dbg_kms(&i915->drm, "fastset requirement not met, forcing full modeset\n");
+ else
+ new_crtc_state->uapi.mode_changed = false;
- return;
- }
+ if (intel_crtc_needs_modeset(new_crtc_state) ||
+ intel_compare_link_m_n(&old_crtc_state->dp_m_n,
+ &new_crtc_state->dp_m_n))
+ new_crtc_state->update_m_n = false;
+
+ if (intel_crtc_needs_modeset(new_crtc_state) ||
+ (old_crtc_state->hw.adjusted_mode.crtc_vtotal == new_crtc_state->hw.adjusted_mode.crtc_vtotal &&
+ old_crtc_state->hw.adjusted_mode.crtc_vblank_end == new_crtc_state->hw.adjusted_mode.crtc_vblank_end))
+ new_crtc_state->update_lrr = false;
- new_crtc_state->uapi.mode_changed = false;
if (!intel_crtc_needs_modeset(new_crtc_state))
new_crtc_state->update_pipe = true;
}
@@ -5912,6 +6033,17 @@ static int intel_async_flip_check_uapi(struct intel_atomic_state *state,
return -EINVAL;
}
+ /*
+ * FIXME: Bigjoiner+async flip is busted currently.
+ * Remove this check once the issues are fixed.
+ */
+ if (new_crtc_state->bigjoiner_pipes) {
+ drm_dbg_kms(&i915->drm,
+ "[CRTC:%d:%s] async flip disallowed with bigjoiner\n",
+ crtc->base.base.id, crtc->base.name);
+ return -EINVAL;
+ }
+
for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
new_plane_state, i) {
if (plane->pipe != crtc->pipe)
@@ -5977,17 +6109,6 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in
return -EINVAL;
}
- /*
- * FIXME: Bigjoiner+async flip is busted currently.
- * Remove this check once the issues are fixed.
- */
- if (new_crtc_state->bigjoiner_pipes) {
- drm_dbg_kms(&i915->drm,
- "[CRTC:%d:%s] async flip disallowed with bigjoiner\n",
- crtc->base.base.id, crtc->base.name);
- return -EINVAL;
- }
-
for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
new_plane_state, i) {
if (plane->pipe != crtc->pipe)
@@ -6183,6 +6304,101 @@ static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
return 0;
}
+static int intel_atomic_check_config(struct intel_atomic_state *state,
+ struct intel_link_bw_limits *limits,
+ enum pipe *failed_pipe)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_crtc_state *new_crtc_state;
+ struct intel_crtc *crtc;
+ int ret;
+ int i;
+
+ *failed_pipe = INVALID_PIPE;
+
+ ret = intel_bigjoiner_add_affected_crtcs(state);
+ if (ret)
+ return ret;
+
+ ret = intel_fdi_add_affected_crtcs(state);
+ if (ret)
+ return ret;
+
+ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+ if (!intel_crtc_needs_modeset(new_crtc_state)) {
+ if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
+ copy_bigjoiner_crtc_state_nomodeset(state, crtc);
+ else
+ intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
+ continue;
+ }
+
+ if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) {
+ drm_WARN_ON(&i915->drm, new_crtc_state->uapi.enable);
+ continue;
+ }
+
+ ret = intel_crtc_prepare_cleared_state(state, crtc);
+ if (ret)
+ break;
+
+ if (!new_crtc_state->hw.enable)
+ continue;
+
+ ret = intel_modeset_pipe_config(state, crtc, limits);
+ if (ret)
+ break;
+
+ ret = intel_atomic_check_bigjoiner(state, crtc);
+ if (ret)
+ break;
+ }
+
+ if (ret)
+ *failed_pipe = crtc->pipe;
+
+ return ret;
+}
+
+static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_link_bw_limits new_limits;
+ struct intel_link_bw_limits old_limits;
+ int ret;
+
+ intel_link_bw_init_limits(i915, &new_limits);
+ old_limits = new_limits;
+
+ while (true) {
+ enum pipe failed_pipe;
+
+ ret = intel_atomic_check_config(state, &new_limits,
+ &failed_pipe);
+ if (ret) {
+ /*
+ * The bpp limit for a pipe is below the minimum it supports, set the
+ * limit to the minimum and recalculate the config.
+ */
+ if (ret == -EINVAL &&
+ intel_link_bw_set_bpp_limit_for_pipe(state,
+ &old_limits,
+ &new_limits,
+ failed_pipe))
+ continue;
+
+ break;
+ }
+
+ old_limits = new_limits;
+
+ ret = intel_link_bw_atomic_check(state, &new_limits);
+ if (ret != -EAGAIN)
+ break;
+ }
+
+ return ret;
+}
/**
* intel_atomic_check - validate state object
* @dev: drm device
@@ -6227,43 +6443,12 @@ int intel_atomic_check(struct drm_device *dev,
return ret;
}
- ret = intel_bigjoiner_add_affected_crtcs(state);
+ ret = intel_atomic_check_config_and_link(state);
if (ret)
goto fail;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
- if (!intel_crtc_needs_modeset(new_crtc_state)) {
- if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
- copy_bigjoiner_crtc_state_nomodeset(state, crtc);
- else
- intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
- continue;
- }
-
- if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) {
- drm_WARN_ON(&dev_priv->drm, new_crtc_state->uapi.enable);
- continue;
- }
-
- ret = intel_crtc_prepare_cleared_state(state, crtc);
- if (ret)
- goto fail;
-
- if (!new_crtc_state->hw.enable)
- continue;
-
- ret = intel_modeset_pipe_config(state, crtc);
- if (ret)
- goto fail;
-
- ret = intel_atomic_check_bigjoiner(state, crtc);
- if (ret)
- goto fail;
- }
-
- for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
- new_crtc_state, i) {
if (!intel_crtc_needs_modeset(new_crtc_state))
continue;
@@ -6297,6 +6482,8 @@ int intel_atomic_check(struct drm_device *dev,
if (intel_cpu_transcoders_need_modeset(state, BIT(master))) {
new_crtc_state->uapi.mode_changed = true;
new_crtc_state->update_pipe = false;
+ new_crtc_state->update_m_n = false;
+ new_crtc_state->update_lrr = false;
}
}
@@ -6309,6 +6496,8 @@ int intel_atomic_check(struct drm_device *dev,
if (intel_cpu_transcoders_need_modeset(state, trans)) {
new_crtc_state->uapi.mode_changed = true;
new_crtc_state->update_pipe = false;
+ new_crtc_state->update_m_n = false;
+ new_crtc_state->update_lrr = false;
}
}
@@ -6316,6 +6505,8 @@ int intel_atomic_check(struct drm_device *dev,
if (intel_pipes_need_modeset(state, new_crtc_state->bigjoiner_pipes)) {
new_crtc_state->uapi.mode_changed = true;
new_crtc_state->update_pipe = false;
+ new_crtc_state->update_m_n = false;
+ new_crtc_state->update_lrr = false;
}
}
}
@@ -6494,9 +6685,12 @@ static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
hsw_set_linetime_wm(new_crtc_state);
- if (new_crtc_state->seamless_m_n)
+ if (new_crtc_state->update_m_n)
intel_cpu_transcoder_set_m1_n1(crtc, new_crtc_state->cpu_transcoder,
&new_crtc_state->dp_m_n);
+
+ if (new_crtc_state->update_lrr)
+ intel_set_transcoder_timings_lrr(new_crtc_state);
}
static void commit_pipe_pre_planes(struct intel_atomic_state *state,
@@ -6533,6 +6727,8 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@@ -6544,6 +6740,9 @@ static void commit_pipe_post_planes(struct intel_atomic_state *state,
if (DISPLAY_VER(dev_priv) >= 9 &&
!intel_crtc_needs_modeset(new_crtc_state))
skl_detach_scalers(new_crtc_state);
+
+ if (vrr_enabling(old_crtc_state, new_crtc_state))
+ intel_vrr_enable(new_crtc_state);
}
static void intel_enable_crtc(struct intel_atomic_state *state,
@@ -6584,12 +6783,6 @@ static void intel_update_crtc(struct intel_atomic_state *state,
intel_dpt_configure(crtc);
}
- if (vrr_enabling(old_crtc_state, new_crtc_state)) {
- intel_vrr_enable(new_crtc_state);
- intel_crtc_update_active_timings(new_crtc_state,
- new_crtc_state->vrr.enable);
- }
-
if (!modeset) {
if (new_crtc_state->preload_luts &&
intel_crtc_needs_color_update(new_crtc_state))
@@ -6603,6 +6796,9 @@ static void intel_update_crtc(struct intel_atomic_state *state,
if (DISPLAY_VER(i915) >= 11 &&
intel_crtc_needs_fastset(new_crtc_state))
icl_set_pipe_chicken(new_crtc_state);
+
+ if (vrr_params_changed(old_crtc_state, new_crtc_state))
+ intel_vrr_set_transcoder_timings(new_crtc_state);
}
intel_fbc_update(state, crtc);
@@ -6616,7 +6812,7 @@ static void intel_update_crtc(struct intel_atomic_state *state,
intel_crtc_planes_update_noarm(state, crtc);
/* Perform vblank evasion around commit operation */
- intel_pipe_update_start(new_crtc_state);
+ intel_pipe_update_start(state, crtc);
commit_pipe_pre_planes(state, crtc);
@@ -6624,7 +6820,17 @@ static void intel_update_crtc(struct intel_atomic_state *state,
commit_pipe_post_planes(state, crtc);
- intel_pipe_update_end(new_crtc_state);
+ intel_pipe_update_end(state, crtc);
+
+ /*
+ * VRR/Seamless M/N update may need to update frame timings.
+ *
+ * FIXME Should be synchronized with the start of vblank somehow...
+ */
+ if (vrr_enabling(old_crtc_state, new_crtc_state) ||
+ new_crtc_state->update_m_n || new_crtc_state->update_lrr)
+ intel_crtc_update_active_timings(new_crtc_state,
+ new_crtc_state->vrr.enable);
/*
* We usually enable FIFO underrun interrupts as part of the
@@ -7033,7 +7239,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_set_cdclk_pre_plane_update(state);
- intel_modeset_verify_disabled(dev_priv, state);
+ intel_modeset_verify_disabled(state);
}
intel_sagv_pre_plane_update(state);
@@ -7085,6 +7291,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
if (new_crtc_state->do_async_flip)
intel_crtc_disable_flip_done(state, crtc);
+
+ intel_color_wait_commit(new_crtc_state);
}
/*
@@ -7111,14 +7319,13 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
}
intel_dbuf_post_plane_update(state);
- intel_psr_post_plane_update(state);
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
intel_post_plane_update(state, crtc);
intel_modeset_put_crtc_power_domains(crtc, &put_domains[crtc->pipe]);
- intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state);
+ intel_modeset_verify_crtc(state, crtc);
/* Must be done after gamma readout due to HSW split gamma vs. IPS w/a */
hsw_ips_post_update(state, crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 13b0904d42..a05c7e2b78 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -190,8 +190,6 @@ enum aux_ch {
AUX_CH_E_XELPD,
};
-#define aux_ch_name(a) ((a) + 'A')
-
enum phy {
PHY_NONE = -1,
@@ -516,8 +514,10 @@ void intel_plane_fixup_bitmasks(struct intel_crtc_state *crtc_state);
void intel_update_watermarks(struct drm_i915_private *i915);
/* modesetting */
-int intel_modeset_all_pipes(struct intel_atomic_state *state,
- const char *reason);
+int intel_modeset_pipes_in_mask_early(struct intel_atomic_state *state,
+ const char *reason, u8 pipe_mask);
+int intel_modeset_all_pipes_late(struct intel_atomic_state *state,
+ const char *reason);
void intel_modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state,
struct intel_power_domain_mask *old_domains);
void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index 53e5c33e08..ccfe27630f 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -175,6 +175,9 @@ struct intel_hotplug {
/* Whether or not to count short HPD IRQs in HPD storms */
u8 hpd_short_storm_enabled;
+ /* Last state reported by oob_hotplug_event for each encoder */
+ unsigned long oob_hotplug_last_state;
+
/*
* if we get a HPD irq from DP and a HPD irq from non-DP
* the non-DP HPD could block the workqueue on a mode config
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 63c1fb9e47..2836826f8c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -43,12 +43,16 @@ static int i915_frontbuffer_tracking(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
+ spin_lock(&dev_priv->display.fb_tracking.lock);
+
seq_printf(m, "FB tracking busy bits: 0x%08x\n",
dev_priv->display.fb_tracking.busy_bits);
seq_printf(m, "FB tracking flip bits: 0x%08x\n",
dev_priv->display.fb_tracking.flip_bits);
+ spin_unlock(&dev_priv->display.fb_tracking.lock);
+
return 0;
}
@@ -233,14 +237,13 @@ static void intel_dp_info(struct seq_file *m, struct intel_connector *connector)
{
struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
- const struct edid *edid = drm_edid_raw(connector->detect_edid);
seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
seq_printf(m, "\taudio support: %s\n",
str_yes_no(connector->base.display_info.has_audio));
drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
- edid, &intel_dp->aux);
+ connector->detect_edid, &intel_dp->aux);
}
static void intel_dp_mst_info(struct seq_file *m,
@@ -641,6 +644,7 @@ static int i915_display_info(struct seq_file *m, void *unused)
static int i915_shared_dplls_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
+ struct intel_shared_dpll *pll;
int i;
drm_modeset_lock_all(&dev_priv->drm);
@@ -649,11 +653,9 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
dev_priv->display.dpll.ref_clks.nssc,
dev_priv->display.dpll.ref_clks.ssc);
- for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) {
- struct intel_shared_dpll *pll = &dev_priv->display.dpll.shared_dplls[i];
-
- seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->info->name,
- pll->info->id);
+ for_each_shared_dpll(dev_priv, pll, i) {
+ seq_printf(m, "DPLL%i: %s, id: %i\n", pll->index,
+ pll->info->name, pll->info->id);
seq_printf(m, " pipe_mask: 0x%x, active: 0x%x, on: %s\n",
pll->state.pipe_mask, pll->active_mask,
str_yes_no(pll->on));
@@ -1189,8 +1191,8 @@ DEFINE_SHOW_ATTRIBUTE(i915_lpsp_capability);
static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
{
- struct drm_connector *connector = m->private;
- struct drm_device *dev = connector->dev;
+ struct intel_connector *connector = to_intel_connector(m->private);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct drm_crtc *crtc;
struct intel_dp *intel_dp;
struct drm_modeset_acquire_ctx ctx;
@@ -1202,7 +1204,7 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
do {
try_again = false;
- ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
+ ret = drm_modeset_lock(&i915->drm.mode_config.connection_mutex,
&ctx);
if (ret) {
if (ret == -EDEADLK && !drm_modeset_backoff(&ctx)) {
@@ -1211,8 +1213,8 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
}
break;
}
- crtc = connector->state->crtc;
- if (connector->status != connector_status_connected || !crtc) {
+ crtc = connector->base.state->crtc;
+ if (connector->base.status != connector_status_connected || !crtc) {
ret = -ENODEV;
break;
}
@@ -1227,24 +1229,24 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
} else if (ret) {
break;
}
- intel_dp = intel_attached_dp(to_intel_connector(connector));
+ intel_dp = intel_attached_dp(connector);
crtc_state = to_intel_crtc_state(crtc->state);
seq_printf(m, "DSC_Enabled: %s\n",
str_yes_no(crtc_state->dsc.compression_enable));
seq_printf(m, "DSC_Sink_Support: %s\n",
- str_yes_no(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)));
+ str_yes_no(drm_dp_sink_supports_dsc(connector->dp.dsc_dpcd)));
seq_printf(m, "DSC_Output_Format_Sink_Support: RGB: %s YCBCR420: %s YCBCR444: %s\n",
- str_yes_no(drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd,
+ str_yes_no(drm_dp_dsc_sink_supports_format(connector->dp.dsc_dpcd,
DP_DSC_RGB)),
- str_yes_no(drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd,
+ str_yes_no(drm_dp_dsc_sink_supports_format(connector->dp.dsc_dpcd,
DP_DSC_YCbCr420_Native)),
- str_yes_no(drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd,
+ str_yes_no(drm_dp_dsc_sink_supports_format(connector->dp.dsc_dpcd,
DP_DSC_YCbCr444)));
seq_printf(m, "Force_DSC_Enable: %s\n",
str_yes_no(intel_dp->force_dsc_en));
if (!intel_dp_is_edp(intel_dp))
seq_printf(m, "FEC_Sink_Support: %s\n",
- str_yes_no(drm_dp_sink_supports_fec(intel_dp->fec_capable)));
+ str_yes_no(drm_dp_sink_supports_fec(connector->dp.fec_capability)));
} while (try_again);
drm_modeset_drop_locks(&ctx);
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c
index c39f8a15d8..2b1ec23ba9 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.c
+++ b/drivers/gpu/drm/i915/display/intel_display_device.c
@@ -710,18 +710,61 @@ static const struct intel_display_device_info xe_hpd_display = {
BIT(PORT_TC1),
};
+#define XE_LPDP_FEATURES \
+ .abox_mask = GENMASK(1, 0), \
+ .color = { \
+ .degamma_lut_size = 129, .gamma_lut_size = 1024, \
+ .degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \
+ DRM_COLOR_LUT_EQUAL_CHANNELS, \
+ }, \
+ .dbuf.size = 4096, \
+ .dbuf.slice_mask = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | \
+ BIT(DBUF_S4), \
+ .has_cdclk_crawl = 1, \
+ .has_cdclk_squash = 1, \
+ .has_ddi = 1, \
+ .has_dp_mst = 1, \
+ .has_dsb = 1, \
+ .has_fpga_dbg = 1, \
+ .has_hotplug = 1, \
+ .has_ipc = 1, \
+ .has_psr = 1, \
+ .pipe_offsets = { \
+ [TRANSCODER_A] = PIPE_A_OFFSET, \
+ [TRANSCODER_B] = PIPE_B_OFFSET, \
+ [TRANSCODER_C] = PIPE_C_OFFSET, \
+ [TRANSCODER_D] = PIPE_D_OFFSET, \
+ }, \
+ .trans_offsets = { \
+ [TRANSCODER_A] = TRANSCODER_A_OFFSET, \
+ [TRANSCODER_B] = TRANSCODER_B_OFFSET, \
+ [TRANSCODER_C] = TRANSCODER_C_OFFSET, \
+ [TRANSCODER_D] = TRANSCODER_D_OFFSET, \
+ }, \
+ TGL_CURSOR_OFFSETS, \
+ \
+ .__runtime_defaults.cpu_transcoder_mask = \
+ BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | \
+ BIT(TRANSCODER_C) | BIT(TRANSCODER_D), \
+ .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B), \
+ .__runtime_defaults.has_dmc = 1, \
+ .__runtime_defaults.has_dsc = 1, \
+ .__runtime_defaults.has_hdcp = 1, \
+ .__runtime_defaults.pipe_mask = \
+ BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), \
+ .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | \
+ BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4)
+
static const struct intel_display_device_info xe_lpdp_display = {
- XE_LPD_FEATURES,
- .has_cdclk_crawl = 1,
- .has_cdclk_squash = 1,
+ XE_LPDP_FEATURES,
+};
- .__runtime_defaults.ip.ver = 14,
- .__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B),
- .__runtime_defaults.cpu_transcoder_mask =
- BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
- BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
- .__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) |
- BIT(PORT_TC1) | BIT(PORT_TC2) | BIT(PORT_TC3) | BIT(PORT_TC4),
+static const struct intel_display_device_info xe2_lpd_display = {
+ XE_LPDP_FEATURES,
+
+ .__runtime_defaults.fbc_mask =
+ BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B) |
+ BIT(INTEL_FBC_C) | BIT(INTEL_FBC_D),
};
/*
@@ -803,6 +846,7 @@ static const struct {
const struct intel_display_device_info *display;
} gmdid_display_map[] = {
{ 14, 0, &xe_lpdp_display },
+ { 20, 0, &xe2_lpd_display },
};
static const struct intel_display_device_info *
@@ -850,16 +894,12 @@ probe_gmdid_display(struct drm_i915_private *i915, u16 *ver, u16 *rel, u16 *step
return &no_display;
}
-const struct intel_display_device_info *
-intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid,
- u16 *gmdid_ver, u16 *gmdid_rel, u16 *gmdid_step)
+static const struct intel_display_device_info *
+probe_display(struct drm_i915_private *i915)
{
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
int i;
- if (has_gmdid)
- return probe_gmdid_display(i915, gmdid_ver, gmdid_rel, gmdid_step);
-
if (has_no_display(pdev)) {
drm_dbg_kms(&i915->drm, "Device doesn't have display\n");
return &no_display;
@@ -876,7 +916,30 @@ intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid,
return &no_display;
}
-void intel_display_device_info_runtime_init(struct drm_i915_private *i915)
+void intel_display_device_probe(struct drm_i915_private *i915)
+{
+ const struct intel_display_device_info *info;
+ u16 ver, rel, step;
+
+ if (HAS_GMD_ID(i915))
+ info = probe_gmdid_display(i915, &ver, &rel, &step);
+ else
+ info = probe_display(i915);
+
+ DISPLAY_INFO(i915) = info;
+
+ memcpy(DISPLAY_RUNTIME_INFO(i915),
+ &DISPLAY_INFO(i915)->__runtime_defaults,
+ sizeof(*DISPLAY_RUNTIME_INFO(i915)));
+
+ if (HAS_GMD_ID(i915)) {
+ DISPLAY_RUNTIME_INFO(i915)->ip.ver = ver;
+ DISPLAY_RUNTIME_INFO(i915)->ip.rel = rel;
+ DISPLAY_RUNTIME_INFO(i915)->ip.step = step;
+ }
+}
+
+static void __intel_display_device_info_runtime_init(struct drm_i915_private *i915)
{
struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(i915);
enum pipe pipe;
@@ -885,6 +948,13 @@ void intel_display_device_info_runtime_init(struct drm_i915_private *i915)
BUILD_BUG_ON(BITS_PER_TYPE(display_runtime->cpu_transcoder_mask) < I915_MAX_TRANSCODERS);
BUILD_BUG_ON(BITS_PER_TYPE(display_runtime->port_mask) < I915_MAX_PORTS);
+ /* This covers both ULT and ULX */
+ if (IS_HASWELL_ULT(i915) || IS_BROADWELL_ULT(i915))
+ display_runtime->port_mask &= ~BIT(PORT_D);
+
+ if (IS_ICL_WITH_PORT_F(i915))
+ display_runtime->port_mask |= BIT(PORT_F);
+
/* Wa_14011765242: adl-s A0,A1 */
if (IS_ALDERLAKE_S(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_A2))
for_each_pipe(i915, pipe)
@@ -970,16 +1040,19 @@ void intel_display_device_info_runtime_init(struct drm_i915_private *i915)
if (dfsm & SKL_DFSM_PIPE_B_DISABLE) {
display_runtime->pipe_mask &= ~BIT(PIPE_B);
display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_B);
+ display_runtime->fbc_mask &= ~BIT(INTEL_FBC_B);
}
if (dfsm & SKL_DFSM_PIPE_C_DISABLE) {
display_runtime->pipe_mask &= ~BIT(PIPE_C);
display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_C);
+ display_runtime->fbc_mask &= ~BIT(INTEL_FBC_C);
}
if (DISPLAY_VER(i915) >= 12 &&
(dfsm & TGL_DFSM_PIPE_D_DISABLE)) {
display_runtime->pipe_mask &= ~BIT(PIPE_D);
display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_D);
+ display_runtime->fbc_mask &= ~BIT(INTEL_FBC_D);
}
if (!display_runtime->pipe_mask)
@@ -999,12 +1072,44 @@ void intel_display_device_info_runtime_init(struct drm_i915_private *i915)
display_runtime->has_dsc = 0;
}
+ if (DISPLAY_VER(i915) >= 20) {
+ u32 cap = intel_de_read(i915, XE2LPD_DE_CAP);
+
+ if (REG_FIELD_GET(XE2LPD_DE_CAP_DSC_MASK, cap) ==
+ XE2LPD_DE_CAP_DSC_REMOVED)
+ display_runtime->has_dsc = 0;
+
+ if (REG_FIELD_GET(XE2LPD_DE_CAP_SCALER_MASK, cap) ==
+ XE2LPD_DE_CAP_SCALER_SINGLE) {
+ for_each_pipe(i915, pipe)
+ if (display_runtime->num_scalers[pipe])
+ display_runtime->num_scalers[pipe] = 1;
+ }
+ }
+
return;
display_fused_off:
memset(display_runtime, 0, sizeof(*display_runtime));
}
+void intel_display_device_info_runtime_init(struct drm_i915_private *i915)
+{
+ if (HAS_DISPLAY(i915))
+ __intel_display_device_info_runtime_init(i915);
+
+ /* Display may have been disabled by runtime init */
+ if (!HAS_DISPLAY(i915)) {
+ i915->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC);
+ i915->display.info.__device_info = &no_display;
+ }
+
+ /* Disable nuclear pageflip by default on pre-g4x */
+ if (!i915->params.nuclear_pageflip &&
+ DISPLAY_VER(i915) < 5 && !IS_G4X(i915))
+ i915->drm.driver_features &= ~DRIVER_ATOMIC;
+}
+
void intel_display_device_info_print(const struct intel_display_device_info *info,
const struct intel_display_runtime_info *runtime,
struct drm_printer *p)
@@ -1025,3 +1130,20 @@ void intel_display_device_info_print(const struct intel_display_device_info *inf
drm_printf(p, "has_dmc: %s\n", str_yes_no(runtime->has_dmc));
drm_printf(p, "has_dsc: %s\n", str_yes_no(runtime->has_dsc));
}
+
+/*
+ * Assuming the device has display hardware, should it be enabled?
+ *
+ * It's an error to call this function if the device does not have display
+ * hardware.
+ *
+ * Disabling display means taking over the display hardware, putting it to
+ * sleep, and preventing connectors from being connected via any means.
+ */
+bool intel_display_device_enabled(struct drm_i915_private *i915)
+{
+ /* Only valid when HAS_DISPLAY() is true */
+ drm_WARN_ON(&i915->drm, !HAS_DISPLAY(i915));
+
+ return !i915->params.disable_display && !intel_opregion_headless_sku(i915);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
index 215e682bd8..5b5c0e5330 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.h
+++ b/drivers/gpu/drm/i915/display/intel_display_device.h
@@ -32,6 +32,7 @@ struct drm_printer;
func(overlay_needs_physical); \
func(supports_tv);
+#define HAS_4TILE(i915) (IS_DG2(i915) || DISPLAY_VER(i915) >= 14)
#define HAS_ASYNC_FLIPS(i915) (DISPLAY_VER(i915) >= 5)
#define HAS_CDCLK_CRAWL(i915) (DISPLAY_INFO(i915)->has_cdclk_crawl)
#define HAS_CDCLK_SQUASH(i915) (DISPLAY_INFO(i915)->has_cdclk_squash)
@@ -55,6 +56,7 @@ struct drm_printer;
#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915))
#define HAS_IPC(i915) (DISPLAY_INFO(i915)->has_ipc)
#define HAS_IPS(i915) (IS_HASWELL_ULT(i915) || IS_BROADWELL(i915))
+#define HAS_LRR(i915) (DISPLAY_VER(i915) >= 12)
#define HAS_LSPCON(i915) (IS_DISPLAY_VER(i915, 9, 10))
#define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14)
#define HAS_MSO(i915) (DISPLAY_VER(i915) >= 12)
@@ -71,6 +73,40 @@ struct drm_printer;
#define OVERLAY_NEEDS_PHYSICAL(i915) (DISPLAY_INFO(i915)->overlay_needs_physical)
#define SUPPORTS_TV(i915) (DISPLAY_INFO(i915)->supports_tv)
+/* Check that device has a display IP version within the specific range. */
+#define IS_DISPLAY_IP_RANGE(__i915, from, until) ( \
+ BUILD_BUG_ON_ZERO((from) < IP_VER(2, 0)) + \
+ (DISPLAY_VER_FULL(__i915) >= (from) && \
+ DISPLAY_VER_FULL(__i915) <= (until)))
+
+/*
+ * Check if a device has a specific IP version as well as a stepping within the
+ * specified range [from, until). The lower bound is inclusive, the upper
+ * bound is exclusive. The most common use-case of this macro is for checking
+ * bounds for workarounds, which usually have a stepping ("from") at which the
+ * hardware issue is first present and another stepping ("until") at which a
+ * hardware fix is present and the software workaround is no longer necessary.
+ * E.g.,
+ *
+ * IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_B2)
+ * IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_C0, STEP_FOREVER)
+ *
+ * "STEP_FOREVER" can be passed as "until" for workarounds that have no upper
+ * stepping bound for the specified IP version.
+ */
+#define IS_DISPLAY_IP_STEP(__i915, ipver, from, until) \
+ (IS_DISPLAY_IP_RANGE((__i915), (ipver), (ipver)) && \
+ IS_DISPLAY_STEP((__i915), (from), (until)))
+
+#define DISPLAY_INFO(i915) ((i915)->display.info.__device_info)
+#define DISPLAY_RUNTIME_INFO(i915) (&(i915)->display.info.__runtime_info)
+
+#define DISPLAY_VER(i915) (DISPLAY_RUNTIME_INFO(i915)->ip.ver)
+#define DISPLAY_VER_FULL(i915) IP_VER(DISPLAY_RUNTIME_INFO(i915)->ip.ver, \
+ DISPLAY_RUNTIME_INFO(i915)->ip.rel)
+#define IS_DISPLAY_VER(i915, from, until) \
+ (DISPLAY_VER(i915) >= (from) && DISPLAY_VER(i915) <= (until))
+
struct intel_display_runtime_info {
struct {
u16 ver;
@@ -123,9 +159,8 @@ struct intel_display_device_info {
} color;
};
-const struct intel_display_device_info *
-intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid,
- u16 *ver, u16 *rel, u16 *step);
+bool intel_display_device_enabled(struct drm_i915_private *i915);
+void intel_display_device_probe(struct drm_i915_private *i915);
void intel_display_device_info_runtime_init(struct drm_i915_private *i915);
void intel_display_device_info_print(const struct intel_display_device_info *info,
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c
index 8f144d4d3c..44b59ac301 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -31,6 +31,7 @@
#include "intel_display_irq.h"
#include "intel_display_power.h"
#include "intel_display_types.h"
+#include "intel_display_wa.h"
#include "intel_dkl_phy.h"
#include "intel_dmc.h"
#include "intel_dp.h"
@@ -88,6 +89,8 @@ void intel_display_driver_init_hw(struct drm_i915_private *i915)
intel_update_cdclk(i915);
intel_cdclk_dump_config(i915, &i915->display.cdclk.hw, "Current CDCLK");
cdclk_state->logical = cdclk_state->actual = i915->display.cdclk.hw;
+
+ intel_display_wa_apply(i915);
}
static const struct drm_mode_config_funcs intel_mode_funcs = {
@@ -377,6 +380,8 @@ int intel_display_driver_probe(struct drm_i915_private *i915)
void intel_display_driver_register(struct drm_i915_private *i915)
{
+ struct drm_printer p = drm_debug_printer("i915 display info:");
+
if (!HAS_DISPLAY(i915))
return;
@@ -404,6 +409,9 @@ void intel_display_driver_register(struct drm_i915_private *i915)
* fbdev->async_cookie.
*/
drm_kms_helper_poll_init(&i915->drm);
+
+ intel_display_device_info_print(DISPLAY_INFO(i915),
+ DISPLAY_RUNTIME_INFO(i915), &p);
}
/* part #1: call before irq uninstall */
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c
index 62ce554755..bff4a76310 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
@@ -792,7 +792,9 @@ static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
{
u32 mask;
- if (DISPLAY_VER(dev_priv) >= 14)
+ if (DISPLAY_VER(dev_priv) >= 20)
+ return 0;
+ else if (DISPLAY_VER(dev_priv) >= 14)
return TGL_DE_PORT_AUX_DDIA |
TGL_DE_PORT_AUX_DDIB;
else if (DISPLAY_VER(dev_priv) >= 13)
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index 9e01054c24..e25785ae1c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -186,8 +186,6 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
return "GMBUS";
case POWER_DOMAIN_INIT:
return "INIT";
- case POWER_DOMAIN_MODESET:
- return "MODESET";
case POWER_DOMAIN_GT_IRQ:
return "GT_IRQ";
case POWER_DOMAIN_DC_OFF:
@@ -218,7 +216,7 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well;
bool is_enabled;
- if (dev_priv->runtime_pm.suspended)
+ if (pm_runtime_suspended(dev_priv->drm.dev))
return false;
is_enabled = true;
@@ -338,8 +336,6 @@ unlock:
mutex_unlock(&power_domains->lock);
}
-#define POWER_DOMAIN_MASK (GENMASK_ULL(POWER_DOMAIN_NUM - 1, 0))
-
static void __async_put_domains_mask(struct i915_power_domains *power_domains,
struct intel_power_domain_mask *mask)
{
@@ -947,7 +943,9 @@ static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
if (!HAS_DISPLAY(dev_priv))
return 0;
- if (IS_DG2(dev_priv))
+ if (DISPLAY_VER(dev_priv) >= 20)
+ max_dc = 2;
+ else if (IS_DG2(dev_priv))
max_dc = 1;
else if (IS_DG1(dev_priv))
max_dc = 3;
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
index d3b5d04b7b..d6c2a5846b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power.h
@@ -108,7 +108,6 @@ enum intel_display_power_domain {
POWER_DOMAIN_AUX_TBT6,
POWER_DOMAIN_GMBUS,
- POWER_DOMAIN_MODESET,
POWER_DOMAIN_GT_IRQ,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_TC_COLD_OFF,
diff --git a/drivers/gpu/drm/i915/display/intel_display_power_map.c b/drivers/gpu/drm/i915/display/intel_display_power_map.c
index 5ad04cd42c..10948b3964 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_map.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c
@@ -332,7 +332,6 @@ I915_DECL_PW_DOMAINS(skl_pwdoms_pw_2,
I915_DECL_PW_DOMAINS(skl_pwdoms_dc_off,
SKL_PW_2_POWER_DOMAINS,
POWER_DOMAIN_AUX_A,
- POWER_DOMAIN_MODESET,
POWER_DOMAIN_GT_IRQ,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
@@ -437,7 +436,6 @@ I915_DECL_PW_DOMAINS(bxt_pwdoms_dc_off,
BXT_PW_2_POWER_DOMAINS,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_GMBUS,
- POWER_DOMAIN_MODESET,
POWER_DOMAIN_GT_IRQ,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
@@ -519,7 +517,6 @@ I915_DECL_PW_DOMAINS(glk_pwdoms_dc_off,
GLK_PW_2_POWER_DOMAINS,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_GMBUS,
- POWER_DOMAIN_MODESET,
POWER_DOMAIN_GT_IRQ,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
@@ -685,7 +682,6 @@ I915_DECL_PW_DOMAINS(icl_pwdoms_pw_2,
I915_DECL_PW_DOMAINS(icl_pwdoms_dc_off,
ICL_PW_2_POWER_DOMAINS,
POWER_DOMAIN_AUX_A,
- POWER_DOMAIN_MODESET,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
@@ -861,7 +857,6 @@ I915_DECL_PW_DOMAINS(tgl_pwdoms_dc_off,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
- POWER_DOMAIN_MODESET,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
@@ -1058,7 +1053,6 @@ I915_DECL_PW_DOMAINS(rkl_pwdoms_dc_off,
RKL_PW_3_POWER_DOMAINS,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_AUX_B,
- POWER_DOMAIN_MODESET,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
@@ -1141,7 +1135,6 @@ I915_DECL_PW_DOMAINS(dg1_pwdoms_dc_off,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_AUX_B,
- POWER_DOMAIN_MODESET,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
@@ -1311,7 +1304,6 @@ I915_DECL_PW_DOMAINS(xelpd_pwdoms_dc_off,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_AUX_B,
- POWER_DOMAIN_MODESET,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
@@ -1426,7 +1418,6 @@ I915_DECL_PW_DOMAINS(xehpd_pwdoms_dc_off,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_AUX_B,
- POWER_DOMAIN_MODESET,
POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
@@ -1545,6 +1536,56 @@ static const struct i915_power_well_desc_list xelpdp_power_wells[] = {
I915_PW_DESCRIPTORS(xelpdp_power_wells_main),
};
+I915_DECL_PW_DOMAINS(xe2lpd_pwdoms_pica_tc,
+ POWER_DOMAIN_PORT_DDI_LANES_TC1,
+ POWER_DOMAIN_PORT_DDI_LANES_TC2,
+ POWER_DOMAIN_PORT_DDI_LANES_TC3,
+ POWER_DOMAIN_PORT_DDI_LANES_TC4,
+ POWER_DOMAIN_AUX_USBC1,
+ POWER_DOMAIN_AUX_USBC2,
+ POWER_DOMAIN_AUX_USBC3,
+ POWER_DOMAIN_AUX_USBC4,
+ POWER_DOMAIN_AUX_TBT1,
+ POWER_DOMAIN_AUX_TBT2,
+ POWER_DOMAIN_AUX_TBT3,
+ POWER_DOMAIN_AUX_TBT4,
+ POWER_DOMAIN_INIT);
+
+static const struct i915_power_well_desc xe2lpd_power_wells_pica[] = {
+ {
+ .instances = &I915_PW_INSTANCES(I915_PW("PICA_TC",
+ &xe2lpd_pwdoms_pica_tc,
+ .id = DISP_PW_ID_NONE),
+ ),
+ .ops = &xe2lpd_pica_power_well_ops,
+ },
+};
+
+I915_DECL_PW_DOMAINS(xe2lpd_pwdoms_dc_off,
+ POWER_DOMAIN_DC_OFF,
+ XELPD_PW_C_POWER_DOMAINS,
+ XELPD_PW_D_POWER_DOMAINS,
+ POWER_DOMAIN_AUDIO_MMIO,
+ POWER_DOMAIN_INIT);
+
+static const struct i915_power_well_desc xe2lpd_power_wells_dcoff[] = {
+ {
+ .instances = &I915_PW_INSTANCES(
+ I915_PW("DC_off", &xe2lpd_pwdoms_dc_off,
+ .id = SKL_DISP_DC_OFF),
+ ),
+ .ops = &gen9_dc_off_power_well_ops,
+ },
+};
+
+static const struct i915_power_well_desc_list xe2lpd_power_wells[] = {
+ I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
+ I915_PW_DESCRIPTORS(icl_power_wells_pw_1),
+ I915_PW_DESCRIPTORS(xe2lpd_power_wells_dcoff),
+ I915_PW_DESCRIPTORS(xelpdp_power_wells_main),
+ I915_PW_DESCRIPTORS(xe2lpd_power_wells_pica),
+};
+
static void init_power_well_domains(const struct i915_power_well_instance *inst,
struct i915_power_well *power_well)
{
@@ -1652,7 +1693,9 @@ int intel_display_power_map_init(struct i915_power_domains *power_domains)
return 0;
}
- if (DISPLAY_VER(i915) >= 14)
+ if (DISPLAY_VER(i915) >= 20)
+ return set_power_wells(power_domains, xe2lpd_power_wells);
+ else if (DISPLAY_VER(i915) >= 14)
return set_power_wells(power_domains, xelpdp_power_wells);
else if (IS_DG2(i915))
return set_power_wells(power_domains, xehpd_power_wells);
diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c
index 916009894d..07d6500500 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -1794,8 +1794,13 @@ static void xelpdp_aux_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch;
+ enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well);
+
+ if (intel_phy_is_tc(dev_priv, phy))
+ icl_tc_port_assert_ref_held(dev_priv, power_well,
+ aux_ch_to_digital_port(dev_priv, aux_ch));
- intel_de_rmw(dev_priv, XELPDP_DP_AUX_CH_CTL(aux_ch),
+ intel_de_rmw(dev_priv, XELPDP_DP_AUX_CH_CTL(dev_priv, aux_ch),
XELPDP_DP_AUX_CH_CTL_POWER_REQUEST,
XELPDP_DP_AUX_CH_CTL_POWER_REQUEST);
@@ -1813,7 +1818,7 @@ static void xelpdp_aux_power_well_disable(struct drm_i915_private *dev_priv,
{
enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch;
- intel_de_rmw(dev_priv, XELPDP_DP_AUX_CH_CTL(aux_ch),
+ intel_de_rmw(dev_priv, XELPDP_DP_AUX_CH_CTL(dev_priv, aux_ch),
XELPDP_DP_AUX_CH_CTL_POWER_REQUEST,
0);
usleep_range(10, 30);
@@ -1824,10 +1829,44 @@ static bool xelpdp_aux_power_well_enabled(struct drm_i915_private *dev_priv,
{
enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch;
- return intel_de_read(dev_priv, XELPDP_DP_AUX_CH_CTL(aux_ch)) &
+ return intel_de_read(dev_priv, XELPDP_DP_AUX_CH_CTL(dev_priv, aux_ch)) &
XELPDP_DP_AUX_CH_CTL_POWER_STATUS;
}
+static void xe2lpd_pica_power_well_enable(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ intel_de_write(dev_priv, XE2LPD_PICA_PW_CTL,
+ XE2LPD_PICA_CTL_POWER_REQUEST);
+
+ if (intel_de_wait_for_set(dev_priv, XE2LPD_PICA_PW_CTL,
+ XE2LPD_PICA_CTL_POWER_STATUS, 1)) {
+ drm_dbg_kms(&dev_priv->drm, "pica power well enable timeout\n");
+
+ drm_WARN(&dev_priv->drm, 1, "Power well PICA timeout when enabled");
+ }
+}
+
+static void xe2lpd_pica_power_well_disable(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ intel_de_write(dev_priv, XE2LPD_PICA_PW_CTL, 0);
+
+ if (intel_de_wait_for_clear(dev_priv, XE2LPD_PICA_PW_CTL,
+ XE2LPD_PICA_CTL_POWER_STATUS, 1)) {
+ drm_dbg_kms(&dev_priv->drm, "pica power well disable timeout\n");
+
+ drm_WARN(&dev_priv->drm, 1, "Power well PICA timeout when disabled");
+ }
+}
+
+static bool xe2lpd_pica_power_well_enabled(struct drm_i915_private *dev_priv,
+ struct i915_power_well *power_well)
+{
+ return intel_de_read(dev_priv, XE2LPD_PICA_PW_CTL) &
+ XE2LPD_PICA_CTL_POWER_STATUS;
+}
+
const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
.sync_hw = i9xx_power_well_sync_hw_noop,
.enable = i9xx_always_on_power_well_noop,
@@ -1947,3 +1986,10 @@ const struct i915_power_well_ops xelpdp_aux_power_well_ops = {
.disable = xelpdp_aux_power_well_disable,
.is_enabled = xelpdp_aux_power_well_enabled,
};
+
+const struct i915_power_well_ops xe2lpd_pica_power_well_ops = {
+ .sync_hw = i9xx_power_well_sync_hw_noop,
+ .enable = xe2lpd_pica_power_well_enable,
+ .disable = xe2lpd_pica_power_well_disable,
+ .is_enabled = xe2lpd_pica_power_well_enabled,
+};
diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h
index a873658831..9357a9a73c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h
@@ -176,5 +176,6 @@ extern const struct i915_power_well_ops icl_aux_power_well_ops;
extern const struct i915_power_well_ops icl_ddi_power_well_ops;
extern const struct i915_power_well_ops tgl_tc_cold_off_ops;
extern const struct i915_power_well_ops xelpdp_aux_power_well_ops;
+extern const struct i915_power_well_ops xe2lpd_pica_power_well_ops;
#endif
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 7fc92b1474..65ea37fe8c 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -500,15 +500,15 @@ struct intel_hdcp_shim {
enum hdcp_wired_protocol protocol;
/* Detects whether sink is HDCP2.2 capable */
- int (*hdcp_2_2_capable)(struct intel_digital_port *dig_port,
+ int (*hdcp_2_2_capable)(struct intel_connector *connector,
bool *capable);
/* Write HDCP2.2 messages */
- int (*write_2_2_msg)(struct intel_digital_port *dig_port,
+ int (*write_2_2_msg)(struct intel_connector *connector,
void *buf, size_t size);
/* Read HDCP2.2 messages */
- int (*read_2_2_msg)(struct intel_digital_port *dig_port,
+ int (*read_2_2_msg)(struct intel_connector *connector,
u8 msg_id, void *buf, size_t size);
/*
@@ -516,7 +516,7 @@ struct intel_hdcp_shim {
* type to Receivers. In DP HDCP2.2 Stream type is one of the input to
* the HDCP2.2 Cipher for En/De-Cryption. Not applicable for HDMI.
*/
- int (*config_stream_type)(struct intel_digital_port *dig_port,
+ int (*config_stream_type)(struct intel_connector *connector,
bool is_repeater, u8 type);
/* Enable/Disable HDCP 2.2 stream encryption on DP MST Transport Link */
@@ -620,6 +620,12 @@ struct intel_connector {
struct intel_dp *mst_port;
+ struct {
+ struct drm_dp_aux *dsc_decompression_aux;
+ u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
+ u8 fec_capability;
+ } dp;
+
/* Work struct to schedule a uevent on link train failure */
struct work_struct modeset_retry_work;
@@ -1083,6 +1089,8 @@ struct intel_crtc_state {
unsigned fb_bits; /* framebuffers to flip */
bool update_pipe; /* can a fast modeset be performed? */
+ bool update_m_n; /* update M/N seamlessly during fastset? */
+ bool update_lrr; /* update TRANS_VTOTAL/etc. during fastset? */
bool disable_cxsr;
bool update_wm_pre, update_wm_post; /* watermarks are updated */
bool fifo_changed; /* FIFO split is changed */
@@ -1189,13 +1197,13 @@ struct intel_crtc_state {
u32 ctrl, div;
} dsi_pll;
- int pipe_bpp;
+ int max_link_bpp_x16; /* in 1/16 bpp units */
+ int pipe_bpp; /* in 1 bpp units */
struct intel_link_m_n dp_m_n;
/* m2_n2 for eDP downclock */
struct intel_link_m_n dp_m2_n2;
bool has_drrs;
- bool seamless_m_n;
/* PSR is supported but might not be enabled due the lack of enabled planes */
bool has_psr;
@@ -1364,7 +1372,12 @@ struct intel_crtc_state {
bool enhanced_framing;
- /* Forward Error correction State */
+ /*
+ * Forward Error Correction.
+ *
+ * Note: This will be false for 128b/132b, which will always have FEC
+ * enabled automatically.
+ */
bool fec_enable;
bool sdp_split_enable;
@@ -1385,7 +1398,7 @@ struct intel_crtc_state {
/* Variable Refresh Rate state */
struct {
- bool enable;
+ bool enable, in_range;
u8 pipeline_full;
u16 flipline, vmin, vmax, guardband;
} vrr;
@@ -1583,7 +1596,6 @@ struct intel_watermark_params {
struct intel_hdmi {
i915_reg_t hdmi_reg;
- int ddc_bus;
struct {
enum drm_dp_dual_mode_type type;
int max_tmds_clock;
@@ -1713,10 +1725,8 @@ struct intel_dp {
u8 psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
- u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
u8 lttpr_phy_caps[DP_MAX_LTTPR_COUNT][DP_LTTPR_PHY_CAP_SIZE];
- u8 fec_capable;
u8 pcon_dsc_dpcd[DP_PCON_DSC_ENCODER_CAP_SIZE];
/* source rates */
int num_source_rates;
@@ -2110,4 +2120,27 @@ to_intel_frontbuffer(struct drm_framebuffer *fb)
return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
}
+static inline int to_bpp_int(int bpp_x16)
+{
+ return bpp_x16 >> 4;
+}
+
+static inline int to_bpp_frac(int bpp_x16)
+{
+ return bpp_x16 & 0xf;
+}
+
+#define BPP_X16_FMT "%d.%04d"
+#define BPP_X16_ARGS(bpp_x16) to_bpp_int(bpp_x16), (to_bpp_frac(bpp_x16) * 625)
+
+static inline int to_bpp_int_roundup(int bpp_x16)
+{
+ return (bpp_x16 + 0xf) >> 4;
+}
+
+static inline int to_bpp_x16(int bpp)
+{
+ return bpp << 4;
+}
+
#endif /* __INTEL_DISPLAY_TYPES_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c b/drivers/gpu/drm/i915/display/intel_display_wa.c
new file mode 100644
index 0000000000..ac136fd992
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_wa.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "i915_reg.h"
+#include "intel_de.h"
+#include "intel_display_wa.h"
+
+static void gen11_display_wa_apply(struct drm_i915_private *i915)
+{
+ /* Wa_1409120013 */
+ intel_de_write(i915, ILK_DPFC_CHICKEN(INTEL_FBC_A),
+ DPFC_CHICKEN_COMP_DUMMY_PIXEL);
+
+ /* Wa_14010594013 */
+ intel_de_rmw(i915, GEN8_CHICKEN_DCPR_1, 0, ICL_DELAY_PMRSP);
+}
+
+static void xe_d_display_wa_apply(struct drm_i915_private *i915)
+{
+ /* Wa_1409120013 */
+ intel_de_write(i915, ILK_DPFC_CHICKEN(INTEL_FBC_A),
+ DPFC_CHICKEN_COMP_DUMMY_PIXEL);
+
+ /* Wa_14013723622 */
+ intel_de_rmw(i915, CLKREQ_POLICY, CLKREQ_POLICY_MEM_UP_OVRD, 0);
+}
+
+static void adlp_display_wa_apply(struct drm_i915_private *i915)
+{
+ /* Wa_22011091694:adlp */
+ intel_de_rmw(i915, GEN9_CLKGATE_DIS_5, 0, DPCE_GATING_DIS);
+
+ /* Bspec/49189 Initialize Sequence */
+ intel_de_rmw(i915, GEN8_CHICKEN_DCPR_1, DDI_CLOCK_REG_ACCESS, 0);
+}
+
+void intel_display_wa_apply(struct drm_i915_private *i915)
+{
+ if (IS_ALDERLAKE_P(i915))
+ adlp_display_wa_apply(i915);
+ else if (DISPLAY_VER(i915) == 12)
+ xe_d_display_wa_apply(i915);
+ else if (DISPLAY_VER(i915) == 11)
+ gen11_display_wa_apply(i915);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.h b/drivers/gpu/drm/i915/display/intel_display_wa.h
new file mode 100644
index 0000000000..63201d0985
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_wa.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_DISPLAY_WA_H__
+#define __INTEL_DISPLAY_WA_H__
+
+struct drm_i915_private;
+
+void intel_display_wa_apply(struct drm_i915_private *i915);
+
+#endif
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index 8751973b57..073b85b576 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -309,7 +309,7 @@ static const struct stepping_info *
intel_get_stepping_info(struct drm_i915_private *i915,
struct stepping_info *si)
{
- const char *step_name = intel_step_name(RUNTIME_INFO(i915)->step.display_step);
+ const char *step_name = intel_display_step_name(i915);
si->stepping = step_name[0];
si->substepping = step_name[1];
@@ -1037,7 +1037,7 @@ void intel_dmc_init(struct drm_i915_private *i915)
INIT_WORK(&dmc->work, dmc_load_work_fn);
- if (IS_METEORLAKE(i915)) {
+ if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0)) {
dmc->fw_path = MTL_DMC_PATH;
dmc->max_fw_size = XELPDP_DMC_MAX_FW_SIZE;
} else if (IS_DG2(i915)) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 18ee4f2a87..ef09356bcb 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -306,13 +306,13 @@ static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
int source_max = intel_dp_max_source_lane_count(dig_port);
int sink_max = intel_dp->max_sink_lane_count;
- int fia_max = intel_tc_port_fia_max_lane_count(dig_port);
+ int lane_max = intel_tc_port_max_lane_count(dig_port);
int lttpr_max = drm_dp_lttpr_max_lane_count(intel_dp->lttpr_common_caps);
if (lttpr_max)
sink_max = min(sink_max, lttpr_max);
- return min3(source_max, sink_max, fia_max);
+ return min3(source_max, sink_max, lane_max);
}
int intel_dp_max_lane_count(struct intel_dp *intel_dp)
@@ -740,14 +740,41 @@ u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 p
return bits_per_pixel;
}
-u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
- u32 link_clock, u32 lane_count,
- u32 mode_clock, u32 mode_hdisplay,
- bool bigjoiner,
- u32 pipe_bpp,
- u32 timeslots)
+static
+u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915,
+ u32 mode_clock, u32 mode_hdisplay,
+ bool bigjoiner)
{
- u32 bits_per_pixel, max_bpp_small_joiner_ram;
+ u32 max_bpp_small_joiner_ram;
+
+ /* 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) {
+ int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24;
+ /* With bigjoiner multiple dsc engines are used in parallel so PPC is 2 */
+ int ppc = 2;
+ u32 max_bpp_bigjoiner =
+ i915->display.cdclk.max_cdclk_freq * ppc * bigjoiner_interface_bits /
+ intel_dp_mode_to_fec_clock(mode_clock);
+
+ max_bpp_small_joiner_ram *= 2;
+
+ return min(max_bpp_small_joiner_ram, max_bpp_bigjoiner);
+ }
+
+ return max_bpp_small_joiner_ram;
+}
+
+u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
+ u32 link_clock, u32 lane_count,
+ u32 mode_clock, u32 mode_hdisplay,
+ bool bigjoiner,
+ enum intel_output_format output_format,
+ u32 pipe_bpp,
+ u32 timeslots)
+{
+ u32 bits_per_pixel, joiner_max_bpp;
/*
* Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)*
@@ -768,47 +795,39 @@ u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
bits_per_pixel = ((link_clock * lane_count) * timeslots) /
(intel_dp_mode_to_fec_clock(mode_clock) * 8);
+ /* Bandwidth required for 420 is half, that of 444 format */
+ if (output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+ bits_per_pixel *= 2;
+
+ /*
+ * According to DSC 1.2a Section 4.1.1 Table 4.1 the maximum
+ * supported PPS value can be 63.9375 and with the further
+ * mention that for 420, 422 formats, bpp should be programmed double
+ * the target bpp restricting our target bpp to be 31.9375 at max.
+ */
+ if (output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+ bits_per_pixel = min_t(u32, bits_per_pixel, 31);
+
drm_dbg_kms(&i915->drm, "Max link bpp is %u for %u timeslots "
"total bw %u pixel clock %u\n",
bits_per_pixel, timeslots,
(link_clock * lane_count * 8),
intel_dp_mode_to_fec_clock(mode_clock));
- /* 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;
-
- /*
- * Greatest allowed DSC BPP = MIN (output BPP from available Link BW
- * check, output bpp from small joiner RAM check)
- */
- bits_per_pixel = min(bits_per_pixel, max_bpp_small_joiner_ram);
-
- if (bigjoiner) {
- u32 max_bpp_bigjoiner =
- i915->display.cdclk.max_cdclk_freq * 48 /
- intel_dp_mode_to_fec_clock(mode_clock);
-
- bits_per_pixel = min(bits_per_pixel, max_bpp_bigjoiner);
- }
+ joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, mode_clock,
+ mode_hdisplay, bigjoiner);
+ bits_per_pixel = min(bits_per_pixel, joiner_max_bpp);
bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp);
- /*
- * Compressed BPP in U6.4 format so multiply by 16, for Gen 11,
- * fractional part is 0
- */
- return bits_per_pixel << 4;
+ return bits_per_pixel;
}
-u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
+u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
int mode_clock, int mode_hdisplay,
bool bigjoiner)
{
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
u8 min_slice_count, i;
int max_slice_width;
@@ -826,7 +845,7 @@ u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
if (mode_clock >= ((i915->display.cdclk.max_cdclk_freq * 85) / 100))
min_slice_count = max_t(u8, min_slice_count, 2);
- max_slice_width = drm_dp_dsc_sink_max_slice_width(intel_dp->dsc_dpcd);
+ max_slice_width = drm_dp_dsc_sink_max_slice_width(connector->dp.dsc_dpcd);
if (max_slice_width < DP_DSC_MIN_SLICE_WIDTH_VALUE) {
drm_dbg_kms(&i915->drm,
"Unsupported slice width %d by DP DSC Sink device\n",
@@ -843,7 +862,7 @@ u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
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))
+ drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false))
break;
/* big joiner needs small joiner to be enabled */
@@ -916,16 +935,42 @@ dfp_can_convert_from_ycbcr444(struct intel_dp *intel_dp,
return false;
}
+static bool
+dfp_can_convert(struct intel_dp *intel_dp,
+ enum intel_output_format output_format,
+ enum intel_output_format sink_format)
+{
+ switch (output_format) {
+ case INTEL_OUTPUT_FORMAT_RGB:
+ return dfp_can_convert_from_rgb(intel_dp, sink_format);
+ case INTEL_OUTPUT_FORMAT_YCBCR444:
+ return dfp_can_convert_from_ycbcr444(intel_dp, sink_format);
+ default:
+ MISSING_CASE(output_format);
+ return false;
+ }
+
+ return false;
+}
+
static enum intel_output_format
intel_dp_output_format(struct intel_connector *connector,
enum intel_output_format sink_format)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ enum intel_output_format force_dsc_output_format =
+ intel_dp->force_dsc_output_format;
enum intel_output_format output_format;
+ if (force_dsc_output_format) {
+ if (source_can_output(intel_dp, force_dsc_output_format) &&
+ (!drm_dp_is_branch(intel_dp->dpcd) ||
+ sink_format != force_dsc_output_format ||
+ dfp_can_convert(intel_dp, force_dsc_output_format, sink_format)))
+ return force_dsc_output_format;
- if (intel_dp->force_dsc_output_format)
- return intel_dp->force_dsc_output_format;
+ drm_dbg_kms(&i915->drm, "Cannot force DSC output format\n");
+ }
if (sink_format == INTEL_OUTPUT_FORMAT_RGB ||
dfp_can_convert_from_rgb(intel_dp, sink_format))
@@ -951,7 +996,7 @@ int intel_dp_min_bpp(enum intel_output_format output_format)
return 8 * 3;
}
-static int intel_dp_output_bpp(enum intel_output_format output_format, int bpp)
+int intel_dp_output_bpp(enum intel_output_format output_format, int bpp)
{
/*
* bpp value was assumed to RGB format. And YCbCr 4:2:0 output
@@ -1122,7 +1167,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
int target_clock = mode->clock;
int max_rate, mode_rate, max_lanes, max_link_clock;
int max_dotclk = dev_priv->max_dotclk_freq;
- u16 dsc_max_output_bpp = 0;
+ u16 dsc_max_compressed_bpp = 0;
u8 dsc_slice_count = 0;
enum drm_mode_status status;
bool dsc = false, bigjoiner = false;
@@ -1164,40 +1209,46 @@ intel_dp_mode_valid(struct drm_connector *_connector,
intel_dp_mode_min_output_bpp(connector, mode));
if (HAS_DSC(dev_priv) &&
- drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) {
+ drm_dp_sink_supports_dsc(connector->dp.dsc_dpcd)) {
+ enum intel_output_format sink_format, output_format;
+ int pipe_bpp;
+
+ sink_format = intel_dp_sink_format(connector, mode);
+ output_format = intel_dp_output_format(connector, sink_format);
/*
* TBD pass the connector BPC,
* for now U8_MAX so that max BPC on that platform would be picked
*/
- int pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, U8_MAX);
+ pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
/*
* Output bpp is stored in 6.4 format so right shift by 4 to get the
* integer value since we support only integer values of bpp.
*/
if (intel_dp_is_edp(intel_dp)) {
- dsc_max_output_bpp =
- drm_edp_dsc_sink_output_bpp(intel_dp->dsc_dpcd) >> 4;
+ dsc_max_compressed_bpp =
+ drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd) >> 4;
dsc_slice_count =
- drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd,
+ drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd,
true);
- } else if (drm_dp_sink_supports_fec(intel_dp->fec_capable)) {
- dsc_max_output_bpp =
- intel_dp_dsc_get_output_bpp(dev_priv,
- max_link_clock,
- max_lanes,
- target_clock,
- mode->hdisplay,
- bigjoiner,
- pipe_bpp, 64) >> 4;
+ } else if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
+ dsc_max_compressed_bpp =
+ intel_dp_dsc_get_max_compressed_bpp(dev_priv,
+ max_link_clock,
+ max_lanes,
+ target_clock,
+ mode->hdisplay,
+ bigjoiner,
+ output_format,
+ pipe_bpp, 64);
dsc_slice_count =
- intel_dp_dsc_get_slice_count(intel_dp,
+ intel_dp_dsc_get_slice_count(connector,
target_clock,
mode->hdisplay,
bigjoiner);
}
- dsc = dsc_max_output_bpp && dsc_slice_count;
+ dsc = dsc_max_compressed_bpp && dsc_slice_count;
}
/*
@@ -1310,33 +1361,34 @@ bool intel_dp_has_hdmi_sink(struct intel_dp *intel_dp)
static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp,
const struct intel_crtc_state *pipe_config)
{
+ struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- /* On TGL, FEC is supported on all Pipes */
if (DISPLAY_VER(dev_priv) >= 12)
return true;
- if (DISPLAY_VER(dev_priv) == 11 && pipe_config->cpu_transcoder != TRANSCODER_A)
+ if (DISPLAY_VER(dev_priv) == 11 && encoder->port != PORT_A)
return true;
return false;
}
static bool intel_dp_supports_fec(struct intel_dp *intel_dp,
+ const struct intel_connector *connector,
const struct intel_crtc_state *pipe_config)
{
return intel_dp_source_supports_fec(intel_dp, pipe_config) &&
- drm_dp_sink_supports_fec(intel_dp->fec_capable);
+ drm_dp_sink_supports_fec(connector->dp.fec_capability);
}
-static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
+static bool intel_dp_supports_dsc(const struct intel_connector *connector,
const struct intel_crtc_state *crtc_state)
{
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP) && !crtc_state->fec_enable)
return false;
return intel_dsc_source_support(crtc_state) &&
- drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd);
+ drm_dp_sink_supports_dsc(connector->dp.dsc_dpcd);
}
static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
@@ -1423,7 +1475,7 @@ intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
if (intel_dp->compliance.test_data.bpc != 0) {
int bpp = 3 * intel_dp->compliance.test_data.bpc;
- limits->min_bpp = limits->max_bpp = bpp;
+ limits->pipe.min_bpp = limits->pipe.max_bpp = bpp;
pipe_config->dither_force_disable = bpp == 6 * 3;
drm_dbg_kms(&i915->drm, "Setting pipe_bpp to %d\n", bpp);
@@ -1485,10 +1537,12 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
int bpp, i, lane_count, clock = intel_dp_mode_clock(pipe_config, conn_state);
int mode_rate, link_rate, link_avail;
- for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
- int output_bpp = intel_dp_output_bpp(pipe_config->output_format, bpp);
+ for (bpp = to_bpp_int(limits->link.max_bpp_x16);
+ bpp >= to_bpp_int(limits->link.min_bpp_x16);
+ bpp -= 2 * 3) {
+ int link_bpp = intel_dp_output_bpp(pipe_config->output_format, bpp);
- mode_rate = intel_dp_link_required(clock, output_bpp);
+ mode_rate = intel_dp_link_required(clock, link_bpp);
for (i = 0; i < intel_dp->num_common_rates; i++) {
link_rate = intel_dp_common_rate(intel_dp, i);
@@ -1516,20 +1570,34 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
return -EINVAL;
}
-int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc)
+static
+u8 intel_dp_dsc_max_src_input_bpc(struct drm_i915_private *i915)
{
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ /* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
+ if (DISPLAY_VER(i915) >= 12)
+ return 12;
+ if (DISPLAY_VER(i915) == 11)
+ return 10;
+
+ return 0;
+}
+
+int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
+ u8 max_req_bpc)
+{
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
int i, num_bpc;
- u8 dsc_bpc[3] = {0};
+ u8 dsc_bpc[3] = {};
u8 dsc_max_bpc;
- /* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
- if (DISPLAY_VER(i915) >= 12)
- dsc_max_bpc = min_t(u8, 12, max_req_bpc);
- else
- dsc_max_bpc = min_t(u8, 10, max_req_bpc);
+ dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
+
+ if (!dsc_max_bpc)
+ return dsc_max_bpc;
- num_bpc = drm_dp_dsc_sink_supported_input_bpcs(intel_dp->dsc_dpcd,
+ dsc_max_bpc = min_t(u8, dsc_max_bpc, max_req_bpc);
+
+ num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
dsc_bpc);
for (i = 0; i < num_bpc; i++) {
if (dsc_max_bpc >= dsc_bpc[i])
@@ -1539,16 +1607,14 @@ int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc)
return 0;
}
-static int intel_dp_source_dsc_version_minor(struct intel_dp *intel_dp)
+static int intel_dp_source_dsc_version_minor(struct drm_i915_private *i915)
{
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-
return DISPLAY_VER(i915) >= 14 ? 2 : 1;
}
-static int intel_dp_sink_dsc_version_minor(struct intel_dp *intel_dp)
+static int intel_dp_sink_dsc_version_minor(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
{
- return (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & DP_DSC_MINOR_MASK) >>
+ return (dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] & DP_DSC_MINOR_MASK) >>
DP_DSC_MINOR_SHIFT;
}
@@ -1574,11 +1640,10 @@ static int intel_dp_get_slice_height(int vactive)
return 2;
}
-static int intel_dp_dsc_compute_params(struct intel_encoder *encoder,
+static int intel_dp_dsc_compute_params(const struct intel_connector *connector,
struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
u8 line_buf_depth;
int ret;
@@ -1599,17 +1664,17 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder,
return ret;
vdsc_cfg->dsc_version_major =
- (intel_dp->dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
+ (connector->dp.dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT;
vdsc_cfg->dsc_version_minor =
- min(intel_dp_source_dsc_version_minor(intel_dp),
- intel_dp_sink_dsc_version_minor(intel_dp));
+ min(intel_dp_source_dsc_version_minor(i915),
+ intel_dp_sink_dsc_version_minor(connector->dp.dsc_dpcd));
if (vdsc_cfg->convert_rgb)
vdsc_cfg->convert_rgb =
- intel_dp->dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] &
+ connector->dp.dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] &
DP_DSC_RGB;
- line_buf_depth = drm_dp_dsc_sink_line_buf_depth(intel_dp->dsc_dpcd);
+ line_buf_depth = drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd);
if (!line_buf_depth) {
drm_dbg_kms(&i915->drm,
"DSC Sink Line Buffer Depth invalid\n");
@@ -1624,15 +1689,16 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder,
DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth;
vdsc_cfg->block_pred_enable =
- intel_dp->dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] &
+ connector->dp.dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] &
DP_DSC_BLK_PREDICTION_IS_SUPPORTED;
return drm_dsc_compute_rc_parameters(vdsc_cfg);
}
-static bool intel_dp_dsc_supports_format(struct intel_dp *intel_dp,
+static bool intel_dp_dsc_supports_format(const struct intel_connector *connector,
enum intel_output_format output_format)
{
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
u8 sink_dsc_format;
switch (output_format) {
@@ -1643,8 +1709,8 @@ static bool intel_dp_dsc_supports_format(struct intel_dp *intel_dp,
sink_dsc_format = DP_DSC_YCbCr444;
break;
case INTEL_OUTPUT_FORMAT_YCBCR420:
- if (min(intel_dp_source_dsc_version_minor(intel_dp),
- intel_dp_sink_dsc_version_minor(intel_dp)) < 2)
+ if (min(intel_dp_source_dsc_version_minor(i915),
+ intel_dp_sink_dsc_version_minor(connector->dp.dsc_dpcd)) < 2)
return false;
sink_dsc_format = DP_DSC_YCbCr420_Native;
break;
@@ -1652,7 +1718,393 @@ static bool intel_dp_dsc_supports_format(struct intel_dp *intel_dp,
return false;
}
- return drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd, sink_dsc_format);
+ return drm_dp_dsc_sink_supports_format(connector->dp.dsc_dpcd, sink_dsc_format);
+}
+
+static bool is_bw_sufficient_for_dsc_config(u16 compressed_bpp, u32 link_clock,
+ u32 lane_count, u32 mode_clock,
+ enum intel_output_format output_format,
+ int timeslots)
+{
+ u32 available_bw, required_bw;
+
+ available_bw = (link_clock * lane_count * timeslots) / 8;
+ required_bw = compressed_bpp * (intel_dp_mode_to_fec_clock(mode_clock));
+
+ return available_bw > required_bw;
+}
+
+static int dsc_compute_link_config(struct intel_dp *intel_dp,
+ struct intel_crtc_state *pipe_config,
+ struct link_config_limits *limits,
+ u16 compressed_bpp,
+ int timeslots)
+{
+ const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
+ int link_rate, lane_count;
+ int i;
+
+ for (i = 0; i < intel_dp->num_common_rates; i++) {
+ link_rate = intel_dp_common_rate(intel_dp, i);
+ if (link_rate < limits->min_rate || link_rate > limits->max_rate)
+ continue;
+
+ for (lane_count = limits->min_lane_count;
+ lane_count <= limits->max_lane_count;
+ lane_count <<= 1) {
+ if (!is_bw_sufficient_for_dsc_config(compressed_bpp, link_rate, lane_count,
+ adjusted_mode->clock,
+ pipe_config->output_format,
+ timeslots))
+ continue;
+
+ pipe_config->lane_count = lane_count;
+ pipe_config->port_clock = link_rate;
+
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static
+u16 intel_dp_dsc_max_sink_compressed_bppx16(const struct intel_connector *connector,
+ struct intel_crtc_state *pipe_config,
+ int bpc)
+{
+ u16 max_bppx16 = drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd);
+
+ if (max_bppx16)
+ return max_bppx16;
+ /*
+ * If support not given in DPCD 67h, 68h use the Maximum Allowed bit rate
+ * values as given in spec Table 2-157 DP v2.0
+ */
+ switch (pipe_config->output_format) {
+ case INTEL_OUTPUT_FORMAT_RGB:
+ case INTEL_OUTPUT_FORMAT_YCBCR444:
+ return (3 * bpc) << 4;
+ case INTEL_OUTPUT_FORMAT_YCBCR420:
+ return (3 * (bpc / 2)) << 4;
+ default:
+ MISSING_CASE(pipe_config->output_format);
+ break;
+ }
+
+ return 0;
+}
+
+static int dsc_sink_min_compressed_bpp(struct intel_crtc_state *pipe_config)
+{
+ /* From Mandatory bit rate range Support Table 2-157 (DP v2.0) */
+ switch (pipe_config->output_format) {
+ case INTEL_OUTPUT_FORMAT_RGB:
+ case INTEL_OUTPUT_FORMAT_YCBCR444:
+ return 8;
+ case INTEL_OUTPUT_FORMAT_YCBCR420:
+ return 6;
+ default:
+ MISSING_CASE(pipe_config->output_format);
+ break;
+ }
+
+ return 0;
+}
+
+static int dsc_sink_max_compressed_bpp(const struct intel_connector *connector,
+ struct intel_crtc_state *pipe_config,
+ int bpc)
+{
+ return intel_dp_dsc_max_sink_compressed_bppx16(connector,
+ pipe_config, bpc) >> 4;
+}
+
+static int dsc_src_min_compressed_bpp(void)
+{
+ /* Min Compressed bpp supported by source is 8 */
+ return 8;
+}
+
+static int dsc_src_max_compressed_bpp(struct intel_dp *intel_dp)
+{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+ /*
+ * Max Compressed bpp for Gen 13+ is 27bpp.
+ * For earlier platform is 23bpp. (Bspec:49259).
+ */
+ if (DISPLAY_VER(i915) <= 12)
+ return 23;
+ else
+ return 27;
+}
+
+/*
+ * From a list of valid compressed bpps try different compressed bpp and find a
+ * suitable link configuration that can support it.
+ */
+static int
+icl_dsc_compute_link_config(struct intel_dp *intel_dp,
+ struct intel_crtc_state *pipe_config,
+ struct link_config_limits *limits,
+ int dsc_max_bpp,
+ int dsc_min_bpp,
+ int pipe_bpp,
+ int timeslots)
+{
+ int i, ret;
+
+ /* Compressed BPP should be less than the Input DSC bpp */
+ dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
+
+ for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) {
+ if (valid_dsc_bpp[i] < dsc_min_bpp ||
+ valid_dsc_bpp[i] > dsc_max_bpp)
+ break;
+
+ ret = dsc_compute_link_config(intel_dp,
+ pipe_config,
+ limits,
+ valid_dsc_bpp[i],
+ timeslots);
+ if (ret == 0) {
+ pipe_config->dsc.compressed_bpp = valid_dsc_bpp[i];
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * From XE_LPD onwards we supports compression bpps in steps of 1 up to
+ * uncompressed bpp-1. So we start from max compressed bpp and see if any
+ * link configuration is able to support that compressed bpp, if not we
+ * step down and check for lower compressed bpp.
+ */
+static int
+xelpd_dsc_compute_link_config(struct intel_dp *intel_dp,
+ struct intel_crtc_state *pipe_config,
+ struct link_config_limits *limits,
+ int dsc_max_bpp,
+ int dsc_min_bpp,
+ int pipe_bpp,
+ int timeslots)
+{
+ u16 compressed_bpp;
+ int ret;
+
+ /* Compressed BPP should be less than the Input DSC bpp */
+ dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
+
+ for (compressed_bpp = dsc_max_bpp;
+ compressed_bpp >= dsc_min_bpp;
+ compressed_bpp--) {
+ ret = dsc_compute_link_config(intel_dp,
+ pipe_config,
+ limits,
+ compressed_bpp,
+ timeslots);
+ if (ret == 0) {
+ pipe_config->dsc.compressed_bpp = compressed_bpp;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
+ const struct intel_connector *connector,
+ struct intel_crtc_state *pipe_config,
+ struct link_config_limits *limits,
+ int pipe_bpp,
+ int timeslots)
+{
+ const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ int dsc_src_min_bpp, dsc_sink_min_bpp, dsc_min_bpp;
+ int dsc_src_max_bpp, dsc_sink_max_bpp, dsc_max_bpp;
+ int dsc_joiner_max_bpp;
+
+ dsc_src_min_bpp = dsc_src_min_compressed_bpp();
+ dsc_sink_min_bpp = dsc_sink_min_compressed_bpp(pipe_config);
+ dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp);
+ dsc_min_bpp = max(dsc_min_bpp, to_bpp_int_roundup(limits->link.min_bpp_x16));
+
+ dsc_src_max_bpp = dsc_src_max_compressed_bpp(intel_dp);
+ dsc_sink_max_bpp = dsc_sink_max_compressed_bpp(connector, pipe_config, pipe_bpp / 3);
+ dsc_max_bpp = dsc_sink_max_bpp ? min(dsc_sink_max_bpp, dsc_src_max_bpp) : dsc_src_max_bpp;
+
+ dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, adjusted_mode->clock,
+ adjusted_mode->hdisplay,
+ pipe_config->bigjoiner_pipes);
+ dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp);
+ dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
+
+ if (DISPLAY_VER(i915) >= 13)
+ return xelpd_dsc_compute_link_config(intel_dp, pipe_config, limits,
+ dsc_max_bpp, dsc_min_bpp, pipe_bpp, timeslots);
+ return icl_dsc_compute_link_config(intel_dp, pipe_config, limits,
+ dsc_max_bpp, dsc_min_bpp, pipe_bpp, timeslots);
+}
+
+static
+u8 intel_dp_dsc_min_src_input_bpc(struct drm_i915_private *i915)
+{
+ /* Min DSC Input BPC for ICL+ is 8 */
+ return HAS_DSC(i915) ? 8 : 0;
+}
+
+static
+bool is_dsc_pipe_bpp_sufficient(struct drm_i915_private *i915,
+ struct drm_connector_state *conn_state,
+ struct link_config_limits *limits,
+ int pipe_bpp)
+{
+ u8 dsc_max_bpc, dsc_min_bpc, dsc_max_pipe_bpp, dsc_min_pipe_bpp;
+
+ dsc_max_bpc = min(intel_dp_dsc_max_src_input_bpc(i915), conn_state->max_requested_bpc);
+ dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
+
+ dsc_max_pipe_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
+ dsc_min_pipe_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
+
+ return pipe_bpp >= dsc_min_pipe_bpp &&
+ pipe_bpp <= dsc_max_pipe_bpp;
+}
+
+static
+int intel_dp_force_dsc_pipe_bpp(struct intel_dp *intel_dp,
+ struct drm_connector_state *conn_state,
+ struct link_config_limits *limits)
+{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ int forced_bpp;
+
+ if (!intel_dp->force_dsc_bpc)
+ return 0;
+
+ forced_bpp = intel_dp->force_dsc_bpc * 3;
+
+ if (is_dsc_pipe_bpp_sufficient(i915, conn_state, limits, forced_bpp)) {
+ drm_dbg_kms(&i915->drm, "Input DSC BPC forced to %d\n", intel_dp->force_dsc_bpc);
+ return forced_bpp;
+ }
+
+ drm_dbg_kms(&i915->drm, "Cannot force DSC BPC:%d, due to DSC BPC limits\n",
+ intel_dp->force_dsc_bpc);
+
+ return 0;
+}
+
+static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
+ struct intel_crtc_state *pipe_config,
+ struct drm_connector_state *conn_state,
+ struct link_config_limits *limits,
+ int timeslots)
+{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ const struct intel_connector *connector =
+ to_intel_connector(conn_state->connector);
+ u8 max_req_bpc = conn_state->max_requested_bpc;
+ u8 dsc_max_bpc, dsc_max_bpp;
+ u8 dsc_min_bpc, dsc_min_bpp;
+ u8 dsc_bpc[3] = {};
+ int forced_bpp, pipe_bpp;
+ int num_bpc, i, ret;
+
+ forced_bpp = intel_dp_force_dsc_pipe_bpp(intel_dp, conn_state, limits);
+
+ if (forced_bpp) {
+ ret = dsc_compute_compressed_bpp(intel_dp, connector, pipe_config,
+ limits, forced_bpp, timeslots);
+ if (ret == 0) {
+ pipe_config->pipe_bpp = forced_bpp;
+ return 0;
+ }
+ }
+
+ dsc_max_bpc = intel_dp_dsc_max_src_input_bpc(i915);
+ if (!dsc_max_bpc)
+ return -EINVAL;
+
+ dsc_max_bpc = min_t(u8, dsc_max_bpc, max_req_bpc);
+ dsc_max_bpp = min(dsc_max_bpc * 3, limits->pipe.max_bpp);
+
+ dsc_min_bpc = intel_dp_dsc_min_src_input_bpc(i915);
+ dsc_min_bpp = max(dsc_min_bpc * 3, limits->pipe.min_bpp);
+
+ /*
+ * Get the maximum DSC bpc that will be supported by any valid
+ * link configuration and compressed bpp.
+ */
+ num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd, dsc_bpc);
+ for (i = 0; i < num_bpc; i++) {
+ pipe_bpp = dsc_bpc[i] * 3;
+ if (pipe_bpp < dsc_min_bpp)
+ break;
+ if (pipe_bpp > dsc_max_bpp)
+ continue;
+ ret = dsc_compute_compressed_bpp(intel_dp, connector, pipe_config,
+ limits, pipe_bpp, timeslots);
+ if (ret == 0) {
+ pipe_config->pipe_bpp = pipe_bpp;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
+ struct intel_crtc_state *pipe_config,
+ struct drm_connector_state *conn_state,
+ struct link_config_limits *limits)
+{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ struct intel_connector *connector =
+ to_intel_connector(conn_state->connector);
+ int pipe_bpp, forced_bpp;
+ int dsc_src_min_bpp, dsc_sink_min_bpp, dsc_min_bpp;
+ int dsc_src_max_bpp, dsc_sink_max_bpp, dsc_max_bpp;
+
+ forced_bpp = intel_dp_force_dsc_pipe_bpp(intel_dp, conn_state, limits);
+
+ if (forced_bpp) {
+ pipe_bpp = forced_bpp;
+ } else {
+ int max_bpc = min(limits->pipe.max_bpp / 3, (int)conn_state->max_requested_bpc);
+
+ /* For eDP use max bpp that can be supported with DSC. */
+ pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, max_bpc);
+ if (!is_dsc_pipe_bpp_sufficient(i915, conn_state, limits, pipe_bpp)) {
+ drm_dbg_kms(&i915->drm,
+ "Computed BPC is not in DSC BPC limits\n");
+ return -EINVAL;
+ }
+ }
+ pipe_config->port_clock = limits->max_rate;
+ pipe_config->lane_count = limits->max_lane_count;
+
+ dsc_src_min_bpp = dsc_src_min_compressed_bpp();
+ dsc_sink_min_bpp = dsc_sink_min_compressed_bpp(pipe_config);
+ dsc_min_bpp = max(dsc_src_min_bpp, dsc_sink_min_bpp);
+ dsc_min_bpp = max(dsc_min_bpp, to_bpp_int_roundup(limits->link.min_bpp_x16));
+
+ dsc_src_max_bpp = dsc_src_max_compressed_bpp(intel_dp);
+ dsc_sink_max_bpp = dsc_sink_max_compressed_bpp(connector, pipe_config, pipe_bpp / 3);
+ dsc_max_bpp = dsc_sink_max_bpp ? min(dsc_sink_max_bpp, dsc_src_max_bpp) : dsc_src_max_bpp;
+ dsc_max_bpp = min(dsc_max_bpp, to_bpp_int(limits->link.max_bpp_x16));
+
+ /* Compressed BPP should be less than the Input DSC bpp */
+ dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
+
+ pipe_config->dsc.compressed_bpp = max(dsc_min_bpp, dsc_max_bpp);
+
+ pipe_config->pipe_bpp = pipe_bpp;
+
+ return 0;
}
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
@@ -1664,52 +2116,45 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+ const struct intel_connector *connector =
+ to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
- int pipe_bpp;
int ret;
pipe_config->fec_enable = !intel_dp_is_edp(intel_dp) &&
- intel_dp_supports_fec(intel_dp, pipe_config);
+ intel_dp_supports_fec(intel_dp, connector, pipe_config);
- if (!intel_dp_supports_dsc(intel_dp, pipe_config))
+ if (!intel_dp_supports_dsc(connector, pipe_config))
return -EINVAL;
- if (!intel_dp_dsc_supports_format(intel_dp, pipe_config->output_format))
+ if (!intel_dp_dsc_supports_format(connector, pipe_config->output_format))
return -EINVAL;
- if (compute_pipe_bpp)
- pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc);
- else
- pipe_bpp = pipe_config->pipe_bpp;
-
- if (intel_dp->force_dsc_bpc) {
- pipe_bpp = intel_dp->force_dsc_bpc * 3;
- drm_dbg_kms(&dev_priv->drm, "Input DSC BPP forced to %d", pipe_bpp);
- }
-
- /* Min Input BPC for ICL+ is 8 */
- if (pipe_bpp < 8 * 3) {
- drm_dbg_kms(&dev_priv->drm,
- "No DSC support for less than 8bpc\n");
- return -EINVAL;
- }
-
/*
- * For now enable DSC for max bpp, max link rate, max lane count.
- * Optimize this later for the minimum possible link rate/lane count
- * with DSC enabled for the requested mode.
+ * compute pipe bpp is set to false for DP MST DSC case
+ * and compressed_bpp is calculated same time once
+ * vpci timeslots are allocated, because overall bpp
+ * calculation procedure is bit different for MST case.
*/
- pipe_config->pipe_bpp = pipe_bpp;
- pipe_config->port_clock = limits->max_rate;
- pipe_config->lane_count = limits->max_lane_count;
+ if (compute_pipe_bpp) {
+ if (intel_dp_is_edp(intel_dp))
+ ret = intel_edp_dsc_compute_pipe_bpp(intel_dp, pipe_config,
+ conn_state, limits);
+ else
+ ret = intel_dp_dsc_compute_pipe_bpp(intel_dp, pipe_config,
+ conn_state, limits, timeslots);
+ if (ret) {
+ drm_dbg_kms(&dev_priv->drm,
+ "No Valid pipe bpp for given mode ret = %d\n", ret);
+ return ret;
+ }
+ }
+ /* Calculate Slice count */
if (intel_dp_is_edp(intel_dp)) {
- pipe_config->dsc.compressed_bpp =
- min_t(u16, drm_edp_dsc_sink_output_bpp(intel_dp->dsc_dpcd) >> 4,
- pipe_config->pipe_bpp);
pipe_config->dsc.slice_count =
- drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd,
+ drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd,
true);
if (!pipe_config->dsc.slice_count) {
drm_dbg_kms(&dev_priv->drm, "Unsupported Slice Count %d\n",
@@ -1717,36 +2162,10 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
return -EINVAL;
}
} else {
- u16 dsc_max_output_bpp = 0;
u8 dsc_dp_slice_count;
- if (compute_pipe_bpp) {
- dsc_max_output_bpp =
- intel_dp_dsc_get_output_bpp(dev_priv,
- pipe_config->port_clock,
- pipe_config->lane_count,
- adjusted_mode->crtc_clock,
- adjusted_mode->crtc_hdisplay,
- pipe_config->bigjoiner_pipes,
- pipe_bpp,
- timeslots);
- /*
- * According to DSC 1.2a Section 4.1.1 Table 4.1 the maximum
- * supported PPS value can be 63.9375 and with the further
- * mention that bpp should be programmed double the target bpp
- * restricting our target bpp to be 31.9375 at max
- */
- if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
- dsc_max_output_bpp = min_t(u16, dsc_max_output_bpp, 31 << 4);
-
- if (!dsc_max_output_bpp) {
- drm_dbg_kms(&dev_priv->drm,
- "Compressed BPP not supported\n");
- return -EINVAL;
- }
- }
dsc_dp_slice_count =
- intel_dp_dsc_get_slice_count(intel_dp,
+ intel_dp_dsc_get_slice_count(connector,
adjusted_mode->crtc_clock,
adjusted_mode->crtc_hdisplay,
pipe_config->bigjoiner_pipes);
@@ -1756,21 +2175,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
return -EINVAL;
}
- /*
- * compute pipe bpp is set to false for DP MST DSC case
- * and compressed_bpp is calculated same time once
- * vpci timeslots are allocated, because overall bpp
- * calculation procedure is bit different for MST case.
- */
- if (compute_pipe_bpp) {
- pipe_config->dsc.compressed_bpp = min_t(u16,
- dsc_max_output_bpp >> 4,
- pipe_config->pipe_bpp);
- }
pipe_config->dsc.slice_count = dsc_dp_slice_count;
- drm_dbg_kms(&dev_priv->drm, "DSC: compressed bpp %d slice count %d\n",
- pipe_config->dsc.compressed_bpp,
- pipe_config->dsc.slice_count);
}
/*
* VDSC engine operates at 1 Pixel per clock, so if peak pixel rate
@@ -1780,7 +2185,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
if (pipe_config->bigjoiner_pipes || pipe_config->dsc.slice_count > 1)
pipe_config->dsc.dsc_split = true;
- ret = intel_dp_dsc_compute_params(&dig_port->base, pipe_config);
+ ret = intel_dp_dsc_compute_params(connector, pipe_config);
if (ret < 0) {
drm_dbg_kms(&dev_priv->drm,
"Cannot compute valid DSC parameters for Input Bpp = %d "
@@ -1800,29 +2205,85 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
return 0;
}
-static int
-intel_dp_compute_link_config(struct intel_encoder *encoder,
- struct intel_crtc_state *pipe_config,
- struct drm_connector_state *conn_state,
- bool respect_downstream_limits)
+/**
+ * intel_dp_compute_config_link_bpp_limits - compute output link bpp limits
+ * @intel_dp: intel DP
+ * @crtc_state: crtc state
+ * @dsc: DSC compression mode
+ * @limits: link configuration limits
+ *
+ * Calculates the output link min, max bpp values in @limits based on the
+ * pipe bpp range, @crtc_state and @dsc mode.
+ *
+ * Returns %true in case of success.
+ */
+bool
+intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state,
+ bool dsc,
+ struct link_config_limits *limits)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
const struct drm_display_mode *adjusted_mode =
- &pipe_config->hw.adjusted_mode;
- struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- struct link_config_limits limits;
- bool joiner_needs_dsc = false;
- int ret;
+ &crtc_state->hw.adjusted_mode;
+ const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ const struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+ int max_link_bpp_x16;
+
+ max_link_bpp_x16 = min(crtc_state->max_link_bpp_x16,
+ to_bpp_x16(limits->pipe.max_bpp));
+
+ if (!dsc) {
+ max_link_bpp_x16 = rounddown(max_link_bpp_x16, to_bpp_x16(2 * 3));
- limits.min_rate = intel_dp_common_rate(intel_dp, 0);
- limits.max_rate = intel_dp_max_link_rate(intel_dp);
+ if (max_link_bpp_x16 < to_bpp_x16(limits->pipe.min_bpp))
+ return false;
- limits.min_lane_count = 1;
- limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
+ limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
+ } else {
+ /*
+ * TODO: set the DSC link limits already here, atm these are
+ * initialized only later in intel_edp_dsc_compute_pipe_bpp() /
+ * intel_dp_dsc_compute_pipe_bpp()
+ */
+ limits->link.min_bpp_x16 = 0;
+ }
- limits.min_bpp = intel_dp_min_bpp(pipe_config->output_format);
- limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config, respect_downstream_limits);
+ limits->link.max_bpp_x16 = max_link_bpp_x16;
+
+ drm_dbg_kms(&i915->drm,
+ "[ENCODER:%d:%s][CRTC:%d:%s] DP link limits: pixel clock %d kHz DSC %s max lanes %d max rate %d max pipe_bpp %d max link_bpp " BPP_X16_FMT "\n",
+ encoder->base.base.id, encoder->base.name,
+ crtc->base.base.id, crtc->base.name,
+ adjusted_mode->crtc_clock,
+ dsc ? "on" : "off",
+ limits->max_lane_count,
+ limits->max_rate,
+ limits->pipe.max_bpp,
+ BPP_X16_ARGS(limits->link.max_bpp_x16));
+
+ return true;
+}
+
+static bool
+intel_dp_compute_config_limits(struct intel_dp *intel_dp,
+ struct intel_crtc_state *crtc_state,
+ bool respect_downstream_limits,
+ bool dsc,
+ struct link_config_limits *limits)
+{
+ limits->min_rate = intel_dp_common_rate(intel_dp, 0);
+ limits->max_rate = intel_dp_max_link_rate(intel_dp);
+
+ /* FIXME 128b/132b SST support missing */
+ limits->max_rate = min(limits->max_rate, 810000);
+
+ limits->min_lane_count = 1;
+ limits->max_lane_count = intel_dp_max_lane_count(intel_dp);
+
+ limits->pipe.min_bpp = intel_dp_min_bpp(crtc_state->output_format);
+ limits->pipe.max_bpp = intel_dp_max_bpp(intel_dp, crtc_state,
+ respect_downstream_limits);
if (intel_dp->use_max_params) {
/*
@@ -1833,16 +2294,33 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
* configuration, and typically on older panels these
* values correspond to the native resolution of the panel.
*/
- limits.min_lane_count = limits.max_lane_count;
- limits.min_rate = limits.max_rate;
+ limits->min_lane_count = limits->max_lane_count;
+ limits->min_rate = limits->max_rate;
}
- intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits);
+ intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
- drm_dbg_kms(&i915->drm, "DP link computation with max lane count %i "
- "max rate %d max bpp %d pixel clock %iKHz\n",
- limits.max_lane_count, limits.max_rate,
- limits.max_bpp, adjusted_mode->crtc_clock);
+ return intel_dp_compute_config_link_bpp_limits(intel_dp,
+ crtc_state,
+ dsc,
+ limits);
+}
+
+static int
+intel_dp_compute_link_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *pipe_config,
+ struct drm_connector_state *conn_state,
+ bool respect_downstream_limits)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
+ const struct drm_display_mode *adjusted_mode =
+ &pipe_config->hw.adjusted_mode;
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ struct link_config_limits limits;
+ bool joiner_needs_dsc = false;
+ bool dsc_needed;
+ int ret = 0;
if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay,
adjusted_mode->crtc_clock))
@@ -1855,16 +2333,34 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
*/
joiner_needs_dsc = DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes;
- /*
- * Optimize for slow and wide for everything, because there are some
- * eDP 1.3 and 1.4 panels don't work well with fast and narrow.
- */
- ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, conn_state, &limits);
+ dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
+ !intel_dp_compute_config_limits(intel_dp, pipe_config,
+ respect_downstream_limits,
+ false,
+ &limits);
- if (ret || joiner_needs_dsc || intel_dp->force_dsc_en) {
+ if (!dsc_needed) {
+ /*
+ * Optimize for slow and wide for everything, because there are some
+ * eDP 1.3 and 1.4 panels don't work well with fast and narrow.
+ */
+ ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config,
+ conn_state, &limits);
+ if (ret)
+ dsc_needed = true;
+ }
+
+ if (dsc_needed) {
drm_dbg_kms(&i915->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n",
str_yes_no(ret), str_yes_no(joiner_needs_dsc),
str_yes_no(intel_dp->force_dsc_en));
+
+ if (!intel_dp_compute_config_limits(intel_dp, pipe_config,
+ respect_downstream_limits,
+ true,
+ &limits))
+ return -EINVAL;
+
ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
conn_state, &limits, 64, true);
if (ret < 0)
@@ -2140,7 +2636,7 @@ static bool can_enable_drrs(struct intel_connector *connector,
static void
intel_dp_drrs_compute_config(struct intel_connector *connector,
struct intel_crtc_state *pipe_config,
- int output_bpp)
+ int link_bpp)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
const struct drm_display_mode *downclock_mode =
@@ -2148,7 +2644,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
int pixel_clock;
if (has_seamless_m_n(connector))
- pipe_config->seamless_m_n = true;
+ pipe_config->update_m_n = true;
if (!can_enable_drrs(connector, pipe_config, downclock_mode)) {
if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder))
@@ -2165,7 +2661,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
if (pipe_config->splitter.enable)
pixel_clock /= pipe_config->splitter.link_count;
- intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
+ intel_link_compute_m_n(link_bpp, pipe_config->lane_count, pixel_clock,
pipe_config->port_clock, &pipe_config->dp_m2_n2,
pipe_config->fec_enable);
@@ -2175,15 +2671,17 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
}
static bool intel_dp_has_audio(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- struct intel_connector *connector = intel_dp->attached_connector;
const struct intel_digital_connector_state *intel_conn_state =
to_intel_digital_connector_state(conn_state);
+ struct intel_connector *connector =
+ to_intel_connector(conn_state->connector);
- if (!intel_dp_port_has_audio(i915, encoder->port))
+ if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) &&
+ !intel_dp_port_has_audio(i915, encoder->port))
return false;
if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
@@ -2236,7 +2734,7 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
return ret;
}
-static void
+void
intel_dp_audio_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
@@ -2244,9 +2742,12 @@ intel_dp_audio_compute_config(struct intel_encoder *encoder,
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct drm_connector *connector = conn_state->connector;
- pipe_config->sdp_split_enable =
- intel_dp_has_audio(encoder, conn_state) &&
- intel_dp_is_uhbr(pipe_config);
+ pipe_config->has_audio =
+ intel_dp_has_audio(encoder, pipe_config, conn_state) &&
+ intel_audio_compute_config(encoder, pipe_config, conn_state);
+
+ pipe_config->sdp_split_enable = pipe_config->has_audio &&
+ intel_dp_is_uhbr(pipe_config);
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] SDP split enable: %s\n",
connector->base.id, connector->name,
@@ -2263,15 +2764,11 @@ intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
const struct drm_display_mode *fixed_mode;
struct intel_connector *connector = intel_dp->attached_connector;
- int ret = 0, output_bpp;
+ int ret = 0, link_bpp;
if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && encoder->port != PORT_A)
pipe_config->has_pch_encoder = true;
- pipe_config->has_audio =
- intel_dp_has_audio(encoder, conn_state) &&
- intel_audio_compute_config(encoder, pipe_config, conn_state);
-
fixed_mode = intel_panel_fixed_mode(connector, adjusted_mode);
if (intel_dp_is_edp(intel_dp) && fixed_mode) {
ret = intel_panel_compute_config(connector, adjusted_mode);
@@ -2316,10 +2813,10 @@ intel_dp_compute_config(struct intel_encoder *encoder,
drm_dp_enhanced_frame_cap(intel_dp->dpcd);
if (pipe_config->dsc.compression_enable)
- output_bpp = pipe_config->dsc.compressed_bpp;
+ link_bpp = pipe_config->dsc.compressed_bpp;
else
- output_bpp = intel_dp_output_bpp(pipe_config->output_format,
- pipe_config->pipe_bpp);
+ link_bpp = intel_dp_output_bpp(pipe_config->output_format,
+ pipe_config->pipe_bpp);
if (intel_dp->mso_link_count) {
int n = intel_dp->mso_link_count;
@@ -2343,7 +2840,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
- intel_link_compute_m_n(output_bpp,
+ intel_link_compute_m_n(link_bpp,
pipe_config->lane_count,
adjusted_mode->crtc_clock,
pipe_config->port_clock,
@@ -2359,7 +2856,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_vrr_compute_config(pipe_config, conn_state);
intel_psr_compute_config(intel_dp, pipe_config, conn_state);
- intel_dp_drrs_compute_config(connector, pipe_config, output_bpp);
+ intel_dp_drrs_compute_config(connector, pipe_config, link_bpp);
intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state);
@@ -2450,7 +2947,7 @@ intel_edp_init_source_oui(struct intel_dp *intel_dp, bool careful)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
u8 oui[] = { 0x00, 0xaa, 0x01 };
- u8 buf[3] = { 0 };
+ u8 buf[3] = {};
/*
* During driver init, we want to be careful and avoid changing the source OUI if it's
@@ -2984,43 +3481,57 @@ bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
}
-static void intel_dp_get_dsc_sink_cap(struct intel_dp *intel_dp)
+static void intel_dp_read_dsc_dpcd(struct drm_dp_aux *aux,
+ u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
{
- struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ if (drm_dp_dpcd_read(aux, DP_DSC_SUPPORT, dsc_dpcd,
+ DP_DSC_RECEIVER_CAP_SIZE) < 0) {
+ drm_err(aux->drm_dev,
+ "Failed to read DPCD register 0x%x\n",
+ DP_DSC_SUPPORT);
+ return;
+ }
+
+ drm_dbg_kms(aux->drm_dev, "DSC DPCD: %*ph\n",
+ DP_DSC_RECEIVER_CAP_SIZE,
+ dsc_dpcd);
+}
+
+void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector)
+{
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
/*
* Clear the cached register set to avoid using stale values
* for the sinks that do not support DSC.
*/
- memset(intel_dp->dsc_dpcd, 0, sizeof(intel_dp->dsc_dpcd));
+ memset(connector->dp.dsc_dpcd, 0, sizeof(connector->dp.dsc_dpcd));
/* Clear fec_capable to avoid using stale values */
- intel_dp->fec_capable = 0;
+ connector->dp.fec_capability = 0;
- /* Cache the DSC DPCD if eDP or DP rev >= 1.4 */
- if (intel_dp->dpcd[DP_DPCD_REV] >= 0x14 ||
- intel_dp->edp_dpcd[0] >= DP_EDP_14) {
- if (drm_dp_dpcd_read(&intel_dp->aux, DP_DSC_SUPPORT,
- intel_dp->dsc_dpcd,
- sizeof(intel_dp->dsc_dpcd)) < 0)
- drm_err(&i915->drm,
- "Failed to read DPCD register 0x%x\n",
- DP_DSC_SUPPORT);
-
- drm_dbg_kms(&i915->drm, "DSC DPCD: %*ph\n",
- (int)sizeof(intel_dp->dsc_dpcd),
- intel_dp->dsc_dpcd);
+ if (dpcd_rev < DP_DPCD_REV_14)
+ return;
- /* FEC is supported only on DP 1.4 */
- if (!intel_dp_is_edp(intel_dp) &&
- drm_dp_dpcd_readb(&intel_dp->aux, DP_FEC_CAPABILITY,
- &intel_dp->fec_capable) < 0)
- drm_err(&i915->drm,
- "Failed to read FEC DPCD register\n");
+ intel_dp_read_dsc_dpcd(connector->dp.dsc_decompression_aux,
+ connector->dp.dsc_dpcd);
- drm_dbg_kms(&i915->drm, "FEC CAPABILITY: %x\n",
- intel_dp->fec_capable);
+ if (drm_dp_dpcd_readb(connector->dp.dsc_decompression_aux, DP_FEC_CAPABILITY,
+ &connector->dp.fec_capability) < 0) {
+ drm_err(&i915->drm, "Failed to read FEC DPCD register\n");
+ return;
}
+
+ drm_dbg_kms(&i915->drm, "FEC CAPABILITY: %x\n",
+ connector->dp.fec_capability);
+}
+
+static void intel_edp_get_dsc_sink_cap(u8 edp_dpcd_rev, struct intel_connector *connector)
+{
+ if (edp_dpcd_rev < DP_EDP_14)
+ return;
+
+ intel_dp_read_dsc_dpcd(connector->dp.dsc_decompression_aux, connector->dp.dsc_dpcd);
}
static void intel_edp_mso_mode_fixup(struct intel_connector *connector,
@@ -3112,7 +3623,7 @@ static void intel_edp_mso_init(struct intel_dp *intel_dp)
}
static bool
-intel_edp_init_dpcd(struct intel_dp *intel_dp)
+intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector)
{
struct drm_i915_private *dev_priv =
to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
@@ -3191,7 +3702,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
/* Read the eDP DSC DPCD registers */
if (HAS_DSC(dev_priv))
- intel_dp_get_dsc_sink_cap(intel_dp);
+ intel_edp_get_dsc_sink_cap(intel_dp->edp_dpcd[0],
+ connector);
/*
* If needed, program our source OUI so we can make various Intel-specific AUX services
@@ -4724,14 +5236,10 @@ intel_dp_update_dfp(struct intel_dp *intel_dp,
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_connector *connector = intel_dp->attached_connector;
- const struct edid *edid;
-
- /* FIXME: Get rid of drm_edid_raw() */
- edid = drm_edid_raw(drm_edid);
intel_dp->dfp.max_bpc =
drm_dp_downstream_max_bpc(intel_dp->dpcd,
- intel_dp->downstream_ports, edid);
+ intel_dp->downstream_ports, drm_edid);
intel_dp->dfp.max_dotclock =
drm_dp_downstream_max_dotclock(intel_dp->dpcd,
@@ -4740,11 +5248,11 @@ intel_dp_update_dfp(struct intel_dp *intel_dp,
intel_dp->dfp.min_tmds_clock =
drm_dp_downstream_min_tmds_clock(intel_dp->dpcd,
intel_dp->downstream_ports,
- edid);
+ drm_edid);
intel_dp->dfp.max_tmds_clock =
drm_dp_downstream_max_tmds_clock(intel_dp->dpcd,
intel_dp->downstream_ports,
- edid);
+ drm_edid);
intel_dp->dfp.pcon_max_frl_bw =
drm_dp_get_pcon_max_frl_bw(intel_dp->dpcd,
@@ -4815,7 +5323,6 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_connector *connector = intel_dp->attached_connector;
const struct drm_edid *drm_edid;
- const struct edid *edid;
bool vrr_capable;
intel_dp_unset_edid(intel_dp);
@@ -4833,10 +5340,8 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
intel_dp_update_dfp(intel_dp, drm_edid);
intel_dp_update_420(intel_dp);
- /* FIXME: Get rid of drm_edid_raw() */
- edid = drm_edid_raw(drm_edid);
-
- drm_dp_cec_set_edid(&intel_dp->aux, edid);
+ drm_dp_cec_attach(&intel_dp->aux,
+ connector->base.display_info.source_physical_address);
}
static void
@@ -4862,13 +5367,32 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
false);
}
+static void
+intel_dp_detect_dsc_caps(struct intel_dp *intel_dp, struct intel_connector *connector)
+{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+ /* Read DP Sink DSC Cap DPCD regs for DP v1.4 */
+ if (!HAS_DSC(i915))
+ return;
+
+ if (intel_dp_is_edp(intel_dp))
+ intel_edp_get_dsc_sink_cap(intel_dp->edp_dpcd[0],
+ connector);
+ else
+ intel_dp_get_dsc_sink_cap(intel_dp->dpcd[DP_DPCD_REV],
+ connector);
+}
+
static int
intel_dp_detect(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx,
bool force)
{
struct drm_i915_private *dev_priv = to_i915(connector->dev);
- struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
+ struct intel_connector *intel_connector =
+ to_intel_connector(connector);
+ struct intel_dp *intel_dp = intel_attached_dp(intel_connector);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *encoder = &dig_port->base;
enum drm_connector_status status;
@@ -4878,7 +5402,7 @@ intel_dp_detect(struct drm_connector *connector,
drm_WARN_ON(&dev_priv->drm,
!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
- if (!INTEL_DISPLAY_ENABLED(dev_priv))
+ if (!intel_display_device_enabled(dev_priv))
return connector_status_disconnected;
/* Can't disconnect eDP */
@@ -4891,7 +5415,7 @@ intel_dp_detect(struct drm_connector *connector,
if (status == connector_status_disconnected) {
memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance));
- memset(intel_dp->dsc_dpcd, 0, sizeof(intel_dp->dsc_dpcd));
+ memset(intel_connector->dp.dsc_dpcd, 0, sizeof(intel_connector->dp.dsc_dpcd));
if (intel_dp->is_mst) {
drm_dbg_kms(&dev_priv->drm,
@@ -4906,9 +5430,7 @@ intel_dp_detect(struct drm_connector *connector,
goto out;
}
- /* Read DP Sink DSC Cap DPCD regs for DP v1.4 */
- if (HAS_DSC(dev_priv))
- intel_dp_get_dsc_sink_cap(intel_dp);
+ intel_dp_detect_dsc_caps(intel_dp, intel_connector);
intel_dp_configure_mst(intel_dp);
@@ -4964,12 +5486,6 @@ out:
if (status != connector_status_connected && !intel_dp->is_mst)
intel_dp_unset_edid(intel_dp);
- /*
- * Make sure the refs for power wells enabled during detect are
- * dropped to avoid a new detect cycle triggered by HPD polling.
- */
- intel_display_power_flush_work(dev_priv);
-
if (!intel_dp_is_edp(intel_dp))
drm_dp_set_subconnector_property(connector,
status,
@@ -4985,9 +5501,6 @@ intel_dp_force(struct drm_connector *connector)
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *intel_encoder = &dig_port->base;
struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
- enum intel_display_power_domain aux_domain =
- intel_aux_power_domain(dig_port);
- intel_wakeref_t wakeref;
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
@@ -4996,11 +5509,7 @@ intel_dp_force(struct drm_connector *connector)
if (connector->status != connector_status_connected)
return;
- wakeref = intel_display_power_get(dev_priv, aux_domain);
-
intel_dp_set_edid(intel_dp);
-
- intel_display_power_put(dev_priv, aux_domain, wakeref);
}
static int intel_dp_get_modes(struct drm_connector *connector)
@@ -5260,15 +5769,26 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn,
return intel_modeset_synced_crtcs(state, conn);
}
-static void intel_dp_oob_hotplug_event(struct drm_connector *connector)
+static void intel_dp_oob_hotplug_event(struct drm_connector *connector,
+ enum drm_connector_status hpd_state)
{
struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector));
struct drm_i915_private *i915 = to_i915(connector->dev);
+ bool hpd_high = hpd_state == connector_status_connected;
+ unsigned int hpd_pin = encoder->hpd_pin;
+ bool need_work = false;
spin_lock_irq(&i915->irq_lock);
- i915->display.hotplug.event_bits |= BIT(encoder->hpd_pin);
+ if (hpd_high != test_bit(hpd_pin, &i915->display.hotplug.oob_hotplug_last_state)) {
+ i915->display.hotplug.event_bits |= BIT(hpd_pin);
+
+ __assign_bit(hpd_pin, &i915->display.hotplug.oob_hotplug_last_state, hpd_high);
+ need_work = true;
+ }
spin_unlock_irq(&i915->irq_lock);
- queue_delayed_work(i915->unordered_wq, &i915->display.hotplug.hotplug_work, 0);
+
+ if (need_work)
+ queue_delayed_work(i915->unordered_wq, &i915->display.hotplug.hotplug_work, 0);
}
static const struct drm_connector_funcs intel_dp_connector_funcs = {
@@ -5506,7 +6026,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
intel_hpd_enable_detection(encoder);
/* Cache DPCD and EDID for edp. */
- has_dpcd = intel_edp_init_dpcd(intel_dp);
+ has_dpcd = intel_edp_init_dpcd(intel_dp, intel_connector);
if (!has_dpcd) {
/* if this fails, presume the device is a ghost */
@@ -5556,7 +6076,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
}
mutex_lock(&dev_priv->drm.mode_config.mutex);
- drm_edid = drm_edid_read_ddc(connector, &intel_dp->aux.ddc);
+ drm_edid = drm_edid_read_ddc(connector, connector->ddc);
if (!drm_edid) {
/* Fallback to EDID from ACPI OpRegion, if any */
drm_edid = intel_opregion_get_edid(intel_connector);
@@ -5695,12 +6215,16 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp);
+ intel_dp_aux_init(intel_dp);
+ intel_connector->dp.dsc_decompression_aux = &intel_dp->aux;
+
drm_dbg_kms(&dev_priv->drm,
"Adding %s connector on [ENCODER:%d:%s]\n",
type == DRM_MODE_CONNECTOR_eDP ? "eDP" : "DP",
intel_encoder->base.base.id, intel_encoder->base.name);
- drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
+ drm_connector_init_with_ddc(dev, connector, &intel_dp_connector_funcs,
+ type, &intel_dp->aux.ddc);
drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
if (!HAS_GMCH(dev_priv) && DISPLAY_VER(dev_priv) < 12)
@@ -5708,8 +6232,6 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
- intel_dp_aux_init(intel_dp);
-
intel_connector_attach_encoder(intel_connector, intel_encoder);
if (HAS_DDI(dev_priv))
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 22099de3ca..484aea215a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -26,7 +26,14 @@ struct intel_encoder;
struct link_config_limits {
int min_rate, max_rate;
int min_lane_count, max_lane_count;
- int min_bpp, max_bpp;
+ struct {
+ /* Uncompressed DSC input or link output bpp in 1 bpp units */
+ int min_bpp, max_bpp;
+ } pipe;
+ struct {
+ /* Compressed or uncompressed link output bpp in 1/16 bpp units */
+ int min_bpp_x16, max_bpp_x16;
+ } link;
};
void intel_edp_fixup_vbt_bpp(struct intel_encoder *encoder, int pipe_bpp);
@@ -65,6 +72,9 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct link_config_limits *limits,
int timeslots,
bool recompute_pipe_bpp);
+void intel_dp_audio_compute_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *pipe_config,
+ struct drm_connector_state *conn_state);
bool intel_dp_has_hdmi_sink(struct intel_dp *intel_dp);
bool intel_dp_is_edp(struct intel_dp *intel_dp);
bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state);
@@ -106,14 +116,16 @@ void intel_read_dp_sdp(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
unsigned int type);
bool intel_digital_port_connected(struct intel_encoder *encoder);
-int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc);
-u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
- u32 link_clock, u32 lane_count,
- u32 mode_clock, u32 mode_hdisplay,
- bool bigjoiner,
- u32 pipe_bpp,
- u32 timeslots);
-u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
+int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
+ u8 dsc_max_bpc);
+u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
+ u32 link_clock, u32 lane_count,
+ u32 mode_clock, u32 mode_hdisplay,
+ bool bigjoiner,
+ enum intel_output_format output_format,
+ u32 pipe_bpp,
+ u32 timeslots);
+u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
int mode_clock, int mode_hdisplay,
bool bigjoiner);
bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
@@ -143,5 +155,14 @@ void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
void intel_dp_phy_test(struct intel_encoder *encoder);
void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
+int intel_dp_output_bpp(enum intel_output_format output_format, int bpp);
+
+bool
+intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state,
+ bool dsc,
+ struct link_config_limits *limits);
+
+void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector);
#endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c
index 2d173bd495..4431b6290c 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -14,6 +14,21 @@
#include "intel_pps.h"
#include "intel_tc.h"
+#define AUX_CH_NAME_BUFSIZE 6
+
+static const char *aux_ch_name(struct drm_i915_private *i915,
+ char *buf, int size, enum aux_ch aux_ch)
+{
+ if (DISPLAY_VER(i915) >= 13 && aux_ch >= AUX_CH_D_XELPD)
+ snprintf(buf, size, "%c", 'A' + aux_ch - AUX_CH_D_XELPD + AUX_CH_D);
+ else if (DISPLAY_VER(i915) >= 12 && aux_ch >= AUX_CH_USBC1)
+ snprintf(buf, size, "USBC%c", '1' + aux_ch - AUX_CH_USBC1);
+ else
+ snprintf(buf, size, "%c", 'A' + aux_ch);
+
+ return buf;
+}
+
u32 intel_dp_aux_pack(const u8 *src, int src_bytes)
{
int i;
@@ -687,10 +702,10 @@ static i915_reg_t xelpdp_aux_ctl_reg(struct intel_dp *intel_dp)
case AUX_CH_USBC2:
case AUX_CH_USBC3:
case AUX_CH_USBC4:
- return XELPDP_DP_AUX_CH_CTL(aux_ch);
+ return XELPDP_DP_AUX_CH_CTL(dev_priv, aux_ch);
default:
MISSING_CASE(aux_ch);
- return XELPDP_DP_AUX_CH_CTL(AUX_CH_A);
+ return XELPDP_DP_AUX_CH_CTL(dev_priv, AUX_CH_A);
}
}
@@ -707,10 +722,10 @@ static i915_reg_t xelpdp_aux_data_reg(struct intel_dp *intel_dp, int index)
case AUX_CH_USBC2:
case AUX_CH_USBC3:
case AUX_CH_USBC4:
- return XELPDP_DP_AUX_CH_DATA(aux_ch, index);
+ return XELPDP_DP_AUX_CH_DATA(dev_priv, aux_ch, index);
default:
MISSING_CASE(aux_ch);
- return XELPDP_DP_AUX_CH_DATA(AUX_CH_A, index);
+ return XELPDP_DP_AUX_CH_DATA(dev_priv, AUX_CH_A, index);
}
}
@@ -728,6 +743,7 @@ void intel_dp_aux_init(struct intel_dp *intel_dp)
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *encoder = &dig_port->base;
enum aux_ch aux_ch = dig_port->aux_ch;
+ char buf[AUX_CH_NAME_BUFSIZE];
if (DISPLAY_VER(dev_priv) >= 14) {
intel_dp->aux_ch_ctl_reg = xelpdp_aux_ctl_reg;
@@ -764,18 +780,9 @@ void intel_dp_aux_init(struct intel_dp *intel_dp)
drm_dp_aux_init(&intel_dp->aux);
/* Failure to allocate our preferred name is not critical */
- if (DISPLAY_VER(dev_priv) >= 13 && aux_ch >= AUX_CH_D_XELPD)
- intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
- aux_ch_name(aux_ch - AUX_CH_D_XELPD + AUX_CH_D),
- encoder->base.name);
- else if (DISPLAY_VER(dev_priv) >= 12 && aux_ch >= AUX_CH_USBC1)
- intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX USBC%c/%s",
- aux_ch - AUX_CH_USBC1 + '1',
- encoder->base.name);
- else
- intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
- aux_ch_name(aux_ch),
- encoder->base.name);
+ intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %s/%s",
+ aux_ch_name(dev_priv, buf, sizeof(buf), aux_ch),
+ encoder->base.name);
intel_dp->aux.transfer = intel_dp_aux_transfer;
cpu_latency_qos_add_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
@@ -819,6 +826,7 @@ enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder)
struct intel_encoder *other;
const char *source;
enum aux_ch aux_ch;
+ char buf[AUX_CH_NAME_BUFSIZE];
aux_ch = intel_bios_dp_aux_ch(encoder->devdata);
source = "VBT";
@@ -836,16 +844,17 @@ enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder)
other = get_encoder_by_aux_ch(encoder, aux_ch);
if (other) {
drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s] AUX CH %c already claimed by [ENCODER:%d:%s]\n",
- encoder->base.base.id, encoder->base.name, aux_ch_name(aux_ch),
+ "[ENCODER:%d:%s] AUX CH %s already claimed by [ENCODER:%d:%s]\n",
+ encoder->base.base.id, encoder->base.name,
+ aux_ch_name(i915, buf, sizeof(buf), aux_ch),
other->base.base.id, other->base.name);
return AUX_CH_NONE;
}
drm_dbg_kms(&i915->drm,
- "[ENCODER:%d:%s] Using AUX CH %c (%s)\n",
+ "[ENCODER:%d:%s] Using AUX CH %s (%s)\n",
encoder->base.base.id, encoder->base.name,
- aux_ch_name(aux_ch), source);
+ aux_ch_name(i915, buf, sizeof(buf), aux_ch), source);
return aux_ch;
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
index 95cc525184..26ea7e9f1b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -169,7 +169,7 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe
struct intel_panel *panel = &connector->panel;
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
u8 tmp;
- u8 buf[2] = { 0 };
+ u8 buf[2] = {};
if (drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &tmp) != 1) {
drm_err(&i915->drm, "[CONNECTOR:%d:%s] Failed to read current backlight mode from DPCD\n",
@@ -204,7 +204,7 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state,
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct drm_device *dev = connector->base.dev;
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
- u8 buf[4] = { 0 };
+ u8 buf[4] = {};
buf[0] = level & 0xFF;
buf[1] = (level & 0xFF00) >> 8;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h b/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h
index 5185345277..34f6e0a48e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_regs.h
@@ -13,48 +13,34 @@
* packet size supported is 20 bytes in each direction, hence the 5 fixed data
* registers
*/
-#define _DPA_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64010)
-#define _DPA_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64014)
-#define _DPB_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64110)
-#define _DPB_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64114)
-
-#define DP_AUX_CH_CTL(aux_ch) _MMIO_PORT(aux_ch, _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL)
-#define DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PORT(aux_ch, _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
-
-#define _XELPDP_USBC1_AUX_CH_CTL 0x16F210
-#define _XELPDP_USBC2_AUX_CH_CTL 0x16F410
-#define _XELPDP_USBC3_AUX_CH_CTL 0x16F610
-#define _XELPDP_USBC4_AUX_CH_CTL 0x16F810
-
-#define XELPDP_DP_AUX_CH_CTL(aux_ch) _MMIO(_PICK(aux_ch, \
- _DPA_AUX_CH_CTL, \
- _DPB_AUX_CH_CTL, \
- 0, /* port/aux_ch C is non-existent */ \
- _XELPDP_USBC1_AUX_CH_CTL, \
- _XELPDP_USBC2_AUX_CH_CTL, \
- _XELPDP_USBC3_AUX_CH_CTL, \
- _XELPDP_USBC4_AUX_CH_CTL))
-
-#define _XELPDP_USBC1_AUX_CH_DATA1 0x16F214
-#define _XELPDP_USBC2_AUX_CH_DATA1 0x16F414
-#define _XELPDP_USBC3_AUX_CH_DATA1 0x16F614
-#define _XELPDP_USBC4_AUX_CH_DATA1 0x16F814
-
-#define XELPDP_DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PICK(aux_ch, \
- _DPA_AUX_CH_DATA1, \
- _DPB_AUX_CH_DATA1, \
- 0, /* port/aux_ch C is non-existent */ \
- _XELPDP_USBC1_AUX_CH_DATA1, \
- _XELPDP_USBC2_AUX_CH_DATA1, \
- _XELPDP_USBC3_AUX_CH_DATA1, \
- _XELPDP_USBC4_AUX_CH_DATA1) + (i) * 4)
+/*
+ * Wrapper macro to convert from aux_ch to the index used in some of the
+ * registers.
+ */
+#define __xe2lpd_aux_ch_idx(aux_ch) \
+ (aux_ch >= AUX_CH_USBC1 ? aux_ch : AUX_CH_USBC4 + 1 + (aux_ch) - AUX_CH_A)
+/* TODO: Remove implicit dev_priv */
+#define _DPA_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64010)
+#define _DPB_AUX_CH_CTL (DISPLAY_MMIO_BASE(dev_priv) + 0x64110)
+#define _XELPDP_USBC1_AUX_CH_CTL 0x16f210
+#define _XELPDP_USBC2_AUX_CH_CTL 0x16f410
+#define DP_AUX_CH_CTL(aux_ch) _MMIO_PORT(aux_ch, _DPA_AUX_CH_CTL, \
+ _DPB_AUX_CH_CTL)
+#define _XELPDP_DP_AUX_CH_CTL(aux_ch) \
+ _MMIO(_PICK_EVEN_2RANGES(aux_ch, AUX_CH_USBC1, \
+ _DPA_AUX_CH_CTL, _DPB_AUX_CH_CTL, \
+ _XELPDP_USBC1_AUX_CH_CTL, \
+ _XELPDP_USBC2_AUX_CH_CTL))
+#define XELPDP_DP_AUX_CH_CTL(i915__, aux_ch) \
+ (DISPLAY_VER(i915__) >= 20 ? \
+ _XELPDP_DP_AUX_CH_CTL(__xe2lpd_aux_ch_idx(aux_ch)) : \
+ _XELPDP_DP_AUX_CH_CTL(aux_ch))
#define DP_AUX_CH_CTL_SEND_BUSY REG_BIT(31)
#define DP_AUX_CH_CTL_DONE REG_BIT(30)
#define DP_AUX_CH_CTL_INTERRUPT REG_BIT(29)
#define DP_AUX_CH_CTL_TIME_OUT_ERROR REG_BIT(28)
-
#define DP_AUX_CH_CTL_TIME_OUT_MASK REG_GENMASK(27, 26)
#define DP_AUX_CH_CTL_TIME_OUT_400us REG_FIELD_PREP(DP_AUX_CH_CTL_TIME_OUT_MASK, 0)
#define DP_AUX_CH_CTL_TIME_OUT_600us REG_FIELD_PREP(DP_AUX_CH_CTL_TIME_OUT_MASK, 1)
@@ -83,4 +69,26 @@
#define DP_AUX_CH_CTL_SYNC_PULSE_SKL_MASK REG_GENMASK(4, 0) /* skl+ */
#define DP_AUX_CH_CTL_SYNC_PULSE_SKL(c) REG_FIELD_PREP(DP_AUX_CH_CTL_SYNC_PULSE_SKL_MASK, (c) - 1)
+/* TODO: Remove implicit dev_priv */
+#define _DPA_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64014)
+#define _DPB_AUX_CH_DATA1 (DISPLAY_MMIO_BASE(dev_priv) + 0x64114)
+#define _XELPDP_USBC1_AUX_CH_DATA1 0x16f214
+#define _XELPDP_USBC2_AUX_CH_DATA1 0x16f414
+#define DP_AUX_CH_DATA(aux_ch, i) _MMIO(_PORT(aux_ch, _DPA_AUX_CH_DATA1, \
+ _DPB_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
+#define _XELPDP_DP_AUX_CH_DATA(aux_ch, i) \
+ _MMIO(_PICK_EVEN_2RANGES(aux_ch, AUX_CH_USBC1, \
+ _DPA_AUX_CH_DATA1, _DPB_AUX_CH_DATA1, \
+ _XELPDP_USBC1_AUX_CH_DATA1, \
+ _XELPDP_USBC2_AUX_CH_DATA1) + (i) * 4) /* 5 registers */
+#define XELPDP_DP_AUX_CH_DATA(i915__, aux_ch, i) \
+ (DISPLAY_VER(i915__) >= 20 ? \
+ _XELPDP_DP_AUX_CH_DATA(__xe2lpd_aux_ch_idx(aux_ch), i) : \
+ _XELPDP_DP_AUX_CH_DATA(aux_ch, i))
+
+/* PICA Power Well Control */
+#define XE2LPD_PICA_PW_CTL _MMIO(0x16fe04)
+#define XE2LPD_PICA_CTL_POWER_REQUEST REG_BIT(31)
+#define XE2LPD_PICA_CTL_POWER_STATUS REG_BIT(30)
+
#endif /* __INTEL_DP_AUX_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index e0c1771614..3a595cd433 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -330,14 +330,26 @@ static const struct hdcp2_dp_msg_data hdcp2_dp_msg_data[] = {
0, 0 },
};
+static struct drm_dp_aux *
+intel_dp_hdcp_get_aux(struct intel_connector *connector)
+{
+ struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
+
+ if (intel_encoder_is_mst(connector->encoder))
+ return &connector->port->aux;
+ else
+ return &dig_port->dp.aux;
+}
+
static int
-intel_dp_hdcp2_read_rx_status(struct intel_digital_port *dig_port,
+intel_dp_hdcp2_read_rx_status(struct intel_connector *connector,
u8 *rx_status)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct drm_dp_aux *aux = intel_dp_hdcp_get_aux(connector);
ssize_t ret;
- ret = drm_dp_dpcd_read(&dig_port->dp.aux,
+ ret = drm_dp_dpcd_read(aux,
DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status,
HDCP_2_2_DP_RXSTATUS_LEN);
if (ret != HDCP_2_2_DP_RXSTATUS_LEN) {
@@ -350,14 +362,14 @@ intel_dp_hdcp2_read_rx_status(struct intel_digital_port *dig_port,
}
static
-int hdcp2_detect_msg_availability(struct intel_digital_port *dig_port,
+int hdcp2_detect_msg_availability(struct intel_connector *connector,
u8 msg_id, bool *msg_ready)
{
u8 rx_status;
int ret;
*msg_ready = false;
- ret = intel_dp_hdcp2_read_rx_status(dig_port, &rx_status);
+ ret = intel_dp_hdcp2_read_rx_status(connector, &rx_status);
if (ret < 0)
return ret;
@@ -383,12 +395,11 @@ int hdcp2_detect_msg_availability(struct intel_digital_port *dig_port,
}
static ssize_t
-intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *dig_port,
+intel_dp_hdcp2_wait_for_msg(struct intel_connector *connector,
const struct hdcp2_dp_msg_data *hdcp2_msg_data)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
- struct intel_dp *dp = &dig_port->dp;
- struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_hdcp *hdcp = &connector->hdcp;
u8 msg_id = hdcp2_msg_data->msg_id;
int ret, timeout;
bool msg_ready = false;
@@ -411,8 +422,8 @@ intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *dig_port,
* the timeout at wait for CP_IRQ.
*/
intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout);
- ret = hdcp2_detect_msg_availability(dig_port,
- msg_id, &msg_ready);
+ ret = hdcp2_detect_msg_availability(connector, msg_id,
+ &msg_ready);
if (!msg_ready)
ret = -ETIMEDOUT;
}
@@ -437,13 +448,14 @@ static const struct hdcp2_dp_msg_data *get_hdcp2_dp_msg_data(u8 msg_id)
}
static
-int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
+int intel_dp_hdcp2_write_msg(struct intel_connector *connector,
void *buf, size_t size)
{
unsigned int offset;
u8 *byte = buf;
ssize_t ret, bytes_to_write, len;
const struct hdcp2_dp_msg_data *hdcp2_msg_data;
+ struct drm_dp_aux *aux;
hdcp2_msg_data = get_hdcp2_dp_msg_data(*byte);
if (!hdcp2_msg_data)
@@ -451,6 +463,8 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
offset = hdcp2_msg_data->offset;
+ aux = intel_dp_hdcp_get_aux(connector);
+
/* No msg_id in DP HDCP2.2 msgs */
bytes_to_write = size - 1;
byte++;
@@ -459,7 +473,7 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ?
DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write;
- ret = drm_dp_dpcd_write(&dig_port->dp.aux,
+ ret = drm_dp_dpcd_write(aux,
offset, (void *)byte, len);
if (ret < 0)
return ret;
@@ -473,12 +487,14 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
}
static
-ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 *dev_cnt, u8 *byte)
+ssize_t get_receiver_id_list_rx_info(struct intel_connector *connector,
+ u32 *dev_cnt, u8 *byte)
{
+ struct drm_dp_aux *aux = intel_dp_hdcp_get_aux(connector);
ssize_t ret;
u8 *rx_info = byte;
- ret = drm_dp_dpcd_read(&dig_port->dp.aux,
+ ret = drm_dp_dpcd_read(aux,
DP_HDCP_2_2_REG_RXINFO_OFFSET,
(void *)rx_info, HDCP_2_2_RXINFO_LEN);
if (ret != HDCP_2_2_RXINFO_LEN)
@@ -494,12 +510,13 @@ ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 *d
}
static
-int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
+int intel_dp_hdcp2_read_msg(struct intel_connector *connector,
u8 msg_id, void *buf, size_t size)
{
+ struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
- struct intel_dp *dp = &dig_port->dp;
- struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
+ struct intel_hdcp *hdcp = &connector->hdcp;
+ struct drm_dp_aux *aux;
unsigned int offset;
u8 *byte = buf;
ssize_t ret, bytes_to_recv, len;
@@ -513,7 +530,9 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
return -EINVAL;
offset = hdcp2_msg_data->offset;
- ret = intel_dp_hdcp2_wait_for_msg(dig_port, hdcp2_msg_data);
+ aux = intel_dp_hdcp_get_aux(connector);
+
+ ret = intel_dp_hdcp2_wait_for_msg(connector, hdcp2_msg_data);
if (ret < 0)
return ret;
@@ -523,7 +542,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
byte++;
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
- ret = get_receiver_id_list_rx_info(dig_port, &dev_cnt, byte);
+ ret = get_receiver_id_list_rx_info(connector, &dev_cnt, byte);
if (ret < 0)
return ret;
@@ -541,11 +560,17 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_recv;
/* Entire msg read timeout since initiate of msg read */
- if (bytes_to_recv == size - 1 && hdcp2_msg_data->msg_read_timeout > 0)
- msg_end = ktime_add_ms(ktime_get_raw(),
- hdcp2_msg_data->msg_read_timeout);
+ if (bytes_to_recv == size - 1 && hdcp2_msg_data->msg_read_timeout > 0) {
+ if (intel_encoder_is_mst(connector->encoder))
+ msg_end = ktime_add_ms(ktime_get_raw(),
+ hdcp2_msg_data->msg_read_timeout *
+ connector->port->parent->num_ports);
+ else
+ msg_end = ktime_add_ms(ktime_get_raw(),
+ hdcp2_msg_data->msg_read_timeout);
+ }
- ret = drm_dp_dpcd_read(&dig_port->dp.aux, offset,
+ ret = drm_dp_dpcd_read(aux, offset,
(void *)byte, len);
if (ret < 0) {
drm_dbg_kms(&i915->drm, "msg_id %d, ret %zd\n",
@@ -574,7 +599,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port,
}
static
-int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *dig_port,
+int intel_dp_hdcp2_config_stream_type(struct intel_connector *connector,
bool is_repeater, u8 content_type)
{
int ret;
@@ -593,7 +618,7 @@ int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *dig_port,
stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE;
stream_type_msg.stream_type = content_type;
- ret = intel_dp_hdcp2_write_msg(dig_port, &stream_type_msg,
+ ret = intel_dp_hdcp2_write_msg(connector, &stream_type_msg,
sizeof(stream_type_msg));
return ret < 0 ? ret : 0;
@@ -607,7 +632,8 @@ int intel_dp_hdcp2_check_link(struct intel_digital_port *dig_port,
u8 rx_status;
int ret;
- ret = intel_dp_hdcp2_read_rx_status(dig_port, &rx_status);
+ ret = intel_dp_hdcp2_read_rx_status(connector,
+ &rx_status);
if (ret)
return ret;
@@ -622,14 +648,17 @@ int intel_dp_hdcp2_check_link(struct intel_digital_port *dig_port,
}
static
-int intel_dp_hdcp2_capable(struct intel_digital_port *dig_port,
+int intel_dp_hdcp2_capable(struct intel_connector *connector,
bool *capable)
{
+ struct drm_dp_aux *aux;
u8 rx_caps[3];
int ret;
+ aux = intel_dp_hdcp_get_aux(connector);
+
*capable = false;
- ret = drm_dp_dpcd_read(&dig_port->dp.aux,
+ ret = drm_dp_dpcd_read(aux,
DP_HDCP_2_2_REG_RX_CAPS_OFFSET,
rx_caps, HDCP_2_2_RXCAPS_LEN);
if (ret != HDCP_2_2_RXCAPS_LEN)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index a62bca622b..1abfafbbfa 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -1401,11 +1401,13 @@ void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp,
* Default value of bit 31 is '0' hence discarding the write
* TODO: Corrective actions on SDP corruption yet to be defined
*/
- if (intel_dp_is_uhbr(crtc_state))
- /* DP v2.0 SCR on SDP CRC16 for 128b/132b Link Layer */
- drm_dp_dpcd_writeb(&intel_dp->aux,
- DP_SDP_ERROR_DETECTION_CONFIGURATION,
- DP_SDP_CRC16_128B132B_EN);
+ if (!intel_dp_is_uhbr(crtc_state))
+ return;
+
+ /* DP v2.0 SCR on SDP CRC16 for 128b/132b Link Layer */
+ drm_dp_dpcd_writeb(&intel_dp->aux,
+ DP_SDP_ERROR_DETECTION_CONFIGURATION,
+ DP_SDP_CRC16_128B132B_EN);
lt_dbg(intel_dp, DP_PHY_DPRX, "DP2.0 SDP CRC16 for 128b/132b enabled\n");
}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index f104bd7f8c..03ac281766 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -94,12 +94,9 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
crtc_state->lane_count = limits->max_lane_count;
crtc_state->port_clock = limits->max_rate;
- // TODO: Handle pbn_div changes by adding a new MST helper
- if (!mst_state->pbn_div) {
- mst_state->pbn_div = drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr,
- crtc_state->port_clock,
- crtc_state->lane_count);
- }
+ mst_state->pbn_div = drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr,
+ crtc_state->port_clock,
+ crtc_state->lane_count);
for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) {
drm_dbg_kms(&i915->drm, "Trying bpp %d\n", bpp);
@@ -154,15 +151,24 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
int slots = -EINVAL;
+ int link_bpp;
- slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, limits->max_bpp,
- limits->min_bpp, limits,
+ /*
+ * FIXME: allocate the BW according to link_bpp, which in the case of
+ * YUV420 is only half of the pipe bpp value.
+ */
+ slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state,
+ to_bpp_int(limits->link.max_bpp_x16),
+ to_bpp_int(limits->link.min_bpp_x16),
+ limits,
conn_state, 2 * 3, false);
if (slots < 0)
return slots;
- intel_link_compute_m_n(crtc_state->pipe_bpp,
+ link_bpp = intel_dp_output_bpp(crtc_state->output_format, crtc_state->pipe_bpp);
+
+ intel_link_compute_m_n(link_bpp,
crtc_state->lane_count,
adjusted_mode->crtc_clock,
crtc_state->port_clock,
@@ -178,8 +184,6 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
struct drm_connector_state *conn_state,
struct link_config_limits *limits)
{
- struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
- struct intel_dp *intel_dp = &intel_mst->primary->dp;
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
@@ -187,7 +191,7 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
&crtc_state->hw.adjusted_mode;
int slots = -EINVAL;
int i, num_bpc;
- u8 dsc_bpc[3] = {0};
+ u8 dsc_bpc[3] = {};
int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp;
u8 dsc_max_bpc;
bool need_timeslot_recalc = false;
@@ -199,10 +203,10 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
else
dsc_max_bpc = min_t(u8, 10, conn_state->max_requested_bpc);
- max_bpp = min_t(u8, dsc_max_bpc * 3, limits->max_bpp);
- min_bpp = limits->min_bpp;
+ max_bpp = min_t(u8, dsc_max_bpc * 3, limits->pipe.max_bpp);
+ min_bpp = limits->pipe.min_bpp;
- num_bpc = drm_dp_dsc_sink_supported_input_bpcs(intel_dp->dsc_dpcd,
+ num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd,
dsc_bpc);
drm_dbg_kms(&i915->drm, "DSC Source supported min bpp %d max bpp %d\n",
@@ -227,6 +231,9 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
if (max_bpp > sink_max_bpp)
max_bpp = sink_max_bpp;
+ min_bpp = max(min_bpp, to_bpp_int_roundup(limits->link.min_bpp_x16));
+ max_bpp = min(max_bpp, to_bpp_int(limits->link.max_bpp_x16));
+
slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, max_bpp,
min_bpp, limits,
conn_state, 2 * 3, true);
@@ -289,17 +296,39 @@ static int intel_dp_mst_update_slots(struct intel_encoder *encoder,
return 0;
}
-static bool intel_dp_mst_has_audio(const struct drm_connector_state *conn_state)
+static bool
+intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
+ struct intel_crtc_state *crtc_state,
+ bool dsc,
+ struct link_config_limits *limits)
{
- const struct intel_digital_connector_state *intel_conn_state =
- to_intel_digital_connector_state(conn_state);
- struct intel_connector *connector =
- to_intel_connector(conn_state->connector);
+ /*
+ * for MST we always configure max link bw - the spec doesn't
+ * seem to suggest we should do otherwise.
+ */
+ limits->min_rate = limits->max_rate =
+ intel_dp_max_link_rate(intel_dp);
- if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
- return connector->base.display_info.has_audio;
- else
- return intel_conn_state->force_audio == HDMI_AUDIO_ON;
+ limits->min_lane_count = limits->max_lane_count =
+ intel_dp_max_lane_count(intel_dp);
+
+ limits->pipe.min_bpp = intel_dp_min_bpp(crtc_state->output_format);
+ /*
+ * FIXME: If all the streams can't fit into the link with
+ * their current pipe_bpp we should reduce pipe_bpp across
+ * the board until things start to fit. Until then we
+ * limit to <= 8bpc since that's what was hardcoded for all
+ * MST streams previously. This hack should be removed once
+ * we have the proper retry logic in place.
+ */
+ limits->pipe.max_bpp = min(crtc_state->pipe_bpp, 24);
+
+ intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
+
+ return intel_dp_compute_config_link_bpp_limits(intel_dp,
+ crtc_state,
+ dsc,
+ limits);
}
static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
@@ -312,7 +341,8 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
const struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
struct link_config_limits limits;
- int ret;
+ bool dsc_needed;
+ int ret = 0;
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
@@ -321,42 +351,40 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->has_pch_encoder = false;
- pipe_config->has_audio =
- intel_dp_mst_has_audio(conn_state) &&
- intel_audio_compute_config(encoder, pipe_config, conn_state);
-
- /*
- * for MST we always configure max link bw - the spec doesn't
- * seem to suggest we should do otherwise.
- */
- limits.min_rate =
- limits.max_rate = intel_dp_max_link_rate(intel_dp);
-
- limits.min_lane_count =
- limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
-
- limits.min_bpp = intel_dp_min_bpp(pipe_config->output_format);
- /*
- * FIXME: If all the streams can't fit into the link with
- * their current pipe_bpp we should reduce pipe_bpp across
- * the board until things start to fit. Until then we
- * limit to <= 8bpc since that's what was hardcoded for all
- * MST streams previously. This hack should be removed once
- * we have the proper retry logic in place.
- */
- limits.max_bpp = min(pipe_config->pipe_bpp, 24);
+ dsc_needed = intel_dp->force_dsc_en ||
+ !intel_dp_mst_compute_config_limits(intel_dp,
+ pipe_config,
+ false,
+ &limits);
- intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits);
+ if (!dsc_needed) {
+ ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
+ conn_state, &limits);
- ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
- conn_state, &limits);
+ if (ret == -EDEADLK)
+ return ret;
- if (ret == -EDEADLK)
- return ret;
+ if (ret)
+ dsc_needed = true;
+ }
/* enable compression if the mode doesn't fit available BW */
- drm_dbg_kms(&dev_priv->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en);
- if (ret || intel_dp->force_dsc_en) {
+ if (dsc_needed) {
+ drm_dbg_kms(&dev_priv->drm, "Try DSC (fallback=%s, force=%s)\n",
+ str_yes_no(ret),
+ str_yes_no(intel_dp->force_dsc_en));
+
+ if (!intel_dp_mst_compute_config_limits(intel_dp,
+ pipe_config,
+ true,
+ &limits))
+ return -EINVAL;
+
+ /*
+ * FIXME: As bpc is hardcoded to 8, as mentioned above,
+ * WARN and ignore the debug flag force_dsc_bpc for now.
+ */
+ drm_WARN(&dev_priv->drm, intel_dp->force_dsc_bpc, "Cannot Force BPC for MST\n");
/*
* Try to get at least some timeslots and then see, if
* we can fit there with DSC.
@@ -387,6 +415,8 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
pipe_config->lane_lat_optim_mask =
bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
+ intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
+
intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
return 0;
@@ -556,12 +586,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
struct intel_dp *intel_dp = &dig_port->dp;
struct intel_connector *connector =
to_intel_connector(old_conn_state->connector);
- struct drm_dp_mst_topology_state *old_mst_state =
- drm_atomic_get_old_mst_topology_state(&state->base, &intel_dp->mst_mgr);
struct drm_dp_mst_topology_state *new_mst_state =
drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr);
- const struct drm_dp_mst_atomic_payload *old_payload =
- drm_atomic_get_mst_payload_state(old_mst_state, connector->port);
struct drm_dp_mst_atomic_payload *new_payload =
drm_atomic_get_mst_payload_state(new_mst_state, connector->port);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
@@ -571,8 +597,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state,
intel_hdcp_disable(intel_mst->connector);
- drm_dp_remove_payload(&intel_dp->mst_mgr, new_mst_state,
- old_payload, new_payload);
+ drm_dp_remove_payload_part1(&intel_dp->mst_mgr, new_mst_state, new_payload);
intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
}
@@ -587,6 +612,14 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
struct intel_dp *intel_dp = &dig_port->dp;
struct intel_connector *connector =
to_intel_connector(old_conn_state->connector);
+ struct drm_dp_mst_topology_state *old_mst_state =
+ drm_atomic_get_old_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+ struct drm_dp_mst_topology_state *new_mst_state =
+ drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr);
+ const struct drm_dp_mst_atomic_payload *old_payload =
+ drm_atomic_get_mst_payload_state(old_mst_state, connector->port);
+ struct drm_dp_mst_atomic_payload *new_payload =
+ drm_atomic_get_mst_payload_state(new_mst_state, connector->port);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
bool last_mst_stream;
@@ -607,6 +640,9 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
wait_for_act_sent(encoder, old_crtc_state);
+ drm_dp_remove_payload_part2(&intel_dp->mst_mgr, new_mst_state,
+ old_payload, new_payload);
+
intel_ddi_disable_transcoder_func(old_crtc_state);
if (DISPLAY_VER(dev_priv) >= 9)
@@ -726,8 +762,8 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
ret = drm_dp_add_payload_part1(&intel_dp->mst_mgr, mst_state,
drm_atomic_get_mst_payload_state(mst_state, connector->port));
if (ret < 0)
- drm_err(&dev_priv->drm, "Failed to create MST payload for %s: %d\n",
- connector->base.name, ret);
+ drm_dbg_kms(&dev_priv->drm, "Failed to create MST payload for %s: %d\n",
+ connector->base.name, ret);
/*
* Before Gen 12 this is not done as part of
@@ -791,6 +827,8 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
intel_de_rmw(dev_priv, CHICKEN_TRANS(trans), 0,
FECSTALL_DIS_DPTSTREAM_DPTTG);
+ intel_audio_sdp_split_update(pipe_config);
+
intel_enable_transcoder(pipe_config);
intel_crtc_vblank_on(pipe_config);
@@ -911,7 +949,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
int max_rate, mode_rate, max_lanes, max_link_clock;
int ret;
bool dsc = false, bigjoiner = false;
- u16 dsc_max_output_bpp = 0;
+ u16 dsc_max_compressed_bpp = 0;
u8 dsc_slice_count = 0;
int target_clock = mode->clock;
@@ -965,30 +1003,31 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
}
if (DISPLAY_VER(dev_priv) >= 10 &&
- drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) {
+ drm_dp_sink_supports_dsc(intel_connector->dp.dsc_dpcd)) {
/*
* TBD pass the connector BPC,
* for now U8_MAX so that max BPC on that platform would be picked
*/
- int pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, U8_MAX);
-
- if (drm_dp_sink_supports_fec(intel_dp->fec_capable)) {
- dsc_max_output_bpp =
- intel_dp_dsc_get_output_bpp(dev_priv,
- max_link_clock,
- max_lanes,
- target_clock,
- mode->hdisplay,
- bigjoiner,
- pipe_bpp, 64) >> 4;
+ int pipe_bpp = intel_dp_dsc_compute_max_bpp(intel_connector, U8_MAX);
+
+ if (drm_dp_sink_supports_fec(intel_connector->dp.fec_capability)) {
+ dsc_max_compressed_bpp =
+ intel_dp_dsc_get_max_compressed_bpp(dev_priv,
+ max_link_clock,
+ max_lanes,
+ target_clock,
+ mode->hdisplay,
+ bigjoiner,
+ INTEL_OUTPUT_FORMAT_RGB,
+ pipe_bpp, 64);
dsc_slice_count =
- intel_dp_dsc_get_slice_count(intel_dp,
+ intel_dp_dsc_get_slice_count(intel_connector,
target_clock,
mode->hdisplay,
bigjoiner);
}
- dsc = dsc_max_output_bpp && dsc_slice_count;
+ dsc = dsc_max_compressed_bpp && dsc_slice_count;
}
/*
@@ -1029,7 +1068,7 @@ intel_dp_mst_detect(struct drm_connector *connector,
struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_dp *intel_dp = intel_connector->mst_port;
- if (!INTEL_DISPLAY_ENABLED(i915))
+ if (!intel_display_device_enabled(i915))
return connector_status_disconnected;
if (drm_connector_is_unregistered(connector))
@@ -1096,6 +1135,21 @@ static int intel_dp_mst_add_properties(struct intel_dp *intel_dp,
return drm_connector_set_path_property(connector, pathprop);
}
+static void
+intel_dp_mst_read_decompression_port_dsc_caps(struct intel_dp *intel_dp,
+ struct intel_connector *connector)
+{
+ u8 dpcd_caps[DP_RECEIVER_CAP_SIZE];
+
+ if (!connector->dp.dsc_decompression_aux)
+ return;
+
+ if (drm_dp_read_dpcd_caps(connector->dp.dsc_decompression_aux, dpcd_caps) < 0)
+ return;
+
+ intel_dp_get_dsc_sink_cap(dpcd_caps[DP_DPCD_REV], connector);
+}
+
static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port,
const char *pathprop)
@@ -1118,6 +1172,14 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
intel_connector->port = port;
drm_dp_mst_get_port_malloc(port);
+ /*
+ * TODO: set the AUX for the actual MST port decompressing the stream.
+ * At the moment the driver only supports enabling this globally in the
+ * first downstream MST branch, via intel_dp's (root port) AUX.
+ */
+ intel_connector->dp.dsc_decompression_aux = &intel_dp->aux;
+ intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector);
+
connector = &intel_connector->base;
ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs,
DRM_MODE_CONNECTOR_DisplayPort);
diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.h b/drivers/gpu/drm/i915/display/intel_dpio_phy.h
index 9c7725dacb..4d43dbbdf8 100644
--- a/drivers/gpu/drm/i915/display/intel_dpio_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.h
@@ -26,6 +26,7 @@ enum dpio_phy {
DPIO_PHY2,
};
+#ifdef I915
void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
enum dpio_phy *phy, enum dpio_channel *ch);
void bxt_ddi_phy_set_signal_levels(struct intel_encoder *encoder,
@@ -70,5 +71,100 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void vlv_phy_reset_lanes(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state);
+#else
+static inline void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
+ enum dpio_phy *phy, enum dpio_channel *ch)
+{
+}
+static inline void bxt_ddi_phy_set_signal_levels(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+}
+static inline void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+{
+}
+static inline void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+{
+}
+static inline bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
+ enum dpio_phy phy)
+{
+ return false;
+}
+static inline bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
+ enum dpio_phy phy)
+{
+ return true;
+}
+static inline u8 bxt_ddi_phy_calc_lane_lat_optim_mask(u8 lane_count)
+{
+ return 0;
+}
+static inline void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
+ u8 lane_lat_optim_mask)
+{
+}
+static inline u8 bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
+{
+ return 0;
+}
+static inline enum dpio_channel vlv_dig_port_to_channel(struct intel_digital_port *dig_port)
+{
+ return DPIO_CH0;
+}
+static inline enum dpio_phy vlv_dig_port_to_phy(struct intel_digital_port *dig_port)
+{
+ return DPIO_PHY0;
+}
+static inline enum dpio_channel vlv_pipe_to_channel(enum pipe pipe)
+{
+ return DPIO_CH0;
+}
+static inline void chv_set_phy_signal_level(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ u32 deemph_reg_value, u32 margin_reg_value,
+ bool uniq_trans_scale)
+{
+}
+static inline void chv_data_lane_soft_reset(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ bool reset)
+{
+}
+static inline void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+}
+static inline void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+}
+static inline void chv_phy_release_cl2_override(struct intel_encoder *encoder)
+{
+}
+static inline void chv_phy_post_pll_disable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *old_crtc_state)
+{
+}
+
+static inline void vlv_set_phy_signal_level(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state,
+ u32 demph_reg_value, u32 preemph_reg_value,
+ u32 uniqtranscale_reg_value, u32 tx3_demph)
+{
+}
+static inline void vlv_phy_pre_pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+}
+static inline void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+}
+static inline void vlv_phy_reset_lanes(struct intel_encoder *encoder,
+ const struct intel_crtc_state *old_crtc_state)
+{
+}
+#endif
#endif /* __INTEL_DPIO_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index 999badfe29..d41c1dc9f6 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -7,6 +7,7 @@
#include <linux/string_helpers.h>
#include "i915_reg.h"
+#include "intel_atomic.h"
#include "intel_crtc.h"
#include "intel_cx0_phy.h"
#include "intel_de.h"
@@ -314,10 +315,11 @@ int pnv_calc_dpll_params(int refclk, struct dpll *clock)
{
clock->m = clock->m2 + 2;
clock->p = clock->p1 * clock->p2;
- if (WARN_ON(clock->n == 0 || clock->p == 0))
- return 0;
- clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
- clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
+
+ clock->vco = clock->n == 0 ? 0 :
+ DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
+ clock->dot = clock->p == 0 ? 0 :
+ DIV_ROUND_CLOSEST(clock->vco, clock->p);
return clock->dot;
}
@@ -331,10 +333,11 @@ int i9xx_calc_dpll_params(int refclk, struct dpll *clock)
{
clock->m = i9xx_dpll_compute_m(clock);
clock->p = clock->p1 * clock->p2;
- if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
- return 0;
- clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
- clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
+
+ clock->vco = clock->n + 2 == 0 ? 0 :
+ DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
+ clock->dot = clock->p == 0 ? 0 :
+ DIV_ROUND_CLOSEST(clock->vco, clock->p);
return clock->dot;
}
@@ -343,10 +346,11 @@ int vlv_calc_dpll_params(int refclk, struct dpll *clock)
{
clock->m = clock->m1 * clock->m2;
clock->p = clock->p1 * clock->p2 * 5;
- if (WARN_ON(clock->n == 0 || clock->p == 0))
- return 0;
- clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
- clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
+
+ clock->vco = clock->n == 0 ? 0 :
+ DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
+ clock->dot = clock->p == 0 ? 0 :
+ DIV_ROUND_CLOSEST(clock->vco, clock->p);
return clock->dot;
}
@@ -355,11 +359,11 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock)
{
clock->m = clock->m1 * clock->m2;
clock->p = clock->p1 * clock->p2 * 5;
- if (WARN_ON(clock->n == 0 || clock->p == 0))
- return 0;
- clock->vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock->m),
- clock->n << 22);
- clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
+
+ clock->vco = clock->n == 0 ? 0 :
+ DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock->m), clock->n << 22);
+ clock->dot = clock->p == 0 ? 0 :
+ DIV_ROUND_CLOSEST(clock->vco, clock->p);
return clock->dot;
}
@@ -1179,6 +1183,8 @@ static int ilk_crtc_compute_clock(struct intel_atomic_state *state,
refclk, NULL, &crtc_state->dpll))
return -EINVAL;
+ i9xx_calc_dpll_params(refclk, &crtc_state->dpll);
+
ilk_compute_dpll(crtc_state, &crtc_state->dpll,
&crtc_state->dpll);
@@ -1253,6 +1259,8 @@ static int chv_crtc_compute_clock(struct intel_atomic_state *state,
refclk, NULL, &crtc_state->dpll))
return -EINVAL;
+ chv_calc_dpll_params(refclk, &crtc_state->dpll);
+
chv_compute_dpll(crtc_state);
/* FIXME this is a mess */
@@ -1275,9 +1283,10 @@ static int vlv_crtc_compute_clock(struct intel_atomic_state *state,
if (!crtc_state->clock_set &&
!vlv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
- refclk, NULL, &crtc_state->dpll)) {
+ refclk, NULL, &crtc_state->dpll))
return -EINVAL;
- }
+
+ vlv_calc_dpll_params(refclk, &crtc_state->dpll);
vlv_compute_dpll(crtc_state);
@@ -1327,6 +1336,8 @@ static int g4x_crtc_compute_clock(struct intel_atomic_state *state,
refclk, NULL, &crtc_state->dpll))
return -EINVAL;
+ i9xx_calc_dpll_params(refclk, &crtc_state->dpll);
+
i9xx_compute_dpll(crtc_state, &crtc_state->dpll,
&crtc_state->dpll);
@@ -1365,6 +1376,8 @@ static int pnv_crtc_compute_clock(struct intel_atomic_state *state,
refclk, NULL, &crtc_state->dpll))
return -EINVAL;
+ pnv_calc_dpll_params(refclk, &crtc_state->dpll);
+
i9xx_compute_dpll(crtc_state, &crtc_state->dpll,
&crtc_state->dpll);
@@ -1401,6 +1414,8 @@ static int i9xx_crtc_compute_clock(struct intel_atomic_state *state,
refclk, NULL, &crtc_state->dpll))
return -EINVAL;
+ i9xx_calc_dpll_params(refclk, &crtc_state->dpll);
+
i9xx_compute_dpll(crtc_state, &crtc_state->dpll,
&crtc_state->dpll);
@@ -1441,6 +1456,8 @@ static int i8xx_crtc_compute_clock(struct intel_atomic_state *state,
refclk, NULL, &crtc_state->dpll))
return -EINVAL;
+ i9xx_calc_dpll_params(refclk, &crtc_state->dpll);
+
i8xx_compute_dpll(crtc_state, &crtc_state->dpll,
&crtc_state->dpll);
@@ -1990,7 +2007,7 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
vlv_enable_pll(crtc_state);
}
- kfree(crtc_state);
+ intel_crtc_destroy_state(&crtc->base, &crtc_state->uapi);
return 0;
}
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
index 6d68b36292..399653a20f 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
@@ -107,22 +107,20 @@ struct intel_dpll_mgr {
struct intel_crtc *crtc,
struct intel_encoder *encoder);
void (*update_ref_clks)(struct drm_i915_private *i915);
- void (*dump_hw_state)(struct drm_i915_private *dev_priv,
+ void (*dump_hw_state)(struct drm_i915_private *i915,
const struct intel_dpll_hw_state *hw_state);
};
static void
-intel_atomic_duplicate_dpll_state(struct drm_i915_private *dev_priv,
+intel_atomic_duplicate_dpll_state(struct drm_i915_private *i915,
struct intel_shared_dpll_state *shared_dpll)
{
- enum intel_dpll_id i;
+ struct intel_shared_dpll *pll;
+ int i;
/* Copy shared dpll state */
- for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) {
- struct intel_shared_dpll *pll = &dev_priv->display.dpll.shared_dplls[i];
-
- shared_dpll[i] = pll->state;
- }
+ for_each_shared_dpll(i915, pll, i)
+ shared_dpll[pll->index] = pll->state;
}
static struct intel_shared_dpll_state *
@@ -144,33 +142,42 @@ intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s)
/**
* intel_get_shared_dpll_by_id - get a DPLL given its id
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
* @id: pll id
*
* Returns:
* A pointer to the DPLL with @id
*/
struct intel_shared_dpll *
-intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
+intel_get_shared_dpll_by_id(struct drm_i915_private *i915,
enum intel_dpll_id id)
{
- return &dev_priv->display.dpll.shared_dplls[id];
+ struct intel_shared_dpll *pll;
+ int i;
+
+ for_each_shared_dpll(i915, pll, i) {
+ if (pll->info->id == id)
+ return pll;
+ }
+
+ MISSING_CASE(id);
+ return NULL;
}
/* For ILK+ */
-void assert_shared_dpll(struct drm_i915_private *dev_priv,
+void assert_shared_dpll(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
bool state)
{
bool cur_state;
struct intel_dpll_hw_state hw_state;
- if (drm_WARN(&dev_priv->drm, !pll,
+ if (drm_WARN(&i915->drm, !pll,
"asserting DPLL %s with no DPLL\n", str_on_off(state)))
return;
- cur_state = intel_dpll_get_hw_state(dev_priv, pll, &hw_state);
- I915_STATE_WARN(dev_priv, cur_state != state,
+ cur_state = intel_dpll_get_hw_state(i915, pll, &hw_state);
+ I915_STATE_WARN(i915, cur_state != state,
"%s assertion failure (expected %s, current %s)\n",
pll->info->name, str_on_off(state),
str_on_off(cur_state));
@@ -221,41 +228,41 @@ intel_tc_pll_enable_reg(struct drm_i915_private *i915,
void intel_enable_shared_dpll(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 drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_shared_dpll *pll = crtc_state->shared_dpll;
unsigned int pipe_mask = BIT(crtc->pipe);
unsigned int old_mask;
- if (drm_WARN_ON(&dev_priv->drm, pll == NULL))
+ if (drm_WARN_ON(&i915->drm, pll == NULL))
return;
- mutex_lock(&dev_priv->display.dpll.lock);
+ mutex_lock(&i915->display.dpll.lock);
old_mask = pll->active_mask;
- if (drm_WARN_ON(&dev_priv->drm, !(pll->state.pipe_mask & pipe_mask)) ||
- drm_WARN_ON(&dev_priv->drm, pll->active_mask & pipe_mask))
+ if (drm_WARN_ON(&i915->drm, !(pll->state.pipe_mask & pipe_mask)) ||
+ drm_WARN_ON(&i915->drm, pll->active_mask & pipe_mask))
goto out;
pll->active_mask |= pipe_mask;
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"enable %s (active 0x%x, on? %d) for [CRTC:%d:%s]\n",
pll->info->name, pll->active_mask, pll->on,
crtc->base.base.id, crtc->base.name);
if (old_mask) {
- drm_WARN_ON(&dev_priv->drm, !pll->on);
- assert_shared_dpll_enabled(dev_priv, pll);
+ drm_WARN_ON(&i915->drm, !pll->on);
+ assert_shared_dpll_enabled(i915, pll);
goto out;
}
- drm_WARN_ON(&dev_priv->drm, pll->on);
+ drm_WARN_ON(&i915->drm, pll->on);
- drm_dbg_kms(&dev_priv->drm, "enabling %s\n", pll->info->name);
- pll->info->funcs->enable(dev_priv, pll);
+ drm_dbg_kms(&i915->drm, "enabling %s\n", pll->info->name);
+ pll->info->funcs->enable(i915, pll);
pll->on = true;
out:
- mutex_unlock(&dev_priv->display.dpll.lock);
+ mutex_unlock(&i915->display.dpll.lock);
}
/**
@@ -267,41 +274,57 @@ out:
void intel_disable_shared_dpll(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 drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_shared_dpll *pll = crtc_state->shared_dpll;
unsigned int pipe_mask = BIT(crtc->pipe);
/* PCH only available on ILK+ */
- if (DISPLAY_VER(dev_priv) < 5)
+ if (DISPLAY_VER(i915) < 5)
return;
if (pll == NULL)
return;
- mutex_lock(&dev_priv->display.dpll.lock);
- if (drm_WARN(&dev_priv->drm, !(pll->active_mask & pipe_mask),
+ mutex_lock(&i915->display.dpll.lock);
+ if (drm_WARN(&i915->drm, !(pll->active_mask & pipe_mask),
"%s not used by [CRTC:%d:%s]\n", pll->info->name,
crtc->base.base.id, crtc->base.name))
goto out;
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"disable %s (active 0x%x, on? %d) for [CRTC:%d:%s]\n",
pll->info->name, pll->active_mask, pll->on,
crtc->base.base.id, crtc->base.name);
- assert_shared_dpll_enabled(dev_priv, pll);
- drm_WARN_ON(&dev_priv->drm, !pll->on);
+ assert_shared_dpll_enabled(i915, pll);
+ drm_WARN_ON(&i915->drm, !pll->on);
pll->active_mask &= ~pipe_mask;
if (pll->active_mask)
goto out;
- drm_dbg_kms(&dev_priv->drm, "disabling %s\n", pll->info->name);
- pll->info->funcs->disable(dev_priv, pll);
+ drm_dbg_kms(&i915->drm, "disabling %s\n", pll->info->name);
+ pll->info->funcs->disable(i915, pll);
pll->on = false;
out:
- mutex_unlock(&dev_priv->display.dpll.lock);
+ mutex_unlock(&i915->display.dpll.lock);
+}
+
+static unsigned long
+intel_dpll_mask_all(struct drm_i915_private *i915)
+{
+ struct intel_shared_dpll *pll;
+ unsigned long dpll_mask = 0;
+ int i;
+
+ for_each_shared_dpll(i915, pll, i) {
+ drm_WARN_ON(&i915->drm, dpll_mask & BIT(pll->info->id));
+
+ dpll_mask |= BIT(pll->info->id);
+ }
+
+ return dpll_mask;
}
static struct intel_shared_dpll *
@@ -310,33 +333,38 @@ intel_find_shared_dpll(struct intel_atomic_state *state,
const struct intel_dpll_hw_state *pll_state,
unsigned long dpll_mask)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- struct intel_shared_dpll *pll, *unused_pll = NULL;
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ unsigned long dpll_mask_all = intel_dpll_mask_all(i915);
struct intel_shared_dpll_state *shared_dpll;
- enum intel_dpll_id i;
+ struct intel_shared_dpll *unused_pll = NULL;
+ enum intel_dpll_id id;
shared_dpll = intel_atomic_get_shared_dpll_state(&state->base);
- drm_WARN_ON(&dev_priv->drm, dpll_mask & ~(BIT(I915_NUM_PLLS) - 1));
+ drm_WARN_ON(&i915->drm, dpll_mask & ~dpll_mask_all);
+
+ for_each_set_bit(id, &dpll_mask, fls(dpll_mask_all)) {
+ struct intel_shared_dpll *pll;
- for_each_set_bit(i, &dpll_mask, I915_NUM_PLLS) {
- pll = &dev_priv->display.dpll.shared_dplls[i];
+ pll = intel_get_shared_dpll_by_id(i915, id);
+ if (!pll)
+ continue;
/* Only want to check enabled timings first */
- if (shared_dpll[i].pipe_mask == 0) {
+ if (shared_dpll[pll->index].pipe_mask == 0) {
if (!unused_pll)
unused_pll = pll;
continue;
}
if (memcmp(pll_state,
- &shared_dpll[i].hw_state,
+ &shared_dpll[pll->index].hw_state,
sizeof(*pll_state)) == 0) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"[CRTC:%d:%s] sharing existing %s (pipe mask 0x%x, active 0x%x)\n",
crtc->base.base.id, crtc->base.name,
pll->info->name,
- shared_dpll[i].pipe_mask,
+ shared_dpll[pll->index].pipe_mask,
pll->active_mask);
return pll;
}
@@ -344,7 +372,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state,
/* Ok no matching timings, maybe there's a free one? */
if (unused_pll) {
- drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] allocated %s\n",
+ drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] allocated %s\n",
crtc->base.base.id, crtc->base.name,
unused_pll->info->name);
return unused_pll;
@@ -383,14 +411,13 @@ intel_reference_shared_dpll(struct intel_atomic_state *state,
const struct intel_dpll_hw_state *pll_state)
{
struct intel_shared_dpll_state *shared_dpll;
- const enum intel_dpll_id id = pll->info->id;
shared_dpll = intel_atomic_get_shared_dpll_state(&state->base);
- if (shared_dpll[id].pipe_mask == 0)
- shared_dpll[id].hw_state = *pll_state;
+ if (shared_dpll[pll->index].pipe_mask == 0)
+ shared_dpll[pll->index].hw_state = *pll_state;
- intel_reference_shared_dpll_crtc(crtc, pll, &shared_dpll[id]);
+ intel_reference_shared_dpll_crtc(crtc, pll, &shared_dpll[pll->index]);
}
/**
@@ -421,11 +448,10 @@ static void intel_unreference_shared_dpll(struct intel_atomic_state *state,
const struct intel_shared_dpll *pll)
{
struct intel_shared_dpll_state *shared_dpll;
- const enum intel_dpll_id id = pll->info->id;
shared_dpll = intel_atomic_get_shared_dpll_state(&state->base);
- intel_unreference_shared_dpll_crtc(crtc, pll, &shared_dpll[id]);
+ intel_unreference_shared_dpll_crtc(crtc, pll, &shared_dpll[pll->index]);
}
static void intel_put_dpll(struct intel_atomic_state *state,
@@ -457,22 +483,19 @@ static void intel_put_dpll(struct intel_atomic_state *state,
*/
void intel_shared_dpll_swap_state(struct intel_atomic_state *state)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_shared_dpll_state *shared_dpll = state->shared_dpll;
- enum intel_dpll_id i;
+ struct intel_shared_dpll *pll;
+ int i;
if (!state->dpll_set)
return;
- for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) {
- struct intel_shared_dpll *pll =
- &dev_priv->display.dpll.shared_dplls[i];
-
- swap(pll->state, shared_dpll[i]);
- }
+ for_each_shared_dpll(i915, pll, i)
+ swap(pll->state, shared_dpll[pll->index]);
}
-static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
+static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
@@ -480,48 +503,48 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
intel_wakeref_t wakeref;
u32 val;
- wakeref = intel_display_power_get_if_enabled(dev_priv,
+ wakeref = intel_display_power_get_if_enabled(i915,
POWER_DOMAIN_DISPLAY_CORE);
if (!wakeref)
return false;
- val = intel_de_read(dev_priv, PCH_DPLL(id));
+ val = intel_de_read(i915, PCH_DPLL(id));
hw_state->dpll = val;
- hw_state->fp0 = intel_de_read(dev_priv, PCH_FP0(id));
- hw_state->fp1 = intel_de_read(dev_priv, PCH_FP1(id));
+ hw_state->fp0 = intel_de_read(i915, PCH_FP0(id));
+ hw_state->fp1 = intel_de_read(i915, PCH_FP1(id));
- intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
+ intel_display_power_put(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref);
return val & DPLL_VCO_ENABLE;
}
-static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
+static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *i915)
{
u32 val;
bool enabled;
- val = intel_de_read(dev_priv, PCH_DREF_CONTROL);
+ val = intel_de_read(i915, PCH_DREF_CONTROL);
enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
DREF_SUPERSPREAD_SOURCE_MASK));
- I915_STATE_WARN(dev_priv, !enabled,
+ I915_STATE_WARN(i915, !enabled,
"PCH refclk assertion failure, should be active but is disabled\n");
}
-static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
+static void ibx_pch_dpll_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
const enum intel_dpll_id id = pll->info->id;
/* PCH refclock must be enabled first */
- ibx_assert_pch_refclk_enabled(dev_priv);
+ ibx_assert_pch_refclk_enabled(i915);
- intel_de_write(dev_priv, PCH_FP0(id), pll->state.hw_state.fp0);
- intel_de_write(dev_priv, PCH_FP1(id), pll->state.hw_state.fp1);
+ intel_de_write(i915, PCH_FP0(id), pll->state.hw_state.fp0);
+ intel_de_write(i915, PCH_FP1(id), pll->state.hw_state.fp1);
- intel_de_write(dev_priv, PCH_DPLL(id), pll->state.hw_state.dpll);
+ intel_de_write(i915, PCH_DPLL(id), pll->state.hw_state.dpll);
/* Wait for the clocks to stabilize. */
- intel_de_posting_read(dev_priv, PCH_DPLL(id));
+ intel_de_posting_read(i915, PCH_DPLL(id));
udelay(150);
/* The pixel multiplier can only be updated once the
@@ -529,18 +552,18 @@ static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
*
* So write it again.
*/
- intel_de_write(dev_priv, PCH_DPLL(id), pll->state.hw_state.dpll);
- intel_de_posting_read(dev_priv, PCH_DPLL(id));
+ intel_de_write(i915, PCH_DPLL(id), pll->state.hw_state.dpll);
+ intel_de_posting_read(i915, PCH_DPLL(id));
udelay(200);
}
-static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
+static void ibx_pch_dpll_disable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
const enum intel_dpll_id id = pll->info->id;
- intel_de_write(dev_priv, PCH_DPLL(id), 0);
- intel_de_posting_read(dev_priv, PCH_DPLL(id));
+ intel_de_write(i915, PCH_DPLL(id), 0);
+ intel_de_posting_read(i915, PCH_DPLL(id));
udelay(200);
}
@@ -557,16 +580,16 @@ static int ibx_get_dpll(struct intel_atomic_state *state,
{
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 drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_shared_dpll *pll;
- enum intel_dpll_id i;
+ enum intel_dpll_id id;
- if (HAS_PCH_IBX(dev_priv)) {
+ if (HAS_PCH_IBX(i915)) {
/* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
- i = (enum intel_dpll_id) crtc->pipe;
- pll = &dev_priv->display.dpll.shared_dplls[i];
+ id = (enum intel_dpll_id) crtc->pipe;
+ pll = intel_get_shared_dpll_by_id(i915, id);
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"[CRTC:%d:%s] using pre-allocated %s\n",
crtc->base.base.id, crtc->base.name,
pll->info->name);
@@ -589,10 +612,10 @@ static int ibx_get_dpll(struct intel_atomic_state *state,
return 0;
}
-static void ibx_dump_hw_state(struct drm_i915_private *dev_priv,
+static void ibx_dump_hw_state(struct drm_i915_private *i915,
const struct intel_dpll_hw_state *hw_state)
{
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
"fp0: 0x%x, fp1: 0x%x\n",
hw_state->dpll,
@@ -621,57 +644,57 @@ static const struct intel_dpll_mgr pch_pll_mgr = {
.dump_hw_state = ibx_dump_hw_state,
};
-static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
+static void hsw_ddi_wrpll_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
const enum intel_dpll_id id = pll->info->id;
- intel_de_write(dev_priv, WRPLL_CTL(id), pll->state.hw_state.wrpll);
- intel_de_posting_read(dev_priv, WRPLL_CTL(id));
+ intel_de_write(i915, WRPLL_CTL(id), pll->state.hw_state.wrpll);
+ intel_de_posting_read(i915, WRPLL_CTL(id));
udelay(20);
}
-static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
+static void hsw_ddi_spll_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
- intel_de_write(dev_priv, SPLL_CTL, pll->state.hw_state.spll);
- intel_de_posting_read(dev_priv, SPLL_CTL);
+ intel_de_write(i915, SPLL_CTL, pll->state.hw_state.spll);
+ intel_de_posting_read(i915, SPLL_CTL);
udelay(20);
}
-static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
+static void hsw_ddi_wrpll_disable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
const enum intel_dpll_id id = pll->info->id;
- intel_de_rmw(dev_priv, WRPLL_CTL(id), WRPLL_PLL_ENABLE, 0);
- intel_de_posting_read(dev_priv, WRPLL_CTL(id));
+ intel_de_rmw(i915, WRPLL_CTL(id), WRPLL_PLL_ENABLE, 0);
+ intel_de_posting_read(i915, WRPLL_CTL(id));
/*
* Try to set up the PCH reference clock once all DPLLs
* that depend on it have been shut down.
*/
- if (dev_priv->display.dpll.pch_ssc_use & BIT(id))
- intel_init_pch_refclk(dev_priv);
+ if (i915->display.dpll.pch_ssc_use & BIT(id))
+ intel_init_pch_refclk(i915);
}
-static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
+static void hsw_ddi_spll_disable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
enum intel_dpll_id id = pll->info->id;
- intel_de_rmw(dev_priv, SPLL_CTL, SPLL_PLL_ENABLE, 0);
- intel_de_posting_read(dev_priv, SPLL_CTL);
+ intel_de_rmw(i915, SPLL_CTL, SPLL_PLL_ENABLE, 0);
+ intel_de_posting_read(i915, SPLL_CTL);
/*
* Try to set up the PCH reference clock once all DPLLs
* that depend on it have been shut down.
*/
- if (dev_priv->display.dpll.pch_ssc_use & BIT(id))
- intel_init_pch_refclk(dev_priv);
+ if (i915->display.dpll.pch_ssc_use & BIT(id))
+ intel_init_pch_refclk(i915);
}
-static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
+static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
@@ -679,35 +702,35 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
intel_wakeref_t wakeref;
u32 val;
- wakeref = intel_display_power_get_if_enabled(dev_priv,
+ wakeref = intel_display_power_get_if_enabled(i915,
POWER_DOMAIN_DISPLAY_CORE);
if (!wakeref)
return false;
- val = intel_de_read(dev_priv, WRPLL_CTL(id));
+ val = intel_de_read(i915, WRPLL_CTL(id));
hw_state->wrpll = val;
- intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
+ intel_display_power_put(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref);
return val & WRPLL_PLL_ENABLE;
}
-static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
+static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
intel_wakeref_t wakeref;
u32 val;
- wakeref = intel_display_power_get_if_enabled(dev_priv,
+ wakeref = intel_display_power_get_if_enabled(i915,
POWER_DOMAIN_DISPLAY_CORE);
if (!wakeref)
return false;
- val = intel_de_read(dev_priv, SPLL_CTL);
+ val = intel_de_read(i915, SPLL_CTL);
hw_state->spll = val;
- intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
+ intel_display_power_put(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref);
return val & SPLL_PLL_ENABLE;
}
@@ -918,7 +941,7 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */,
*r2_out = best.r2;
}
-static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv,
+static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *i915,
const struct intel_shared_dpll *pll,
const struct intel_dpll_hw_state *pll_state)
{
@@ -929,8 +952,8 @@ static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv,
switch (wrpll & WRPLL_REF_MASK) {
case WRPLL_REF_SPECIAL_HSW:
/* Muxed-SSC for BDW, non-SSC for non-ULT HSW. */
- if (IS_HASWELL(dev_priv) && !IS_HASWELL_ULT(dev_priv)) {
- refclk = dev_priv->display.dpll.ref_clks.nssc;
+ if (IS_HASWELL(i915) && !IS_HASWELL_ULT(i915)) {
+ refclk = i915->display.dpll.ref_clks.nssc;
break;
}
fallthrough;
@@ -940,7 +963,7 @@ static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv,
* code only cares about 5% accuracy, and spread is a max of
* 0.5% downspread.
*/
- refclk = dev_priv->display.dpll.ref_clks.ssc;
+ refclk = i915->display.dpll.ref_clks.ssc;
break;
case WRPLL_REF_LCPLL:
refclk = 2700000;
@@ -996,7 +1019,7 @@ hsw_ddi_wrpll_get_dpll(struct intel_atomic_state *state,
static int
hsw_ddi_lcpll_compute_dpll(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
int clock = crtc_state->port_clock;
switch (clock / 2) {
@@ -1005,7 +1028,7 @@ hsw_ddi_lcpll_compute_dpll(struct intel_crtc_state *crtc_state)
case 270000:
return 0;
default:
- drm_dbg_kms(&dev_priv->drm, "Invalid clock for DP: %d\n",
+ drm_dbg_kms(&i915->drm, "Invalid clock for DP: %d\n",
clock);
return -EINVAL;
}
@@ -1014,7 +1037,7 @@ hsw_ddi_lcpll_compute_dpll(struct intel_crtc_state *crtc_state)
static struct intel_shared_dpll *
hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
struct intel_shared_dpll *pll;
enum intel_dpll_id pll_id;
int clock = crtc_state->port_clock;
@@ -1034,7 +1057,7 @@ hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state)
return NULL;
}
- pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
+ pll = intel_get_shared_dpll_by_id(i915, pll_id);
if (!pll)
return NULL;
@@ -1170,10 +1193,10 @@ static void hsw_update_dpll_ref_clks(struct drm_i915_private *i915)
i915->display.dpll.ref_clks.nssc = 135000;
}
-static void hsw_dump_hw_state(struct drm_i915_private *dev_priv,
+static void hsw_dump_hw_state(struct drm_i915_private *i915,
const struct intel_dpll_hw_state *hw_state)
{
- drm_dbg_kms(&dev_priv->drm, "dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
+ drm_dbg_kms(&i915->drm, "dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
hw_state->wrpll, hw_state->spll);
}
@@ -1191,17 +1214,17 @@ static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
.get_freq = hsw_ddi_spll_get_freq,
};
-static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
+static void hsw_ddi_lcpll_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
}
-static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
+static void hsw_ddi_lcpll_disable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
}
-static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
+static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
@@ -1265,60 +1288,60 @@ static const struct skl_dpll_regs skl_dpll_regs[4] = {
},
};
-static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
+static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
const enum intel_dpll_id id = pll->info->id;
- intel_de_rmw(dev_priv, DPLL_CTRL1,
+ intel_de_rmw(i915, DPLL_CTRL1,
DPLL_CTRL1_HDMI_MODE(id) | DPLL_CTRL1_SSC(id) | DPLL_CTRL1_LINK_RATE_MASK(id),
pll->state.hw_state.ctrl1 << (id * 6));
- intel_de_posting_read(dev_priv, DPLL_CTRL1);
+ intel_de_posting_read(i915, DPLL_CTRL1);
}
-static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
+static void skl_ddi_pll_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
const struct skl_dpll_regs *regs = skl_dpll_regs;
const enum intel_dpll_id id = pll->info->id;
- skl_ddi_pll_write_ctrl1(dev_priv, pll);
+ skl_ddi_pll_write_ctrl1(i915, pll);
- intel_de_write(dev_priv, regs[id].cfgcr1, pll->state.hw_state.cfgcr1);
- intel_de_write(dev_priv, regs[id].cfgcr2, pll->state.hw_state.cfgcr2);
- intel_de_posting_read(dev_priv, regs[id].cfgcr1);
- intel_de_posting_read(dev_priv, regs[id].cfgcr2);
+ intel_de_write(i915, regs[id].cfgcr1, pll->state.hw_state.cfgcr1);
+ intel_de_write(i915, regs[id].cfgcr2, pll->state.hw_state.cfgcr2);
+ intel_de_posting_read(i915, regs[id].cfgcr1);
+ intel_de_posting_read(i915, regs[id].cfgcr2);
/* the enable bit is always bit 31 */
- intel_de_rmw(dev_priv, regs[id].ctl, 0, LCPLL_PLL_ENABLE);
+ intel_de_rmw(i915, regs[id].ctl, 0, LCPLL_PLL_ENABLE);
- if (intel_de_wait_for_set(dev_priv, DPLL_STATUS, DPLL_LOCK(id), 5))
- drm_err(&dev_priv->drm, "DPLL %d not locked\n", id);
+ if (intel_de_wait_for_set(i915, DPLL_STATUS, DPLL_LOCK(id), 5))
+ drm_err(&i915->drm, "DPLL %d not locked\n", id);
}
-static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
+static void skl_ddi_dpll0_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
- skl_ddi_pll_write_ctrl1(dev_priv, pll);
+ skl_ddi_pll_write_ctrl1(i915, pll);
}
-static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
+static void skl_ddi_pll_disable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
const struct skl_dpll_regs *regs = skl_dpll_regs;
const enum intel_dpll_id id = pll->info->id;
/* the enable bit is always bit 31 */
- intel_de_rmw(dev_priv, regs[id].ctl, LCPLL_PLL_ENABLE, 0);
- intel_de_posting_read(dev_priv, regs[id].ctl);
+ intel_de_rmw(i915, regs[id].ctl, LCPLL_PLL_ENABLE, 0);
+ intel_de_posting_read(i915, regs[id].ctl);
}
-static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
+static void skl_ddi_dpll0_disable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
}
-static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
+static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
@@ -1328,34 +1351,34 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
intel_wakeref_t wakeref;
bool ret;
- wakeref = intel_display_power_get_if_enabled(dev_priv,
+ wakeref = intel_display_power_get_if_enabled(i915,
POWER_DOMAIN_DISPLAY_CORE);
if (!wakeref)
return false;
ret = false;
- val = intel_de_read(dev_priv, regs[id].ctl);
+ val = intel_de_read(i915, regs[id].ctl);
if (!(val & LCPLL_PLL_ENABLE))
goto out;
- val = intel_de_read(dev_priv, DPLL_CTRL1);
+ val = intel_de_read(i915, DPLL_CTRL1);
hw_state->ctrl1 = (val >> (id * 6)) & 0x3f;
/* avoid reading back stale values if HDMI mode is not enabled */
if (val & DPLL_CTRL1_HDMI_MODE(id)) {
- hw_state->cfgcr1 = intel_de_read(dev_priv, regs[id].cfgcr1);
- hw_state->cfgcr2 = intel_de_read(dev_priv, regs[id].cfgcr2);
+ hw_state->cfgcr1 = intel_de_read(i915, regs[id].cfgcr1);
+ hw_state->cfgcr2 = intel_de_read(i915, regs[id].cfgcr2);
}
ret = true;
out:
- intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
+ intel_display_power_put(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref);
return ret;
}
-static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
+static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
@@ -1365,7 +1388,7 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
u32 val;
bool ret;
- wakeref = intel_display_power_get_if_enabled(dev_priv,
+ wakeref = intel_display_power_get_if_enabled(i915,
POWER_DOMAIN_DISPLAY_CORE);
if (!wakeref)
return false;
@@ -1373,17 +1396,17 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
ret = false;
/* DPLL0 is always enabled since it drives CDCLK */
- val = intel_de_read(dev_priv, regs[id].ctl);
- if (drm_WARN_ON(&dev_priv->drm, !(val & LCPLL_PLL_ENABLE)))
+ val = intel_de_read(i915, regs[id].ctl);
+ if (drm_WARN_ON(&i915->drm, !(val & LCPLL_PLL_ENABLE)))
goto out;
- val = intel_de_read(dev_priv, DPLL_CTRL1);
+ val = intel_de_read(i915, DPLL_CTRL1);
hw_state->ctrl1 = (val >> (id * 6)) & 0x3f;
ret = true;
out:
- intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
+ intel_display_power_put(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref);
return ret;
}
@@ -1873,10 +1896,10 @@ static void skl_update_dpll_ref_clks(struct drm_i915_private *i915)
i915->display.dpll.ref_clks.nssc = i915->display.cdclk.hw.ref;
}
-static void skl_dump_hw_state(struct drm_i915_private *dev_priv,
+static void skl_dump_hw_state(struct drm_i915_private *i915,
const struct intel_dpll_hw_state *hw_state)
{
- drm_dbg_kms(&dev_priv->drm, "dpll_hw_state: "
+ drm_dbg_kms(&i915->drm, "dpll_hw_state: "
"ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
hw_state->ctrl1,
hw_state->cfgcr1,
@@ -1914,129 +1937,129 @@ static const struct intel_dpll_mgr skl_pll_mgr = {
.dump_hw_state = skl_dump_hw_state,
};
-static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
- struct intel_shared_dpll *pll)
+static void bxt_ddi_pll_enable(struct drm_i915_private *i915,
+ struct intel_shared_dpll *pll)
{
u32 temp;
enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
enum dpio_phy phy;
enum dpio_channel ch;
- bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
+ bxt_port_to_phy_channel(i915, port, &phy, &ch);
/* Non-SSC reference */
- intel_de_rmw(dev_priv, BXT_PORT_PLL_ENABLE(port), 0, PORT_PLL_REF_SEL);
+ intel_de_rmw(i915, BXT_PORT_PLL_ENABLE(port), 0, PORT_PLL_REF_SEL);
- if (IS_GEMINILAKE(dev_priv)) {
- intel_de_rmw(dev_priv, BXT_PORT_PLL_ENABLE(port),
+ if (IS_GEMINILAKE(i915)) {
+ intel_de_rmw(i915, BXT_PORT_PLL_ENABLE(port),
0, PORT_PLL_POWER_ENABLE);
- if (wait_for_us((intel_de_read(dev_priv, BXT_PORT_PLL_ENABLE(port)) &
+ if (wait_for_us((intel_de_read(i915, BXT_PORT_PLL_ENABLE(port)) &
PORT_PLL_POWER_STATE), 200))
- drm_err(&dev_priv->drm,
+ drm_err(&i915->drm,
"Power state not set for PLL:%d\n", port);
}
/* Disable 10 bit clock */
- intel_de_rmw(dev_priv, BXT_PORT_PLL_EBB_4(phy, ch),
+ intel_de_rmw(i915, BXT_PORT_PLL_EBB_4(phy, ch),
PORT_PLL_10BIT_CLK_ENABLE, 0);
/* Write P1 & P2 */
- intel_de_rmw(dev_priv, BXT_PORT_PLL_EBB_0(phy, ch),
+ intel_de_rmw(i915, BXT_PORT_PLL_EBB_0(phy, ch),
PORT_PLL_P1_MASK | PORT_PLL_P2_MASK, pll->state.hw_state.ebb0);
/* Write M2 integer */
- intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 0),
+ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 0),
PORT_PLL_M2_INT_MASK, pll->state.hw_state.pll0);
/* Write N */
- intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 1),
+ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 1),
PORT_PLL_N_MASK, pll->state.hw_state.pll1);
/* Write M2 fraction */
- intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 2),
+ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 2),
PORT_PLL_M2_FRAC_MASK, pll->state.hw_state.pll2);
/* Write M2 fraction enable */
- intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 3),
+ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 3),
PORT_PLL_M2_FRAC_ENABLE, pll->state.hw_state.pll3);
/* Write coeff */
- temp = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 6));
+ temp = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 6));
temp &= ~PORT_PLL_PROP_COEFF_MASK;
temp &= ~PORT_PLL_INT_COEFF_MASK;
temp &= ~PORT_PLL_GAIN_CTL_MASK;
temp |= pll->state.hw_state.pll6;
- intel_de_write(dev_priv, BXT_PORT_PLL(phy, ch, 6), temp);
+ intel_de_write(i915, BXT_PORT_PLL(phy, ch, 6), temp);
/* Write calibration val */
- intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 8),
+ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 8),
PORT_PLL_TARGET_CNT_MASK, pll->state.hw_state.pll8);
- intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 9),
+ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 9),
PORT_PLL_LOCK_THRESHOLD_MASK, pll->state.hw_state.pll9);
- temp = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 10));
+ temp = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 10));
temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
temp &= ~PORT_PLL_DCO_AMP_MASK;
temp |= pll->state.hw_state.pll10;
- intel_de_write(dev_priv, BXT_PORT_PLL(phy, ch, 10), temp);
+ intel_de_write(i915, BXT_PORT_PLL(phy, ch, 10), temp);
/* Recalibrate with new settings */
- temp = intel_de_read(dev_priv, BXT_PORT_PLL_EBB_4(phy, ch));
+ temp = intel_de_read(i915, BXT_PORT_PLL_EBB_4(phy, ch));
temp |= PORT_PLL_RECALIBRATE;
- intel_de_write(dev_priv, BXT_PORT_PLL_EBB_4(phy, ch), temp);
+ intel_de_write(i915, BXT_PORT_PLL_EBB_4(phy, ch), temp);
temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
temp |= pll->state.hw_state.ebb4;
- intel_de_write(dev_priv, BXT_PORT_PLL_EBB_4(phy, ch), temp);
+ intel_de_write(i915, BXT_PORT_PLL_EBB_4(phy, ch), temp);
/* Enable PLL */
- intel_de_rmw(dev_priv, BXT_PORT_PLL_ENABLE(port), 0, PORT_PLL_ENABLE);
- intel_de_posting_read(dev_priv, BXT_PORT_PLL_ENABLE(port));
+ intel_de_rmw(i915, BXT_PORT_PLL_ENABLE(port), 0, PORT_PLL_ENABLE);
+ intel_de_posting_read(i915, BXT_PORT_PLL_ENABLE(port));
- if (wait_for_us((intel_de_read(dev_priv, BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
+ if (wait_for_us((intel_de_read(i915, BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
200))
- drm_err(&dev_priv->drm, "PLL %d not locked\n", port);
+ drm_err(&i915->drm, "PLL %d not locked\n", port);
- if (IS_GEMINILAKE(dev_priv)) {
- temp = intel_de_read(dev_priv, BXT_PORT_TX_DW5_LN0(phy, ch));
+ if (IS_GEMINILAKE(i915)) {
+ temp = intel_de_read(i915, BXT_PORT_TX_DW5_LN0(phy, ch));
temp |= DCC_DELAY_RANGE_2;
- intel_de_write(dev_priv, BXT_PORT_TX_DW5_GRP(phy, ch), temp);
+ intel_de_write(i915, BXT_PORT_TX_DW5_GRP(phy, ch), temp);
}
/*
* While we write to the group register to program all lanes at once we
* can read only lane registers and we pick lanes 0/1 for that.
*/
- temp = intel_de_read(dev_priv, BXT_PORT_PCS_DW12_LN01(phy, ch));
+ temp = intel_de_read(i915, BXT_PORT_PCS_DW12_LN01(phy, ch));
temp &= ~LANE_STAGGER_MASK;
temp &= ~LANESTAGGER_STRAP_OVRD;
temp |= pll->state.hw_state.pcsdw12;
- intel_de_write(dev_priv, BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
+ intel_de_write(i915, BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
}
-static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
- struct intel_shared_dpll *pll)
+static void bxt_ddi_pll_disable(struct drm_i915_private *i915,
+ struct intel_shared_dpll *pll)
{
enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
- intel_de_rmw(dev_priv, BXT_PORT_PLL_ENABLE(port), PORT_PLL_ENABLE, 0);
- intel_de_posting_read(dev_priv, BXT_PORT_PLL_ENABLE(port));
+ intel_de_rmw(i915, BXT_PORT_PLL_ENABLE(port), PORT_PLL_ENABLE, 0);
+ intel_de_posting_read(i915, BXT_PORT_PLL_ENABLE(port));
- if (IS_GEMINILAKE(dev_priv)) {
- intel_de_rmw(dev_priv, BXT_PORT_PLL_ENABLE(port),
+ if (IS_GEMINILAKE(i915)) {
+ intel_de_rmw(i915, BXT_PORT_PLL_ENABLE(port),
PORT_PLL_POWER_ENABLE, 0);
- if (wait_for_us(!(intel_de_read(dev_priv, BXT_PORT_PLL_ENABLE(port)) &
+ if (wait_for_us(!(intel_de_read(i915, BXT_PORT_PLL_ENABLE(port)) &
PORT_PLL_POWER_STATE), 200))
- drm_err(&dev_priv->drm,
+ drm_err(&i915->drm,
"Power state not reset for PLL:%d\n", port);
}
}
-static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
- struct intel_shared_dpll *pll,
- struct intel_dpll_hw_state *hw_state)
+static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *i915,
+ struct intel_shared_dpll *pll,
+ struct intel_dpll_hw_state *hw_state)
{
enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
intel_wakeref_t wakeref;
@@ -2045,49 +2068,49 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
u32 val;
bool ret;
- bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
+ bxt_port_to_phy_channel(i915, port, &phy, &ch);
- wakeref = intel_display_power_get_if_enabled(dev_priv,
+ wakeref = intel_display_power_get_if_enabled(i915,
POWER_DOMAIN_DISPLAY_CORE);
if (!wakeref)
return false;
ret = false;
- val = intel_de_read(dev_priv, BXT_PORT_PLL_ENABLE(port));
+ val = intel_de_read(i915, BXT_PORT_PLL_ENABLE(port));
if (!(val & PORT_PLL_ENABLE))
goto out;
- hw_state->ebb0 = intel_de_read(dev_priv, BXT_PORT_PLL_EBB_0(phy, ch));
+ hw_state->ebb0 = intel_de_read(i915, BXT_PORT_PLL_EBB_0(phy, ch));
hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
- hw_state->ebb4 = intel_de_read(dev_priv, BXT_PORT_PLL_EBB_4(phy, ch));
+ hw_state->ebb4 = intel_de_read(i915, BXT_PORT_PLL_EBB_4(phy, ch));
hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
- hw_state->pll0 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 0));
+ hw_state->pll0 = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 0));
hw_state->pll0 &= PORT_PLL_M2_INT_MASK;
- hw_state->pll1 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 1));
+ hw_state->pll1 = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 1));
hw_state->pll1 &= PORT_PLL_N_MASK;
- hw_state->pll2 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 2));
+ hw_state->pll2 = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 2));
hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
- hw_state->pll3 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 3));
+ hw_state->pll3 = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 3));
hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
- hw_state->pll6 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 6));
+ hw_state->pll6 = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 6));
hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
PORT_PLL_INT_COEFF_MASK |
PORT_PLL_GAIN_CTL_MASK;
- hw_state->pll8 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 8));
+ hw_state->pll8 = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 8));
hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
- hw_state->pll9 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 9));
+ hw_state->pll9 = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 9));
hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
- hw_state->pll10 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 10));
+ hw_state->pll10 = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 10));
hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
PORT_PLL_DCO_AMP_MASK;
@@ -2096,20 +2119,20 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
* can read only lane registers. We configure all lanes the same way, so
* here just read out lanes 0/1 and output a note if lanes 2/3 differ.
*/
- hw_state->pcsdw12 = intel_de_read(dev_priv,
+ hw_state->pcsdw12 = intel_de_read(i915,
BXT_PORT_PCS_DW12_LN01(phy, ch));
- if (intel_de_read(dev_priv, BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12)
- drm_dbg(&dev_priv->drm,
+ if (intel_de_read(i915, BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12)
+ drm_dbg(&i915->drm,
"lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
hw_state->pcsdw12,
- intel_de_read(dev_priv,
+ intel_de_read(i915,
BXT_PORT_PCS_DW12_LN23(phy, ch)));
hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
ret = true;
out:
- intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
+ intel_display_power_put(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref);
return ret;
}
@@ -2300,15 +2323,15 @@ static int bxt_get_dpll(struct intel_atomic_state *state,
{
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 drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_shared_dpll *pll;
enum intel_dpll_id id;
/* 1:1 mapping between ports and PLLs */
id = (enum intel_dpll_id) encoder->port;
- pll = intel_get_shared_dpll_by_id(dev_priv, id);
+ pll = intel_get_shared_dpll_by_id(i915, id);
- drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] using pre-allocated %s\n",
+ drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] using pre-allocated %s\n",
crtc->base.base.id, crtc->base.name, pll->info->name);
intel_reference_shared_dpll(state, crtc,
@@ -2326,10 +2349,10 @@ static void bxt_update_dpll_ref_clks(struct drm_i915_private *i915)
/* DSI non-SSC ref 19.2MHz */
}
-static void bxt_dump_hw_state(struct drm_i915_private *dev_priv,
+static void bxt_dump_hw_state(struct drm_i915_private *i915,
const struct intel_dpll_hw_state *hw_state)
{
- drm_dbg_kms(&dev_priv->drm, "dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x,"
+ drm_dbg_kms(&i915->drm, "dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x,"
"pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, "
"pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n",
hw_state->ebb0,
@@ -2557,9 +2580,9 @@ static const struct skl_wrpll_params tgl_tbt_pll_24MHz_values = {
static int icl_calc_dp_combo_pll(struct intel_crtc_state *crtc_state,
struct skl_wrpll_params *pll_params)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
const struct icl_combo_pll_params *params =
- dev_priv->display.dpll.ref_clks.nssc == 24000 ?
+ i915->display.dpll.ref_clks.nssc == 24000 ?
icl_dp_combo_pll_24MHz_values :
icl_dp_combo_pll_19_2MHz_values;
int clock = crtc_state->port_clock;
@@ -2579,12 +2602,12 @@ static int icl_calc_dp_combo_pll(struct intel_crtc_state *crtc_state,
static int icl_calc_tbt_pll(struct intel_crtc_state *crtc_state,
struct skl_wrpll_params *pll_params)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
- if (DISPLAY_VER(dev_priv) >= 12) {
- switch (dev_priv->display.dpll.ref_clks.nssc) {
+ if (DISPLAY_VER(i915) >= 12) {
+ switch (i915->display.dpll.ref_clks.nssc) {
default:
- MISSING_CASE(dev_priv->display.dpll.ref_clks.nssc);
+ MISSING_CASE(i915->display.dpll.ref_clks.nssc);
fallthrough;
case 19200:
case 38400:
@@ -2595,9 +2618,9 @@ static int icl_calc_tbt_pll(struct intel_crtc_state *crtc_state,
break;
}
} else {
- switch (dev_priv->display.dpll.ref_clks.nssc) {
+ switch (i915->display.dpll.ref_clks.nssc) {
default:
- MISSING_CASE(dev_priv->display.dpll.ref_clks.nssc);
+ MISSING_CASE(i915->display.dpll.ref_clks.nssc);
fallthrough;
case 19200:
case 38400:
@@ -2853,8 +2876,8 @@ static int icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc,
static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
struct intel_dpll_hw_state *pll_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
- int refclk_khz = dev_priv->display.dpll.ref_clks.nssc;
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ int refclk_khz = i915->display.dpll.ref_clks.nssc;
int clock = crtc_state->port_clock;
u32 dco_khz, m1div, m2div_int, m2div_rem, m2div_frac;
u32 iref_ndiv, iref_trim, iref_pulse_w;
@@ -2864,7 +2887,7 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
u64 tmp;
bool use_ssc = false;
bool is_dp = !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI);
- bool is_dkl = DISPLAY_VER(dev_priv) >= 12;
+ bool is_dkl = DISPLAY_VER(i915) >= 12;
int ret;
ret = icl_mg_pll_find_divisors(clock, is_dp, use_ssc, &dco_khz,
@@ -2962,8 +2985,8 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
DKL_PLL_DIV0_PROP_COEFF(prop_coeff) |
DKL_PLL_DIV0_FBPREDIV(m1div) |
DKL_PLL_DIV0_FBDIV_INT(m2div_int);
- if (dev_priv->display.vbt.override_afc_startup) {
- u8 val = dev_priv->display.vbt.override_afc_startup_val;
+ if (i915->display.vbt.override_afc_startup) {
+ u8 val = i915->display.vbt.override_afc_startup_val;
pll_state->mg_pll_div0 |= DKL_PLL_DIV0_AFC_STARTUP(val);
}
@@ -3053,16 +3076,16 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
return 0;
}
-static int icl_ddi_mg_pll_get_freq(struct drm_i915_private *dev_priv,
+static int icl_ddi_mg_pll_get_freq(struct drm_i915_private *i915,
const struct intel_shared_dpll *pll,
const struct intel_dpll_hw_state *pll_state)
{
u32 m1, m2_int, m2_frac, div1, div2, ref_clock;
u64 tmp;
- ref_clock = dev_priv->display.dpll.ref_clks.nssc;
+ ref_clock = i915->display.dpll.ref_clks.nssc;
- if (DISPLAY_VER(dev_priv) >= 12) {
+ if (DISPLAY_VER(i915) >= 12) {
m1 = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBPREDIV_MASK;
m1 = m1 >> DKL_PLL_DIV0_FBPREDIV_SHIFT;
m2_int = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBDIV_INT_MASK;
@@ -3167,7 +3190,7 @@ static void icl_update_active_dpll(struct intel_atomic_state *state,
static int icl_compute_combo_phy_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct icl_port_dpll *port_dpll =
@@ -3184,12 +3207,12 @@ static int icl_compute_combo_phy_dpll(struct intel_atomic_state *state,
if (ret)
return ret;
- icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state);
+ icl_calc_dpll_state(i915, &pll_params, &port_dpll->hw_state);
/* this is mainly for the fastset check */
icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT);
- crtc_state->port_clock = icl_ddi_combo_pll_get_freq(dev_priv, NULL,
+ crtc_state->port_clock = icl_ddi_combo_pll_get_freq(i915, NULL,
&port_dpll->hw_state);
return 0;
@@ -3199,7 +3222,7 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct icl_port_dpll *port_dpll =
@@ -3207,13 +3230,13 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state,
enum port port = encoder->port;
unsigned long dpll_mask;
- if (IS_ALDERLAKE_S(dev_priv)) {
+ if (IS_ALDERLAKE_S(i915)) {
dpll_mask =
BIT(DPLL_ID_DG1_DPLL3) |
BIT(DPLL_ID_DG1_DPLL2) |
BIT(DPLL_ID_ICL_DPLL1) |
BIT(DPLL_ID_ICL_DPLL0);
- } else if (IS_DG1(dev_priv)) {
+ } else if (IS_DG1(i915)) {
if (port == PORT_D || port == PORT_E) {
dpll_mask =
BIT(DPLL_ID_DG1_DPLL2) |
@@ -3223,13 +3246,13 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state,
BIT(DPLL_ID_DG1_DPLL0) |
BIT(DPLL_ID_DG1_DPLL1);
}
- } else if (IS_ROCKETLAKE(dev_priv)) {
+ } else if (IS_ROCKETLAKE(i915)) {
dpll_mask =
BIT(DPLL_ID_EHL_DPLL4) |
BIT(DPLL_ID_ICL_DPLL1) |
BIT(DPLL_ID_ICL_DPLL0);
- } else if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) &&
- port != PORT_A) {
+ } else if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) &&
+ port != PORT_A) {
dpll_mask =
BIT(DPLL_ID_EHL_DPLL4) |
BIT(DPLL_ID_ICL_DPLL1) |
@@ -3239,7 +3262,7 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state,
}
/* Eliminate DPLLs from consideration if reserved by HTI */
- dpll_mask &= ~intel_hti_dpll_mask(dev_priv);
+ dpll_mask &= ~intel_hti_dpll_mask(i915);
port_dpll->pll = intel_find_shared_dpll(state, crtc,
&port_dpll->hw_state,
@@ -3258,7 +3281,7 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state,
static int icl_compute_tc_phy_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct icl_port_dpll *port_dpll =
@@ -3271,7 +3294,7 @@ static int icl_compute_tc_phy_dplls(struct intel_atomic_state *state,
if (ret)
return ret;
- icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state);
+ icl_calc_dpll_state(i915, &pll_params, &port_dpll->hw_state);
port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY];
ret = icl_calc_mg_pll_state(crtc_state, &port_dpll->hw_state);
@@ -3281,7 +3304,7 @@ static int icl_compute_tc_phy_dplls(struct intel_atomic_state *state,
/* this is mainly for the fastset check */
icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_MG_PHY);
- crtc_state->port_clock = icl_ddi_mg_pll_get_freq(dev_priv, NULL,
+ crtc_state->port_clock = icl_ddi_mg_pll_get_freq(i915, NULL,
&port_dpll->hw_state);
return 0;
@@ -3291,7 +3314,7 @@ static int icl_get_tc_phy_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct icl_port_dpll *port_dpll =
@@ -3310,7 +3333,7 @@ static int icl_get_tc_phy_dplls(struct intel_atomic_state *state,
port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY];
- dpll_id = icl_tc_port_to_pll_id(intel_port_to_tc(dev_priv,
+ dpll_id = icl_tc_port_to_pll_id(intel_port_to_tc(i915,
encoder->port));
port_dpll->pll = intel_find_shared_dpll(state, crtc,
&port_dpll->hw_state,
@@ -3337,12 +3360,12 @@ static int icl_compute_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
- enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
- if (intel_phy_is_combo(dev_priv, phy))
+ if (intel_phy_is_combo(i915, phy))
return icl_compute_combo_phy_dpll(state, crtc);
- else if (intel_phy_is_tc(dev_priv, phy))
+ else if (intel_phy_is_tc(i915, phy))
return icl_compute_tc_phy_dplls(state, crtc);
MISSING_CASE(phy);
@@ -3354,12 +3377,12 @@ static int icl_get_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
- enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ enum phy phy = intel_port_to_phy(i915, encoder->port);
- if (intel_phy_is_combo(dev_priv, phy))
+ if (intel_phy_is_combo(i915, phy))
return icl_get_combo_phy_dpll(state, crtc, encoder);
- else if (intel_phy_is_tc(dev_priv, phy))
+ else if (intel_phy_is_tc(i915, phy))
return icl_get_tc_phy_dplls(state, crtc, encoder);
MISSING_CASE(phy);
@@ -3393,7 +3416,7 @@ static void icl_put_dplls(struct intel_atomic_state *state,
}
}
-static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv,
+static bool mg_pll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
@@ -3403,46 +3426,46 @@ static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv,
bool ret = false;
u32 val;
- i915_reg_t enable_reg = intel_tc_pll_enable_reg(dev_priv, pll);
+ i915_reg_t enable_reg = intel_tc_pll_enable_reg(i915, pll);
- wakeref = intel_display_power_get_if_enabled(dev_priv,
+ wakeref = intel_display_power_get_if_enabled(i915,
POWER_DOMAIN_DISPLAY_CORE);
if (!wakeref)
return false;
- val = intel_de_read(dev_priv, enable_reg);
+ val = intel_de_read(i915, enable_reg);
if (!(val & PLL_ENABLE))
goto out;
- hw_state->mg_refclkin_ctl = intel_de_read(dev_priv,
+ hw_state->mg_refclkin_ctl = intel_de_read(i915,
MG_REFCLKIN_CTL(tc_port));
hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK;
hw_state->mg_clktop2_coreclkctl1 =
- intel_de_read(dev_priv, MG_CLKTOP2_CORECLKCTL1(tc_port));
+ intel_de_read(i915, MG_CLKTOP2_CORECLKCTL1(tc_port));
hw_state->mg_clktop2_coreclkctl1 &=
MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
hw_state->mg_clktop2_hsclkctl =
- intel_de_read(dev_priv, MG_CLKTOP2_HSCLKCTL(tc_port));
+ intel_de_read(i915, MG_CLKTOP2_HSCLKCTL(tc_port));
hw_state->mg_clktop2_hsclkctl &=
MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK |
MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK;
- hw_state->mg_pll_div0 = intel_de_read(dev_priv, MG_PLL_DIV0(tc_port));
- hw_state->mg_pll_div1 = intel_de_read(dev_priv, MG_PLL_DIV1(tc_port));
- hw_state->mg_pll_lf = intel_de_read(dev_priv, MG_PLL_LF(tc_port));
- hw_state->mg_pll_frac_lock = intel_de_read(dev_priv,
+ hw_state->mg_pll_div0 = intel_de_read(i915, MG_PLL_DIV0(tc_port));
+ hw_state->mg_pll_div1 = intel_de_read(i915, MG_PLL_DIV1(tc_port));
+ hw_state->mg_pll_lf = intel_de_read(i915, MG_PLL_LF(tc_port));
+ hw_state->mg_pll_frac_lock = intel_de_read(i915,
MG_PLL_FRAC_LOCK(tc_port));
- hw_state->mg_pll_ssc = intel_de_read(dev_priv, MG_PLL_SSC(tc_port));
+ hw_state->mg_pll_ssc = intel_de_read(i915, MG_PLL_SSC(tc_port));
- hw_state->mg_pll_bias = intel_de_read(dev_priv, MG_PLL_BIAS(tc_port));
+ hw_state->mg_pll_bias = intel_de_read(i915, MG_PLL_BIAS(tc_port));
hw_state->mg_pll_tdc_coldst_bias =
- intel_de_read(dev_priv, MG_PLL_TDC_COLDST_BIAS(tc_port));
+ intel_de_read(i915, MG_PLL_TDC_COLDST_BIAS(tc_port));
- if (dev_priv->display.dpll.ref_clks.nssc == 38400) {
+ if (i915->display.dpll.ref_clks.nssc == 38400) {
hw_state->mg_pll_tdc_coldst_bias_mask = MG_PLL_TDC_COLDST_COLDSTART;
hw_state->mg_pll_bias_mask = 0;
} else {
@@ -3455,11 +3478,11 @@ static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv,
ret = true;
out:
- intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
+ intel_display_power_put(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref);
return ret;
}
-static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
+static bool dkl_pll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
@@ -3469,12 +3492,12 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
bool ret = false;
u32 val;
- wakeref = intel_display_power_get_if_enabled(dev_priv,
+ wakeref = intel_display_power_get_if_enabled(i915,
POWER_DOMAIN_DISPLAY_CORE);
if (!wakeref)
return false;
- val = intel_de_read(dev_priv, intel_tc_pll_enable_reg(dev_priv, pll));
+ val = intel_de_read(i915, intel_tc_pll_enable_reg(i915, pll));
if (!(val & PLL_ENABLE))
goto out;
@@ -3482,12 +3505,12 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
* All registers read here have the same HIP_INDEX_REG even though
* they are on different building blocks
*/
- hw_state->mg_refclkin_ctl = intel_dkl_phy_read(dev_priv,
+ hw_state->mg_refclkin_ctl = intel_dkl_phy_read(i915,
DKL_REFCLKIN_CTL(tc_port));
hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK;
hw_state->mg_clktop2_hsclkctl =
- intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port));
+ intel_dkl_phy_read(i915, DKL_CLKTOP2_HSCLKCTL(tc_port));
hw_state->mg_clktop2_hsclkctl &=
MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
@@ -3495,42 +3518,42 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK;
hw_state->mg_clktop2_coreclkctl1 =
- intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port));
+ intel_dkl_phy_read(i915, DKL_CLKTOP2_CORECLKCTL1(tc_port));
hw_state->mg_clktop2_coreclkctl1 &=
MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
- hw_state->mg_pll_div0 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV0(tc_port));
+ hw_state->mg_pll_div0 = intel_dkl_phy_read(i915, DKL_PLL_DIV0(tc_port));
val = DKL_PLL_DIV0_MASK;
- if (dev_priv->display.vbt.override_afc_startup)
+ if (i915->display.vbt.override_afc_startup)
val |= DKL_PLL_DIV0_AFC_STARTUP_MASK;
hw_state->mg_pll_div0 &= val;
- hw_state->mg_pll_div1 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port));
+ hw_state->mg_pll_div1 = intel_dkl_phy_read(i915, DKL_PLL_DIV1(tc_port));
hw_state->mg_pll_div1 &= (DKL_PLL_DIV1_IREF_TRIM_MASK |
DKL_PLL_DIV1_TDC_TARGET_CNT_MASK);
- hw_state->mg_pll_ssc = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port));
+ hw_state->mg_pll_ssc = intel_dkl_phy_read(i915, DKL_PLL_SSC(tc_port));
hw_state->mg_pll_ssc &= (DKL_PLL_SSC_IREF_NDIV_RATIO_MASK |
DKL_PLL_SSC_STEP_LEN_MASK |
DKL_PLL_SSC_STEP_NUM_MASK |
DKL_PLL_SSC_EN);
- hw_state->mg_pll_bias = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port));
+ hw_state->mg_pll_bias = intel_dkl_phy_read(i915, DKL_PLL_BIAS(tc_port));
hw_state->mg_pll_bias &= (DKL_PLL_BIAS_FRAC_EN_H |
DKL_PLL_BIAS_FBDIV_FRAC_MASK);
hw_state->mg_pll_tdc_coldst_bias =
- intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port));
+ intel_dkl_phy_read(i915, DKL_PLL_TDC_COLDST_BIAS(tc_port));
hw_state->mg_pll_tdc_coldst_bias &= (DKL_PLL_TDC_SSC_STEP_SIZE_MASK |
DKL_PLL_TDC_FEED_FWD_GAIN_MASK);
ret = true;
out:
- intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
+ intel_display_power_put(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref);
return ret;
}
-static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
+static bool icl_pll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state,
i915_reg_t enable_reg)
@@ -3540,94 +3563,94 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
bool ret = false;
u32 val;
- wakeref = intel_display_power_get_if_enabled(dev_priv,
+ wakeref = intel_display_power_get_if_enabled(i915,
POWER_DOMAIN_DISPLAY_CORE);
if (!wakeref)
return false;
- val = intel_de_read(dev_priv, enable_reg);
+ val = intel_de_read(i915, enable_reg);
if (!(val & PLL_ENABLE))
goto out;
- if (IS_ALDERLAKE_S(dev_priv)) {
- hw_state->cfgcr0 = intel_de_read(dev_priv, ADLS_DPLL_CFGCR0(id));
- hw_state->cfgcr1 = intel_de_read(dev_priv, ADLS_DPLL_CFGCR1(id));
- } else if (IS_DG1(dev_priv)) {
- hw_state->cfgcr0 = intel_de_read(dev_priv, DG1_DPLL_CFGCR0(id));
- hw_state->cfgcr1 = intel_de_read(dev_priv, DG1_DPLL_CFGCR1(id));
- } else if (IS_ROCKETLAKE(dev_priv)) {
- hw_state->cfgcr0 = intel_de_read(dev_priv,
+ if (IS_ALDERLAKE_S(i915)) {
+ hw_state->cfgcr0 = intel_de_read(i915, ADLS_DPLL_CFGCR0(id));
+ hw_state->cfgcr1 = intel_de_read(i915, ADLS_DPLL_CFGCR1(id));
+ } else if (IS_DG1(i915)) {
+ hw_state->cfgcr0 = intel_de_read(i915, DG1_DPLL_CFGCR0(id));
+ hw_state->cfgcr1 = intel_de_read(i915, DG1_DPLL_CFGCR1(id));
+ } else if (IS_ROCKETLAKE(i915)) {
+ hw_state->cfgcr0 = intel_de_read(i915,
RKL_DPLL_CFGCR0(id));
- hw_state->cfgcr1 = intel_de_read(dev_priv,
+ hw_state->cfgcr1 = intel_de_read(i915,
RKL_DPLL_CFGCR1(id));
- } else if (DISPLAY_VER(dev_priv) >= 12) {
- hw_state->cfgcr0 = intel_de_read(dev_priv,
+ } else if (DISPLAY_VER(i915) >= 12) {
+ hw_state->cfgcr0 = intel_de_read(i915,
TGL_DPLL_CFGCR0(id));
- hw_state->cfgcr1 = intel_de_read(dev_priv,
+ hw_state->cfgcr1 = intel_de_read(i915,
TGL_DPLL_CFGCR1(id));
- if (dev_priv->display.vbt.override_afc_startup) {
- hw_state->div0 = intel_de_read(dev_priv, TGL_DPLL0_DIV0(id));
+ if (i915->display.vbt.override_afc_startup) {
+ hw_state->div0 = intel_de_read(i915, TGL_DPLL0_DIV0(id));
hw_state->div0 &= TGL_DPLL0_DIV0_AFC_STARTUP_MASK;
}
} else {
- if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) &&
+ if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) &&
id == DPLL_ID_EHL_DPLL4) {
- hw_state->cfgcr0 = intel_de_read(dev_priv,
+ hw_state->cfgcr0 = intel_de_read(i915,
ICL_DPLL_CFGCR0(4));
- hw_state->cfgcr1 = intel_de_read(dev_priv,
+ hw_state->cfgcr1 = intel_de_read(i915,
ICL_DPLL_CFGCR1(4));
} else {
- hw_state->cfgcr0 = intel_de_read(dev_priv,
+ hw_state->cfgcr0 = intel_de_read(i915,
ICL_DPLL_CFGCR0(id));
- hw_state->cfgcr1 = intel_de_read(dev_priv,
+ hw_state->cfgcr1 = intel_de_read(i915,
ICL_DPLL_CFGCR1(id));
}
}
ret = true;
out:
- intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
+ intel_display_power_put(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref);
return ret;
}
-static bool combo_pll_get_hw_state(struct drm_i915_private *dev_priv,
+static bool combo_pll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
- i915_reg_t enable_reg = intel_combo_pll_enable_reg(dev_priv, pll);
+ i915_reg_t enable_reg = intel_combo_pll_enable_reg(i915, pll);
- return icl_pll_get_hw_state(dev_priv, pll, hw_state, enable_reg);
+ return icl_pll_get_hw_state(i915, pll, hw_state, enable_reg);
}
-static bool tbt_pll_get_hw_state(struct drm_i915_private *dev_priv,
+static bool tbt_pll_get_hw_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state)
{
- return icl_pll_get_hw_state(dev_priv, pll, hw_state, TBT_PLL_ENABLE);
+ return icl_pll_get_hw_state(i915, pll, hw_state, TBT_PLL_ENABLE);
}
-static void icl_dpll_write(struct drm_i915_private *dev_priv,
+static void icl_dpll_write(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
const enum intel_dpll_id id = pll->info->id;
i915_reg_t cfgcr0_reg, cfgcr1_reg, div0_reg = INVALID_MMIO_REG;
- if (IS_ALDERLAKE_S(dev_priv)) {
+ if (IS_ALDERLAKE_S(i915)) {
cfgcr0_reg = ADLS_DPLL_CFGCR0(id);
cfgcr1_reg = ADLS_DPLL_CFGCR1(id);
- } else if (IS_DG1(dev_priv)) {
+ } else if (IS_DG1(i915)) {
cfgcr0_reg = DG1_DPLL_CFGCR0(id);
cfgcr1_reg = DG1_DPLL_CFGCR1(id);
- } else if (IS_ROCKETLAKE(dev_priv)) {
+ } else if (IS_ROCKETLAKE(i915)) {
cfgcr0_reg = RKL_DPLL_CFGCR0(id);
cfgcr1_reg = RKL_DPLL_CFGCR1(id);
- } else if (DISPLAY_VER(dev_priv) >= 12) {
+ } else if (DISPLAY_VER(i915) >= 12) {
cfgcr0_reg = TGL_DPLL_CFGCR0(id);
cfgcr1_reg = TGL_DPLL_CFGCR1(id);
div0_reg = TGL_DPLL0_DIV0(id);
} else {
- if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) &&
+ if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) &&
id == DPLL_ID_EHL_DPLL4) {
cfgcr0_reg = ICL_DPLL_CFGCR0(4);
cfgcr1_reg = ICL_DPLL_CFGCR1(4);
@@ -3637,18 +3660,18 @@ static void icl_dpll_write(struct drm_i915_private *dev_priv,
}
}
- intel_de_write(dev_priv, cfgcr0_reg, hw_state->cfgcr0);
- intel_de_write(dev_priv, cfgcr1_reg, hw_state->cfgcr1);
- drm_WARN_ON_ONCE(&dev_priv->drm, dev_priv->display.vbt.override_afc_startup &&
+ intel_de_write(i915, cfgcr0_reg, hw_state->cfgcr0);
+ intel_de_write(i915, cfgcr1_reg, hw_state->cfgcr1);
+ drm_WARN_ON_ONCE(&i915->drm, i915->display.vbt.override_afc_startup &&
!i915_mmio_reg_valid(div0_reg));
- if (dev_priv->display.vbt.override_afc_startup &&
+ if (i915->display.vbt.override_afc_startup &&
i915_mmio_reg_valid(div0_reg))
- intel_de_rmw(dev_priv, div0_reg,
+ intel_de_rmw(i915, div0_reg,
TGL_DPLL0_DIV0_AFC_STARTUP_MASK, hw_state->div0);
- intel_de_posting_read(dev_priv, cfgcr1_reg);
+ intel_de_posting_read(i915, cfgcr1_reg);
}
-static void icl_mg_pll_write(struct drm_i915_private *dev_priv,
+static void icl_mg_pll_write(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
@@ -3660,38 +3683,38 @@ static void icl_mg_pll_write(struct drm_i915_private *dev_priv,
* during the calc/readout phase if the mask depends on some other HW
* state like refclk, see icl_calc_mg_pll_state().
*/
- intel_de_rmw(dev_priv, MG_REFCLKIN_CTL(tc_port),
+ intel_de_rmw(i915, MG_REFCLKIN_CTL(tc_port),
MG_REFCLKIN_CTL_OD_2_MUX_MASK, hw_state->mg_refclkin_ctl);
- intel_de_rmw(dev_priv, MG_CLKTOP2_CORECLKCTL1(tc_port),
+ intel_de_rmw(i915, MG_CLKTOP2_CORECLKCTL1(tc_port),
MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK,
hw_state->mg_clktop2_coreclkctl1);
- intel_de_rmw(dev_priv, MG_CLKTOP2_HSCLKCTL(tc_port),
+ intel_de_rmw(i915, MG_CLKTOP2_HSCLKCTL(tc_port),
MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK |
MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK,
hw_state->mg_clktop2_hsclkctl);
- intel_de_write(dev_priv, MG_PLL_DIV0(tc_port), hw_state->mg_pll_div0);
- intel_de_write(dev_priv, MG_PLL_DIV1(tc_port), hw_state->mg_pll_div1);
- intel_de_write(dev_priv, MG_PLL_LF(tc_port), hw_state->mg_pll_lf);
- intel_de_write(dev_priv, MG_PLL_FRAC_LOCK(tc_port),
+ intel_de_write(i915, MG_PLL_DIV0(tc_port), hw_state->mg_pll_div0);
+ intel_de_write(i915, MG_PLL_DIV1(tc_port), hw_state->mg_pll_div1);
+ intel_de_write(i915, MG_PLL_LF(tc_port), hw_state->mg_pll_lf);
+ intel_de_write(i915, MG_PLL_FRAC_LOCK(tc_port),
hw_state->mg_pll_frac_lock);
- intel_de_write(dev_priv, MG_PLL_SSC(tc_port), hw_state->mg_pll_ssc);
+ intel_de_write(i915, MG_PLL_SSC(tc_port), hw_state->mg_pll_ssc);
- intel_de_rmw(dev_priv, MG_PLL_BIAS(tc_port),
+ intel_de_rmw(i915, MG_PLL_BIAS(tc_port),
hw_state->mg_pll_bias_mask, hw_state->mg_pll_bias);
- intel_de_rmw(dev_priv, MG_PLL_TDC_COLDST_BIAS(tc_port),
+ intel_de_rmw(i915, MG_PLL_TDC_COLDST_BIAS(tc_port),
hw_state->mg_pll_tdc_coldst_bias_mask,
hw_state->mg_pll_tdc_coldst_bias);
- intel_de_posting_read(dev_priv, MG_PLL_TDC_COLDST_BIAS(tc_port));
+ intel_de_posting_read(i915, MG_PLL_TDC_COLDST_BIAS(tc_port));
}
-static void dkl_pll_write(struct drm_i915_private *dev_priv,
+static void dkl_pll_write(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
@@ -3703,83 +3726,83 @@ static void dkl_pll_write(struct drm_i915_private *dev_priv,
* though on different building block
*/
/* All the registers are RMW */
- val = intel_dkl_phy_read(dev_priv, DKL_REFCLKIN_CTL(tc_port));
+ val = intel_dkl_phy_read(i915, DKL_REFCLKIN_CTL(tc_port));
val &= ~MG_REFCLKIN_CTL_OD_2_MUX_MASK;
val |= hw_state->mg_refclkin_ctl;
- intel_dkl_phy_write(dev_priv, DKL_REFCLKIN_CTL(tc_port), val);
+ intel_dkl_phy_write(i915, DKL_REFCLKIN_CTL(tc_port), val);
- val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port));
+ val = intel_dkl_phy_read(i915, DKL_CLKTOP2_CORECLKCTL1(tc_port));
val &= ~MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
val |= hw_state->mg_clktop2_coreclkctl1;
- intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), val);
+ intel_dkl_phy_write(i915, DKL_CLKTOP2_CORECLKCTL1(tc_port), val);
- val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port));
+ val = intel_dkl_phy_read(i915, DKL_CLKTOP2_HSCLKCTL(tc_port));
val &= ~(MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK |
MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK);
val |= hw_state->mg_clktop2_hsclkctl;
- intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), val);
+ intel_dkl_phy_write(i915, DKL_CLKTOP2_HSCLKCTL(tc_port), val);
val = DKL_PLL_DIV0_MASK;
- if (dev_priv->display.vbt.override_afc_startup)
+ if (i915->display.vbt.override_afc_startup)
val |= DKL_PLL_DIV0_AFC_STARTUP_MASK;
- intel_dkl_phy_rmw(dev_priv, DKL_PLL_DIV0(tc_port), val,
+ intel_dkl_phy_rmw(i915, DKL_PLL_DIV0(tc_port), val,
hw_state->mg_pll_div0);
- val = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port));
+ val = intel_dkl_phy_read(i915, DKL_PLL_DIV1(tc_port));
val &= ~(DKL_PLL_DIV1_IREF_TRIM_MASK |
DKL_PLL_DIV1_TDC_TARGET_CNT_MASK);
val |= hw_state->mg_pll_div1;
- intel_dkl_phy_write(dev_priv, DKL_PLL_DIV1(tc_port), val);
+ intel_dkl_phy_write(i915, DKL_PLL_DIV1(tc_port), val);
- val = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port));
+ val = intel_dkl_phy_read(i915, DKL_PLL_SSC(tc_port));
val &= ~(DKL_PLL_SSC_IREF_NDIV_RATIO_MASK |
DKL_PLL_SSC_STEP_LEN_MASK |
DKL_PLL_SSC_STEP_NUM_MASK |
DKL_PLL_SSC_EN);
val |= hw_state->mg_pll_ssc;
- intel_dkl_phy_write(dev_priv, DKL_PLL_SSC(tc_port), val);
+ intel_dkl_phy_write(i915, DKL_PLL_SSC(tc_port), val);
- val = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port));
+ val = intel_dkl_phy_read(i915, DKL_PLL_BIAS(tc_port));
val &= ~(DKL_PLL_BIAS_FRAC_EN_H |
DKL_PLL_BIAS_FBDIV_FRAC_MASK);
val |= hw_state->mg_pll_bias;
- intel_dkl_phy_write(dev_priv, DKL_PLL_BIAS(tc_port), val);
+ intel_dkl_phy_write(i915, DKL_PLL_BIAS(tc_port), val);
- val = intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port));
+ val = intel_dkl_phy_read(i915, DKL_PLL_TDC_COLDST_BIAS(tc_port));
val &= ~(DKL_PLL_TDC_SSC_STEP_SIZE_MASK |
DKL_PLL_TDC_FEED_FWD_GAIN_MASK);
val |= hw_state->mg_pll_tdc_coldst_bias;
- intel_dkl_phy_write(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), val);
+ intel_dkl_phy_write(i915, DKL_PLL_TDC_COLDST_BIAS(tc_port), val);
- intel_dkl_phy_posting_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port));
+ intel_dkl_phy_posting_read(i915, DKL_PLL_TDC_COLDST_BIAS(tc_port));
}
-static void icl_pll_power_enable(struct drm_i915_private *dev_priv,
+static void icl_pll_power_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
i915_reg_t enable_reg)
{
- intel_de_rmw(dev_priv, enable_reg, 0, PLL_POWER_ENABLE);
+ intel_de_rmw(i915, enable_reg, 0, PLL_POWER_ENABLE);
/*
* The spec says we need to "wait" but it also says it should be
* immediate.
*/
- if (intel_de_wait_for_set(dev_priv, enable_reg, PLL_POWER_STATE, 1))
- drm_err(&dev_priv->drm, "PLL %d Power not enabled\n",
+ if (intel_de_wait_for_set(i915, enable_reg, PLL_POWER_STATE, 1))
+ drm_err(&i915->drm, "PLL %d Power not enabled\n",
pll->info->id);
}
-static void icl_pll_enable(struct drm_i915_private *dev_priv,
+static void icl_pll_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
i915_reg_t enable_reg)
{
- intel_de_rmw(dev_priv, enable_reg, 0, PLL_ENABLE);
+ intel_de_rmw(i915, enable_reg, 0, PLL_ENABLE);
/* Timeout is actually 600us. */
- if (intel_de_wait_for_set(dev_priv, enable_reg, PLL_LOCK, 1))
- drm_err(&dev_priv->drm, "PLL %d not locked\n", pll->info->id);
+ if (intel_de_wait_for_set(i915, enable_reg, PLL_LOCK, 1))
+ drm_err(&i915->drm, "PLL %d not locked\n", pll->info->id);
}
static void adlp_cmtg_clock_gating_wa(struct drm_i915_private *i915, struct intel_shared_dpll *pll)
@@ -3806,12 +3829,12 @@ static void adlp_cmtg_clock_gating_wa(struct drm_i915_private *i915, struct inte
drm_dbg_kms(&i915->drm, "Unexpected flags in TRANS_CMTG_CHICKEN: %08x\n", val);
}
-static void combo_pll_enable(struct drm_i915_private *dev_priv,
+static void combo_pll_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
- i915_reg_t enable_reg = intel_combo_pll_enable_reg(dev_priv, pll);
+ i915_reg_t enable_reg = intel_combo_pll_enable_reg(i915, pll);
- if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) &&
+ if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) &&
pll->info->id == DPLL_ID_EHL_DPLL4) {
/*
@@ -3819,13 +3842,13 @@ static void combo_pll_enable(struct drm_i915_private *dev_priv,
* This can be done by taking a reference on DPLL4 power
* domain.
*/
- pll->wakeref = intel_display_power_get(dev_priv,
+ pll->wakeref = intel_display_power_get(i915,
POWER_DOMAIN_DC_OFF);
}
- icl_pll_power_enable(dev_priv, pll, enable_reg);
+ icl_pll_power_enable(i915, pll, enable_reg);
- icl_dpll_write(dev_priv, pll);
+ icl_dpll_write(i915, pll);
/*
* DVFS pre sequence would be here, but in our driver the cdclk code
@@ -3833,19 +3856,19 @@ static void combo_pll_enable(struct drm_i915_private *dev_priv,
* nothing here.
*/
- icl_pll_enable(dev_priv, pll, enable_reg);
+ icl_pll_enable(i915, pll, enable_reg);
- adlp_cmtg_clock_gating_wa(dev_priv, pll);
+ adlp_cmtg_clock_gating_wa(i915, pll);
/* DVFS post sequence would be here. See the comment above. */
}
-static void tbt_pll_enable(struct drm_i915_private *dev_priv,
+static void tbt_pll_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
- icl_pll_power_enable(dev_priv, pll, TBT_PLL_ENABLE);
+ icl_pll_power_enable(i915, pll, TBT_PLL_ENABLE);
- icl_dpll_write(dev_priv, pll);
+ icl_dpll_write(i915, pll);
/*
* DVFS pre sequence would be here, but in our driver the cdclk code
@@ -3853,22 +3876,22 @@ static void tbt_pll_enable(struct drm_i915_private *dev_priv,
* nothing here.
*/
- icl_pll_enable(dev_priv, pll, TBT_PLL_ENABLE);
+ icl_pll_enable(i915, pll, TBT_PLL_ENABLE);
/* DVFS post sequence would be here. See the comment above. */
}
-static void mg_pll_enable(struct drm_i915_private *dev_priv,
+static void mg_pll_enable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
- i915_reg_t enable_reg = intel_tc_pll_enable_reg(dev_priv, pll);
+ i915_reg_t enable_reg = intel_tc_pll_enable_reg(i915, pll);
- icl_pll_power_enable(dev_priv, pll, enable_reg);
+ icl_pll_power_enable(i915, pll, enable_reg);
- if (DISPLAY_VER(dev_priv) >= 12)
- dkl_pll_write(dev_priv, pll);
+ if (DISPLAY_VER(i915) >= 12)
+ dkl_pll_write(i915, pll);
else
- icl_mg_pll_write(dev_priv, pll);
+ icl_mg_pll_write(i915, pll);
/*
* DVFS pre sequence would be here, but in our driver the cdclk code
@@ -3876,12 +3899,12 @@ static void mg_pll_enable(struct drm_i915_private *dev_priv,
* nothing here.
*/
- icl_pll_enable(dev_priv, pll, enable_reg);
+ icl_pll_enable(i915, pll, enable_reg);
/* DVFS post sequence would be here. See the comment above. */
}
-static void icl_pll_disable(struct drm_i915_private *dev_priv,
+static void icl_pll_disable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
i915_reg_t enable_reg)
{
@@ -3893,50 +3916,50 @@ static void icl_pll_disable(struct drm_i915_private *dev_priv,
* nothing here.
*/
- intel_de_rmw(dev_priv, enable_reg, PLL_ENABLE, 0);
+ intel_de_rmw(i915, enable_reg, PLL_ENABLE, 0);
/* Timeout is actually 1us. */
- if (intel_de_wait_for_clear(dev_priv, enable_reg, PLL_LOCK, 1))
- drm_err(&dev_priv->drm, "PLL %d locked\n", pll->info->id);
+ if (intel_de_wait_for_clear(i915, enable_reg, PLL_LOCK, 1))
+ drm_err(&i915->drm, "PLL %d locked\n", pll->info->id);
/* DVFS post sequence would be here. See the comment above. */
- intel_de_rmw(dev_priv, enable_reg, PLL_POWER_ENABLE, 0);
+ intel_de_rmw(i915, enable_reg, PLL_POWER_ENABLE, 0);
/*
* The spec says we need to "wait" but it also says it should be
* immediate.
*/
- if (intel_de_wait_for_clear(dev_priv, enable_reg, PLL_POWER_STATE, 1))
- drm_err(&dev_priv->drm, "PLL %d Power not disabled\n",
+ if (intel_de_wait_for_clear(i915, enable_reg, PLL_POWER_STATE, 1))
+ drm_err(&i915->drm, "PLL %d Power not disabled\n",
pll->info->id);
}
-static void combo_pll_disable(struct drm_i915_private *dev_priv,
+static void combo_pll_disable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
- i915_reg_t enable_reg = intel_combo_pll_enable_reg(dev_priv, pll);
+ i915_reg_t enable_reg = intel_combo_pll_enable_reg(i915, pll);
- icl_pll_disable(dev_priv, pll, enable_reg);
+ icl_pll_disable(i915, pll, enable_reg);
- if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) &&
+ if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) &&
pll->info->id == DPLL_ID_EHL_DPLL4)
- intel_display_power_put(dev_priv, POWER_DOMAIN_DC_OFF,
+ intel_display_power_put(i915, POWER_DOMAIN_DC_OFF,
pll->wakeref);
}
-static void tbt_pll_disable(struct drm_i915_private *dev_priv,
+static void tbt_pll_disable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
- icl_pll_disable(dev_priv, pll, TBT_PLL_ENABLE);
+ icl_pll_disable(i915, pll, TBT_PLL_ENABLE);
}
-static void mg_pll_disable(struct drm_i915_private *dev_priv,
+static void mg_pll_disable(struct drm_i915_private *i915,
struct intel_shared_dpll *pll)
{
- i915_reg_t enable_reg = intel_tc_pll_enable_reg(dev_priv, pll);
+ i915_reg_t enable_reg = intel_tc_pll_enable_reg(i915, pll);
- icl_pll_disable(dev_priv, pll, enable_reg);
+ icl_pll_disable(i915, pll, enable_reg);
}
static void icl_update_dpll_ref_clks(struct drm_i915_private *i915)
@@ -3945,10 +3968,10 @@ static void icl_update_dpll_ref_clks(struct drm_i915_private *i915)
i915->display.dpll.ref_clks.nssc = i915->display.cdclk.hw.ref;
}
-static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
+static void icl_dump_hw_state(struct drm_i915_private *i915,
const struct intel_dpll_hw_state *hw_state)
{
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, div0: 0x%x, "
"mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
"mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, "
@@ -4130,62 +4153,64 @@ static const struct intel_dpll_mgr adlp_pll_mgr = {
/**
* intel_shared_dpll_init - Initialize shared DPLLs
- * @dev_priv: i915 device
+ * @i915: i915 device
*
- * Initialize shared DPLLs for @dev_priv.
+ * Initialize shared DPLLs for @i915.
*/
-void intel_shared_dpll_init(struct drm_i915_private *dev_priv)
+void intel_shared_dpll_init(struct drm_i915_private *i915)
{
const struct intel_dpll_mgr *dpll_mgr = NULL;
const struct dpll_info *dpll_info;
int i;
- mutex_init(&dev_priv->display.dpll.lock);
+ mutex_init(&i915->display.dpll.lock);
- if (DISPLAY_VER(dev_priv) >= 14 || IS_DG2(dev_priv))
+ if (DISPLAY_VER(i915) >= 14 || IS_DG2(i915))
/* No shared DPLLs on DG2; port PLLs are part of the PHY */
dpll_mgr = NULL;
- else if (IS_ALDERLAKE_P(dev_priv))
+ else if (IS_ALDERLAKE_P(i915))
dpll_mgr = &adlp_pll_mgr;
- else if (IS_ALDERLAKE_S(dev_priv))
+ else if (IS_ALDERLAKE_S(i915))
dpll_mgr = &adls_pll_mgr;
- else if (IS_DG1(dev_priv))
+ else if (IS_DG1(i915))
dpll_mgr = &dg1_pll_mgr;
- else if (IS_ROCKETLAKE(dev_priv))
+ else if (IS_ROCKETLAKE(i915))
dpll_mgr = &rkl_pll_mgr;
- else if (DISPLAY_VER(dev_priv) >= 12)
+ else if (DISPLAY_VER(i915) >= 12)
dpll_mgr = &tgl_pll_mgr;
- else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv))
+ else if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915))
dpll_mgr = &ehl_pll_mgr;
- else if (DISPLAY_VER(dev_priv) >= 11)
+ else if (DISPLAY_VER(i915) >= 11)
dpll_mgr = &icl_pll_mgr;
- else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
+ else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
dpll_mgr = &bxt_pll_mgr;
- else if (DISPLAY_VER(dev_priv) == 9)
+ else if (DISPLAY_VER(i915) == 9)
dpll_mgr = &skl_pll_mgr;
- else if (HAS_DDI(dev_priv))
+ else if (HAS_DDI(i915))
dpll_mgr = &hsw_pll_mgr;
- else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
+ else if (HAS_PCH_IBX(i915) || HAS_PCH_CPT(i915))
dpll_mgr = &pch_pll_mgr;
- if (!dpll_mgr) {
- dev_priv->display.dpll.num_shared_dpll = 0;
+ if (!dpll_mgr)
return;
- }
dpll_info = dpll_mgr->dpll_info;
for (i = 0; dpll_info[i].name; i++) {
- if (drm_WARN_ON(&dev_priv->drm,
- i >= ARRAY_SIZE(dev_priv->display.dpll.shared_dplls)))
+ if (drm_WARN_ON(&i915->drm,
+ i >= ARRAY_SIZE(i915->display.dpll.shared_dplls)))
+ break;
+
+ /* must fit into unsigned long bitmask on 32bit */
+ if (drm_WARN_ON(&i915->drm, dpll_info[i].id >= 32))
break;
- drm_WARN_ON(&dev_priv->drm, i != dpll_info[i].id);
- dev_priv->display.dpll.shared_dplls[i].info = &dpll_info[i];
+ i915->display.dpll.shared_dplls[i].info = &dpll_info[i];
+ i915->display.dpll.shared_dplls[i].index = i;
}
- dev_priv->display.dpll.mgr = dpll_mgr;
- dev_priv->display.dpll.num_shared_dpll = i;
+ i915->display.dpll.mgr = dpll_mgr;
+ i915->display.dpll.num_shared_dpll = i;
}
/**
@@ -4206,10 +4231,10 @@ int intel_compute_shared_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
- const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr;
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_dpll_mgr *dpll_mgr = i915->display.dpll.mgr;
- if (drm_WARN_ON(&dev_priv->drm, !dpll_mgr))
+ if (drm_WARN_ON(&i915->drm, !dpll_mgr))
return -EINVAL;
return dpll_mgr->compute_dplls(state, crtc, encoder);
@@ -4239,10 +4264,10 @@ int intel_reserve_shared_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
- const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr;
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_dpll_mgr *dpll_mgr = i915->display.dpll.mgr;
- if (drm_WARN_ON(&dev_priv->drm, !dpll_mgr))
+ if (drm_WARN_ON(&i915->drm, !dpll_mgr))
return -EINVAL;
return dpll_mgr->get_dplls(state, crtc, encoder);
@@ -4262,8 +4287,8 @@ int intel_reserve_shared_dplls(struct intel_atomic_state *state,
void intel_release_shared_dplls(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
- const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr;
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_dpll_mgr *dpll_mgr = i915->display.dpll.mgr;
/*
* FIXME: this function is called for every platform having a
@@ -4291,10 +4316,10 @@ void intel_update_active_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ const struct intel_dpll_mgr *dpll_mgr = i915->display.dpll.mgr;
- if (drm_WARN_ON(&dev_priv->drm, !dpll_mgr))
+ if (drm_WARN_ON(&i915->drm, !dpll_mgr))
return;
dpll_mgr->update_active_dpll(state, crtc, encoder);
@@ -4370,10 +4395,11 @@ void intel_dpll_update_ref_clks(struct drm_i915_private *i915)
void intel_dpll_readout_hw_state(struct drm_i915_private *i915)
{
+ struct intel_shared_dpll *pll;
int i;
- for (i = 0; i < i915->display.dpll.num_shared_dpll; i++)
- readout_dpll_hw_state(i915, &i915->display.dpll.shared_dplls[i]);
+ for_each_shared_dpll(i915, pll, i)
+ readout_dpll_hw_state(i915, pll);
}
static void sanitize_dpll_state(struct drm_i915_private *i915,
@@ -4397,29 +4423,30 @@ static void sanitize_dpll_state(struct drm_i915_private *i915,
void intel_dpll_sanitize_state(struct drm_i915_private *i915)
{
+ struct intel_shared_dpll *pll;
int i;
- for (i = 0; i < i915->display.dpll.num_shared_dpll; i++)
- sanitize_dpll_state(i915, &i915->display.dpll.shared_dplls[i]);
+ for_each_shared_dpll(i915, pll, i)
+ sanitize_dpll_state(i915, pll);
}
/**
* intel_dpll_dump_hw_state - write hw_state to dmesg
- * @dev_priv: i915 drm device
+ * @i915: i915 drm device
* @hw_state: hw state to be written to the log
*
* Write the relevant values in @hw_state to dmesg using drm_dbg_kms.
*/
-void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
+void intel_dpll_dump_hw_state(struct drm_i915_private *i915,
const struct intel_dpll_hw_state *hw_state)
{
- if (dev_priv->display.dpll.mgr) {
- dev_priv->display.dpll.mgr->dump_hw_state(dev_priv, hw_state);
+ if (i915->display.dpll.mgr) {
+ i915->display.dpll.mgr->dump_hw_state(i915, hw_state);
} else {
/* fallback for platforms that don't use the shared dpll
* infrastructure
*/
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
"fp0: 0x%x, fp1: 0x%x\n",
hw_state->dpll,
@@ -4430,10 +4457,10 @@ void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
}
static void
-verify_single_dpll_state(struct drm_i915_private *dev_priv,
+verify_single_dpll_state(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
struct intel_crtc *crtc,
- struct intel_crtc_state *new_crtc_state)
+ const struct intel_crtc_state *new_crtc_state)
{
struct intel_dpll_hw_state dpll_hw_state;
u8 pipe_mask;
@@ -4441,22 +4468,22 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,
memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
- drm_dbg_kms(&dev_priv->drm, "%s\n", pll->info->name);
+ drm_dbg_kms(&i915->drm, "%s\n", pll->info->name);
- active = intel_dpll_get_hw_state(dev_priv, pll, &dpll_hw_state);
+ active = intel_dpll_get_hw_state(i915, pll, &dpll_hw_state);
if (!(pll->info->flags & INTEL_DPLL_ALWAYS_ON)) {
- I915_STATE_WARN(dev_priv, !pll->on && pll->active_mask,
+ I915_STATE_WARN(i915, !pll->on && pll->active_mask,
"pll in active use but not on in sw tracking\n");
- I915_STATE_WARN(dev_priv, pll->on && !pll->active_mask,
+ I915_STATE_WARN(i915, pll->on && !pll->active_mask,
"pll is on but not used by any active pipe\n");
- I915_STATE_WARN(dev_priv, pll->on != active,
+ I915_STATE_WARN(i915, pll->on != active,
"pll on state mismatch (expected %i, found %i)\n",
pll->on, active);
}
if (!crtc) {
- I915_STATE_WARN(dev_priv,
+ I915_STATE_WARN(i915,
pll->active_mask & ~pll->state.pipe_mask,
"more active pll users than references: 0x%x vs 0x%x\n",
pll->active_mask, pll->state.pipe_mask);
@@ -4467,32 +4494,35 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,
pipe_mask = BIT(crtc->pipe);
if (new_crtc_state->hw.active)
- I915_STATE_WARN(dev_priv, !(pll->active_mask & pipe_mask),
+ I915_STATE_WARN(i915, !(pll->active_mask & pipe_mask),
"pll active mismatch (expected pipe %c in active mask 0x%x)\n",
pipe_name(crtc->pipe), pll->active_mask);
else
- I915_STATE_WARN(dev_priv, pll->active_mask & pipe_mask,
+ I915_STATE_WARN(i915, pll->active_mask & pipe_mask,
"pll active mismatch (didn't expect pipe %c in active mask 0x%x)\n",
pipe_name(crtc->pipe), pll->active_mask);
- I915_STATE_WARN(dev_priv, !(pll->state.pipe_mask & pipe_mask),
+ I915_STATE_WARN(i915, !(pll->state.pipe_mask & pipe_mask),
"pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n",
pipe_mask, pll->state.pipe_mask);
- I915_STATE_WARN(dev_priv,
+ I915_STATE_WARN(i915,
pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state,
sizeof(dpll_hw_state)),
"pll hw state mismatch\n");
}
-void intel_shared_dpll_state_verify(struct intel_crtc *crtc,
- struct intel_crtc_state *old_crtc_state,
- struct intel_crtc_state *new_crtc_state)
+void intel_shared_dpll_state_verify(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
+ const struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
if (new_crtc_state->shared_dpll)
- verify_single_dpll_state(dev_priv, new_crtc_state->shared_dpll,
+ verify_single_dpll_state(i915, new_crtc_state->shared_dpll,
crtc, new_crtc_state);
if (old_crtc_state->shared_dpll &&
@@ -4500,20 +4530,21 @@ void intel_shared_dpll_state_verify(struct intel_crtc *crtc,
u8 pipe_mask = BIT(crtc->pipe);
struct intel_shared_dpll *pll = old_crtc_state->shared_dpll;
- I915_STATE_WARN(dev_priv, pll->active_mask & pipe_mask,
+ I915_STATE_WARN(i915, pll->active_mask & pipe_mask,
"pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n",
pipe_name(crtc->pipe), pll->active_mask);
- I915_STATE_WARN(dev_priv, pll->state.pipe_mask & pipe_mask,
+ I915_STATE_WARN(i915, pll->state.pipe_mask & pipe_mask,
"pll enabled crtcs mismatch (found %x in enabled mask (0x%x))\n",
pipe_name(crtc->pipe), pll->state.pipe_mask);
}
}
-void intel_shared_dpll_verify_disabled(struct drm_i915_private *i915)
+void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state)
{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_shared_dpll *pll;
int i;
- for (i = 0; i < i915->display.dpll.num_shared_dpll; i++)
- verify_single_dpll_state(i915, &i915->display.dpll.shared_dplls[i],
- NULL, NULL);
+ for_each_shared_dpll(i915, pll, i)
+ verify_single_dpll_state(i915, pll, NULL, NULL);
}
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
index 04e6810954..dd4796a617 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
@@ -29,6 +29,10 @@
#include "intel_wakeref.h"
+#define for_each_shared_dpll(__i915, __pll, __i) \
+ for ((__i) = 0; (__i) < (__i915)->display.dpll.num_shared_dpll && \
+ ((__pll) = &(__i915)->display.dpll.shared_dplls[(__i)]) ; (__i)++)
+
enum tc_port;
struct drm_i915_private;
struct intel_atomic_state;
@@ -262,8 +266,7 @@ struct dpll_info {
const struct intel_shared_dpll_funcs *funcs;
/**
- * @id: unique indentifier for this DPLL; should match the index in the
- * dev_priv->shared_dplls array
+ * @id: unique indentifier for this DPLL
*/
enum intel_dpll_id id;
@@ -291,6 +294,11 @@ struct intel_shared_dpll {
struct intel_shared_dpll_state state;
/**
+ * @index: index for atomic state
+ */
+ u8 index;
+
+ /**
* @active_mask: mask of active pipes (i.e. DPMS on) using this DPLL
*/
u8 active_mask;
@@ -319,9 +327,9 @@ struct intel_shared_dpll {
/* shared dpll functions */
struct intel_shared_dpll *
-intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
+intel_get_shared_dpll_by_id(struct drm_i915_private *i915,
enum intel_dpll_id id);
-void assert_shared_dpll(struct drm_i915_private *dev_priv,
+void assert_shared_dpll(struct drm_i915_private *i915,
struct intel_shared_dpll *pll,
bool state);
#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
@@ -351,19 +359,18 @@ bool intel_dpll_get_hw_state(struct drm_i915_private *i915,
void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_shared_dpll_swap_state(struct intel_atomic_state *state);
-void intel_shared_dpll_init(struct drm_i915_private *dev_priv);
-void intel_dpll_update_ref_clks(struct drm_i915_private *dev_priv);
-void intel_dpll_readout_hw_state(struct drm_i915_private *dev_priv);
-void intel_dpll_sanitize_state(struct drm_i915_private *dev_priv);
+void intel_shared_dpll_init(struct drm_i915_private *i915);
+void intel_dpll_update_ref_clks(struct drm_i915_private *i915);
+void intel_dpll_readout_hw_state(struct drm_i915_private *i915);
+void intel_dpll_sanitize_state(struct drm_i915_private *i915);
-void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
+void intel_dpll_dump_hw_state(struct drm_i915_private *i915,
const struct intel_dpll_hw_state *hw_state);
enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port);
bool intel_dpll_is_combophy(enum intel_dpll_id id);
-void intel_shared_dpll_state_verify(struct intel_crtc *crtc,
- struct intel_crtc_state *old_crtc_state,
- struct intel_crtc_state *new_crtc_state);
-void intel_shared_dpll_verify_disabled(struct drm_i915_private *i915);
+void intel_shared_dpll_state_verify(struct intel_atomic_state *state,
+ struct intel_crtc *crtc);
+void intel_shared_dpll_verify_disabled(struct intel_atomic_state *state);
#endif /* _INTEL_DPLL_MGR_H_ */
diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c
index fbfd8f959f..48582b31b7 100644
--- a/drivers/gpu/drm/i915/display/intel_dpt.c
+++ b/drivers/gpu/drm/i915/display/intel_dpt.c
@@ -29,7 +29,7 @@ static inline struct i915_dpt *
i915_vm_to_dpt(struct i915_address_space *vm)
{
BUILD_BUG_ON(offsetof(struct i915_dpt, vm));
- GEM_BUG_ON(!i915_is_dpt(vm));
+ drm_WARN_ON(&vm->i915->drm, !i915_is_dpt(vm));
return container_of(vm, struct i915_dpt, vm);
}
diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c
index 0d35b6be5b..6282ec0fc9 100644
--- a/drivers/gpu/drm/i915/display/intel_drrs.c
+++ b/drivers/gpu/drm/i915/display/intel_drrs.c
@@ -9,6 +9,7 @@
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_drrs.h"
+#include "intel_frontbuffer.h"
#include "intel_panel.h"
/**
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c
index bed058d2c3..7fd6280c54 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -5,13 +5,19 @@
*/
#include "gem/i915_gem_internal.h"
+#include "gem/i915_gem_lmem.h"
#include "i915_drv.h"
+#include "i915_irq.h"
#include "i915_reg.h"
+#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dsb.h"
#include "intel_dsb_regs.h"
+#include "intel_vblank.h"
+#include "intel_vrr.h"
+#include "skl_watermark.h"
struct i915_vma;
@@ -47,6 +53,8 @@ struct intel_dsb {
* register.
*/
unsigned int ins_start_offset;
+
+ int dewake_scanline;
};
/**
@@ -70,17 +78,21 @@ struct intel_dsb {
#define DSB_OPCODE_SHIFT 24
#define DSB_OPCODE_NOOP 0x0
#define DSB_OPCODE_MMIO_WRITE 0x1
+#define DSB_BYTE_EN 0xf
+#define DSB_BYTE_EN_SHIFT 20
+#define DSB_REG_VALUE_MASK 0xfffff
#define DSB_OPCODE_WAIT_USEC 0x2
-#define DSB_OPCODE_WAIT_LINES 0x3
+#define DSB_OPCODE_WAIT_SCANLINE 0x3
#define DSB_OPCODE_WAIT_VBLANKS 0x4
#define DSB_OPCODE_WAIT_DSL_IN 0x5
#define DSB_OPCODE_WAIT_DSL_OUT 0x6
+#define DSB_SCANLINE_UPPER_SHIFT 20
+#define DSB_SCANLINE_LOWER_SHIFT 0
#define DSB_OPCODE_INTERRUPT 0x7
#define DSB_OPCODE_INDEXED_WRITE 0x9
+/* see DSB_REG_VALUE_MASK */
#define DSB_OPCODE_POLL 0xA
-#define DSB_BYTE_EN 0xF
-#define DSB_BYTE_EN_SHIFT 20
-#define DSB_REG_VALUE_MASK 0xfffff
+/* see DSB_REG_VALUE_MASK */
static bool assert_dsb_has_room(struct intel_dsb *dsb)
{
@@ -93,10 +105,26 @@ static bool assert_dsb_has_room(struct intel_dsb *dsb)
crtc->base.base.id, crtc->base.name, dsb->id);
}
+static void intel_dsb_dump(struct intel_dsb *dsb)
+{
+ struct intel_crtc *crtc = dsb->crtc;
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ const u32 *buf = dsb->cmd_buf;
+ int i;
+
+ drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] DSB %d commands {\n",
+ crtc->base.base.id, crtc->base.name, dsb->id);
+ for (i = 0; i < ALIGN(dsb->free_pos, 64 / 4); i += 4)
+ drm_dbg_kms(&i915->drm,
+ " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ i * 4, buf[i], buf[i+1], buf[i+2], buf[i+3]);
+ drm_dbg_kms(&i915->drm, "}\n");
+}
+
static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe,
enum dsb_id id)
{
- return intel_de_read(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY;
+ return intel_de_read_fw(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY;
}
static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
@@ -121,7 +149,15 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
const u32 *buf = dsb->cmd_buf;
u32 prev_opcode, prev_reg;
- prev_opcode = buf[dsb->ins_start_offset + 1] >> DSB_OPCODE_SHIFT;
+ /*
+ * Nothing emitted yet? Must check before looking
+ * at the actual data since i915_gem_object_create_internal()
+ * does *not* give you zeroed memory!
+ */
+ if (dsb->free_pos == 0)
+ return false;
+
+ prev_opcode = buf[dsb->ins_start_offset + 1] & ~DSB_REG_VALUE_MASK;
prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK;
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
@@ -129,12 +165,18 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
static bool intel_dsb_prev_ins_is_mmio_write(struct intel_dsb *dsb, i915_reg_t reg)
{
- return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_MMIO_WRITE, reg);
+ /* only full byte-enables can be converted to indexed writes */
+ return intel_dsb_prev_ins_is_write(dsb,
+ DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT |
+ DSB_BYTE_EN << DSB_BYTE_EN_SHIFT,
+ reg);
}
static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_t reg)
{
- return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_INDEXED_WRITE, reg);
+ return intel_dsb_prev_ins_is_write(dsb,
+ DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT,
+ reg);
}
/**
@@ -200,6 +242,53 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
}
}
+static u32 intel_dsb_mask_to_byte_en(u32 mask)
+{
+ return (!!(mask & 0xff000000) << 3 |
+ !!(mask & 0x00ff0000) << 2 |
+ !!(mask & 0x0000ff00) << 1 |
+ !!(mask & 0x000000ff) << 0);
+}
+
+/* Note: mask implemented via byte enables! */
+void intel_dsb_reg_write_masked(struct intel_dsb *dsb,
+ i915_reg_t reg, u32 mask, u32 val)
+{
+ intel_dsb_emit(dsb, val,
+ (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) |
+ (intel_dsb_mask_to_byte_en(mask) << DSB_BYTE_EN_SHIFT) |
+ i915_mmio_reg_offset(reg));
+}
+
+void intel_dsb_noop(struct intel_dsb *dsb, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ intel_dsb_emit(dsb, 0,
+ DSB_OPCODE_NOOP << DSB_OPCODE_SHIFT);
+}
+
+void intel_dsb_nonpost_start(struct intel_dsb *dsb)
+{
+ struct intel_crtc *crtc = dsb->crtc;
+ enum pipe pipe = crtc->pipe;
+
+ intel_dsb_reg_write_masked(dsb, DSB_CTRL(pipe, dsb->id),
+ DSB_NON_POSTED, DSB_NON_POSTED);
+ intel_dsb_noop(dsb, 4);
+}
+
+void intel_dsb_nonpost_end(struct intel_dsb *dsb)
+{
+ struct intel_crtc *crtc = dsb->crtc;
+ enum pipe pipe = crtc->pipe;
+
+ intel_dsb_reg_write_masked(dsb, DSB_CTRL(pipe, dsb->id),
+ DSB_NON_POSTED, 0);
+ intel_dsb_noop(dsb, 4);
+}
+
static void intel_dsb_align_tail(struct intel_dsb *dsb)
{
u32 aligned_tail, tail;
@@ -216,17 +305,42 @@ static void intel_dsb_align_tail(struct intel_dsb *dsb)
void intel_dsb_finish(struct intel_dsb *dsb)
{
+ struct intel_crtc *crtc = dsb->crtc;
+
+ /*
+ * DSB_FORCE_DEWAKE remains active even after DSB is
+ * disabled, so make sure to clear it (if set during
+ * intel_dsb_commit()).
+ */
+ intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(crtc->pipe, dsb->id),
+ DSB_FORCE_DEWAKE, 0);
+
intel_dsb_align_tail(dsb);
+
+ i915_gem_object_flush_map(dsb->vma->obj);
}
-/**
- * intel_dsb_commit() - Trigger workload execution of DSB.
- * @dsb: DSB context
- * @wait_for_vblank: wait for vblank before executing
- *
- * This function is used to do actual write to hardware using DSB.
- */
-void intel_dsb_commit(struct intel_dsb *dsb, bool wait_for_vblank)
+static int intel_dsb_dewake_scanline(const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
+ unsigned int latency = skl_watermark_max_latency(i915);
+ int vblank_start;
+
+ if (crtc_state->vrr.enable) {
+ vblank_start = intel_vrr_vmin_vblank_start(crtc_state);
+ } else {
+ vblank_start = adjusted_mode->crtc_vblank_start;
+
+ if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+ vblank_start = DIV_ROUND_UP(vblank_start, 2);
+ }
+
+ return max(0, vblank_start - intel_usecs_to_scanlines(adjusted_mode, latency));
+}
+
+static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
+ int dewake_scanline)
{
struct intel_crtc *crtc = dsb->crtc;
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
@@ -243,13 +357,48 @@ void intel_dsb_commit(struct intel_dsb *dsb, bool wait_for_vblank)
return;
}
- intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id),
- (wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0) |
- DSB_ENABLE);
- intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id),
- i915_ggtt_offset(dsb->vma));
- intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id),
- i915_ggtt_offset(dsb->vma) + tail);
+ intel_de_write_fw(dev_priv, DSB_CTRL(pipe, dsb->id),
+ ctrl | DSB_ENABLE);
+
+ intel_de_write_fw(dev_priv, DSB_HEAD(pipe, dsb->id),
+ i915_ggtt_offset(dsb->vma));
+
+ if (dewake_scanline >= 0) {
+ int diff, hw_dewake_scanline;
+
+ hw_dewake_scanline = intel_crtc_scanline_to_hw(crtc, dewake_scanline);
+
+ intel_de_write_fw(dev_priv, DSB_PMCTRL(pipe, dsb->id),
+ DSB_ENABLE_DEWAKE |
+ DSB_SCANLINE_FOR_DEWAKE(hw_dewake_scanline));
+
+ /*
+ * Force DEwake immediately if we're already past
+ * or close to racing past the target scanline.
+ */
+ diff = dewake_scanline - intel_get_crtc_scanline(crtc);
+ intel_de_write_fw(dev_priv, DSB_PMCTRL_2(pipe, dsb->id),
+ (diff >= 0 && diff < 5 ? DSB_FORCE_DEWAKE : 0) |
+ DSB_BLOCK_DEWAKE_EXTENSION);
+ }
+
+ intel_de_write_fw(dev_priv, DSB_TAIL(pipe, dsb->id),
+ i915_ggtt_offset(dsb->vma) + tail);
+}
+
+/**
+ * intel_dsb_commit() - Trigger workload execution of DSB.
+ * @dsb: DSB context
+ * @wait_for_vblank: wait for vblank before executing
+ *
+ * This function is used to do actual write to hardware using DSB.
+ */
+void intel_dsb_commit(struct intel_dsb *dsb,
+ bool wait_for_vblank)
+{
+ _intel_dsb_commit(dsb,
+ wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0,
+ wait_for_vblank ? dsb->dewake_scanline : -1);
}
void intel_dsb_wait(struct intel_dsb *dsb)
@@ -258,20 +407,31 @@ void intel_dsb_wait(struct intel_dsb *dsb)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
- if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1))
+ if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) {
+ u32 offset = i915_ggtt_offset(dsb->vma);
+
+ intel_de_write_fw(dev_priv, DSB_CTRL(pipe, dsb->id),
+ DSB_ENABLE | DSB_HALT);
+
drm_err(&dev_priv->drm,
- "[CRTC:%d:%s] DSB %d timed out waiting for idle\n",
- crtc->base.base.id, crtc->base.name, dsb->id);
+ "[CRTC:%d:%s] DSB %d timed out waiting for idle (current head=0x%x, head=0x%x, tail=0x%x)\n",
+ crtc->base.base.id, crtc->base.name, dsb->id,
+ intel_de_read_fw(dev_priv, DSB_CURRENT_HEAD(pipe, dsb->id)) - offset,
+ intel_de_read_fw(dev_priv, DSB_HEAD(pipe, dsb->id)) - offset,
+ intel_de_read_fw(dev_priv, DSB_TAIL(pipe, dsb->id)) - offset);
+
+ intel_dsb_dump(dsb);
+ }
/* Attempt to reset it */
dsb->free_pos = 0;
dsb->ins_start_offset = 0;
- intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), 0);
+ intel_de_write_fw(dev_priv, DSB_CTRL(pipe, dsb->id), 0);
}
/**
* intel_dsb_prepare() - Allocate, pin and map the DSB command buffer.
- * @crtc: the CRTC
+ * @crtc_state: the CRTC state
* @max_cmds: number of commands we need to fit into command buffer
*
* This function prepare the command buffer which is used to store dsb
@@ -280,9 +440,10 @@ void intel_dsb_wait(struct intel_dsb *dsb)
* Returns:
* DSB context, NULL on failure
*/
-struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc,
+struct intel_dsb *intel_dsb_prepare(const struct intel_crtc_state *crtc_state,
unsigned int max_cmds)
{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct drm_i915_gem_object *obj;
intel_wakeref_t wakeref;
@@ -303,9 +464,18 @@ struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc,
/* ~1 qword per instruction, full cachelines */
size = ALIGN(max_cmds * 8, CACHELINE_BYTES);
- obj = i915_gem_object_create_internal(i915, PAGE_ALIGN(size));
- if (IS_ERR(obj))
- goto out_put_rpm;
+ if (HAS_LMEM(i915)) {
+ obj = i915_gem_object_create_lmem(i915, PAGE_ALIGN(size),
+ I915_BO_ALLOC_CONTIGUOUS);
+ if (IS_ERR(obj))
+ goto out_put_rpm;
+ } else {
+ obj = i915_gem_object_create_internal(i915, PAGE_ALIGN(size));
+ if (IS_ERR(obj))
+ goto out_put_rpm;
+
+ i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
+ }
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
if (IS_ERR(vma)) {
@@ -328,6 +498,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc,
dsb->size = size / 4; /* in dwords */
dsb->free_pos = 0;
dsb->ins_start_offset = 0;
+ dsb->dewake_scanline = intel_dsb_dewake_scanline(crtc_state);
return dsb;
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h
index b8148b4702..16d80f4343 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -11,14 +11,21 @@
#include "i915_reg_defs.h"
struct intel_crtc;
+struct intel_crtc_state;
struct intel_dsb;
-struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc,
+struct intel_dsb *intel_dsb_prepare(const struct intel_crtc_state *crtc_state,
unsigned int max_cmds);
void intel_dsb_finish(struct intel_dsb *dsb);
void intel_dsb_cleanup(struct intel_dsb *dsb);
void intel_dsb_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val);
+void intel_dsb_reg_write_masked(struct intel_dsb *dsb,
+ i915_reg_t reg, u32 mask, u32 val);
+void intel_dsb_noop(struct intel_dsb *dsb, int count);
+void intel_dsb_nonpost_start(struct intel_dsb *dsb);
+void intel_dsb_nonpost_end(struct intel_dsb *dsb);
+
void intel_dsb_commit(struct intel_dsb *dsb,
bool wait_for_vblank);
void intel_dsb_wait(struct intel_dsb *dsb);
diff --git a/drivers/gpu/drm/i915/display/intel_dsb_regs.h b/drivers/gpu/drm/i915/display/intel_dsb_regs.h
index 12535d4787..210e266544 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb_regs.h
@@ -37,6 +37,19 @@
#define DSB_DEBUG(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x14)
#define DSB_POLLMASK(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x1c)
#define DSB_STATUS(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x24)
+#define DSB_HP_IDLE_STATUS REG_BIT(31)
+#define DSB_DEWAKE_STATUS REG_BIT(30)
+#define DSB_REQARB_SM_STATE_MASK REG_GENMASK(29, 27)
+#define DSB_SAFE_WINDOW_LIVE REG_BIT(26)
+#define DSB_VTDFAULT_ARB_SM_STATE_MASK REG_GENMASK(25, 23)
+#define DSB_TLBTRANS_SM_STATE_MASK REG_GENMASK(21, 20)
+#define DSB_SAFE_WINDOW REG_BIT(19)
+#define DSB_POINTERS_SM_STATE_MASK REG_GENMASK(18, 17)
+#define DSB_BUSY_ON_DELAYED_VBLANK REG_BIT(16)
+#define DSB_MMIO_ARB_SM_STATE_MASK REG_GENMASK(15, 13)
+#define DSB_MMIO_INST_SM_STATE_MASK REG_GENMASK(11, 7)
+#define DSB_RESET_SM_STATE_MASK REG_GENMASK(5, 4)
+#define DSB_RUN_SM_STATE_MASK REG_GENMASK(2, 0)
#define DSB_INTERRUPT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x28)
#define DSB_ATS_FAULT_INT_EN REG_BIT(20)
#define DSB_GTT_FAULT_INT_EN REG_BIT(19)
@@ -58,10 +71,28 @@
#define DSB_RM_READY_TIMEOUT_VALUE(x) REG_FIELD_PREP(DSB_RM_READY_TIMEOUT_VALUE, (x)) /* usec */
#define DSB_RMTIMEOUTREG_CAPTURE(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x34)
#define DSB_PMCTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x38)
+#define DSB_ENABLE_DEWAKE REG_BIT(31)
+#define DSB_SCANLINE_FOR_DEWAKE_MASK REG_GENMASK(30, 0)
+#define DSB_SCANLINE_FOR_DEWAKE(x) REG_FIELD_PREP(DSB_SCANLINE_FOR_DEWAKE_MASK, (x))
#define DSB_PMCTRL_2(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x3c)
+#define DSB_MMIOGEN_DEWAKE_DIS REG_BIT(31)
+#define DSB_FORCE_DEWAKE REG_BIT(23)
+#define DSB_BLOCK_DEWAKE_EXTENSION REG_BIT(15)
+#define DSB_OVERRIDE_DC5_DC6_OK REG_BIT(7)
#define DSB_PF_LN_LOWER(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x40)
#define DSB_PF_LN_UPPER(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x44)
#define DSB_BUFRPT_CNT(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x48)
#define DSB_CHICKEN(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0xf0)
+#define DSB_FORCE_DMA_SYNC_RESET REG_BIT(31)
+#define DSB_FORCE_VTD_ENGIE_RESET REG_BIT(30)
+#define DSB_DISABLE_IPC_DEMOTE REG_BIT(29)
+#define DSB_SKIP_WAITS_EN REG_BIT(23)
+#define DSB_EXTEND_HP_IDLE REG_BIT(16)
+#define DSB_CTRL_WAIT_SAFE_WINDOW REG_BIT(15)
+#define DSB_CTRL_NO_WAIT_VBLANK REG_BIT(14)
+#define DSB_INST_WAIT_SAFE_WINDOW REG_BIT(7)
+#define DSB_INST_NO_WAIT_VBLANK REG_BIT(6)
+#define DSB_MMIOGEN_DEWAKE_DIS_CHICKEN REG_BIT(2)
+#define DSB_DISABLE_MMIO_COUNT_FOR_INDEXED REG_BIT(0)
#endif /* __INTEL_DSB_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
index e56ec3f2d8..24b2cbcfc1 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
@@ -565,6 +565,9 @@ static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data)
u8 payload_size = *(data + 6);
u8 *payload_data;
+ drm_dbg_kms(&i915->drm, "bus %d client-addr 0x%02x reg 0x%02x data %*ph\n",
+ vbt_i2c_bus_num, slave_addr, reg_offset, payload_size, data + 7);
+
if (intel_dsi->i2c_bus_num < 0) {
intel_dsi->i2c_bus_num = vbt_i2c_bus_num;
i2c_acpi_find_adapter(intel_dsi, slave_addr);
diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c
index d1cfa966d4..9111e9d464 100644
--- a/drivers/gpu/drm/i915/display/intel_dvo.c
+++ b/drivers/gpu/drm/i915/display/intel_dvo.c
@@ -325,7 +325,7 @@ intel_dvo_detect(struct drm_connector *_connector, bool force)
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n",
connector->base.base.id, connector->base.name);
- if (!INTEL_DISPLAY_ENABLED(i915))
+ if (!intel_display_device_enabled(i915))
return connector_status_disconnected;
return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
@@ -334,7 +334,6 @@ intel_dvo_detect(struct drm_connector *_connector, bool force)
static int intel_dvo_get_modes(struct drm_connector *_connector)
{
struct intel_connector *connector = to_intel_connector(_connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
int num_modes;
/*
@@ -343,8 +342,7 @@ static int intel_dvo_get_modes(struct drm_connector *_connector)
* (TV-out, for example), but for now with just TMDS and LVDS,
* that's not the case.
*/
- num_modes = intel_ddc_get_modes(&connector->base,
- intel_gmbus_get_adapter(i915, GMBUS_PIN_DPC));
+ num_modes = intel_ddc_get_modes(&connector->base, connector->base.ddc);
if (num_modes)
return num_modes;
@@ -539,9 +537,10 @@ void intel_dvo_init(struct drm_i915_private *i915)
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT;
- drm_connector_init(&i915->drm, &connector->base,
- &intel_dvo_connector_funcs,
- intel_dvo_connector_type(&intel_dvo->dev));
+ drm_connector_init_with_ddc(&i915->drm, &connector->base,
+ &intel_dvo_connector_funcs,
+ intel_dvo_connector_type(&intel_dvo->dev),
+ intel_gmbus_get_adapter(i915, GMBUS_PIN_DPC));
drm_connector_helper_add(&connector->base,
&intel_dvo_connector_helper_funcs);
diff --git a/drivers/gpu/drm/i915/display/intel_dvo.h b/drivers/gpu/drm/i915/display/intel_dvo.h
index 3ed0fdf8ef..bf7a356422 100644
--- a/drivers/gpu/drm/i915/display/intel_dvo.h
+++ b/drivers/gpu/drm/i915/display/intel_dvo.h
@@ -8,6 +8,12 @@
struct drm_i915_private;
+#ifdef I915
void intel_dvo_init(struct drm_i915_private *dev_priv);
+#else
+static inline void intel_dvo_init(struct drm_i915_private *dev_priv)
+{
+}
+#endif
#endif /* __INTEL_DVO_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c
index 689b7c16d3..646f367a13 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -7,11 +7,15 @@
#include <drm/drm_framebuffer.h>
#include <drm/drm_modeset_helper.h>
+#include <linux/dma-fence.h>
+#include <linux/dma-resv.h>
+
#include "i915_drv.h"
#include "intel_display.h"
#include "intel_display_types.h"
#include "intel_dpt.h"
#include "intel_fb.h"
+#include "intel_frontbuffer.h"
#define check_array_bounds(i915, a, i) drm_WARN_ON(&(i915)->drm, (i) >= ARRAY_SIZE(a))
@@ -1113,7 +1117,7 @@ static int intel_fb_offset_to_xy(int *x, int *y,
return -EINVAL;
}
- height = drm_framebuffer_plane_height(fb->height, fb, color_plane);
+ height = drm_format_info_plane_height(fb->format, fb->height, color_plane);
height = ALIGN(height, intel_tile_height(fb, color_plane));
/* Catch potential overflows early */
@@ -1909,6 +1913,21 @@ static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
return drm_gem_handle_create(file, &obj->base, handle);
}
+struct frontbuffer_fence_cb {
+ struct dma_fence_cb base;
+ struct intel_frontbuffer *front;
+};
+
+static void intel_user_framebuffer_fence_wake(struct dma_fence *dma,
+ struct dma_fence_cb *data)
+{
+ struct frontbuffer_fence_cb *cb = container_of(data, typeof(*cb), base);
+
+ intel_frontbuffer_queue_flush(cb->front);
+ kfree(cb);
+ dma_fence_put(dma);
+}
+
static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
struct drm_file *file,
unsigned int flags, unsigned int color,
@@ -1916,11 +1935,47 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
unsigned int num_clips)
{
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+ struct intel_frontbuffer *front = to_intel_frontbuffer(fb);
+ struct dma_fence *fence;
+ struct frontbuffer_fence_cb *cb;
+ int ret = 0;
- i915_gem_object_flush_if_display(obj);
- intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB);
+ if (!atomic_read(&front->bits))
+ return 0;
- return 0;
+ if (dma_resv_test_signaled(obj->base.resv, dma_resv_usage_rw(false)))
+ goto flush;
+
+ ret = dma_resv_get_singleton(obj->base.resv, dma_resv_usage_rw(false),
+ &fence);
+ if (ret || !fence)
+ goto flush;
+
+ cb = kmalloc(sizeof(*cb), GFP_KERNEL);
+ if (!cb) {
+ dma_fence_put(fence);
+ ret = -ENOMEM;
+ goto flush;
+ }
+
+ cb->front = front;
+
+ intel_frontbuffer_invalidate(front, ORIGIN_DIRTYFB);
+
+ ret = dma_fence_add_callback(fence, &cb->base,
+ intel_user_framebuffer_fence_wake);
+ if (ret) {
+ intel_user_framebuffer_fence_wake(fence, &cb->base);
+ if (ret == -ENOENT)
+ ret = 0;
+ }
+
+ return ret;
+
+flush:
+ i915_gem_object_flush_if_display(obj);
+ intel_frontbuffer_flush(front, ORIGIN_DIRTYFB);
+ return ret;
}
static const struct drm_framebuffer_funcs intel_fb_funcs = {
diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c
index fffd568070..7b42aef37d 100644
--- a/drivers/gpu/drm/i915/display/intel_fb_pin.c
+++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c
@@ -35,7 +35,8 @@ intel_pin_fb_obj_dpt(struct drm_framebuffer *fb,
* We are not syncing against the binding (and potential migrations)
* below, so this vm must never be async.
*/
- GEM_WARN_ON(vm->bind_async_flags);
+ if (drm_WARN_ON(&dev_priv->drm, vm->bind_async_flags))
+ return ERR_PTR(-EINVAL);
if (WARN_ON(!i915_gem_object_is_framebuffer(obj)))
return ERR_PTR(-EINVAL);
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index 25382022cd..4820d21cc9 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -50,6 +50,7 @@
#include "i915_vma.h"
#include "intel_cdclk.h"
#include "intel_de.h"
+#include "intel_display_device.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"
#include "intel_fbc.h"
@@ -332,12 +333,14 @@ static void i8xx_fbc_program_cfb(struct intel_fbc *fbc)
{
struct drm_i915_private *i915 = fbc->i915;
- GEM_BUG_ON(range_overflows_end_t(u64, i915_gem_stolen_area_address(i915),
- i915_gem_stolen_node_offset(&fbc->compressed_fb),
- U32_MAX));
- GEM_BUG_ON(range_overflows_end_t(u64, i915_gem_stolen_area_address(i915),
- i915_gem_stolen_node_offset(&fbc->compressed_llb),
- U32_MAX));
+ drm_WARN_ON(&i915->drm,
+ range_overflows_end_t(u64, i915_gem_stolen_area_address(i915),
+ i915_gem_stolen_node_offset(&fbc->compressed_fb),
+ U32_MAX));
+ drm_WARN_ON(&i915->drm,
+ range_overflows_end_t(u64, i915_gem_stolen_area_address(i915),
+ i915_gem_stolen_node_offset(&fbc->compressed_llb),
+ U32_MAX));
intel_de_write(i915, FBC_CFB_BASE,
i915_gem_stolen_node_address(i915, &fbc->compressed_fb));
intel_de_write(i915, FBC_LL_BASE,
@@ -590,6 +593,9 @@ static u32 ivb_dpfc_ctl(struct intel_fbc *fbc)
if (IS_IVYBRIDGE(i915))
dpfc_ctl |= DPFC_CTL_PLANE_IVB(fbc_state->plane->i9xx_plane);
+ if (DISPLAY_VER(i915) >= 20)
+ dpfc_ctl |= DPFC_CTL_PLANE_BINDING(fbc_state->plane->id);
+
if (fbc_state->fence_id >= 0)
dpfc_ctl |= DPFC_CTL_FENCE_EN_IVB;
@@ -847,39 +853,64 @@ void intel_fbc_cleanup(struct drm_i915_private *i915)
}
}
-static bool stride_is_valid(const struct intel_plane_state *plane_state)
+static bool i8xx_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
{
- struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int stride = intel_fbc_plane_stride(plane_state) *
fb->format->cpp[0];
- /* This should have been caught earlier. */
- if (drm_WARN_ON_ONCE(&i915->drm, (stride & (64 - 1)) != 0))
- return false;
+ return stride == 4096 || stride == 8192;
+}
- /* Below are the additional FBC restrictions. */
- if (stride < 512)
- return false;
+static bool i965_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
+{
+ const struct drm_framebuffer *fb = plane_state->hw.fb;
+ unsigned int stride = intel_fbc_plane_stride(plane_state) *
+ fb->format->cpp[0];
- if (DISPLAY_VER(i915) == 2 || DISPLAY_VER(i915) == 3)
- return stride == 4096 || stride == 8192;
+ return stride >= 2048 && stride <= 16384;
+}
- if (DISPLAY_VER(i915) == 4 && !IS_G4X(i915) && stride < 2048)
- return false;
+static bool g4x_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
+{
+ return true;
+}
+
+static bool skl_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
+{
+ const struct drm_framebuffer *fb = plane_state->hw.fb;
+ unsigned int stride = intel_fbc_plane_stride(plane_state) *
+ fb->format->cpp[0];
/* Display WA #1105: skl,bxt,kbl,cfl,glk */
- if ((DISPLAY_VER(i915) == 9 || IS_GEMINILAKE(i915)) &&
- fb->modifier == DRM_FORMAT_MOD_LINEAR && stride & 511)
+ if (fb->modifier == DRM_FORMAT_MOD_LINEAR && stride & 511)
return false;
- if (stride > 16384)
- return false;
+ return true;
+}
+static bool icl_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
+{
return true;
}
-static bool pixel_format_is_valid(const struct intel_plane_state *plane_state)
+static bool stride_is_valid(const struct intel_plane_state *plane_state)
+{
+ struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
+
+ if (DISPLAY_VER(i915) >= 11)
+ return icl_fbc_stride_is_valid(plane_state);
+ else if (DISPLAY_VER(i915) >= 9)
+ return skl_fbc_stride_is_valid(plane_state);
+ else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915))
+ return g4x_fbc_stride_is_valid(plane_state);
+ else if (DISPLAY_VER(i915) == 4)
+ return i965_fbc_stride_is_valid(plane_state);
+ else
+ return i8xx_fbc_stride_is_valid(plane_state);
+}
+
+static bool i8xx_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state)
{
struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
@@ -893,6 +924,22 @@ static bool pixel_format_is_valid(const struct intel_plane_state *plane_state)
/* 16bpp not supported on gen2 */
if (DISPLAY_VER(i915) == 2)
return false;
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool g4x_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state)
+{
+ struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
+ const struct drm_framebuffer *fb = plane_state->hw.fb;
+
+ switch (fb->format->format) {
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_XBGR8888:
+ return true;
+ case DRM_FORMAT_RGB565:
/* WaFbcOnly1to1Ratio:ctg */
if (IS_G4X(i915))
return false;
@@ -902,22 +949,68 @@ static bool pixel_format_is_valid(const struct intel_plane_state *plane_state)
}
}
-static bool rotation_is_valid(const struct intel_plane_state *plane_state)
+static bool lnl_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state)
+{
+ const struct drm_framebuffer *fb = plane_state->hw.fb;
+
+ switch (fb->format->format) {
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_RGB565:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool pixel_format_is_valid(const struct intel_plane_state *plane_state)
{
struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
+
+ if (DISPLAY_VER(i915) >= 20)
+ return lnl_fbc_pixel_format_is_valid(plane_state);
+ else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915))
+ return g4x_fbc_pixel_format_is_valid(plane_state);
+ else
+ return i8xx_fbc_pixel_format_is_valid(plane_state);
+}
+
+static bool i8xx_fbc_rotation_is_valid(const struct intel_plane_state *plane_state)
+{
+ return plane_state->hw.rotation == DRM_MODE_ROTATE_0;
+}
+
+static bool g4x_fbc_rotation_is_valid(const struct intel_plane_state *plane_state)
+{
+ return true;
+}
+
+static bool skl_fbc_rotation_is_valid(const struct intel_plane_state *plane_state)
+{
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int rotation = plane_state->hw.rotation;
- if (DISPLAY_VER(i915) >= 9 && fb->format->format == DRM_FORMAT_RGB565 &&
+ if (fb->format->format == DRM_FORMAT_RGB565 &&
drm_rotation_90_or_270(rotation))
return false;
- else if (DISPLAY_VER(i915) <= 4 && !IS_G4X(i915) &&
- rotation != DRM_MODE_ROTATE_0)
- return false;
return true;
}
+static bool rotation_is_valid(const struct intel_plane_state *plane_state)
+{
+ struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
+
+ if (DISPLAY_VER(i915) >= 9)
+ return skl_fbc_rotation_is_valid(plane_state);
+ else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915))
+ return g4x_fbc_rotation_is_valid(plane_state);
+ else
+ return i8xx_fbc_rotation_is_valid(plane_state);
+}
+
/*
* For some reason, the hardware tracking starts looking at whatever we
* programmed as the display plane base address register. It does not look at
@@ -951,16 +1044,21 @@ static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state *
return effective_w <= max_w && effective_h <= max_h;
}
-static bool tiling_is_valid(const struct intel_plane_state *plane_state)
+static bool i8xx_fbc_tiling_valid(const struct intel_plane_state *plane_state)
+{
+ const struct drm_framebuffer *fb = plane_state->hw.fb;
+
+ return fb->modifier == I915_FORMAT_MOD_X_TILED;
+}
+
+static bool skl_fbc_tiling_valid(const struct intel_plane_state *plane_state)
{
- struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
switch (fb->modifier) {
case DRM_FORMAT_MOD_LINEAR:
case I915_FORMAT_MOD_Y_TILED:
case I915_FORMAT_MOD_Yf_TILED:
- return DISPLAY_VER(i915) >= 9;
case I915_FORMAT_MOD_4_TILED:
case I915_FORMAT_MOD_X_TILED:
return true;
@@ -969,6 +1067,16 @@ static bool tiling_is_valid(const struct intel_plane_state *plane_state)
}
}
+static bool tiling_is_valid(const struct intel_plane_state *plane_state)
+{
+ struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
+
+ if (DISPLAY_VER(i915) >= 9)
+ return skl_fbc_tiling_valid(plane_state);
+ else
+ return i8xx_fbc_tiling_valid(plane_state);
+}
+
static void intel_fbc_update_state(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_plane *plane)
@@ -1100,7 +1208,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,
/* Wa_14016291713 */
if ((IS_DISPLAY_VER(i915, 12, 13) ||
- IS_MTL_DISPLAY_STEP(i915, STEP_A0, STEP_C0)) &&
+ IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_C0)) &&
crtc_state->has_psr) {
plane_state->no_fbc_reason = "PSR1 enabled (Wa_14016291713)";
return 0;
@@ -1126,7 +1234,8 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,
return 0;
}
- if (plane_state->hw.pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE &&
+ if (DISPLAY_VER(i915) < 20 &&
+ plane_state->hw.pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE &&
fb->format->has_alpha) {
plane_state->no_fbc_reason = "per-pixel alpha not supported";
return 0;
@@ -1306,11 +1415,9 @@ static void __intel_fbc_post_update(struct intel_fbc *fbc)
lockdep_assert_held(&fbc->lock);
fbc->flip_pending = false;
+ fbc->busy_bits = 0;
- if (!fbc->busy_bits)
- intel_fbc_activate(fbc);
- else
- intel_fbc_deactivate(fbc, "frontbuffer write");
+ intel_fbc_activate(fbc);
}
void intel_fbc_post_update(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h
index 4adb98afe6..6720ec8ee8 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.h
+++ b/drivers/gpu/drm/i915/display/intel_fbc.h
@@ -20,6 +20,8 @@ struct intel_plane_state;
enum intel_fbc_id {
INTEL_FBC_A,
INTEL_FBC_B,
+ INTEL_FBC_C,
+ INTEL_FBC_D,
I915_MAX_FBCS,
};
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index e12b46a84f..e6429dfebe 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -13,6 +13,7 @@
#include "intel_display_types.h"
#include "intel_fdi.h"
#include "intel_fdi_regs.h"
+#include "intel_link_bw.h"
struct intel_fdi_funcs {
void (*fdi_link_train)(struct intel_crtc *crtc,
@@ -119,6 +120,53 @@ void intel_fdi_link_train(struct intel_crtc *crtc,
dev_priv->display.funcs.fdi->fdi_link_train(crtc, crtc_state);
}
+/**
+ * intel_fdi_add_affected_crtcs - add CRTCs on FDI affected by other modeset CRTCs
+ * @state: intel atomic state
+ *
+ * Add a CRTC using FDI to @state if changing another CRTC's FDI BW usage is
+ * known to affect the available FDI BW for the former CRTC. In practice this
+ * means adding CRTC B on IVYBRIDGE if its use of FDI lanes is limited (by
+ * CRTC C) and CRTC C is getting disabled.
+ *
+ * Returns 0 in case of success, or a negative error code otherwise.
+ */
+int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_crtc_state *old_crtc_state;
+ const struct intel_crtc_state *new_crtc_state;
+ struct intel_crtc *crtc;
+
+ if (!IS_IVYBRIDGE(i915) || INTEL_NUM_PIPES(i915) != 3)
+ return 0;
+
+ crtc = intel_crtc_for_pipe(i915, PIPE_C);
+ new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
+ if (!new_crtc_state)
+ return 0;
+
+ if (!intel_crtc_needs_modeset(new_crtc_state))
+ return 0;
+
+ old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
+ if (!old_crtc_state->fdi_lanes)
+ return 0;
+
+ crtc = intel_crtc_for_pipe(i915, PIPE_B);
+ new_crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+ if (IS_ERR(new_crtc_state))
+ return PTR_ERR(new_crtc_state);
+
+ old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
+ if (!old_crtc_state->fdi_lanes)
+ return 0;
+
+ return intel_modeset_pipes_in_mask_early(state,
+ "FDI link BW decrease on pipe C",
+ BIT(PIPE_B));
+}
+
/* units of 100MHz */
static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
{
@@ -129,13 +177,16 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
}
static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
- struct intel_crtc_state *pipe_config)
+ struct intel_crtc_state *pipe_config,
+ enum pipe *pipe_to_reduce)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_atomic_state *state = pipe_config->uapi.state;
struct intel_crtc *other_crtc;
struct intel_crtc_state *other_crtc_state;
+ *pipe_to_reduce = pipe;
+
drm_dbg_kms(&dev_priv->drm,
"checking fdi config on pipe %c, lanes %i\n",
pipe_name(pipe), pipe_config->fdi_lanes);
@@ -198,6 +249,9 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
if (pipe_required_fdi_lanes(other_crtc_state) > 2) {
drm_dbg_kms(&dev_priv->drm,
"fdi link B uses too many lanes to enable link C\n");
+
+ *pipe_to_reduce = PIPE_B;
+
return -EINVAL;
}
return 0;
@@ -232,16 +286,42 @@ int intel_fdi_link_freq(struct drm_i915_private *i915,
return i915->display.fdi.pll_freq;
}
+/**
+ * intel_fdi_compute_pipe_bpp - compute pipe bpp limited by max link bpp
+ * @crtc_state: the crtc state
+ *
+ * Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can
+ * call this function during state computation in the simple case where the
+ * link bpp will always match the pipe bpp. This is the case for all non-DP
+ * encoders, while DP encoders will use a link bpp lower than pipe bpp in case
+ * of DSC compression.
+ *
+ * Returns %true in case of success, %false if pipe bpp would need to be
+ * reduced below its valid range.
+ */
+bool intel_fdi_compute_pipe_bpp(struct intel_crtc_state *crtc_state)
+{
+ int pipe_bpp = min(crtc_state->pipe_bpp,
+ to_bpp_int(crtc_state->max_link_bpp_x16));
+
+ pipe_bpp = rounddown(pipe_bpp, 2 * 3);
+
+ if (pipe_bpp < 6 * 3)
+ return false;
+
+ crtc_state->pipe_bpp = pipe_bpp;
+
+ return true;
+}
+
int ilk_fdi_compute_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *i915 = to_i915(dev);
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
- int lane, link_bw, fdi_dotclock, ret;
- bool needs_recompute = false;
+ int lane, link_bw, fdi_dotclock;
-retry:
/* FDI is a binary signal running at ~2.7GHz, encoding
* each output octet as 10 bits. The actual frequency
* is stored as a divider into a 100MHz clock, and the
@@ -261,25 +341,69 @@ retry:
intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
link_bw, &pipe_config->fdi_m_n, false);
- ret = ilk_check_fdi_lanes(dev, crtc->pipe, pipe_config);
- if (ret == -EDEADLK)
+ return 0;
+}
+
+static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ struct intel_crtc_state *pipe_config,
+ struct intel_link_bw_limits *limits)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ enum pipe pipe_to_reduce;
+ int ret;
+
+ ret = ilk_check_fdi_lanes(&i915->drm, crtc->pipe, pipe_config,
+ &pipe_to_reduce);
+ if (ret != -EINVAL)
return ret;
- if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
- pipe_config->pipe_bpp -= 2*3;
- drm_dbg_kms(&i915->drm,
- "fdi link bw constraint, reducing pipe bpp to %i\n",
- pipe_config->pipe_bpp);
- needs_recompute = true;
- pipe_config->bw_constrained = true;
+ ret = intel_link_bw_reduce_bpp(state, limits,
+ BIT(pipe_to_reduce),
+ "FDI link BW");
- goto retry;
- }
+ return ret ? : -EAGAIN;
+}
+
+/**
+ * intel_fdi_atomic_check_link - check all modeset FDI link configuration
+ * @state: intel atomic state
+ * @limits: link BW limits
+ *
+ * Check the link configuration for all modeset FDI outputs. If the
+ * configuration is invalid @limits will be updated if possible to
+ * reduce the total BW, after which the configuration for all CRTCs in
+ * @state must be recomputed with the updated @limits.
+ *
+ * Returns:
+ * - 0 if the confugration is valid
+ * - %-EAGAIN, if the configuration is invalid and @limits got updated
+ * with fallback values with which the configuration of all CRTCs
+ * in @state must be recomputed
+ * - Other negative error, if the configuration is invalid without a
+ * fallback possibility, or the check failed for another reason
+ */
+int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
+ struct intel_link_bw_limits *limits)
+{
+ struct intel_crtc *crtc;
+ struct intel_crtc_state *crtc_state;
+ int i;
+
+ for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
+ int ret;
+
+ if (!crtc_state->has_pch_encoder ||
+ !intel_crtc_needs_modeset(crtc_state) ||
+ !crtc_state->hw.enable)
+ continue;
- if (needs_recompute)
- return -EAGAIN;
+ ret = intel_fdi_atomic_check_bw(state, crtc, crtc_state, limits);
+ if (ret)
+ return ret;
+ }
- return ret;
+ return 0;
}
static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool enable)
@@ -766,7 +890,10 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
* WaFDIAutoLinkSetTimingOverrride:hsw
*/
intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A),
- FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2) | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
+ FDI_RX_PWRDN_LANE1_VAL(2) |
+ FDI_RX_PWRDN_LANE0_VAL(2) |
+ FDI_RX_TP1_TO_TP2_48 |
+ FDI_RX_FDI_DELAY_90);
/* Enable the PCH Receiver FDI PLL */
rx_ctl_val = dev_priv->display.fdi.rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
@@ -799,7 +926,9 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
* achieved on the PCH side in FDI_RX_CTL, so no need to set the
* port reversal bit */
intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E),
- DDI_BUF_CTL_ENABLE | ((crtc_state->fdi_lanes - 1) << 1) | DDI_BUF_TRANS_SELECT(i / 2));
+ DDI_BUF_CTL_ENABLE |
+ ((crtc_state->fdi_lanes - 1) << 1) |
+ DDI_BUF_TRANS_SELECT(i / 2));
intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));
udelay(600);
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
index 1cdb861727..477ff01369 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.h
+++ b/drivers/gpu/drm/i915/display/intel_fdi.h
@@ -6,16 +6,24 @@
#ifndef _INTEL_FDI_H_
#define _INTEL_FDI_H_
+#include <linux/types.h>
+
enum pipe;
struct drm_i915_private;
+struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_encoder;
+struct intel_link_bw_limits;
+int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state);
int intel_fdi_link_freq(struct drm_i915_private *i915,
const struct intel_crtc_state *pipe_config);
+bool intel_fdi_compute_pipe_bpp(struct intel_crtc_state *crtc_state);
int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
struct intel_crtc_state *pipe_config);
+int intel_fdi_atomic_check_link(struct intel_atomic_state *state,
+ struct intel_link_bw_limits *limits);
void intel_fdi_normal_train(struct intel_crtc *crtc);
void ilk_fdi_disable(struct intel_crtc *crtc);
void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
index 22392f94b6..2ea37c0414 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
@@ -55,6 +55,8 @@
* cancelled as soon as busyness is detected.
*/
+#include "gem/i915_gem_object_frontbuffer.h"
+#include "i915_active.h"
#include "i915_drv.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"
@@ -202,6 +204,33 @@ void __intel_fb_flush(struct intel_frontbuffer *front,
frontbuffer_flush(i915, frontbuffer_bits, origin);
}
+static void intel_frontbuffer_flush_work(struct work_struct *work)
+{
+ struct intel_frontbuffer *front =
+ container_of(work, struct intel_frontbuffer, flush_work);
+
+ i915_gem_object_flush_if_display(front->obj);
+ intel_frontbuffer_flush(front, ORIGIN_DIRTYFB);
+ intel_frontbuffer_put(front);
+}
+
+/**
+ * intel_frontbuffer_queue_flush - queue flushing frontbuffer object
+ * @front: GEM object to flush
+ *
+ * This function is targeted for our dirty callback for queueing flush when
+ * dma fence is signales
+ */
+void intel_frontbuffer_queue_flush(struct intel_frontbuffer *front)
+{
+ if (!front)
+ return;
+
+ kref_get(&front->ref);
+ if (!schedule_work(&front->flush_work))
+ intel_frontbuffer_put(front);
+}
+
static int frontbuffer_active(struct i915_active *ref)
{
struct intel_frontbuffer *front =
@@ -223,7 +252,7 @@ static void frontbuffer_retire(struct i915_active *ref)
static void frontbuffer_release(struct kref *ref)
__releases(&intel_bo_to_i915(front->obj)->display.fb_tracking.lock)
{
- struct intel_frontbuffer *front =
+ struct intel_frontbuffer *ret, *front =
container_of(ref, typeof(*front), ref);
struct drm_i915_gem_object *obj = front->obj;
@@ -231,12 +260,11 @@ static void frontbuffer_release(struct kref *ref)
i915_ggtt_clear_scanout(obj);
- i915_gem_object_set_frontbuffer(obj, NULL);
+ ret = i915_gem_object_set_frontbuffer(obj, NULL);
+ drm_WARN_ON(&intel_bo_to_i915(obj)->drm, ret);
spin_unlock(&intel_bo_to_i915(obj)->display.fb_tracking.lock);
i915_active_fini(&front->write);
-
- i915_gem_object_put(obj);
kfree_rcu(front, rcu);
}
@@ -261,6 +289,7 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)
frontbuffer_active,
frontbuffer_retire,
I915_ACTIVE_RETIRE_SLEEPS);
+ INIT_WORK(&front->flush_work, intel_frontbuffer_flush_work);
spin_lock(&i915->display.fb_tracking.lock);
cur = i915_gem_object_set_frontbuffer(obj, front);
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.h b/drivers/gpu/drm/i915/display/intel_frontbuffer.h
index 72d89be328..abb51e8bb9 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.h
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.h
@@ -46,6 +46,8 @@ struct intel_frontbuffer {
struct i915_active write;
struct drm_i915_gem_object *obj;
struct rcu_head rcu;
+
+ struct work_struct flush_work;
};
/*
@@ -135,6 +137,8 @@ static inline void intel_frontbuffer_flush(struct intel_frontbuffer *front,
__intel_fb_flush(front, origin, frontbuffer_bits);
}
+void intel_frontbuffer_queue_flush(struct intel_frontbuffer *front);
+
void intel_frontbuffer_track(struct intel_frontbuffer *old,
struct intel_frontbuffer *new,
unsigned int frontbuffer_bits);
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
index e95ddb580e..40d7b6f3f4 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
@@ -155,7 +155,10 @@ static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *i915,
const struct gmbus_pin *pins;
size_t size;
- if (INTEL_PCH_TYPE(i915) >= PCH_DG2) {
+ if (INTEL_PCH_TYPE(i915) >= PCH_LNL) {
+ pins = gmbus_pins_mtp;
+ size = ARRAY_SIZE(gmbus_pins_mtp);
+ } else if (INTEL_PCH_TYPE(i915) >= PCH_DG2) {
pins = gmbus_pins_dg2;
size = ARRAY_SIZE(gmbus_pins_dg2);
} else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) {
@@ -778,7 +781,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
struct intel_gmbus *bus = to_intel_gmbus(adapter);
struct drm_i915_private *i915 = bus->i915;
u8 cmd = DRM_HDCP_DDC_AKSV;
- u8 buf[DRM_HDCP_KSV_LEN] = { 0 };
+ u8 buf[DRM_HDCP_KSV_LEN] = {};
struct i2c_msg msgs[] = {
{
.addr = DRM_HDCP_DDC_ADDR,
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c
index a42549fa96..c89da3568e 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -163,7 +163,6 @@ bool intel_hdcp_capable(struct intel_connector *connector)
/* Is HDCP2.2 capable on Platform and Sink */
bool intel_hdcp2_capable(struct intel_connector *connector)
{
- struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
bool capable = false;
@@ -174,14 +173,8 @@ bool intel_hdcp2_capable(struct intel_connector *connector)
/* If MTL+ make sure gsc is loaded and proxy is setup */
if (intel_hdcp_gsc_cs_required(i915)) {
- struct intel_gt *gt = i915->media_gt;
- struct intel_gsc_uc *gsc = gt ? &gt->uc.gsc : NULL;
-
- if (!gsc || !intel_uc_fw_is_running(&gsc->fw)) {
- drm_dbg_kms(&i915->drm,
- "GSC components required for HDCP2.2 are not ready\n");
+ if (!intel_hdcp_gsc_check_status(i915))
return false;
- }
}
/* MEI/GSC interface is solid depending on which is used */
@@ -193,7 +186,7 @@ bool intel_hdcp2_capable(struct intel_connector *connector)
mutex_unlock(&i915->display.hdcp.hdcp_mutex);
/* Sink's capability for HDCP2.2 */
- hdcp->shim->hdcp_2_2_capable(dig_port, &capable);
+ hdcp->shim->hdcp_2_2_capable(connector, &capable);
return capable;
}
@@ -1415,7 +1408,6 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector)
/* Authentication flow starts from here */
static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
{
- struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
union {
@@ -1437,12 +1429,12 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
if (ret < 0)
return ret;
- ret = shim->write_2_2_msg(dig_port, &msgs.ake_init,
+ ret = shim->write_2_2_msg(connector, &msgs.ake_init,
sizeof(msgs.ake_init));
if (ret < 0)
return ret;
- ret = shim->read_2_2_msg(dig_port, HDCP_2_2_AKE_SEND_CERT,
+ ret = shim->read_2_2_msg(connector, HDCP_2_2_AKE_SEND_CERT,
&msgs.send_cert, sizeof(msgs.send_cert));
if (ret < 0)
return ret;
@@ -1471,11 +1463,11 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
if (ret < 0)
return ret;
- ret = shim->write_2_2_msg(dig_port, &msgs.no_stored_km, size);
+ ret = shim->write_2_2_msg(connector, &msgs.no_stored_km, size);
if (ret < 0)
return ret;
- ret = shim->read_2_2_msg(dig_port, HDCP_2_2_AKE_SEND_HPRIME,
+ ret = shim->read_2_2_msg(connector, HDCP_2_2_AKE_SEND_HPRIME,
&msgs.send_hprime, sizeof(msgs.send_hprime));
if (ret < 0)
return ret;
@@ -1486,7 +1478,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
if (!hdcp->is_paired) {
/* Pairing is required */
- ret = shim->read_2_2_msg(dig_port,
+ ret = shim->read_2_2_msg(connector,
HDCP_2_2_AKE_SEND_PAIRING_INFO,
&msgs.pairing_info,
sizeof(msgs.pairing_info));
@@ -1504,7 +1496,6 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
static int hdcp2_locality_check(struct intel_connector *connector)
{
- struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
union {
struct hdcp2_lc_init lc_init;
@@ -1518,12 +1509,12 @@ static int hdcp2_locality_check(struct intel_connector *connector)
if (ret < 0)
continue;
- ret = shim->write_2_2_msg(dig_port, &msgs.lc_init,
+ ret = shim->write_2_2_msg(connector, &msgs.lc_init,
sizeof(msgs.lc_init));
if (ret < 0)
continue;
- ret = shim->read_2_2_msg(dig_port,
+ ret = shim->read_2_2_msg(connector,
HDCP_2_2_LC_SEND_LPRIME,
&msgs.send_lprime,
sizeof(msgs.send_lprime));
@@ -1540,7 +1531,6 @@ static int hdcp2_locality_check(struct intel_connector *connector)
static int hdcp2_session_key_exchange(struct intel_connector *connector)
{
- struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
struct hdcp2_ske_send_eks send_eks;
int ret;
@@ -1549,7 +1539,7 @@ static int hdcp2_session_key_exchange(struct intel_connector *connector)
if (ret < 0)
return ret;
- ret = hdcp->shim->write_2_2_msg(dig_port, &send_eks,
+ ret = hdcp->shim->write_2_2_msg(connector, &send_eks,
sizeof(send_eks));
if (ret < 0)
return ret;
@@ -1587,12 +1577,12 @@ int _hdcp2_propagate_stream_management_info(struct intel_connector *connector)
streams_size_delta = (HDCP_2_2_MAX_CONTENT_STREAMS_CNT - data->k) *
sizeof(struct hdcp2_streamid_type);
/* Send it to Repeater */
- ret = shim->write_2_2_msg(dig_port, &msgs.stream_manage,
+ ret = shim->write_2_2_msg(connector, &msgs.stream_manage,
sizeof(msgs.stream_manage) - streams_size_delta);
if (ret < 0)
goto out;
- ret = shim->read_2_2_msg(dig_port, HDCP_2_2_REP_STREAM_READY,
+ ret = shim->read_2_2_msg(connector, HDCP_2_2_REP_STREAM_READY,
&msgs.stream_ready, sizeof(msgs.stream_ready));
if (ret < 0)
goto out;
@@ -1622,7 +1612,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
u8 *rx_info;
int ret;
- ret = shim->read_2_2_msg(dig_port, HDCP_2_2_REP_SEND_RECVID_LIST,
+ ret = shim->read_2_2_msg(connector, HDCP_2_2_REP_SEND_RECVID_LIST,
&msgs.recvid_list, sizeof(msgs.recvid_list));
if (ret < 0)
return ret;
@@ -1675,7 +1665,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
return ret;
hdcp->seq_num_v = seq_num_v;
- ret = shim->write_2_2_msg(dig_port, &msgs.rep_ack,
+ ret = shim->write_2_2_msg(connector, &msgs.rep_ack,
sizeof(msgs.rep_ack));
if (ret < 0)
return ret;
@@ -1685,7 +1675,6 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
static int hdcp2_authenticate_sink(struct intel_connector *connector)
{
- struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
const struct intel_hdcp_shim *shim = hdcp->shim;
@@ -1711,7 +1700,7 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
}
if (shim->config_stream_type) {
- ret = shim->config_stream_type(dig_port,
+ ret = shim->config_stream_type(connector,
hdcp->is_repeater,
hdcp->content_type);
if (ret < 0)
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
index d753db3eef..18117b789b 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
@@ -11,610 +11,27 @@
#include "i915_drv.h"
#include "i915_utils.h"
#include "intel_hdcp_gsc.h"
+#include "intel_hdcp_gsc_message.h"
bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915)
{
return DISPLAY_VER(i915) >= 14;
}
-static int
-gsc_hdcp_initiate_session(struct device *dev, struct hdcp_port_data *data,
- struct hdcp2_ake_init *ake_data)
+bool intel_hdcp_gsc_check_status(struct drm_i915_private *i915)
{
- struct wired_cmd_initiate_hdcp2_session_in session_init_in = { { 0 } };
- struct wired_cmd_initiate_hdcp2_session_out
- session_init_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
-
- if (!dev || !data || !ake_data)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- session_init_in.header.api_version = HDCP_API_VERSION;
- session_init_in.header.command_id = WIRED_INITIATE_HDCP2_SESSION;
- session_init_in.header.status = FW_HDCP_STATUS_SUCCESS;
- session_init_in.header.buffer_len =
- WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN;
-
- session_init_in.port.integrated_port_type = data->port_type;
- session_init_in.port.physical_port = (u8)data->hdcp_ddi;
- session_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
- session_init_in.protocol = data->protocol;
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&session_init_in,
- sizeof(session_init_in),
- (u8 *)&session_init_out,
- sizeof(session_init_out));
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
- return byte;
- }
-
- if (session_init_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
- WIRED_INITIATE_HDCP2_SESSION,
- session_init_out.header.status);
- return -EIO;
- }
-
- ake_data->msg_id = HDCP_2_2_AKE_INIT;
- ake_data->tx_caps = session_init_out.tx_caps;
- memcpy(ake_data->r_tx, session_init_out.r_tx, HDCP_2_2_RTX_LEN);
-
- return 0;
-}
-
-static int
-gsc_hdcp_verify_receiver_cert_prepare_km(struct device *dev,
- struct hdcp_port_data *data,
- struct hdcp2_ake_send_cert *rx_cert,
- bool *km_stored,
- struct hdcp2_ake_no_stored_km
- *ek_pub_km,
- size_t *msg_sz)
-{
- struct wired_cmd_verify_receiver_cert_in verify_rxcert_in = { { 0 } };
- struct wired_cmd_verify_receiver_cert_out verify_rxcert_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
-
- if (!dev || !data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- verify_rxcert_in.header.api_version = HDCP_API_VERSION;
- verify_rxcert_in.header.command_id = WIRED_VERIFY_RECEIVER_CERT;
- verify_rxcert_in.header.status = FW_HDCP_STATUS_SUCCESS;
- verify_rxcert_in.header.buffer_len =
- WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN;
-
- verify_rxcert_in.port.integrated_port_type = data->port_type;
- verify_rxcert_in.port.physical_port = (u8)data->hdcp_ddi;
- verify_rxcert_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
-
- verify_rxcert_in.cert_rx = rx_cert->cert_rx;
- memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, HDCP_2_2_RRX_LEN);
- memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN);
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_rxcert_in,
- sizeof(verify_rxcert_in),
- (u8 *)&verify_rxcert_out,
- sizeof(verify_rxcert_out));
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed: %zd\n", byte);
- return byte;
- }
-
- if (verify_rxcert_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
- WIRED_VERIFY_RECEIVER_CERT,
- verify_rxcert_out.header.status);
- return -EIO;
- }
-
- *km_stored = !!verify_rxcert_out.km_stored;
- if (verify_rxcert_out.km_stored) {
- ek_pub_km->msg_id = HDCP_2_2_AKE_STORED_KM;
- *msg_sz = sizeof(struct hdcp2_ake_stored_km);
- } else {
- ek_pub_km->msg_id = HDCP_2_2_AKE_NO_STORED_KM;
- *msg_sz = sizeof(struct hdcp2_ake_no_stored_km);
- }
-
- memcpy(ek_pub_km->e_kpub_km, &verify_rxcert_out.ekm_buff,
- sizeof(verify_rxcert_out.ekm_buff));
-
- return 0;
-}
-
-static int
-gsc_hdcp_verify_hprime(struct device *dev, struct hdcp_port_data *data,
- struct hdcp2_ake_send_hprime *rx_hprime)
-{
- struct wired_cmd_ake_send_hprime_in send_hprime_in = { { 0 } };
- struct wired_cmd_ake_send_hprime_out send_hprime_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
-
- if (!dev || !data || !rx_hprime)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- send_hprime_in.header.api_version = HDCP_API_VERSION;
- send_hprime_in.header.command_id = WIRED_AKE_SEND_HPRIME;
- send_hprime_in.header.status = FW_HDCP_STATUS_SUCCESS;
- send_hprime_in.header.buffer_len = WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN;
-
- send_hprime_in.port.integrated_port_type = data->port_type;
- send_hprime_in.port.physical_port = (u8)data->hdcp_ddi;
- send_hprime_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
-
- memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
- HDCP_2_2_H_PRIME_LEN);
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&send_hprime_in,
- sizeof(send_hprime_in),
- (u8 *)&send_hprime_out,
- sizeof(send_hprime_out));
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
- return byte;
- }
-
- if (send_hprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
- WIRED_AKE_SEND_HPRIME, send_hprime_out.header.status);
- return -EIO;
- }
-
- return 0;
-}
-
-static int
-gsc_hdcp_store_pairing_info(struct device *dev, struct hdcp_port_data *data,
- struct hdcp2_ake_send_pairing_info *pairing_info)
-{
- struct wired_cmd_ake_send_pairing_info_in pairing_info_in = { { 0 } };
- struct wired_cmd_ake_send_pairing_info_out pairing_info_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
-
- if (!dev || !data || !pairing_info)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- pairing_info_in.header.api_version = HDCP_API_VERSION;
- pairing_info_in.header.command_id = WIRED_AKE_SEND_PAIRING_INFO;
- pairing_info_in.header.status = FW_HDCP_STATUS_SUCCESS;
- pairing_info_in.header.buffer_len =
- WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN;
-
- pairing_info_in.port.integrated_port_type = data->port_type;
- pairing_info_in.port.physical_port = (u8)data->hdcp_ddi;
- pairing_info_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
-
- memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
- HDCP_2_2_E_KH_KM_LEN);
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&pairing_info_in,
- sizeof(pairing_info_in),
- (u8 *)&pairing_info_out,
- sizeof(pairing_info_out));
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
- return byte;
- }
-
- if (pairing_info_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. Status: 0x%X\n",
- WIRED_AKE_SEND_PAIRING_INFO,
- pairing_info_out.header.status);
- return -EIO;
- }
-
- return 0;
-}
-
-static int
-gsc_hdcp_initiate_locality_check(struct device *dev,
- struct hdcp_port_data *data,
- struct hdcp2_lc_init *lc_init_data)
-{
- struct wired_cmd_init_locality_check_in lc_init_in = { { 0 } };
- struct wired_cmd_init_locality_check_out lc_init_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
-
- if (!dev || !data || !lc_init_data)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- lc_init_in.header.api_version = HDCP_API_VERSION;
- lc_init_in.header.command_id = WIRED_INIT_LOCALITY_CHECK;
- lc_init_in.header.status = FW_HDCP_STATUS_SUCCESS;
- lc_init_in.header.buffer_len = WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_IN;
-
- lc_init_in.port.integrated_port_type = data->port_type;
- lc_init_in.port.physical_port = (u8)data->hdcp_ddi;
- lc_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&lc_init_in, sizeof(lc_init_in),
- (u8 *)&lc_init_out, sizeof(lc_init_out));
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
- return byte;
- }
-
- if (lc_init_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. status: 0x%X\n",
- WIRED_INIT_LOCALITY_CHECK, lc_init_out.header.status);
- return -EIO;
- }
-
- lc_init_data->msg_id = HDCP_2_2_LC_INIT;
- memcpy(lc_init_data->r_n, lc_init_out.r_n, HDCP_2_2_RN_LEN);
-
- return 0;
-}
-
-static int
-gsc_hdcp_verify_lprime(struct device *dev, struct hdcp_port_data *data,
- struct hdcp2_lc_send_lprime *rx_lprime)
-{
- struct wired_cmd_validate_locality_in verify_lprime_in = { { 0 } };
- struct wired_cmd_validate_locality_out verify_lprime_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
-
- if (!dev || !data || !rx_lprime)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- verify_lprime_in.header.api_version = HDCP_API_VERSION;
- verify_lprime_in.header.command_id = WIRED_VALIDATE_LOCALITY;
- verify_lprime_in.header.status = FW_HDCP_STATUS_SUCCESS;
- verify_lprime_in.header.buffer_len =
- WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_IN;
-
- verify_lprime_in.port.integrated_port_type = data->port_type;
- verify_lprime_in.port.physical_port = (u8)data->hdcp_ddi;
- verify_lprime_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
-
- memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,
- HDCP_2_2_L_PRIME_LEN);
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_lprime_in,
- sizeof(verify_lprime_in),
- (u8 *)&verify_lprime_out,
- sizeof(verify_lprime_out));
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
- return byte;
- }
-
- if (verify_lprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
- WIRED_VALIDATE_LOCALITY,
- verify_lprime_out.header.status);
- return -EIO;
- }
-
- return 0;
-}
-
-static int gsc_hdcp_get_session_key(struct device *dev,
- struct hdcp_port_data *data,
- struct hdcp2_ske_send_eks *ske_data)
-{
- struct wired_cmd_get_session_key_in get_skey_in = { { 0 } };
- struct wired_cmd_get_session_key_out get_skey_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
-
- if (!dev || !data || !ske_data)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- get_skey_in.header.api_version = HDCP_API_VERSION;
- get_skey_in.header.command_id = WIRED_GET_SESSION_KEY;
- get_skey_in.header.status = FW_HDCP_STATUS_SUCCESS;
- get_skey_in.header.buffer_len = WIRED_CMD_BUF_LEN_GET_SESSION_KEY_IN;
-
- get_skey_in.port.integrated_port_type = data->port_type;
- get_skey_in.port.physical_port = (u8)data->hdcp_ddi;
- get_skey_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&get_skey_in, sizeof(get_skey_in),
- (u8 *)&get_skey_out, sizeof(get_skey_out));
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
- return byte;
- }
-
- if (get_skey_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
- WIRED_GET_SESSION_KEY, get_skey_out.header.status);
- return -EIO;
- }
-
- ske_data->msg_id = HDCP_2_2_SKE_SEND_EKS;
- memcpy(ske_data->e_dkey_ks, get_skey_out.e_dkey_ks,
- HDCP_2_2_E_DKEY_KS_LEN);
- memcpy(ske_data->riv, get_skey_out.r_iv, HDCP_2_2_RIV_LEN);
-
- return 0;
-}
-
-static int
-gsc_hdcp_repeater_check_flow_prepare_ack(struct device *dev,
- struct hdcp_port_data *data,
- struct hdcp2_rep_send_receiverid_list
- *rep_topology,
- struct hdcp2_rep_send_ack
- *rep_send_ack)
-{
- struct wired_cmd_verify_repeater_in verify_repeater_in = { { 0 } };
- struct wired_cmd_verify_repeater_out verify_repeater_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
-
- if (!dev || !rep_topology || !rep_send_ack || !data)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- verify_repeater_in.header.api_version = HDCP_API_VERSION;
- verify_repeater_in.header.command_id = WIRED_VERIFY_REPEATER;
- verify_repeater_in.header.status = FW_HDCP_STATUS_SUCCESS;
- verify_repeater_in.header.buffer_len =
- WIRED_CMD_BUF_LEN_VERIFY_REPEATER_IN;
-
- verify_repeater_in.port.integrated_port_type = data->port_type;
- verify_repeater_in.port.physical_port = (u8)data->hdcp_ddi;
- verify_repeater_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
-
- memcpy(verify_repeater_in.rx_info, rep_topology->rx_info,
- HDCP_2_2_RXINFO_LEN);
- memcpy(verify_repeater_in.seq_num_v, rep_topology->seq_num_v,
- HDCP_2_2_SEQ_NUM_LEN);
- memcpy(verify_repeater_in.v_prime, rep_topology->v_prime,
- HDCP_2_2_V_PRIME_HALF_LEN);
- memcpy(verify_repeater_in.receiver_ids, rep_topology->receiver_ids,
- HDCP_2_2_RECEIVER_IDS_MAX_LEN);
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_repeater_in,
- sizeof(verify_repeater_in),
- (u8 *)&verify_repeater_out,
- sizeof(verify_repeater_out));
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
- return byte;
- }
-
- if (verify_repeater_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
- WIRED_VERIFY_REPEATER,
- verify_repeater_out.header.status);
- return -EIO;
- }
-
- memcpy(rep_send_ack->v, verify_repeater_out.v,
- HDCP_2_2_V_PRIME_HALF_LEN);
- rep_send_ack->msg_id = HDCP_2_2_REP_SEND_ACK;
-
- return 0;
-}
-
-static int gsc_hdcp_verify_mprime(struct device *dev,
- struct hdcp_port_data *data,
- struct hdcp2_rep_stream_ready *stream_ready)
-{
- struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;
- struct wired_cmd_repeater_auth_stream_req_out
- verify_mprime_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
- size_t cmd_size;
-
- if (!dev || !stream_ready || !data)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- cmd_size = struct_size(verify_mprime_in, streams, data->k);
- if (cmd_size == SIZE_MAX)
- return -EINVAL;
-
- verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL);
- if (!verify_mprime_in)
- return -ENOMEM;
-
- verify_mprime_in->header.api_version = HDCP_API_VERSION;
- verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
- verify_mprime_in->header.status = FW_HDCP_STATUS_SUCCESS;
- verify_mprime_in->header.buffer_len = cmd_size - sizeof(verify_mprime_in->header);
-
- verify_mprime_in->port.integrated_port_type = data->port_type;
- verify_mprime_in->port.physical_port = (u8)data->hdcp_ddi;
- verify_mprime_in->port.attached_transcoder = (u8)data->hdcp_transcoder;
-
- memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, HDCP_2_2_MPRIME_LEN);
- drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m);
-
- memcpy(verify_mprime_in->streams, data->streams,
- array_size(data->k, sizeof(*data->streams)));
-
- verify_mprime_in->k = cpu_to_be16(data->k);
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)verify_mprime_in, cmd_size,
- (u8 *)&verify_mprime_out,
- sizeof(verify_mprime_out));
- kfree(verify_mprime_in);
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
- return byte;
- }
-
- if (verify_mprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
- WIRED_REPEATER_AUTH_STREAM_REQ,
- verify_mprime_out.header.status);
- return -EIO;
- }
-
- return 0;
-}
-
-static int gsc_hdcp_enable_authentication(struct device *dev,
- struct hdcp_port_data *data)
-{
- struct wired_cmd_enable_auth_in enable_auth_in = { { 0 } };
- struct wired_cmd_enable_auth_out enable_auth_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
-
- if (!dev || !data)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- enable_auth_in.header.api_version = HDCP_API_VERSION;
- enable_auth_in.header.command_id = WIRED_ENABLE_AUTH;
- enable_auth_in.header.status = FW_HDCP_STATUS_SUCCESS;
- enable_auth_in.header.buffer_len = WIRED_CMD_BUF_LEN_ENABLE_AUTH_IN;
-
- enable_auth_in.port.integrated_port_type = data->port_type;
- enable_auth_in.port.physical_port = (u8)data->hdcp_ddi;
- enable_auth_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
- enable_auth_in.stream_type = data->streams[0].stream_type;
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&enable_auth_in,
- sizeof(enable_auth_in),
- (u8 *)&enable_auth_out,
- sizeof(enable_auth_out));
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
- return byte;
- }
-
- if (enable_auth_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
- WIRED_ENABLE_AUTH, enable_auth_out.header.status);
- return -EIO;
- }
-
- return 0;
-}
-
-static int
-gsc_hdcp_close_session(struct device *dev, struct hdcp_port_data *data)
-{
- struct wired_cmd_close_session_in session_close_in = { { 0 } };
- struct wired_cmd_close_session_out session_close_out = { { 0 } };
- struct drm_i915_private *i915;
- ssize_t byte;
-
- if (!dev || !data)
- return -EINVAL;
-
- i915 = kdev_to_i915(dev);
- if (!i915) {
- dev_err(dev, "DRM not initialized, aborting HDCP.\n");
- return -ENODEV;
- }
-
- session_close_in.header.api_version = HDCP_API_VERSION;
- session_close_in.header.command_id = WIRED_CLOSE_SESSION;
- session_close_in.header.status = FW_HDCP_STATUS_SUCCESS;
- session_close_in.header.buffer_len =
- WIRED_CMD_BUF_LEN_CLOSE_SESSION_IN;
-
- session_close_in.port.integrated_port_type = data->port_type;
- session_close_in.port.physical_port = (u8)data->hdcp_ddi;
- session_close_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
-
- byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&session_close_in,
- sizeof(session_close_in),
- (u8 *)&session_close_out,
- sizeof(session_close_out));
- if (byte < 0) {
- drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
- return byte;
- }
+ struct intel_gt *gt = i915->media_gt;
+ struct intel_gsc_uc *gsc = gt ? &gt->uc.gsc : NULL;
- if (session_close_out.header.status != FW_HDCP_STATUS_SUCCESS) {
- drm_dbg_kms(&i915->drm, "Session Close Failed. status: 0x%X\n",
- session_close_out.header.status);
- return -EIO;
+ if (!gsc || !intel_uc_fw_is_running(&gsc->fw)) {
+ drm_dbg_kms(&i915->drm,
+ "GSC components required for HDCP2.2 are not ready\n");
+ return false;
}
- return 0;
+ return true;
}
-static const struct i915_hdcp_ops gsc_hdcp_ops = {
- .initiate_hdcp2_session = gsc_hdcp_initiate_session,
- .verify_receiver_cert_prepare_km =
- gsc_hdcp_verify_receiver_cert_prepare_km,
- .verify_hprime = gsc_hdcp_verify_hprime,
- .store_pairing_info = gsc_hdcp_store_pairing_info,
- .initiate_locality_check = gsc_hdcp_initiate_locality_check,
- .verify_lprime = gsc_hdcp_verify_lprime,
- .get_session_key = gsc_hdcp_get_session_key,
- .repeater_check_flow_prepare_ack =
- gsc_hdcp_repeater_check_flow_prepare_ack,
- .verify_mprime = gsc_hdcp_verify_mprime,
- .enable_hdcp_authentication = gsc_hdcp_enable_authentication,
- .close_hdcp_session = gsc_hdcp_close_session,
-};
-
/*This function helps allocate memory for the command that we will send to gsc cs */
static int intel_hdcp_gsc_initialize_message(struct drm_i915_private *i915,
struct intel_hdcp_gsc_message *hdcp_message)
@@ -667,6 +84,22 @@ out_unpin:
return err;
}
+static const struct i915_hdcp_ops gsc_hdcp_ops = {
+ .initiate_hdcp2_session = intel_hdcp_gsc_initiate_session,
+ .verify_receiver_cert_prepare_km =
+ intel_hdcp_gsc_verify_receiver_cert_prepare_km,
+ .verify_hprime = intel_hdcp_gsc_verify_hprime,
+ .store_pairing_info = intel_hdcp_gsc_store_pairing_info,
+ .initiate_locality_check = intel_hdcp_gsc_initiate_locality_check,
+ .verify_lprime = intel_hdcp_gsc_verify_lprime,
+ .get_session_key = intel_hdcp_gsc_get_session_key,
+ .repeater_check_flow_prepare_ack =
+ intel_hdcp_gsc_repeater_check_flow_prepare_ack,
+ .verify_mprime = intel_hdcp_gsc_verify_mprime,
+ .enable_hdcp_authentication = intel_hdcp_gsc_enable_authentication,
+ .close_hdcp_session = intel_hdcp_gsc_close_session,
+};
+
static int intel_hdcp_gsc_hdcp2_init(struct drm_i915_private *i915)
{
struct intel_hdcp_gsc_message *hdcp_message;
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h
index cbf96551e5..eba2057c5a 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h
+++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h
@@ -23,5 +23,6 @@ ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
size_t msg_out_len);
int intel_hdcp_gsc_init(struct drm_i915_private *i915);
void intel_hdcp_gsc_fini(struct drm_i915_private *i915);
+bool intel_hdcp_gsc_check_status(struct drm_i915_private *i915);
#endif /* __INTEL_HDCP_GCS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c
new file mode 100644
index 0000000000..240b00849f
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.c
@@ -0,0 +1,590 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2023, Intel Corporation.
+ */
+
+#include <linux/err.h>
+#include <drm/i915_hdcp_interface.h>
+
+#include "i915_drv.h"
+#include "intel_hdcp_gsc_message.h"
+
+int
+intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_ake_init *ake_data)
+{
+ struct wired_cmd_initiate_hdcp2_session_in session_init_in = {};
+ struct wired_cmd_initiate_hdcp2_session_out session_init_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+
+ if (!dev || !data || !ake_data)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ session_init_in.header.api_version = HDCP_API_VERSION;
+ session_init_in.header.command_id = WIRED_INITIATE_HDCP2_SESSION;
+ session_init_in.header.status = FW_HDCP_STATUS_SUCCESS;
+ session_init_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_INITIATE_HDCP2_SESSION_IN;
+
+ session_init_in.port.integrated_port_type = data->port_type;
+ session_init_in.port.physical_port = (u8)data->hdcp_ddi;
+ session_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
+ session_init_in.protocol = data->protocol;
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&session_init_in,
+ sizeof(session_init_in),
+ (u8 *)&session_init_out,
+ sizeof(session_init_out));
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (session_init_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
+ WIRED_INITIATE_HDCP2_SESSION,
+ session_init_out.header.status);
+ return -EIO;
+ }
+
+ ake_data->msg_id = HDCP_2_2_AKE_INIT;
+ ake_data->tx_caps = session_init_out.tx_caps;
+ memcpy(ake_data->r_tx, session_init_out.r_tx, HDCP_2_2_RTX_LEN);
+
+ return 0;
+}
+
+int
+intel_hdcp_gsc_verify_receiver_cert_prepare_km(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_ake_send_cert *rx_cert,
+ bool *km_stored,
+ struct hdcp2_ake_no_stored_km
+ *ek_pub_km,
+ size_t *msg_sz)
+{
+ struct wired_cmd_verify_receiver_cert_in verify_rxcert_in = {};
+ struct wired_cmd_verify_receiver_cert_out verify_rxcert_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+
+ if (!dev || !data || !rx_cert || !km_stored || !ek_pub_km || !msg_sz)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ verify_rxcert_in.header.api_version = HDCP_API_VERSION;
+ verify_rxcert_in.header.command_id = WIRED_VERIFY_RECEIVER_CERT;
+ verify_rxcert_in.header.status = FW_HDCP_STATUS_SUCCESS;
+ verify_rxcert_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_VERIFY_RECEIVER_CERT_IN;
+
+ verify_rxcert_in.port.integrated_port_type = data->port_type;
+ verify_rxcert_in.port.physical_port = (u8)data->hdcp_ddi;
+ verify_rxcert_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
+
+ verify_rxcert_in.cert_rx = rx_cert->cert_rx;
+ memcpy(verify_rxcert_in.r_rx, &rx_cert->r_rx, HDCP_2_2_RRX_LEN);
+ memcpy(verify_rxcert_in.rx_caps, rx_cert->rx_caps, HDCP_2_2_RXCAPS_LEN);
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_rxcert_in,
+ sizeof(verify_rxcert_in),
+ (u8 *)&verify_rxcert_out,
+ sizeof(verify_rxcert_out));
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed: %zd\n", byte);
+ return byte;
+ }
+
+ if (verify_rxcert_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
+ WIRED_VERIFY_RECEIVER_CERT,
+ verify_rxcert_out.header.status);
+ return -EIO;
+ }
+
+ *km_stored = !!verify_rxcert_out.km_stored;
+ if (verify_rxcert_out.km_stored) {
+ ek_pub_km->msg_id = HDCP_2_2_AKE_STORED_KM;
+ *msg_sz = sizeof(struct hdcp2_ake_stored_km);
+ } else {
+ ek_pub_km->msg_id = HDCP_2_2_AKE_NO_STORED_KM;
+ *msg_sz = sizeof(struct hdcp2_ake_no_stored_km);
+ }
+
+ memcpy(ek_pub_km->e_kpub_km, &verify_rxcert_out.ekm_buff,
+ sizeof(verify_rxcert_out.ekm_buff));
+
+ return 0;
+}
+
+int
+intel_hdcp_gsc_verify_hprime(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_ake_send_hprime *rx_hprime)
+{
+ struct wired_cmd_ake_send_hprime_in send_hprime_in = {};
+ struct wired_cmd_ake_send_hprime_out send_hprime_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+
+ if (!dev || !data || !rx_hprime)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ send_hprime_in.header.api_version = HDCP_API_VERSION;
+ send_hprime_in.header.command_id = WIRED_AKE_SEND_HPRIME;
+ send_hprime_in.header.status = FW_HDCP_STATUS_SUCCESS;
+ send_hprime_in.header.buffer_len = WIRED_CMD_BUF_LEN_AKE_SEND_HPRIME_IN;
+
+ send_hprime_in.port.integrated_port_type = data->port_type;
+ send_hprime_in.port.physical_port = (u8)data->hdcp_ddi;
+ send_hprime_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
+
+ memcpy(send_hprime_in.h_prime, rx_hprime->h_prime,
+ HDCP_2_2_H_PRIME_LEN);
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&send_hprime_in,
+ sizeof(send_hprime_in),
+ (u8 *)&send_hprime_out,
+ sizeof(send_hprime_out));
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (send_hprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
+ WIRED_AKE_SEND_HPRIME, send_hprime_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int
+intel_hdcp_gsc_store_pairing_info(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info)
+{
+ struct wired_cmd_ake_send_pairing_info_in pairing_info_in = {};
+ struct wired_cmd_ake_send_pairing_info_out pairing_info_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+
+ if (!dev || !data || !pairing_info)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ pairing_info_in.header.api_version = HDCP_API_VERSION;
+ pairing_info_in.header.command_id = WIRED_AKE_SEND_PAIRING_INFO;
+ pairing_info_in.header.status = FW_HDCP_STATUS_SUCCESS;
+ pairing_info_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_SEND_PAIRING_INFO_IN;
+
+ pairing_info_in.port.integrated_port_type = data->port_type;
+ pairing_info_in.port.physical_port = (u8)data->hdcp_ddi;
+ pairing_info_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
+
+ memcpy(pairing_info_in.e_kh_km, pairing_info->e_kh_km,
+ HDCP_2_2_E_KH_KM_LEN);
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&pairing_info_in,
+ sizeof(pairing_info_in),
+ (u8 *)&pairing_info_out,
+ sizeof(pairing_info_out));
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (pairing_info_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. Status: 0x%X\n",
+ WIRED_AKE_SEND_PAIRING_INFO,
+ pairing_info_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int
+intel_hdcp_gsc_initiate_locality_check(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_lc_init *lc_init_data)
+{
+ struct wired_cmd_init_locality_check_in lc_init_in = {};
+ struct wired_cmd_init_locality_check_out lc_init_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+
+ if (!dev || !data || !lc_init_data)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ lc_init_in.header.api_version = HDCP_API_VERSION;
+ lc_init_in.header.command_id = WIRED_INIT_LOCALITY_CHECK;
+ lc_init_in.header.status = FW_HDCP_STATUS_SUCCESS;
+ lc_init_in.header.buffer_len = WIRED_CMD_BUF_LEN_INIT_LOCALITY_CHECK_IN;
+
+ lc_init_in.port.integrated_port_type = data->port_type;
+ lc_init_in.port.physical_port = (u8)data->hdcp_ddi;
+ lc_init_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&lc_init_in, sizeof(lc_init_in),
+ (u8 *)&lc_init_out, sizeof(lc_init_out));
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (lc_init_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. status: 0x%X\n",
+ WIRED_INIT_LOCALITY_CHECK, lc_init_out.header.status);
+ return -EIO;
+ }
+
+ lc_init_data->msg_id = HDCP_2_2_LC_INIT;
+ memcpy(lc_init_data->r_n, lc_init_out.r_n, HDCP_2_2_RN_LEN);
+
+ return 0;
+}
+
+int
+intel_hdcp_gsc_verify_lprime(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_lc_send_lprime *rx_lprime)
+{
+ struct wired_cmd_validate_locality_in verify_lprime_in = {};
+ struct wired_cmd_validate_locality_out verify_lprime_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+
+ if (!dev || !data || !rx_lprime)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ verify_lprime_in.header.api_version = HDCP_API_VERSION;
+ verify_lprime_in.header.command_id = WIRED_VALIDATE_LOCALITY;
+ verify_lprime_in.header.status = FW_HDCP_STATUS_SUCCESS;
+ verify_lprime_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_VALIDATE_LOCALITY_IN;
+
+ verify_lprime_in.port.integrated_port_type = data->port_type;
+ verify_lprime_in.port.physical_port = (u8)data->hdcp_ddi;
+ verify_lprime_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
+
+ memcpy(verify_lprime_in.l_prime, rx_lprime->l_prime,
+ HDCP_2_2_L_PRIME_LEN);
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_lprime_in,
+ sizeof(verify_lprime_in),
+ (u8 *)&verify_lprime_out,
+ sizeof(verify_lprime_out));
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (verify_lprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
+ WIRED_VALIDATE_LOCALITY,
+ verify_lprime_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int intel_hdcp_gsc_get_session_key(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_ske_send_eks *ske_data)
+{
+ struct wired_cmd_get_session_key_in get_skey_in = {};
+ struct wired_cmd_get_session_key_out get_skey_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+
+ if (!dev || !data || !ske_data)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ get_skey_in.header.api_version = HDCP_API_VERSION;
+ get_skey_in.header.command_id = WIRED_GET_SESSION_KEY;
+ get_skey_in.header.status = FW_HDCP_STATUS_SUCCESS;
+ get_skey_in.header.buffer_len = WIRED_CMD_BUF_LEN_GET_SESSION_KEY_IN;
+
+ get_skey_in.port.integrated_port_type = data->port_type;
+ get_skey_in.port.physical_port = (u8)data->hdcp_ddi;
+ get_skey_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&get_skey_in, sizeof(get_skey_in),
+ (u8 *)&get_skey_out, sizeof(get_skey_out));
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (get_skey_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
+ WIRED_GET_SESSION_KEY, get_skey_out.header.status);
+ return -EIO;
+ }
+
+ ske_data->msg_id = HDCP_2_2_SKE_SEND_EKS;
+ memcpy(ske_data->e_dkey_ks, get_skey_out.e_dkey_ks,
+ HDCP_2_2_E_DKEY_KS_LEN);
+ memcpy(ske_data->riv, get_skey_out.r_iv, HDCP_2_2_RIV_LEN);
+
+ return 0;
+}
+
+int
+intel_hdcp_gsc_repeater_check_flow_prepare_ack(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_rep_send_receiverid_list
+ *rep_topology,
+ struct hdcp2_rep_send_ack
+ *rep_send_ack)
+{
+ struct wired_cmd_verify_repeater_in verify_repeater_in = {};
+ struct wired_cmd_verify_repeater_out verify_repeater_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+
+ if (!dev || !rep_topology || !rep_send_ack || !data)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ verify_repeater_in.header.api_version = HDCP_API_VERSION;
+ verify_repeater_in.header.command_id = WIRED_VERIFY_REPEATER;
+ verify_repeater_in.header.status = FW_HDCP_STATUS_SUCCESS;
+ verify_repeater_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_VERIFY_REPEATER_IN;
+
+ verify_repeater_in.port.integrated_port_type = data->port_type;
+ verify_repeater_in.port.physical_port = (u8)data->hdcp_ddi;
+ verify_repeater_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
+
+ memcpy(verify_repeater_in.rx_info, rep_topology->rx_info,
+ HDCP_2_2_RXINFO_LEN);
+ memcpy(verify_repeater_in.seq_num_v, rep_topology->seq_num_v,
+ HDCP_2_2_SEQ_NUM_LEN);
+ memcpy(verify_repeater_in.v_prime, rep_topology->v_prime,
+ HDCP_2_2_V_PRIME_HALF_LEN);
+ memcpy(verify_repeater_in.receiver_ids, rep_topology->receiver_ids,
+ HDCP_2_2_RECEIVER_IDS_MAX_LEN);
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&verify_repeater_in,
+ sizeof(verify_repeater_in),
+ (u8 *)&verify_repeater_out,
+ sizeof(verify_repeater_out));
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (verify_repeater_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
+ WIRED_VERIFY_REPEATER,
+ verify_repeater_out.header.status);
+ return -EIO;
+ }
+
+ memcpy(rep_send_ack->v, verify_repeater_out.v,
+ HDCP_2_2_V_PRIME_HALF_LEN);
+ rep_send_ack->msg_id = HDCP_2_2_REP_SEND_ACK;
+
+ return 0;
+}
+
+int intel_hdcp_gsc_verify_mprime(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_rep_stream_ready *stream_ready)
+{
+ struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in;
+ struct wired_cmd_repeater_auth_stream_req_out verify_mprime_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+ size_t cmd_size;
+
+ if (!dev || !stream_ready || !data)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ cmd_size = struct_size(verify_mprime_in, streams, data->k);
+ if (cmd_size == SIZE_MAX)
+ return -EINVAL;
+
+ verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL);
+ if (!verify_mprime_in)
+ return -ENOMEM;
+
+ verify_mprime_in->header.api_version = HDCP_API_VERSION;
+ verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ;
+ verify_mprime_in->header.status = FW_HDCP_STATUS_SUCCESS;
+ verify_mprime_in->header.buffer_len = cmd_size - sizeof(verify_mprime_in->header);
+
+ verify_mprime_in->port.integrated_port_type = data->port_type;
+ verify_mprime_in->port.physical_port = (u8)data->hdcp_ddi;
+ verify_mprime_in->port.attached_transcoder = (u8)data->hdcp_transcoder;
+
+ memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, HDCP_2_2_MPRIME_LEN);
+ drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m);
+
+ memcpy(verify_mprime_in->streams, data->streams,
+ array_size(data->k, sizeof(*data->streams)));
+
+ verify_mprime_in->k = cpu_to_be16(data->k);
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)verify_mprime_in, cmd_size,
+ (u8 *)&verify_mprime_out,
+ sizeof(verify_mprime_out));
+ kfree(verify_mprime_in);
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (verify_mprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
+ WIRED_REPEATER_AUTH_STREAM_REQ,
+ verify_mprime_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int intel_hdcp_gsc_enable_authentication(struct device *dev,
+ struct hdcp_port_data *data)
+{
+ struct wired_cmd_enable_auth_in enable_auth_in = {};
+ struct wired_cmd_enable_auth_out enable_auth_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+
+ if (!dev || !data)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ enable_auth_in.header.api_version = HDCP_API_VERSION;
+ enable_auth_in.header.command_id = WIRED_ENABLE_AUTH;
+ enable_auth_in.header.status = FW_HDCP_STATUS_SUCCESS;
+ enable_auth_in.header.buffer_len = WIRED_CMD_BUF_LEN_ENABLE_AUTH_IN;
+
+ enable_auth_in.port.integrated_port_type = data->port_type;
+ enable_auth_in.port.physical_port = (u8)data->hdcp_ddi;
+ enable_auth_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
+ enable_auth_in.stream_type = data->streams[0].stream_type;
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&enable_auth_in,
+ sizeof(enable_auth_in),
+ (u8 *)&enable_auth_out,
+ sizeof(enable_auth_out));
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (enable_auth_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
+ WIRED_ENABLE_AUTH, enable_auth_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int
+intel_hdcp_gsc_close_session(struct device *dev, struct hdcp_port_data *data)
+{
+ struct wired_cmd_close_session_in session_close_in = {};
+ struct wired_cmd_close_session_out session_close_out = {};
+ struct drm_i915_private *i915;
+ ssize_t byte;
+
+ if (!dev || !data)
+ return -EINVAL;
+
+ i915 = kdev_to_i915(dev);
+ if (!i915) {
+ dev_err(dev, "DRM not initialized, aborting HDCP.\n");
+ return -ENODEV;
+ }
+
+ session_close_in.header.api_version = HDCP_API_VERSION;
+ session_close_in.header.command_id = WIRED_CLOSE_SESSION;
+ session_close_in.header.status = FW_HDCP_STATUS_SUCCESS;
+ session_close_in.header.buffer_len =
+ WIRED_CMD_BUF_LEN_CLOSE_SESSION_IN;
+
+ session_close_in.port.integrated_port_type = data->port_type;
+ session_close_in.port.physical_port = (u8)data->hdcp_ddi;
+ session_close_in.port.attached_transcoder = (u8)data->hdcp_transcoder;
+
+ byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&session_close_in,
+ sizeof(session_close_in),
+ (u8 *)&session_close_out,
+ sizeof(session_close_out));
+ if (byte < 0) {
+ drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
+ return byte;
+ }
+
+ if (session_close_out.header.status != FW_HDCP_STATUS_SUCCESS) {
+ drm_dbg_kms(&i915->drm, "Session Close Failed. status: 0x%X\n",
+ session_close_out.header.status);
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.h b/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.h
new file mode 100644
index 0000000000..ce199d6f62
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc_message.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_HDCP_GSC_MESSAGE_H__
+#define __INTEL_HDCP_GSC_MESSAGE_H__
+
+#include <linux/types.h>
+
+struct device;
+struct drm_i915_private;
+struct hdcp_port_data;
+struct hdcp2_ake_init;
+struct hdcp2_ake_send_cert;
+struct hdcp2_ake_no_stored_km;
+struct hdcp2_ake_send_hprime;
+struct hdcp2_ake_send_pairing_info;
+struct hdcp2_lc_init;
+struct hdcp2_lc_send_lprime;
+struct hdcp2_ske_send_eks;
+struct hdcp2_rep_send_receiverid_list;
+struct hdcp2_rep_send_ack;
+struct hdcp2_rep_stream_ready;
+
+ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
+ size_t msg_in_len, u8 *msg_out,
+ size_t msg_out_len);
+bool intel_hdcp_gsc_check_status(struct drm_i915_private *i915);
+int
+intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_ake_init *ake_data);
+int
+intel_hdcp_gsc_verify_receiver_cert_prepare_km(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_ake_send_cert *rx_cert,
+ bool *km_stored,
+ struct hdcp2_ake_no_stored_km
+ *ek_pub_km,
+ size_t *msg_sz);
+int
+intel_hdcp_gsc_verify_hprime(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_ake_send_hprime *rx_hprime);
+int
+intel_hdcp_gsc_store_pairing_info(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_ake_send_pairing_info *pairing_info);
+int
+intel_hdcp_gsc_initiate_locality_check(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_lc_init *lc_init_data);
+int
+intel_hdcp_gsc_verify_lprime(struct device *dev, struct hdcp_port_data *data,
+ struct hdcp2_lc_send_lprime *rx_lprime);
+int intel_hdcp_gsc_get_session_key(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_ske_send_eks *ske_data);
+int
+intel_hdcp_gsc_repeater_check_flow_prepare_ack(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_rep_send_receiverid_list
+ *rep_topology,
+ struct hdcp2_rep_send_ack
+ *rep_send_ack);
+int intel_hdcp_gsc_verify_mprime(struct device *dev,
+ struct hdcp_port_data *data,
+ struct hdcp2_rep_stream_ready *stream_ready);
+int intel_hdcp_gsc_enable_authentication(struct device *dev,
+ struct hdcp_port_data *data);
+int
+intel_hdcp_gsc_close_session(struct device *dev, struct hdcp_port_data *data);
+
+#endif /* __INTEL_HDCP_GSC_MESSAGE_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index bc975918e0..bfa456fa7d 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -1240,26 +1240,23 @@ static void hsw_set_infoframes(struct intel_encoder *encoder,
void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable)
{
struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi);
- struct i2c_adapter *adapter;
+ struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI)
return;
- adapter = intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
-
drm_dbg_kms(&dev_priv->drm, "%s DP dual mode adaptor TMDS output\n",
enable ? "Enabling" : "Disabling");
- drm_dp_dual_mode_set_tmds_output(&dev_priv->drm, hdmi->dp_dual_mode.type, adapter, enable);
+ drm_dp_dual_mode_set_tmds_output(&dev_priv->drm,
+ hdmi->dp_dual_mode.type, ddc, enable);
}
static int intel_hdmi_hdcp_read(struct intel_digital_port *dig_port,
unsigned int offset, void *buffer, size_t size)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_hdmi *hdmi = &dig_port->hdmi;
- struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915,
- hdmi->ddc_bus);
+ struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
int ret;
u8 start = offset & 0xff;
struct i2c_msg msgs[] = {
@@ -1276,7 +1273,7 @@ static int intel_hdmi_hdcp_read(struct intel_digital_port *dig_port,
.buf = buffer
}
};
- ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs));
+ ret = i2c_transfer(ddc, msgs, ARRAY_SIZE(msgs));
if (ret == ARRAY_SIZE(msgs))
return 0;
return ret >= 0 ? -EIO : ret;
@@ -1285,10 +1282,8 @@ static int intel_hdmi_hdcp_read(struct intel_digital_port *dig_port,
static int intel_hdmi_hdcp_write(struct intel_digital_port *dig_port,
unsigned int offset, void *buffer, size_t size)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_hdmi *hdmi = &dig_port->hdmi;
- struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915,
- hdmi->ddc_bus);
+ struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
int ret;
u8 *write_buf;
struct i2c_msg msg;
@@ -1305,7 +1300,7 @@ static int intel_hdmi_hdcp_write(struct intel_digital_port *dig_port,
msg.len = size + 1,
msg.buf = write_buf;
- ret = i2c_transfer(adapter, &msg, 1);
+ ret = i2c_transfer(ddc, &msg, 1);
if (ret == 1)
ret = 0;
else if (ret >= 0)
@@ -1321,8 +1316,7 @@ int intel_hdmi_hdcp_write_an_aksv(struct intel_digital_port *dig_port,
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_hdmi *hdmi = &dig_port->hdmi;
- struct i2c_adapter *adapter = intel_gmbus_get_adapter(i915,
- hdmi->ddc_bus);
+ struct i2c_adapter *ddc = hdmi->attached_connector->base.ddc;
int ret;
ret = intel_hdmi_hdcp_write(dig_port, DRM_HDCP_DDC_AN, an,
@@ -1333,7 +1327,7 @@ int intel_hdmi_hdcp_write_an_aksv(struct intel_digital_port *dig_port,
return ret;
}
- ret = intel_gmbus_output_aksv(adapter);
+ ret = intel_gmbus_output_aksv(ddc);
if (ret < 0) {
drm_dbg_kms(&i915->drm, "Failed to output aksv (%d)\n", ret);
return ret;
@@ -1665,9 +1659,10 @@ intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *dig_port,
}
static
-int intel_hdmi_hdcp2_write_msg(struct intel_digital_port *dig_port,
+int intel_hdmi_hdcp2_write_msg(struct intel_connector *connector,
void *buf, size_t size)
{
+ struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
unsigned int offset;
offset = HDCP_2_2_HDMI_REG_WR_MSG_OFFSET;
@@ -1675,9 +1670,10 @@ int intel_hdmi_hdcp2_write_msg(struct intel_digital_port *dig_port,
}
static
-int intel_hdmi_hdcp2_read_msg(struct intel_digital_port *dig_port,
+int intel_hdmi_hdcp2_read_msg(struct intel_connector *connector,
u8 msg_id, void *buf, size_t size)
{
+ struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_hdmi *hdmi = &dig_port->hdmi;
struct intel_hdcp *hdcp = &hdmi->attached_connector->hdcp;
@@ -1733,9 +1729,10 @@ int intel_hdmi_hdcp2_check_link(struct intel_digital_port *dig_port,
}
static
-int intel_hdmi_hdcp2_capable(struct intel_digital_port *dig_port,
+int intel_hdmi_hdcp2_capable(struct intel_connector *connector,
bool *capable)
{
+ struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
u8 hdcp2_version;
int ret;
@@ -2404,9 +2401,10 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector));
struct intel_encoder *encoder = &hdmi_to_dig_port(hdmi)->base;
- struct i2c_adapter *adapter =
- intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
- enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(&dev_priv->drm, adapter);
+ struct i2c_adapter *ddc = connector->ddc;
+ enum drm_dp_dual_mode_type type;
+
+ type = drm_dp_dual_mode_detect(&dev_priv->drm, ddc);
/*
* Type 1 DVI adaptors are not required to implement any
@@ -2433,7 +2431,7 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector)
hdmi->dp_dual_mode.type = type;
hdmi->dp_dual_mode.max_tmds_clock =
- drm_dp_dual_mode_max_tmds_clock(&dev_priv->drm, type, adapter);
+ drm_dp_dual_mode_max_tmds_clock(&dev_priv->drm, type, ddc);
drm_dbg_kms(&dev_priv->drm,
"DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n",
@@ -2454,24 +2452,21 @@ intel_hdmi_set_edid(struct drm_connector *connector)
{
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
+ struct i2c_adapter *ddc = connector->ddc;
intel_wakeref_t wakeref;
const struct drm_edid *drm_edid;
- const struct edid *edid;
bool connected = false;
- struct i2c_adapter *i2c;
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
- i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
+ drm_edid = drm_edid_read_ddc(connector, ddc);
- drm_edid = drm_edid_read_ddc(connector, i2c);
-
- if (!drm_edid && !intel_gmbus_is_forced_bit(i2c)) {
+ if (!drm_edid && !intel_gmbus_is_forced_bit(ddc)) {
drm_dbg_kms(&dev_priv->drm,
"HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n");
- intel_gmbus_force_bit(i2c, true);
- drm_edid = drm_edid_read_ddc(connector, i2c);
- intel_gmbus_force_bit(i2c, false);
+ intel_gmbus_force_bit(ddc, true);
+ drm_edid = drm_edid_read_ddc(connector, ddc);
+ intel_gmbus_force_bit(ddc, false);
}
/* Below we depend on display info having been updated */
@@ -2479,9 +2474,7 @@ intel_hdmi_set_edid(struct drm_connector *connector)
to_intel_connector(connector)->detect_edid = drm_edid;
- /* FIXME: Get rid of drm_edid_raw() */
- edid = drm_edid_raw(drm_edid);
- if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
+ if (drm_edid_is_digital(drm_edid)) {
intel_hdmi_dp_dual_mode_detect(connector);
connected = true;
@@ -2489,7 +2482,8 @@ intel_hdmi_set_edid(struct drm_connector *connector)
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
- cec_notifier_set_phys_addr_from_edid(intel_hdmi->cec_notifier, edid);
+ cec_notifier_set_phys_addr(intel_hdmi->cec_notifier,
+ connector->display_info.source_physical_address);
return connected;
}
@@ -2506,7 +2500,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
- if (!INTEL_DISPLAY_ENABLED(dev_priv))
+ if (!intel_display_device_enabled(dev_priv))
return connector_status_disconnected;
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
@@ -2526,12 +2520,6 @@ out:
if (status != connector_status_connected)
cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);
- /*
- * Make sure the refs for power wells enabled during detect are
- * dropped to avoid a new detect cycle triggered by HPD polling.
- */
- intel_display_power_flush_work(dev_priv);
-
return status;
}
@@ -2557,37 +2545,6 @@ static int intel_hdmi_get_modes(struct drm_connector *connector)
return drm_edid_connector_add_modes(connector);
}
-static struct i2c_adapter *
-intel_hdmi_get_i2c_adapter(struct drm_connector *connector)
-{
- struct drm_i915_private *dev_priv = to_i915(connector->dev);
- struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
-
- return intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
-}
-
-static void intel_hdmi_create_i2c_symlink(struct drm_connector *connector)
-{
- struct drm_i915_private *i915 = to_i915(connector->dev);
- struct i2c_adapter *adapter = intel_hdmi_get_i2c_adapter(connector);
- struct kobject *i2c_kobj = &adapter->dev.kobj;
- struct kobject *connector_kobj = &connector->kdev->kobj;
- int ret;
-
- ret = sysfs_create_link(connector_kobj, i2c_kobj, i2c_kobj->name);
- if (ret)
- drm_err(&i915->drm, "Failed to create i2c symlink (%d)\n", ret);
-}
-
-static void intel_hdmi_remove_i2c_symlink(struct drm_connector *connector)
-{
- struct i2c_adapter *adapter = intel_hdmi_get_i2c_adapter(connector);
- struct kobject *i2c_kobj = &adapter->dev.kobj;
- struct kobject *connector_kobj = &connector->kdev->kobj;
-
- sysfs_remove_link(connector_kobj, i2c_kobj->name);
-}
-
static int
intel_hdmi_connector_register(struct drm_connector *connector)
{
@@ -2597,8 +2554,6 @@ intel_hdmi_connector_register(struct drm_connector *connector)
if (ret)
return ret;
- intel_hdmi_create_i2c_symlink(connector);
-
return ret;
}
@@ -2608,7 +2563,6 @@ static void intel_hdmi_connector_unregister(struct drm_connector *connector)
cec_notifier_conn_unregister(n);
- intel_hdmi_remove_i2c_symlink(connector);
intel_connector_unregister(connector);
}
@@ -2922,13 +2876,17 @@ get_encoder_by_ddc_pin(struct intel_encoder *encoder, u8 ddc_pin)
struct intel_encoder *other;
for_each_intel_encoder(&i915->drm, other) {
+ struct intel_connector *connector;
+
if (other == encoder)
continue;
if (!intel_encoder_is_dig_port(other))
continue;
- if (enc_to_dig_port(other)->hdmi.ddc_bus == ddc_pin)
+ connector = enc_to_dig_port(other)->hdmi.attached_connector;
+
+ if (connector && connector->base.ddc == intel_gmbus_get_adapter(i915, ddc_pin))
return other;
}
@@ -3020,9 +2978,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
struct intel_encoder *intel_encoder = &dig_port->base;
struct drm_device *dev = intel_encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct i2c_adapter *ddc;
enum port port = intel_encoder->port;
struct cec_connector_info conn_info;
+ u8 ddc_pin;
drm_dbg_kms(&dev_priv->drm,
"Adding HDMI connector on [ENCODER:%d:%s]\n",
@@ -3037,16 +2995,15 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
intel_encoder->base.name))
return;
- intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(intel_encoder);
- if (!intel_hdmi->ddc_bus)
+ ddc_pin = intel_hdmi_ddc_pin(intel_encoder);
+ if (!ddc_pin)
return;
- ddc = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
-
drm_connector_init_with_ddc(dev, connector,
&intel_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA,
- ddc);
+ intel_gmbus_get_adapter(dev_priv, ddc_pin));
+
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
if (DISPLAY_VER(dev_priv) < 12)
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c
index 69a83dcc19..0c0700c6ec 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
@@ -25,6 +25,7 @@
#include "i915_drv.h"
#include "i915_irq.h"
+#include "intel_display_power.h"
#include "intel_display_types.h"
#include "intel_hotplug.h"
#include "intel_hotplug_irq.h"
@@ -259,21 +260,22 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
}
-enum intel_hotplug_state
-intel_encoder_hotplug(struct intel_encoder *encoder,
- struct intel_connector *connector)
+static enum intel_hotplug_state
+intel_hotplug_detect_connector(struct intel_connector *connector)
{
struct drm_device *dev = connector->base.dev;
enum drm_connector_status old_status;
u64 old_epoch_counter;
+ int status;
bool ret = false;
drm_WARN_ON(dev, !mutex_is_locked(&dev->mode_config.mutex));
old_status = connector->base.status;
old_epoch_counter = connector->base.epoch_counter;
- connector->base.status =
- drm_helper_probe_detect(&connector->base, NULL, false);
+ status = drm_helper_probe_detect(&connector->base, NULL, false);
+ if (!connector->base.force)
+ connector->base.status = status;
if (old_epoch_counter != connector->base.epoch_counter)
ret = true;
@@ -291,6 +293,13 @@ intel_encoder_hotplug(struct intel_encoder *encoder,
return INTEL_HOTPLUG_UNCHANGED;
}
+enum intel_hotplug_state
+intel_encoder_hotplug(struct intel_encoder *encoder,
+ struct intel_connector *connector)
+{
+ return intel_hotplug_detect_connector(connector);
+}
+
static bool intel_encoder_has_hpd_pulse(struct intel_encoder *encoder)
{
return intel_encoder_is_dig_port(encoder) &&
@@ -631,6 +640,49 @@ void intel_hpd_init(struct drm_i915_private *dev_priv)
spin_unlock_irq(&dev_priv->irq_lock);
}
+static void i915_hpd_poll_detect_connectors(struct drm_i915_private *i915)
+{
+ struct drm_connector_list_iter conn_iter;
+ struct intel_connector *connector;
+ struct intel_connector *first_changed_connector = NULL;
+ int changed = 0;
+
+ mutex_lock(&i915->drm.mode_config.mutex);
+
+ if (!i915->drm.mode_config.poll_enabled)
+ goto out;
+
+ drm_connector_list_iter_begin(&i915->drm, &conn_iter);
+ for_each_intel_connector_iter(connector, &conn_iter) {
+ if (!(connector->base.polled & DRM_CONNECTOR_POLL_HPD))
+ continue;
+
+ if (intel_hotplug_detect_connector(connector) != INTEL_HOTPLUG_CHANGED)
+ continue;
+
+ changed++;
+
+ if (changed == 1) {
+ drm_connector_get(&connector->base);
+ first_changed_connector = connector;
+ }
+ }
+ drm_connector_list_iter_end(&conn_iter);
+
+out:
+ mutex_unlock(&i915->drm.mode_config.mutex);
+
+ if (!changed)
+ return;
+
+ if (changed == 1)
+ drm_kms_helper_connector_hotplug_event(&first_changed_connector->base);
+ else
+ drm_kms_helper_hotplug_event(&i915->drm);
+
+ drm_connector_put(&first_changed_connector->base);
+}
+
static void i915_hpd_poll_init_work(struct work_struct *work)
{
struct drm_i915_private *dev_priv =
@@ -638,11 +690,25 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
display.hotplug.poll_init_work);
struct drm_connector_list_iter conn_iter;
struct intel_connector *connector;
+ intel_wakeref_t wakeref;
bool enabled;
mutex_lock(&dev_priv->drm.mode_config.mutex);
enabled = READ_ONCE(dev_priv->display.hotplug.poll_enabled);
+ /*
+ * Prevent taking a power reference from this sequence of
+ * i915_hpd_poll_init_work() -> drm_helper_hpd_irq_event() ->
+ * connector detect which would requeue i915_hpd_poll_init_work()
+ * and so risk an endless loop of this same sequence.
+ */
+ if (!enabled) {
+ wakeref = intel_display_power_get(dev_priv,
+ POWER_DOMAIN_DISPLAY_CORE);
+ drm_WARN_ON(&dev_priv->drm,
+ READ_ONCE(dev_priv->display.hotplug.poll_enabled));
+ cancel_work(&dev_priv->display.hotplug.poll_init_work);
+ }
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
@@ -669,8 +735,13 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
* We might have missed any hotplugs that happened while we were
* in the middle of disabling polling
*/
- if (!enabled)
- drm_helper_hpd_irq_event(&dev_priv->drm);
+ if (!enabled) {
+ i915_hpd_poll_detect_connectors(dev_priv);
+
+ intel_display_power_put(dev_priv,
+ POWER_DOMAIN_DISPLAY_CORE,
+ wakeref);
+ }
}
/**
@@ -692,7 +763,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
void intel_hpd_poll_enable(struct drm_i915_private *dev_priv)
{
if (!HAS_DISPLAY(dev_priv) ||
- !INTEL_DISPLAY_ENABLED(dev_priv))
+ !intel_display_device_enabled(dev_priv))
return;
WRITE_ONCE(dev_priv->display.hotplug.poll_enabled, true);
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
index 95a7ea94f4..f07047e9cb 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c
@@ -163,7 +163,9 @@ static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
(!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)))
return;
- if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
+ if (INTEL_PCH_TYPE(dev_priv) >= PCH_LNL)
+ hpd->pch_hpd = hpd_mtp;
+ else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
hpd->pch_hpd = hpd_sde_dg1;
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
hpd->pch_hpd = hpd_mtp;
@@ -514,6 +516,9 @@ void xelpdp_pica_irq_handler(struct drm_i915_private *i915, u32 iir)
u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
u32 pin_mask = 0, long_mask = 0;
+ if (DISPLAY_VER(i915) >= 20)
+ trigger_aux |= iir & XE2LPD_AUX_DDI_MASK;
+
for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
u32 val;
@@ -1060,6 +1065,19 @@ static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
mtp_tc_hpd_detection_setup(i915);
}
+static void xe2lpd_sde_hpd_irq_setup(struct drm_i915_private *i915)
+{
+ u32 hotplug_irqs, enabled_irqs;
+
+ enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd);
+ hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd);
+
+ ibx_display_interrupt_update(i915, hotplug_irqs, enabled_irqs);
+
+ mtp_ddi_hpd_detection_setup(i915);
+ mtp_tc_hpd_detection_setup(i915);
+}
+
static bool is_xelpdp_pica_hpd_pin(enum hpd_pin hpd_pin)
{
return hpd_pin >= HPD_PORT_TC1 && hpd_pin <= HPD_PORT_TC4;
@@ -1119,7 +1137,9 @@ static void xelpdp_hpd_irq_setup(struct drm_i915_private *i915)
xelpdp_pica_hpd_detection_setup(i915);
- if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
+ if (INTEL_PCH_TYPE(i915) >= PCH_LNL)
+ xe2lpd_sde_hpd_irq_setup(i915);
+ else if (INTEL_PCH_TYPE(i915) >= PCH_MTP)
mtp_hpd_irq_setup(i915);
}
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c
new file mode 100644
index 0000000000..c5eb5f2425
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include "i915_drv.h"
+
+#include "intel_atomic.h"
+#include "intel_display_types.h"
+#include "intel_fdi.h"
+#include "intel_link_bw.h"
+
+/**
+ * intel_link_bw_init_limits - initialize BW limits
+ * @i915: device instance
+ * @limits: link BW limits
+ *
+ * Initialize @limits.
+ */
+void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits)
+{
+ enum pipe pipe;
+
+ limits->bpp_limit_reached_pipes = 0;
+ for_each_pipe(i915, pipe)
+ limits->max_bpp_x16[pipe] = INT_MAX;
+}
+
+/**
+ * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
+ * @state: atomic state
+ * @limits: link BW limits
+ * @pipe_mask: mask of pipes to select from
+ * @reason: explanation of why bpp reduction is needed
+ *
+ * Select the pipe from @pipe_mask with the biggest link bpp value and set the
+ * maximum of link bpp in @limits below this value. Modeset the selected pipe,
+ * so that its state will get recomputed.
+ *
+ * This function can be called to resolve a link's BW overallocation by reducing
+ * the link bpp of one pipe on the link and hence reducing the total link BW.
+ *
+ * Returns
+ * - 0 in case of success
+ * - %-ENOSPC if no pipe can further reduce its link bpp
+ * - Other negative error, if modesetting the selected pipe failed
+ */
+int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
+ struct intel_link_bw_limits *limits,
+ u8 pipe_mask,
+ const char *reason)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ enum pipe max_bpp_pipe = INVALID_PIPE;
+ struct intel_crtc *crtc;
+ int max_bpp = 0;
+
+ for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
+ struct intel_crtc_state *crtc_state;
+ int link_bpp;
+
+ if (limits->bpp_limit_reached_pipes & BIT(crtc->pipe))
+ continue;
+
+ crtc_state = intel_atomic_get_crtc_state(&state->base,
+ crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ if (crtc_state->dsc.compression_enable)
+ link_bpp = crtc_state->dsc.compressed_bpp;
+ else
+ /*
+ * TODO: for YUV420 the actual link bpp is only half
+ * of the pipe bpp value. The MST encoder's BW allocation
+ * is based on the pipe bpp value, set the actual link bpp
+ * limit here once the MST BW allocation is fixed.
+ */
+ link_bpp = crtc_state->pipe_bpp;
+
+ if (link_bpp > max_bpp) {
+ max_bpp = link_bpp;
+ max_bpp_pipe = crtc->pipe;
+ }
+ }
+
+ if (max_bpp_pipe == INVALID_PIPE)
+ return -ENOSPC;
+
+ limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1;
+
+ return intel_modeset_pipes_in_mask_early(state, reason,
+ BIT(max_bpp_pipe));
+}
+
+/**
+ * intel_link_bw_set_bpp_limit_for_pipe - set link bpp limit for a pipe to its minimum
+ * @state: atomic state
+ * @old_limits: link BW limits
+ * @new_limits: link BW limits
+ * @pipe: pipe
+ *
+ * Set the link bpp limit for @pipe in @new_limits to its value in
+ * @old_limits and mark this limit as the minimum. This function must be
+ * called after a pipe's compute config function failed, @old_limits
+ * containing the bpp limit with which compute config previously passed.
+ *
+ * The function will fail if setting a minimum is not possible, either
+ * because the old and new limits match (and so would lead to a pipe compute
+ * config failure) or the limit is already at the minimum.
+ *
+ * Returns %true in case of success.
+ */
+bool
+intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state *state,
+ const struct intel_link_bw_limits *old_limits,
+ struct intel_link_bw_limits *new_limits,
+ enum pipe pipe)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+
+ if (pipe == INVALID_PIPE)
+ return false;
+
+ if (new_limits->max_bpp_x16[pipe] ==
+ old_limits->max_bpp_x16[pipe])
+ return false;
+
+ if (drm_WARN_ON(&i915->drm,
+ new_limits->bpp_limit_reached_pipes & BIT(pipe)))
+ return false;
+
+ new_limits->max_bpp_x16[pipe] =
+ old_limits->max_bpp_x16[pipe];
+ new_limits->bpp_limit_reached_pipes |= BIT(pipe);
+
+ return true;
+}
+
+static int check_all_link_config(struct intel_atomic_state *state,
+ struct intel_link_bw_limits *limits)
+{
+ /* TODO: Check additional shared display link configurations like MST */
+ int ret;
+
+ ret = intel_fdi_atomic_check_link(state, limits);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static bool
+assert_link_limit_change_valid(struct drm_i915_private *i915,
+ const struct intel_link_bw_limits *old_limits,
+ const struct intel_link_bw_limits *new_limits)
+{
+ bool bpps_changed = false;
+ enum pipe pipe;
+
+ for_each_pipe(i915, pipe) {
+ /* The bpp limit can only decrease. */
+ if (drm_WARN_ON(&i915->drm,
+ new_limits->max_bpp_x16[pipe] >
+ old_limits->max_bpp_x16[pipe]))
+ return false;
+
+ if (new_limits->max_bpp_x16[pipe] <
+ old_limits->max_bpp_x16[pipe])
+ bpps_changed = true;
+ }
+
+ /* At least one limit must change. */
+ if (drm_WARN_ON(&i915->drm,
+ !bpps_changed))
+ return false;
+
+ return true;
+}
+
+/**
+ * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
+ * @state: atomic state
+ * @new_limits: link BW limits
+ *
+ * Check the configuration of all shared display links in @state and set new BW
+ * limits in @new_limits if there is a BW limitation.
+ *
+ * Returns:
+ * - 0 if the confugration is valid
+ * - %-EAGAIN, if the configuration is invalid and @new_limits got updated
+ * with fallback values with which the configuration of all CRTCs
+ * in @state must be recomputed
+ * - Other negative error, if the configuration is invalid without a
+ * fallback possibility, or the check failed for another reason
+ */
+int intel_link_bw_atomic_check(struct intel_atomic_state *state,
+ struct intel_link_bw_limits *new_limits)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_link_bw_limits old_limits = *new_limits;
+ int ret;
+
+ ret = check_all_link_config(state, new_limits);
+ if (ret != -EAGAIN)
+ return ret;
+
+ if (!assert_link_limit_change_valid(i915, &old_limits, new_limits))
+ return -EINVAL;
+
+ return -EAGAIN;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.h b/drivers/gpu/drm/i915/display/intel_link_bw.h
new file mode 100644
index 0000000000..e07df22a77
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_link_bw.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef __INTEL_LINK_BW_H__
+#define __INTEL_LINK_BW_H__
+
+#include <linux/types.h>
+
+#include "intel_display_limits.h"
+
+struct drm_i915_private;
+
+struct intel_atomic_state;
+struct intel_crtc_state;
+
+struct intel_link_bw_limits {
+ u8 bpp_limit_reached_pipes;
+ /* in 1/16 bpp units */
+ int max_bpp_x16[I915_MAX_PIPES];
+};
+
+void intel_link_bw_init_limits(struct drm_i915_private *i915,
+ struct intel_link_bw_limits *limits);
+int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
+ struct intel_link_bw_limits *limits,
+ u8 pipe_mask,
+ const char *reason);
+bool intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state *state,
+ const struct intel_link_bw_limits *old_limits,
+ struct intel_link_bw_limits *new_limits,
+ enum pipe pipe);
+int intel_link_bw_atomic_check(struct intel_atomic_state *state,
+ struct intel_link_bw_limits *new_limits);
+
+#endif
diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.h b/drivers/gpu/drm/i915/display/intel_lpe_audio.h
index 0beecac267..2c5fcb6e1f 100644
--- a/drivers/gpu/drm/i915/display/intel_lpe_audio.h
+++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.h
@@ -12,11 +12,29 @@ enum port;
enum transcoder;
struct drm_i915_private;
+#ifdef I915
int intel_lpe_audio_init(struct drm_i915_private *dev_priv);
void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv);
void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv);
void intel_lpe_audio_notify(struct drm_i915_private *dev_priv,
enum transcoder cpu_transcoder, enum port port,
const void *eld, int ls_clock, bool dp_output);
+#else
+static inline int intel_lpe_audio_init(struct drm_i915_private *dev_priv)
+{
+ return -ENODEV;
+}
+static inline void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)
+{
+}
+static inline void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv)
+{
+}
+static inline void intel_lpe_audio_notify(struct drm_i915_private *dev_priv,
+ enum transcoder cpu_transcoder, enum port port,
+ const void *eld, int ls_clock, bool dp_output)
+{
+}
+#endif
#endif /* __INTEL_LPE_AUDIO_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c
index bb3b5355a0..1d048fa985 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -144,15 +144,27 @@ static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon)
struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
enum drm_lspcon_mode current_mode;
- struct i2c_adapter *adapter = &intel_dp->aux.ddc;
+ struct i2c_adapter *ddc = &intel_dp->aux.ddc;
- if (drm_lspcon_get_mode(intel_dp->aux.drm_dev, adapter, &current_mode)) {
+ if (drm_lspcon_get_mode(intel_dp->aux.drm_dev, ddc, &current_mode)) {
drm_dbg_kms(&i915->drm, "Error reading LSPCON mode\n");
return DRM_LSPCON_MODE_INVALID;
}
return current_mode;
}
+static int lspcon_get_mode_settle_timeout(struct intel_lspcon *lspcon)
+{
+ /*
+ * On some CometLake-based device designs the Parade PS175 takes more
+ * than 400ms to settle in PCON mode. 100 reboot trials on one device
+ * resulted in a median settle time of 440ms and a maximum of 444ms.
+ * Even after increasing the timeout to 500ms, 2% of devices still had
+ * this error. So this sets the timeout to 800ms.
+ */
+ return lspcon->vendor == LSPCON_VENDOR_PARADE ? 800 : 400;
+}
+
static enum drm_lspcon_mode lspcon_wait_mode(struct intel_lspcon *lspcon,
enum drm_lspcon_mode mode)
{
@@ -167,7 +179,8 @@ static enum drm_lspcon_mode lspcon_wait_mode(struct intel_lspcon *lspcon,
drm_dbg_kms(&i915->drm, "Waiting for LSPCON mode %s to settle\n",
lspcon_mode_name(mode));
- wait_for((current_mode = lspcon_get_current_mode(lspcon)) == mode, 400);
+ wait_for((current_mode = lspcon_get_current_mode(lspcon)) == mode,
+ lspcon_get_mode_settle_timeout(lspcon));
if (current_mode != mode)
drm_err(&i915->drm, "LSPCON mode hasn't settled\n");
@@ -185,9 +198,9 @@ static int lspcon_change_mode(struct intel_lspcon *lspcon,
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
int err;
enum drm_lspcon_mode current_mode;
- struct i2c_adapter *adapter = &intel_dp->aux.ddc;
+ struct i2c_adapter *ddc = &intel_dp->aux.ddc;
- err = drm_lspcon_get_mode(intel_dp->aux.drm_dev, adapter, &current_mode);
+ err = drm_lspcon_get_mode(intel_dp->aux.drm_dev, ddc, &current_mode);
if (err) {
drm_err(&i915->drm, "Error reading LSPCON mode\n");
return err;
@@ -198,7 +211,7 @@ static int lspcon_change_mode(struct intel_lspcon *lspcon,
return 0;
}
- err = drm_lspcon_set_mode(intel_dp->aux.drm_dev, adapter, mode);
+ err = drm_lspcon_set_mode(intel_dp->aux.drm_dev, ddc, mode);
if (err < 0) {
drm_err(&i915->drm, "LSPCON mode change failed\n");
return err;
@@ -233,7 +246,7 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
enum drm_dp_dual_mode_type adaptor_type;
struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
- struct i2c_adapter *adapter = &intel_dp->aux.ddc;
+ struct i2c_adapter *ddc = &intel_dp->aux.ddc;
enum drm_lspcon_mode expected_mode;
expected_mode = lspcon_wake_native_aux_ch(lspcon) ?
@@ -244,7 +257,7 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
if (retry)
usleep_range(500, 1000);
- adaptor_type = drm_dp_dual_mode_detect(intel_dp->aux.drm_dev, adapter);
+ adaptor_type = drm_dp_dual_mode_detect(intel_dp->aux.drm_dev, ddc);
if (adaptor_type == DRM_DP_DUAL_MODE_LSPCON)
break;
}
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index dcb07d9a73..bcbdd1984f 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -430,11 +430,18 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
return -EINVAL;
}
+ if (HAS_PCH_SPLIT(i915)) {
+ crtc_state->has_pch_encoder = true;
+ if (!intel_fdi_compute_pipe_bpp(crtc_state))
+ return -EINVAL;
+ }
+
if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
lvds_bpp = 8*3;
else
lvds_bpp = 6*3;
+ /* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */
if (lvds_bpp != crtc_state->pipe_bpp && !crtc_state->bw_constrained) {
drm_dbg_kms(&i915->drm,
"forcing display bpp (was %d) to LVDS (%d)\n",
@@ -458,9 +465,6 @@ static int intel_lvds_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
- if (HAS_PCH_SPLIT(i915))
- crtc_state->has_pch_encoder = true;
-
ret = intel_panel_fitting(crtc_state, conn_state);
if (ret)
return ret;
@@ -842,7 +846,7 @@ void intel_lvds_init(struct drm_i915_private *i915)
struct intel_encoder *encoder;
i915_reg_t lvds_reg;
u32 lvds;
- u8 pin;
+ u8 ddc_pin;
/* Skip init on machines we know falsely report LVDS */
if (dmi_check_system(intel_no_lvds)) {
@@ -869,8 +873,8 @@ void intel_lvds_init(struct drm_i915_private *i915)
return;
}
- pin = GMBUS_PIN_PANEL;
- if (!intel_bios_is_lvds_present(i915, &pin)) {
+ ddc_pin = GMBUS_PIN_PANEL;
+ if (!intel_bios_is_lvds_present(i915, &ddc_pin)) {
if ((lvds & LVDS_PORT_EN) == 0) {
drm_dbg_kms(&i915->drm,
"LVDS is not present in VBT\n");
@@ -893,8 +897,10 @@ void intel_lvds_init(struct drm_i915_private *i915)
lvds_encoder->attached_connector = connector;
encoder = &lvds_encoder->base;
- drm_connector_init(&i915->drm, &connector->base, &intel_lvds_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS);
+ drm_connector_init_with_ddc(&i915->drm, &connector->base,
+ &intel_lvds_connector_funcs,
+ DRM_MODE_CONNECTOR_LVDS,
+ intel_gmbus_get_adapter(i915, ddc_pin));
drm_encoder_init(&i915->drm, &encoder->base, &intel_lvds_enc_funcs,
DRM_MODE_ENCODER_LVDS, "LVDS");
@@ -948,13 +954,10 @@ void intel_lvds_init(struct drm_i915_private *i915)
* preferred mode is the right one.
*/
mutex_lock(&i915->drm.mode_config.mutex);
- if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) {
- drm_edid = drm_edid_read_switcheroo(&connector->base,
- intel_gmbus_get_adapter(i915, pin));
- } else {
- drm_edid = drm_edid_read_ddc(&connector->base,
- intel_gmbus_get_adapter(i915, pin));
- }
+ if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC)
+ drm_edid = drm_edid_read_switcheroo(&connector->base, connector->base.ddc);
+ else
+ drm_edid = drm_edid_read_ddc(&connector->base, connector->base.ddc);
if (drm_edid) {
if (drm_edid_connector_update(&connector->base, drm_edid) ||
!drm_edid_connector_add_modes(&connector->base)) {
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.h b/drivers/gpu/drm/i915/display/intel_lvds.h
index 9d3372dc50..7ad5fa9c04 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.h
+++ b/drivers/gpu/drm/i915/display/intel_lvds.h
@@ -13,10 +13,29 @@
enum pipe;
struct drm_i915_private;
+#ifdef I915
bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv,
i915_reg_t lvds_reg, enum pipe *pipe);
void intel_lvds_init(struct drm_i915_private *dev_priv);
struct intel_encoder *intel_get_lvds_encoder(struct drm_i915_private *dev_priv);
bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv);
+#else
+static inline bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv,
+ i915_reg_t lvds_reg, enum pipe *pipe)
+{
+ return false;
+}
+static inline void intel_lvds_init(struct drm_i915_private *dev_priv)
+{
+}
+static inline struct intel_encoder *intel_get_lvds_encoder(struct drm_i915_private *dev_priv)
+{
+ return NULL;
+}
+static inline bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv)
+{
+ return false;
+}
+#endif
#endif /* __INTEL_LVDS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
index 138144a65a..5e1c2c7804 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
@@ -23,8 +23,8 @@
* Cross check the actual hw state with our own modeset state tracking (and its
* internal consistency).
*/
-static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
+static void intel_connector_verify_state(const struct intel_crtc_state *crtc_state,
+ const struct drm_connector_state *conn_state)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
@@ -66,12 +66,12 @@ verify_connector_state(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct drm_connector *connector;
- struct drm_connector_state *new_conn_state;
+ const struct drm_connector_state *new_conn_state;
int i;
for_each_new_connector_in_state(&state->base, connector, new_conn_state, i) {
struct drm_encoder *encoder = connector->encoder;
- struct intel_crtc_state *crtc_state = NULL;
+ const struct intel_crtc_state *crtc_state = NULL;
if (new_conn_state->crtc != &crtc->base)
continue;
@@ -86,38 +86,40 @@ verify_connector_state(struct intel_atomic_state *state,
}
}
-static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv,
- const struct intel_crtc_state *pipe_config)
+static void intel_pipe_config_sanity_check(const struct intel_crtc_state *crtc_state)
{
- if (pipe_config->has_pch_encoder) {
- int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config),
- &pipe_config->fdi_m_n);
- int dotclock = pipe_config->hw.adjusted_mode.crtc_clock;
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+ if (crtc_state->has_pch_encoder) {
+ int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(i915, crtc_state),
+ &crtc_state->fdi_m_n);
+ int dotclock = crtc_state->hw.adjusted_mode.crtc_clock;
/*
* FDI already provided one idea for the dotclock.
* Yell if the encoder disagrees. Allow for slight
* rounding differences.
*/
- drm_WARN(&dev_priv->drm, abs(fdi_dotclock - dotclock) > 1,
+ drm_WARN(&i915->drm, abs(fdi_dotclock - dotclock) > 1,
"FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n",
fdi_dotclock, dotclock);
}
}
static void
-verify_encoder_state(struct drm_i915_private *dev_priv, struct intel_atomic_state *state)
+verify_encoder_state(struct intel_atomic_state *state)
{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_encoder *encoder;
struct drm_connector *connector;
- struct drm_connector_state *old_conn_state, *new_conn_state;
+ const struct drm_connector_state *old_conn_state, *new_conn_state;
int i;
- for_each_intel_encoder(&dev_priv->drm, encoder) {
+ for_each_intel_encoder(&i915->drm, encoder) {
bool enabled = false, found = false;
enum pipe pipe;
- drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s]\n",
+ drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s]\n",
encoder->base.base.id,
encoder->base.name);
@@ -132,7 +134,7 @@ verify_encoder_state(struct drm_i915_private *dev_priv, struct intel_atomic_stat
found = true;
enabled = true;
- I915_STATE_WARN(dev_priv,
+ I915_STATE_WARN(i915,
new_conn_state->crtc != encoder->base.crtc,
"connector's crtc doesn't match encoder crtc\n");
}
@@ -140,7 +142,7 @@ verify_encoder_state(struct drm_i915_private *dev_priv, struct intel_atomic_stat
if (!found)
continue;
- I915_STATE_WARN(dev_priv, !!encoder->base.crtc != enabled,
+ I915_STATE_WARN(i915, !!encoder->base.crtc != enabled,
"encoder's enabled state mismatch (expected %i, found %i)\n",
!!encoder->base.crtc, enabled);
@@ -148,7 +150,7 @@ verify_encoder_state(struct drm_i915_private *dev_priv, struct intel_atomic_stat
bool active;
active = encoder->get_hw_state(encoder, &pipe);
- I915_STATE_WARN(dev_priv, active,
+ I915_STATE_WARN(i915, active,
"encoder detached but still enabled on pipe %c.\n",
pipe_name(pipe));
}
@@ -156,96 +158,98 @@ verify_encoder_state(struct drm_i915_private *dev_priv, struct intel_atomic_stat
}
static void
-verify_crtc_state(struct intel_crtc *crtc,
- struct intel_crtc_state *old_crtc_state,
- struct intel_crtc_state *new_crtc_state)
+verify_crtc_state(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct intel_encoder *encoder;
- struct intel_crtc_state *pipe_config = old_crtc_state;
- struct drm_atomic_state *state = old_crtc_state->uapi.state;
+ struct drm_i915_private *i915 = to_i915(dev);
+ const struct intel_crtc_state *sw_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ struct intel_crtc_state *hw_crtc_state;
struct intel_crtc *master_crtc;
+ struct intel_encoder *encoder;
- __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi);
- intel_crtc_free_hw_state(old_crtc_state);
- intel_crtc_state_reset(old_crtc_state, crtc);
- old_crtc_state->uapi.state = state;
+ hw_crtc_state = intel_crtc_state_alloc(crtc);
+ if (!hw_crtc_state)
+ return;
- drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s]\n", crtc->base.base.id,
+ drm_dbg_kms(&i915->drm, "[CRTC:%d:%s]\n", crtc->base.base.id,
crtc->base.name);
- pipe_config->hw.enable = new_crtc_state->hw.enable;
+ hw_crtc_state->hw.enable = sw_crtc_state->hw.enable;
- intel_crtc_get_pipe_config(pipe_config);
+ intel_crtc_get_pipe_config(hw_crtc_state);
/* we keep both pipes enabled on 830 */
- if (IS_I830(dev_priv) && pipe_config->hw.active)
- pipe_config->hw.active = new_crtc_state->hw.active;
+ if (IS_I830(i915) && hw_crtc_state->hw.active)
+ hw_crtc_state->hw.active = sw_crtc_state->hw.active;
- I915_STATE_WARN(dev_priv,
- new_crtc_state->hw.active != pipe_config->hw.active,
+ I915_STATE_WARN(i915,
+ sw_crtc_state->hw.active != hw_crtc_state->hw.active,
"crtc active state doesn't match with hw state (expected %i, found %i)\n",
- new_crtc_state->hw.active, pipe_config->hw.active);
+ sw_crtc_state->hw.active, hw_crtc_state->hw.active);
- I915_STATE_WARN(dev_priv, crtc->active != new_crtc_state->hw.active,
+ I915_STATE_WARN(i915, crtc->active != sw_crtc_state->hw.active,
"transitional active state does not match atomic hw state (expected %i, found %i)\n",
- new_crtc_state->hw.active, crtc->active);
+ sw_crtc_state->hw.active, crtc->active);
- master_crtc = intel_master_crtc(new_crtc_state);
+ master_crtc = intel_master_crtc(sw_crtc_state);
for_each_encoder_on_crtc(dev, &master_crtc->base, encoder) {
enum pipe pipe;
bool active;
active = encoder->get_hw_state(encoder, &pipe);
- I915_STATE_WARN(dev_priv, active != new_crtc_state->hw.active,
+ I915_STATE_WARN(i915, active != sw_crtc_state->hw.active,
"[ENCODER:%i] active %i with crtc active %i\n",
encoder->base.base.id, active,
- new_crtc_state->hw.active);
+ sw_crtc_state->hw.active);
- I915_STATE_WARN(dev_priv, active && master_crtc->pipe != pipe,
+ I915_STATE_WARN(i915, active && master_crtc->pipe != pipe,
"Encoder connected to wrong pipe %c\n",
pipe_name(pipe));
if (active)
- intel_encoder_get_config(encoder, pipe_config);
+ intel_encoder_get_config(encoder, hw_crtc_state);
}
- if (!new_crtc_state->hw.active)
- return;
+ if (!sw_crtc_state->hw.active)
+ goto destroy_state;
- intel_pipe_config_sanity_check(dev_priv, pipe_config);
+ intel_pipe_config_sanity_check(hw_crtc_state);
- if (!intel_pipe_config_compare(new_crtc_state,
- pipe_config, false)) {
- I915_STATE_WARN(dev_priv, 1, "pipe state doesn't match!\n");
- intel_crtc_state_dump(pipe_config, NULL, "hw state");
- intel_crtc_state_dump(new_crtc_state, NULL, "sw state");
+ if (!intel_pipe_config_compare(sw_crtc_state,
+ hw_crtc_state, false)) {
+ I915_STATE_WARN(i915, 1, "pipe state doesn't match!\n");
+ intel_crtc_state_dump(hw_crtc_state, NULL, "hw state");
+ intel_crtc_state_dump(sw_crtc_state, NULL, "sw state");
}
+
+destroy_state:
+ intel_crtc_destroy_state(&crtc->base, &hw_crtc_state->uapi);
}
-void intel_modeset_verify_crtc(struct intel_crtc *crtc,
- struct intel_atomic_state *state,
- struct intel_crtc_state *old_crtc_state,
- struct intel_crtc_state *new_crtc_state)
+void intel_modeset_verify_crtc(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
+ const struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+
if (!intel_crtc_needs_modeset(new_crtc_state) &&
!intel_crtc_needs_fastset(new_crtc_state))
return;
- intel_wm_state_verify(crtc, new_crtc_state);
+ intel_wm_state_verify(state, crtc);
verify_connector_state(state, crtc);
- verify_crtc_state(crtc, old_crtc_state, new_crtc_state);
- intel_shared_dpll_state_verify(crtc, old_crtc_state, new_crtc_state);
- intel_mpllb_state_verify(state, new_crtc_state);
- intel_c10pll_state_verify(state, new_crtc_state);
+ verify_crtc_state(state, crtc);
+ intel_shared_dpll_state_verify(state, crtc);
+ intel_mpllb_state_verify(state, crtc);
+ intel_c10pll_state_verify(state, crtc);
}
-void intel_modeset_verify_disabled(struct drm_i915_private *dev_priv,
- struct intel_atomic_state *state)
+void intel_modeset_verify_disabled(struct intel_atomic_state *state)
{
- verify_encoder_state(dev_priv, state);
+ verify_encoder_state(state);
verify_connector_state(state, NULL);
- intel_shared_dpll_verify_disabled(dev_priv);
+ intel_shared_dpll_verify_disabled(state);
}
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.h b/drivers/gpu/drm/i915/display/intel_modeset_verify.h
index 2d6fbe4f78..3bef8735cb 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_verify.h
+++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.h
@@ -6,16 +6,11 @@
#ifndef __INTEL_MODESET_VERIFY_H__
#define __INTEL_MODESET_VERIFY_H__
-struct drm_i915_private;
struct intel_atomic_state;
struct intel_crtc;
-struct intel_crtc_state;
-void intel_modeset_verify_crtc(struct intel_crtc *crtc,
- struct intel_atomic_state *state,
- struct intel_crtc_state *old_crtc_state,
- struct intel_crtc_state *new_crtc_state);
-void intel_modeset_verify_disabled(struct drm_i915_private *dev_priv,
- struct intel_atomic_state *state);
+void intel_modeset_verify_crtc(struct intel_atomic_state *state,
+ struct intel_crtc *crtc);
+void intel_modeset_verify_disabled(struct intel_atomic_state *state);
#endif /* __INTEL_MODESET_VERIFY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c
index 09c1aa1427..2b1392d5a9 100644
--- a/drivers/gpu/drm/i915/display/intel_overlay.c
+++ b/drivers/gpu/drm/i915/display/intel_overlay.c
@@ -29,12 +29,14 @@
#include <drm/drm_fourcc.h>
#include "gem/i915_gem_internal.h"
+#include "gem/i915_gem_object_frontbuffer.h"
#include "gem/i915_gem_pm.h"
#include "gt/intel_gpu_commands.h"
#include "gt/intel_ring.h"
#include "i915_drv.h"
#include "i915_reg.h"
+#include "intel_color_regs.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_frontbuffer.h"
diff --git a/drivers/gpu/drm/i915/display/intel_overlay.h b/drivers/gpu/drm/i915/display/intel_overlay.h
index a167c28acd..c3f68fce6f 100644
--- a/drivers/gpu/drm/i915/display/intel_overlay.h
+++ b/drivers/gpu/drm/i915/display/intel_overlay.h
@@ -13,6 +13,7 @@ struct drm_i915_private;
struct intel_overlay;
struct intel_overlay_error_state;
+#ifdef I915
void intel_overlay_setup(struct drm_i915_private *dev_priv);
void intel_overlay_cleanup(struct drm_i915_private *dev_priv);
int intel_overlay_switch_off(struct intel_overlay *overlay);
@@ -25,5 +26,39 @@ struct intel_overlay_error_state *
intel_overlay_capture_error_state(struct drm_i915_private *dev_priv);
void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
struct intel_overlay_error_state *error);
+#else
+static inline void intel_overlay_setup(struct drm_i915_private *dev_priv)
+{
+}
+static inline void intel_overlay_cleanup(struct drm_i915_private *dev_priv)
+{
+}
+static inline int intel_overlay_switch_off(struct intel_overlay *overlay)
+{
+ return 0;
+}
+static inline int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return 0;
+}
+static inline int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return 0;
+}
+static inline void intel_overlay_reset(struct drm_i915_private *dev_priv)
+{
+}
+static inline struct intel_overlay_error_state *
+intel_overlay_capture_error_state(struct drm_i915_private *dev_priv)
+{
+ return NULL;
+}
+static inline void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
+ struct intel_overlay_error_state *error)
+{
+}
+#endif
#endif /* __INTEL_OVERLAY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index 9232a305b1..483beedac5 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -59,15 +59,6 @@ intel_panel_preferred_fixed_mode(struct intel_connector *connector)
struct drm_display_mode, head);
}
-static bool is_in_vrr_range(struct intel_connector *connector, int vrefresh)
-{
- const struct drm_display_info *info = &connector->base.display_info;
-
- return intel_vrr_is_capable(connector) &&
- vrefresh >= info->monitor_range.min_vfreq &&
- vrefresh <= info->monitor_range.max_vfreq;
-}
-
static bool is_best_fixed_mode(struct intel_connector *connector,
int vrefresh, int fixed_mode_vrefresh,
const struct drm_display_mode *best_mode)
@@ -81,8 +72,8 @@ static bool is_best_fixed_mode(struct intel_connector *connector,
* vrefresh, which we can then reduce to match the requested
* vrefresh by extending the vblank length.
*/
- if (is_in_vrr_range(connector, vrefresh) &&
- is_in_vrr_range(connector, fixed_mode_vrefresh) &&
+ if (intel_vrr_is_in_range(connector, vrefresh) &&
+ intel_vrr_is_in_range(connector, fixed_mode_vrefresh) &&
fixed_mode_vrefresh < vrefresh)
return false;
@@ -224,8 +215,8 @@ int intel_panel_compute_config(struct intel_connector *connector,
* Assume that we shouldn't muck about with the
* timings if they don't land in the VRR range.
*/
- is_vrr = is_in_vrr_range(connector, vrefresh) &&
- is_in_vrr_range(connector, fixed_mode_vrefresh);
+ is_vrr = intel_vrr_is_in_range(connector, vrefresh) &&
+ intel_vrr_is_in_range(connector, fixed_mode_vrefresh);
if (!is_vrr) {
/*
@@ -689,7 +680,7 @@ intel_panel_detect(struct drm_connector *connector, bool force)
{
struct drm_i915_private *i915 = to_i915(connector->dev);
- if (!INTEL_DISPLAY_ENABLED(i915))
+ if (!intel_display_device_enabled(i915))
return connector_status_disconnected;
return connector_status_connected;
diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.h b/drivers/gpu/drm/i915/display/intel_pch_display.h
index 41a63413cb..35f8288af3 100644
--- a/drivers/gpu/drm/i915/display/intel_pch_display.h
+++ b/drivers/gpu/drm/i915/display/intel_pch_display.h
@@ -15,6 +15,7 @@ struct intel_crtc;
struct intel_crtc_state;
struct intel_link_m_n;
+#ifdef I915
bool intel_has_pch_trancoder(struct drm_i915_private *i915,
enum pipe pch_transcoder);
enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc);
@@ -41,5 +42,57 @@ void intel_pch_transcoder_get_m2_n2(struct intel_crtc *crtc,
struct intel_link_m_n *m_n);
void intel_pch_sanitize(struct drm_i915_private *i915);
+#else
+static inline bool intel_has_pch_trancoder(struct drm_i915_private *i915,
+ enum pipe pch_transcoder)
+{
+ return false;
+}
+static inline int intel_crtc_pch_transcoder(struct intel_crtc *crtc)
+{
+ return 0;
+}
+static inline void ilk_pch_pre_enable(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+}
+static inline void ilk_pch_enable(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+}
+static inline void ilk_pch_disable(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+}
+static inline void ilk_pch_post_disable(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+}
+static inline void ilk_pch_get_config(struct intel_crtc_state *crtc_state)
+{
+}
+static inline void lpt_pch_enable(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+}
+static inline void lpt_pch_disable(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+}
+static inline void lpt_pch_get_config(struct intel_crtc_state *crtc_state)
+{
+}
+static inline void intel_pch_transcoder_get_m1_n1(struct intel_crtc *crtc,
+ struct intel_link_m_n *m_n)
+{
+}
+static inline void intel_pch_transcoder_get_m2_n2(struct intel_crtc *crtc,
+ struct intel_link_m_n *m_n)
+{
+}
+static inline void intel_pch_sanitize(struct drm_i915_private *i915)
+{
+}
+#endif
#endif
diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c
index 9583e86b60..713cfba714 100644
--- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c
+++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c
@@ -492,6 +492,7 @@ static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv)
static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)
{
struct intel_encoder *encoder;
+ struct intel_shared_dpll *pll;
int i;
u32 val, final;
bool has_lvds = false;
@@ -527,8 +528,10 @@ static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)
}
/* Check if any DPLLs are using the SSC source */
- for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) {
- u32 temp = intel_de_read(dev_priv, PCH_DPLL(i));
+ for_each_shared_dpll(dev_priv, pll, i) {
+ u32 temp;
+
+ temp = intel_de_read(dev_priv, PCH_DPLL(pll->info->id));
if (!(temp & DPLL_VCO_ENABLE))
continue;
diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.h b/drivers/gpu/drm/i915/display/intel_pch_refclk.h
index 9bcf56629f..ae3403c0ce 100644
--- a/drivers/gpu/drm/i915/display/intel_pch_refclk.h
+++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.h
@@ -11,6 +11,7 @@
struct drm_i915_private;
struct intel_crtc_state;
+#ifdef I915
void lpt_program_iclkip(const struct intel_crtc_state *crtc_state);
void lpt_disable_iclkip(struct drm_i915_private *dev_priv);
int lpt_get_iclkip(struct drm_i915_private *dev_priv);
@@ -18,5 +19,27 @@ int lpt_iclkip(const struct intel_crtc_state *crtc_state);
void intel_init_pch_refclk(struct drm_i915_private *dev_priv);
void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv);
+#else
+static inline void lpt_program_iclkip(const struct intel_crtc_state *crtc_state)
+{
+}
+static inline void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
+{
+}
+static inline int lpt_get_iclkip(struct drm_i915_private *dev_priv)
+{
+ return 0;
+}
+static inline int lpt_iclkip(const struct intel_crtc_state *crtc_state)
+{
+ return 0;
+}
+static inline void intel_init_pch_refclk(struct drm_i915_private *dev_priv)
+{
+}
+static inline void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
+{
+}
+#endif
#endif
diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c
index 736072a8b2..a55c09cbd0 100644
--- a/drivers/gpu/drm/i915/display/intel_plane_initial.c
+++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c
@@ -9,6 +9,7 @@
#include "intel_display.h"
#include "intel_display_types.h"
#include "intel_fb.h"
+#include "intel_frontbuffer.h"
#include "intel_plane_initial.h"
static bool
@@ -165,7 +166,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+ struct drm_mode_fb_cmd2 mode_cmd = {};
struct drm_framebuffer *fb = &plane_config->fb->base;
struct i915_vma *vma;
diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c
index f7608d3636..744e332fa2 100644
--- a/drivers/gpu/drm/i915/display/intel_pmdemand.c
+++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c
@@ -92,7 +92,7 @@ int intel_pmdemand_init(struct drm_i915_private *i915)
&pmdemand_state->base,
&intel_pmdemand_funcs);
- if (IS_MTL_DISPLAY_STEP(i915, STEP_A0, STEP_C0))
+ if (IS_DISPLAY_IP_STEP(i915, IP_VER(14, 0), STEP_A0, STEP_C0))
/* Wa_14016740474 */
intel_de_rmw(i915, XELPD_CHICKEN_DCPR_3, 0, DMD_RSP_TIMEOUT_DISABLE);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 5cf3db7058..614b4534ef 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -23,6 +23,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
+#include <drm/drm_debugfs.h>
#include "i915_drv.h"
#include "i915_reg.h"
@@ -32,6 +33,7 @@
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_aux.h"
+#include "intel_frontbuffer.h"
#include "intel_hdmi.h"
#include "intel_psr.h"
#include "intel_psr_regs.h"
@@ -1362,8 +1364,7 @@ static void wm_optimization_wa(struct intel_dp *intel_dp,
bool set_wa_bit = false;
/* Wa_14015648006 */
- if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) ||
- IS_DISPLAY_VER(dev_priv, 11, 13))
+ if (IS_DISPLAY_VER(dev_priv, 11, 14))
set_wa_bit |= crtc_state->wm_level_disabled;
/* Wa_16013835468 */
@@ -1461,7 +1462,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
* All supported adlp panels have 1-based X granularity, this may
* cause issues if non-supported panels are used.
*/
- if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
+ if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0))
intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(cpu_transcoder), 0,
ADLP_1_BASED_X_GRANULARITY);
else if (IS_ALDERLAKE_P(dev_priv))
@@ -1469,7 +1470,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
ADLP_1_BASED_X_GRANULARITY);
/* Wa_16012604467:adlp,mtl[a0,b0] */
- if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
+ if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0))
intel_de_rmw(dev_priv,
MTL_CLKGATE_DIS_TRANS(cpu_transcoder), 0,
MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS);
@@ -1627,7 +1628,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
if (intel_dp->psr.psr2_enabled) {
/* Wa_16012604467:adlp,mtl[a0,b0] */
- if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
+ if (IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0))
intel_de_rmw(dev_priv,
MTL_CLKGATE_DIS_TRANS(cpu_transcoder),
MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS, 0);
@@ -2101,7 +2102,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
goto skip_sel_fetch_set_loop;
/* Wa_14014971492 */
- if ((IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) ||
+ if ((IS_DISPLAY_IP_STEP(dev_priv, IP_VER(14, 0), STEP_A0, STEP_B0) ||
IS_ALDERLAKE_P(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
crtc_state->splitter.enable)
pipe_clip.y1 = 0;
@@ -2208,10 +2209,12 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state,
}
}
-static void _intel_psr_post_plane_update(const struct intel_atomic_state *state,
- const struct intel_crtc_state *crtc_state)
+void intel_psr_post_plane_update(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+ const struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
struct intel_encoder *encoder;
if (!crtc_state->has_psr)
@@ -2244,24 +2247,16 @@ static void _intel_psr_post_plane_update(const struct intel_atomic_state *state,
if (crtc_state->crc_enabled && psr->enabled)
psr_force_hw_tracking_exit(intel_dp);
+ /*
+ * Clear possible busy bits in case we have
+ * invalidate -> flip -> flush sequence.
+ */
+ intel_dp->psr.busy_frontbuffer_bits = 0;
+
mutex_unlock(&psr->lock);
}
}
-void intel_psr_post_plane_update(const struct intel_atomic_state *state)
-{
- struct drm_i915_private *dev_priv = to_i915(state->base.dev);
- struct intel_crtc_state *crtc_state;
- struct intel_crtc *crtc;
- int i;
-
- if (!HAS_PSR(dev_priv))
- return;
-
- for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i)
- _intel_psr_post_plane_update(state, crtc_state);
-}
-
static int _psr2_ready_for_pipe_update_locked(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -3167,7 +3162,7 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data)
};
const char *str;
int ret;
- u8 val;
+ u8 status, error_status;
if (!CAN_PSR(intel_dp)) {
seq_puts(m, "PSR Unsupported\n");
@@ -3177,19 +3172,34 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data)
if (connector->base.status != connector_status_connected)
return -ENODEV;
- ret = drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val);
- if (ret != 1)
- return ret < 0 ? ret : -EIO;
+ ret = psr_get_status_and_error_status(intel_dp, &status, &error_status);
+ if (ret)
+ return ret;
- val &= DP_PSR_SINK_STATE_MASK;
- if (val < ARRAY_SIZE(sink_status))
- str = sink_status[val];
+ status &= DP_PSR_SINK_STATE_MASK;
+ if (status < ARRAY_SIZE(sink_status))
+ str = sink_status[status];
else
str = "unknown";
- seq_printf(m, "Sink PSR status: 0x%x [%s]\n", val, str);
+ seq_printf(m, "Sink PSR status: 0x%x [%s]\n", status, str);
- return 0;
+ seq_printf(m, "Sink PSR error status: 0x%x", error_status);
+
+ if (error_status & (DP_PSR_RFB_STORAGE_ERROR |
+ DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR |
+ DP_PSR_LINK_CRC_ERROR))
+ seq_puts(m, ":\n");
+ else
+ seq_puts(m, "\n");
+ if (error_status & DP_PSR_RFB_STORAGE_ERROR)
+ seq_puts(m, "\tPSR RFB storage error\n");
+ if (error_status & DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR)
+ seq_puts(m, "\tPSR VSC SDP uncorrectable error\n");
+ if (error_status & DP_PSR_LINK_CRC_ERROR)
+ seq_puts(m, "\tPSR Link CRC error\n");
+
+ return ret;
}
DEFINE_SHOW_ATTRIBUTE(i915_psr_sink_status);
diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h
index 0b95e8aa61..bf35f42df6 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.h
+++ b/drivers/gpu/drm/i915/display/intel_psr.h
@@ -24,7 +24,8 @@ struct intel_plane_state;
void intel_psr_init_dpcd(struct intel_dp *intel_dp);
void intel_psr_pre_plane_update(struct intel_atomic_state *state,
struct intel_crtc *crtc);
-void intel_psr_post_plane_update(const struct intel_atomic_state *state);
+void intel_psr_post_plane_update(struct intel_atomic_state *state,
+ struct intel_crtc *crtc);
void intel_psr_disable(struct intel_dp *intel_dp,
const struct intel_crtc_state *old_crtc_state);
int intel_psr_debug_set(struct intel_dp *intel_dp, u64 value);
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index 0ce935efe5..312f88d90a 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -44,6 +44,7 @@
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_types.h"
+#include "intel_fdi.h"
#include "intel_fifo_underrun.h"
#include "intel_gmbus.h"
#include "intel_hdmi.h"
@@ -57,15 +58,16 @@
#define SDVO_LVDS_MASK (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1)
#define SDVO_TV_MASK (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_YPRPB0)
-#define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\
- SDVO_TV_MASK)
+#define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK | SDVO_TV_MASK)
-#define IS_TV(c) (c->output_flag & SDVO_TV_MASK)
-#define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK)
-#define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK)
-#define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK))
-#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK))
+#define IS_TV(c) ((c)->output_flag & SDVO_TV_MASK)
+#define IS_TMDS(c) ((c)->output_flag & SDVO_TMDS_MASK)
+#define IS_LVDS(c) ((c)->output_flag & SDVO_LVDS_MASK)
+#define IS_TV_OR_LVDS(c) ((c)->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK))
+#define IS_DIGITAL(c) ((c)->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK))
+#define HAS_DDC(c) ((c)->output_flag & (SDVO_RGB_MASK | SDVO_TMDS_MASK | \
+ SDVO_LVDS_MASK))
static const char * const tv_format_names[] = {
"NTSC_M" , "NTSC_J" , "NTSC_443",
@@ -79,20 +81,25 @@ static const char * const tv_format_names[] = {
#define TV_FORMAT_NUM ARRAY_SIZE(tv_format_names)
+struct intel_sdvo;
+
+struct intel_sdvo_ddc {
+ struct i2c_adapter ddc;
+ struct intel_sdvo *sdvo;
+ u8 ddc_bus;
+};
+
struct intel_sdvo {
struct intel_encoder base;
struct i2c_adapter *i2c;
u8 slave_addr;
- struct i2c_adapter ddc;
+ struct intel_sdvo_ddc ddc[3];
/* Register for the SDVO device: SDVOB or SDVOC */
i915_reg_t sdvo_reg;
- /* Active outputs controlled by this SDVO output */
- u16 controlled_output;
-
/*
* Capabilities of the SDVO device returned by
* intel_sdvo_get_capabilities()
@@ -105,21 +112,10 @@ struct intel_sdvo {
int pixel_clock_min, pixel_clock_max;
/*
- * For multiple function SDVO device,
- * this is for current attached outputs.
- */
- u16 attached_output;
-
- /*
* Hotplug activation bits for this device
*/
u16 hotplug_active;
- enum port port;
-
- /* DDC bus used by this SDVO encoder */
- u8 ddc_bus;
-
/*
* the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd
*/
@@ -233,7 +229,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
return;
}
- if (intel_sdvo->port == PORT_B)
+ if (intel_sdvo->base.port == PORT_B)
cval = intel_de_read(dev_priv, GEN3_SDVOC);
else
bval = intel_de_read(dev_priv, GEN3_SDVOB);
@@ -410,7 +406,7 @@ static const char *sdvo_cmd_name(u8 cmd)
return NULL;
}
-#define SDVO_NAME(svdo) ((svdo)->port == PORT_B ? "SDVOB" : "SDVOC")
+#define SDVO_NAME(svdo) ((svdo)->base.port == PORT_B ? "SDVOB" : "SDVOC")
static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
const void *args, int args_len)
@@ -653,7 +649,7 @@ intel_sdvo_get_value(struct intel_sdvo *intel_sdvo, u8 cmd, void *value, int len
static bool intel_sdvo_set_target_input(struct intel_sdvo *intel_sdvo)
{
- struct intel_sdvo_set_target_input_args targets = {0};
+ struct intel_sdvo_set_target_input_args targets = {};
return intel_sdvo_set_value(intel_sdvo,
SDVO_CMD_SET_TARGET_INPUT,
&targets, sizeof(targets));
@@ -1212,7 +1208,7 @@ static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo,
struct intel_sdvo_tv_format format;
u32 format_map;
- format_map = 1 << conn_state->tv.mode;
+ format_map = 1 << conn_state->tv.legacy_mode;
memset(&format, 0, sizeof(format));
memcpy(&format, &format_map, min(sizeof(format), sizeof(format_map)));
@@ -1224,12 +1220,13 @@ static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo,
static bool
intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo,
+ struct intel_sdvo_connector *intel_sdvo_connector,
const struct drm_display_mode *mode)
{
struct intel_sdvo_dtd output_dtd;
if (!intel_sdvo_set_target_output(intel_sdvo,
- intel_sdvo->attached_output))
+ intel_sdvo_connector->output_flag))
return false;
intel_sdvo_get_dtd_from_mode(&output_dtd, mode);
@@ -1270,10 +1267,10 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
return true;
}
-static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config)
+static int i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(pipe_config->uapi.crtc->dev);
- unsigned dotclock = pipe_config->port_clock;
+ unsigned int dotclock = pipe_config->hw.adjusted_mode.crtc_clock;
struct dpll *clock = &pipe_config->dpll;
/*
@@ -1293,11 +1290,14 @@ static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config)
clock->m1 = 12;
clock->m2 = 8;
} else {
- drm_WARN(&dev_priv->drm, 1,
- "SDVO TV clock out of range: %i\n", dotclock);
+ drm_dbg_kms(&dev_priv->drm,
+ "SDVO TV clock out of range: %i\n", dotclock);
+ return -EINVAL;
}
pipe_config->clock_set = true;
+
+ return 0;
}
static bool intel_has_hdmi_sink(struct intel_sdvo_connector *intel_sdvo_connector,
@@ -1352,14 +1352,18 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
struct drm_display_mode *mode = &pipe_config->hw.mode;
+ if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) {
+ pipe_config->has_pch_encoder = true;
+ if (!intel_fdi_compute_pipe_bpp(pipe_config))
+ return -EINVAL;
+ }
+
DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
+ /* FIXME: Don't increase pipe_bpp */
pipe_config->pipe_bpp = 8*3;
pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
- if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
- pipe_config->has_pch_encoder = true;
-
/*
* We need to construct preferred input timings based on our
* output timings. To do that, we have to set the output
@@ -1367,7 +1371,9 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
* the sequence to do it. Oh well.
*/
if (IS_TV(intel_sdvo_connector)) {
- if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode))
+ if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo,
+ intel_sdvo_connector,
+ mode))
return -EINVAL;
(void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
@@ -1385,7 +1391,9 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
if (ret)
return ret;
- if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, fixed_mode))
+ if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo,
+ intel_sdvo_connector,
+ fixed_mode))
return -EINVAL;
(void) intel_sdvo_get_preferred_input_mode(intel_sdvo,
@@ -1415,8 +1423,13 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
conn_state);
/* Clock computation needs to happen after pixel multiplier. */
- if (IS_TV(intel_sdvo_connector))
- i9xx_adjust_sdvo_tv_clock(pipe_config);
+ if (IS_TV(intel_sdvo_connector)) {
+ int ret;
+
+ ret = i9xx_adjust_sdvo_tv_clock(pipe_config);
+ if (ret)
+ return ret;
+ }
if (conn_state->picture_aspect_ratio)
adjusted_mode->picture_aspect_ratio =
@@ -1521,7 +1534,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
* channel on the motherboard. In a two-input device, the first input
* will be SDVOB and the second SDVOC.
*/
- in_out.in0 = intel_sdvo->attached_output;
+ in_out.in0 = intel_sdvo_connector->output_flag;
in_out.in1 = 0;
intel_sdvo_set_value(intel_sdvo,
@@ -1530,7 +1543,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
/* Set the output timings to the screen */
if (!intel_sdvo_set_target_output(intel_sdvo,
- intel_sdvo->attached_output))
+ intel_sdvo_connector->output_flag))
return;
/* lvds has a special fixed output timing. */
@@ -1598,7 +1611,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
sdvox |= SDVO_BORDER_ENABLE;
} else {
sdvox = intel_de_read(dev_priv, intel_sdvo->sdvo_reg);
- if (intel_sdvo->port == PORT_B)
+ if (intel_sdvo->base.port == PORT_B)
sdvox &= SDVOB_PRESERVE_MASK;
else
sdvox &= SDVOC_PRESERVE_MASK;
@@ -1867,6 +1880,8 @@ static void intel_enable_sdvo(struct intel_atomic_state *state,
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
+ struct intel_sdvo_connector *intel_sdvo_connector =
+ to_intel_sdvo_connector(conn_state->connector);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
u32 temp;
bool input1, input2;
@@ -1896,7 +1911,7 @@ static void intel_enable_sdvo(struct intel_atomic_state *state,
if (0)
intel_sdvo_set_encoder_power_state(intel_sdvo,
DRM_MODE_DPMS_ON);
- intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
+ intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo_connector->output_flag);
if (pipe_config->has_audio)
intel_sdvo_enable_audio(intel_sdvo, pipe_config, conn_state);
@@ -1962,7 +1977,7 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
" device_rev_id: %d\n"
" sdvo_version_major: %d\n"
" sdvo_version_minor: %d\n"
- " sdvo_inputs_mask: %d\n"
+ " sdvo_num_inputs: %d\n"
" smooth_scaling: %d\n"
" sharp_scaling: %d\n"
" up_scaling: %d\n"
@@ -1974,7 +1989,7 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
caps->device_rev_id,
caps->sdvo_version_major,
caps->sdvo_version_minor,
- caps->sdvo_inputs_mask,
+ caps->sdvo_num_inputs,
caps->smooth_scaling,
caps->sharp_scaling,
caps->up_scaling,
@@ -2035,18 +2050,15 @@ intel_sdvo_hotplug(struct intel_encoder *encoder,
return intel_encoder_hotplug(encoder, connector);
}
-static bool
-intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
-{
- /* Is there more than one type of output? */
- return hweight16(intel_sdvo->caps.output_flags) > 1;
-}
-
static const struct drm_edid *
intel_sdvo_get_edid(struct drm_connector *connector)
{
- struct intel_sdvo *sdvo = intel_attached_sdvo(to_intel_connector(connector));
- return drm_edid_read_ddc(connector, &sdvo->ddc);
+ struct i2c_adapter *ddc = connector->ddc;
+
+ if (!ddc)
+ return NULL;
+
+ return drm_edid_read_ddc(connector, ddc);
}
/* Mac mini hack -- use the same DDC as the analog connector */
@@ -2054,43 +2066,23 @@ static const struct drm_edid *
intel_sdvo_get_analog_edid(struct drm_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->dev);
- struct i2c_adapter *i2c;
+ struct i2c_adapter *ddc;
- i2c = intel_gmbus_get_adapter(i915, i915->display.vbt.crt_ddc_pin);
+ ddc = intel_gmbus_get_adapter(i915, i915->display.vbt.crt_ddc_pin);
+ if (!ddc)
+ return NULL;
- return drm_edid_read_ddc(connector, i2c);
+ return drm_edid_read_ddc(connector, ddc);
}
static enum drm_connector_status
intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
{
- struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
enum drm_connector_status status;
const struct drm_edid *drm_edid;
drm_edid = intel_sdvo_get_edid(connector);
- if (!drm_edid && intel_sdvo_multifunc_encoder(intel_sdvo)) {
- u8 ddc, saved_ddc = intel_sdvo->ddc_bus;
-
- /*
- * Don't use the 1 as the argument of DDC bus switch to get
- * the EDID. It is used for SDVO SPD ROM.
- */
- for (ddc = intel_sdvo->ddc_bus >> 1; ddc > 1; ddc >>= 1) {
- intel_sdvo->ddc_bus = ddc;
- drm_edid = intel_sdvo_get_edid(connector);
- if (drm_edid)
- break;
- }
- /*
- * If we found the EDID on the other bus,
- * assume that is the correct DDC bus.
- */
- if (!drm_edid)
- intel_sdvo->ddc_bus = saved_ddc;
- }
-
/*
* When there is no edid and no monitor is connected with VGA
* port, try to use the CRT ddc to read the EDID for DVI-connector.
@@ -2100,10 +2092,8 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
status = connector_status_unknown;
if (drm_edid) {
- const struct edid *edid = drm_edid_raw(drm_edid);
-
/* DDC bus is shared, match EDID to connector type */
- if (edid && edid->input & DRM_EDID_INPUT_DIGITAL)
+ if (drm_edid_is_digital(drm_edid))
status = connector_status_connected;
else
status = connector_status_disconnected;
@@ -2117,8 +2107,7 @@ static bool
intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo,
const struct drm_edid *drm_edid)
{
- const struct edid *edid = drm_edid_raw(drm_edid);
- bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
+ bool monitor_is_digital = drm_edid_is_digital(drm_edid);
bool connector_is_digital = !!IS_DIGITAL(sdvo);
DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n",
@@ -2138,9 +2127,13 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
- if (!INTEL_DISPLAY_ENABLED(i915))
+ if (!intel_display_device_enabled(i915))
return connector_status_disconnected;
+ if (!intel_sdvo_set_target_output(intel_sdvo,
+ intel_sdvo_connector->output_flag))
+ return connector_status_unknown;
+
if (!intel_sdvo_get_value(intel_sdvo,
SDVO_CMD_GET_ATTACHED_DISPLAYS,
&response, 2))
@@ -2153,8 +2146,6 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
if (response == 0)
return connector_status_disconnected;
- intel_sdvo->attached_output = response;
-
if ((intel_sdvo_connector->output_flag & response) == 0)
ret = connector_status_disconnected;
else if (IS_TMDS(intel_sdvo_connector))
@@ -2282,6 +2273,8 @@ static const struct drm_display_mode sdvo_tv_modes[] = {
static int intel_sdvo_get_tv_modes(struct drm_connector *connector)
{
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
+ struct intel_sdvo_connector *intel_sdvo_connector =
+ to_intel_sdvo_connector(connector);
const struct drm_connector_state *conn_state = connector->state;
struct intel_sdvo_sdtv_resolution_request tv_res;
u32 reply = 0, format_map = 0;
@@ -2295,11 +2288,11 @@ static int intel_sdvo_get_tv_modes(struct drm_connector *connector)
* Read the list of supported input resolutions for the selected TV
* format.
*/
- format_map = 1 << conn_state->tv.mode;
+ format_map = 1 << conn_state->tv.legacy_mode;
memcpy(&tv_res, &format_map,
min(sizeof(format_map), sizeof(struct intel_sdvo_sdtv_resolution_request)));
- if (!intel_sdvo_set_target_output(intel_sdvo, intel_sdvo->attached_output))
+ if (!intel_sdvo_set_target_output(intel_sdvo, intel_sdvo_connector->output_flag))
return 0;
BUILD_BUG_ON(sizeof(tv_res) != 3);
@@ -2360,7 +2353,7 @@ intel_sdvo_connector_atomic_get_property(struct drm_connector *connector,
int i;
for (i = 0; i < intel_sdvo_connector->format_supported_num; i++)
- if (state->tv.mode == intel_sdvo_connector->tv_format_supported[i]) {
+ if (state->tv.legacy_mode == intel_sdvo_connector->tv_format_supported[i]) {
*val = i;
return 0;
@@ -2416,7 +2409,7 @@ intel_sdvo_connector_atomic_set_property(struct drm_connector *connector,
struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state(state);
if (property == intel_sdvo_connector->tv_format) {
- state->tv.mode = intel_sdvo_connector->tv_format_supported[val];
+ state->tv.legacy_mode = intel_sdvo_connector->tv_format_supported[val];
if (state->crtc) {
struct drm_crtc_state *crtc_state =
@@ -2464,31 +2457,6 @@ intel_sdvo_connector_atomic_set_property(struct drm_connector *connector,
return 0;
}
-static int
-intel_sdvo_connector_register(struct drm_connector *connector)
-{
- struct intel_sdvo *sdvo = intel_attached_sdvo(to_intel_connector(connector));
- int ret;
-
- ret = intel_connector_register(connector);
- if (ret)
- return ret;
-
- return sysfs_create_link(&connector->kdev->kobj,
- &sdvo->ddc.dev.kobj,
- sdvo->ddc.dev.kobj.name);
-}
-
-static void
-intel_sdvo_connector_unregister(struct drm_connector *connector)
-{
- struct intel_sdvo *sdvo = intel_attached_sdvo(to_intel_connector(connector));
-
- sysfs_remove_link(&connector->kdev->kobj,
- sdvo->ddc.dev.kobj.name);
- intel_connector_unregister(connector);
-}
-
static struct drm_connector_state *
intel_sdvo_connector_duplicate_state(struct drm_connector *connector)
{
@@ -2507,8 +2475,8 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.atomic_get_property = intel_sdvo_connector_atomic_get_property,
.atomic_set_property = intel_sdvo_connector_atomic_set_property,
- .late_register = intel_sdvo_connector_register,
- .early_unregister = intel_sdvo_connector_unregister,
+ .late_register = intel_connector_register,
+ .early_unregister = intel_connector_unregister,
.destroy = intel_connector_destroy,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_duplicate_state = intel_sdvo_connector_duplicate_state,
@@ -2545,29 +2513,37 @@ static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs
.atomic_check = intel_sdvo_atomic_check,
};
-static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
+static void intel_sdvo_encoder_destroy(struct drm_encoder *_encoder)
{
- struct intel_sdvo *intel_sdvo = to_sdvo(to_intel_encoder(encoder));
+ struct intel_encoder *encoder = to_intel_encoder(_encoder);
+ struct intel_sdvo *sdvo = to_sdvo(encoder);
+ int i;
- i2c_del_adapter(&intel_sdvo->ddc);
- intel_encoder_destroy(encoder);
-}
+ for (i = 0; i < ARRAY_SIZE(sdvo->ddc); i++) {
+ if (sdvo->ddc[i].ddc_bus)
+ i2c_del_adapter(&sdvo->ddc[i].ddc);
+ }
+
+ drm_encoder_cleanup(&encoder->base);
+ kfree(sdvo);
+};
static const struct drm_encoder_funcs intel_sdvo_enc_funcs = {
- .destroy = intel_sdvo_enc_destroy,
+ .destroy = intel_sdvo_encoder_destroy,
};
-static void
-intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
+static int
+intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo,
+ struct intel_sdvo_connector *connector)
{
u16 mask = 0;
- unsigned int num_bits;
+ int num_bits;
/*
* Make a mask of outputs less than or equal to our own priority in the
* list.
*/
- switch (sdvo->controlled_output) {
+ switch (connector->output_flag) {
case SDVO_OUTPUT_LVDS1:
mask |= SDVO_OUTPUT_LVDS1;
fallthrough;
@@ -2596,7 +2572,7 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
num_bits = 3;
/* Corresponds to SDVO_CONTROL_BUS_DDCx */
- sdvo->ddc_bus = 1 << num_bits;
+ return num_bits;
}
/*
@@ -2606,31 +2582,38 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
* DDC bus number assignment is in a priority order of RGB outputs, then TMDS
* outputs, then LVDS outputs.
*/
-static void
-intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
- struct intel_sdvo *sdvo)
+static struct intel_sdvo_ddc *
+intel_sdvo_select_ddc_bus(struct intel_sdvo *sdvo,
+ struct intel_sdvo_connector *connector)
{
- struct sdvo_device_mapping *mapping;
+ struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
+ const struct sdvo_device_mapping *mapping;
+ int ddc_bus;
- if (sdvo->port == PORT_B)
+ if (sdvo->base.port == PORT_B)
mapping = &dev_priv->display.vbt.sdvo_mappings[0];
else
mapping = &dev_priv->display.vbt.sdvo_mappings[1];
if (mapping->initialized)
- sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4);
+ ddc_bus = (mapping->ddc_pin & 0xf0) >> 4;
else
- intel_sdvo_guess_ddc_bus(sdvo);
+ ddc_bus = intel_sdvo_guess_ddc_bus(sdvo, connector);
+
+ if (ddc_bus < 1 || ddc_bus > 3)
+ return NULL;
+
+ return &sdvo->ddc[ddc_bus - 1];
}
static void
-intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
- struct intel_sdvo *sdvo)
+intel_sdvo_select_i2c_bus(struct intel_sdvo *sdvo)
{
- struct sdvo_device_mapping *mapping;
+ struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
+ const struct sdvo_device_mapping *mapping;
u8 pin;
- if (sdvo->port == PORT_B)
+ if (sdvo->base.port == PORT_B)
mapping = &dev_priv->display.vbt.sdvo_mappings[0];
else
mapping = &dev_priv->display.vbt.sdvo_mappings[1];
@@ -2641,6 +2624,10 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
else
pin = GMBUS_PIN_DPB;
+ drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] I2C pin %d, slave addr 0x%x\n",
+ sdvo->base.base.base.id, sdvo->base.base.name,
+ pin, sdvo->slave_addr);
+
sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin);
/*
@@ -2665,12 +2652,12 @@ intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo)
}
static u8
-intel_sdvo_get_slave_addr(struct drm_i915_private *dev_priv,
- struct intel_sdvo *sdvo)
+intel_sdvo_get_slave_addr(struct intel_sdvo *sdvo)
{
- struct sdvo_device_mapping *my_mapping, *other_mapping;
+ struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
+ const struct sdvo_device_mapping *my_mapping, *other_mapping;
- if (sdvo->port == PORT_B) {
+ if (sdvo->base.port == PORT_B) {
my_mapping = &dev_priv->display.vbt.sdvo_mappings[0];
other_mapping = &dev_priv->display.vbt.sdvo_mappings[1];
} else {
@@ -2697,28 +2684,36 @@ intel_sdvo_get_slave_addr(struct drm_i915_private *dev_priv,
* No SDVO device info is found for another DVO port,
* so use mapping assumption we had before BIOS parsing.
*/
- if (sdvo->port == PORT_B)
+ if (sdvo->base.port == PORT_B)
return 0x70;
else
return 0x72;
}
static int
+intel_sdvo_init_ddc_proxy(struct intel_sdvo_ddc *ddc,
+ struct intel_sdvo *sdvo, int bit);
+
+static int
intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
struct intel_sdvo *encoder)
{
- struct drm_connector *drm_connector;
+ struct drm_i915_private *i915 = to_i915(encoder->base.base.dev);
+ struct intel_sdvo_ddc *ddc = NULL;
int ret;
- drm_connector = &connector->base.base;
- ret = drm_connector_init(encoder->base.base.dev,
- drm_connector,
- &intel_sdvo_connector_funcs,
- connector->base.base.connector_type);
+ if (HAS_DDC(connector))
+ ddc = intel_sdvo_select_ddc_bus(encoder, connector);
+
+ ret = drm_connector_init_with_ddc(encoder->base.base.dev,
+ &connector->base.base,
+ &intel_sdvo_connector_funcs,
+ connector->base.base.connector_type,
+ ddc ? &ddc->ddc : NULL);
if (ret < 0)
return ret;
- drm_connector_helper_add(drm_connector,
+ drm_connector_helper_add(&connector->base.base,
&intel_sdvo_connector_helper_funcs);
connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
@@ -2727,6 +2722,11 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
intel_connector_attach_encoder(&connector->base, &encoder->base);
+ if (ddc)
+ drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using %s\n",
+ connector->base.base.base.id, connector->base.base.name,
+ ddc->ddc.name);
+
return 0;
}
@@ -2924,7 +2924,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, u16 type)
if (!intel_panel_preferred_fixed_mode(intel_connector)) {
mutex_lock(&i915->drm.mode_config.mutex);
- intel_ddc_get_modes(connector, &intel_sdvo->ddc);
+ intel_ddc_get_modes(connector, connector->ddc);
intel_panel_add_edid_fixed_modes(intel_connector, false);
mutex_unlock(&i915->drm.mode_config.mutex);
@@ -2988,7 +2988,6 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo)
SDVO_OUTPUT_LVDS0,
SDVO_OUTPUT_LVDS1,
};
- struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev);
u16 flags;
int i;
@@ -3000,10 +2999,6 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo)
return false;
}
- intel_sdvo->controlled_output = flags;
-
- intel_sdvo_select_ddc_bus(i915, intel_sdvo);
-
for (i = 0; i < ARRAY_SIZE(probe_order); i++) {
u16 type = flags & probe_order[i];
@@ -3071,7 +3066,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
drm_property_add_enum(intel_sdvo_connector->tv_format, i,
tv_format_names[intel_sdvo_connector->tv_format_supported[i]]);
- intel_sdvo_connector->base.base.state->tv.mode = intel_sdvo_connector->tv_format_supported[0];
+ intel_sdvo_connector->base.base.state->tv.legacy_mode = intel_sdvo_connector->tv_format_supported[0];
drm_object_attach_property(&intel_sdvo_connector->base.base.base,
intel_sdvo_connector->tv_format, 0);
return true;
@@ -3256,9 +3251,10 @@ static int intel_sdvo_ddc_proxy_xfer(struct i2c_adapter *adapter,
struct i2c_msg *msgs,
int num)
{
- struct intel_sdvo *sdvo = adapter->algo_data;
+ struct intel_sdvo_ddc *ddc = adapter->algo_data;
+ struct intel_sdvo *sdvo = ddc->sdvo;
- if (!__intel_sdvo_set_control_bus_switch(sdvo, sdvo->ddc_bus))
+ if (!__intel_sdvo_set_control_bus_switch(sdvo, 1 << ddc->ddc_bus))
return -EIO;
return sdvo->i2c->algo->master_xfer(sdvo->i2c, msgs, num);
@@ -3266,7 +3262,9 @@ static int intel_sdvo_ddc_proxy_xfer(struct i2c_adapter *adapter,
static u32 intel_sdvo_ddc_proxy_func(struct i2c_adapter *adapter)
{
- struct intel_sdvo *sdvo = adapter->algo_data;
+ struct intel_sdvo_ddc *ddc = adapter->algo_data;
+ struct intel_sdvo *sdvo = ddc->sdvo;
+
return sdvo->i2c->algo->functionality(sdvo->i2c);
}
@@ -3278,21 +3276,27 @@ static const struct i2c_algorithm intel_sdvo_ddc_proxy = {
static void proxy_lock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
- struct intel_sdvo *sdvo = adapter->algo_data;
+ struct intel_sdvo_ddc *ddc = adapter->algo_data;
+ struct intel_sdvo *sdvo = ddc->sdvo;
+
sdvo->i2c->lock_ops->lock_bus(sdvo->i2c, flags);
}
static int proxy_trylock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
- struct intel_sdvo *sdvo = adapter->algo_data;
+ struct intel_sdvo_ddc *ddc = adapter->algo_data;
+ struct intel_sdvo *sdvo = ddc->sdvo;
+
return sdvo->i2c->lock_ops->trylock_bus(sdvo->i2c, flags);
}
static void proxy_unlock_bus(struct i2c_adapter *adapter,
unsigned int flags)
{
- struct intel_sdvo *sdvo = adapter->algo_data;
+ struct intel_sdvo_ddc *ddc = adapter->algo_data;
+ struct intel_sdvo *sdvo = ddc->sdvo;
+
sdvo->i2c->lock_ops->unlock_bus(sdvo->i2c, flags);
}
@@ -3302,21 +3306,26 @@ static const struct i2c_lock_operations proxy_lock_ops = {
.unlock_bus = proxy_unlock_bus,
};
-static bool
-intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo,
- struct drm_i915_private *dev_priv)
+static int
+intel_sdvo_init_ddc_proxy(struct intel_sdvo_ddc *ddc,
+ struct intel_sdvo *sdvo, int ddc_bus)
{
+ struct drm_i915_private *dev_priv = to_i915(sdvo->base.base.dev);
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
- sdvo->ddc.owner = THIS_MODULE;
- sdvo->ddc.class = I2C_CLASS_DDC;
- snprintf(sdvo->ddc.name, I2C_NAME_SIZE, "SDVO DDC proxy");
- sdvo->ddc.dev.parent = &pdev->dev;
- sdvo->ddc.algo_data = sdvo;
- sdvo->ddc.algo = &intel_sdvo_ddc_proxy;
- sdvo->ddc.lock_ops = &proxy_lock_ops;
+ ddc->sdvo = sdvo;
+ ddc->ddc_bus = ddc_bus;
- return i2c_add_adapter(&sdvo->ddc) == 0;
+ ddc->ddc.owner = THIS_MODULE;
+ ddc->ddc.class = I2C_CLASS_DDC;
+ snprintf(ddc->ddc.name, I2C_NAME_SIZE, "SDVO %c DDC%d",
+ port_name(sdvo->base.port), ddc_bus);
+ ddc->ddc.dev.parent = &pdev->dev;
+ ddc->ddc.algo_data = ddc;
+ ddc->ddc.algo = &intel_sdvo_ddc_proxy;
+ ddc->ddc.lock_ops = &proxy_lock_ops;
+
+ return i2c_add_adapter(&ddc->ddc);
}
static bool is_sdvo_port_valid(struct drm_i915_private *dev_priv, enum port port)
@@ -3351,23 +3360,21 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
if (!intel_sdvo)
return false;
- intel_sdvo->sdvo_reg = sdvo_reg;
- intel_sdvo->port = port;
- intel_sdvo->slave_addr =
- intel_sdvo_get_slave_addr(dev_priv, intel_sdvo) >> 1;
- intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo);
- if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev_priv))
- goto err_i2c_bus;
-
/* encoder type will be decided later */
intel_encoder = &intel_sdvo->base;
intel_encoder->type = INTEL_OUTPUT_SDVO;
intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER;
intel_encoder->port = port;
+
drm_encoder_init(&dev_priv->drm, &intel_encoder->base,
&intel_sdvo_enc_funcs, 0,
"SDVO %c", port_name(port));
+ intel_sdvo->sdvo_reg = sdvo_reg;
+ intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(intel_sdvo) >> 1;
+
+ intel_sdvo_select_i2c_bus(intel_sdvo);
+
/* Read the regs to test if we can talk to the device */
for (i = 0; i < 0x40; i++) {
u8 byte;
@@ -3399,6 +3406,15 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
intel_sdvo->colorimetry_cap =
intel_sdvo_get_colorimetry_cap(intel_sdvo);
+ for (i = 0; i < ARRAY_SIZE(intel_sdvo->ddc); i++) {
+ int ret;
+
+ ret = intel_sdvo_init_ddc_proxy(&intel_sdvo->ddc[i],
+ intel_sdvo, i + 1);
+ if (ret)
+ goto err;
+ }
+
if (!intel_sdvo_output_setup(intel_sdvo)) {
drm_dbg_kms(&dev_priv->drm,
"SDVO output failed to setup on %s\n",
@@ -3412,7 +3428,7 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
* hotplug lines.
*/
if (intel_sdvo->hotplug_active) {
- if (intel_sdvo->port == PORT_B)
+ if (intel_sdvo->base.port == PORT_B)
intel_encoder->hpd_pin = HPD_SDVO_B;
else
intel_encoder->hpd_pin = HPD_SDVO_C;
@@ -3439,15 +3455,14 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
drm_dbg_kms(&dev_priv->drm, "%s device VID/DID: %02X:%02X.%02X, "
"clock range %dMHz - %dMHz, "
- "input 1: %c, input 2: %c, "
+ "num inputs: %d, "
"output 1: %c, output 2: %c\n",
SDVO_NAME(intel_sdvo),
intel_sdvo->caps.vendor_id, intel_sdvo->caps.device_id,
intel_sdvo->caps.device_rev_id,
intel_sdvo->pixel_clock_min / 1000,
intel_sdvo->pixel_clock_max / 1000,
- (intel_sdvo->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
- (intel_sdvo->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
+ intel_sdvo->caps.sdvo_num_inputs,
/* check currently supported outputs */
intel_sdvo->caps.output_flags &
(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0 |
@@ -3460,13 +3475,9 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
err_output:
intel_sdvo_output_cleanup(intel_sdvo);
-
err:
- drm_encoder_cleanup(&intel_encoder->base);
- i2c_del_adapter(&intel_sdvo->ddc);
-err_i2c_bus:
intel_sdvo_unselect_i2c_bus(intel_sdvo);
- kfree(intel_sdvo);
+ intel_sdvo_encoder_destroy(&intel_encoder->base);
return false;
}
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.h b/drivers/gpu/drm/i915/display/intel_sdvo.h
index 2868852c85..d1815b4103 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.h
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.h
@@ -14,9 +14,22 @@ struct drm_i915_private;
enum pipe;
enum port;
+#ifdef I915
bool intel_sdvo_port_enabled(struct drm_i915_private *dev_priv,
i915_reg_t sdvo_reg, enum pipe *pipe);
bool intel_sdvo_init(struct drm_i915_private *dev_priv,
i915_reg_t reg, enum port port);
+#else
+static inline bool intel_sdvo_port_enabled(struct drm_i915_private *dev_priv,
+ i915_reg_t sdvo_reg, enum pipe *pipe)
+{
+ return false;
+}
+static inline bool intel_sdvo_init(struct drm_i915_private *dev_priv,
+ i915_reg_t reg, enum port port)
+{
+ return false;
+}
+#endif
#endif /* __INTEL_SDVO_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo_regs.h b/drivers/gpu/drm/i915/display/intel_sdvo_regs.h
index 74dc6c042b..54f099abef 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_sdvo_regs.h
@@ -57,7 +57,7 @@ struct intel_sdvo_caps {
u8 device_rev_id;
u8 sdvo_version_major;
u8 sdvo_version_minor;
- unsigned int sdvo_inputs_mask:2;
+ unsigned int sdvo_num_inputs:2;
unsigned int smooth_scaling:1;
unsigned int sharp_scaling:1;
unsigned int up_scaling:1;
diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c
index 88ef56b6e0..ce5a73a4cc 100644
--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c
@@ -1993,12 +1993,13 @@ int intel_snps_phy_check_hdmi_link_rate(int clock)
}
void intel_mpllb_state_verify(struct intel_atomic_state *state,
- struct intel_crtc_state *new_crtc_state)
+ struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
- struct intel_mpllb_state mpllb_hw_state = { 0 };
- struct intel_mpllb_state *mpllb_sw_state = &new_crtc_state->mpllb_state;
- struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
+ const struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ struct intel_mpllb_state mpllb_hw_state = {};
+ const struct intel_mpllb_state *mpllb_sw_state = &new_crtc_state->mpllb_state;
struct intel_encoder *encoder;
if (!IS_DG2(i915))
diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.h b/drivers/gpu/drm/i915/display/intel_snps_phy.h
index 557ef820bc..515abf7c59 100644
--- a/drivers/gpu/drm/i915/display/intel_snps_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_snps_phy.h
@@ -10,6 +10,7 @@
struct drm_i915_private;
struct intel_atomic_state;
+struct intel_crtc;
struct intel_crtc_state;
struct intel_encoder;
struct intel_mpllb_state;
@@ -33,6 +34,6 @@ int intel_snps_phy_check_hdmi_link_rate(int clock);
void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_mpllb_state_verify(struct intel_atomic_state *state,
- struct intel_crtc_state *new_crtc_state);
+ struct intel_crtc *crtc);
#endif /* __INTEL_SNPS_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index 25034bbf14..1fb16510f7 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -45,6 +45,7 @@
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fb.h"
+#include "intel_frontbuffer.h"
#include "intel_sprite.h"
static void i9xx_plane_linear_gamma(u16 gamma[8])
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.h b/drivers/gpu/drm/i915/display/intel_sprite.h
index 91c6dca342..044a032e41 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.h
+++ b/drivers/gpu/drm/i915/display/intel_sprite.h
@@ -16,6 +16,7 @@ struct intel_crtc_state;
struct intel_plane_state;
enum pipe;
+#ifdef I915
struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,
enum pipe pipe, int plane);
int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
@@ -29,5 +30,12 @@ int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
+#else
+static inline struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,
+ int pipe, int plane)
+{
+ return NULL;
+}
+#endif
#endif /* __INTEL_SPRITE_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index cdf2455440..f64d348a96 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -260,7 +260,7 @@ assert_tc_port_power_enabled(struct intel_tc_port *tc)
!intel_display_power_is_enabled(i915, tc_port_power_domain(tc)));
}
-u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
+static u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_tc_port *tc = to_tc_port(dig_port);
@@ -290,7 +290,32 @@ u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port)
DP_PIN_ASSIGNMENT_SHIFT(tc->phy_fia_idx);
}
-static int mtl_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port)
+static int lnl_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
+ intel_wakeref_t wakeref;
+ u32 val, pin_assignment;
+
+ with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
+ val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port));
+
+ pin_assignment =
+ REG_FIELD_GET(TCSS_DDI_STATUS_PIN_ASSIGNMENT_MASK, val);
+
+ switch (pin_assignment) {
+ default:
+ MISSING_CASE(pin_assignment);
+ fallthrough;
+ case DP_PIN_ASSIGNMENT_D:
+ return 2;
+ case DP_PIN_ASSIGNMENT_C:
+ case DP_PIN_ASSIGNMENT_E:
+ return 4;
+ }
+}
+
+static int mtl_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
intel_wakeref_t wakeref;
@@ -311,23 +336,12 @@ static int mtl_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_po
}
}
-int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
+static int intel_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
- struct intel_tc_port *tc = to_tc_port(dig_port);
- enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
intel_wakeref_t wakeref;
- u32 lane_mask;
-
- if (!intel_phy_is_tc(i915, phy) || tc->mode != TC_PORT_DP_ALT)
- return 4;
-
- assert_tc_cold_blocked(tc);
-
- if (DISPLAY_VER(i915) >= 14)
- return mtl_tc_port_get_pin_assignment_mask(dig_port);
+ u32 lane_mask = 0;
- lane_mask = 0;
with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
lane_mask = intel_tc_port_get_lane_mask(dig_port);
@@ -348,6 +362,26 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
}
}
+int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_tc_port *tc = to_tc_port(dig_port);
+ enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
+
+ if (!intel_phy_is_tc(i915, phy) || tc->mode != TC_PORT_DP_ALT)
+ return 4;
+
+ assert_tc_cold_blocked(tc);
+
+ if (DISPLAY_VER(i915) >= 20)
+ return lnl_tc_port_get_max_lane_count(dig_port);
+
+ if (DISPLAY_VER(i915) >= 14)
+ return mtl_tc_port_get_max_lane_count(dig_port);
+
+ return intel_tc_port_get_max_lane_count(dig_port);
+}
+
void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
int required_lanes)
{
@@ -583,7 +617,7 @@ static bool tc_phy_verify_legacy_or_dp_alt_mode(struct intel_tc_port *tc,
struct intel_digital_port *dig_port = tc->dig_port;
int max_lanes;
- max_lanes = intel_tc_port_fia_max_lane_count(dig_port);
+ max_lanes = intel_tc_port_max_lane_count(dig_port);
if (tc->mode == TC_PORT_LEGACY) {
drm_WARN_ON(&i915->drm, max_lanes != 4);
return true;
diff --git a/drivers/gpu/drm/i915/display/intel_tc.h b/drivers/gpu/drm/i915/display/intel_tc.h
index 3b16491925..80a61e5285 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.h
+++ b/drivers/gpu/drm/i915/display/intel_tc.h
@@ -19,9 +19,8 @@ bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port);
bool intel_tc_port_connected(struct intel_encoder *encoder);
bool intel_tc_port_connected_locked(struct intel_encoder *encoder);
-u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port);
u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port);
-int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
+int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port);
void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
int required_lanes);
diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
index d84a79491d..f790fd10ba 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -949,7 +949,7 @@ intel_disable_tv(struct intel_atomic_state *state,
static const struct tv_mode *intel_tv_mode_find(const struct drm_connector_state *conn_state)
{
- int format = conn_state->tv.mode;
+ int format = conn_state->tv.legacy_mode;
return &tv_modes[format];
}
@@ -1710,7 +1710,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
break;
}
- connector->state->tv.mode = i;
+ connector->state->tv.legacy_mode = i;
}
static int
@@ -1726,7 +1726,7 @@ intel_tv_detect(struct drm_connector *connector,
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] force=%d\n",
connector->base.id, connector->name, force);
- if (!INTEL_DISPLAY_ENABLED(i915))
+ if (!intel_display_device_enabled(i915))
return connector_status_disconnected;
if (force) {
@@ -1865,7 +1865,7 @@ static int intel_tv_atomic_check(struct drm_connector *connector,
old_state = drm_atomic_get_old_connector_state(state, connector);
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
- if (old_state->tv.mode != new_state->tv.mode ||
+ if (old_state->tv.legacy_mode != new_state->tv.legacy_mode ||
old_state->tv.margins.left != new_state->tv.margins.left ||
old_state->tv.margins.right != new_state->tv.margins.right ||
old_state->tv.margins.top != new_state->tv.margins.top ||
@@ -1902,7 +1902,7 @@ static void intel_tv_add_properties(struct drm_connector *connector)
conn_state->tv.margins.right = 46;
conn_state->tv.margins.bottom = 37;
- conn_state->tv.mode = 0;
+ conn_state->tv.legacy_mode = 0;
/* Create TV properties then attach current values */
for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
@@ -1916,7 +1916,7 @@ static void intel_tv_add_properties(struct drm_connector *connector)
drm_object_attach_property(&connector->base,
i915->drm.mode_config.legacy_tv_mode_property,
- conn_state->tv.mode);
+ conn_state->tv.legacy_mode);
drm_object_attach_property(&connector->base,
i915->drm.mode_config.tv_left_margin_property,
conn_state->tv.margins.left);
diff --git a/drivers/gpu/drm/i915/display/intel_tv.h b/drivers/gpu/drm/i915/display/intel_tv.h
index 44518575ec..f08827b8bf 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.h
+++ b/drivers/gpu/drm/i915/display/intel_tv.h
@@ -8,6 +8,12 @@
struct drm_i915_private;
+#ifdef I915
void intel_tv_init(struct drm_i915_private *dev_priv);
+#else
+static inline void intel_tv_init(struct drm_i915_private *dev_priv)
+{
+}
+#endif
#endif /* __INTEL_TV_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c
index f5659ebd08..2cec2abf97 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.c
+++ b/drivers/gpu/drm/i915/display/intel_vblank.c
@@ -251,6 +251,20 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
return (position + crtc->scanline_offset) % vtotal;
}
+int intel_crtc_scanline_to_hw(struct intel_crtc *crtc, int scanline)
+{
+ const struct drm_vblank_crtc *vblank =
+ &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)];
+ const struct drm_display_mode *mode = &vblank->hwmode;
+ int vtotal;
+
+ vtotal = mode->crtc_vtotal;
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ vtotal /= 2;
+
+ return (scanline + vtotal - crtc->scanline_offset) % vtotal;
+}
+
static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc,
bool in_vblank_irq,
int *vpos, int *hpos,
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h
index 08e706b291..17636f140c 100644
--- a/drivers/gpu/drm/i915/display/intel_vblank.h
+++ b/drivers/gpu/drm/i915/display/intel_vblank.h
@@ -22,5 +22,6 @@ void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc);
void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc);
void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state,
bool vrr_enable);
+int intel_crtc_scanline_to_hw(struct intel_crtc *crtc, int scanline);
#endif /* __INTEL_VBLANK_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 9d76c27567..6757dbae9e 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -80,13 +80,19 @@ calculate_rc_params(struct drm_dsc_config *vdsc_cfg)
int bpc = vdsc_cfg->bits_per_component;
int bpp = vdsc_cfg->bits_per_pixel >> 4;
int qp_bpc_modifier = (bpc - 8) * 2;
+ int uncompressed_bpg_rate;
+ int first_line_bpg_offset;
u32 res, buf_i, bpp_i;
if (vdsc_cfg->slice_height >= 8)
- vdsc_cfg->first_line_bpg_offset =
- 12 + DIV_ROUND_UP((9 * min(34, vdsc_cfg->slice_height - 8)), 100);
+ first_line_bpg_offset =
+ 12 + (9 * min(34, vdsc_cfg->slice_height - 8)) / 100;
else
- vdsc_cfg->first_line_bpg_offset = 2 * (vdsc_cfg->slice_height - 1);
+ first_line_bpg_offset = 2 * (vdsc_cfg->slice_height - 1);
+
+ uncompressed_bpg_rate = (3 * bpc + (vdsc_cfg->convert_rgb ? 0 : 2)) * 3;
+ vdsc_cfg->first_line_bpg_offset = clamp(first_line_bpg_offset, 0,
+ uncompressed_bpg_rate - 3 * bpp);
/*
* According to DSC 1.2 spec in Section 4.1 if native_420 is set:
@@ -350,9 +356,14 @@ intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
return POWER_DOMAIN_TRANSCODER_VDSC_PW2;
}
+static int intel_dsc_get_vdsc_per_pipe(const struct intel_crtc_state *crtc_state)
+{
+ return crtc_state->dsc.dsc_split ? 2 : 1;
+}
+
int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
{
- int num_vdsc_instances = (crtc_state->dsc.dsc_split) ? 2 : 1;
+ int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state);
if (crtc_state->bigjoiner_pipes)
num_vdsc_instances *= 2;
@@ -360,6 +371,43 @@ int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
return num_vdsc_instances;
}
+static void intel_dsc_get_pps_reg(const struct intel_crtc_state *crtc_state, int pps,
+ i915_reg_t *dsc_reg, int dsc_reg_num)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+ enum pipe pipe = crtc->pipe;
+ bool pipe_dsc;
+
+ pipe_dsc = is_pipe_dsc(crtc, cpu_transcoder);
+
+ if (dsc_reg_num >= 3)
+ MISSING_CASE(dsc_reg_num);
+ if (dsc_reg_num >= 2)
+ dsc_reg[1] = pipe_dsc ? ICL_DSC1_PPS(pipe, pps) : DSCC_PPS(pps);
+ if (dsc_reg_num >= 1)
+ dsc_reg[0] = pipe_dsc ? ICL_DSC0_PPS(pipe, pps) : DSCA_PPS(pps);
+}
+
+static void intel_dsc_pps_write(const struct intel_crtc_state *crtc_state,
+ int pps, u32 pps_val)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ i915_reg_t dsc_reg[2];
+ int i, vdsc_per_pipe, dsc_reg_num;
+
+ vdsc_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
+ dsc_reg_num = min_t(int, ARRAY_SIZE(dsc_reg), vdsc_per_pipe);
+
+ drm_WARN_ON_ONCE(&i915->drm, dsc_reg_num < vdsc_per_pipe);
+
+ intel_dsc_get_pps_reg(crtc_state, pps, dsc_reg, dsc_reg_num);
+
+ for (i = 0; i < dsc_reg_num; i++)
+ intel_de_write(i915, dsc_reg[i], pps_val);
+}
+
static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -367,359 +415,119 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum pipe pipe = crtc->pipe;
- u32 pps_val = 0;
+ u32 pps_val;
u32 rc_buf_thresh_dword[4];
u32 rc_range_params_dword[8];
int i = 0;
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
+ int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
- /* Populate PICTURE_PARAMETER_SET_0 registers */
- pps_val = DSC_VER_MAJ | vdsc_cfg->dsc_version_minor <<
- DSC_VER_MIN_SHIFT |
- vdsc_cfg->bits_per_component << DSC_BPC_SHIFT |
- vdsc_cfg->line_buf_depth << DSC_LINE_BUF_DEPTH_SHIFT;
+ /* PPS 0 */
+ pps_val = DSC_PPS0_VER_MAJOR(1) |
+ DSC_PPS0_VER_MINOR(vdsc_cfg->dsc_version_minor) |
+ DSC_PPS0_BPC(vdsc_cfg->bits_per_component) |
+ DSC_PPS0_LINE_BUF_DEPTH(vdsc_cfg->line_buf_depth);
if (vdsc_cfg->dsc_version_minor == 2) {
- pps_val |= DSC_ALT_ICH_SEL;
+ pps_val |= DSC_PPS0_ALT_ICH_SEL;
if (vdsc_cfg->native_420)
- pps_val |= DSC_NATIVE_420_ENABLE;
+ pps_val |= DSC_PPS0_NATIVE_420_ENABLE;
if (vdsc_cfg->native_422)
- pps_val |= DSC_NATIVE_422_ENABLE;
+ pps_val |= DSC_PPS0_NATIVE_422_ENABLE;
}
if (vdsc_cfg->block_pred_enable)
- pps_val |= DSC_BLOCK_PREDICTION;
+ pps_val |= DSC_PPS0_BLOCK_PREDICTION;
if (vdsc_cfg->convert_rgb)
- pps_val |= DSC_COLOR_SPACE_CONVERSION;
+ pps_val |= DSC_PPS0_COLOR_SPACE_CONVERSION;
if (vdsc_cfg->simple_422)
- pps_val |= DSC_422_ENABLE;
+ pps_val |= DSC_PPS0_422_ENABLE;
if (vdsc_cfg->vbr_enable)
- pps_val |= DSC_VBR_ENABLE;
+ pps_val |= DSC_PPS0_VBR_ENABLE;
drm_dbg_kms(&dev_priv->drm, "PPS0 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_0,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_0,
- pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_0(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_0(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 0, pps_val);
- /* Populate PICTURE_PARAMETER_SET_1 registers */
- pps_val = 0;
- pps_val |= DSC_BPP(vdsc_cfg->bits_per_pixel);
+ /* PPS 1 */
+ pps_val = DSC_PPS1_BPP(vdsc_cfg->bits_per_pixel);
drm_dbg_kms(&dev_priv->drm, "PPS1 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_1,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_1,
- pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_1(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 1, pps_val);
- /* Populate PICTURE_PARAMETER_SET_2 registers */
- pps_val = 0;
- pps_val |= DSC_PIC_HEIGHT(vdsc_cfg->pic_height) |
- DSC_PIC_WIDTH(vdsc_cfg->pic_width / num_vdsc_instances);
+ /* PPS 2 */
+ pps_val = DSC_PPS2_PIC_HEIGHT(vdsc_cfg->pic_height) |
+ DSC_PPS2_PIC_WIDTH(vdsc_cfg->pic_width / num_vdsc_instances);
drm_dbg_kms(&dev_priv->drm, "PPS2 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_2,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_2,
- pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_2(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_2(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 2, pps_val);
- /* Populate PICTURE_PARAMETER_SET_3 registers */
- pps_val = 0;
- pps_val |= DSC_SLICE_HEIGHT(vdsc_cfg->slice_height) |
- DSC_SLICE_WIDTH(vdsc_cfg->slice_width);
+ /* PPS 3 */
+ pps_val = DSC_PPS3_SLICE_HEIGHT(vdsc_cfg->slice_height) |
+ DSC_PPS3_SLICE_WIDTH(vdsc_cfg->slice_width);
drm_dbg_kms(&dev_priv->drm, "PPS3 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_3,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_3,
- pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_3(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_3(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 3, pps_val);
- /* Populate PICTURE_PARAMETER_SET_4 registers */
- pps_val = 0;
- pps_val |= DSC_INITIAL_XMIT_DELAY(vdsc_cfg->initial_xmit_delay) |
- DSC_INITIAL_DEC_DELAY(vdsc_cfg->initial_dec_delay);
+ /* PPS 4 */
+ pps_val = DSC_PPS4_INITIAL_XMIT_DELAY(vdsc_cfg->initial_xmit_delay) |
+ DSC_PPS4_INITIAL_DEC_DELAY(vdsc_cfg->initial_dec_delay);
drm_dbg_kms(&dev_priv->drm, "PPS4 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_4,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_4,
- pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_4(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_4(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 4, pps_val);
- /* Populate PICTURE_PARAMETER_SET_5 registers */
- pps_val = 0;
- pps_val |= DSC_SCALE_INC_INT(vdsc_cfg->scale_increment_interval) |
- DSC_SCALE_DEC_INT(vdsc_cfg->scale_decrement_interval);
+ /* PPS 5 */
+ pps_val = DSC_PPS5_SCALE_INC_INT(vdsc_cfg->scale_increment_interval) |
+ DSC_PPS5_SCALE_DEC_INT(vdsc_cfg->scale_decrement_interval);
drm_dbg_kms(&dev_priv->drm, "PPS5 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_5,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_5,
- pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_5(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_5(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 5, pps_val);
- /* Populate PICTURE_PARAMETER_SET_6 registers */
- pps_val = 0;
- pps_val |= DSC_INITIAL_SCALE_VALUE(vdsc_cfg->initial_scale_value) |
- DSC_FIRST_LINE_BPG_OFFSET(vdsc_cfg->first_line_bpg_offset) |
- DSC_FLATNESS_MIN_QP(vdsc_cfg->flatness_min_qp) |
- DSC_FLATNESS_MAX_QP(vdsc_cfg->flatness_max_qp);
+ /* PPS 6 */
+ pps_val = DSC_PPS6_INITIAL_SCALE_VALUE(vdsc_cfg->initial_scale_value) |
+ DSC_PPS6_FIRST_LINE_BPG_OFFSET(vdsc_cfg->first_line_bpg_offset) |
+ DSC_PPS6_FLATNESS_MIN_QP(vdsc_cfg->flatness_min_qp) |
+ DSC_PPS6_FLATNESS_MAX_QP(vdsc_cfg->flatness_max_qp);
drm_dbg_kms(&dev_priv->drm, "PPS6 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_6,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_6,
- pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_6(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_6(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 6, pps_val);
- /* Populate PICTURE_PARAMETER_SET_7 registers */
- pps_val = 0;
- pps_val |= DSC_SLICE_BPG_OFFSET(vdsc_cfg->slice_bpg_offset) |
- DSC_NFL_BPG_OFFSET(vdsc_cfg->nfl_bpg_offset);
+ /* PPS 7 */
+ pps_val = DSC_PPS7_SLICE_BPG_OFFSET(vdsc_cfg->slice_bpg_offset) |
+ DSC_PPS7_NFL_BPG_OFFSET(vdsc_cfg->nfl_bpg_offset);
drm_dbg_kms(&dev_priv->drm, "PPS7 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_7,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_7,
- pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_7(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_7(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 7, pps_val);
- /* Populate PICTURE_PARAMETER_SET_8 registers */
- pps_val = 0;
- pps_val |= DSC_FINAL_OFFSET(vdsc_cfg->final_offset) |
- DSC_INITIAL_OFFSET(vdsc_cfg->initial_offset);
+ /* PPS 8 */
+ pps_val = DSC_PPS8_FINAL_OFFSET(vdsc_cfg->final_offset) |
+ DSC_PPS8_INITIAL_OFFSET(vdsc_cfg->initial_offset);
drm_dbg_kms(&dev_priv->drm, "PPS8 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_8,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_8,
- pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_8(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_8(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 8, pps_val);
- /* Populate PICTURE_PARAMETER_SET_9 registers */
- pps_val = 0;
- pps_val |= DSC_RC_MODEL_SIZE(vdsc_cfg->rc_model_size) |
- DSC_RC_EDGE_FACTOR(DSC_RC_EDGE_FACTOR_CONST);
+ /* PPS 9 */
+ pps_val = DSC_PPS9_RC_MODEL_SIZE(vdsc_cfg->rc_model_size) |
+ DSC_PPS9_RC_EDGE_FACTOR(DSC_RC_EDGE_FACTOR_CONST);
drm_dbg_kms(&dev_priv->drm, "PPS9 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_9,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv, DSCC_PICTURE_PARAMETER_SET_9,
- pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_9(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_9(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 9, pps_val);
- /* Populate PICTURE_PARAMETER_SET_10 registers */
- pps_val = 0;
- pps_val |= DSC_RC_QUANT_INC_LIMIT0(vdsc_cfg->rc_quant_incr_limit0) |
- DSC_RC_QUANT_INC_LIMIT1(vdsc_cfg->rc_quant_incr_limit1) |
- DSC_RC_TARGET_OFF_HIGH(DSC_RC_TGT_OFFSET_HI_CONST) |
- DSC_RC_TARGET_OFF_LOW(DSC_RC_TGT_OFFSET_LO_CONST);
+ /* PPS 10 */
+ pps_val = DSC_PPS10_RC_QUANT_INC_LIMIT0(vdsc_cfg->rc_quant_incr_limit0) |
+ DSC_PPS10_RC_QUANT_INC_LIMIT1(vdsc_cfg->rc_quant_incr_limit1) |
+ DSC_PPS10_RC_TARGET_OFF_HIGH(DSC_RC_TGT_OFFSET_HI_CONST) |
+ DSC_PPS10_RC_TARGET_OFF_LOW(DSC_RC_TGT_OFFSET_LO_CONST);
drm_dbg_kms(&dev_priv->drm, "PPS10 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_10,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- DSCC_PICTURE_PARAMETER_SET_10, pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_10(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_10(pipe),
- pps_val);
- }
-
- /* Populate Picture parameter set 16 */
- pps_val = 0;
- pps_val |= DSC_SLICE_CHUNK_SIZE(vdsc_cfg->slice_chunk_size) |
- DSC_SLICE_PER_LINE((vdsc_cfg->pic_width / num_vdsc_instances) /
- vdsc_cfg->slice_width) |
- DSC_SLICE_ROW_PER_FRAME(vdsc_cfg->pic_height /
- vdsc_cfg->slice_height);
+ intel_dsc_pps_write(crtc_state, 10, pps_val);
+
+ /* PPS 16 */
+ pps_val = DSC_PPS16_SLICE_CHUNK_SIZE(vdsc_cfg->slice_chunk_size) |
+ DSC_PPS16_SLICE_PER_LINE((vdsc_cfg->pic_width / num_vdsc_instances) /
+ vdsc_cfg->slice_width) |
+ DSC_PPS16_SLICE_ROW_PER_FRAME(vdsc_cfg->pic_height /
+ vdsc_cfg->slice_height);
drm_dbg_kms(&dev_priv->drm, "PPS16 = 0x%08x\n", pps_val);
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- intel_de_write(dev_priv, DSCA_PICTURE_PARAMETER_SET_16,
- pps_val);
- /*
- * If 2 VDSC instances are needed, configure PPS for second
- * VDSC
- */
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- DSCC_PICTURE_PARAMETER_SET_16, pps_val);
- } else {
- intel_de_write(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_16(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- ICL_DSC1_PICTURE_PARAMETER_SET_16(pipe),
- pps_val);
- }
+ intel_dsc_pps_write(crtc_state, 16, pps_val);
if (DISPLAY_VER(dev_priv) >= 14) {
- /* Populate PICTURE_PARAMETER_SET_17 registers */
- pps_val = 0;
- pps_val |= DSC_SL_BPG_OFFSET(vdsc_cfg->second_line_bpg_offset);
+ /* PPS 17 */
+ pps_val = DSC_PPS17_SL_BPG_OFFSET(vdsc_cfg->second_line_bpg_offset);
drm_dbg_kms(&dev_priv->drm, "PPS17 = 0x%08x\n", pps_val);
- intel_de_write(dev_priv,
- MTL_DSC0_PICTURE_PARAMETER_SET_17(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- MTL_DSC1_PICTURE_PARAMETER_SET_17(pipe),
- pps_val);
+ intel_dsc_pps_write(crtc_state, 17, pps_val);
- /* Populate PICTURE_PARAMETER_SET_18 registers */
- pps_val = 0;
- pps_val |= DSC_NSL_BPG_OFFSET(vdsc_cfg->nsl_bpg_offset) |
- DSC_SL_OFFSET_ADJ(vdsc_cfg->second_line_offset_adj);
+ /* PPS 18 */
+ pps_val = DSC_PPS18_NSL_BPG_OFFSET(vdsc_cfg->nsl_bpg_offset) |
+ DSC_PPS18_SL_OFFSET_ADJ(vdsc_cfg->second_line_offset_adj);
drm_dbg_kms(&dev_priv->drm, "PPS18 = 0x%08x\n", pps_val);
- intel_de_write(dev_priv,
- MTL_DSC0_PICTURE_PARAMETER_SET_18(pipe),
- pps_val);
- if (crtc_state->dsc.dsc_split)
- intel_de_write(dev_priv,
- MTL_DSC1_PICTURE_PARAMETER_SET_18(pipe),
- pps_val);
+ intel_dsc_pps_write(crtc_state, 18, pps_val);
}
/* Populate the RC_BUF_THRESH registers */
@@ -740,7 +548,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
rc_buf_thresh_dword[2]);
intel_de_write(dev_priv, DSCA_RC_BUF_THRESH_1_UDW,
rc_buf_thresh_dword[3]);
- if (crtc_state->dsc.dsc_split) {
+ if (vdsc_instances_per_pipe > 1) {
intel_de_write(dev_priv, DSCC_RC_BUF_THRESH_0,
rc_buf_thresh_dword[0]);
intel_de_write(dev_priv, DSCC_RC_BUF_THRESH_0_UDW,
@@ -759,7 +567,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
rc_buf_thresh_dword[2]);
intel_de_write(dev_priv, ICL_DSC0_RC_BUF_THRESH_1_UDW(pipe),
rc_buf_thresh_dword[3]);
- if (crtc_state->dsc.dsc_split) {
+ if (vdsc_instances_per_pipe > 1) {
intel_de_write(dev_priv,
ICL_DSC1_RC_BUF_THRESH_0(pipe),
rc_buf_thresh_dword[0]);
@@ -805,7 +613,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
rc_range_params_dword[6]);
intel_de_write(dev_priv, DSCA_RC_RANGE_PARAMETERS_3_UDW,
rc_range_params_dword[7]);
- if (crtc_state->dsc.dsc_split) {
+ if (vdsc_instances_per_pipe > 1) {
intel_de_write(dev_priv, DSCC_RC_RANGE_PARAMETERS_0,
rc_range_params_dword[0]);
intel_de_write(dev_priv,
@@ -848,7 +656,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
intel_de_write(dev_priv,
ICL_DSC0_RC_RANGE_PARAMETERS_3_UDW(pipe),
rc_range_params_dword[7]);
- if (crtc_state->dsc.dsc_split) {
+ if (vdsc_instances_per_pipe > 1) {
intel_de_write(dev_priv,
ICL_DSC1_RC_RANGE_PARAMETERS_0(pipe),
rc_range_params_dword[0]);
@@ -954,6 +762,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 dss_ctl1_val = 0;
u32 dss_ctl2_val = 0;
+ int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
if (!crtc_state->dsc.compression_enable)
return;
@@ -961,7 +770,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
intel_dsc_pps_configure(crtc_state);
dss_ctl2_val |= LEFT_BRANCH_VDSC_ENABLE;
- if (crtc_state->dsc.dsc_split) {
+ if (vdsc_instances_per_pipe > 1) {
dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
dss_ctl1_val |= JOINER_ENABLE;
}
@@ -987,16 +796,168 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
}
}
+static u32 intel_dsc_pps_read(struct intel_crtc_state *crtc_state, int pps,
+ bool *check_equal)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ i915_reg_t dsc_reg[2];
+ int i, vdsc_per_pipe, dsc_reg_num;
+ u32 val = 0;
+
+ vdsc_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
+ dsc_reg_num = min_t(int, ARRAY_SIZE(dsc_reg), vdsc_per_pipe);
+
+ drm_WARN_ON_ONCE(&i915->drm, dsc_reg_num < vdsc_per_pipe);
+
+ intel_dsc_get_pps_reg(crtc_state, pps, dsc_reg, dsc_reg_num);
+
+ if (check_equal)
+ *check_equal = true;
+
+ for (i = 0; i < dsc_reg_num; i++) {
+ u32 tmp;
+
+ tmp = intel_de_read(i915, dsc_reg[i]);
+
+ if (i == 0) {
+ val = tmp;
+ } else if (check_equal && tmp != val) {
+ *check_equal = false;
+ break;
+ } else if (!check_equal) {
+ break;
+ }
+ }
+
+ return val;
+}
+
+static u32 intel_dsc_pps_read_and_verify(struct intel_crtc_state *crtc_state, int pps)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ u32 val;
+ bool all_equal;
+
+ val = intel_dsc_pps_read(crtc_state, pps, &all_equal);
+ drm_WARN_ON(&i915->drm, !all_equal);
+
+ return val;
+}
+
+static void intel_dsc_get_pps_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 *i915 = to_i915(crtc->base.dev);
+ int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
+ u32 pps_temp;
+
+ /* PPS 0 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 0);
+
+ vdsc_cfg->bits_per_component = REG_FIELD_GET(DSC_PPS0_BPC_MASK, pps_temp);
+ vdsc_cfg->line_buf_depth = REG_FIELD_GET(DSC_PPS0_LINE_BUF_DEPTH_MASK, pps_temp);
+ vdsc_cfg->block_pred_enable = pps_temp & DSC_PPS0_BLOCK_PREDICTION;
+ vdsc_cfg->convert_rgb = pps_temp & DSC_PPS0_COLOR_SPACE_CONVERSION;
+ vdsc_cfg->simple_422 = pps_temp & DSC_PPS0_422_ENABLE;
+ vdsc_cfg->native_422 = pps_temp & DSC_PPS0_NATIVE_422_ENABLE;
+ vdsc_cfg->native_420 = pps_temp & DSC_PPS0_NATIVE_420_ENABLE;
+ vdsc_cfg->vbr_enable = pps_temp & DSC_PPS0_VBR_ENABLE;
+
+ /* PPS 1 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 1);
+
+ vdsc_cfg->bits_per_pixel = REG_FIELD_GET(DSC_PPS1_BPP_MASK, pps_temp);
+
+ if (vdsc_cfg->native_420)
+ vdsc_cfg->bits_per_pixel >>= 1;
+
+ crtc_state->dsc.compressed_bpp = vdsc_cfg->bits_per_pixel >> 4;
+
+ /* PPS 2 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 2);
+
+ vdsc_cfg->pic_width = REG_FIELD_GET(DSC_PPS2_PIC_WIDTH_MASK, pps_temp) * num_vdsc_instances;
+ vdsc_cfg->pic_height = REG_FIELD_GET(DSC_PPS2_PIC_HEIGHT_MASK, pps_temp);
+
+ /* PPS 3 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 3);
+
+ vdsc_cfg->slice_width = REG_FIELD_GET(DSC_PPS3_SLICE_WIDTH_MASK, pps_temp);
+ vdsc_cfg->slice_height = REG_FIELD_GET(DSC_PPS3_SLICE_HEIGHT_MASK, pps_temp);
+
+ /* PPS 4 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 4);
+
+ vdsc_cfg->initial_dec_delay = REG_FIELD_GET(DSC_PPS4_INITIAL_DEC_DELAY_MASK, pps_temp);
+ vdsc_cfg->initial_xmit_delay = REG_FIELD_GET(DSC_PPS4_INITIAL_XMIT_DELAY_MASK, pps_temp);
+
+ /* PPS 5 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 5);
+
+ vdsc_cfg->scale_decrement_interval = REG_FIELD_GET(DSC_PPS5_SCALE_DEC_INT_MASK, pps_temp);
+ vdsc_cfg->scale_increment_interval = REG_FIELD_GET(DSC_PPS5_SCALE_INC_INT_MASK, pps_temp);
+
+ /* PPS 6 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 6);
+
+ vdsc_cfg->initial_scale_value = REG_FIELD_GET(DSC_PPS6_INITIAL_SCALE_VALUE_MASK, pps_temp);
+ vdsc_cfg->first_line_bpg_offset = REG_FIELD_GET(DSC_PPS6_FIRST_LINE_BPG_OFFSET_MASK, pps_temp);
+ vdsc_cfg->flatness_min_qp = REG_FIELD_GET(DSC_PPS6_FLATNESS_MIN_QP_MASK, pps_temp);
+ vdsc_cfg->flatness_max_qp = REG_FIELD_GET(DSC_PPS6_FLATNESS_MAX_QP_MASK, pps_temp);
+
+ /* PPS 7 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 7);
+
+ vdsc_cfg->nfl_bpg_offset = REG_FIELD_GET(DSC_PPS7_NFL_BPG_OFFSET_MASK, pps_temp);
+ vdsc_cfg->slice_bpg_offset = REG_FIELD_GET(DSC_PPS7_SLICE_BPG_OFFSET_MASK, pps_temp);
+
+ /* PPS 8 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 8);
+
+ vdsc_cfg->initial_offset = REG_FIELD_GET(DSC_PPS8_INITIAL_OFFSET_MASK, pps_temp);
+ vdsc_cfg->final_offset = REG_FIELD_GET(DSC_PPS8_FINAL_OFFSET_MASK, pps_temp);
+
+ /* PPS 9 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 9);
+
+ vdsc_cfg->rc_model_size = REG_FIELD_GET(DSC_PPS9_RC_MODEL_SIZE_MASK, pps_temp);
+
+ /* PPS 10 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 10);
+
+ vdsc_cfg->rc_quant_incr_limit0 = REG_FIELD_GET(DSC_PPS10_RC_QUANT_INC_LIMIT0_MASK, pps_temp);
+ vdsc_cfg->rc_quant_incr_limit1 = REG_FIELD_GET(DSC_PPS10_RC_QUANT_INC_LIMIT1_MASK, pps_temp);
+
+ /* PPS 16 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 16);
+
+ vdsc_cfg->slice_chunk_size = REG_FIELD_GET(DSC_PPS16_SLICE_CHUNK_SIZE_MASK, pps_temp);
+
+ if (DISPLAY_VER(i915) >= 14) {
+ /* PPS 17 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 17);
+
+ vdsc_cfg->second_line_bpg_offset = REG_FIELD_GET(DSC_PPS17_SL_BPG_OFFSET_MASK, pps_temp);
+
+ /* PPS 18 */
+ pps_temp = intel_dsc_pps_read_and_verify(crtc_state, 18);
+
+ vdsc_cfg->nsl_bpg_offset = REG_FIELD_GET(DSC_PPS18_NSL_BPG_OFFSET_MASK, pps_temp);
+ vdsc_cfg->second_line_offset_adj = REG_FIELD_GET(DSC_PPS18_SL_OFFSET_ADJ_MASK, pps_temp);
+ }
+}
+
void intel_dsc_get_config(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 drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
- enum pipe pipe = crtc->pipe;
enum intel_display_power_domain power_domain;
intel_wakeref_t wakeref;
- u32 dss_ctl1, dss_ctl2, pps0 = 0, pps1 = 0;
+ u32 dss_ctl1, dss_ctl2;
if (!intel_dsc_source_support(crtc_state))
return;
@@ -1017,24 +978,7 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
crtc_state->dsc.dsc_split = (dss_ctl2 & RIGHT_BRANCH_VDSC_ENABLE) &&
(dss_ctl1 & JOINER_ENABLE);
- /* FIXME: add more state readout as needed */
-
- /* PPS0 & PPS1 */
- if (!is_pipe_dsc(crtc, cpu_transcoder)) {
- pps1 = intel_de_read(dev_priv, DSCA_PICTURE_PARAMETER_SET_1);
- } else {
- pps0 = intel_de_read(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_0(pipe));
- pps1 = intel_de_read(dev_priv,
- ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe));
- }
-
- vdsc_cfg->bits_per_pixel = pps1;
-
- if (pps0 & DSC_NATIVE_420_ENABLE)
- vdsc_cfg->bits_per_pixel >>= 1;
-
- crtc_state->dsc.compressed_bpp = vdsc_cfg->bits_per_pixel >> 4;
+ intel_dsc_get_pps_config(crtc_state);
out:
intel_display_power_put(dev_priv, power_domain, wakeref);
}
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
index b71f00b5c7..8b21dc8e26 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h
@@ -46,35 +46,13 @@
_ICL_PIPE_DSS_CTL2_PB, \
_ICL_PIPE_DSS_CTL2_PC)
-/* MTL Display Stream Compression registers */
-#define _MTL_DSC0_PICTURE_PARAMETER_SET_17_PB 0x782B4
-#define _MTL_DSC1_PICTURE_PARAMETER_SET_17_PB 0x783B4
-#define _MTL_DSC0_PICTURE_PARAMETER_SET_17_PC 0x784B4
-#define _MTL_DSC1_PICTURE_PARAMETER_SET_17_PC 0x785B4
-#define MTL_DSC0_PICTURE_PARAMETER_SET_17(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _MTL_DSC0_PICTURE_PARAMETER_SET_17_PB, \
- _MTL_DSC0_PICTURE_PARAMETER_SET_17_PC)
-#define MTL_DSC1_PICTURE_PARAMETER_SET_17(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _MTL_DSC1_PICTURE_PARAMETER_SET_17_PB, \
- _MTL_DSC1_PICTURE_PARAMETER_SET_17_PC)
-#define DSC_SL_BPG_OFFSET(offset) ((offset) << 27)
-
-#define _MTL_DSC0_PICTURE_PARAMETER_SET_18_PB 0x782B8
-#define _MTL_DSC1_PICTURE_PARAMETER_SET_18_PB 0x783B8
-#define _MTL_DSC0_PICTURE_PARAMETER_SET_18_PC 0x784B8
-#define _MTL_DSC1_PICTURE_PARAMETER_SET_18_PC 0x785B8
-#define MTL_DSC0_PICTURE_PARAMETER_SET_18(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _MTL_DSC0_PICTURE_PARAMETER_SET_18_PB, \
- _MTL_DSC0_PICTURE_PARAMETER_SET_18_PC)
-#define MTL_DSC1_PICTURE_PARAMETER_SET_18(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _MTL_DSC1_PICTURE_PARAMETER_SET_18_PB, \
- _MTL_DSC1_PICTURE_PARAMETER_SET_18_PC)
-#define DSC_NSL_BPG_OFFSET(offset) ((offset) << 16)
-#define DSC_SL_OFFSET_ADJ(offset) ((offset) << 0)
-
/* Icelake Display Stream Compression Registers */
#define DSCA_PICTURE_PARAMETER_SET_0 _MMIO(0x6B200)
#define DSCC_PICTURE_PARAMETER_SET_0 _MMIO(0x6BA00)
+#define _DSCA_PPS_0 0x6B200
+#define _DSCC_PPS_0 0x6BA00
+#define DSCA_PPS(pps) _MMIO(_DSCA_PPS_0 + ((pps) < 12 ? (pps) : (pps) + 12) * 4)
+#define DSCC_PPS(pps) _MMIO(_DSCC_PPS_0 + ((pps) < 12 ? (pps) : (pps) + 12) * 4)
#define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PB 0x78270
#define _ICL_DSC1_PICTURE_PARAMETER_SET_0_PB 0x78370
#define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PC 0x78470
@@ -85,251 +63,128 @@
#define ICL_DSC1_PICTURE_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
_ICL_DSC1_PICTURE_PARAMETER_SET_0_PB, \
_ICL_DSC1_PICTURE_PARAMETER_SET_0_PC)
-#define DSC_NATIVE_422_ENABLE BIT(23)
-#define DSC_NATIVE_420_ENABLE BIT(22)
-#define DSC_ALT_ICH_SEL (1 << 20)
-#define DSC_VBR_ENABLE (1 << 19)
-#define DSC_422_ENABLE (1 << 18)
-#define DSC_COLOR_SPACE_CONVERSION (1 << 17)
-#define DSC_BLOCK_PREDICTION (1 << 16)
-#define DSC_LINE_BUF_DEPTH_SHIFT 12
-#define DSC_BPC_SHIFT 8
-#define DSC_VER_MIN_SHIFT 4
-#define DSC_VER_MAJ (0x1 << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_1 _MMIO(0x6B204)
-#define DSCC_PICTURE_PARAMETER_SET_1 _MMIO(0x6BA04)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_1_PB 0x78274
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_1_PB 0x78374
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_1_PC 0x78474
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_1_PC 0x78574
-#define ICL_DSC0_PICTURE_PARAMETER_SET_1(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_1_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_1_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_1(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_1_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_1_PC)
-#define DSC_BPP(bpp) ((bpp) << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_2 _MMIO(0x6B208)
-#define DSCC_PICTURE_PARAMETER_SET_2 _MMIO(0x6BA08)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_2_PB 0x78278
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_2_PB 0x78378
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_2_PC 0x78478
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_2_PC 0x78578
-#define ICL_DSC0_PICTURE_PARAMETER_SET_2(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_2_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_2_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_2(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_2_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_2_PC)
-#define DSC_PIC_WIDTH(pic_width) ((pic_width) << 16)
-#define DSC_PIC_HEIGHT(pic_height) ((pic_height) << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_3 _MMIO(0x6B20C)
-#define DSCC_PICTURE_PARAMETER_SET_3 _MMIO(0x6BA0C)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_3_PB 0x7827C
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_3_PB 0x7837C
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_3_PC 0x7847C
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_3_PC 0x7857C
-#define ICL_DSC0_PICTURE_PARAMETER_SET_3(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_3_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_3_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_3(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_3_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_3_PC)
-#define DSC_SLICE_WIDTH(slice_width) ((slice_width) << 16)
-#define DSC_SLICE_HEIGHT(slice_height) ((slice_height) << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_4 _MMIO(0x6B210)
-#define DSCC_PICTURE_PARAMETER_SET_4 _MMIO(0x6BA10)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_4_PB 0x78280
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_4_PB 0x78380
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_4_PC 0x78480
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_4_PC 0x78580
-#define ICL_DSC0_PICTURE_PARAMETER_SET_4(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_4_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_4_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_4(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_4_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_4_PC)
-#define DSC_INITIAL_DEC_DELAY(dec_delay) ((dec_delay) << 16)
-#define DSC_INITIAL_XMIT_DELAY(xmit_delay) ((xmit_delay) << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_5 _MMIO(0x6B214)
-#define DSCC_PICTURE_PARAMETER_SET_5 _MMIO(0x6BA14)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_5_PB 0x78284
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_5_PB 0x78384
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_5_PC 0x78484
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_5_PC 0x78584
-#define ICL_DSC0_PICTURE_PARAMETER_SET_5(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_5_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_5_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_5(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_5_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_5_PC)
-#define DSC_SCALE_DEC_INT(scale_dec) ((scale_dec) << 16)
-#define DSC_SCALE_INC_INT(scale_inc) ((scale_inc) << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_6 _MMIO(0x6B218)
-#define DSCC_PICTURE_PARAMETER_SET_6 _MMIO(0x6BA18)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_6_PB 0x78288
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_6_PB 0x78388
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_6_PC 0x78488
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_6_PC 0x78588
-#define ICL_DSC0_PICTURE_PARAMETER_SET_6(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_6_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_6_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_6(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_6_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_6_PC)
-#define DSC_FLATNESS_MAX_QP(max_qp) ((max_qp) << 24)
-#define DSC_FLATNESS_MIN_QP(min_qp) ((min_qp) << 16)
-#define DSC_FIRST_LINE_BPG_OFFSET(offset) ((offset) << 8)
-#define DSC_INITIAL_SCALE_VALUE(value) ((value) << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_7 _MMIO(0x6B21C)
-#define DSCC_PICTURE_PARAMETER_SET_7 _MMIO(0x6BA1C)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_7_PB 0x7828C
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_7_PB 0x7838C
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_7_PC 0x7848C
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_7_PC 0x7858C
-#define ICL_DSC0_PICTURE_PARAMETER_SET_7(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_7_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_7_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_7(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_7_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_7_PC)
-#define DSC_NFL_BPG_OFFSET(bpg_offset) ((bpg_offset) << 16)
-#define DSC_SLICE_BPG_OFFSET(bpg_offset) ((bpg_offset) << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_8 _MMIO(0x6B220)
-#define DSCC_PICTURE_PARAMETER_SET_8 _MMIO(0x6BA20)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_8_PB 0x78290
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_8_PB 0x78390
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_8_PC 0x78490
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_8_PC 0x78590
-#define ICL_DSC0_PICTURE_PARAMETER_SET_8(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_8_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_8_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_8(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_8_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_8_PC)
-#define DSC_INITIAL_OFFSET(initial_offset) ((initial_offset) << 16)
-#define DSC_FINAL_OFFSET(final_offset) ((final_offset) << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_9 _MMIO(0x6B224)
-#define DSCC_PICTURE_PARAMETER_SET_9 _MMIO(0x6BA24)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_9_PB 0x78294
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_9_PB 0x78394
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_9_PC 0x78494
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_9_PC 0x78594
-#define ICL_DSC0_PICTURE_PARAMETER_SET_9(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_9_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_9_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_9(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_9_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_9_PC)
-#define DSC_RC_EDGE_FACTOR(rc_edge_fact) ((rc_edge_fact) << 16)
-#define DSC_RC_MODEL_SIZE(rc_model_size) ((rc_model_size) << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_10 _MMIO(0x6B228)
-#define DSCC_PICTURE_PARAMETER_SET_10 _MMIO(0x6BA28)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_10_PB 0x78298
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_10_PB 0x78398
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_10_PC 0x78498
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_10_PC 0x78598
-#define ICL_DSC0_PICTURE_PARAMETER_SET_10(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_10_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_10_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_10(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_10_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_10_PC)
-#define DSC_RC_TARGET_OFF_LOW(rc_tgt_off_low) ((rc_tgt_off_low) << 20)
-#define DSC_RC_TARGET_OFF_HIGH(rc_tgt_off_high) ((rc_tgt_off_high) << 16)
-#define DSC_RC_QUANT_INC_LIMIT1(lim) ((lim) << 8)
-#define DSC_RC_QUANT_INC_LIMIT0(lim) ((lim) << 0)
-
-#define DSCA_PICTURE_PARAMETER_SET_11 _MMIO(0x6B22C)
-#define DSCC_PICTURE_PARAMETER_SET_11 _MMIO(0x6BA2C)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_11_PB 0x7829C
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_11_PB 0x7839C
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_11_PC 0x7849C
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_11_PC 0x7859C
-#define ICL_DSC0_PICTURE_PARAMETER_SET_11(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_11_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_11_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_11(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_11_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_11_PC)
-
-#define DSCA_PICTURE_PARAMETER_SET_12 _MMIO(0x6B260)
-#define DSCC_PICTURE_PARAMETER_SET_12 _MMIO(0x6BA60)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_12_PB 0x782A0
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_12_PB 0x783A0
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_12_PC 0x784A0
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_12_PC 0x785A0
-#define ICL_DSC0_PICTURE_PARAMETER_SET_12(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_12_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_12_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_12(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_12_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_12_PC)
-
-#define DSCA_PICTURE_PARAMETER_SET_13 _MMIO(0x6B264)
-#define DSCC_PICTURE_PARAMETER_SET_13 _MMIO(0x6BA64)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_13_PB 0x782A4
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_13_PB 0x783A4
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_13_PC 0x784A4
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_13_PC 0x785A4
-#define ICL_DSC0_PICTURE_PARAMETER_SET_13(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_13_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_13_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_13(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_13_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_13_PC)
-
-#define DSCA_PICTURE_PARAMETER_SET_14 _MMIO(0x6B268)
-#define DSCC_PICTURE_PARAMETER_SET_14 _MMIO(0x6BA68)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_14_PB 0x782A8
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_14_PB 0x783A8
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_14_PC 0x784A8
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_14_PC 0x785A8
-#define ICL_DSC0_PICTURE_PARAMETER_SET_14(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_14_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_14_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_14(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_14_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_14_PC)
-
-#define DSCA_PICTURE_PARAMETER_SET_15 _MMIO(0x6B26C)
-#define DSCC_PICTURE_PARAMETER_SET_15 _MMIO(0x6BA6C)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_15_PB 0x782AC
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_15_PB 0x783AC
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_15_PC 0x784AC
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_15_PC 0x785AC
-#define ICL_DSC0_PICTURE_PARAMETER_SET_15(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_15_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_15_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_15(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_15_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_15_PC)
-
-#define DSCA_PICTURE_PARAMETER_SET_16 _MMIO(0x6B270)
-#define DSCC_PICTURE_PARAMETER_SET_16 _MMIO(0x6BA70)
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_16_PB 0x782B0
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_16_PB 0x783B0
-#define _ICL_DSC0_PICTURE_PARAMETER_SET_16_PC 0x784B0
-#define _ICL_DSC1_PICTURE_PARAMETER_SET_16_PC 0x785B0
-#define ICL_DSC0_PICTURE_PARAMETER_SET_16(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_16_PB, \
- _ICL_DSC0_PICTURE_PARAMETER_SET_16_PC)
-#define ICL_DSC1_PICTURE_PARAMETER_SET_16(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_16_PB, \
- _ICL_DSC1_PICTURE_PARAMETER_SET_16_PC)
-#define DSC_SLICE_ROW_PER_FRAME(slice_row_per_frame) ((slice_row_per_frame) << 20)
-#define DSC_SLICE_PER_LINE(slice_per_line) ((slice_per_line) << 16)
-#define DSC_SLICE_CHUNK_SIZE(slice_chunk_size) ((slice_chunk_size) << 0)
+#define _ICL_DSC0_PPS_0(pipe) _PICK_EVEN((pipe) - PIPE_B, \
+ _ICL_DSC0_PICTURE_PARAMETER_SET_0_PB, \
+ _ICL_DSC0_PICTURE_PARAMETER_SET_0_PC)
+#define _ICL_DSC1_PPS_0(pipe) _PICK_EVEN((pipe) - PIPE_B, \
+ _ICL_DSC1_PICTURE_PARAMETER_SET_0_PB, \
+ _ICL_DSC1_PICTURE_PARAMETER_SET_0_PC)
+#define ICL_DSC0_PPS(pipe, pps) _MMIO(_ICL_DSC0_PPS_0(pipe) + ((pps) * 4))
+#define ICL_DSC1_PPS(pipe, pps) _MMIO(_ICL_DSC1_PPS_0(pipe) + ((pps) * 4))
+
+/* PPS 0 */
+#define DSC_PPS0_NATIVE_422_ENABLE REG_BIT(23)
+#define DSC_PPS0_NATIVE_420_ENABLE REG_BIT(22)
+#define DSC_PPS0_ALT_ICH_SEL REG_BIT(20)
+#define DSC_PPS0_VBR_ENABLE REG_BIT(19)
+#define DSC_PPS0_422_ENABLE REG_BIT(18)
+#define DSC_PPS0_COLOR_SPACE_CONVERSION REG_BIT(17)
+#define DSC_PPS0_BLOCK_PREDICTION REG_BIT(16)
+#define DSC_PPS0_LINE_BUF_DEPTH_MASK REG_GENMASK(15, 12)
+#define DSC_PPS0_LINE_BUF_DEPTH(depth) REG_FIELD_PREP(DSC_PPS0_LINE_BUF_DEPTH_MASK, depth)
+#define DSC_PPS0_BPC_MASK REG_GENMASK(11, 8)
+#define DSC_PPS0_BPC(bpc) REG_FIELD_PREP(DSC_PPS0_BPC_MASK, bpc)
+#define DSC_PPS0_VER_MINOR_MASK REG_GENMASK(7, 4)
+#define DSC_PPS0_VER_MINOR(minor) REG_FIELD_PREP(DSC_PPS0_VER_MINOR_MASK, minor)
+#define DSC_PPS0_VER_MAJOR_MASK REG_GENMASK(3, 0)
+#define DSC_PPS0_VER_MAJOR(major) REG_FIELD_PREP(DSC_PPS0_VER_MAJOR_MASK, major)
+
+/* PPS 1 */
+#define DSC_PPS1_BPP_MASK REG_GENMASK(9, 0)
+#define DSC_PPS1_BPP(bpp) REG_FIELD_PREP(DSC_PPS1_BPP_MASK, bpp)
+
+/* PPS 2 */
+#define DSC_PPS2_PIC_WIDTH_MASK REG_GENMASK(31, 16)
+#define DSC_PPS2_PIC_HEIGHT_MASK REG_GENMASK(15, 0)
+#define DSC_PPS2_PIC_WIDTH(pic_width) REG_FIELD_PREP(DSC_PPS2_PIC_WIDTH_MASK, pic_width)
+#define DSC_PPS2_PIC_HEIGHT(pic_height) REG_FIELD_PREP(DSC_PPS2_PIC_HEIGHT_MASK, pic_height)
+
+/* PPS 3 */
+#define DSC_PPS3_SLICE_WIDTH_MASK REG_GENMASK(31, 16)
+#define DSC_PPS3_SLICE_HEIGHT_MASK REG_GENMASK(15, 0)
+#define DSC_PPS3_SLICE_WIDTH(slice_width) REG_FIELD_PREP(DSC_PPS3_SLICE_WIDTH_MASK, slice_width)
+#define DSC_PPS3_SLICE_HEIGHT(slice_height) REG_FIELD_PREP(DSC_PPS3_SLICE_HEIGHT_MASK, slice_height)
+
+/* PPS 4 */
+#define DSC_PPS4_INITIAL_DEC_DELAY_MASK REG_GENMASK(31, 16)
+#define DSC_PPS4_INITIAL_XMIT_DELAY_MASK REG_GENMASK(9, 0)
+#define DSC_PPS4_INITIAL_DEC_DELAY(dec_delay) REG_FIELD_PREP(DSC_PPS4_INITIAL_DEC_DELAY_MASK, \
+ dec_delay)
+#define DSC_PPS4_INITIAL_XMIT_DELAY(xmit_delay) REG_FIELD_PREP(DSC_PPS4_INITIAL_XMIT_DELAY_MASK, \
+ xmit_delay)
+
+/* PPS 5 */
+#define DSC_PPS5_SCALE_DEC_INT_MASK REG_GENMASK(27, 16)
+#define DSC_PPS5_SCALE_INC_INT_MASK REG_GENMASK(15, 0)
+#define DSC_PPS5_SCALE_DEC_INT(scale_dec) REG_FIELD_PREP(DSC_PPS5_SCALE_DEC_INT_MASK, scale_dec)
+#define DSC_PPS5_SCALE_INC_INT(scale_inc) REG_FIELD_PREP(DSC_PPS5_SCALE_INC_INT_MASK, scale_inc)
+
+/* PPS 6 */
+#define DSC_PPS6_FLATNESS_MAX_QP_MASK REG_GENMASK(28, 24)
+#define DSC_PPS6_FLATNESS_MIN_QP_MASK REG_GENMASK(20, 16)
+#define DSC_PPS6_FIRST_LINE_BPG_OFFSET_MASK REG_GENMASK(12, 8)
+#define DSC_PPS6_INITIAL_SCALE_VALUE_MASK REG_GENMASK(5, 0)
+#define DSC_PPS6_FLATNESS_MAX_QP(max_qp) REG_FIELD_PREP(DSC_PPS6_FLATNESS_MAX_QP_MASK, max_qp)
+#define DSC_PPS6_FLATNESS_MIN_QP(min_qp) REG_FIELD_PREP(DSC_PPS6_FLATNESS_MIN_QP_MASK, min_qp)
+#define DSC_PPS6_FIRST_LINE_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS6_FIRST_LINE_BPG_OFFSET_MASK, \
+ offset)
+#define DSC_PPS6_INITIAL_SCALE_VALUE(value) REG_FIELD_PREP(DSC_PPS6_INITIAL_SCALE_VALUE_MASK, \
+ value)
+
+/* PPS 7 */
+#define DSC_PPS7_NFL_BPG_OFFSET_MASK REG_GENMASK(31, 16)
+#define DSC_PPS7_SLICE_BPG_OFFSET_MASK REG_GENMASK(15, 0)
+#define DSC_PPS7_NFL_BPG_OFFSET(bpg_offset) REG_FIELD_PREP(DSC_PPS7_NFL_BPG_OFFSET_MASK, bpg_offset)
+#define DSC_PPS7_SLICE_BPG_OFFSET(bpg_offset) REG_FIELD_PREP(DSC_PPS7_SLICE_BPG_OFFSET_MASK, \
+ bpg_offset)
+/* PPS 8 */
+#define DSC_PPS8_INITIAL_OFFSET_MASK REG_GENMASK(31, 16)
+#define DSC_PPS8_FINAL_OFFSET_MASK REG_GENMASK(15, 0)
+#define DSC_PPS8_INITIAL_OFFSET(initial_offset) REG_FIELD_PREP(DSC_PPS8_INITIAL_OFFSET_MASK, \
+ initial_offset)
+#define DSC_PPS8_FINAL_OFFSET(final_offset) REG_FIELD_PREP(DSC_PPS8_FINAL_OFFSET_MASK, \
+ final_offset)
+
+/* PPS 9 */
+#define DSC_PPS9_RC_EDGE_FACTOR_MASK REG_GENMASK(19, 16)
+#define DSC_PPS9_RC_MODEL_SIZE_MASK REG_GENMASK(15, 0)
+#define DSC_PPS9_RC_EDGE_FACTOR(rc_edge_fact) REG_FIELD_PREP(DSC_PPS9_RC_EDGE_FACTOR_MASK, \
+ rc_edge_fact)
+#define DSC_PPS9_RC_MODEL_SIZE(rc_model_size) REG_FIELD_PREP(DSC_PPS9_RC_MODEL_SIZE_MASK, \
+ rc_model_size)
+
+/* PPS 10 */
+#define DSC_PPS10_RC_TGT_OFF_LOW_MASK REG_GENMASK(23, 20)
+#define DSC_PPS10_RC_TGT_OFF_HIGH_MASK REG_GENMASK(19, 16)
+#define DSC_PPS10_RC_QUANT_INC_LIMIT1_MASK REG_GENMASK(12, 8)
+#define DSC_PPS10_RC_QUANT_INC_LIMIT0_MASK REG_GENMASK(4, 0)
+#define DSC_PPS10_RC_TARGET_OFF_LOW(rc_tgt_off_low) REG_FIELD_PREP(DSC_PPS10_RC_TGT_OFF_LOW_MASK, \
+ rc_tgt_off_low)
+#define DSC_PPS10_RC_TARGET_OFF_HIGH(rc_tgt_off_high) REG_FIELD_PREP(DSC_PPS10_RC_TGT_OFF_HIGH_MASK, \
+ rc_tgt_off_high)
+#define DSC_PPS10_RC_QUANT_INC_LIMIT1(lim) REG_FIELD_PREP(DSC_PPS10_RC_QUANT_INC_LIMIT1_MASK, lim)
+#define DSC_PPS10_RC_QUANT_INC_LIMIT0(lim) REG_FIELD_PREP(DSC_PPS10_RC_QUANT_INC_LIMIT0_MASK, lim)
+
+/* PPS 16 */
+#define DSC_PPS16_SLICE_ROW_PR_FRME_MASK REG_GENMASK(31, 20)
+#define DSC_PPS16_SLICE_PER_LINE_MASK REG_GENMASK(18, 16)
+#define DSC_PPS16_SLICE_CHUNK_SIZE_MASK REG_GENMASK(15, 0)
+#define DSC_PPS16_SLICE_ROW_PER_FRAME(slice_row_per_frame) REG_FIELD_PREP(DSC_PPS16_SLICE_ROW_PR_FRME_MASK, \
+ slice_row_per_frame)
+#define DSC_PPS16_SLICE_PER_LINE(slice_per_line) REG_FIELD_PREP(DSC_PPS16_SLICE_PER_LINE_MASK, \
+ slice_per_line)
+#define DSC_PPS16_SLICE_CHUNK_SIZE(slice_chunk_size) REG_FIELD_PREP(DSC_PPS16_SLICE_CHUNK_SIZE_MASK, \
+ slice_chunk_size)
+
+/* PPS 17 (MTL+) */
+#define DSC_PPS17_SL_BPG_OFFSET_MASK REG_GENMASK(31, 27)
+#define DSC_PPS17_SL_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS17_SL_BPG_OFFSET_MASK, offset)
+
+/* PPS 18 (MTL+) */
+#define DSC_PPS18_NSL_BPG_OFFSET_MASK REG_GENMASK(31, 16)
+#define DSC_PPS18_SL_OFFSET_ADJ_MASK REG_GENMASK(15, 0)
+#define DSC_PPS18_NSL_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS18_NSL_BPG_OFFSET_MASK, offset)
+#define DSC_PPS18_SL_OFFSET_ADJ(offset) REG_FIELD_PREP(DSC_PPS18_SL_OFFSET_ADJ_MASK, offset)
/* Icelake Rate Control Buffer Threshold Registers */
#define DSCA_RC_BUF_THRESH_0 _MMIO(0x6B230)
diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c
index 286a0bdd28..4b98833bfa 100644
--- a/drivers/gpu/drm/i915/display/intel_vga.c
+++ b/drivers/gpu/drm/i915/display/intel_vga.c
@@ -3,11 +3,9 @@
* Copyright © 2019 Intel Corporation
*/
-#include <linux/pci.h>
#include <linux/vgaarb.h>
#include <video/vga.h>
-
#include "soc/intel_gmch.h"
#include "i915_drv.h"
@@ -99,20 +97,6 @@ void intel_vga_reset_io_mem(struct drm_i915_private *i915)
vga_put(pdev, VGA_RSRC_LEGACY_IO);
}
-static unsigned int
-intel_vga_set_decode(struct pci_dev *pdev, bool enable_decode)
-{
- struct drm_i915_private *i915 = pdev_to_i915(pdev);
-
- intel_gmch_vga_set_state(i915, enable_decode);
-
- if (enable_decode)
- return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
- VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
- else
- return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
-}
-
int intel_vga_register(struct drm_i915_private *i915)
{
@@ -127,7 +111,7 @@ int intel_vga_register(struct drm_i915_private *i915)
* then we do not take part in VGA arbitration and the
* vga_client_register() fails with -ENODEV.
*/
- ret = vga_client_register(pdev, intel_vga_set_decode);
+ ret = vga_client_register(pdev, intel_gmch_vga_set_decode);
if (ret && ret != -ENODEV)
return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index 88e4759b53..5d905f932c 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -42,6 +42,15 @@ bool intel_vrr_is_capable(struct intel_connector *connector)
info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10;
}
+bool intel_vrr_is_in_range(struct intel_connector *connector, int vrefresh)
+{
+ const struct drm_display_info *info = &connector->base.display_info;
+
+ return intel_vrr_is_capable(connector) &&
+ vrefresh >= info->monitor_range.min_vfreq &&
+ vrefresh <= info->monitor_range.max_vfreq;
+}
+
void
intel_vrr_check_modeset(struct intel_atomic_state *state)
{
@@ -108,12 +117,17 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
const struct drm_display_info *info = &connector->base.display_info;
int vmin, vmax;
- if (!intel_vrr_is_capable(connector))
+ if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return;
- if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+ crtc_state->vrr.in_range =
+ intel_vrr_is_in_range(connector, drm_mode_vrefresh(adjusted_mode));
+ if (!crtc_state->vrr.in_range)
return;
+ if (HAS_LRR(i915))
+ crtc_state->update_lrr = true;
+
vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000,
adjusted_mode->crtc_htotal * info->monitor_range.max_vfreq);
vmax = adjusted_mode->crtc_clock * 1000 /
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h
index de16960c49..8993785820 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.h
+++ b/drivers/gpu/drm/i915/display/intel_vrr.h
@@ -14,6 +14,7 @@ struct intel_connector;
struct intel_crtc_state;
bool intel_vrr_is_capable(struct intel_connector *connector);
+bool intel_vrr_is_in_range(struct intel_connector *connector, int vrefresh);
void intel_vrr_check_modeset(struct intel_atomic_state *state);
void intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_wm.c b/drivers/gpu/drm/i915/display/intel_wm.c
index b615449e70..82c4933ad5 100644
--- a/drivers/gpu/drm/i915/display/intel_wm.c
+++ b/drivers/gpu/drm/i915/display/intel_wm.c
@@ -290,7 +290,7 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
{
struct seq_file *m = file->private_data;
struct drm_i915_private *dev_priv = m->private;
- u16 new[8] = { 0 };
+ u16 new[8] = {};
int level;
int ret;
char tmp[32];
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index ffc15d278a..245a64332c 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -16,10 +16,12 @@
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fbc.h"
+#include "intel_frontbuffer.h"
#include "intel_psr.h"
#include "skl_scaler.h"
#include "skl_universal_plane.h"
#include "skl_watermark.h"
+#include "gt/intel_gt.h"
#include "pxp/intel_pxp.h"
static const u32 skl_plane_formats[] = {
@@ -1245,7 +1247,7 @@ icl_plane_update_noarm(struct intel_plane *plane,
}
/* FLAT CCS doesn't need to program AUX_DIST */
- if (!HAS_FLAT_CCS(dev_priv))
+ if (!HAS_FLAT_CCS(dev_priv) && DISPLAY_VER(dev_priv) < 20)
intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
skl_plane_aux_dist(plane_state, color_plane));
@@ -1941,13 +1943,16 @@ static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe)
return pipe - PIPE_A + INTEL_FBC_A;
}
-static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
+static bool skl_plane_has_fbc(struct drm_i915_private *i915,
enum intel_fbc_id fbc_id, enum plane_id plane_id)
{
- if ((DISPLAY_RUNTIME_INFO(dev_priv)->fbc_mask & BIT(fbc_id)) == 0)
+ if ((DISPLAY_RUNTIME_INFO(i915)->fbc_mask & BIT(fbc_id)) == 0)
return false;
- return plane_id == PLANE_PRIMARY;
+ if (DISPLAY_VER(i915) >= 20)
+ return icl_is_hdr_plane(i915, plane_id);
+ else
+ return plane_id == PLANE_PRIMARY;
}
static struct intel_fbc *skl_plane_fbc(struct drm_i915_private *dev_priv,
@@ -2168,11 +2173,6 @@ skl_plane_disable_flip_done(struct intel_plane *plane)
static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915,
enum pipe pipe, enum plane_id plane_id)
{
- /* Wa_14017240301 */
- if (IS_MTL_GRAPHICS_STEP(i915, M, STEP_A0, STEP_B0) ||
- IS_MTL_GRAPHICS_STEP(i915, P, STEP_A0, STEP_B0))
- return false;
-
/* Wa_22011186057 */
if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
return false;
@@ -2203,10 +2203,6 @@ static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915,
if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
return false;
- /* Wa_14013215631 */
- if (IS_DG2_DISPLAY_STEP(i915, STEP_A0, STEP_C0))
- return false;
-
return plane_id < PLANE_SPRITE4;
}
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 063929a42a..99b8ccdc3d 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -1367,7 +1367,7 @@ skl_total_relative_data_rate(const struct intel_crtc_state *crtc_state)
u64 data_rate = 0;
for_each_plane_id_on_crtc(crtc, plane_id) {
- if (plane_id == PLANE_CURSOR)
+ if (plane_id == PLANE_CURSOR && DISPLAY_VER(i915) < 20)
continue;
data_rate += crtc_state->rel_data_rate[plane_id];
@@ -1514,10 +1514,12 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
return 0;
/* Allocate fixed number of blocks for cursor. */
- cursor_size = skl_cursor_allocation(crtc_state, num_active);
- iter.size -= cursor_size;
- skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR],
- alloc->end - cursor_size, alloc->end);
+ if (DISPLAY_VER(i915) < 20) {
+ cursor_size = skl_cursor_allocation(crtc_state, num_active);
+ iter.size -= cursor_size;
+ skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR],
+ alloc->end - cursor_size, alloc->end);
+ }
iter.data_rate = skl_total_relative_data_rate(crtc_state);
@@ -1531,7 +1533,7 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
const struct skl_plane_wm *wm =
&crtc_state->wm.skl.optimal.planes[plane_id];
- if (plane_id == PLANE_CURSOR) {
+ if (plane_id == PLANE_CURSOR && DISPLAY_VER(i915) < 20) {
const struct skl_ddb_entry *ddb =
&crtc_state->wm.skl.plane_ddb[plane_id];
@@ -1579,7 +1581,7 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state,
const struct skl_plane_wm *wm =
&crtc_state->wm.skl.optimal.planes[plane_id];
- if (plane_id == PLANE_CURSOR)
+ if (plane_id == PLANE_CURSOR && DISPLAY_VER(i915) < 20)
continue;
if (DISPLAY_VER(i915) < 11 &&
@@ -2616,7 +2618,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
/* TODO: Implement vblank synchronized MBUS joining changes */
- ret = intel_modeset_all_pipes(state, "MBUS joining change");
+ ret = intel_modeset_all_pipes_late(state, "MBUS joining change");
if (ret)
return ret;
}
@@ -3132,10 +3134,12 @@ static void skl_wm_get_hw_state_and_sanitize(struct drm_i915_private *i915)
skl_wm_sanitize(i915);
}
-void intel_wm_state_verify(struct intel_crtc *crtc,
- struct intel_crtc_state *new_crtc_state)
+void intel_wm_state_verify(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
struct skl_hw_state {
struct skl_ddb_entry ddb[I915_MAX_PLANES];
struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
@@ -3719,3 +3723,17 @@ void skl_watermark_debugfs_register(struct drm_i915_private *i915)
debugfs_create_file("i915_sagv_status", 0444, minor->debugfs_root, i915,
&intel_sagv_status_fops);
}
+
+unsigned int skl_watermark_max_latency(struct drm_i915_private *i915)
+{
+ int level;
+
+ for (level = i915->display.wm.num_levels - 1; level >= 0; level--) {
+ unsigned int latency = skl_wm_latency(i915, level, NULL);
+
+ if (latency)
+ return latency;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.h b/drivers/gpu/drm/i915/display/skl_watermark.h
index f91a3d4ddc..fb0da36fd3 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.h
+++ b/drivers/gpu/drm/i915/display/skl_watermark.h
@@ -38,14 +38,16 @@ bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb,
const struct skl_ddb_entry *entries,
int num_entries, int ignore_idx);
-void intel_wm_state_verify(struct intel_crtc *crtc,
- struct intel_crtc_state *new_crtc_state);
+void intel_wm_state_verify(struct intel_atomic_state *state,
+ struct intel_crtc *crtc);
void skl_watermark_ipc_init(struct drm_i915_private *i915);
void skl_watermark_ipc_update(struct drm_i915_private *i915);
bool skl_watermark_ipc_enabled(struct drm_i915_private *i915);
void skl_watermark_debugfs_register(struct drm_i915_private *i915);
+unsigned int skl_watermark_max_latency(struct drm_i915_private *i915);
+
void skl_wm_init(struct drm_i915_private *i915);
struct intel_dbuf_state {
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index d778b88413..f488394d31 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -23,6 +23,7 @@
* Author: Jani Nikula <jani.nikula@intel.com>
*/
+#include <linux/dmi.h>
#include <linux/slab.h>
#include <drm/drm_atomic_helper.h>
@@ -1760,6 +1761,126 @@ static void vlv_dphy_param_init(struct intel_dsi *intel_dsi)
intel_dsi_log_params(intel_dsi);
}
+typedef void (*vlv_dsi_dmi_quirk_func)(struct intel_dsi *intel_dsi);
+
+/*
+ * Vtotal is wrong on the Asus TF103C leading to the last line of the display
+ * being shown as the first line. The factory installed Android has a hardcoded
+ * modeline, causing it to not suffer from this BIOS bug.
+ *
+ * Original mode: "1280x800": 60 67700 1280 1312 1328 1376 800 808 812 820 0x8 0xa
+ * Fixed mode: "1280x800": 60 67700 1280 1312 1328 1376 800 808 812 816 0x8 0xa
+ *
+ * https://gitlab.freedesktop.org/drm/intel/-/issues/9381
+ */
+static void vlv_dsi_asus_tf103c_mode_fixup(struct intel_dsi *intel_dsi)
+{
+ /* Cast away the const as we want to fixup the mode */
+ struct drm_display_mode *fixed_mode = (struct drm_display_mode *)
+ intel_panel_preferred_fixed_mode(intel_dsi->attached_connector);
+
+ if (fixed_mode->vtotal == 820)
+ fixed_mode->vtotal -= 4;
+}
+
+/*
+ * On the Lenovo Yoga Tablet 2 830 / 1050 there are 2 problems:
+ * 1. The I2C MIPI sequence elements reference bus 3. ACPI has I2C1 - I2C7
+ * which under Linux become bus 0 - 6. And the MIPI sequence reference
+ * to bus 3 is indented for I2C3 which is bus 2 under Linux.
+ *
+ * Note mipi_exec_i2c() cannot just subtract 1 from the bus
+ * given in the I2C MIPI sequence element. Since on other
+ * devices the I2C bus-numbers used in the MIPI sequences do
+ * actually start at 0.
+ *
+ * 2. width_/height_mm contain a bogus 192mm x 120mm size. This is
+ * especially a problem on the 8" 830 version which uses a 10:16
+ * portrait screen where as the bogus size is 16:10.
+ *
+ * https://gitlab.freedesktop.org/drm/intel/-/issues/9379
+ */
+static void vlv_dsi_lenovo_yoga_tab2_size_fixup(struct intel_dsi *intel_dsi)
+{
+ const struct drm_display_mode *fixed_mode =
+ intel_panel_preferred_fixed_mode(intel_dsi->attached_connector);
+ struct drm_display_info *info = &intel_dsi->attached_connector->base.display_info;
+
+ intel_dsi->i2c_bus_num = 2;
+
+ /*
+ * The 10" 1050 uses a 1920x1200 landscape screen, where as the 8" 830
+ * uses a 1200x1920 portrait screen.
+ */
+ if (fixed_mode->hdisplay == 1920) {
+ info->width_mm = 216;
+ info->height_mm = 135;
+ } else {
+ info->width_mm = 107;
+ info->height_mm = 171;
+ }
+}
+
+/*
+ * On the Lenovo Yoga Tab 3 Pro YT3-X90F there are 2 problems:
+ * 1. i2c_acpi_find_adapter() picks the wrong adapter causing mipi_exec_i2c()
+ * to not work. Fix this by setting i2c_bus_num.
+ * 2. There is no backlight off MIPI sequence, causing the backlight to stay on.
+ * Add a backlight off sequence mirroring the existing backlight on sequence.
+ *
+ * https://gitlab.freedesktop.org/drm/intel/-/issues/9380
+ */
+static void vlv_dsi_lenovo_yoga_tab3_backlight_fixup(struct intel_dsi *intel_dsi)
+{
+ static const u8 backlight_off_sequence[16] = {
+ /* Header Seq-id 7, length after header 11 bytes */
+ 0x07, 0x0b, 0x00, 0x00, 0x00,
+ /* MIPI_SEQ_ELEM_I2C bus 0 addr 0x2c reg 0x00 data-len 1 data 0x00 */
+ 0x04, 0x08, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x00,
+ /* MIPI_SEQ_ELEM_END */
+ 0x00
+ };
+ struct intel_connector *connector = intel_dsi->attached_connector;
+
+ intel_dsi->i2c_bus_num = 0;
+ connector->panel.vbt.dsi.sequence[MIPI_SEQ_BACKLIGHT_OFF] = backlight_off_sequence;
+}
+
+static const struct dmi_system_id vlv_dsi_dmi_quirk_table[] = {
+ {
+ /* Asus Transformer Pad TF103C */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
+ },
+ .driver_data = (void *)vlv_dsi_asus_tf103c_mode_fixup,
+ },
+ {
+ /*
+ * Lenovo Yoga Tablet 2 830F/L or 1050F/L (The 8" and 10"
+ * Lenovo Yoga Tablet 2 use the same mainboard)
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
+ DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
+ /* Partial match on beginning of BIOS version */
+ DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
+ },
+ .driver_data = (void *)vlv_dsi_lenovo_yoga_tab2_size_fixup,
+ },
+ {
+ /* Lenovo Yoga Tab 3 Pro YT3-X90F */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
+ },
+ .driver_data = (void *)vlv_dsi_lenovo_yoga_tab3_backlight_fixup,
+ },
+ { }
+};
+
void vlv_dsi_init(struct drm_i915_private *dev_priv)
{
struct intel_dsi *intel_dsi;
@@ -1768,6 +1889,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
struct intel_connector *intel_connector;
struct drm_connector *connector;
struct drm_display_mode *current_mode;
+ const struct dmi_system_id *dmi_id;
enum port port;
enum pipe pipe;
@@ -1899,6 +2021,14 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
goto err_cleanup_connector;
}
+ dmi_id = dmi_first_match(vlv_dsi_dmi_quirk_table);
+ if (dmi_id) {
+ vlv_dsi_dmi_quirk_func quirk_func =
+ (vlv_dsi_dmi_quirk_func)dmi_id->driver_data;
+
+ quirk_func(intel_dsi);
+ }
+
intel_panel_init(intel_connector, NULL);
intel_backlight_setup(intel_connector, INVALID_PIPE);
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.h b/drivers/gpu/drm/i915/display/vlv_dsi.h
index 0c2b279df9..cf9d7b82f2 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.h
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.h
@@ -12,8 +12,21 @@ enum port;
struct drm_i915_private;
struct intel_dsi;
+#ifdef I915
void vlv_dsi_wait_for_fifo_empty(struct intel_dsi *intel_dsi, enum port port);
enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt);
void vlv_dsi_init(struct drm_i915_private *dev_priv);
+#else
+static inline void vlv_dsi_wait_for_fifo_empty(struct intel_dsi *intel_dsi, enum port port)
+{
+}
+static inline enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt)
+{
+ return 0;
+}
+static inline void vlv_dsi_init(struct drm_i915_private *dev_priv)
+{
+}
+#endif
#endif /* __VLV_DSI_H__ */
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.h b/drivers/gpu/drm/i915/display/vlv_dsi_pll.h
index ab9291ad1e..fbe5113dbe 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.h
+++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.h
@@ -32,7 +32,16 @@ u32 bxt_dsi_get_pclk(struct intel_encoder *encoder,
struct intel_crtc_state *config);
void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port);
+#ifdef I915
void assert_dsi_pll_enabled(struct drm_i915_private *i915);
void assert_dsi_pll_disabled(struct drm_i915_private *i915);
+#else
+static inline void assert_dsi_pll_enabled(struct drm_i915_private *i915)
+{
+}
+static inline void assert_dsi_pll_disabled(struct drm_i915_private *i915)
+{
+}
+#endif
#endif /* __VLV_DSI_PLL_H__ */