From aedeed4af6fdd23426a6cec09c3e5872003e4a07 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Jan 2025 11:54:14 +0200 Subject: [PATCH 01/16] drm/i915/ddi: write payload for 128b/132b SST Write the payload allocation table for 128b/132b SST. Use VCPID 1 and start from slot 0, with dp_m_n.tu slots. This is preparation for enabling 128b/132b SST. This path is not reachable yet. Indeed, we don't yet compute TU for 128b/132b SST. v2: Handle drm_dp_dpcd_write_payload() failures (Imre) v3: Include drm_dp_helper.h (kernel test robot) Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20250107095414.1244286-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 44f9bde2cdcc..f8e111d8c3a5 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -2574,6 +2575,7 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state, { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); + int ret; intel_dp_set_link_params(intel_dp, crtc_state->port_clock, @@ -2668,6 +2670,14 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state, /* 6.o Configure and enable FEC if needed */ intel_ddi_enable_fec(encoder, crtc_state); + /* 7.a 128b/132b SST. */ + if (!is_mst && intel_dp_is_uhbr(crtc_state)) { + /* VCPID 1, start slot 0 for 128b/132b, tu slots */ + ret = drm_dp_dpcd_write_payload(&intel_dp->aux, 1, 0, crtc_state->dp_m_n.tu); + if (ret < 0) + intel_dp_queue_modeset_retry_for_link(state, encoder, crtc_state); + } + if (!is_mst) intel_dsc_dp_pps_write(encoder, crtc_state); } @@ -2681,6 +2691,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); + int ret; intel_dp_set_link_params(intel_dp, crtc_state->port_clock, @@ -2807,6 +2818,13 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state, /* 7.l Configure and enable FEC if needed */ intel_ddi_enable_fec(encoder, crtc_state); + if (!is_mst && intel_dp_is_uhbr(crtc_state)) { + /* VCPID 1, start slot 0 for 128b/132b, tu slots */ + ret = drm_dp_dpcd_write_payload(&intel_dp->aux, 1, 0, crtc_state->dp_m_n.tu); + if (ret < 0) + intel_dp_queue_modeset_retry_for_link(state, encoder, crtc_state); + } + if (!is_mst) intel_dsc_dp_pps_write(encoder, crtc_state); } -- 2.51.0 From a9efb7e2f72e5f5835b942aaadcd5d730d0ad673 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 3 Jan 2025 15:52:34 +0200 Subject: [PATCH 02/16] drm/i915/ddi: initialize 128b/132b SST DP2 VFREQ registers Write the DP2 specific VFREQ registers. This is preparation for enabling 128b/132b SST. This path is not reachable yet. v2: Check for !is_hdmi (Imre) Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/7d90547e9ce01642b722efca0bf81cadb754e790.1735912293.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index f8e111d8c3a5..dff6f4e495a6 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3473,8 +3473,21 @@ static void intel_ddi_enable(struct intel_atomic_state *state, { struct intel_display *display = to_intel_display(encoder); struct intel_crtc *pipe_crtc; + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + bool is_hdmi = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI); int i; + /* 128b/132b SST */ + if (!is_hdmi && intel_dp_is_uhbr(crtc_state)) { + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + u64 crtc_clock_hz = KHz(adjusted_mode->crtc_clock); + + intel_de_write(display, TRANS_DP2_VFREQHIGH(cpu_transcoder), + TRANS_DP2_VFREQ_PIXEL_CLOCK(crtc_clock_hz >> 24)); + intel_de_write(display, TRANS_DP2_VFREQLOW(cpu_transcoder), + TRANS_DP2_VFREQ_PIXEL_CLOCK(crtc_clock_hz & 0xffffff)); + } + intel_ddi_enable_transcoder_func(encoder, crtc_state); /* Enable/Disable DP2.0 SDP split config before transcoder */ @@ -3491,7 +3504,7 @@ static void intel_ddi_enable(struct intel_atomic_state *state, intel_crtc_vblank_on(pipe_crtc_state); } - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + if (is_hdmi) intel_ddi_enable_hdmi(state, encoder, crtc_state, conn_state); else intel_ddi_enable_dp(state, encoder, crtc_state, conn_state); -- 2.51.0 From 591b9170b7bcf29632c0e36eef825972a33e5afa Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 3 Jan 2025 15:52:35 +0200 Subject: [PATCH 03/16] drm/i915/ddi: enable ACT handling for 128b/132b SST Add ACT handling for 128b/132b SST enable/disable. This is preparation for enabling 128b/132b SST. This path is not reachable yet. v2: - Check for !is_hdmi (Imre) - Add disable sequence (Imre) Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/b0226471f9445d988917cee49dbbd93a1493f3c7.1735912293.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index dff6f4e495a6..6e0b8ba4d9ab 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3199,7 +3199,9 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state, { struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_crtc *pipe_crtc; + bool is_hdmi = intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI); int i; for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) { @@ -3211,6 +3213,20 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state, intel_disable_transcoder(old_crtc_state); + /* 128b/132b SST */ + if (!is_hdmi && intel_dp_is_uhbr(old_crtc_state)) { + /* VCPID 1, start slot 0 for 128b/132b, clear */ + drm_dp_dpcd_write_payload(&intel_dp->aux, 1, 0, 0); + + intel_ddi_clear_act_sent(encoder, old_crtc_state); + + intel_de_rmw(display, TRANS_DDI_FUNC_CTL(display, old_crtc_state->cpu_transcoder), + TRANS_DDI_DP_VC_PAYLOAD_ALLOC, 0); + + intel_ddi_wait_for_act_sent(encoder, old_crtc_state); + drm_dp_dpcd_poll_act_handled(&intel_dp->aux, 0); + } + intel_ddi_disable_transcoder_func(old_crtc_state); for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) { @@ -3493,6 +3509,19 @@ static void intel_ddi_enable(struct intel_atomic_state *state, /* Enable/Disable DP2.0 SDP split config before transcoder */ intel_audio_sdp_split_update(crtc_state); + /* 128b/132b SST */ + if (!is_hdmi && intel_dp_is_uhbr(crtc_state)) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + intel_ddi_clear_act_sent(encoder, crtc_state); + + intel_de_rmw(display, TRANS_DDI_FUNC_CTL(display, cpu_transcoder), 0, + TRANS_DDI_DP_VC_PAYLOAD_ALLOC); + + intel_ddi_wait_for_act_sent(encoder, crtc_state); + drm_dp_dpcd_poll_act_handled(&intel_dp->aux, 0); + } + intel_enable_transcoder(crtc_state); intel_ddi_wait_for_fec_status(encoder, crtc_state, true); -- 2.51.0 From 35d2e4b7564994e69583e12b0a0d74521657faeb Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 3 Jan 2025 15:52:36 +0200 Subject: [PATCH 04/16] drm/i915/ddi: start distinguishing 128b/132b SST and MST at state readout MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit We'll want to distinguish 128b/132b SST and MST modes at state readout. There's a catch, though. From the hardware perspective, 128b/132b SST and MST programming are pretty much the same. And we can't really ask the sink at this point. If we have more than one transcoder in 128b/132b mode associated with the port, we can safely assume it's MST. But for MST with only a single stream enabled, we are pretty much out of luck. Let's fall back to looking at the software state, i.e. intel_dp->is_mst. It should be fine for the state checker, but for hardware takeover at probe, we'll have to trust the GOP has only enabled SST. TODO: Not sure how this *or* our current code handles 128b/132b enabled by GOP. Cc: Imre Deak Cc: Ville Syrjälä Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/119a773a0d4d74ad204435e462f8d12cb0ea4128.1735912293.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 29 +++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 6e0b8ba4d9ab..327277d4e94d 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -787,7 +787,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder, intel_wakeref_t wakeref; enum pipe p; u32 tmp; - u8 mst_pipe_mask; + u8 mst_pipe_mask = 0, dp128b132b_pipe_mask = 0; *pipe_mask = 0; *is_dp_mst = false; @@ -824,7 +824,6 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder, goto out; } - mst_pipe_mask = 0; for_each_pipe(dev_priv, p) { enum transcoder cpu_transcoder = (enum transcoder)p; u32 port_mask, ddi_select, ddi_mode; @@ -853,9 +852,10 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder, ddi_mode = tmp & TRANS_DDI_MODE_SELECT_MASK; - if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST || - (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display))) + if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST) mst_pipe_mask |= BIT(p); + else if (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display)) + dp128b132b_pipe_mask |= BIT(p); *pipe_mask |= BIT(p); } @@ -865,6 +865,23 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder, "No pipe for [ENCODER:%d:%s] found\n", encoder->base.base.id, encoder->base.name); + if (!mst_pipe_mask && dp128b132b_pipe_mask) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + /* + * If we don't have 8b/10b MST, but have more than one + * transcoder in 128b/132b mode, we know it must be 128b/132b + * MST. + * + * Otherwise, we fall back to checking the current MST + * state. It's not accurate for hardware takeover at probe, but + * we don't expect MST to have been enabled at that point, and + * can assume it's SST. + */ + if (hweight8(dp128b132b_pipe_mask) > 1 || intel_dp->is_mst) + mst_pipe_mask = dp128b132b_pipe_mask; + } + if (!mst_pipe_mask && hweight8(*pipe_mask) > 1) { drm_dbg_kms(&dev_priv->drm, "Multiple pipes for [ENCODER:%d:%s] (pipe_mask %02x)\n", @@ -875,9 +892,9 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder, if (mst_pipe_mask && mst_pipe_mask != *pipe_mask) drm_dbg_kms(&dev_priv->drm, - "Conflicting MST and non-MST state for [ENCODER:%d:%s] (pipe_mask %02x mst_pipe_mask %02x)\n", + "Conflicting MST and non-MST state for [ENCODER:%d:%s] (pipe masks: all %02x, MST %02x, 128b/132b %02x)\n", encoder->base.base.id, encoder->base.name, - *pipe_mask, mst_pipe_mask); + *pipe_mask, mst_pipe_mask, dp128b132b_pipe_mask); else *is_dp_mst = mst_pipe_mask; -- 2.51.0 From 40d489fac0e82e3f758b17d775355f514a6ec970 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 3 Jan 2025 15:52:37 +0200 Subject: [PATCH 05/16] drm/i915/ddi: handle 128b/132b SST in intel_ddi_read_func_ctl() We'll only ever get here in MST mode from MST stream encoders; the primary encoder's ->get_config() won't be called when we've detected it's MST. v2: Read mst_master_transcoder in 128b/132b SST path (Imre) Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/436854c0bb6ab5c14c3d3837694ea60ac2fbaba2.1735912293.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 327277d4e94d..594cbac816d7 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4049,6 +4049,11 @@ static void intel_ddi_read_func_ctl_dp_sst(struct intel_encoder *encoder, crtc_state->lane_count = ((ddi_func_ctl & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1; + if (DISPLAY_VER(display) >= 12 && + (ddi_func_ctl & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B) + crtc_state->mst_master_transcoder = + REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, ddi_func_ctl); + intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder, &crtc_state->dp_m_n); intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder, &crtc_state->dp_m2_n2); @@ -4143,9 +4148,19 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder, intel_ddi_read_func_ctl_fdi(encoder, pipe_config, ddi_func_ctl); } else if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_SST) { intel_ddi_read_func_ctl_dp_sst(encoder, pipe_config, ddi_func_ctl); - } else if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST || - (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display))) { + } else if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST) { intel_ddi_read_func_ctl_dp_mst(encoder, pipe_config, ddi_func_ctl); + } else if (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display)) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + /* + * If this is true, we know we're being called from mst stream + * encoder's ->get_config(). + */ + if (intel_dp->is_mst) + intel_ddi_read_func_ctl_dp_mst(encoder, pipe_config, ddi_func_ctl); + else + intel_ddi_read_func_ctl_dp_sst(encoder, pipe_config, ddi_func_ctl); } } -- 2.51.0 From 79a6734cd56e70e22d557acbfc62ab36c835fa8f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 3 Jan 2025 15:52:38 +0200 Subject: [PATCH 06/16] drm/i915/ddi: disable trancoder port select for 128b/132b SST 128b/1232b SST will have mst_master_transcoder set and matching cpu_transcoder. Ensure disable also for 128b/132b SST. Reviewed-by: Imre Deak Co-developed-by: Imre Deak Signed-off-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/eaf705b3490d828ba33e85f40a7794d58de7c5ad.1735912293.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 594cbac816d7..acb986bc1f33 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -658,6 +658,7 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); u32 ctl; if (DISPLAY_VER(dev_priv) >= 11) @@ -677,7 +678,8 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK); if (DISPLAY_VER(dev_priv) >= 12) { - if (!intel_dp_mst_is_master_trans(crtc_state)) { + if (!intel_dp_mst_is_master_trans(crtc_state) || + (!is_mst && intel_dp_is_uhbr(crtc_state))) { ctl &= ~(TGL_TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK); } -- 2.51.0 From ef0a0757bbeac9aedff66464c6fba2d896cfe343 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 3 Jan 2025 15:52:39 +0200 Subject: [PATCH 07/16] drm/i915/dp: compute config for 128b/132b SST w/o DSC Enable basic 128b/132b SST functionality without compression. Reuse intel_dp_mtp_tu_compute_config() to figure out the TU after we've determined we need to use an UHBR rate. It's slightly complicated as the M/N computation is done in different places in MST and SST paths, so we need to avoid trashing the values later for UHBR. If uncompressed UHBR fails, we drop to compressed non-UHBR, which is quite likely to fail as well. We still lack 128b/132b SST+DSC. We need mst_master_transcoder also for 128b/132b SST. Use cpu_transcoder directly. Enhanced framing is "don't care" for 128b/132b link. v2: mst_master_transcoder, enhanced framing (Imre) Reviewed-by: Imre Deak Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/084e4e05bf25a5dd396dd391014943d42b11c88d.1735912293.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 34 +++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 4fa0e0b675b0..f1f3b1bb1e89 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2519,8 +2519,8 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp, limits->min_rate = intel_dp_min_link_rate(intel_dp); limits->max_rate = intel_dp_max_link_rate(intel_dp); - /* FIXME 128b/132b SST support missing */ - if (!is_mst) + /* FIXME 128b/132b SST+DSC support missing */ + if (!is_mst && dsc) limits->max_rate = min(limits->max_rate, 810000); limits->min_rate = min(limits->min_rate, limits->max_rate); @@ -2638,6 +2638,13 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, */ ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, conn_state, &limits); + if (!ret && intel_dp_is_uhbr(pipe_config)) + ret = intel_dp_mtp_tu_compute_config(intel_dp, + pipe_config, + pipe_config->pipe_bpp, + pipe_config->pipe_bpp, + conn_state, + 0, false); if (ret) dsc_needed = true; } @@ -3151,8 +3158,13 @@ intel_dp_compute_config(struct intel_encoder *encoder, pipe_config->limited_color_range = intel_dp_limited_color_range(pipe_config, conn_state); - pipe_config->enhanced_framing = - drm_dp_enhanced_frame_cap(intel_dp->dpcd); + if (intel_dp_is_uhbr(pipe_config)) { + /* 128b/132b SST also needs this */ + pipe_config->mst_master_transcoder = pipe_config->cpu_transcoder; + } else { + pipe_config->enhanced_framing = + drm_dp_enhanced_frame_cap(intel_dp->dpcd); + } if (pipe_config->dsc.compression_enable) link_bpp_x16 = pipe_config->dsc.compressed_bpp_x16; @@ -3183,12 +3195,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); + if (!intel_dp_is_uhbr(pipe_config)) { + 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); + } /* FIXME: abstract this better */ if (pipe_config->splitter.enable) -- 2.51.0 From eb18e25b60f7f7f51a63cd99a177a924ba1f4fba Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Dec 2024 18:27:37 +0200 Subject: [PATCH 08/16] drm/i915/pmdemand: convert to_intel_pmdemand_state() to a function In preparation for making struct intel_pmdemand_state an opaque type, convert to_intel_pmdemand_state() to a function. Cc: Gustavo Sousa Reviewed-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/10324781f9f7eae5a92506aaa7a40403efd345dd.1735662324.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_pmdemand.c | 5 +++++ drivers/gpu/drm/i915/display/intel_pmdemand.h | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c index cdd314956a31..69b40b3735b3 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.c +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c @@ -15,6 +15,11 @@ #include "intel_pmdemand.h" #include "skl_watermark.h" +struct intel_pmdemand_state *to_intel_pmdemand_state(struct intel_global_state *obj_state) +{ + return container_of(obj_state, struct intel_pmdemand_state, base); +} + static struct intel_global_state * intel_pmdemand_duplicate_state(struct intel_global_obj *obj) { diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.h b/drivers/gpu/drm/i915/display/intel_pmdemand.h index a1c49efdc493..89296364ec3b 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.h +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.h @@ -43,8 +43,7 @@ struct intel_pmdemand_state { struct pmdemand_params params; }; -#define to_intel_pmdemand_state(global_state) \ - container_of_const((global_state), struct intel_pmdemand_state, base) +struct intel_pmdemand_state *to_intel_pmdemand_state(struct intel_global_state *obj_state); void intel_pmdemand_init_early(struct drm_i915_private *i915); int intel_pmdemand_init(struct drm_i915_private *i915); -- 2.51.0 From 0a08320bfa385ec73e92a37e96e090ecc9a5027f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Dec 2024 18:27:38 +0200 Subject: [PATCH 09/16] drm/i915/pmdemand: make struct intel_pmdemand_state opaque Only intel_pmdemand.c should look inside the struct intel_pmdemand_state. Indeed, this is already the case. Finish the job and make struct intel_pmdemand_state opaque, preventing any direct pokes at the guts of it in the future. Cc: Gustavo Sousa Reviewed-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/bc5f418785ecd51454761e9a55f21340470a92e3.1735662324.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_pmdemand.c | 28 +++++++++++++++ drivers/gpu/drm/i915/display/intel_pmdemand.h | 34 +++---------------- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c index 69b40b3735b3..500faf639290 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.c +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c @@ -15,6 +15,34 @@ #include "intel_pmdemand.h" #include "skl_watermark.h" +struct pmdemand_params { + u16 qclk_gv_bw; + u8 voltage_index; + u8 qclk_gv_index; + u8 active_pipes; + u8 active_dbufs; /* pre-Xe3 only */ + /* Total number of non type C active phys from active_phys_mask */ + u8 active_phys; + u8 plls; + u16 cdclk_freq_mhz; + /* max from ddi_clocks[] */ + u16 ddiclk_max; + u8 scalers; /* pre-Xe3 only */ +}; + +struct intel_pmdemand_state { + struct intel_global_state base; + + /* Maintain a persistent list of port clocks across all crtcs */ + int ddi_clocks[I915_MAX_PIPES]; + + /* Maintain a persistent list of non type C phys mask */ + u16 active_combo_phys_mask; + + /* Parameters to be configured in the pmdemand registers */ + struct pmdemand_params params; +}; + struct intel_pmdemand_state *to_intel_pmdemand_state(struct intel_global_state *obj_state) { return container_of(obj_state, struct intel_pmdemand_state, base); diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.h b/drivers/gpu/drm/i915/display/intel_pmdemand.h index 89296364ec3b..34f68912fe04 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.h +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.h @@ -6,42 +6,16 @@ #ifndef __INTEL_PMDEMAND_H__ #define __INTEL_PMDEMAND_H__ -#include "intel_display_limits.h" -#include "intel_global_state.h" +#include +enum pipe; struct drm_i915_private; struct intel_atomic_state; struct intel_crtc_state; struct intel_encoder; +struct intel_global_state; struct intel_plane_state; - -struct pmdemand_params { - u16 qclk_gv_bw; - u8 voltage_index; - u8 qclk_gv_index; - u8 active_pipes; - u8 active_dbufs; /* pre-Xe3 only */ - /* Total number of non type C active phys from active_phys_mask */ - u8 active_phys; - u8 plls; - u16 cdclk_freq_mhz; - /* max from ddi_clocks[] */ - u16 ddiclk_max; - u8 scalers; /* pre-Xe3 only */ -}; - -struct intel_pmdemand_state { - struct intel_global_state base; - - /* Maintain a persistent list of port clocks across all crtcs */ - int ddi_clocks[I915_MAX_PIPES]; - - /* Maintain a persistent list of non type C phys mask */ - u16 active_combo_phys_mask; - - /* Parameters to be configured in the pmdemand registers */ - struct pmdemand_params params; -}; +struct intel_pmdemand_state; struct intel_pmdemand_state *to_intel_pmdemand_state(struct intel_global_state *obj_state); -- 2.51.0 From 445fc685498bbb2e319394a016f9d39541ea6d68 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Dec 2024 18:27:39 +0200 Subject: [PATCH 10/16] drm/i915/pmdemand: convert to struct intel_display Going forward, struct intel_display is the main display device structure. Convert pmdemand to it. Cc: Gustavo Sousa Reviewed-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/c1d92e9490013d5aba50fc1d1ebc0ee18e82cf7e.1735662324.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../drm/i915/display/intel_display_driver.c | 4 +- .../drm/i915/display/intel_display_power.c | 4 +- .../drm/i915/display/intel_modeset_setup.c | 17 +- drivers/gpu/drm/i915/display/intel_pmdemand.c | 160 +++++++++--------- drivers/gpu/drm/i915/display/intel_pmdemand.h | 14 +- 5 files changed, 101 insertions(+), 98 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 497b4a1f045f..c4cfb0406fa2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -233,7 +233,7 @@ int intel_display_driver_probe_noirq(struct intel_display *display) if (ret < 0) goto cleanup_vga; - intel_pmdemand_init_early(i915); + intel_pmdemand_init_early(display); intel_power_domains_init_hw(display, false); @@ -265,7 +265,7 @@ int intel_display_driver_probe_noirq(struct intel_display *display) if (ret) goto cleanup_vga_client_pw_domain_dmc; - ret = intel_pmdemand_init(i915); + ret = intel_pmdemand_init(display); if (ret) goto cleanup_vga_client_pw_domain_dmc; diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 34465d56def0..d3b8453a1705 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1103,7 +1103,7 @@ static void gen9_dbuf_enable(struct intel_display *display) slices_mask = BIT(DBUF_S1) | display->dbuf.enabled_slices; if (DISPLAY_VER(display) >= 14) - intel_pmdemand_program_dbuf(dev_priv, slices_mask); + intel_pmdemand_program_dbuf(display, slices_mask); /* * Just power up at least 1 slice, we will @@ -1119,7 +1119,7 @@ static void gen9_dbuf_disable(struct intel_display *display) gen9_dbuf_slices_update(dev_priv, 0); if (DISPLAY_VER(display) >= 14) - intel_pmdemand_program_dbuf(dev_priv, 0); + intel_pmdemand_program_dbuf(display, 0); } static void gen12_dbuf_slices_config(struct intel_display *display) diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 9db30db428f7..9a2bea19f17b 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -116,6 +116,7 @@ static void set_encoder_for_connector(struct intel_connector *connector, static void reset_encoder_connector_state(struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_pmdemand_state *pmdemand_state = to_intel_pmdemand_state(i915->display.pmdemand.obj.state); @@ -128,7 +129,7 @@ static void reset_encoder_connector_state(struct intel_encoder *encoder) continue; /* Clear the corresponding bit in pmdemand active phys mask */ - intel_pmdemand_update_phys_mask(i915, encoder, + intel_pmdemand_update_phys_mask(display, encoder, pmdemand_state, false); set_encoder_for_connector(connector, NULL); @@ -152,6 +153,7 @@ static void reset_crtc_encoder_state(struct intel_crtc *crtc) static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc) { + struct intel_display *display = to_intel_display(crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_bw_state *bw_state = to_intel_bw_state(i915->display.bw.obj.state); @@ -185,7 +187,7 @@ static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc) bw_state->data_rate[pipe] = 0; bw_state->num_active_planes[pipe] = 0; - intel_pmdemand_update_port_clock(i915, pmdemand_state, pipe, 0); + intel_pmdemand_update_port_clock(display, pmdemand_state, pipe, 0); } /* @@ -582,6 +584,7 @@ static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) static void intel_sanitize_encoder(struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_connector *connector; struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); @@ -613,7 +616,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) encoder->base.name); /* Clear the corresponding bit in pmdemand active phys mask */ - intel_pmdemand_update_phys_mask(i915, encoder, + intel_pmdemand_update_phys_mask(display, encoder, pmdemand_state, false); /* @@ -770,11 +773,11 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915) } } - intel_pmdemand_update_phys_mask(i915, encoder, + intel_pmdemand_update_phys_mask(display, encoder, pmdemand_state, true); } else { - intel_pmdemand_update_phys_mask(i915, encoder, + intel_pmdemand_update_phys_mask(display, encoder, pmdemand_state, false); @@ -899,13 +902,13 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915) cdclk_state->min_voltage_level[crtc->pipe] = crtc_state->min_voltage_level; - intel_pmdemand_update_port_clock(i915, pmdemand_state, pipe, + intel_pmdemand_update_port_clock(display, pmdemand_state, pipe, crtc_state->port_clock); intel_bw_crtc_update(bw_state, crtc_state); } - intel_pmdemand_init_pmdemand_params(i915, pmdemand_state); + intel_pmdemand_init_pmdemand_params(display, pmdemand_state); } static void diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c index 500faf639290..9373cf2885ab 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.c +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c @@ -74,10 +74,10 @@ static const struct intel_global_state_funcs intel_pmdemand_funcs = { static struct intel_pmdemand_state * intel_atomic_get_pmdemand_state(struct intel_atomic_state *state) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); struct intel_global_state *pmdemand_state = intel_atomic_get_global_obj_state(state, - &i915->display.pmdemand.obj); + &display->pmdemand.obj); if (IS_ERR(pmdemand_state)) return ERR_CAST(pmdemand_state); @@ -88,10 +88,10 @@ intel_atomic_get_pmdemand_state(struct intel_atomic_state *state) static struct intel_pmdemand_state * intel_atomic_get_old_pmdemand_state(struct intel_atomic_state *state) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); struct intel_global_state *pmdemand_state = intel_atomic_get_old_global_obj_state(state, - &i915->display.pmdemand.obj); + &display->pmdemand.obj); if (!pmdemand_state) return NULL; @@ -102,10 +102,10 @@ intel_atomic_get_old_pmdemand_state(struct intel_atomic_state *state) static struct intel_pmdemand_state * intel_atomic_get_new_pmdemand_state(struct intel_atomic_state *state) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); struct intel_global_state *pmdemand_state = intel_atomic_get_new_global_obj_state(state, - &i915->display.pmdemand.obj); + &display->pmdemand.obj); if (!pmdemand_state) return NULL; @@ -113,40 +113,41 @@ intel_atomic_get_new_pmdemand_state(struct intel_atomic_state *state) return to_intel_pmdemand_state(pmdemand_state); } -int intel_pmdemand_init(struct drm_i915_private *i915) +int intel_pmdemand_init(struct intel_display *display) { + struct drm_i915_private *i915 = to_i915(display->drm); struct intel_pmdemand_state *pmdemand_state; pmdemand_state = kzalloc(sizeof(*pmdemand_state), GFP_KERNEL); if (!pmdemand_state) return -ENOMEM; - intel_atomic_global_obj_init(i915, &i915->display.pmdemand.obj, + intel_atomic_global_obj_init(i915, &display->pmdemand.obj, &pmdemand_state->base, &intel_pmdemand_funcs); - if (IS_DISPLAY_VERx100_STEP(i915, 1400, STEP_A0, STEP_C0)) + if (IS_DISPLAY_VERx100_STEP(display, 1400, STEP_A0, STEP_C0)) /* Wa_14016740474 */ - intel_de_rmw(i915, XELPD_CHICKEN_DCPR_3, 0, DMD_RSP_TIMEOUT_DISABLE); + intel_de_rmw(display, XELPD_CHICKEN_DCPR_3, 0, DMD_RSP_TIMEOUT_DISABLE); return 0; } -void intel_pmdemand_init_early(struct drm_i915_private *i915) +void intel_pmdemand_init_early(struct intel_display *display) { - mutex_init(&i915->display.pmdemand.lock); - init_waitqueue_head(&i915->display.pmdemand.waitqueue); + mutex_init(&display->pmdemand.lock); + init_waitqueue_head(&display->pmdemand.waitqueue); } void -intel_pmdemand_update_phys_mask(struct drm_i915_private *i915, +intel_pmdemand_update_phys_mask(struct intel_display *display, struct intel_encoder *encoder, struct intel_pmdemand_state *pmdemand_state, bool set_bit) { enum phy phy; - if (DISPLAY_VER(i915) < 14) + if (DISPLAY_VER(display) < 14) return; if (!encoder) @@ -164,18 +165,18 @@ intel_pmdemand_update_phys_mask(struct drm_i915_private *i915, } void -intel_pmdemand_update_port_clock(struct drm_i915_private *i915, +intel_pmdemand_update_port_clock(struct intel_display *display, struct intel_pmdemand_state *pmdemand_state, enum pipe pipe, int port_clock) { - if (DISPLAY_VER(i915) < 14) + if (DISPLAY_VER(display) < 14) return; pmdemand_state->ddi_clocks[pipe] = port_clock; } static void -intel_pmdemand_update_max_ddiclk(struct drm_i915_private *i915, +intel_pmdemand_update_max_ddiclk(struct intel_display *display, struct intel_atomic_state *state, struct intel_pmdemand_state *pmdemand_state) { @@ -185,7 +186,7 @@ intel_pmdemand_update_max_ddiclk(struct drm_i915_private *i915, int i; for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) - intel_pmdemand_update_port_clock(i915, pmdemand_state, + intel_pmdemand_update_port_clock(display, pmdemand_state, crtc->pipe, new_crtc_state->port_clock); @@ -196,7 +197,7 @@ intel_pmdemand_update_max_ddiclk(struct drm_i915_private *i915, } static void -intel_pmdemand_update_connector_phys(struct drm_i915_private *i915, +intel_pmdemand_update_connector_phys(struct intel_display *display, struct intel_atomic_state *state, struct drm_connector_state *conn_state, bool set_bit, @@ -217,12 +218,12 @@ intel_pmdemand_update_connector_phys(struct drm_i915_private *i915, if (!crtc_state->hw.active) return; - intel_pmdemand_update_phys_mask(i915, encoder, pmdemand_state, + intel_pmdemand_update_phys_mask(display, encoder, pmdemand_state, set_bit); } static void -intel_pmdemand_update_active_non_tc_phys(struct drm_i915_private *i915, +intel_pmdemand_update_active_non_tc_phys(struct intel_display *display, struct intel_atomic_state *state, struct intel_pmdemand_state *pmdemand_state) { @@ -237,12 +238,12 @@ intel_pmdemand_update_active_non_tc_phys(struct drm_i915_private *i915, continue; /* First clear the active phys in the old connector state */ - intel_pmdemand_update_connector_phys(i915, state, + intel_pmdemand_update_connector_phys(display, state, old_conn_state, false, pmdemand_state); /* Then set the active phys in new connector state */ - intel_pmdemand_update_connector_phys(i915, state, + intel_pmdemand_update_connector_phys(display, state, new_conn_state, true, pmdemand_state); } @@ -253,7 +254,7 @@ intel_pmdemand_update_active_non_tc_phys(struct drm_i915_private *i915, } static bool -intel_pmdemand_encoder_has_tc_phy(struct drm_i915_private *i915, +intel_pmdemand_encoder_has_tc_phy(struct intel_display *display, struct intel_encoder *encoder) { return encoder && intel_encoder_is_tc(encoder); @@ -262,7 +263,7 @@ intel_pmdemand_encoder_has_tc_phy(struct drm_i915_private *i915, static bool intel_pmdemand_connector_needs_update(struct intel_atomic_state *state) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); struct drm_connector_state *old_conn_state; struct drm_connector_state *new_conn_state; struct drm_connector *connector; @@ -279,8 +280,8 @@ intel_pmdemand_connector_needs_update(struct intel_atomic_state *state) continue; if (old_encoder == new_encoder || - (intel_pmdemand_encoder_has_tc_phy(i915, old_encoder) && - intel_pmdemand_encoder_has_tc_phy(i915, new_encoder))) + (intel_pmdemand_encoder_has_tc_phy(display, old_encoder) && + intel_pmdemand_encoder_has_tc_phy(display, new_encoder))) continue; return true; @@ -337,13 +338,13 @@ static bool intel_pmdemand_needs_update(struct intel_atomic_state *state) int intel_pmdemand_atomic_check(struct intel_atomic_state *state) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); const struct intel_bw_state *new_bw_state; const struct intel_cdclk_state *new_cdclk_state; const struct intel_dbuf_state *new_dbuf_state; struct intel_pmdemand_state *new_pmdemand_state; - if (DISPLAY_VER(i915) < 14) + if (DISPLAY_VER(display) < 14) return 0; if (!intel_pmdemand_needs_update(state)) @@ -365,14 +366,14 @@ int intel_pmdemand_atomic_check(struct intel_atomic_state *state) if (IS_ERR(new_dbuf_state)) return PTR_ERR(new_dbuf_state); - if (DISPLAY_VER(i915) < 30) { + if (DISPLAY_VER(display) < 30) { new_pmdemand_state->params.active_dbufs = min_t(u8, hweight8(new_dbuf_state->enabled_slices), 3); new_pmdemand_state->params.active_pipes = min_t(u8, hweight8(new_dbuf_state->active_pipes), 3); } else { new_pmdemand_state->params.active_pipes = - min_t(u8, hweight8(new_dbuf_state->active_pipes), INTEL_NUM_PIPES(i915)); + min_t(u8, hweight8(new_dbuf_state->active_pipes), INTEL_NUM_PIPES(display)); } new_cdclk_state = intel_atomic_get_cdclk_state(state); @@ -384,9 +385,9 @@ int intel_pmdemand_atomic_check(struct intel_atomic_state *state) new_pmdemand_state->params.cdclk_freq_mhz = DIV_ROUND_UP(new_cdclk_state->actual.cdclk, 1000); - intel_pmdemand_update_max_ddiclk(i915, state, new_pmdemand_state); + intel_pmdemand_update_max_ddiclk(display, state, new_pmdemand_state); - intel_pmdemand_update_active_non_tc_phys(i915, state, new_pmdemand_state); + intel_pmdemand_update_active_non_tc_phys(display, state, new_pmdemand_state); /* * Active_PLLs starts with 1 because of CDCLK PLL. @@ -407,36 +408,36 @@ int intel_pmdemand_atomic_check(struct intel_atomic_state *state) return intel_atomic_lock_global_state(&new_pmdemand_state->base); } -static bool intel_pmdemand_check_prev_transaction(struct drm_i915_private *i915) +static bool intel_pmdemand_check_prev_transaction(struct intel_display *display) { - return !(intel_de_wait_for_clear(i915, + return !(intel_de_wait_for_clear(display, XELPDP_INITIATE_PMDEMAND_REQUEST(1), XELPDP_PMDEMAND_REQ_ENABLE, 10) || - intel_de_wait_for_clear(i915, + intel_de_wait_for_clear(display, GEN12_DCPR_STATUS_1, XELPDP_PMDEMAND_INFLIGHT_STATUS, 10)); } void -intel_pmdemand_init_pmdemand_params(struct drm_i915_private *i915, +intel_pmdemand_init_pmdemand_params(struct intel_display *display, struct intel_pmdemand_state *pmdemand_state) { u32 reg1, reg2; - if (DISPLAY_VER(i915) < 14) + if (DISPLAY_VER(display) < 14) return; - mutex_lock(&i915->display.pmdemand.lock); - if (drm_WARN_ON(&i915->drm, - !intel_pmdemand_check_prev_transaction(i915))) { + mutex_lock(&display->pmdemand.lock); + if (drm_WARN_ON(display->drm, + !intel_pmdemand_check_prev_transaction(display))) { memset(&pmdemand_state->params, 0, sizeof(pmdemand_state->params)); goto unlock; } - reg1 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0)); + reg1 = intel_de_read(display, XELPDP_INITIATE_PMDEMAND_REQUEST(0)); - reg2 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1)); + reg2 = intel_de_read(display, XELPDP_INITIATE_PMDEMAND_REQUEST(1)); pmdemand_state->params.qclk_gv_bw = REG_FIELD_GET(XELPDP_PMDEMAND_QCLK_GV_BW_MASK, reg1); @@ -452,7 +453,7 @@ intel_pmdemand_init_pmdemand_params(struct drm_i915_private *i915, pmdemand_state->params.ddiclk_max = REG_FIELD_GET(XELPDP_PMDEMAND_DDICLK_FREQ_MASK, reg2); - if (DISPLAY_VER(i915) >= 30) { + if (DISPLAY_VER(display) >= 30) { pmdemand_state->params.active_pipes = REG_FIELD_GET(XE3_PMDEMAND_PIPES_MASK, reg1); } else { @@ -466,49 +467,49 @@ intel_pmdemand_init_pmdemand_params(struct drm_i915_private *i915, } unlock: - mutex_unlock(&i915->display.pmdemand.lock); + mutex_unlock(&display->pmdemand.lock); } -static bool intel_pmdemand_req_complete(struct drm_i915_private *i915) +static bool intel_pmdemand_req_complete(struct intel_display *display) { - return !(intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1)) & + return !(intel_de_read(display, XELPDP_INITIATE_PMDEMAND_REQUEST(1)) & XELPDP_PMDEMAND_REQ_ENABLE); } -static void intel_pmdemand_wait(struct drm_i915_private *i915) +static void intel_pmdemand_wait(struct intel_display *display) { - if (!wait_event_timeout(i915->display.pmdemand.waitqueue, - intel_pmdemand_req_complete(i915), + if (!wait_event_timeout(display->pmdemand.waitqueue, + intel_pmdemand_req_complete(display), msecs_to_jiffies_timeout(10))) - drm_err(&i915->drm, + drm_err(display->drm, "timed out waiting for Punit PM Demand Response\n"); } /* Required to be programmed during Display Init Sequences. */ -void intel_pmdemand_program_dbuf(struct drm_i915_private *i915, +void intel_pmdemand_program_dbuf(struct intel_display *display, u8 dbuf_slices) { u32 dbufs = min_t(u32, hweight8(dbuf_slices), 3); /* PM Demand only tracks active dbufs on pre-Xe3 platforms */ - if (DISPLAY_VER(i915) >= 30) + if (DISPLAY_VER(display) >= 30) return; - mutex_lock(&i915->display.pmdemand.lock); - if (drm_WARN_ON(&i915->drm, - !intel_pmdemand_check_prev_transaction(i915))) + mutex_lock(&display->pmdemand.lock); + if (drm_WARN_ON(display->drm, + !intel_pmdemand_check_prev_transaction(display))) goto unlock; - intel_de_rmw(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0), + intel_de_rmw(display, XELPDP_INITIATE_PMDEMAND_REQUEST(0), XELPDP_PMDEMAND_DBUFS_MASK, REG_FIELD_PREP(XELPDP_PMDEMAND_DBUFS_MASK, dbufs)); - intel_de_rmw(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1), 0, + intel_de_rmw(display, XELPDP_INITIATE_PMDEMAND_REQUEST(1), 0, XELPDP_PMDEMAND_REQ_ENABLE); - intel_pmdemand_wait(i915); + intel_pmdemand_wait(display); unlock: - mutex_unlock(&i915->display.pmdemand.lock); + mutex_unlock(&display->pmdemand.lock); } static void @@ -568,38 +569,37 @@ intel_pmdemand_update_params(struct intel_display *display, } static void -intel_pmdemand_program_params(struct drm_i915_private *i915, +intel_pmdemand_program_params(struct intel_display *display, const struct intel_pmdemand_state *new, const struct intel_pmdemand_state *old, bool serialized) { - struct intel_display *display = &i915->display; bool changed = false; u32 reg1, mod_reg1; u32 reg2, mod_reg2; - mutex_lock(&i915->display.pmdemand.lock); - if (drm_WARN_ON(&i915->drm, - !intel_pmdemand_check_prev_transaction(i915))) + mutex_lock(&display->pmdemand.lock); + if (drm_WARN_ON(display->drm, + !intel_pmdemand_check_prev_transaction(display))) goto unlock; - reg1 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0)); + reg1 = intel_de_read(display, XELPDP_INITIATE_PMDEMAND_REQUEST(0)); mod_reg1 = reg1; - reg2 = intel_de_read(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1)); + reg2 = intel_de_read(display, XELPDP_INITIATE_PMDEMAND_REQUEST(1)); mod_reg2 = reg2; intel_pmdemand_update_params(display, new, old, &mod_reg1, &mod_reg2, serialized); if (reg1 != mod_reg1) { - intel_de_write(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(0), + intel_de_write(display, XELPDP_INITIATE_PMDEMAND_REQUEST(0), mod_reg1); changed = true; } if (reg2 != mod_reg2) { - intel_de_write(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1), + intel_de_write(display, XELPDP_INITIATE_PMDEMAND_REQUEST(1), mod_reg2); changed = true; } @@ -608,17 +608,17 @@ intel_pmdemand_program_params(struct drm_i915_private *i915, if (!changed) goto unlock; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "initate pmdemand request values: (0x%x 0x%x)\n", mod_reg1, mod_reg2); - intel_de_rmw(i915, XELPDP_INITIATE_PMDEMAND_REQUEST(1), 0, + intel_de_rmw(display, XELPDP_INITIATE_PMDEMAND_REQUEST(1), 0, XELPDP_PMDEMAND_REQ_ENABLE); - intel_pmdemand_wait(i915); + intel_pmdemand_wait(display); unlock: - mutex_unlock(&i915->display.pmdemand.lock); + mutex_unlock(&display->pmdemand.lock); } static bool @@ -630,13 +630,13 @@ intel_pmdemand_state_changed(const struct intel_pmdemand_state *new, void intel_pmdemand_pre_plane_update(struct intel_atomic_state *state) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); const struct intel_pmdemand_state *new_pmdemand_state = intel_atomic_get_new_pmdemand_state(state); const struct intel_pmdemand_state *old_pmdemand_state = intel_atomic_get_old_pmdemand_state(state); - if (DISPLAY_VER(i915) < 14) + if (DISPLAY_VER(display) < 14) return; if (!new_pmdemand_state || @@ -646,20 +646,20 @@ void intel_pmdemand_pre_plane_update(struct intel_atomic_state *state) WARN_ON(!new_pmdemand_state->base.changed); - intel_pmdemand_program_params(i915, new_pmdemand_state, + intel_pmdemand_program_params(display, new_pmdemand_state, old_pmdemand_state, intel_atomic_global_state_is_serialized(state)); } void intel_pmdemand_post_plane_update(struct intel_atomic_state *state) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); const struct intel_pmdemand_state *new_pmdemand_state = intel_atomic_get_new_pmdemand_state(state); const struct intel_pmdemand_state *old_pmdemand_state = intel_atomic_get_old_pmdemand_state(state); - if (DISPLAY_VER(i915) < 14) + if (DISPLAY_VER(display) < 14) return; if (!new_pmdemand_state || @@ -669,6 +669,6 @@ void intel_pmdemand_post_plane_update(struct intel_atomic_state *state) WARN_ON(!new_pmdemand_state->base.changed); - intel_pmdemand_program_params(i915, new_pmdemand_state, NULL, + intel_pmdemand_program_params(display, new_pmdemand_state, NULL, intel_atomic_global_state_is_serialized(state)); } diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.h b/drivers/gpu/drm/i915/display/intel_pmdemand.h index 34f68912fe04..821ef2c4134a 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.h +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.h @@ -9,9 +9,9 @@ #include enum pipe; -struct drm_i915_private; struct intel_atomic_state; struct intel_crtc_state; +struct intel_display; struct intel_encoder; struct intel_global_state; struct intel_plane_state; @@ -19,18 +19,18 @@ struct intel_pmdemand_state; struct intel_pmdemand_state *to_intel_pmdemand_state(struct intel_global_state *obj_state); -void intel_pmdemand_init_early(struct drm_i915_private *i915); -int intel_pmdemand_init(struct drm_i915_private *i915); -void intel_pmdemand_init_pmdemand_params(struct drm_i915_private *i915, +void intel_pmdemand_init_early(struct intel_display *display); +int intel_pmdemand_init(struct intel_display *display); +void intel_pmdemand_init_pmdemand_params(struct intel_display *display, struct intel_pmdemand_state *pmdemand_state); -void intel_pmdemand_update_port_clock(struct drm_i915_private *i915, +void intel_pmdemand_update_port_clock(struct intel_display *display, struct intel_pmdemand_state *pmdemand_state, enum pipe pipe, int port_clock); -void intel_pmdemand_update_phys_mask(struct drm_i915_private *i915, +void intel_pmdemand_update_phys_mask(struct intel_display *display, struct intel_encoder *encoder, struct intel_pmdemand_state *pmdemand_state, bool clear_bit); -void intel_pmdemand_program_dbuf(struct drm_i915_private *i915, +void intel_pmdemand_program_dbuf(struct intel_display *display, u8 dbuf_slices); void intel_pmdemand_pre_plane_update(struct intel_atomic_state *state); void intel_pmdemand_post_plane_update(struct intel_atomic_state *state); -- 2.51.0 From 15133582465fe19252eb1dd90c4570bb42e795ab Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 31 Dec 2024 18:27:40 +0200 Subject: [PATCH 11/16] drm/i915/display: convert global state to struct intel_display Going forward, struct intel_display is the main display device structure. Convert intel_global_state.[ch] to it. This allows us to make intel_pmdemand.c completely independent of i915_drv.h. Cc: Gustavo Sousa Reviewed-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/2b5e743b285a86a59ee87085727847c758c8d552.1735662324.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_bw.c | 3 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 3 +- .../drm/i915/display/intel_display_driver.c | 4 +- .../gpu/drm/i915/display/intel_global_state.c | 42 +++++++++---------- .../gpu/drm/i915/display/intel_global_state.h | 6 +-- drivers/gpu/drm/i915/display/intel_pmdemand.c | 6 +-- drivers/gpu/drm/i915/display/skl_watermark.c | 3 +- 7 files changed, 33 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 08e8a67ca74c..23edc81741de 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -1447,13 +1447,14 @@ static const struct intel_global_state_funcs intel_bw_funcs = { int intel_bw_init(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; struct intel_bw_state *state; state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) return -ENOMEM; - intel_atomic_global_obj_init(i915, &i915->display.bw.obj, + intel_atomic_global_obj_init(display, &display->bw.obj, &state->base, &intel_bw_funcs); /* diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 3506e576bf6b..c7a603589412 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -3217,14 +3217,13 @@ int intel_cdclk_state_set_joined_mbus(struct intel_atomic_state *state, bool joi int intel_cdclk_init(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_cdclk_state *cdclk_state; cdclk_state = kzalloc(sizeof(*cdclk_state), GFP_KERNEL); if (!cdclk_state) return -ENOMEM; - intel_atomic_global_obj_init(dev_priv, &display->cdclk.obj, + intel_atomic_global_obj_init(display, &display->cdclk.obj, &cdclk_state->base, &intel_cdclk_funcs); return 0; diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index c4cfb0406fa2..1aa0b298c278 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -163,9 +163,7 @@ static void intel_mode_config_init(struct intel_display *display) static void intel_mode_config_cleanup(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); - - intel_atomic_global_obj_cleanup(i915); + intel_atomic_global_obj_cleanup(display); drm_mode_config_cleanup(display->drm); } diff --git a/drivers/gpu/drm/i915/display/intel_global_state.c b/drivers/gpu/drm/i915/display/intel_global_state.c index cbcd1e91b7be..8a49e2bb37fa 100644 --- a/drivers/gpu/drm/i915/display/intel_global_state.c +++ b/drivers/gpu/drm/i915/display/intel_global_state.c @@ -75,7 +75,7 @@ intel_atomic_global_state_get(struct intel_global_state *obj_state) return obj_state; } -void intel_atomic_global_obj_init(struct drm_i915_private *dev_priv, +void intel_atomic_global_obj_init(struct intel_display *display, struct intel_global_obj *obj, struct intel_global_state *state, const struct intel_global_state_funcs *funcs) @@ -88,26 +88,26 @@ void intel_atomic_global_obj_init(struct drm_i915_private *dev_priv, obj->state = state; obj->funcs = funcs; - list_add_tail(&obj->head, &dev_priv->display.global.obj_list); + list_add_tail(&obj->head, &display->global.obj_list); } -void intel_atomic_global_obj_cleanup(struct drm_i915_private *dev_priv) +void intel_atomic_global_obj_cleanup(struct intel_display *display) { struct intel_global_obj *obj, *next; - list_for_each_entry_safe(obj, next, &dev_priv->display.global.obj_list, head) { + list_for_each_entry_safe(obj, next, &display->global.obj_list, head) { list_del(&obj->head); - drm_WARN_ON(&dev_priv->drm, kref_read(&obj->state->ref) != 1); + drm_WARN_ON(display->drm, kref_read(&obj->state->ref) != 1); intel_atomic_global_state_put(obj->state); } } -static void assert_global_state_write_locked(struct drm_i915_private *dev_priv) +static void assert_global_state_write_locked(struct intel_display *display) { struct intel_crtc *crtc; - for_each_intel_crtc(&dev_priv->drm, crtc) + for_each_intel_crtc(display->drm, crtc) drm_modeset_lock_assert_held(&crtc->base.mutex); } @@ -126,23 +126,23 @@ static bool modeset_lock_is_held(struct drm_modeset_acquire_ctx *ctx, static void assert_global_state_read_locked(struct intel_atomic_state *state) { + struct intel_display *display = to_intel_display(state); struct drm_modeset_acquire_ctx *ctx = state->base.acquire_ctx; - struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc *crtc; - for_each_intel_crtc(&dev_priv->drm, crtc) { + for_each_intel_crtc(display->drm, crtc) { if (modeset_lock_is_held(ctx, &crtc->base.mutex)) return; } - drm_WARN(&dev_priv->drm, 1, "Global state not read locked\n"); + drm_WARN(display->drm, 1, "Global state not read locked\n"); } struct intel_global_state * intel_atomic_get_global_obj_state(struct intel_atomic_state *state, struct intel_global_obj *obj) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); int index, num_objs, i; size_t size; struct __intel_global_objs_state *arr; @@ -184,7 +184,7 @@ intel_atomic_get_global_obj_state(struct intel_atomic_state *state, state->num_global_objs = num_objs; - drm_dbg_atomic(&i915->drm, "Added new global object %p state %p to %p\n", + drm_dbg_atomic(display->drm, "Added new global object %p state %p to %p\n", obj, obj_state, state); return obj_state; @@ -218,14 +218,14 @@ intel_atomic_get_new_global_obj_state(struct intel_atomic_state *state, void intel_atomic_swap_global_state(struct intel_atomic_state *state) { - struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); struct intel_global_state *old_obj_state, *new_obj_state; struct intel_global_obj *obj; int i; for_each_oldnew_global_obj_in_state(state, obj, old_obj_state, new_obj_state, i) { - drm_WARN_ON(&dev_priv->drm, obj->state != old_obj_state); + drm_WARN_ON(display->drm, obj->state != old_obj_state); /* * If the new state wasn't modified (and properly @@ -234,7 +234,7 @@ void intel_atomic_swap_global_state(struct intel_atomic_state *state) if (!new_obj_state->changed) continue; - assert_global_state_write_locked(dev_priv); + assert_global_state_write_locked(display); old_obj_state->state = state; new_obj_state->state = NULL; @@ -265,10 +265,10 @@ void intel_atomic_clear_global_state(struct intel_atomic_state *state) int intel_atomic_lock_global_state(struct intel_global_state *obj_state) { struct intel_atomic_state *state = obj_state->state; - struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); struct intel_crtc *crtc; - for_each_intel_crtc(&dev_priv->drm, crtc) { + for_each_intel_crtc(display->drm, crtc) { int ret; ret = drm_modeset_lock(&crtc->base.mutex, @@ -298,10 +298,10 @@ int intel_atomic_serialize_global_state(struct intel_global_state *obj_state) bool intel_atomic_global_state_is_serialized(struct intel_atomic_state *state) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); struct intel_crtc *crtc; - for_each_intel_crtc(&i915->drm, crtc) + for_each_intel_crtc(display->drm, crtc) if (!intel_atomic_get_new_crtc_state(state, crtc)) return false; return true; @@ -344,7 +344,7 @@ intel_atomic_global_state_setup_commit(struct intel_atomic_state *state) int intel_atomic_global_state_wait_for_dependencies(struct intel_atomic_state *state) { - struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_display *display = to_intel_display(state); const struct intel_global_state *old_obj_state; struct intel_global_obj *obj; int i; @@ -358,7 +358,7 @@ intel_atomic_global_state_wait_for_dependencies(struct intel_atomic_state *state ret = wait_for_completion_timeout(&commit->done, 10 * HZ); if (ret == 0) { - drm_err(&i915->drm, "global state timed out\n"); + drm_err(display->drm, "global state timed out\n"); return -ETIMEDOUT; } } diff --git a/drivers/gpu/drm/i915/display/intel_global_state.h b/drivers/gpu/drm/i915/display/intel_global_state.h index 6506a8e32972..d42fb2547ee9 100644 --- a/drivers/gpu/drm/i915/display/intel_global_state.h +++ b/drivers/gpu/drm/i915/display/intel_global_state.h @@ -9,8 +9,8 @@ #include #include -struct drm_i915_private; struct intel_atomic_state; +struct intel_display; struct intel_global_obj; struct intel_global_state; @@ -69,11 +69,11 @@ struct __intel_global_objs_state { struct intel_global_state *state, *old_state, *new_state; }; -void intel_atomic_global_obj_init(struct drm_i915_private *dev_priv, +void intel_atomic_global_obj_init(struct intel_display *display, struct intel_global_obj *obj, struct intel_global_state *state, const struct intel_global_state_funcs *funcs); -void intel_atomic_global_obj_cleanup(struct drm_i915_private *dev_priv); +void intel_atomic_global_obj_cleanup(struct intel_display *display); struct intel_global_state * intel_atomic_get_global_obj_state(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c index 9373cf2885ab..975520322136 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.c +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c @@ -5,14 +5,15 @@ #include -#include "i915_drv.h" #include "i915_reg.h" +#include "i915_utils.h" #include "intel_atomic.h" #include "intel_bw.h" #include "intel_cdclk.h" #include "intel_de.h" #include "intel_display_trace.h" #include "intel_pmdemand.h" +#include "intel_step.h" #include "skl_watermark.h" struct pmdemand_params { @@ -115,14 +116,13 @@ intel_atomic_get_new_pmdemand_state(struct intel_atomic_state *state) int intel_pmdemand_init(struct intel_display *display) { - struct drm_i915_private *i915 = to_i915(display->drm); struct intel_pmdemand_state *pmdemand_state; pmdemand_state = kzalloc(sizeof(*pmdemand_state), GFP_KERNEL); if (!pmdemand_state) return -ENOMEM; - intel_atomic_global_obj_init(i915, &display->pmdemand.obj, + intel_atomic_global_obj_init(display, &display->pmdemand.obj, &pmdemand_state->base, &intel_pmdemand_funcs); diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 407af5b9f1dc..f4458d1185b3 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3333,13 +3333,14 @@ intel_atomic_get_dbuf_state(struct intel_atomic_state *state) int intel_dbuf_init(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; struct intel_dbuf_state *dbuf_state; dbuf_state = kzalloc(sizeof(*dbuf_state), GFP_KERNEL); if (!dbuf_state) return -ENOMEM; - intel_atomic_global_obj_init(i915, &i915->display.dbuf.obj, + intel_atomic_global_obj_init(display, &display->dbuf.obj, &dbuf_state->base, &intel_dbuf_funcs); return 0; -- 2.51.0 From 47ad90921586dbe1f37dab3f4352df8e42d2fa30 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 19 Dec 2024 19:14:13 -0300 Subject: [PATCH 12/16] drm/i915/dmc_wl: Use enum values for enable_dmc_wl Currently, after sanitization, enable_dmc_wl will behave like a boolean parameter (enabled vs disabled). However, in upcoming changes, we will allow more values for debugging purposes. For that, let's make the sanitized value an enumeration. Signed-off-by: Gustavo Sousa Reviewed-by: Dnyaneshwar Bhadane Link: https://patchwork.freedesktop.org/patch/msgid/20241219221429.109668-2-gustavo.sousa@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 29 ++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index 02de3ae15074..0850a7d866cc 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -50,6 +50,15 @@ #define DMC_WAKELOCK_CTL_TIMEOUT_US 5000 #define DMC_WAKELOCK_HOLD_TIME 50 +/* + * Possible non-negative values for the enable_dmc_wl param. + */ +enum { + ENABLE_DMC_WL_DISABLED, + ENABLE_DMC_WL_ENABLED, + ENABLE_DMC_WL_MAX, +}; + struct intel_dmc_wl_range { u32 start; u32 end; @@ -270,12 +279,20 @@ static bool __intel_dmc_wl_supported(struct intel_display *display) static void intel_dmc_wl_sanitize_param(struct intel_display *display) { - if (!HAS_DMC_WAKELOCK(display)) - display->params.enable_dmc_wl = 0; - else if (display->params.enable_dmc_wl >= 0) - display->params.enable_dmc_wl = !!display->params.enable_dmc_wl; - else - display->params.enable_dmc_wl = DISPLAY_VER(display) >= 30; + if (!HAS_DMC_WAKELOCK(display)) { + display->params.enable_dmc_wl = ENABLE_DMC_WL_DISABLED; + } else if (display->params.enable_dmc_wl < 0) { + if (DISPLAY_VER(display) >= 30) + display->params.enable_dmc_wl = ENABLE_DMC_WL_ENABLED; + else + display->params.enable_dmc_wl = ENABLE_DMC_WL_DISABLED; + } else if (display->params.enable_dmc_wl >= ENABLE_DMC_WL_MAX) { + display->params.enable_dmc_wl = ENABLE_DMC_WL_ENABLED; + } + + drm_WARN_ON(display->drm, + display->params.enable_dmc_wl < 0 || + display->params.enable_dmc_wl >= ENABLE_DMC_WL_MAX); drm_dbg_kms(display->drm, "Sanitized enable_dmc_wl value: %d\n", display->params.enable_dmc_wl); -- 2.51.0 From 81a1d1f5d275547f51849e14401264f0e8147bd8 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 19 Dec 2024 19:14:14 -0300 Subject: [PATCH 13/16] drm/i915/dmc_wl: Show description string for enable_dmc_wl We already provide the value resulting from sanitization of enable_dmc_wl in dmesg, however the reader will need to either have the meanings memorized or look them up in the parameter's documentation. Let's make things easier by providing a short human-readable name for the parameter in dmesg. Signed-off-by: Gustavo Sousa Reviewed-by: Dnyaneshwar Bhadane Link: https://patchwork.freedesktop.org/patch/msgid/20241219221429.109668-3-gustavo.sousa@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index 0850a7d866cc..af07eaa3a821 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -279,6 +279,8 @@ static bool __intel_dmc_wl_supported(struct intel_display *display) static void intel_dmc_wl_sanitize_param(struct intel_display *display) { + const char *desc; + if (!HAS_DMC_WAKELOCK(display)) { display->params.enable_dmc_wl = ENABLE_DMC_WL_DISABLED; } else if (display->params.enable_dmc_wl < 0) { @@ -294,8 +296,20 @@ static void intel_dmc_wl_sanitize_param(struct intel_display *display) display->params.enable_dmc_wl < 0 || display->params.enable_dmc_wl >= ENABLE_DMC_WL_MAX); - drm_dbg_kms(display->drm, "Sanitized enable_dmc_wl value: %d\n", - display->params.enable_dmc_wl); + switch (display->params.enable_dmc_wl) { + case ENABLE_DMC_WL_DISABLED: + desc = "disabled"; + break; + case ENABLE_DMC_WL_ENABLED: + desc = "enabled"; + break; + default: + desc = "unknown"; + break; + } + + drm_dbg_kms(display->drm, "Sanitized enable_dmc_wl value: %d (%s)\n", + display->params.enable_dmc_wl, desc); } void intel_dmc_wl_init(struct intel_display *display) -- 2.51.0 From a56d1e380d7475c154c39b08a3793a73e015589f Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 19 Dec 2024 19:14:15 -0300 Subject: [PATCH 14/16] drm/i915/dmc_wl: Allow enable_dmc_wl=2 to mean "match any register" When debugging issues that might be related to the DMC wakelock code, it is sometimes useful to compare runs when we match any register offset vs the regular case. If issues disappear when we take the wakelock for any register, it might indicate that we are missing some offset to be tracked. Support matching any register offset with enable_dmc_wl=2. Signed-off-by: Gustavo Sousa Reviewed-by: Dnyaneshwar Bhadane Link: https://patchwork.freedesktop.org/patch/msgid/20241219221429.109668-4-gustavo.sousa@intel.com Signed-off-by: Matt Roper --- .../gpu/drm/i915/display/intel_display_params.c | 2 +- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_params.c b/drivers/gpu/drm/i915/display/intel_display_params.c index f92e4640a613..f0f388f38fa7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.c +++ b/drivers/gpu/drm/i915/display/intel_display_params.c @@ -130,7 +130,7 @@ intel_display_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, intel_display_param_named_unsafe(enable_dmc_wl, int, 0400, "Enable DMC wakelock " - "(-1=use per-chip default, 0=disabled, 1=enabled) " + "(-1=use per-chip default, 0=disabled, 1=enabled, 2=match any register) " "Default: -1"); __maybe_unused diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index af07eaa3a821..d442a150b327 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -56,6 +56,7 @@ enum { ENABLE_DMC_WL_DISABLED, ENABLE_DMC_WL_ENABLED, + ENABLE_DMC_WL_ANY_REGISTER, ENABLE_DMC_WL_MAX, }; @@ -239,10 +240,15 @@ static bool intel_dmc_wl_reg_in_range(i915_reg_t reg, return false; } -static bool intel_dmc_wl_check_range(i915_reg_t reg, u32 dc_state) +static bool intel_dmc_wl_check_range(struct intel_display *display, + i915_reg_t reg, + u32 dc_state) { const struct intel_dmc_wl_range *ranges; + if (display->params.enable_dmc_wl == ENABLE_DMC_WL_ANY_REGISTER) + return true; + /* * Check that the offset is in one of the ranges for which * registers are powered off during DC states. @@ -303,6 +309,9 @@ static void intel_dmc_wl_sanitize_param(struct intel_display *display) case ENABLE_DMC_WL_ENABLED: desc = "enabled"; break; + case ENABLE_DMC_WL_ANY_REGISTER: + desc = "match any register"; + break; default: desc = "unknown"; break; @@ -429,7 +438,8 @@ void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg) spin_lock_irqsave(&wl->lock, flags); - if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state)) + if (i915_mmio_reg_valid(reg) && + !intel_dmc_wl_check_range(display, reg, wl->dc_state)) goto out_unlock; if (!wl->enabled) { @@ -461,7 +471,8 @@ void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg) spin_lock_irqsave(&wl->lock, flags); - if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state)) + if (i915_mmio_reg_valid(reg) && + !intel_dmc_wl_check_range(display, reg, wl->dc_state)) goto out_unlock; if (WARN_RATELIMIT(!refcount_read(&wl->refcount), -- 2.51.0 From 34e47bdbad0353acaf1eeecea64ffa711061b65c Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Thu, 19 Dec 2024 19:14:16 -0300 Subject: [PATCH 15/16] drm/i915/dmc_wl: Allow enable_dmc_wl=3 to mean "always locked" When debugging issues that might be related to the DMC wakelock code, it might be useful to compare runs with the lock acquired while DC states are enabled vs the regular case. If issues disappear with the former, it might be a symptom of something wrong in our code. Support having this "always locked" behavior with enable_dmc_wl=3. Signed-off-by: Gustavo Sousa Reviewed-by: Dnyaneshwar Bhadane Link: https://patchwork.freedesktop.org/patch/msgid/20241219221429.109668-5-gustavo.sousa@intel.com Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/display/intel_display_params.c | 2 +- drivers/gpu/drm/i915/display/intel_dmc_wl.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_params.c b/drivers/gpu/drm/i915/display/intel_display_params.c index f0f388f38fa7..c4f1ab43fc0c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.c +++ b/drivers/gpu/drm/i915/display/intel_display_params.c @@ -130,7 +130,7 @@ intel_display_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, intel_display_param_named_unsafe(enable_dmc_wl, int, 0400, "Enable DMC wakelock " - "(-1=use per-chip default, 0=disabled, 1=enabled, 2=match any register) " + "(-1=use per-chip default, 0=disabled, 1=enabled, 2=match any register, 3=always locked) " "Default: -1"); __maybe_unused diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c index d442a150b327..1bdc08e6aa45 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -57,6 +57,7 @@ enum { ENABLE_DMC_WL_DISABLED, ENABLE_DMC_WL_ENABLED, ENABLE_DMC_WL_ANY_REGISTER, + ENABLE_DMC_WL_ALWAYS_LOCKED, ENABLE_DMC_WL_MAX, }; @@ -312,6 +313,9 @@ static void intel_dmc_wl_sanitize_param(struct intel_display *display) case ENABLE_DMC_WL_ANY_REGISTER: desc = "match any register"; break; + case ENABLE_DMC_WL_ALWAYS_LOCKED: + desc = "always locked"; + break; default: desc = "unknown"; break; @@ -332,7 +336,8 @@ void intel_dmc_wl_init(struct intel_display *display) INIT_DELAYED_WORK(&wl->work, intel_dmc_wl_work); spin_lock_init(&wl->lock); - refcount_set(&wl->refcount, 0); + refcount_set(&wl->refcount, + display->params.enable_dmc_wl == ENABLE_DMC_WL_ALWAYS_LOCKED ? 1 : 0); } /* Must only be called as part of enabling dynamic DC states. */ -- 2.51.0 From e995bb4adc728345d6c988efff36f4933e662703 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 7 Jan 2025 20:22:40 +0200 Subject: [PATCH 16/16] drm/i915/gvt: store virtual_dp_monitor_edid in rodata The virtual DP EDID isn't modified. Add const modifier to store it in rodata. Reviewed-by: Nemesa Garg Reviewed-by: Zhi Wang Link: https://patchwork.freedesktop.org/patch/msgid/20250107182240.1765311-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gvt/display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 95570cabdf27..c98dfcc3d0de 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -97,7 +97,7 @@ int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe) return 0; } -static unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = { +static const unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = { { /* EDID with 1024x768 as its resolution */ /*Header*/ -- 2.51.0