From 46c092af66f99f22476164fe2f1516856e2b8ef6 Mon Sep 17 00:00:00 2001 From: V3n3RiX Date: Sat, 17 Jul 2021 12:19:34 +0100 Subject: sys-kernel/linux-{image,sources}-redcore : version bump (5.13.2) - MASKED for now --- ...el-i915-backport-MSO-fixes-to-kernel-5.12.patch | 461 +++++++++++++++++++++ 1 file changed, 461 insertions(+) create mode 100644 sys-kernel/linux-image-redcore/files/5.13-Intel-i915-backport-MSO-fixes-to-kernel-5.12.patch (limited to 'sys-kernel/linux-image-redcore/files/5.13-Intel-i915-backport-MSO-fixes-to-kernel-5.12.patch') diff --git a/sys-kernel/linux-image-redcore/files/5.13-Intel-i915-backport-MSO-fixes-to-kernel-5.12.patch b/sys-kernel/linux-image-redcore/files/5.13-Intel-i915-backport-MSO-fixes-to-kernel-5.12.patch new file mode 100644 index 00000000..b0440c04 --- /dev/null +++ b/sys-kernel/linux-image-redcore/files/5.13-Intel-i915-backport-MSO-fixes-to-kernel-5.12.patch @@ -0,0 +1,461 @@ +diff -Naur linux-5.12/drivers/gpu/drm/i915/display/intel_ddi.c linux-5.12-p/drivers/gpu/drm/i915/display/intel_ddi.c +--- linux-5.12/drivers/gpu/drm/i915/display/intel_ddi.c 2021-04-25 22:49:08.000000000 +0200 ++++ linux-5.12-p/drivers/gpu/drm/i915/display/intel_ddi.c 2021-04-29 21:14:27.250013980 +0200 +@@ -3638,6 +3638,73 @@ + } + } + ++static void intel_ddi_mso_get_config(struct intel_encoder *encoder, ++ struct intel_crtc_state *pipe_config) ++{ ++ struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); ++ struct drm_i915_private *i915 = to_i915(crtc->base.dev); ++ enum pipe pipe = crtc->pipe; ++ u32 dss1; ++ ++ if (!HAS_MSO(i915)) ++ return; ++ ++ dss1 = intel_de_read(i915, ICL_PIPE_DSS_CTL1(pipe)); ++ ++ pipe_config->splitter.enable = dss1 & SPLITTER_ENABLE; ++ if (!pipe_config->splitter.enable) ++ return; ++ ++ /* Splitter enable is supported for pipe A only. */ ++ if (drm_WARN_ON(&i915->drm, pipe != PIPE_A)) { ++ pipe_config->splitter.enable = false; ++ return; ++ } ++ ++ switch (dss1 & SPLITTER_CONFIGURATION_MASK) { ++ default: ++ drm_WARN(&i915->drm, true, ++ "Invalid splitter configuration, dss1=0x%08x\n", dss1); ++ fallthrough; ++ case SPLITTER_CONFIGURATION_2_SEGMENT: ++ pipe_config->splitter.link_count = 2; ++ break; ++ case SPLITTER_CONFIGURATION_4_SEGMENT: ++ pipe_config->splitter.link_count = 4; ++ break; ++ } ++ ++ pipe_config->splitter.pixel_overlap = REG_FIELD_GET(OVERLAP_PIXELS_MASK, dss1); ++} ++ ++static void intel_ddi_mso_configure(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); ++ enum pipe pipe = crtc->pipe; ++ u32 dss1 = 0; ++ ++ if (!HAS_MSO(i915)) ++ return; ++ ++ if (crtc_state->splitter.enable) { ++ /* Splitter enable is supported for pipe A only. */ ++ if (drm_WARN_ON(&i915->drm, pipe != PIPE_A)) ++ return; ++ ++ dss1 |= SPLITTER_ENABLE; ++ dss1 |= OVERLAP_PIXELS(crtc_state->splitter.pixel_overlap); ++ if (crtc_state->splitter.link_count == 2) ++ dss1 |= SPLITTER_CONFIGURATION_2_SEGMENT; ++ else ++ dss1 |= SPLITTER_CONFIGURATION_4_SEGMENT; ++ } ++ ++ intel_de_rmw(i915, ICL_PIPE_DSS_CTL1(pipe), ++ SPLITTER_ENABLE | SPLITTER_CONFIGURATION_MASK | ++ OVERLAP_PIXELS_MASK, dss1); ++} ++ + static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, +@@ -3732,6 +3799,11 @@ + intel_ddi_power_up_lanes(encoder, crtc_state); + + /* ++ * 7.g Program CoG/MSO configuration bits in DSS_CTL1 if selected. ++ */ ++ intel_ddi_mso_configure(crtc_state); ++ ++ /* + * 7.g Configure and enable DDI_BUF_CTL + * 7.h Wait for DDI_BUF_CTL DDI Idle Status = 0b (Not Idle), timeout + * after 500 us. +@@ -4828,6 +4900,8 @@ + intel_ddi_read_func_ctl(encoder, pipe_config); + } + ++ intel_ddi_mso_get_config(encoder, pipe_config); ++ + pipe_config->has_audio = + intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder); + +@@ -5612,6 +5686,10 @@ + goto err; + + dig_port->hpd_pulse = intel_dp_hpd_pulse; ++ ++ /* Splitter enable for eDP MSO is supported for pipe A only. */ ++ if (dig_port->dp.mso_link_count) ++ encoder->pipe_mask = BIT(PIPE_A); + } + + /* In theory we don't need the encoder->type check, but leave it just in +diff -Naur linux-5.12/drivers/gpu/drm/i915/display/intel_display.c linux-5.12-p/drivers/gpu/drm/i915/display/intel_display.c +--- linux-5.12/drivers/gpu/drm/i915/display/intel_display.c 2021-04-25 22:49:08.000000000 +0200 ++++ linux-5.12-p/drivers/gpu/drm/i915/display/intel_display.c 2021-04-29 21:14:27.253013937 +0200 +@@ -6380,8 +6380,30 @@ + pipe_mode->crtc_clock /= 2; + } + +- intel_mode_from_crtc_timings(pipe_mode, pipe_mode); +- intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode); ++ if (crtc_state->splitter.enable) { ++ int n = crtc_state->splitter.link_count; ++ int overlap = crtc_state->splitter.pixel_overlap; ++ ++ /* ++ * eDP MSO uses segment timings from EDID for transcoder ++ * timings, but full mode for everything else. ++ * ++ * h_full = (h_segment - pixel_overlap) * link_count ++ */ ++ pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n; ++ pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n; ++ pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n; ++ pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n; ++ pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n; ++ pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n; ++ pipe_mode->crtc_clock *= n; ++ ++ intel_mode_from_crtc_timings(pipe_mode, pipe_mode); ++ intel_mode_from_crtc_timings(adjusted_mode, pipe_mode); ++ } else { ++ intel_mode_from_crtc_timings(pipe_mode, pipe_mode); ++ intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode); ++ } + + intel_crtc_compute_pixel_rate(crtc_state); + +@@ -6419,6 +6441,19 @@ + pipe_config->pipe_src_w /= 2; + } + ++ if (pipe_config->splitter.enable) { ++ int n = pipe_config->splitter.link_count; ++ int overlap = pipe_config->splitter.pixel_overlap; ++ ++ pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n; ++ pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n; ++ pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n; ++ pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n; ++ pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n; ++ pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n; ++ pipe_mode->crtc_clock *= n; ++ } ++ + intel_mode_from_crtc_timings(pipe_mode, pipe_mode); + + if (INTEL_GEN(dev_priv) < 4) { +@@ -10295,6 +10330,11 @@ + pipe_config->bigjoiner_slave ? "slave" : + pipe_config->bigjoiner ? "master" : "no"); + ++ drm_dbg_kms(&dev_priv->drm, "splitter: %s, link count %d, overlap %d\n", ++ enableddisabled(pipe_config->splitter.enable), ++ pipe_config->splitter.link_count, ++ pipe_config->splitter.pixel_overlap); ++ + if (pipe_config->has_pch_encoder) + intel_dump_m_n_config(pipe_config, "fdi", + pipe_config->fdi_lanes, +@@ -11335,6 +11375,10 @@ + PIPE_CONF_CHECK_I(dsc.dsc_split); + PIPE_CONF_CHECK_I(dsc.compressed_bpp); + ++ PIPE_CONF_CHECK_BOOL(splitter.enable); ++ PIPE_CONF_CHECK_I(splitter.link_count); ++ PIPE_CONF_CHECK_I(splitter.pixel_overlap); ++ + PIPE_CONF_CHECK_I(mst_master_transcoder); + + PIPE_CONF_CHECK_BOOL(vrr.enable); +diff -Naur linux-5.12/drivers/gpu/drm/i915/display/intel_display_types.h linux-5.12-p/drivers/gpu/drm/i915/display/intel_display_types.h +--- linux-5.12/drivers/gpu/drm/i915/display/intel_display_types.h 2021-04-25 22:49:08.000000000 +0200 ++++ linux-5.12-p/drivers/gpu/drm/i915/display/intel_display_types.h 2021-04-29 21:14:27.244014066 +0200 +@@ -1159,6 +1159,13 @@ + u8 pipeline_full; + u16 flipline, vmin, vmax; + } vrr; ++ ++ /* Stream Splitter for eDP MSO */ ++ struct { ++ bool enable; ++ u8 link_count; ++ u8 pixel_overlap; ++ } splitter; + }; + + enum intel_pipe_crc_source { +@@ -1448,6 +1455,8 @@ + int max_link_lane_count; + /* Max rate for the current link */ + int max_link_rate; ++ int mso_link_count; ++ int mso_pixel_overlap; + /* sink or branch descriptor */ + struct drm_dp_desc desc; + struct drm_dp_aux aux; +diff -Naur linux-5.12/drivers/gpu/drm/i915/display/intel_dp.c linux-5.12-p/drivers/gpu/drm/i915/display/intel_dp.c +--- linux-5.12/drivers/gpu/drm/i915/display/intel_dp.c 2021-04-25 22:49:08.000000000 +0200 ++++ linux-5.12-p/drivers/gpu/drm/i915/display/intel_dp.c 2021-04-29 21:14:27.254013923 +0200 +@@ -1724,6 +1724,7 @@ + { + struct intel_connector *intel_connector = intel_dp->attached_connector; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); ++ int pixel_clock; + + if (pipe_config->vrr.enable) + return; +@@ -1742,10 +1743,18 @@ + return; + + pipe_config->has_drrs = true; +- intel_link_compute_m_n(output_bpp, pipe_config->lane_count, +- intel_connector->panel.downclock_mode->clock, ++ ++ pixel_clock = intel_connector->panel.downclock_mode->clock; ++ 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, + pipe_config->port_clock, &pipe_config->dp_m2_n2, + constant_n, pipe_config->fec_enable); ++ ++ /* FIXME: abstract this better */ ++ if (pipe_config->splitter.enable) ++ pipe_config->dp_m2_n2.gmch_m *= pipe_config->splitter.link_count; + } + + int +@@ -1820,6 +1829,26 @@ + output_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; ++ int overlap = intel_dp->mso_pixel_overlap; ++ ++ pipe_config->splitter.enable = true; ++ pipe_config->splitter.link_count = n; ++ pipe_config->splitter.pixel_overlap = overlap; ++ ++ drm_dbg_kms(&dev_priv->drm, "MSO link count %d, pixel overlap %d\n", ++ n, overlap); ++ ++ adjusted_mode->crtc_hdisplay = adjusted_mode->crtc_hdisplay / n + overlap; ++ adjusted_mode->crtc_hblank_start = adjusted_mode->crtc_hblank_start / n + overlap; ++ adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_end / n + overlap; ++ adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hsync_start / n + overlap; ++ adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_end / n + overlap; ++ adjusted_mode->crtc_htotal = adjusted_mode->crtc_htotal / n + overlap; ++ adjusted_mode->crtc_clock /= n; ++ } ++ + intel_link_compute_m_n(output_bpp, + pipe_config->lane_count, + adjusted_mode->crtc_clock, +@@ -1827,6 +1856,10 @@ + &pipe_config->dp_m_n, + constant_n, pipe_config->fec_enable); + ++ /* FIXME: abstract this better */ ++ if (pipe_config->splitter.enable) ++ pipe_config->dp_m_n.gmch_m *= pipe_config->splitter.link_count; ++ + if (!HAS_DDI(dev_priv)) + intel_dp_set_clock(encoder, pipe_config); + +@@ -3517,6 +3550,64 @@ + } + } + ++static void intel_edp_mso_mode_fixup(struct intel_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ struct intel_dp *intel_dp = intel_attached_dp(connector); ++ struct drm_i915_private *i915 = to_i915(connector->base.dev); ++ int n = intel_dp->mso_link_count; ++ int overlap = intel_dp->mso_pixel_overlap; ++ ++ if (!mode || !n) ++ return; ++ ++ mode->hdisplay = (mode->hdisplay - overlap) * n; ++ mode->hsync_start = (mode->hsync_start - overlap) * n; ++ mode->hsync_end = (mode->hsync_end - overlap) * n; ++ mode->htotal = (mode->htotal - overlap) * n; ++ mode->clock *= n; ++ ++ drm_mode_set_name(mode); ++ ++ drm_dbg_kms(&i915->drm, ++ "[CONNECTOR:%d:%s] using generated MSO mode: ", ++ connector->base.base.id, connector->base.name); ++ drm_mode_debug_printmodeline(mode); ++} ++ ++static void intel_edp_mso_init(struct intel_dp *intel_dp) ++{ ++ struct drm_i915_private *i915 = dp_to_i915(intel_dp); ++ u8 mso; ++ ++ if (intel_dp->edp_dpcd[0] < DP_EDP_14) ++ return; ++ ++ if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_MSO_LINK_CAPABILITIES, &mso) != 1) { ++ drm_err(&i915->drm, "Failed to read MSO cap\n"); ++ return; ++ } ++ ++ /* Valid configurations are SST or MSO 2x1, 2x2, 4x1 */ ++ mso &= DP_EDP_MSO_NUMBER_OF_LINKS_MASK; ++ if (mso % 2 || mso > drm_dp_max_lane_count(intel_dp->dpcd)) { ++ drm_err(&i915->drm, "Invalid MSO link count cap %u\n", mso); ++ mso = 0; ++ } ++ ++ if (mso) { ++ drm_dbg_kms(&i915->drm, "Sink MSO %ux%u configuration\n", ++ mso, drm_dp_max_lane_count(intel_dp->dpcd) / mso); ++ if (!HAS_MSO(i915)) { ++ drm_err(&i915->drm, "No source MSO support, disabling\n"); ++ mso = 0; ++ } ++ } ++ ++ intel_dp->mso_link_count = mso; ++ intel_dp->mso_pixel_overlap = 0; /* FIXME: read from DisplayID v2.0 */ ++} ++ + static bool + intel_edp_init_dpcd(struct intel_dp *intel_dp) + { +@@ -3600,6 +3691,8 @@ + */ + intel_edp_init_source_oui(intel_dp, true); + ++ intel_edp_mso_init(intel_dp); ++ + return true; + } + +@@ -5546,19 +5639,18 @@ + { + struct intel_connector *intel_connector = to_intel_connector(connector); + struct edid *edid; ++ int num_modes = 0; + + edid = intel_connector->detect_edid; + if (edid) { +- int ret = intel_connector_update_modes(connector, edid); ++ num_modes = intel_connector_update_modes(connector, edid); + + if (intel_vrr_is_capable(connector)) + drm_connector_set_vrr_capable_property(connector, + true); +- if (ret) +- return ret; + } + +- /* if eDP has no EDID, fall back to fixed mode */ ++ /* Also add fixed mode, which may or may not be present in EDID */ + if (intel_dp_is_edp(intel_attached_dp(intel_connector)) && + intel_connector->panel.fixed_mode) { + struct drm_display_mode *mode; +@@ -5567,10 +5659,13 @@ + intel_connector->panel.fixed_mode); + if (mode) { + drm_mode_probed_add(connector, mode); +- return 1; ++ num_modes++; + } + } + ++ if (num_modes) ++ return num_modes; ++ + if (!edid) { + struct intel_dp *intel_dp = intel_attached_dp(intel_connector); + struct drm_display_mode *mode; +@@ -5580,11 +5675,11 @@ + intel_dp->downstream_ports); + if (mode) { + drm_mode_probed_add(connector, mode); +- return 1; ++ num_modes++; + } + } + +- return 0; ++ return num_modes; + } + + static int +@@ -6457,6 +6552,10 @@ + if (fixed_mode) + downclock_mode = intel_dp_drrs_init(intel_connector, fixed_mode); + ++ /* multiply the mode clock and horizontal timings for MSO */ ++ intel_edp_mso_mode_fixup(intel_connector, fixed_mode); ++ intel_edp_mso_mode_fixup(intel_connector, downclock_mode); ++ + /* fallback to VBT if available for eDP */ + if (!fixed_mode) + fixed_mode = intel_panel_vbt_fixed_mode(intel_connector); +diff -Naur linux-5.12/drivers/gpu/drm/i915/i915_drv.h linux-5.12-p/drivers/gpu/drm/i915/i915_drv.h +--- linux-5.12/drivers/gpu/drm/i915/i915_drv.h 2021-04-25 22:49:08.000000000 +0200 ++++ linux-5.12-p/drivers/gpu/drm/i915/i915_drv.h 2021-04-29 21:14:27.244014066 +0200 +@@ -1718,6 +1718,8 @@ + + #define HAS_CSR(dev_priv) (INTEL_INFO(dev_priv)->display.has_csr) + ++#define HAS_MSO(i915) (INTEL_GEN(i915) >= 12) ++ + #define HAS_RUNTIME_PM(dev_priv) (INTEL_INFO(dev_priv)->has_runtime_pm) + #define HAS_64BIT_RELOC(dev_priv) (INTEL_INFO(dev_priv)->has_64bit_reloc) + +diff -Naur linux-5.12/drivers/gpu/drm/i915/i915_reg.h linux-5.12-p/drivers/gpu/drm/i915/i915_reg.h +--- linux-5.12/drivers/gpu/drm/i915/i915_reg.h 2021-04-25 22:49:08.000000000 +0200 ++++ linux-5.12-p/drivers/gpu/drm/i915/i915_reg.h 2021-04-29 21:14:27.239014138 +0200 +@@ -11427,6 +11427,9 @@ + #define BIG_JOINER_ENABLE (1 << 29) + #define MASTER_BIG_JOINER_ENABLE (1 << 28) + #define VGA_CENTERING_ENABLE (1 << 27) ++#define SPLITTER_CONFIGURATION_MASK REG_GENMASK(26, 25) ++#define SPLITTER_CONFIGURATION_2_SEGMENT REG_FIELD_PREP(SPLITTER_CONFIGURATION_MASK, 0) ++#define SPLITTER_CONFIGURATION_4_SEGMENT REG_FIELD_PREP(SPLITTER_CONFIGURATION_MASK, 1) + + #define _ICL_PIPE_DSS_CTL2_PB 0x78204 + #define _ICL_PIPE_DSS_CTL2_PC 0x78404 +diff -Naur linux-5.12/include/drm/drm_dp_helper.h linux-5.12-p/include/drm/drm_dp_helper.h +--- linux-5.12/include/drm/drm_dp_helper.h 2021-04-25 22:49:08.000000000 +0200 ++++ linux-5.12-p/include/drm/drm_dp_helper.h 2021-04-29 21:14:27.233014224 +0200 +@@ -1016,6 +1016,11 @@ + #define DP_EDP_REGIONAL_BACKLIGHT_BASE 0x740 /* eDP 1.4 */ + #define DP_EDP_REGIONAL_BACKLIGHT_0 0x741 /* eDP 1.4 */ + ++#define DP_EDP_MSO_LINK_CAPABILITIES 0x7a4 /* eDP 1.4 */ ++# define DP_EDP_MSO_NUMBER_OF_LINKS_MASK (7 << 0) ++# define DP_EDP_MSO_NUMBER_OF_LINKS_SHIFT 0 ++# define DP_EDP_MSO_INDEPENDENT_LINK_BIT (1 << 3) ++ + /* Sideband MSG Buffers */ + #define DP_SIDEBAND_MSG_DOWN_REQ_BASE 0x1000 /* 1.2 MST */ + #define DP_SIDEBAND_MSG_UP_REP_BASE 0x1200 /* 1.2 MST */ -- cgit v1.2.3