From patchwork Wed Aug 21 10:19:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [01/29] drm/i915/dp: Add dp link rates for BMG From: Ankit Nautiyal X-Patchwork-Id: 609634 Message-Id: <20240821101945.273525-2-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:17 +0530 Currently we are using mtl_rates for BMG, but BMG support 13.5G which MTL does not. Add a new array for BMG rates. Bspec: 67066 Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 49a37b996530..ce9d493074e7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -528,6 +528,10 @@ static void intel_dp_set_source_rates(struct intel_dp *intel_dp) { /* The values must be in increasing order */ + static const int bmg_rates[] = { + 162000, 216000, 243000, 270000, 324000, 432000, 540000, 675000, + 810000, 1000000, 1350000, + }; static const int mtl_rates[] = { 162000, 216000, 243000, 270000, 324000, 432000, 540000, 675000, 810000, 1000000, 2000000, @@ -558,9 +562,14 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) intel_dp->source_rates || intel_dp->num_source_rates); if (DISPLAY_VER(dev_priv) >= 14) { - source_rates = mtl_rates; - size = ARRAY_SIZE(mtl_rates); - max_rate = mtl_max_source_rate(intel_dp); + if (DISPLAY_VER(dev_priv) == 14 && IS_DGFX(dev_priv)) { + source_rates = bmg_rates; + size = ARRAY_SIZE(bmg_rates); + } else { + source_rates = mtl_rates; + size = ARRAY_SIZE(mtl_rates); + max_rate = mtl_max_source_rate(intel_dp); + } } else if (DISPLAY_VER(dev_priv) >= 11) { source_rates = icl_rates; size = ARRAY_SIZE(icl_rates); From patchwork Wed Aug 21 10:19:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [02/29] drm/i915/dp: Fix potential overflow in bandwidth calculation for DSC config From: Ankit Nautiyal X-Patchwork-Id: 609633 Message-Id: <20240821101945.273525-3-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:18 +0530 In the function is_bw_sufficient_for_dsc_config overflow can occur for higher link rates. Avoid potential overflow by using 64-bit integers for bandwidth calculations. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ce9d493074e7..4b0a3b1729aa 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1887,10 +1887,10 @@ static bool is_bw_sufficient_for_dsc_config(u16 compressed_bppx16, u32 link_cloc enum intel_output_format output_format, int timeslots) { - u32 available_bw, required_bw; + u64 available_bw, required_bw; - available_bw = (link_clock * lane_count * timeslots * 16) / 8; - required_bw = compressed_bppx16 * (intel_dp_mode_to_fec_clock(mode_clock)); + available_bw = DIV_ROUND_DOWN_ULL((u64) link_clock * lane_count * timeslots * 16, 8); + required_bw = (u64) compressed_bppx16 * (intel_dp_mode_to_fec_clock(mode_clock)); return available_bw > required_bw; } From patchwork Wed Aug 21 10:19:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [03/29] drm/i915/display: Modify debugfs for joiner to force n pipes From: Ankit Nautiyal X-Patchwork-Id: 609635 Message-Id: <20240821101945.273525-4-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:19 +0530 At the moment, the debugfs for joiner allows only to force enable/disable pipe joiner for 2 pipes. Modify it to force join 'n' number of pipes. This will help in case of ultra joiner where 4 pipes are joined. Signed-off-by: Ankit Nautiyal --- .../drm/i915/display/intel_display_debugfs.c | 71 ++++++++++++++++++- .../drm/i915/display/intel_display_types.h | 8 ++- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 9c5a3f5beda2..8b4cf93fbe4f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1501,6 +1501,73 @@ static int intel_crtc_pipe_show(struct seq_file *m, void *unused) } DEFINE_SHOW_ATTRIBUTE(intel_crtc_pipe); +static int i915_joiner_show(struct seq_file *m, void *data) +{ + struct intel_connector *connector = m->private; + struct drm_i915_private *i915 = to_i915(connector->base.dev); + int ret; + + ret = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex); + if (ret) + return ret; + + seq_printf(m, "Force_joined_pipes: %d\n", connector->force_joined_pipes); + + drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); + + return ret; +} + +static ssize_t i915_joiner_write(struct file *file, + const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct intel_connector *connector = m->private; + struct drm_i915_private *i915 = to_i915(connector->base.dev); + int force_join_pipes = 0; + int ret; + + if (len == 0) + return 0; + + drm_dbg(&i915->drm, + "Copied %zu bytes from user to force joiner\n", len); + + ret = kstrtoint_from_user(ubuf, len, 0, &force_join_pipes); + if (ret < 0) + return ret; + + drm_dbg(&i915->drm, "Got %d for force joining pipes\n", force_join_pipes); + + if (force_join_pipes < INTEL_PIPE_JOINER_NONE || + force_join_pipes >= INTEL_PIPE_JOINER_INVALID) { + drm_dbg(&i915->drm, "Ignoring Invalid num of pipes %d for force joining\n", + force_join_pipes); + connector->force_joined_pipes = INTEL_PIPE_JOINER_NONE; + } else { + connector->force_joined_pipes = force_join_pipes; + } + + *offp += len; + + return len; +} + +static int i915_joiner_open(struct inode *inode, struct file *file) +{ + return single_open(file, i915_joiner_show, inode->i_private); +} + +static const struct file_operations i915_joiner_fops = { + .owner = THIS_MODULE, + .open = i915_joiner_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = i915_joiner_write +}; + /** * intel_connector_debugfs_add - add i915 specific connector debugfs files * @connector: pointer to a registered intel_connector @@ -1550,8 +1617,8 @@ void intel_connector_debugfs_add(struct intel_connector *connector) if (DISPLAY_VER(i915) >= 11 && (connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector_type == DRM_MODE_CONNECTOR_eDP)) { - debugfs_create_bool("i915_bigjoiner_force_enable", 0644, root, - &connector->force_bigjoiner_enable); + debugfs_create_file("i915_joiner_force_enable", 0644, root, + connector, &i915_joiner_fops); } if (connector_type == DRM_MODE_CONNECTOR_DSI || diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index ea6548ceab2f..129408bd0d3a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -613,6 +613,12 @@ struct intel_hdcp { enum transcoder stream_transcoder; }; +enum intel_joiner_pipe_count { + INTEL_PIPE_JOINER_NONE = 0, + INTEL_PIPE_JOINER_BIG = 2, + INTEL_PIPE_JOINER_INVALID, +}; + struct intel_connector { struct drm_connector base; /* @@ -651,7 +657,7 @@ struct intel_connector { struct intel_dp *mst_port; - bool force_bigjoiner_enable; + enum intel_joiner_pipe_count force_joined_pipes; struct { struct drm_dp_aux *dsc_decompression_aux; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 4b0a3b1729aa..b6aef2408ea7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1277,7 +1277,7 @@ bool intel_dp_need_joiner(struct intel_dp *intel_dp, return false; return clock > i915->display.cdclk.max_dotclk_freq || hdisplay > 5120 || - connector->force_bigjoiner_enable; + connector->force_joined_pipes == INTEL_PIPE_JOINER_BIG; } bool intel_dp_has_dsc(const struct intel_connector *connector) From patchwork Wed Aug 21 10:19:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [04/29] drm/i915/display: Use joined pipes in intel_dp_joiner_needs_dsc From: Ankit Nautiyal X-Patchwork-Id: 609636 Message-Id: <20240821101945.273525-5-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:20 +0530 In preparation of ultrajoiner, use number of joined pipes in the intel_dp_joiner_needs_dsc helper, instead of joiner flag. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_display.h | 2 ++ drivers/gpu/drm/i915/display/intel_dp.c | 18 +++++++++++++----- drivers/gpu/drm/i915/display/intel_dp.h | 4 +++- drivers/gpu/drm/i915/display/intel_dp_mst.c | 13 ++++++++++--- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2755ebbbb9d2..8815b5fb1604 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -277,7 +277,7 @@ bool intel_crtc_is_joiner_primary(const struct intel_crtc_state *crtc_state) crtc->pipe == joiner_primary_pipe(crtc_state); } -static int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state) +int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state) { return hweight8(crtc_state->joiner_pipes); } diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index b0cf6ca70952..0aecc3330a53 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -584,4 +584,6 @@ bool assert_port_valid(struct drm_i915_private *i915, enum port port); bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915); +int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state); + #endif diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index b6aef2408ea7..0100f5404699 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1315,6 +1315,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, u8 dsc_slice_count = 0; enum drm_mode_status status; bool dsc = false, joiner = false; + enum intel_joiner_pipe_count joined_pipes = INTEL_PIPE_JOINER_NONE; status = intel_cpu_transcoder_mode_valid(dev_priv, mode); if (status != MODE_OK) @@ -1338,7 +1339,8 @@ intel_dp_mode_valid(struct drm_connector *_connector, if (intel_dp_need_joiner(intel_dp, connector, mode->hdisplay, target_clock)) { joiner = true; - max_dotclk *= 2; + joined_pipes = INTEL_PIPE_JOINER_BIG; + max_dotclk *= INTEL_PIPE_JOINER_BIG; } if (target_clock > max_dotclk) return MODE_CLOCK_HIGH; @@ -1396,7 +1398,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, dsc = dsc_max_compressed_bpp && dsc_slice_count; } - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) + if (intel_dp_joiner_needs_dsc(dev_priv, joined_pipes) && !dsc) return MODE_CLOCK_HIGH; if (mode_rate > max_rate && !dsc) @@ -2504,14 +2506,15 @@ int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state) return intel_dp_link_required(adjusted_mode->crtc_clock, bpp); } -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner) +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, + enum intel_joiner_pipe_count joined_pipes) { /* * Pipe joiner needs compression up to display 12 due to bandwidth * limitation. DG2 onwards pipe joiner can be enabled without * compression. */ - return DISPLAY_VER(i915) < 13 && use_joiner; + return DISPLAY_VER(i915) < 13 && (joined_pipes == INTEL_PIPE_JOINER_BIG); } static int @@ -2529,6 +2532,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct link_config_limits limits; bool dsc_needed, joiner_needs_dsc; + enum intel_joiner_pipe_count joined_pipes; int ret = 0; if (pipe_config->fec_enable && @@ -2540,7 +2544,11 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, adjusted_mode->crtc_clock)) pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); - joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->joiner_pipes); + joined_pipes = intel_joiner_num_pipes(pipe_config); + if (joined_pipes >= INTEL_PIPE_JOINER_INVALID) + drm_warn(&i915->drm, "Invalid joined pipes : %d\n", joined_pipes); + + joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, joined_pipes); dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en || !intel_dp_compute_config_limits(intel_dp, pipe_config, diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 1b9aaddd8c35..0a14db9bb20f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -8,6 +8,7 @@ #include +enum intel_joiner_pipe_count; enum intel_output_format; enum pipe; enum port; @@ -123,7 +124,8 @@ int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16, int bw_overhead); int intel_dp_max_link_data_rate(struct intel_dp *intel_dp, int max_dprx_rate, int max_dprx_lanes); -bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner); +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, + enum intel_joiner_pipe_count joined_pipes); bool intel_dp_has_joiner(struct intel_dp *intel_dp); bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 45d2230d1801..195deb3d6155 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -568,6 +568,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, &pipe_config->hw.adjusted_mode; struct link_config_limits limits; bool dsc_needed, joiner_needs_dsc; + enum intel_joiner_pipe_count joined_pipes; int ret = 0; if (pipe_config->fec_enable && @@ -586,7 +587,11 @@ 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; - joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->joiner_pipes); + joined_pipes = intel_joiner_num_pipes(pipe_config); + if (joined_pipes >= INTEL_PIPE_JOINER_INVALID) + drm_warn(&dev_priv->drm, "Invalid joined pipes : %d\n", joined_pipes); + + joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, joined_pipes); dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en || !intel_dp_mst_compute_config_limits(intel_dp, @@ -1426,6 +1431,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, u16 dsc_max_compressed_bpp = 0; u8 dsc_slice_count = 0; int target_clock = mode->clock; + enum intel_joiner_pipe_count joined_pipes = INTEL_PIPE_JOINER_NONE; if (drm_connector_is_unregistered(connector)) { *status = MODE_ERROR; @@ -1468,7 +1474,8 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, if (intel_dp_need_joiner(intel_dp, intel_connector, mode->hdisplay, target_clock)) { joiner = true; - max_dotclk *= 2; + joined_pipes = INTEL_PIPE_JOINER_BIG; + max_dotclk *= INTEL_PIPE_JOINER_BIG; } ret = drm_modeset_lock(&mgr->base.lock, ctx); @@ -1508,7 +1515,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, dsc = dsc_max_compressed_bpp && dsc_slice_count; } - if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) { + if (intel_dp_joiner_needs_dsc(dev_priv, joined_pipes) && !dsc) { *status = MODE_CLOCK_HIGH; return 0; } From patchwork Wed Aug 21 10:19:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [05/29] drm/i915/display: Use joined pipes in intel_mode_valid_max_plane_size From: Ankit Nautiyal X-Patchwork-Id: 609638 Message-Id: <20240821101945.273525-6-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:21 +0530 In preparation of ultrajoiner, use number of joined pipes in the intel_mode_valid_max_plane_size helper, instead of joiner flag. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- drivers/gpu/drm/i915/display/intel_display.h | 3 ++- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- drivers/gpu/drm/i915/display/intel_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 2 +- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8815b5fb1604..4441ab04a060 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8082,7 +8082,7 @@ enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *de enum drm_mode_status intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv, const struct drm_display_mode *mode, - bool joiner) + enum intel_joiner_pipe_count joined_pipes) { int plane_width_max, plane_height_max; @@ -8099,7 +8099,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv, * too big for that. */ if (DISPLAY_VER(dev_priv) >= 11) { - plane_width_max = 5120 << joiner; + plane_width_max = 5120 << joined_pipes / 2; plane_height_max = 4320; } else { plane_width_max = 5120; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 0aecc3330a53..bf665f947b97 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -31,6 +31,7 @@ #include "intel_display_limits.h" enum drm_scaling_filter; +enum intel_joiner_pipe_count; struct dpll; struct drm_atomic_state; struct drm_connector; @@ -415,7 +416,7 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv, enum drm_mode_status intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv, const struct drm_display_mode *mode, - bool joiner); + enum intel_joiner_pipe_count joined_pipes); enum drm_mode_status intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915, const struct drm_display_mode *mode); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0100f5404699..6df59905f28d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1408,7 +1408,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, if (status != MODE_OK) return status; - return intel_mode_valid_max_plane_size(dev_priv, mode, joiner); + return intel_mode_valid_max_plane_size(dev_priv, mode, joined_pipes); } bool intel_dp_source_supports_tps3(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 195deb3d6155..27cf302c9a34 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1525,7 +1525,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, return 0; } - *status = intel_mode_valid_max_plane_size(dev_priv, mode, joiner); + *status = intel_mode_valid_max_plane_size(dev_priv, mode, joined_pipes); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c index bd5888ce4852..acc17546215f 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.c +++ b/drivers/gpu/drm/i915/display/intel_dsi.c @@ -76,7 +76,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector, if (fixed_mode->clock > max_dotclk) return MODE_CLOCK_HIGH; - return intel_mode_valid_max_plane_size(dev_priv, mode, false); + return intel_mode_valid_max_plane_size(dev_priv, mode, INTEL_PIPE_JOINER_NONE); } struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi, diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 19498ee455fa..5aa4a9f0c470 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2048,7 +2048,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, return status; } - return intel_mode_valid_max_plane_size(dev_priv, mode, false); + return intel_mode_valid_max_plane_size(dev_priv, mode, INTEL_PIPE_JOINER_NONE); } bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state, From patchwork Wed Aug 21 10:19:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [06/29] drm/i915/display: Use joined pipes in dsc helpers for slices, bpp From: Ankit Nautiyal X-Patchwork-Id: 609637 Message-Id: <20240821101945.273525-7-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:22 +0530 In preparation of ultrajoiner, use number of joined pipes in the dsc helpers to compute dsc slices and max compressed bpp, instead of using the joiner flag. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp.c | 27 +++++++++++---------- drivers/gpu/drm/i915/display/intel_dp.h | 4 +-- drivers/gpu/drm/i915/display/intel_dp_mst.c | 11 +++++---- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 6df59905f28d..b2058e5e54b3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -865,14 +865,14 @@ u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 p static u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915, u32 mode_clock, u32 mode_hdisplay, - bool bigjoiner) + enum intel_joiner_pipe_count joined_pipes) { 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) { + if (joined_pipes == INTEL_PIPE_JOINER_BIG) { 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; @@ -891,7 +891,7 @@ u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915, 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_joiner_pipe_count joined_pipes, enum intel_output_format output_format, u32 pipe_bpp, u32 timeslots) @@ -937,7 +937,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915, intel_dp_mode_to_fec_clock(mode_clock)); joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, mode_clock, - mode_hdisplay, bigjoiner); + mode_hdisplay, joined_pipes); 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); @@ -947,7 +947,7 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915, u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, int mode_clock, int mode_hdisplay, - bool bigjoiner) + enum intel_joiner_pipe_count joined_pipes) { struct drm_i915_private *i915 = to_i915(connector->base.dev); u8 min_slice_count, i; @@ -981,14 +981,14 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, /* Find the closest match to the valid slice count values */ for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) { - u8 test_slice_count = valid_dsc_slicecount[i] << bigjoiner; + u8 test_slice_count = valid_dsc_slicecount[i] << (joined_pipes / 2); if (test_slice_count > drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false)) break; /* big joiner needs small joiner to be enabled */ - if (bigjoiner && test_slice_count < 4) + if (joined_pipes == INTEL_PIPE_JOINER_BIG && test_slice_count < 4) continue; if (min_slice_count <= test_slice_count) @@ -1314,7 +1314,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, u16 dsc_max_compressed_bpp = 0; u8 dsc_slice_count = 0; enum drm_mode_status status; - bool dsc = false, joiner = false; + bool dsc = false; enum intel_joiner_pipe_count joined_pipes = INTEL_PIPE_JOINER_NONE; status = intel_cpu_transcoder_mode_valid(dev_priv, mode); @@ -1338,7 +1338,6 @@ intel_dp_mode_valid(struct drm_connector *_connector, if (intel_dp_need_joiner(intel_dp, connector, mode->hdisplay, target_clock)) { - joiner = true; joined_pipes = INTEL_PIPE_JOINER_BIG; max_dotclk *= INTEL_PIPE_JOINER_BIG; } @@ -1385,14 +1384,14 @@ intel_dp_mode_valid(struct drm_connector *_connector, max_lanes, target_clock, mode->hdisplay, - joiner, + joined_pipes, output_format, pipe_bpp, 64); dsc_slice_count = intel_dp_dsc_get_slice_count(connector, target_clock, mode->hdisplay, - joiner); + joined_pipes); } dsc = dsc_max_compressed_bpp && dsc_slice_count; @@ -2108,6 +2107,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *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; + int joined_pipes = intel_joiner_num_pipes(pipe_config); dsc_src_min_bpp = dsc_src_min_compressed_bpp(); dsc_sink_min_bpp = intel_dp_dsc_sink_min_compressed_bpp(pipe_config); @@ -2122,7 +2122,7 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp, dsc_joiner_max_bpp = get_max_compressed_bpp_with_joiner(i915, adjusted_mode->clock, adjusted_mode->hdisplay, - pipe_config->joiner_pipes); + joined_pipes); dsc_max_bpp = min(dsc_max_bpp, dsc_joiner_max_bpp); dsc_max_bpp = min(dsc_max_bpp, fxp_q4_to_int(limits->link.max_bpp_x16)); @@ -2307,6 +2307,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; + int joined_pipes = intel_joiner_num_pipes(pipe_config); int ret; pipe_config->fec_enable = pipe_config->fec_enable || @@ -2356,7 +2357,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, intel_dp_dsc_get_slice_count(connector, adjusted_mode->crtc_clock, adjusted_mode->crtc_hdisplay, - pipe_config->joiner_pipes); + joined_pipes); if (!dsc_dp_slice_count) { drm_dbg_kms(&dev_priv->drm, "Compressed Slice Count not supported\n"); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 0a14db9bb20f..f284058f5148 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -144,7 +144,7 @@ int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector, 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_joiner_pipe_count joined_pipes, enum intel_output_format output_format, u32 pipe_bpp, u32 timeslots); @@ -154,7 +154,7 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector int bpc); u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, int mode_clock, int mode_hdisplay, - bool bigjoiner); + enum intel_joiner_pipe_count joined_pipes); bool intel_dp_need_joiner(struct intel_dp *intel_dp, struct intel_connector *connector, int hdisplay, int clock); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 27cf302c9a34..9dc12b799414 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -102,11 +102,13 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state, flags |= crtc_state->fec_enable ? DRM_DP_BW_OVERHEAD_FEC : 0; if (dsc) { + int joined_pipes = intel_joiner_num_pipes(crtc_state); + flags |= DRM_DP_BW_OVERHEAD_DSC; dsc_slice_count = intel_dp_dsc_get_slice_count(connector, adjusted_mode->clock, adjusted_mode->hdisplay, - crtc_state->joiner_pipes); + joined_pipes); } overhead = drm_dp_bw_overhead(crtc_state->lane_count, @@ -1427,7 +1429,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq; int max_rate, mode_rate, max_lanes, max_link_clock; int ret; - bool dsc = false, joiner = false; + bool dsc = false; u16 dsc_max_compressed_bpp = 0; u8 dsc_slice_count = 0; int target_clock = mode->clock; @@ -1473,7 +1475,6 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, */ if (intel_dp_need_joiner(intel_dp, intel_connector, mode->hdisplay, target_clock)) { - joiner = true; joined_pipes = INTEL_PIPE_JOINER_BIG; max_dotclk *= INTEL_PIPE_JOINER_BIG; } @@ -1502,14 +1503,14 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, max_lanes, target_clock, mode->hdisplay, - joiner, + joined_pipes, INTEL_OUTPUT_FORMAT_RGB, pipe_bpp, 64); dsc_slice_count = intel_dp_dsc_get_slice_count(intel_connector, target_clock, mode->hdisplay, - joiner); + joined_pipes); } dsc = dsc_max_compressed_bpp && dsc_slice_count; From patchwork Wed Aug 21 10:19:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [07/29] drm/i915: Add some essential functionality for joiners From: Ankit Nautiyal X-Patchwork-Id: 609639 Message-Id: <20240821101945.273525-8-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:23 +0530 From: Stanislav Lisovskiy In most of the cases we now try to avoid mentioning things like "bigjoiner" or "ultrajoiner" trying to unify the API and refer mostly to all this functionality as "joiner". In majority cases that should be way to go. However in some cases we still need to distinguish between bigjoiner primaries and secondaries(such as DSC register programming). Create correspondent helper functions and start using them, in order be prepared for adding ultrajoiner functionality. v2: Fixed checkpatch warnings (Ankit) Signed-off-by: Stanislav Lisovskiy Signed-off-by: Ankit Nautiyal --- .../gpu/drm/i915/display/intel_atomic_plane.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 75 ++++++++++++++++--- drivers/gpu/drm/i915/display/intel_display.h | 8 +- .../drm/i915/display/intel_modeset_verify.c | 2 +- drivers/gpu/drm/i915/display/intel_vdsc.c | 4 +- 5 files changed, 76 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index e979786aa5cf..9862d0339e6a 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -724,7 +724,7 @@ int intel_plane_atomic_check(struct intel_atomic_state *state, if (new_crtc_state && intel_crtc_is_joiner_secondary(new_crtc_state)) { struct intel_crtc *primary_crtc = - intel_primary_crtc(new_crtc_state); + intel_joiner_primary_crtc(new_crtc_state); struct intel_plane *primary_crtc_plane = intel_crtc_get_plane(primary_crtc, plane->id); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 4441ab04a060..b2d5e17e416f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -253,6 +253,68 @@ static enum pipe joiner_primary_pipe(const struct intel_crtc_state *crtc_state) return ffs(crtc_state->joiner_pipes) - 1; } +int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state) +{ + return hweight8(crtc_state->joiner_pipes); +} + +bool intel_crtc_is_ultrajoiner(const struct intel_crtc_state *crtc_state) +{ + return intel_joiner_num_pipes(crtc_state) == 4; +} + +static bool intel_is_joiner(const struct intel_crtc_state *crtc_state) +{ + return intel_joiner_num_pipes(crtc_state) > 1; +} + +static u8 bigjoiner_primary_pipes(const struct intel_crtc_state *crtc_state) +{ + int lsb = ffs(crtc_state->joiner_pipes) - 1; + int msb = fls(crtc_state->joiner_pipes) - 1; + int i; + u8 bigjoiner_primary_mask = 0; + + for (i = lsb; i < msb; i += 4) { + /* + * Regardless of how joiner_pipes mask is set, currently + * we always assume, that primary pipe bit goes before secondary + * pipe bit. So in each set of 2 bits, least significant bit is + * bigjoiner primary pipe and most significant bit is secondary pipe. + */ + bigjoiner_primary_mask |= + ((BIT(0) | BIT(2)) << i) & crtc_state->joiner_pipes; + } + + return bigjoiner_primary_mask; +} + +bool intel_crtc_is_bigjoiner_primary(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + if (!intel_is_joiner(crtc_state)) + return false; + + return BIT(crtc->pipe) & bigjoiner_primary_pipes(crtc_state); +} + +bool intel_crtc_is_bigjoiner_secondary(const struct intel_crtc_state *crtc_state) +{ + if (!intel_is_joiner(crtc_state)) + return false; + + return !intel_crtc_is_bigjoiner_primary(crtc_state); +} + +bool intel_crtc_is_ultrajoiner_primary(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + return intel_crtc_is_ultrajoiner(crtc_state) && + (crtc->pipe == joiner_primary_pipe(crtc_state)); +} + u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state) { if (crtc_state->joiner_pipes) @@ -277,11 +339,6 @@ bool intel_crtc_is_joiner_primary(const struct intel_crtc_state *crtc_state) crtc->pipe == joiner_primary_pipe(crtc_state); } -int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state) -{ - return hweight8(crtc_state->joiner_pipes); -} - u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -289,7 +346,7 @@ u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state) return BIT(crtc->pipe) | crtc_state->joiner_pipes; } -struct intel_crtc *intel_primary_crtc(const struct intel_crtc_state *crtc_state) +struct intel_crtc *intel_joiner_primary_crtc(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); @@ -809,7 +866,7 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, int num_encoders = 0; int i; - primary_crtc = intel_primary_crtc(crtc_state); + primary_crtc = intel_joiner_primary_crtc(crtc_state); for_each_new_connector_in_state(&state->base, connector, connector_state, i) { if (connector_state->crtc != &primary_crtc->base) @@ -4528,7 +4585,7 @@ copy_joiner_crtc_state_nomodeset(struct intel_atomic_state *state, { struct intel_crtc_state *secondary_crtc_state = intel_atomic_get_new_crtc_state(state, secondary_crtc); - struct intel_crtc *primary_crtc = intel_primary_crtc(secondary_crtc_state); + struct intel_crtc *primary_crtc = intel_joiner_primary_crtc(secondary_crtc_state); const struct intel_crtc_state *primary_crtc_state = intel_atomic_get_new_crtc_state(state, primary_crtc); @@ -4548,7 +4605,7 @@ copy_joiner_crtc_state_modeset(struct intel_atomic_state *state, { struct intel_crtc_state *secondary_crtc_state = intel_atomic_get_new_crtc_state(state, secondary_crtc); - struct intel_crtc *primary_crtc = intel_primary_crtc(secondary_crtc_state); + struct intel_crtc *primary_crtc = intel_joiner_primary_crtc(secondary_crtc_state); const struct intel_crtc_state *primary_crtc_state = intel_atomic_get_new_crtc_state(state, primary_crtc); struct intel_crtc_state *saved_state; diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index bf665f947b97..35e68e4cc712 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -424,10 +424,14 @@ enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port); bool is_trans_port_sync_mode(const struct intel_crtc_state *state); bool is_trans_port_sync_master(const struct intel_crtc_state *state); u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state); -bool intel_crtc_is_joiner_secondary(const struct intel_crtc_state *crtc_state); bool intel_crtc_is_joiner_primary(const struct intel_crtc_state *crtc_state); +bool intel_crtc_is_joiner_secondary(const struct intel_crtc_state *crtc_state); +bool intel_crtc_is_bigjoiner_primary(const struct intel_crtc_state *crtc_state); +bool intel_crtc_is_bigjoiner_secondary(const struct intel_crtc_state *crtc_state); +bool intel_crtc_is_ultrajoiner(const struct intel_crtc_state *crtc_state); +bool intel_crtc_is_ultrajoiner_primary(const struct intel_crtc_state *crtc_state); u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state); -struct intel_crtc *intel_primary_crtc(const struct intel_crtc_state *crtc_state); +struct intel_crtc *intel_joiner_primary_crtc(const struct intel_crtc_state *crtc_state); bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state); bool intel_pipe_config_compare(const struct intel_crtc_state *current_config, const struct intel_crtc_state *pipe_config, diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c index 3491db5cad31..b53b810c6470 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c @@ -193,7 +193,7 @@ verify_crtc_state(struct intel_atomic_state *state, "transitional active state does not match atomic hw state (expected %i, found %i)\n", sw_crtc_state->hw.active, crtc->active); - primary_crtc = intel_primary_crtc(sw_crtc_state); + primary_crtc = intel_joiner_primary_crtc(sw_crtc_state); for_each_encoder_on_crtc(dev, &primary_crtc->base, encoder) { enum pipe pipe; diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 2e849b015e74..8158e3702ed5 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -742,7 +742,7 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state) u32 dss_ctl1_val = 0; if (crtc_state->joiner_pipes && !crtc_state->dsc.compression_enable) { - if (intel_crtc_is_joiner_secondary(crtc_state)) + if (intel_crtc_is_bigjoiner_secondary(crtc_state)) dss_ctl1_val |= UNCOMPRESSED_JOINER_SECONDARY; else dss_ctl1_val |= UNCOMPRESSED_JOINER_PRIMARY; @@ -771,7 +771,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state) } if (crtc_state->joiner_pipes) { dss_ctl1_val |= BIG_JOINER_ENABLE; - if (!intel_crtc_is_joiner_secondary(crtc_state)) + if (intel_crtc_is_bigjoiner_primary(crtc_state)) dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE; } intel_de_write(dev_priv, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder), dss_ctl1_val); From patchwork Wed Aug 21 10:19:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [08/29] drm/i915: Split current joiner hw state readout From: Ankit Nautiyal X-Patchwork-Id: 609642 Message-Id: <20240821101945.273525-9-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:24 +0530 From: Stanislav Lisovskiy We need to add a new sanity checks and also do some preparations for adding ultrajoiner hw state readout. Lets first split reading of the uncompressed joiner and bigjoiner bit masks into separate functions. v2: Fixed checkpatch warnings (Ankit) Signed-off-by: Stanislav Lisovskiy Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_display.c | 65 +++++++++++++++----- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index b2d5e17e416f..2c563a05caaa 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3591,51 +3591,82 @@ static bool transcoder_ddi_func_is_enabled(struct drm_i915_private *dev_priv, return tmp & TRANS_DDI_FUNC_ENABLE; } -static void enabled_joiner_pipes(struct drm_i915_private *dev_priv, - u8 *primary_pipes, u8 *secondary_pipes) +static void enabled_uncompressed_joiner_pipes(struct drm_i915_private *dev_priv, + u8 *primary_pipes, u8 *secondary_pipes) { struct intel_crtc *crtc; *primary_pipes = 0; *secondary_pipes = 0; + if (DISPLAY_VER(dev_priv) < 13) + return; + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc, joiner_pipes(dev_priv)) { enum intel_display_power_domain power_domain; enum pipe pipe = crtc->pipe; intel_wakeref_t wakeref; - power_domain = intel_dsc_power_domain(crtc, (enum transcoder) pipe); + power_domain = POWER_DOMAIN_PIPE(pipe); with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) { u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe)); - if (!(tmp & BIG_JOINER_ENABLE)) - continue; - - if (tmp & PRIMARY_BIG_JOINER_ENABLE) + if (tmp & UNCOMPRESSED_JOINER_PRIMARY) *primary_pipes |= BIT(pipe); - else + if (tmp & UNCOMPRESSED_JOINER_SECONDARY) *secondary_pipes |= BIT(pipe); } + } +} - if (DISPLAY_VER(dev_priv) < 13) - continue; +static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv, + u8 *primary_pipes, u8 *secondary_pipes) +{ + struct intel_crtc *crtc; - power_domain = POWER_DOMAIN_PIPE(pipe); + *primary_pipes = 0; + *secondary_pipes = 0; + + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, crtc, + joiner_pipes(dev_priv)) { + enum intel_display_power_domain power_domain; + enum pipe pipe = crtc->pipe; + intel_wakeref_t wakeref; + + power_domain = intel_dsc_power_domain(crtc, (enum transcoder)pipe); with_intel_display_power_if_enabled(dev_priv, power_domain, wakeref) { u32 tmp = intel_de_read(dev_priv, ICL_PIPE_DSS_CTL1(pipe)); - if (tmp & UNCOMPRESSED_JOINER_PRIMARY) + if (!(tmp & BIG_JOINER_ENABLE)) + continue; + + if (tmp & PRIMARY_BIG_JOINER_ENABLE) *primary_pipes |= BIT(pipe); - if (tmp & UNCOMPRESSED_JOINER_SECONDARY) + else *secondary_pipes |= BIT(pipe); } } +} + +static void enabled_joiner_pipes(struct drm_i915_private *dev_priv, + u8 *primary_pipes, u8 *secondary_pipes) +{ + u8 primary_uncompressed_joiner_pipes, primary_bigjoiner_pipes; + u8 secondary_uncompressed_joiner_pipes, secondary_bigjoiner_pipes; + + enabled_uncompressed_joiner_pipes(dev_priv, &primary_uncompressed_joiner_pipes, + &secondary_uncompressed_joiner_pipes); + + enabled_bigjoiner_pipes(dev_priv, &primary_bigjoiner_pipes, + &secondary_bigjoiner_pipes); + + *primary_pipes = 0; + *secondary_pipes = 0; + + *primary_pipes = primary_uncompressed_joiner_pipes | primary_bigjoiner_pipes; - /* Joiner pipes should always be consecutive primary and secondary */ - drm_WARN(&dev_priv->drm, *secondary_pipes != *primary_pipes << 1, - "Joiner misconfigured (primary pipes 0x%x, secondary pipes 0x%x)\n", - *primary_pipes, *secondary_pipes); + *secondary_pipes = secondary_uncompressed_joiner_pipes | secondary_bigjoiner_pipes; } static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes, u8 secondary_pipes) From patchwork Wed Aug 21 10:19:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [09/29] drm/i915: Add bigjoiner and uncompressed joiner hw readout sanity checks From: Ankit Nautiyal X-Patchwork-Id: 609640 Message-Id: <20240821101945.273525-10-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:25 +0530 From: Stanislav Lisovskiy Adding sanity checks for primary and secondary bigjoiner/uncompressed bitmasks, should make it easier to spot possible issues. Signed-off-by: Stanislav Lisovskiy Reviewed-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_display.c | 25 +++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2c563a05caaa..c58f8209d966 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3649,11 +3649,17 @@ static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv, } } +static u8 expected_secondary_pipes(u8 primary_pipes) +{ + return primary_pipes << 1; +} + static void enabled_joiner_pipes(struct drm_i915_private *dev_priv, u8 *primary_pipes, u8 *secondary_pipes) { u8 primary_uncompressed_joiner_pipes, primary_bigjoiner_pipes; u8 secondary_uncompressed_joiner_pipes, secondary_bigjoiner_pipes; + u8 uncompressed_joiner_pipes, bigjoiner_pipes; enabled_uncompressed_joiner_pipes(dev_priv, &primary_uncompressed_joiner_pipes, &secondary_uncompressed_joiner_pipes); @@ -3661,11 +3667,28 @@ static void enabled_joiner_pipes(struct drm_i915_private *dev_priv, enabled_bigjoiner_pipes(dev_priv, &primary_bigjoiner_pipes, &secondary_bigjoiner_pipes); + uncompressed_joiner_pipes = primary_uncompressed_joiner_pipes | + secondary_uncompressed_joiner_pipes; + bigjoiner_pipes = primary_bigjoiner_pipes | secondary_bigjoiner_pipes; + + drm_WARN(&dev_priv->drm, (uncompressed_joiner_pipes & bigjoiner_pipes) != 0, + "Uncomressed joiner pipes(%x) and bigjoiner pipes(%x) can't intersect\n", + uncompressed_joiner_pipes, bigjoiner_pipes); + drm_WARN(&dev_priv->drm, secondary_bigjoiner_pipes != + expected_secondary_pipes(primary_bigjoiner_pipes), + "Wrong secondary bigjoiner pipes(expected %x, current %x)\n", + expected_secondary_pipes(primary_bigjoiner_pipes), + secondary_bigjoiner_pipes); + drm_WARN(&dev_priv->drm, secondary_uncompressed_joiner_pipes != + expected_secondary_pipes(primary_uncompressed_joiner_pipes), + "Wrong secondary uncompressed joiner pipes(expected %x, current %x)\n", + expected_secondary_pipes(primary_uncompressed_joiner_pipes), + secondary_uncompressed_joiner_pipes); + *primary_pipes = 0; *secondary_pipes = 0; *primary_pipes = primary_uncompressed_joiner_pipes | primary_bigjoiner_pipes; - *secondary_pipes = secondary_uncompressed_joiner_pipes | secondary_bigjoiner_pipes; } From patchwork Wed Aug 21 10:19:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [10/29] drm/i915: Implement hw state readout and checks for ultrajoiner From: Ankit Nautiyal X-Patchwork-Id: 609641 Message-Id: <20240821101945.273525-11-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:26 +0530 From: Stanislav Lisovskiy Ultrajoiner mode has some new bits and states to be read out from the hw. Lets make changes accordingly. v2: Fix checkpatch warnings. (Ankit) v3: Add separate functions for computing expected secondary_big/ultrajoiner pipes. (Ankit) Signed-off-by: Stanislav Lisovskiy Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 133 ++++++++++++++---- .../gpu/drm/i915/display/intel_vdsc_regs.h | 3 + 2 files changed, 108 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c58f8209d966..29ee27a8041b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3649,17 +3649,63 @@ static void enabled_bigjoiner_pipes(struct drm_i915_private *dev_priv, } } -static u8 expected_secondary_pipes(u8 primary_pipes) +static void enabled_ultrajoiner_pipes(struct drm_i915_private *i915, + u8 *primary_pipes, u8 *secondary_pipes) { + struct intel_crtc *crtc; + + *primary_pipes = 0; + *secondary_pipes = 0; + + if (DISPLAY_VER(i915) < 14) + return; + + for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, + joiner_pipes(i915)) { + enum intel_display_power_domain power_domain; + enum pipe pipe = crtc->pipe; + intel_wakeref_t wakeref; + + power_domain = intel_dsc_power_domain(crtc, (enum transcoder)pipe); + with_intel_display_power_if_enabled(i915, power_domain, wakeref) { + u32 tmp = intel_de_read(i915, ICL_PIPE_DSS_CTL1(pipe)); + + if (!(tmp & ULTRA_JOINER_ENABLE)) + continue; + + if (tmp & PRIMARY_ULTRA_JOINER_ENABLE) + *primary_pipes |= BIT(pipe); + else + *secondary_pipes |= BIT(pipe); + } + } +} + +static u8 expected_secondary_bigjoiner_pipes(u8 primary_pipes) +{ + if (!primary_pipes) + return 0; + return primary_pipes << 1; } +static u8 expected_secondary_ultrajoiner_pipes(u8 primary_pipes) +{ + if (!primary_pipes) + return 0; + + return GENMASK(2, primary_pipes); +} + static void enabled_joiner_pipes(struct drm_i915_private *dev_priv, - u8 *primary_pipes, u8 *secondary_pipes) + u8 *primary_pipes, u8 *secondary_pipes, + bool *ultrajoiner_used) { u8 primary_uncompressed_joiner_pipes, primary_bigjoiner_pipes; + u8 primary_ultrajoiner_pipes; u8 secondary_uncompressed_joiner_pipes, secondary_bigjoiner_pipes; - u8 uncompressed_joiner_pipes, bigjoiner_pipes; + u8 secondary_ultrajoiner_pipes; + u8 uncompressed_joiner_pipes, bigjoiner_pipes, ultrajoiner_pipes; enabled_uncompressed_joiner_pipes(dev_priv, &primary_uncompressed_joiner_pipes, &secondary_uncompressed_joiner_pipes); @@ -3667,32 +3713,49 @@ static void enabled_joiner_pipes(struct drm_i915_private *dev_priv, enabled_bigjoiner_pipes(dev_priv, &primary_bigjoiner_pipes, &secondary_bigjoiner_pipes); + enabled_ultrajoiner_pipes(dev_priv, &primary_ultrajoiner_pipes, + &secondary_ultrajoiner_pipes); + uncompressed_joiner_pipes = primary_uncompressed_joiner_pipes | secondary_uncompressed_joiner_pipes; bigjoiner_pipes = primary_bigjoiner_pipes | secondary_bigjoiner_pipes; + ultrajoiner_pipes = primary_ultrajoiner_pipes | secondary_ultrajoiner_pipes; + *ultrajoiner_used = ultrajoiner_pipes != 0; drm_WARN(&dev_priv->drm, (uncompressed_joiner_pipes & bigjoiner_pipes) != 0, "Uncomressed joiner pipes(%x) and bigjoiner pipes(%x) can't intersect\n", uncompressed_joiner_pipes, bigjoiner_pipes); + drm_WARN(&dev_priv->drm, (ultrajoiner_pipes & bigjoiner_pipes) != ultrajoiner_pipes, + "Ultrajoiner pipes(%x) should be bigjoiner pipes(%x)\n", + ultrajoiner_pipes, bigjoiner_pipes); + drm_WARN(&dev_priv->drm, secondary_bigjoiner_pipes != - expected_secondary_pipes(primary_bigjoiner_pipes), + expected_secondary_bigjoiner_pipes(primary_bigjoiner_pipes), "Wrong secondary bigjoiner pipes(expected %x, current %x)\n", - expected_secondary_pipes(primary_bigjoiner_pipes), + expected_secondary_bigjoiner_pipes(primary_bigjoiner_pipes), secondary_bigjoiner_pipes); drm_WARN(&dev_priv->drm, secondary_uncompressed_joiner_pipes != - expected_secondary_pipes(primary_uncompressed_joiner_pipes), + expected_secondary_bigjoiner_pipes(primary_uncompressed_joiner_pipes), "Wrong secondary uncompressed joiner pipes(expected %x, current %x)\n", - expected_secondary_pipes(primary_uncompressed_joiner_pipes), + expected_secondary_bigjoiner_pipes(primary_uncompressed_joiner_pipes), secondary_uncompressed_joiner_pipes); + drm_WARN(&dev_priv->drm, secondary_ultrajoiner_pipes != + expected_secondary_ultrajoiner_pipes(primary_ultrajoiner_pipes), + "Wrong secondary ultrajoiner pipes(expected %x, current %x)\n", + expected_secondary_ultrajoiner_pipes(primary_ultrajoiner_pipes), + secondary_ultrajoiner_pipes); *primary_pipes = 0; *secondary_pipes = 0; - *primary_pipes = primary_uncompressed_joiner_pipes | primary_bigjoiner_pipes; - *secondary_pipes = secondary_uncompressed_joiner_pipes | secondary_bigjoiner_pipes; + *primary_pipes = primary_uncompressed_joiner_pipes | primary_bigjoiner_pipes | + primary_ultrajoiner_pipes; + *secondary_pipes = secondary_uncompressed_joiner_pipes | secondary_bigjoiner_pipes | + secondary_ultrajoiner_pipes; } -static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes, u8 secondary_pipes) +static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes, + u8 secondary_pipes, bool ultrajoiner_used) { if ((secondary_pipes & BIT(pipe)) == 0) return pipe; @@ -3700,27 +3763,37 @@ static enum pipe get_joiner_primary_pipe(enum pipe pipe, u8 primary_pipes, u8 se /* ignore everything above our pipe */ primary_pipes &= ~GENMASK(7, pipe); - /* highest remaining bit should be our primary pipe */ - return fls(primary_pipes) - 1; + if (!ultrajoiner_used) + /* highest remaining bit should be our master pipe */ + return fls(primary_pipes) - 1; + + /* lowest remaining bit should be our primary master pipe */ + return ffs(primary_pipes) - 1; } -static u8 get_joiner_secondary_pipes(enum pipe pipe, u8 primary_pipes, u8 secondary_pipes) +static u8 get_joiner_secondary_pipes(enum pipe pipe, u8 primary_pipes, + u8 secondary_pipes, bool ultrajoiner_used) { enum pipe primary_pipe, next_primary_pipe; - primary_pipe = get_joiner_primary_pipe(pipe, primary_pipes, secondary_pipes); + primary_pipe = get_joiner_primary_pipe(pipe, primary_pipes, + secondary_pipes, ultrajoiner_used); if ((primary_pipes & BIT(primary_pipe)) == 0) return 0; - /* ignore our primary pipe and everything below it */ - primary_pipes &= ~GENMASK(primary_pipe, 0); - /* make sure a high bit is set for the ffs() */ - primary_pipes |= BIT(7); - /* lowest remaining bit should be the next primary pipe */ - next_primary_pipe = ffs(primary_pipes) - 1; + if (!ultrajoiner_used) { + /* ignore our primary pipe and everything below it */ + primary_pipes &= ~GENMASK(primary_pipe, 0); + /* make sure a high bit is set for the ffs() */ + primary_pipes |= BIT(7); + /* lowest remaining bit should be the next primary pipe */ + next_primary_pipe = ffs(primary_pipes) - 1; - return secondary_pipes & GENMASK(next_primary_pipe - 1, primary_pipe); + return secondary_pipes & GENMASK(next_primary_pipe - 1, primary_pipe); + } else { + return (secondary_pipes | primary_pipes) & ~BIT(primary_pipe); + } } static u8 hsw_panel_transcoders(struct drm_i915_private *i915) @@ -3741,6 +3814,7 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc) enum transcoder cpu_transcoder; u8 primary_pipes, secondary_pipes; u8 enabled_transcoders = 0; + bool ultrajoiner_used; /* * XXX: Do intel_display_power_get_if_enabled before reading this (for @@ -3791,11 +3865,12 @@ static u8 hsw_enabled_transcoders(struct intel_crtc *crtc) if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder)) enabled_transcoders |= BIT(cpu_transcoder); - /* joiner secondary -> consider the primary pipe's transcoder as well */ - enabled_joiner_pipes(dev_priv, &primary_pipes, &secondary_pipes); + /* joiner slave -> consider the master pipe's transcoder as well */ + enabled_joiner_pipes(dev_priv, &primary_pipes, &secondary_pipes, &ultrajoiner_used); if (secondary_pipes & BIT(crtc->pipe)) { cpu_transcoder = (enum transcoder) - get_joiner_primary_pipe(crtc->pipe, primary_pipes, secondary_pipes); + get_joiner_primary_pipe(crtc->pipe, primary_pipes, + secondary_pipes, ultrajoiner_used); if (transcoder_ddi_func_is_enabled(dev_priv, cpu_transcoder)) enabled_transcoders |= BIT(cpu_transcoder); } @@ -3927,16 +4002,18 @@ static void intel_joiner_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); u8 primary_pipes, secondary_pipes; + bool ultrajoiner_used; enum pipe pipe = crtc->pipe; - enabled_joiner_pipes(i915, &primary_pipes, &secondary_pipes); + enabled_joiner_pipes(i915, &primary_pipes, &secondary_pipes, &ultrajoiner_used); if (((primary_pipes | secondary_pipes) & BIT(pipe)) == 0) return; - crtc_state->joiner_pipes = - BIT(get_joiner_primary_pipe(pipe, primary_pipes, secondary_pipes)) | - get_joiner_secondary_pipes(pipe, primary_pipes, secondary_pipes); + crtc_state->joiner_pipes = BIT(get_joiner_primary_pipe(pipe, primary_pipes, + secondary_pipes, ultrajoiner_used)) | + get_joiner_secondary_pipes(pipe, primary_pipes, + secondary_pipes, ultrajoiner_used); } static bool hsw_get_pipe_config(struct intel_crtc *crtc, diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h index f921ad67b587..db07c9775892 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h @@ -37,6 +37,9 @@ #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 ULTRA_JOINER_ENABLE REG_BIT(23) +#define PRIMARY_ULTRA_JOINER_ENABLE REG_BIT(22) #define UNCOMPRESSED_JOINER_PRIMARY (1 << 21) #define UNCOMPRESSED_JOINER_SECONDARY (1 << 20) From patchwork Wed Aug 21 10:19:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [11/29] drm/i915/display/vdsc: Add ultrajoiner support with DSC From: Ankit Nautiyal X-Patchwork-Id: 609643 Message-Id: <20240821101945.273525-12-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:27 +0530 From: Stanislav Lisovskiy Add changes to DSC which are required for Ultrajoiner. v2: Use correct helper for setting bits for bigjoiner secondary. (Ankit) Signed-off-by: Stanislav Lisovskiy Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_vdsc.c | 24 ++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 8158e3702ed5..d9c55470bda9 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -379,8 +379,11 @@ static int intel_dsc_get_vdsc_per_pipe(const struct intel_crtc_state *crtc_state int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state) { int num_vdsc_instances = intel_dsc_get_vdsc_per_pipe(crtc_state); + int joined_pipes = intel_joiner_num_pipes(crtc_state); - if (crtc_state->joiner_pipes) + if (joined_pipes == 4) + num_vdsc_instances *= 4; + else if (joined_pipes == 2) num_vdsc_instances *= 2; return num_vdsc_instances; @@ -751,6 +754,13 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state) } } +static bool intel_crtc_ultrajoiner_enable_needed(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + return intel_joiner_num_pipes(crtc_state) == 4 && crtc->pipe != PIPE_D; +} + void intel_dsc_enable(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -770,7 +780,19 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state) dss_ctl1_val |= JOINER_ENABLE; } if (crtc_state->joiner_pipes) { + /* + * This bit doesn't seem to follow master/slave logic or + * any other logic, so lets just add helper function to + * at least hide this hassle.. + */ + if (intel_crtc_ultrajoiner_enable_needed(crtc_state)) + dss_ctl1_val |= ULTRA_JOINER_ENABLE; + + if (intel_crtc_is_ultrajoiner_primary(crtc_state)) + dss_ctl1_val |= PRIMARY_ULTRA_JOINER_ENABLE; + dss_ctl1_val |= BIG_JOINER_ENABLE; + if (intel_crtc_is_bigjoiner_primary(crtc_state)) dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE; } From patchwork Wed Aug 21 10:19:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [12/29] drm/i915/display: Modify maxdotclock helper for ultrajoiner From: Ankit Nautiyal X-Patchwork-Id: 609644 Message-Id: <20240821101945.273525-13-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:28 +0530 With ultrajoiner maxdotclock supported is 4 * maxdotclock. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 29ee27a8041b..68e0d628fe11 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8149,6 +8149,9 @@ static int max_dotclock(struct drm_i915_private *i915) if (DISPLAY_VER(i915) >= 11) max_dotclock *= 2; + if (IS_DGFX(i915) && DISPLAY_VER(i915) >= 14) + max_dotclock *= 4; + return max_dotclock; } From patchwork Wed Aug 21 10:19:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [13/29] drm/i915: Compute config and mode valid changes for ultrajoiner From: Ankit Nautiyal X-Patchwork-Id: 609645 Message-Id: <20240821101945.273525-14-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:29 +0530 From: Stanislav Lisovskiy Implement required changes for mode validation and compute config, to support Ultrajoiner. This also includes required DSC changes and checks. v2: -Use enum for Ultrajoiner pipes. -Drop changes for HDMI. -Separate out DSC changes into another patch. Signed-off-by: Stanislav Lisovskiy Signed-off-by: Ankit Nautiyal --- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 71 +++++++++++++++---- drivers/gpu/drm/i915/display/intel_dp.h | 7 +- drivers/gpu/drm/i915/display/intel_dp_mst.c | 15 ++-- 4 files changed, 71 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 129408bd0d3a..f2d04a2fa09e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -616,6 +616,7 @@ struct intel_hdcp { enum intel_joiner_pipe_count { INTEL_PIPE_JOINER_NONE = 0, INTEL_PIPE_JOINER_BIG = 2, + INTEL_PIPE_JOINER_ULTRA = 4, INTEL_PIPE_JOINER_INVALID, }; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index b2058e5e54b3..5a47f460c80a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -868,24 +868,34 @@ u32 get_max_compressed_bpp_with_joiner(struct drm_i915_private *i915, enum intel_joiner_pipe_count joined_pipes) { u32 max_bpp_small_joiner_ram; + u32 max_bpp_joiner; /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */ max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) / mode_hdisplay; + max_bpp_joiner = max_bpp_small_joiner_ram; - if (joined_pipes == INTEL_PIPE_JOINER_BIG) { - int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24; + /* if ultra joiner is enabled, we have 2 bigjoiners enabled */ + if (joined_pipes == INTEL_PIPE_JOINER_BIG || + joined_pipes == INTEL_PIPE_JOINER_ULTRA) { + int joiner_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 / + max_bpp_joiner = + i915->display.cdclk.max_cdclk_freq * ppc * joiner_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); } + if (joined_pipes == INTEL_PIPE_JOINER_ULTRA) { + /* TODO: Check for ultrajoiner ram constraints */ - return max_bpp_small_joiner_ram; + /* both get multiplied by 2, because ram bits/ppc now doubled */ + max_bpp_small_joiner_ram *= 2; + max_bpp_joiner *= 2; + } + + return min(max_bpp_small_joiner_ram, max_bpp_joiner); } u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915, @@ -991,6 +1001,10 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, if (joined_pipes == INTEL_PIPE_JOINER_BIG && test_slice_count < 4) continue; + /* ultrajoiner needs 2 bigjoiners to be enabled */ + if (joined_pipes == INTEL_PIPE_JOINER_ULTRA && test_slice_count < 8) + continue; + if (min_slice_count <= test_slice_count) return test_slice_count; } @@ -1267,9 +1281,9 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, return MODE_OK; } -bool intel_dp_need_joiner(struct intel_dp *intel_dp, - struct intel_connector *connector, - int hdisplay, int clock) +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, + struct intel_connector *connector, + int hdisplay, int clock) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); @@ -1300,6 +1314,25 @@ bool intel_dp_has_dsc(const struct intel_connector *connector) return true; } +static +bool intel_can_ultrajoiner(const struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + return IS_DGFX(i915) && DISPLAY_VER(i915) >= 14; +} + +bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock) +{ + const struct intel_encoder *encoder = &dp_to_dig_port(dp)->base; + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + if (!intel_can_ultrajoiner(encoder)) + return false; + + return clock > (i915->display.cdclk.max_dotclk_freq * 2); +} + static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *_connector, struct drm_display_mode *mode) @@ -1336,11 +1369,15 @@ intel_dp_mode_valid(struct drm_connector *_connector, target_clock = fixed_mode->clock; } - if (intel_dp_need_joiner(intel_dp, connector, - mode->hdisplay, target_clock)) { + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) { + joined_pipes = INTEL_PIPE_JOINER_ULTRA; + max_dotclk *= INTEL_PIPE_JOINER_ULTRA; + } else if (intel_dp_need_bigjoiner(intel_dp, connector, + mode->hdisplay, target_clock)) { joined_pipes = INTEL_PIPE_JOINER_BIG; max_dotclk *= INTEL_PIPE_JOINER_BIG; } + if (target_clock > max_dotclk) return MODE_CLOCK_HIGH; @@ -2514,8 +2551,10 @@ bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, * Pipe joiner needs compression up to display 12 due to bandwidth * limitation. DG2 onwards pipe joiner can be enabled without * compression. + * Ultrajoiner always needs compression. */ - return DISPLAY_VER(i915) < 13 && (joined_pipes == INTEL_PIPE_JOINER_BIG); + return (DISPLAY_VER(i915) < 13 && (joined_pipes == INTEL_PIPE_JOINER_BIG)) || + joined_pipes == INTEL_PIPE_JOINER_ULTRA; } static int @@ -2540,9 +2579,11 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, !intel_dp_supports_fec(intel_dp, connector, pipe_config)) return -EINVAL; - if (intel_dp_need_joiner(intel_dp, connector, - adjusted_mode->crtc_hdisplay, - adjusted_mode->crtc_clock)) + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock)) + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe); + else if (intel_dp_need_bigjoiner(intel_dp, connector, + adjusted_mode->crtc_hdisplay, + adjusted_mode->crtc_clock)) pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); joined_pipes = intel_joiner_num_pipes(pipe_config); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index f284058f5148..b413b9f5fdf8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -155,9 +155,10 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, int mode_clock, int mode_hdisplay, enum intel_joiner_pipe_count joined_pipes); -bool intel_dp_need_joiner(struct intel_dp *intel_dp, - struct intel_connector *connector, - int hdisplay, int clock); +bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, + struct intel_connector *connector, + int hdisplay, int clock); +bool intel_dp_need_ultrajoiner(struct intel_dp *intel_dp, int clock); static inline unsigned int intel_dp_unused_lane_mask(int lane_count) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 9dc12b799414..7485a4d76876 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -580,9 +580,11 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; - if (intel_dp_need_joiner(intel_dp, connector, - adjusted_mode->crtc_hdisplay, - adjusted_mode->crtc_clock)) + if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock)) + pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe); + else if (intel_dp_need_bigjoiner(intel_dp, connector, + adjusted_mode->crtc_hdisplay, + adjusted_mode->crtc_clock)) pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB; @@ -1473,8 +1475,11 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, * corresponding link capabilities of the sink) in case the * stream is uncompressed for it by the last branch device. */ - if (intel_dp_need_joiner(intel_dp, intel_connector, - mode->hdisplay, target_clock)) { + if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) { + joined_pipes = INTEL_PIPE_JOINER_BIG; + max_dotclk *= INTEL_PIPE_JOINER_BIG; + } else if (intel_dp_need_bigjoiner(intel_dp, intel_connector, + mode->hdisplay, target_clock)) { joined_pipes = INTEL_PIPE_JOINER_BIG; max_dotclk *= INTEL_PIPE_JOINER_BIG; } From patchwork Wed Aug 21 10:19:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [14/29] drm/i915: Add new abstraction layer to handle pipe order for different joiners From: Ankit Nautiyal X-Patchwork-Id: 609646 Message-Id: <20240821101945.273525-15-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:30 +0530 From: Stanislav Lisovskiy Ultrajoiner case requires special treatment where both reverse and staight order iteration doesn't work(for instance disabling case requires order to be: primary master, slaves, secondary master). Lets unify our approach by using not only pipe masks for iterating required pipes based on joiner type used, but also using different "priority" arrays for each of those. v2: Fix checkpatch warnings. (Ankit) Signed-off-by: Stanislav Lisovskiy Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_ddi.c | 19 +++-- drivers/gpu/drm/i915/display/intel_display.c | 89 ++++++++++++++++---- drivers/gpu/drm/i915/display/intel_display.h | 7 ++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 18 ++-- 4 files changed, 102 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 11ee4406dce8..04bbb8dc326b 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3116,10 +3116,11 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state, const struct drm_connector_state *old_conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *pipe_crtc; + struct intel_crtc *pipe_crtc; enum pipe pipe; - for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(old_crtc_state)) { + for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(old_crtc_state), + intel_get_pipe_order_disable(old_crtc_state)) { const struct intel_crtc_state *old_pipe_crtc_state = intel_atomic_get_old_crtc_state(state, pipe_crtc); @@ -3130,8 +3131,9 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state, intel_ddi_disable_transcoder_func(old_crtc_state); - for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(old_crtc_state)) { + for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(old_crtc_state), + intel_get_pipe_order_disable(old_crtc_state)) { const struct intel_crtc_state *old_pipe_crtc_state = intel_atomic_get_old_crtc_state(state, pipe_crtc); @@ -3383,7 +3385,7 @@ static void intel_enable_ddi(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - struct intel_crtc *pipe_crtc; + struct intel_crtc *pipe_crtc; enum pipe pipe; intel_ddi_enable_transcoder_func(encoder, crtc_state); @@ -3394,8 +3396,9 @@ static void intel_enable_ddi(struct intel_atomic_state *state, intel_ddi_wait_for_fec_status(encoder, crtc_state, true); - for_each_intel_crtc_in_pipe_mask_reverse(&i915->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(crtc_state)) { + for_each_intel_crtc_in_mask_priority(i915, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(crtc_state), + intel_get_pipe_order_enable(crtc_state)) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 68e0d628fe11..0f19e933e32a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1731,6 +1731,56 @@ static void hsw_configure_cpu_transcoder(const struct intel_crtc_state *crtc_sta hsw_set_transconf(crtc_state); } +static +bool intel_is_bigjoiner(const struct intel_crtc_state *pipe_config) +{ + return hweight8(pipe_config->joiner_pipes) == 2; +} + +static +bool intel_is_ultrajoiner(const struct intel_crtc_state *pipe_config) +{ + return hweight8(pipe_config->joiner_pipes) == 4; +} + +const enum pipe *intel_get_pipe_order_enable(const struct intel_crtc_state *crtc_state) +{ + static const enum pipe ultrajoiner_pipe_order_enable[I915_MAX_PIPES] = { + PIPE_B, PIPE_D, PIPE_C, PIPE_A + }; + static const enum pipe bigjoiner_pipe_order_enable[I915_MAX_PIPES] = { + PIPE_B, PIPE_A, PIPE_D, PIPE_C + }; + static const enum pipe nojoiner_pipe_order_enable[I915_MAX_PIPES] = { + PIPE_A, PIPE_B, PIPE_C, PIPE_D + }; + + if (intel_is_ultrajoiner(crtc_state)) + return ultrajoiner_pipe_order_enable; + else if (intel_is_bigjoiner(crtc_state)) + return bigjoiner_pipe_order_enable; + return nojoiner_pipe_order_enable; +} + +const enum pipe *intel_get_pipe_order_disable(const struct intel_crtc_state *crtc_state) +{ + static const enum pipe ultrajoiner_pipe_order_disable[I915_MAX_PIPES] = { + PIPE_A, PIPE_B, PIPE_D, PIPE_C + }; + static const enum pipe bigjoiner_pipe_order_disable[I915_MAX_PIPES] = { + PIPE_A, PIPE_B, PIPE_C, PIPE_D + }; + static const enum pipe nojoiner_pipe_order_disable[I915_MAX_PIPES] = { + PIPE_A, PIPE_B, PIPE_C, PIPE_D + }; + + if (intel_is_ultrajoiner(crtc_state)) + return ultrajoiner_pipe_order_disable; + else if (intel_is_bigjoiner(crtc_state)) + return bigjoiner_pipe_order_disable; + return nojoiner_pipe_order_disable; +} + static void hsw_crtc_enable(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -1738,19 +1788,21 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder; - struct intel_crtc *pipe_crtc; + struct intel_crtc *pipe_crtc; enum pipe pipe; if (drm_WARN_ON(&dev_priv->drm, crtc->active)) return; - for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(new_crtc_state)) + for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(new_crtc_state), + intel_get_pipe_order_enable(new_crtc_state)) intel_dmc_enable_pipe(dev_priv, pipe_crtc->pipe); intel_encoders_pre_pll_enable(state, crtc); - for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(new_crtc_state)) { + for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(new_crtc_state), + intel_get_pipe_order_enable(new_crtc_state)) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); @@ -1760,8 +1812,9 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_encoders_pre_enable(state, crtc); - for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(new_crtc_state)) { + for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(new_crtc_state), + intel_get_pipe_order_enable(new_crtc_state)) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); @@ -1779,8 +1832,9 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (!transcoder_is_dsi(cpu_transcoder)) hsw_configure_cpu_transcoder(new_crtc_state); - for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(new_crtc_state)) { + for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(new_crtc_state), + intel_get_pipe_order_enable(new_crtc_state)) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); @@ -1815,8 +1869,9 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_encoders_enable(state, crtc); - for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(new_crtc_state)) { + for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(new_crtc_state), + intel_get_pipe_order_enable(new_crtc_state)) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); enum pipe hsw_workaround_pipe; @@ -1901,7 +1956,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); - struct intel_crtc *pipe_crtc; + struct intel_crtc *pipe_crtc; enum pipe pipe; /* * FIXME collapse everything to one hook. @@ -1910,8 +1965,9 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); intel_encoders_post_disable(state, crtc); - for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(old_crtc_state)) { + for_each_intel_crtc_in_mask_priority(i915, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(old_crtc_state), + intel_get_pipe_order_disable(old_crtc_state)) { const struct intel_crtc_state *old_pipe_crtc_state = intel_atomic_get_old_crtc_state(state, pipe_crtc); @@ -1920,8 +1976,9 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_post_pll_disable(state, crtc); - for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(old_crtc_state)) + for_each_intel_crtc_in_mask_priority(i915, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(old_crtc_state), + intel_get_pipe_order_disable(old_crtc_state)) intel_dmc_disable_pipe(i915, pipe_crtc->pipe); } diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 35e68e4cc712..4cfd1da0bbc0 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -275,6 +275,11 @@ enum phy_fia { &(dev)->mode_config.crtc_list, \ base.head) +#define for_each_intel_crtc_in_mask_priority(__dev_priv, intel_crtc, __p, __mask, __priolist) \ + for_each_pipe(__dev_priv, __p) \ + for_each_if((__mask) & BIT(__priolist[__p])) \ + for_each_if(intel_crtc = intel_crtc_for_pipe(__dev_priv, __priolist[__p])) + #define for_each_intel_crtc_in_pipe_mask(dev, intel_crtc, pipe_mask) \ list_for_each_entry(intel_crtc, \ &(dev)->mode_config.crtc_list, \ @@ -432,6 +437,8 @@ bool intel_crtc_is_ultrajoiner(const struct intel_crtc_state *crtc_state); bool intel_crtc_is_ultrajoiner_primary(const struct intel_crtc_state *crtc_state); u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state); struct intel_crtc *intel_joiner_primary_crtc(const struct intel_crtc_state *crtc_state); +const enum pipe *intel_get_pipe_order_enable(const struct intel_crtc_state *crtc_state); +const enum pipe *intel_get_pipe_order_disable(const struct intel_crtc_state *crtc_state); bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state); bool intel_pipe_config_compare(const struct intel_crtc_state *current_config, const struct intel_crtc_state *pipe_config, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 7485a4d76876..67794c4254e3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -1008,7 +1008,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, 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); - struct intel_crtc *pipe_crtc; + struct intel_crtc *pipe_crtc; enum pipe pipe; bool last_mst_stream; intel_dp->active_mst_links--; @@ -1017,8 +1017,9 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, DISPLAY_VER(dev_priv) >= 12 && last_mst_stream && !intel_dp_mst_is_master_trans(old_crtc_state)); - for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(old_crtc_state)) { + for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(old_crtc_state), + intel_get_pipe_order_disable(old_crtc_state)) { const struct intel_crtc_state *old_pipe_crtc_state = intel_atomic_get_old_crtc_state(state, pipe_crtc); @@ -1042,8 +1043,9 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, intel_ddi_disable_transcoder_func(old_crtc_state); - for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(old_crtc_state)) { + for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(old_crtc_state), + intel_get_pipe_order_disable(old_crtc_state)) { const struct intel_crtc_state *old_pipe_crtc_state = intel_atomic_get_old_crtc_state(state, pipe_crtc); @@ -1262,6 +1264,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, enum transcoder trans = pipe_config->cpu_transcoder; bool first_mst_stream = intel_dp->active_mst_links == 1; struct intel_crtc *pipe_crtc; + enum pipe pipe; int ret; drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder); @@ -1309,8 +1312,9 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, intel_enable_transcoder(pipe_config); - for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, - intel_crtc_joined_pipe_mask(pipe_config)) { + for_each_intel_crtc_in_mask_priority(dev_priv, pipe_crtc, pipe, + intel_crtc_joined_pipe_mask(pipe_config), + intel_get_pipe_order_enable(pipe_config)) { const struct intel_crtc_state *pipe_crtc_state = intel_atomic_get_new_crtc_state(state, pipe_crtc); From patchwork Wed Aug 21 10:19:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [15/29] drm/i915/intel_dp: Add support for forcing ultrajoiner From: Ankit Nautiyal X-Patchwork-Id: 609647 Message-Id: <20240821101945.273525-16-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:31 +0530 Allow forcing ultrajoiner through debugfs. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp.c | 11 +++++++---- drivers/gpu/drm/i915/display/intel_dp.h | 4 +++- drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 ++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 5a47f460c80a..9fc1ec301b72 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1322,7 +1322,9 @@ bool intel_can_ultrajoiner(const struct intel_encoder *encoder) return IS_DGFX(i915) && DISPLAY_VER(i915) >= 14; } -bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock) +bool intel_dp_need_ultrajoiner(struct intel_dp *dp, + struct intel_connector *connector, + int clock) { const struct intel_encoder *encoder = &dp_to_dig_port(dp)->base; struct drm_i915_private *i915 = to_i915(encoder->base.dev); @@ -1330,7 +1332,8 @@ bool intel_dp_need_ultrajoiner(struct intel_dp *dp, int clock) if (!intel_can_ultrajoiner(encoder)) return false; - return clock > (i915->display.cdclk.max_dotclk_freq * 2); + return clock > (i915->display.cdclk.max_dotclk_freq * 2) || + connector->force_joined_pipes == INTEL_PIPE_JOINER_ULTRA; } static enum drm_mode_status @@ -1369,7 +1372,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, target_clock = fixed_mode->clock; } - if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) { + if (intel_dp_need_ultrajoiner(intel_dp, connector, target_clock)) { joined_pipes = INTEL_PIPE_JOINER_ULTRA; max_dotclk *= INTEL_PIPE_JOINER_ULTRA; } else if (intel_dp_need_bigjoiner(intel_dp, connector, @@ -2579,7 +2582,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, !intel_dp_supports_fec(intel_dp, connector, pipe_config)) return -EINVAL; - if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock)) + if (intel_dp_need_ultrajoiner(intel_dp, connector, adjusted_mode->crtc_clock)) pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe); else if (intel_dp_need_bigjoiner(intel_dp, connector, adjusted_mode->crtc_hdisplay, diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index b413b9f5fdf8..748e1a94afd2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -158,7 +158,9 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, struct intel_connector *connector, int hdisplay, int clock); -bool intel_dp_need_ultrajoiner(struct intel_dp *intel_dp, int clock); +bool intel_dp_need_ultrajoiner(struct intel_dp *intel_dp, + struct intel_connector *connector, + int clock); static inline unsigned int intel_dp_unused_lane_mask(int lane_count) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 67794c4254e3..c5d32bf66b55 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -580,7 +580,8 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; - if (intel_dp_need_ultrajoiner(intel_dp, adjusted_mode->crtc_clock)) + if (intel_dp_need_ultrajoiner(intel_dp, connector, + adjusted_mode->crtc_clock)) pipe_config->joiner_pipes = GENMASK(crtc->pipe + 3, crtc->pipe); else if (intel_dp_need_bigjoiner(intel_dp, connector, adjusted_mode->crtc_hdisplay, @@ -1479,7 +1480,8 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, * corresponding link capabilities of the sink) in case the * stream is uncompressed for it by the last branch device. */ - if (intel_dp_need_ultrajoiner(intel_dp, target_clock)) { + if (intel_dp_need_ultrajoiner(intel_dp, intel_connector, + target_clock)) { joined_pipes = INTEL_PIPE_JOINER_BIG; max_dotclk *= INTEL_PIPE_JOINER_BIG; } else if (intel_dp_need_bigjoiner(intel_dp, intel_connector, From patchwork Wed Aug 21 10:19:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [16/29] drm/i915/display: Prepare for dsc 3 stream splitter From: Ankit Nautiyal X-Patchwork-Id: 609648 Message-Id: <20240821101945.273525-17-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:32 +0530 At the moment dsc_split represents that dsc splitter is used or not. With 3 DSC engines, the splitter can split into two streams or three streams. Use enum for dsc_split to make space for case with three streams. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/icl_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 2 +- .../gpu/drm/i915/display/intel_display_types.h | 7 ++++++- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_vdsc.c | 16 +++++++++++++--- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 55dd57d1bf94..2c3e212b264a 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1594,7 +1594,7 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder, /* FIXME: split only when necessary */ if (crtc_state->dsc.slice_count > 1) - crtc_state->dsc.dsc_split = true; + crtc_state->dsc.dsc_split = DSC_SPLIT_2_STREAMS; /* FIXME: initialize from VBT */ vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0f19e933e32a..806670ea589e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5716,7 +5716,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(dsc.config.nsl_bpg_offset); PIPE_CONF_CHECK_BOOL(dsc.compression_enable); - PIPE_CONF_CHECK_BOOL(dsc.dsc_split); + PIPE_CONF_CHECK_I(dsc.dsc_split); PIPE_CONF_CHECK_I(dsc.compressed_bpp_x16); PIPE_CONF_CHECK_BOOL(splitter.enable); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f2d04a2fa09e..5aefd7800659 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1043,6 +1043,11 @@ struct intel_csc_matrix { u16 postoff[3]; }; +enum intel_dsc_split_state { + DSC_SPLIT_DISABLED, + DSC_SPLIT_2_STREAMS, +}; + struct intel_crtc_state { /* * uapi (drm) state. This is the software state shown to userspace. @@ -1368,7 +1373,7 @@ struct intel_crtc_state { /* Display Stream compression state */ struct { bool compression_enable; - bool dsc_split; + enum intel_dsc_split_state dsc_split; /* Compressed Bpp in U6.4 format (first 4 bits for fractional part) */ u16 compressed_bpp_x16; u8 slice_count; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9fc1ec301b72..8847881e2ace 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2412,7 +2412,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, * then we need to use 2 VDSC instances. */ if (pipe_config->joiner_pipes || pipe_config->dsc.slice_count > 1) - pipe_config->dsc.dsc_split = true; + pipe_config->dsc.dsc_split = DSC_SPLIT_2_STREAMS; ret = intel_dp_dsc_compute_params(connector, pipe_config); if (ret < 0) { diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index d9c55470bda9..198478453770 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -373,7 +373,14 @@ intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder) static int intel_dsc_get_vdsc_per_pipe(const struct intel_crtc_state *crtc_state) { - return crtc_state->dsc.dsc_split ? 2 : 1; + switch (crtc_state->dsc.dsc_split) { + case DSC_SPLIT_2_STREAMS : + return 2; + case DSC_SPLIT_DISABLED : + default : + break; + } + return 1; } int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state) @@ -985,8 +992,11 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state) if (!crtc_state->dsc.compression_enable) goto out; - crtc_state->dsc.dsc_split = (dss_ctl2 & RIGHT_BRANCH_VDSC_ENABLE) && - (dss_ctl1 & JOINER_ENABLE); + if ((dss_ctl1 & JOINER_ENABLE) && + (dss_ctl2 & RIGHT_BRANCH_VDSC_ENABLE)) + crtc_state->dsc.dsc_split = DSC_SPLIT_2_STREAMS; + else + crtc_state->dsc.dsc_split = DSC_SPLIT_DISABLED; intel_dsc_get_pps_config(crtc_state); out: From patchwork Wed Aug 21 10:19:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [17/29] drm/i915/vdsc: Use VDSC0/VDSC1 for LEFT/RIGHT VDSC engine From: Ankit Nautiyal X-Patchwork-Id: 609649 Message-Id: <20240821101945.273525-18-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:33 +0530 Drop use of LEFT/RIGHT VDSC engine and use VDSC0/VDSC1 instead. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_vdsc.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_vdsc_regs.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 198478453770..ad0d91403cb7 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -781,9 +781,9 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state) intel_dsc_pps_configure(crtc_state); - dss_ctl2_val |= LEFT_BRANCH_VDSC_ENABLE; + dss_ctl2_val |= VDSC0_ENABLE; if (vdsc_instances_per_pipe > 1) { - dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE; + dss_ctl2_val |= VDSC1_ENABLE; dss_ctl1_val |= JOINER_ENABLE; } if (crtc_state->joiner_pipes) { @@ -988,12 +988,12 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state) dss_ctl1 = intel_de_read(dev_priv, dss_ctl1_reg(crtc, cpu_transcoder)); dss_ctl2 = intel_de_read(dev_priv, dss_ctl2_reg(crtc, cpu_transcoder)); - crtc_state->dsc.compression_enable = dss_ctl2 & LEFT_BRANCH_VDSC_ENABLE; + crtc_state->dsc.compression_enable = dss_ctl2 & VDSC0_ENABLE; if (!crtc_state->dsc.compression_enable) goto out; if ((dss_ctl1 & JOINER_ENABLE) && - (dss_ctl2 & RIGHT_BRANCH_VDSC_ENABLE)) + (dss_ctl2 & VDSC1_ENABLE)) crtc_state->dsc.dsc_split = DSC_SPLIT_2_STREAMS; else crtc_state->dsc.dsc_split = DSC_SPLIT_DISABLED; diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h index db07c9775892..87d230f061e5 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h @@ -21,8 +21,8 @@ #define MAX_DL_BUFFER_TARGET_DEPTH 0x5a0 #define DSS_CTL2 _MMIO(0x67404) -#define LEFT_BRANCH_VDSC_ENABLE (1 << 31) -#define RIGHT_BRANCH_VDSC_ENABLE (1 << 15) +#define VDSC0_ENABLE REG_BIT(31) +#define VDSC1_ENABLE REG_BIT(15) #define RIGHT_DL_BUF_TARGET_DEPTH_MASK (0xfff << 0) #define RIGHT_DL_BUF_TARGET_DEPTH(pixels) ((pixels) << 0) From patchwork Wed Aug 21 10:19:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [18/29] drm/i915/vdsc: Add register bits for VDSC2 engine From: Ankit Nautiyal X-Patchwork-Id: 609650 Message-Id: <20240821101945.273525-19-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:34 +0530 Add bits to enable third VDSC engine VDSC2. Signed-off-by: Ankit Nautiyal --- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_vdsc.c | 20 +++++++++++++++---- .../gpu/drm/i915/display/intel_vdsc_regs.h | 4 ++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 5aefd7800659..dfb087e914a7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1046,6 +1046,7 @@ struct intel_csc_matrix { enum intel_dsc_split_state { DSC_SPLIT_DISABLED, DSC_SPLIT_2_STREAMS, + DSC_SPLIT_3_STREAMS, }; struct intel_crtc_state { diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index ad0d91403cb7..7900c104f338 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -376,6 +376,8 @@ static int intel_dsc_get_vdsc_per_pipe(const struct intel_crtc_state *crtc_state switch (crtc_state->dsc.dsc_split) { case DSC_SPLIT_2_STREAMS : return 2; + case DSC_SPLIT_3_STREAMS : + return 3; case DSC_SPLIT_DISABLED : default : break; @@ -786,6 +788,12 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state) dss_ctl2_val |= VDSC1_ENABLE; dss_ctl1_val |= JOINER_ENABLE; } + + if (vdsc_instances_per_pipe > 2) { + dss_ctl2_val |= VDSC2_ENABLE; + dss_ctl2_val |= SMALL_JOINER_CONFIG_3_ENGINES; + } + if (crtc_state->joiner_pipes) { /* * This bit doesn't seem to follow master/slave logic or @@ -992,11 +1000,15 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state) if (!crtc_state->dsc.compression_enable) goto out; - if ((dss_ctl1 & JOINER_ENABLE) && - (dss_ctl2 & VDSC1_ENABLE)) - crtc_state->dsc.dsc_split = DSC_SPLIT_2_STREAMS; - else + if (dss_ctl1 & JOINER_ENABLE) { + if (dss_ctl2 & (VDSC2_ENABLE | SMALL_JOINER_CONFIG_3_ENGINES)) + crtc_state->dsc.dsc_split = DSC_SPLIT_3_STREAMS; + + else if (dss_ctl2 & VDSC1_ENABLE) + crtc_state->dsc.dsc_split = DSC_SPLIT_2_STREAMS; + } else { crtc_state->dsc.dsc_split = DSC_SPLIT_DISABLED; + } intel_dsc_get_pps_config(crtc_state); out: diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h index 87d230f061e5..3ee99ad07adb 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h @@ -22,6 +22,10 @@ #define DSS_CTL2 _MMIO(0x67404) #define VDSC0_ENABLE REG_BIT(31) +#define VDSC2_ENABLE REG_BIT(30) +#define SMALL_JOINER_CONFIG_3_ENGINES REG_BIT(23) +#define ODD_PIXEL_REMOVAL REG_BIT(18) +#define ODD_PIXEL_REMOVAL_CONFIG_EOL REG_BIT(17) #define VDSC1_ENABLE REG_BIT(15) #define RIGHT_DL_BUF_TARGET_DEPTH_MASK (0xfff << 0) #define RIGHT_DL_BUF_TARGET_DEPTH(pixels) ((pixels) << 0) From patchwork Wed Aug 21 10:19:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [19/29] drm/i915/vdsc: Add support for read/write PPS for DSC3 From: Ankit Nautiyal X-Patchwork-Id: 609651 Message-Id: <20240821101945.273525-20-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:35 +0530 With BMG each pipe has 3 DSC engines, so add bits to read/write the PPS registers for the 3rd VDSC engine. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_vdsc.c | 8 +++++--- drivers/gpu/drm/i915/display/intel_vdsc_regs.h | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 7900c104f338..0e2c504b057c 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -408,8 +408,10 @@ static void intel_dsc_get_pps_reg(const struct intel_crtc_state *crtc_state, int pipe_dsc = is_pipe_dsc(crtc, cpu_transcoder); - if (dsc_reg_num >= 3) + if (dsc_reg_num >= 4) MISSING_CASE(dsc_reg_num); + if (dsc_reg_num >= 3) + dsc_reg[2] = BMG_DSC2_PPS(pipe, pps); if (dsc_reg_num >= 2) dsc_reg[1] = pipe_dsc ? ICL_DSC1_PPS(pipe, pps) : DSCC_PPS(pps); if (dsc_reg_num >= 1) @@ -421,7 +423,7 @@ static void intel_dsc_pps_write(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); - i915_reg_t dsc_reg[2]; + i915_reg_t dsc_reg[3]; int i, vdsc_per_pipe, dsc_reg_num; vdsc_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state); @@ -833,7 +835,7 @@ static u32 intel_dsc_pps_read(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); - i915_reg_t dsc_reg[2]; + i915_reg_t dsc_reg[3]; int i, vdsc_per_pipe, dsc_reg_num; u32 val; diff --git a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h index 3ee99ad07adb..6f7bea3a7dee 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h @@ -62,8 +62,10 @@ #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 _BMG_DSC2_PICTURE_PARAMETER_SET_0_PB 0x78970 #define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PC 0x78470 #define _ICL_DSC1_PICTURE_PARAMETER_SET_0_PC 0x78570 +#define _BMG_DSC2_PICTURE_PARAMETER_SET_0_PC 0x78A70 #define ICL_DSC0_PICTURE_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe) - PIPE_B, \ _ICL_DSC0_PICTURE_PARAMETER_SET_0_PB, \ _ICL_DSC0_PICTURE_PARAMETER_SET_0_PC) @@ -76,8 +78,12 @@ #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 _BMG_DSC2_PPS_0(pipe) _PICK_EVEN((pipe) - PIPE_B, \ + _BMG_DSC2_PICTURE_PARAMETER_SET_0_PB, \ + _BMG_DSC2_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)) +#define BMG_DSC2_PPS(pipe, pps) _MMIO(_BMG_DSC2_PPS_0(pipe) + ((pps) * 4)) /* PPS 0 */ #define DSC_PPS0_NATIVE_422_ENABLE REG_BIT(23) From patchwork Wed Aug 21 10:19:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [20/29] drm/i915/dp: Add check for hdisplay divisible by slice count From: Ankit Nautiyal X-Patchwork-Id: 609652 Message-Id: <20240821101945.273525-21-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:36 +0530 As per Bspec:49259 while computing the dsc slice count, we need to ensure that mode->hdisplay is divisible by the slice count. This check is there for DSI, where we select slice_count from bios, but is missing for DP. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 8847881e2ace..49ee6dcca8c4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1005,6 +1005,9 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, if (joined_pipes == INTEL_PIPE_JOINER_ULTRA && test_slice_count < 8) continue; + if (mode_hdisplay % test_slice_count) + continue; + if (min_slice_count <= test_slice_count) return test_slice_count; } From patchwork Wed Aug 21 10:19:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [21/29] drm/i915/display: Add DSC pixel replication From: Ankit Nautiyal X-Patchwork-Id: 609654 Message-Id: <20240821101945.273525-22-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:37 +0530 With 3 VDSC engines and Ultrajoiner, we may encounter a situation where hdisplay is not a multiple of slice count. In this case we need to add extra pixels to the last slice to distribute pixels evenly across slices. Add member to store DSC pixel replication when hdisplay is not divisible by slice_width. Fill DSS_CTL3 register with the pixel replication count. TODO: 1. Scaler: If the DSC is enabled and pixel replication is occurring, then the scaler window size and position must fit within the pipe active size plus the pixel replication. 2. PIPE_SRC: Horizontal Src size must always be programmed to the same value as the Horizontal Active except when panel fitting is enabled or DSC pixel replication is enabled. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 1 + .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_vdsc.c | 21 ++++++++++++++++++- .../gpu/drm/i915/display/intel_vdsc_regs.h | 8 +++++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 806670ea589e..dbb6c51d4ac9 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5718,6 +5718,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(dsc.compression_enable); PIPE_CONF_CHECK_I(dsc.dsc_split); PIPE_CONF_CHECK_I(dsc.compressed_bpp_x16); + PIPE_CONF_CHECK_I(dsc.pixel_replication_count); PIPE_CONF_CHECK_BOOL(splitter.enable); PIPE_CONF_CHECK_I(splitter.link_count); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index dfb087e914a7..5dd048d37b9a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1378,6 +1378,7 @@ struct intel_crtc_state { /* Compressed Bpp in U6.4 format (first 4 bits for fractional part) */ u16 compressed_bpp_x16; u8 slice_count; + int pixel_replication_count; struct drm_dsc_config config; } dsc; diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 0e2c504b057c..7ce503a41e4a 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -778,6 +778,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; + u32 dss_ctl3_val = 0; int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state); if (!crtc_state->dsc.compression_enable) @@ -813,8 +814,16 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state) if (intel_crtc_is_bigjoiner_primary(crtc_state)) dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE; } + + if (crtc_state->dsc.pixel_replication_count) + dss_ctl3_val = DSC_PIXEL_REPLICATION(crtc_state->dsc.pixel_replication_count); + intel_de_write(dev_priv, dss_ctl1_reg(crtc, crtc_state->cpu_transcoder), dss_ctl1_val); intel_de_write(dev_priv, dss_ctl2_reg(crtc, crtc_state->cpu_transcoder), dss_ctl2_val); + + if (IS_BATTLEMAGE(dev_priv) && dss_ctl3_val) + intel_de_write(dev_priv, + BMG_PIPE_DSS_CTL3(crtc_state->cpu_transcoder), dss_ctl3_val); } void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state) @@ -827,6 +836,9 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state) old_crtc_state->joiner_pipes) { intel_de_write(dev_priv, dss_ctl1_reg(crtc, old_crtc_state->cpu_transcoder), 0); intel_de_write(dev_priv, dss_ctl2_reg(crtc, old_crtc_state->cpu_transcoder), 0); + + if (IS_BATTLEMAGE(dev_priv)) + intel_de_write(dev_priv, BMG_PIPE_DSS_CTL3(old_crtc_state->cpu_transcoder), 0); } } @@ -984,7 +996,7 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state) enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; enum intel_display_power_domain power_domain; intel_wakeref_t wakeref; - u32 dss_ctl1, dss_ctl2; + u32 dss_ctl1, dss_ctl2, dss_ctl3; if (!intel_dsc_source_support(crtc_state)) return; @@ -998,6 +1010,9 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state) dss_ctl1 = intel_de_read(dev_priv, dss_ctl1_reg(crtc, cpu_transcoder)); dss_ctl2 = intel_de_read(dev_priv, dss_ctl2_reg(crtc, cpu_transcoder)); + if (IS_BATTLEMAGE(dev_priv)) + dss_ctl3 = intel_de_read(dev_priv, BMG_PIPE_DSS_CTL3(crtc_state->cpu_transcoder)); + crtc_state->dsc.compression_enable = dss_ctl2 & VDSC0_ENABLE; if (!crtc_state->dsc.compression_enable) goto out; @@ -1012,6 +1027,10 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state) crtc_state->dsc.dsc_split = DSC_SPLIT_DISABLED; } + if (dss_ctl3 & DSC_PIXEL_REPLICATION_MASK) + crtc_state->dsc.pixel_replication_count = + dss_ctl3 & DSC_PIXEL_REPLICATION_MASK; + 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 6f7bea3a7dee..ecf36505128e 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vdsc_regs.h @@ -53,6 +53,14 @@ _ICL_PIPE_DSS_CTL2_PB, \ _ICL_PIPE_DSS_CTL2_PC) +#define _BMG_PIPE_DSS_CTL3_PB 0x782F0 +#define _BMG_PIPE_DSS_CTL3_PC 0x784F0 +#define BMG_PIPE_DSS_CTL3(pipe) _MMIO_PIPE((pipe) - PIPE_B, \ + _BMG_PIPE_DSS_CTL3_PB, \ + _BMG_PIPE_DSS_CTL3_PC) +#define DSC_PIXEL_REPLICATION_MASK REG_GENMASK(15, 0) +#define DSC_PIXEL_REPLICATION(count) ((count) << 0) + /* Icelake Display Stream Compression Registers */ #define DSCA_PICTURE_PARAMETER_SET_0 _MMIO(0x6B200) #define DSCC_PICTURE_PARAMETER_SET_0 _MMIO(0x6BA00) From patchwork Wed Aug 21 10:19:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [22/29] drm/i915/dp: Compute pixel replication count for DSC 12 slices case From: Ankit Nautiyal X-Patchwork-Id: 609653 Message-Id: <20240821101945.273525-23-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:38 +0530 Add check if pixel replication is required while computing slice count and fill the pixel replication count in crtc_state. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp.c | 64 ++++++++++++++++++++- drivers/gpu/drm/i915/display/intel_dp.h | 1 + drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 + 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 49ee6dcca8c4..806c40068150 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -955,13 +955,38 @@ u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915, return bits_per_pixel; } +static +bool can_use_pixel_replication(struct drm_i915_private *i915, + int mode_hdisplay, u8 slice_count, + enum intel_output_format output_format, + bool ultrajoiner) +{ + int slice_width; + + if (!(mode_hdisplay % slice_count)) + return false; + + if (!IS_BATTLEMAGE(i915) || !ultrajoiner) + return false; + + slice_width = DIV_ROUND_UP(mode_hdisplay, slice_count); + + /* Odd slice width is not supported by YCbCr420/422 formats */ + if (slice_width % 2 && output_format == INTEL_OUTPUT_FORMAT_YCBCR420) + return false; + + return true; +} + u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, int mode_clock, int mode_hdisplay, + enum intel_output_format output_format, enum intel_joiner_pipe_count joined_pipes) { struct drm_i915_private *i915 = to_i915(connector->base.dev); u8 min_slice_count, i; int max_slice_width; + bool ultrajoiner = joined_pipes == 4 ? true : false; if (mode_clock <= DP_DSC_PEAK_PIXEL_RATE) min_slice_count = DIV_ROUND_UP(mode_clock, @@ -1005,7 +1030,10 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, if (joined_pipes == INTEL_PIPE_JOINER_ULTRA && test_slice_count < 8) continue; - if (mode_hdisplay % test_slice_count) + if (mode_hdisplay % test_slice_count && + !can_use_pixel_replication(i915, mode_hdisplay, + test_slice_count, + output_format, ultrajoiner)) continue; if (min_slice_count <= test_slice_count) @@ -1434,6 +1462,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, intel_dp_dsc_get_slice_count(connector, target_clock, mode->hdisplay, + output_format, joined_pipes); } @@ -2337,6 +2366,35 @@ static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp, return 0; } +static +int intel_dp_dsc_get_pixel_replication(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + int mode_hdisplay = pipe_config->hw.adjusted_mode.hdisplay; + int slice_count = pipe_config->dsc.slice_count; + int pixel_replication_count; + int slice_width; + bool ultrajoiner = false; + + if (intel_joiner_num_pipes(pipe_config) == 4) + ultrajoiner = true; + + if (!can_use_pixel_replication(i915, mode_hdisplay, slice_count, + pipe_config->output_format, ultrajoiner)) + return 0; + + slice_width = DIV_ROUND_UP(mode_hdisplay, slice_count); + + pixel_replication_count = (slice_width * slice_count) - mode_hdisplay; + + if (pixel_replication_count >= 0) + return pixel_replication_count; + + return 0; +} + int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state, @@ -2400,6 +2458,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, intel_dp_dsc_get_slice_count(connector, adjusted_mode->crtc_clock, adjusted_mode->crtc_hdisplay, + pipe_config->output_format, joined_pipes); if (!dsc_dp_slice_count) { drm_dbg_kms(&dev_priv->drm, @@ -2409,6 +2468,9 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, pipe_config->dsc.slice_count = dsc_dp_slice_count; } + + pipe_config->dsc.pixel_replication_count = + intel_dp_dsc_get_pixel_replication(intel_dp, pipe_config); /* * VDSC engine operates at 1 Pixel per clock, so if peak pixel rate * is greater than the maximum Cdclock and if slice count is even diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 748e1a94afd2..ec81667466dd 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -154,6 +154,7 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector int bpc); u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, int mode_clock, int mode_hdisplay, + enum intel_output_format output_format, enum intel_joiner_pipe_count joined_pipes); bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, struct intel_connector *connector, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index c5d32bf66b55..f5a5f9117192 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -108,6 +108,7 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state, dsc_slice_count = intel_dp_dsc_get_slice_count(connector, adjusted_mode->clock, adjusted_mode->hdisplay, + crtc_state->output_format, joined_pipes); } @@ -1521,6 +1522,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, intel_dp_dsc_get_slice_count(intel_connector, target_clock, mode->hdisplay, + INTEL_OUTPUT_FORMAT_RGB, joined_pipes); } From patchwork Wed Aug 21 10:19:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [23/29] drm/i915/dsc: Account for Odd pixel removal From: Ankit Nautiyal X-Patchwork-Id: 609655 Message-Id: <20240821101945.273525-24-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:39 +0530 With 3 DSC engines we can support 12 slices. With ultra joiner usecase while dividing the width into into 12 slices, we might end up having odd number of pixels per pipe. As per Bspec, pipe src size should be even, so an extra pixel is added in each pipe. For Pipe A and C the odd pixel is added at the end of pipe and for Pipe B and D it is added at the begining of the pipe. This extra pixel needs to be dropped in Splitter hardware. So account for odd pixel removal while programming DSS CTL. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_vdsc.c | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 7ce503a41e4a..23838cfe16da 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -772,6 +772,26 @@ static bool intel_crtc_ultrajoiner_enable_needed(const struct intel_crtc_state * return intel_joiner_num_pipes(crtc_state) == 4 && crtc->pipe != PIPE_D; } +/* + * With 12 slices, there can be a case where the src width is odd. + * As per Bspec the src width should be even, so an extra Odd Pixel is + * programmed in Pipe in such cases. This extra pixel needs to be + * dropped in Splitter HW. + */ +static +bool intel_dsc_need_odd_pixel_removal(const struct intel_crtc_state *crtc_state) +{ + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + + if (intel_joiner_num_pipes(crtc_state) != 4) + return false; + + if ((pipe_src_w + crtc_state->dsc.pixel_replication_count) % 4) + return true; + + return false; +} + void intel_dsc_enable(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -815,6 +835,12 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state) dss_ctl1_val |= PRIMARY_BIG_JOINER_ENABLE; } + if (intel_dsc_need_odd_pixel_removal(crtc_state)) { + dss_ctl2_val |= ODD_PIXEL_REMOVAL; + if (crtc->pipe == PIPE_A || crtc->pipe == PIPE_C) + dss_ctl2_val |= ODD_PIXEL_REMOVAL_CONFIG_EOL; + } + if (crtc_state->dsc.pixel_replication_count) dss_ctl3_val = DSC_PIXEL_REPLICATION(crtc_state->dsc.pixel_replication_count); From patchwork Wed Aug 21 10:19:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [24/29] drm/i915/dp: Add support for 3 vdsc engines and 12 slices. From: Ankit Nautiyal X-Patchwork-Id: 609656 Message-Id: <20240821101945.273525-25-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:40 +0530 Certain resolutions require 12 DSC slices support along with ultrajoiner. For such cases, the third VDSC Engine per Pipe is enabled. Each VDSC Engine processes 1 Slice, resulting in a total of 12 VDSC Instances (4 Pipes * 3 VDSC Instances per Pipe). Add support for 12 DSC slices and 3 VDSC engines for such modes. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 806c40068150..f8efebb910d0 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -112,8 +112,10 @@ static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15}; /* With Single pipe configuration, HW is capable of supporting maximum * of 4 slices per line. + * For higher resolutions where 12 slice support is required with + * ultrajoiner, only then each pipe can support 3 slices. */ -static const u8 valid_dsc_slicecount[] = {1, 2, 4}; +static const u8 valid_dsc_slicecount[] = {1, 2, 3, 4}; /** * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or PCH) @@ -2475,8 +2477,13 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, * VDSC engine operates at 1 Pixel per clock, so if peak pixel rate * is greater than the maximum Cdclock and if slice count is even * then we need to use 2 VDSC instances. + * In case of Ultrajoiner along with 12 slices we need to use 3 + * VDSC instances. */ - if (pipe_config->joiner_pipes || pipe_config->dsc.slice_count > 1) + if (pipe_config->joiner_pipes && joined_pipes == 4 && + pipe_config->dsc.slice_count == 12) + pipe_config->dsc.dsc_split = DSC_SPLIT_3_STREAMS; + else if (pipe_config->joiner_pipes || pipe_config->dsc.slice_count > 1) pipe_config->dsc.dsc_split = DSC_SPLIT_2_STREAMS; ret = intel_dp_dsc_compute_params(connector, pipe_config); From patchwork Wed Aug 21 10:19:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [25/29] drm/i915/display: Add bits for link_n_exended for DISPLAY >= 14 From: Ankit Nautiyal X-Patchwork-Id: 609657 Message-Id: <20240821101945.273525-26-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:41 +0530 LINK_N register has bits 31:24 for extended link N value used for HDMI2.1 and for an alternate mode of operation of DP TG DDA (Bspec:50488). Add support for these extra bits. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 31 +++++++++++++++---- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 2 ++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index dbb6c51d4ac9..2911bb64177c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2709,6 +2709,8 @@ intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes, compute_m_n(&m_n->link_m, &m_n->link_n, pixel_clock, link_symbol_clock, 0x80000); + + m_n->link_n_ext = 0; } void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv) @@ -2746,6 +2748,7 @@ void intel_set_m_n(struct drm_i915_private *i915, i915_reg_t data_m_reg, i915_reg_t data_n_reg, i915_reg_t link_m_reg, i915_reg_t link_n_reg) { + u8 link_n_ext = 0; intel_de_write(i915, data_m_reg, TU_SIZE(m_n->tu) | m_n->data_m); intel_de_write(i915, data_n_reg, m_n->data_n); intel_de_write(i915, link_m_reg, m_n->link_m); @@ -2753,7 +2756,11 @@ void intel_set_m_n(struct drm_i915_private *i915, * On BDW+ writing LINK_N arms the double buffered update * of all the M/N registers, so it must be written last. */ - intel_de_write(i915, link_n_reg, m_n->link_n); + + if (DISPLAY_VER(i915) >= 14 && m_n->link_n_ext) + link_n_ext = PIPE_LINK_N1_EXTENDED(m_n->link_n_ext); + + intel_de_write(i915, link_n_reg, m_n->link_n | link_n_ext); } bool intel_cpu_transcoder_has_m2_n2(struct drm_i915_private *dev_priv, @@ -3460,8 +3467,17 @@ void intel_get_m_n(struct drm_i915_private *i915, i915_reg_t data_m_reg, i915_reg_t data_n_reg, i915_reg_t link_m_reg, i915_reg_t link_n_reg) { + u32 link_n; + m_n->link_m = intel_de_read(i915, link_m_reg) & DATA_LINK_M_N_MASK; - m_n->link_n = intel_de_read(i915, link_n_reg) & DATA_LINK_M_N_MASK; + + link_n = intel_de_read(i915, link_n_reg); + m_n->link_n = link_n & DATA_LINK_M_N_MASK; + if (DISPLAY_VER(i915) >= 14) + m_n->link_n_ext = REG_FIELD_GET(PIPE_LINK_N1_EXTENDED_MASK, link_n); + else + m_n->link_n_ext = 0; + m_n->data_m = intel_de_read(i915, data_m_reg) & DATA_LINK_M_N_MASK; m_n->data_n = intel_de_read(i915, data_n_reg) & DATA_LINK_M_N_MASK; m_n->tu = REG_FIELD_GET(TU_SIZE_MASK, intel_de_read(i915, data_m_reg)) + 1; @@ -5088,7 +5104,8 @@ intel_compare_link_m_n(const struct intel_link_m_n *m_n, m_n->data_m == m2_n2->data_m && m_n->data_n == m2_n2->data_n && m_n->link_m == m2_n2->link_m && - m_n->link_n == m2_n2->link_n; + m_n->link_n == m2_n2->link_n && + m_n->link_n_ext == m2_n2->link_n_ext; } static bool @@ -5378,18 +5395,20 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if (!intel_compare_link_m_n(¤t_config->name, \ &pipe_config->name)) { \ pipe_config_mismatch(&p, fastset, crtc, __stringify(name), \ - "(expected tu %i data %i/%i link %i/%i, " \ - "found tu %i, data %i/%i link %i/%i)", \ + "(expected tu %i data %i/%i link %i/%i link_n_ext %i, " \ + "found tu %i, data %i/%i link %i/%i link_n_ext %i)", \ current_config->name.tu, \ current_config->name.data_m, \ current_config->name.data_n, \ current_config->name.link_m, \ current_config->name.link_n, \ + current_config->name.link_n_ext, \ pipe_config->name.tu, \ pipe_config->name.data_m, \ pipe_config->name.data_n, \ pipe_config->name.link_m, \ - pipe_config->name.link_n); \ + pipe_config->name.link_n, \ + pipe_config->name.link_n_ext); \ ret = false; \ } \ } while (0) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 5dd048d37b9a..1851f16fab7b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1035,6 +1035,7 @@ struct intel_link_m_n { u32 data_n; u32 link_m; u32 link_n; + u8 link_n_ext; }; struct intel_csc_matrix { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0e3d79227e3c..0f3ece13ffc2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2172,6 +2172,8 @@ #define _PIPEB_DATA_N2 0x6103c #define _PIPEB_LINK_M1 0x61040 #define _PIPEB_LINK_N1 0x61044 +#define PIPE_LINK_N1_EXTENDED_MASK REG_GENMASK(31,24) +#define PIPE_LINK_N1_EXTENDED(val) REG_FIELD_PREP(PIPE_LINK_N1_EXTENDED_MASK, (val)) #define _PIPEB_LINK_M2 0x61048 #define _PIPEB_LINK_N2 0x6104c From patchwork Wed Aug 21 10:19:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [26/29] drm/i915/display: Limit m/n ratio to 10 for BMG + Display > 14 From: Ankit Nautiyal X-Patchwork-Id: 609658 Message-Id: <20240821101945.273525-27-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:42 +0530 As per Bspec:68922 for platforms BMG and Display > 14 which support higher link rates have a HW limitation: If the CEILING( Link M / Link N ) ratio is greater than 10.0, then hardware cannot support the given resolution / refresh rate at the given configuration. Modify the helper to compute m_n, to check for the max link_m/n ratio for the given platforms, and return error code in case the resolution/refresh rate is not supported. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 27 ++++++++++++-- drivers/gpu/drm/i915/display/intel_display.h | 9 ++--- drivers/gpu/drm/i915/display/intel_dp.c | 37 +++++++++++++------- drivers/gpu/drm/i915/display/intel_dp_mst.c | 26 ++++++++------ drivers/gpu/drm/i915/display/intel_fdi.c | 15 ++++---- 5 files changed, 78 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2911bb64177c..6eba1d4ac0ce 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2683,8 +2683,15 @@ static void compute_m_n(u32 *ret_m, u32 *ret_n, intel_reduce_m_n_ratio(ret_m, ret_n); } -void -intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes, +static int +get_max_link_m_n_ratio(struct drm_i915_private *i915) +{ + return 10; +} + +int +intel_link_compute_m_n(struct drm_i915_private *i915, + u16 bits_per_pixel_x16, int nlanes, int pixel_clock, int link_clock, int bw_overhead, struct intel_link_m_n *m_n) @@ -2693,6 +2700,7 @@ intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes, u32 data_m = intel_dp_effective_data_rate(pixel_clock, bits_per_pixel_x16, bw_overhead); u32 data_n = drm_dp_max_dprx_data_rate(link_clock, nlanes); + int link_m_n_ratio, max_link_m_n_ratio; /* * Windows/BIOS uses fixed M/N values always. Follow suit. @@ -2711,6 +2719,21 @@ intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes, 0x80000); m_n->link_n_ext = 0; + + if (DISPLAY_VER(i915) < 14 || (DISPLAY_VER(i915) == 14 && !IS_DGFX(i915))) + return 0; + + max_link_m_n_ratio = get_max_link_m_n_ratio(i915); + + link_m_n_ratio = DIV_ROUND_UP(m_n->link_m, m_n->link_m); + + if (link_m_n_ratio > max_link_m_n_ratio) { + drm_dbg_kms(&i915->drm, "Cannot support Link_m/Link_n ratio : %d > max_link_m_n_ratio\n", + link_m_n_ratio); + return -EINVAL; + } + + return 0; } void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 4cfd1da0bbc0..6a4451e6d500 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -412,10 +412,11 @@ int intel_atomic_add_affected_planes(struct intel_atomic_state *state, struct intel_crtc *crtc); u8 intel_calc_active_pipes(struct intel_atomic_state *state, u8 active_pipes); -void intel_link_compute_m_n(u16 bpp, int nlanes, - int pixel_clock, int link_clock, - int bw_overhead, - struct intel_link_m_n *m_n); +int intel_link_compute_m_n(struct drm_i915_private *i915, + u16 bpp, int nlanes, + int pixel_clock, int link_clock, + int bw_overhead, + struct intel_link_m_n *m_n); u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv, u32 pixel_format, u64 modifier); enum drm_mode_status diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f8efebb910d0..edf49fa4e844 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2978,7 +2978,7 @@ static bool can_enable_drrs(struct intel_connector *connector, intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; } -static void +static int intel_dp_drrs_compute_config(struct intel_connector *connector, struct intel_crtc_state *pipe_config, int link_bpp_x16) @@ -2987,6 +2987,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, const struct drm_display_mode *downclock_mode = intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); int pixel_clock; + int ret; /* * FIXME all joined pipes share the same transcoder. @@ -2998,7 +2999,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, if (!can_enable_drrs(connector, pipe_config, downclock_mode)) { if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder)) intel_zero_m_n(&pipe_config->dp_m2_n2); - return; + return 0; } if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) @@ -3010,14 +3011,18 @@ 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(link_bpp_x16, pipe_config->lane_count, pixel_clock, - pipe_config->port_clock, - intel_dp_bw_fec_overhead(pipe_config->fec_enable), - &pipe_config->dp_m2_n2); + ret = intel_link_compute_m_n(i915, link_bpp_x16, pipe_config->lane_count, pixel_clock, + pipe_config->port_clock, + intel_dp_bw_fec_overhead(pipe_config->fec_enable), + &pipe_config->dp_m2_n2); + if (ret) + return ret; /* FIXME: abstract this better */ if (pipe_config->splitter.enable) pipe_config->dp_m2_n2.data_m *= pipe_config->splitter.link_count; + + return 0; } static bool intel_dp_has_audio(struct intel_encoder *encoder, @@ -3221,12 +3226,14 @@ intel_dp_compute_config(struct intel_encoder *encoder, intel_dp_audio_compute_config(encoder, pipe_config, conn_state); - intel_link_compute_m_n(link_bpp_x16, - pipe_config->lane_count, - adjusted_mode->crtc_clock, - pipe_config->port_clock, - intel_dp_bw_fec_overhead(pipe_config->fec_enable), - &pipe_config->dp_m_n); + ret = intel_link_compute_m_n(dev_priv, link_bpp_x16, + pipe_config->lane_count, + adjusted_mode->crtc_clock, + pipe_config->port_clock, + intel_dp_bw_fec_overhead(pipe_config->fec_enable), + &pipe_config->dp_m_n); + if (ret) + return ret; /* FIXME: abstract this better */ if (pipe_config->splitter.enable) @@ -3239,7 +3246,11 @@ intel_dp_compute_config(struct intel_encoder *encoder, intel_dp_compute_as_sdp(intel_dp, pipe_config); intel_psr_compute_config(intel_dp, pipe_config, conn_state); intel_alpm_lobf_compute_config(intel_dp, pipe_config, conn_state); - intel_dp_drrs_compute_config(connector, pipe_config, link_bpp_x16); + + ret = intel_dp_drrs_compute_config(connector, pipe_config, link_bpp_x16); + if (ret) + return ret; + intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state); intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index f5a5f9117192..5289ba133fc5 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -125,7 +125,7 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state, return max(overhead, intel_dp_bw_fec_overhead(crtc_state->fec_enable)); } -static void intel_dp_mst_compute_m_n(const struct intel_crtc_state *crtc_state, +static int intel_dp_mst_compute_m_n(const struct intel_crtc_state *crtc_state, const struct intel_connector *connector, int overhead, int bpp_x16, @@ -133,15 +133,20 @@ static void intel_dp_mst_compute_m_n(const struct intel_crtc_state *crtc_state, { const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + struct drm_i915_private *i915 = to_i915(connector->base.dev); + int ret; /* TODO: Check WA 14013163432 to set data M/N for full BW utilization. */ - intel_link_compute_m_n(bpp_x16, crtc_state->lane_count, - adjusted_mode->crtc_clock, - crtc_state->port_clock, - overhead, - m_n); + ret = intel_link_compute_m_n(i915, bpp_x16, crtc_state->lane_count, + adjusted_mode->crtc_clock, + crtc_state->port_clock, + overhead, m_n); + if (ret) + return ret; m_n->tu = DIV_ROUND_UP_ULL(mul_u32_u32(m_n->data_m, 64), m_n->data_n); + + return ret; } static int intel_dp_mst_calc_pbn(int pixel_clock, int bpp_x16, int bw_overhead) @@ -223,10 +228,11 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, remote_bw_overhead = intel_dp_mst_bw_overhead(crtc_state, connector, true, dsc, link_bpp_x16); - intel_dp_mst_compute_m_n(crtc_state, connector, - local_bw_overhead, - link_bpp_x16, - &crtc_state->dp_m_n); + if (!intel_dp_mst_compute_m_n(crtc_state, connector, + local_bw_overhead, + link_bpp_x16, + &crtc_state->dp_m_n)) + continue; /* * The TU size programmed to the HW determines which slots in diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index 222cd0e1a2bc..b71414fa1f0f 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -324,7 +324,7 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc, 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; + int lane, link_bw, fdi_dotclock, ret; /* FDI is a binary signal running at ~2.7GHz, encoding * each output octet as 10 bits. The actual frequency @@ -342,13 +342,14 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc, pipe_config->fdi_lanes = lane; - intel_link_compute_m_n(fxp_q4_from_int(pipe_config->pipe_bpp), - lane, fdi_dotclock, - link_bw, - intel_dp_bw_fec_overhead(false), - &pipe_config->fdi_m_n); + ret = intel_link_compute_m_n(i915, + fxp_q4_from_int(pipe_config->pipe_bpp), + lane, fdi_dotclock, + link_bw, + intel_dp_bw_fec_overhead(false), + &pipe_config->fdi_m_n); - return 0; + return ret; } static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state, From patchwork Wed Aug 21 10:19:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [27/29] drm/i915/display: Add bits for Wa_14021768792 for linkm/n ratio > 10 From: Ankit Nautiyal X-Patchwork-Id: 609660 Message-Id: <20240821101945.273525-28-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:43 +0530 To support Link M/N ratio between 10.0 and 15.0, for some BMG ultrajoiner cases we need Wa_14021768792. To bypass the hardware limitation within the Timing Generator DDA (TGDDA), we need to program the LINKM and LINKN registers as defined in the WA. Along with this we also need relvant bits in HDMI_EMP_DATA and CHICKEN_TRANS regs. Add the bits for the WA and a new member 'bmg_bypass_m_n_ratio_limit' to track if we need to bypass the Link M/N ratio limit in intel_link_m_n structure. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 75 ++++++++++++++++++- .../drm/i915/display/intel_display_types.h | 2 + drivers/gpu/drm/i915/i915_reg.h | 5 ++ 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6eba1d4ac0ce..c460e09ea97f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2795,6 +2795,19 @@ bool intel_cpu_transcoder_has_m2_n2(struct drm_i915_private *dev_priv, return IS_DISPLAY_VER(dev_priv, 5, 7) || IS_CHERRYVIEW(dev_priv); } +static +void bmg_bypass_m_n_limit_write(struct intel_crtc *crtc, + enum transcoder transcoder, + const struct intel_link_m_n *m_n) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + int m_n_frac = m_n->link_m % m_n->link_n; + enum pipe pipe = crtc->pipe; + + intel_de_rmw(i915, MTL_CHICKEN_TRANS(transcoder), 0, BMG_DP_BYPASS_M_N_LIMIT); + intel_de_write(i915, HDMI_EMP_DATA(pipe), m_n_frac); +} + void intel_cpu_transcoder_set_m1_n1(struct intel_crtc *crtc, enum transcoder transcoder, const struct intel_link_m_n *m_n) @@ -2812,6 +2825,9 @@ void intel_cpu_transcoder_set_m1_n1(struct intel_crtc *crtc, intel_set_m_n(dev_priv, m_n, PIPE_DATA_M_G4X(pipe), PIPE_DATA_N_G4X(pipe), PIPE_LINK_M_G4X(pipe), PIPE_LINK_N_G4X(pipe)); + + if (m_n->bypass_m_n_ratio_limit) + bmg_bypass_m_n_limit_write(crtc, transcoder, m_n); } void intel_cpu_transcoder_set_m2_n2(struct intel_crtc *crtc, @@ -2828,6 +2844,9 @@ void intel_cpu_transcoder_set_m2_n2(struct intel_crtc *crtc, PIPE_DATA_N2(dev_priv, transcoder), PIPE_LINK_M2(dev_priv, transcoder), PIPE_LINK_N2(dev_priv, transcoder)); + + if (m_n->bypass_m_n_ratio_limit) + bmg_bypass_m_n_limit_write(crtc, transcoder, m_n); } static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state) @@ -3506,12 +3525,48 @@ void intel_get_m_n(struct drm_i915_private *i915, m_n->tu = REG_FIELD_GET(TU_SIZE_MASK, intel_de_read(i915, data_m_reg)) + 1; } +static +void bmg_bypass_m_n_limit_read(struct intel_crtc *crtc, + enum transcoder transcoder, + struct intel_link_m_n *m_n) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + u32 chicken_trans, m_n_frac; + + chicken_trans = intel_de_read(i915, MTL_CHICKEN_TRANS(transcoder)); + m_n_frac = intel_de_read(i915, HDMI_EMP_DATA(pipe)); + + if ((chicken_trans & BMG_DP_BYPASS_M_N_LIMIT) && + m_n_frac == (m_n->link_m % m_n->link_n)) + m_n->bypass_m_n_ratio_limit = true; +} + +static +int bmg_can_bypass_m_n_limit(struct drm_i915_private *i915, + int m_n_ratio, + enum pipe pipe) +{ + if (DISPLAY_VER(i915) != 14 || !IS_DGFX(i915) || + !IS_DISPLAY_STEP(i915, STEP_C0, STEP_FOREVER)) + return false; + + if (pipe != PIPE_A) + return false; + + if (m_n_ratio > 15) + return false; + + return true; +} + void intel_cpu_transcoder_get_m1_n1(struct intel_crtc *crtc, enum transcoder transcoder, struct intel_link_m_n *m_n) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; + int m_n_ratio; if (DISPLAY_VER(dev_priv) >= 5) intel_get_m_n(dev_priv, m_n, @@ -3523,6 +3578,11 @@ void intel_cpu_transcoder_get_m1_n1(struct intel_crtc *crtc, intel_get_m_n(dev_priv, m_n, PIPE_DATA_M_G4X(pipe), PIPE_DATA_N_G4X(pipe), PIPE_LINK_M_G4X(pipe), PIPE_LINK_N_G4X(pipe)); + + m_n_ratio = DIV_ROUND_UP(m_n->link_m, m_n->link_n); + + if (bmg_can_bypass_m_n_limit(dev_priv, m_n_ratio, pipe)) + bmg_bypass_m_n_limit_read(crtc, transcoder, m_n); } void intel_cpu_transcoder_get_m2_n2(struct intel_crtc *crtc, @@ -3530,6 +3590,8 @@ void intel_cpu_transcoder_get_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + int m_n_ratio; if (!intel_cpu_transcoder_has_m2_n2(dev_priv, transcoder)) return; @@ -3539,6 +3601,11 @@ void intel_cpu_transcoder_get_m2_n2(struct intel_crtc *crtc, PIPE_DATA_N2(dev_priv, transcoder), PIPE_LINK_M2(dev_priv, transcoder), PIPE_LINK_N2(dev_priv, transcoder)); + + m_n_ratio = DIV_ROUND_UP(m_n->link_m, m_n->link_n); + + if (bmg_can_bypass_m_n_limit(dev_priv, m_n_ratio, pipe)) + bmg_bypass_m_n_limit_read(crtc, transcoder, m_n); } static void ilk_get_pfit_config(struct intel_crtc_state *crtc_state) @@ -5418,20 +5485,22 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if (!intel_compare_link_m_n(¤t_config->name, \ &pipe_config->name)) { \ pipe_config_mismatch(&p, fastset, crtc, __stringify(name), \ - "(expected tu %i data %i/%i link %i/%i link_n_ext %i, " \ - "found tu %i, data %i/%i link %i/%i link_n_ext %i)", \ + "(expected tu %i data %i/%i link %i/%i link_n_ext %i bypass_m_n_ratio_limit %s, " \ + "found tu %i, data %i/%i link %i/%i link_n_ext %i bypass_m_n_ratio_limit %s)", \ current_config->name.tu, \ current_config->name.data_m, \ current_config->name.data_n, \ current_config->name.link_m, \ current_config->name.link_n, \ current_config->name.link_n_ext, \ + str_yes_no(current_config->name.bypass_m_n_ratio_limit), \ pipe_config->name.tu, \ pipe_config->name.data_m, \ pipe_config->name.data_n, \ pipe_config->name.link_m, \ pipe_config->name.link_n, \ - pipe_config->name.link_n_ext); \ + pipe_config->name.link_n_ext, \ + str_yes_no(pipe_config->name.bypass_m_n_ratio_limit)); \ ret = false; \ } \ } while (0) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 1851f16fab7b..f920c0060f60 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1036,6 +1036,8 @@ struct intel_link_m_n { u32 link_m; u32 link_n; u8 link_n_ext; + /* Wa_14021768792 for linkm/n ratio > 10 */ + bool bypass_m_n_ratio_limit; }; struct intel_csc_matrix { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0f3ece13ffc2..e275533b178b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1110,6 +1110,10 @@ #define _TRANS_VSYNCSHIFT_A 0x60028 #define _TRANS_MULT_A 0x6002c +#define _HDMI_EMP_DATA_A 0x600d8 +#define _HDMI_EMP_DATA_B 0x610d8 +#define HDMI_EMP_DATA(pipe) _MMIO_PIPE(pipe, _HDMI_EMP_DATA_A, _HDMI_EMP_DATA_B) + /* Pipe/transcoder B timing regs */ #define _TRANS_HTOTAL_B 0x61000 #define _TRANS_HBLANK_B 0x61004 @@ -2796,6 +2800,7 @@ #define PSR2_ADD_VERTICAL_LINE_COUNT REG_BIT(15) #define DP_FEC_BS_JITTER_WA REG_BIT(15) #define PSR2_VSC_ENABLE_PROG_HEADER REG_BIT(12) +#define BMG_DP_BYPASS_M_N_LIMIT REG_BIT(11) #define DP_DSC_INSERT_SF_AT_EOL_WA REG_BIT(4) #define HDCP_LINE_REKEY_DISABLE REG_BIT(0) From patchwork Wed Aug 21 10:19:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [28/29] drm/i915/display: Implement Wa_14021768792 for BMG DP for link_m/n ratio > 10 From: Ankit Nautiyal X-Patchwork-Id: 609659 Message-Id: <20240821101945.273525-29-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:44 +0530 Handle the bypass logic for the M/N ratio limit for DP. Calculate the M/N ratio, check if it can bypass the limit, and set the appropriate flags for the workaround. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 1 - drivers/gpu/drm/i915/display/intel_display.h | 4 +++ drivers/gpu/drm/i915/display/intel_dp.c | 31 ++++++++++++++++++-- drivers/gpu/drm/i915/display/intel_dp.h | 4 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 +++- 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c460e09ea97f..30934c2db112 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3542,7 +3542,6 @@ void bmg_bypass_m_n_limit_read(struct intel_crtc *crtc, m_n->bypass_m_n_ratio_limit = true; } -static int bmg_can_bypass_m_n_limit(struct drm_i915_private *i915, int m_n_ratio, enum pipe pipe) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 6a4451e6d500..de2eea13c5c3 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -599,4 +599,8 @@ bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915); int intel_joiner_num_pipes(const struct intel_crtc_state *crtc_state); +int bmg_can_bypass_m_n_limit(struct drm_i915_private *i915, + int m_n_ratio, + enum pipe pipe); + #endif diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index edf49fa4e844..bf83da396c58 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2978,6 +2978,27 @@ static bool can_enable_drrs(struct intel_connector *connector, intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; } +bool +intel_dp_bmg_bypass_m_n_limit(struct drm_i915_private *i915, + struct intel_link_m_n *m_n, + enum pipe pipe) +{ + int m_n_ratio, m_n_frac; + + m_n_ratio = DIV_ROUND_UP(m_n->link_m, m_n->link_n); + + if (!bmg_can_bypass_m_n_limit(i915, m_n_ratio, pipe)) + return false; + + m_n_frac = m_n->link_m % m_n->link_n; + + m_n->link_n_ext = m_n_ratio | (m_n_ratio + (m_n_frac > 0 ? 1 : 0)) << 4; + + m_n->bypass_m_n_ratio_limit = true; + + return true; +} + static int intel_dp_drrs_compute_config(struct intel_connector *connector, struct intel_crtc_state *pipe_config, @@ -2986,6 +3007,8 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, struct drm_i915_private *i915 = to_i915(connector->base.dev); const struct drm_display_mode *downclock_mode = intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + enum pipe pipe = crtc->pipe; int pixel_clock; int ret; @@ -3015,7 +3038,8 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, pipe_config->port_clock, intel_dp_bw_fec_overhead(pipe_config->fec_enable), &pipe_config->dp_m2_n2); - if (ret) + + if (ret && !intel_dp_bmg_bypass_m_n_limit(i915, &pipe_config->dp_m2_n2, pipe)) return ret; /* FIXME: abstract this better */ @@ -3150,6 +3174,8 @@ 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; + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + enum pipe pipe = crtc->pipe; int ret = 0, link_bpp_x16; if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && encoder->port != PORT_A) @@ -3232,7 +3258,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, pipe_config->port_clock, intel_dp_bw_fec_overhead(pipe_config->fec_enable), &pipe_config->dp_m_n); - if (ret) + + if (ret && !intel_dp_bmg_bypass_m_n_limit(dev_priv, &pipe_config->dp_m_n, pipe)) return ret; /* FIXME: abstract this better */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index ec81667466dd..bcf12e73e012 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -23,6 +23,7 @@ struct intel_crtc_state; struct intel_digital_port; struct intel_dp; struct intel_encoder; +struct intel_link_m_n; struct link_config_limits { int min_rate, max_rate; @@ -209,5 +210,8 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp, void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector); bool intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder); +bool intel_dp_bmg_bypass_m_n_limit(struct drm_i915_private *i915, + struct intel_link_m_n *m_n, + enum pipe pipe); #endif /* __INTEL_DP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 5289ba133fc5..8af0f8cd5cf0 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -134,6 +134,8 @@ static int intel_dp_mst_compute_m_n(const struct intel_crtc_state *crtc_state, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + enum pipe pipe = crtc->pipe; int ret; /* TODO: Check WA 14013163432 to set data M/N for full BW utilization. */ @@ -141,7 +143,8 @@ static int intel_dp_mst_compute_m_n(const struct intel_crtc_state *crtc_state, adjusted_mode->crtc_clock, crtc_state->port_clock, overhead, m_n); - if (ret) + + if (ret && !intel_dp_bmg_bypass_m_n_limit(i915, m_n, pipe)) return ret; m_n->tu = DIV_ROUND_UP_ULL(mul_u32_u32(m_n->data_m, 64), m_n->data_n); From patchwork Wed Aug 21 10:19:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [29/29] drm/i915: Add Wa_14021768792 as per WA framework From: Ankit Nautiyal X-Patchwork-Id: 609661 Message-Id: <20240821101945.273525-30-ankit.k.nautiyal@intel.com> To: intel-gfx-trybot@lists.freedesktop.org Date: Wed, 21 Aug 2024 15:49:45 +0530 Modify the condition for WA as per Xe WA framework. Signed-off-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- drivers/gpu/drm/i915/display/intel_display_wa.h | 2 ++ drivers/gpu/drm/xe/display/xe_display_wa.c | 5 +++++ drivers/gpu/drm/xe/xe_wa_oob.rules | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 30934c2db112..176102b2ec80 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -75,6 +75,7 @@ #include "intel_display_driver.h" #include "intel_display_power.h" #include "intel_display_types.h" +#include "intel_display_wa.h" #include "intel_dmc.h" #include "intel_dp.h" #include "intel_dp_link_training.h" @@ -3546,8 +3547,7 @@ int bmg_can_bypass_m_n_limit(struct drm_i915_private *i915, int m_n_ratio, enum pipe pipe) { - if (DISPLAY_VER(i915) != 14 || !IS_DGFX(i915) || - !IS_DISPLAY_STEP(i915, STEP_C0, STEP_FOREVER)) + if (!intel_display_needs_wa_14021768792(i915)) return false; if (pipe != PIPE_A) diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.h b/drivers/gpu/drm/i915/display/intel_display_wa.h index be644ab6ae00..10c1b5787d05 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.h +++ b/drivers/gpu/drm/i915/display/intel_display_wa.h @@ -14,8 +14,10 @@ void intel_display_wa_apply(struct drm_i915_private *i915); #ifdef I915 static inline bool intel_display_needs_wa_16023588340(struct drm_i915_private *i915) { return false; } +static inline bool intel_display_needs_wa_14021768792(struct drm_i915_private *i915) { return false; } #else bool intel_display_needs_wa_16023588340(struct drm_i915_private *i915); +bool intel_display_needs_wa_14021768792(struct drm_i915_private *i915); #endif #endif diff --git a/drivers/gpu/drm/xe/display/xe_display_wa.c b/drivers/gpu/drm/xe/display/xe_display_wa.c index 68e3d1959ad6..c4728e61e190 100644 --- a/drivers/gpu/drm/xe/display/xe_display_wa.c +++ b/drivers/gpu/drm/xe/display/xe_display_wa.c @@ -14,3 +14,8 @@ bool intel_display_needs_wa_16023588340(struct drm_i915_private *i915) { return XE_WA(xe_root_mmio_gt(i915), 16023588340); } + +bool intel_display_needs_wa_14021768792(struct drm_i915_private *i915) +{ + return XE_WA(xe_root_mmio_gt(i915), 14021768792); +} diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules index 540d38603f32..6687a6b82afc 100644 --- a/drivers/gpu/drm/xe/xe_wa_oob.rules +++ b/drivers/gpu/drm/xe/xe_wa_oob.rules @@ -31,3 +31,4 @@ GRAPHICS_VERSION(2001) 22019338487_display PLATFORM(LUNARLAKE) 16023588340 GRAPHICS_VERSION(2001) +14021768792 PLATFORM(BATTLEMAGE), GRAPHICS_STEP(C0, FOREVER)