From patchwork Tue Nov 3 01:50:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gwan-gyeong Mun X-Patchwork-Id: 11875735 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E78A3C00A89 for ; Tue, 3 Nov 2020 01:51:04 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 77BCE2074F for ; Tue, 3 Nov 2020 01:51:04 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 77BCE2074F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B76B76E12E; Tue, 3 Nov 2020 01:51:03 +0000 (UTC) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTPS id 46DDC6E12E for ; Tue, 3 Nov 2020 01:51:02 +0000 (UTC) IronPort-SDR: x63oG0g+gLhqTZ1WzBJiPcUN/ja+bO9LisQ3VGZmNplR0nBFcTeglsOexiZdPS+NDRK7zDdoAB zKxhXVISdFiA== X-IronPort-AV: E=McAfee;i="6000,8403,9793"; a="155971618" X-IronPort-AV: E=Sophos;i="5.77,446,1596524400"; d="scan'208";a="155971618" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Nov 2020 17:51:01 -0800 IronPort-SDR: Wxmu3kvbm5o1Nw5z7WLXN8In+pRGplX8Ca+v39aNdoSDNe4HdsGKRTLx14LTqnxi5E4gmbeuZK 2riGcnb95yow== X-IronPort-AV: E=Sophos;i="5.77,446,1596524400"; d="scan'208";a="470597847" Received: from helsinki.fi.intel.com ([10.237.66.162]) by orsmga004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Nov 2020 17:50:59 -0800 From: Gwan-gyeong Mun To: intel-gfx@lists.freedesktop.org Date: Tue, 3 Nov 2020 03:50:44 +0200 Message-Id: <20201103015045.109306-1-gwan-gyeong.mun@intel.com> X-Mailer: git-send-email 2.25.0 MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 1/2] drm/i915/display: Support PSR Multiple Transcoders X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" It is a preliminary work for supporting multiple EDP PSR and DP PanelReplay. And it refactors singleton PSR to Multi Transcoder supportable PSR. And this moves and renames the i915_psr structure of drm_i915_private's to intel_dp's intel_psr structure. It also causes changes in PSR interrupt handling routine for supporting multiple transcoders. But it does not change the scenario and timing of enabling and disabling PSR. Signed-off-by: Gwan-gyeong Mun Cc: José Roberto de Souza Cc: Juha-Pekka Heikkila --- drivers/gpu/drm/i915/display/intel_ddi.c | 5 + drivers/gpu/drm/i915/display/intel_display.c | 6 +- .../drm/i915/display/intel_display_debugfs.c | 109 +++- .../drm/i915/display/intel_display_types.h | 38 ++ drivers/gpu/drm/i915/display/intel_dp.c | 21 +- drivers/gpu/drm/i915/display/intel_psr.c | 606 +++++++++--------- drivers/gpu/drm/i915/display/intel_psr.h | 16 +- drivers/gpu/drm/i915/display/intel_sprite.c | 6 +- drivers/gpu/drm/i915/i915_drv.h | 39 -- drivers/gpu/drm/i915/i915_irq.c | 47 +- 10 files changed, 496 insertions(+), 397 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 19b16517a502..983781ce3683 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4127,7 +4127,10 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state, intel_ddi_set_dp_msa(crtc_state, conn_state); + //TODO: move PSR related functions into intel_psr_update() + intel_psr2_program_trans_man_trk_ctl(intel_dp, crtc_state); intel_psr_update(intel_dp, crtc_state, conn_state); + intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); intel_edp_drrs_update(intel_dp, crtc_state); @@ -5275,6 +5278,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) goto err; dig_port->hpd_pulse = intel_dp_hpd_pulse; + + intel_psr_init(&dig_port->dp); } /* In theory we don't need the encoder->type check, but leave it just in diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index cddbda5303ff..be5238e5d587 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -15506,8 +15506,6 @@ static void commit_pipe_config(struct intel_atomic_state *state, if (new_crtc_state->update_pipe) intel_pipe_fastset(old_crtc_state, new_crtc_state); - - intel_psr2_program_trans_man_trk_ctl(new_crtc_state); } if (dev_priv->display.atomic_update_watermarks) @@ -17435,8 +17433,6 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv) intel_dvo_init(dev_priv); } - intel_psr_init(dev_priv); - for_each_intel_encoder(&dev_priv->drm, encoder) { encoder->base.possible_crtcs = intel_encoder_possible_crtcs(encoder); @@ -18373,7 +18369,7 @@ int intel_modeset_init(struct drm_i915_private *i915) intel_init_ipc(i915); - intel_psr_set_force_mode_changed(i915->psr.dp); + intel_psr_set_force_mode_changed(i915); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index cfb4c1474982..b87c321b2bf5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -248,18 +248,17 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data) "sink internal error", }; struct drm_connector *connector = m->private; - struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector)); int ret; - if (!CAN_PSR(dev_priv)) { - seq_puts(m, "PSR Unsupported\n"); + if (connector->status != connector_status_connected) return -ENODEV; - } - if (connector->status != connector_status_connected) + if (!CAN_PSR(intel_dp)) { + seq_puts(m, "PSR Unsupported\n"); return -ENODEV; + } ret = drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val); @@ -279,12 +278,13 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data) DEFINE_SHOW_ATTRIBUTE(i915_psr_sink_status); static void -psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m) +psr_source_status(struct intel_dp *intel_dp, struct seq_file *m) { u32 val, status_val; const char *status = "unknown"; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - if (dev_priv->psr.psr2_enabled) { + if (intel_dp->psr.psr2_enabled) { static const char * const live_status[] = { "IDLE", "CAPTURE", @@ -299,7 +299,7 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m) "TG_ON" }; val = intel_de_read(dev_priv, - EDP_PSR2_STATUS(dev_priv->psr.transcoder)); + EDP_PSR2_STATUS(intel_dp->psr.transcoder)); status_val = (val & EDP_PSR2_STATUS_STATE_MASK) >> EDP_PSR2_STATUS_STATE_SHIFT; if (status_val < ARRAY_SIZE(live_status)) @@ -316,7 +316,7 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m) "SRDENT_ON", }; val = intel_de_read(dev_priv, - EDP_PSR_STATUS(dev_priv->psr.transcoder)); + EDP_PSR_STATUS(intel_dp->psr.transcoder)); status_val = (val & EDP_PSR_STATUS_STATE_MASK) >> EDP_PSR_STATUS_STATE_SHIFT; if (status_val < ARRAY_SIZE(live_status)) @@ -326,21 +326,18 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m) seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val); } -static int i915_edp_psr_status(struct seq_file *m, void *data) +static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) { - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct i915_psr *psr = &dev_priv->psr; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_psr *psr = &intel_dp->psr; intel_wakeref_t wakeref; const char *status; bool enabled; u32 val; - if (!HAS_PSR(dev_priv)) - return -ENODEV; - seq_printf(m, "Sink support: %s", yesno(psr->sink_support)); - if (psr->dp) - seq_printf(m, " [0x%02x]", psr->dp->psr_dpcd[0]); + if (psr->sink_support) + seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]); seq_puts(m, "\n"); if (!psr->sink_support) @@ -364,16 +361,16 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) if (psr->psr2_enabled) { val = intel_de_read(dev_priv, - EDP_PSR2_CTL(dev_priv->psr.transcoder)); + EDP_PSR2_CTL(intel_dp->psr.transcoder)); enabled = val & EDP_PSR2_ENABLE; } else { val = intel_de_read(dev_priv, - EDP_PSR_CTL(dev_priv->psr.transcoder)); + EDP_PSR_CTL(intel_dp->psr.transcoder)); enabled = val & EDP_PSR_ENABLE; } seq_printf(m, "Source PSR ctl: %s [0x%08x]\n", enableddisabled(enabled), val); - psr_source_status(dev_priv, m); + psr_source_status(intel_dp, m); seq_printf(m, "Busy frontbuffer bits: 0x%08x\n", psr->busy_frontbuffer_bits); @@ -382,7 +379,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) */ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { val = intel_de_read(dev_priv, - EDP_PSR_PERF_CNT(dev_priv->psr.transcoder)); + EDP_PSR_PERF_CNT(intel_dp->psr.transcoder)); val &= EDP_PSR_PERF_CNT_MASK; seq_printf(m, "Performance counter: %u\n", val); } @@ -403,7 +400,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) */ for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame += 3) { val = intel_de_read(dev_priv, - PSR2_SU_STATUS(dev_priv->psr.transcoder, frame)); + PSR2_SU_STATUS(intel_dp->psr.transcoder, frame)); su_frames_val[frame / 3] = val; } @@ -428,24 +425,56 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) return 0; } +static int i915_edp_psr_status(struct seq_file *m, void *data) +{ + struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct intel_encoder *encoder; + struct intel_dp *intel_dp = NULL; + + if (!HAS_PSR(dev_priv)) + return -ENODEV; + + /* Find the first EDP */ + for_each_intel_dp(&dev_priv->drm, encoder) { + if (encoder->type == INTEL_OUTPUT_EDP) { + intel_dp = enc_to_intel_dp(encoder); + break; + } + } + + if (!intel_dp) + return -ENODEV; + + return intel_psr_status(m, intel_dp); +} static int i915_edp_psr_debug_set(void *data, u64 val) { struct drm_i915_private *dev_priv = data; intel_wakeref_t wakeref; - int ret; + int ret = -ENODEV; + struct intel_encoder *encoder; - if (!CAN_PSR(dev_priv)) - return -ENODEV; + if (!HAS_PSR(dev_priv)) + return ret; - drm_dbg_kms(&dev_priv->drm, "Setting PSR debug to %llx\n", val); + for_each_intel_dp(&dev_priv->drm, encoder) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + if (!CAN_PSR(intel_dp)) + continue; - wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); + if (encoder->type == INTEL_OUTPUT_EDP) { + drm_dbg_kms(&dev_priv->drm, "Setting PSR debug to %llx\n", val); - ret = intel_psr_debug_set(dev_priv, val); + wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); - intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); + // TODO: split to each transcoder's PSR debug state + ret = intel_psr_debug_set(intel_dp, val); + + intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); + } + } return ret; } @@ -454,12 +483,25 @@ static int i915_edp_psr_debug_get(void *data, u64 *val) { struct drm_i915_private *dev_priv = data; + struct intel_encoder *encoder; - if (!CAN_PSR(dev_priv)) + if (!HAS_PSR(dev_priv)) return -ENODEV; - *val = READ_ONCE(dev_priv->psr.debug); - return 0; + for_each_intel_dp(&dev_priv->drm, encoder) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + if (!CAN_PSR(intel_dp)) + continue; + + // TODO: split to each transcoder's PSR debug state + if (encoder->type == INTEL_OUTPUT_EDP) { + *val = READ_ONCE(intel_dp->psr.debug); + return 0; + } + } + + return -ENODEV; } DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops, @@ -1103,9 +1145,6 @@ static void drrs_status_per_crtc(struct seq_file *m, /* disable_drrs() will make drrs->dp NULL */ if (!drrs->dp) { seq_puts(m, "Idleness DRRS: Disabled\n"); - if (dev_priv->psr.enabled) - seq_puts(m, - "\tAs PSR is enabled, DRRS is not enabled\n"); mutex_unlock(&drrs->mutex); return; } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f6f0626649e0..42b7f0ff3600 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1286,6 +1286,42 @@ struct intel_dp_compliance { u8 test_lane_count; }; +struct intel_psr { + struct mutex lock; + +#define I915_PSR_DEBUG_MODE_MASK 0x0f +#define I915_PSR_DEBUG_DEFAULT 0x00 +#define I915_PSR_DEBUG_DISABLE 0x01 +#define I915_PSR_DEBUG_ENABLE 0x02 +#define I915_PSR_DEBUG_FORCE_PSR1 0x03 +#define I915_PSR_DEBUG_IRQ 0x10 + + u32 debug; + bool sink_support; + bool enabled; + enum pipe pipe; + enum transcoder transcoder; + bool active; + struct work_struct work; + unsigned busy_frontbuffer_bits; + bool sink_psr2_support; + bool link_standby; + bool colorimetry_support; + bool psr2_enabled; + bool psr2_sel_fetch_enabled; + u8 sink_sync_latency; + ktime_t last_entry_attempt; + ktime_t last_exit; + bool sink_not_reliable; + bool irq_aux_error; + u16 su_x_granularity; + bool dc3co_enabled; + u32 dc3co_exit_delay; + struct delayed_work dc3co_work; + bool force_mode_changed; + struct drm_dp_vsc_sdp vsc; +}; + struct intel_dp { i915_reg_t output_reg; u32 DP; @@ -1406,6 +1442,8 @@ struct intel_dp { bool hobl_failed; bool hobl_active; + + struct intel_psr psr; }; enum lspcon_vendor { diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index cf09aca7607b..f4627351fa17 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2640,12 +2640,10 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp *intel_dp, const struct drm_connector_state *conn_state, struct drm_dp_vsc_sdp *vsc) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - vsc->sdp_type = DP_SDP_VSC; - if (dev_priv->psr.psr2_enabled) { - if (dev_priv->psr.colorimetry_support && + if (intel_dp->psr.psr2_enabled) { + if (intel_dp->psr.colorimetry_support && intel_dp_needs_vsc_sdp(crtc_state, conn_state)) { /* [PSR2, +Colorimetry] */ intel_dp_compute_vsc_colorimetry(crtc_state, conn_state, @@ -7972,6 +7970,17 @@ static void intel_dp_modeset_retry_work_fn(struct work_struct *work) drm_kms_helper_hotplug_event(connector->dev); } +static void intel_dp_update_pipe(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + intel_panel_update_backlight(state, encoder, crtc_state, conn_state); + intel_psr2_program_trans_man_trk_ctl(intel_dp, crtc_state); +} + bool intel_dp_init_connector(struct intel_digital_port *dig_port, struct intel_connector *intel_connector) @@ -8127,7 +8136,7 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, intel_encoder->get_config = intel_dp_get_config; intel_encoder->sync_state = intel_dp_sync_state; intel_encoder->initial_fastset_check = intel_dp_initial_fastset_check; - intel_encoder->update_pipe = intel_panel_update_backlight; + intel_encoder->update_pipe = intel_dp_update_pipe; intel_encoder->suspend = intel_dp_encoder_suspend; intel_encoder->shutdown = intel_dp_encoder_shutdown; if (IS_CHERRYVIEW(dev_priv)) { @@ -8214,6 +8223,8 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, if (!intel_dp_init_connector(dig_port, intel_connector)) goto err_init_connector; + intel_psr_init(&dig_port->dp); + return true; err_init_connector: diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 1576c3722d0b..0dfe8b8440c7 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -79,11 +79,13 @@ * use page flips. */ -static bool psr_global_enabled(struct drm_i915_private *i915) +static bool psr_global_enabled(struct intel_dp *intel_dp) { - switch (i915->psr.debug & I915_PSR_DEBUG_MODE_MASK) { + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + + switch (intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK) { case I915_PSR_DEBUG_DEFAULT: - return i915->params.enable_psr; + return dev_priv->params.enable_psr; case I915_PSR_DEBUG_DISABLE: return false; default: @@ -91,9 +93,9 @@ static bool psr_global_enabled(struct drm_i915_private *i915) } } -static bool psr2_global_enabled(struct drm_i915_private *dev_priv) +static bool psr2_global_enabled(struct intel_dp *intel_dp) { - switch (dev_priv->psr.debug & I915_PSR_DEBUG_MODE_MASK) { + switch (intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK) { case I915_PSR_DEBUG_DISABLE: case I915_PSR_DEBUG_FORCE_PSR1: return false; @@ -102,11 +104,12 @@ static bool psr2_global_enabled(struct drm_i915_private *dev_priv) } } -static void psr_irq_control(struct drm_i915_private *dev_priv) +static void psr_irq_control(struct intel_dp *intel_dp) { enum transcoder trans_shift; u32 mask, val; i915_reg_t imr_reg; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); /* * gen12+ has registers relative to transcoder and one per transcoder @@ -115,14 +118,14 @@ static void psr_irq_control(struct drm_i915_private *dev_priv) */ if (INTEL_GEN(dev_priv) >= 12) { trans_shift = 0; - imr_reg = TRANS_PSR_IMR(dev_priv->psr.transcoder); + imr_reg = TRANS_PSR_IMR(intel_dp->psr.transcoder); } else { - trans_shift = dev_priv->psr.transcoder; + trans_shift = intel_dp->psr.transcoder; imr_reg = EDP_PSR_IMR; } mask = EDP_PSR_ERROR(trans_shift); - if (dev_priv->psr.debug & I915_PSR_DEBUG_IRQ) + if (intel_dp->psr.debug & I915_PSR_DEBUG_IRQ) mask |= EDP_PSR_POST_EXIT(trans_shift) | EDP_PSR_PRE_ENTRY(trans_shift); @@ -171,38 +174,37 @@ static void psr_event_print(struct drm_i915_private *i915, drm_dbg_kms(&i915->drm, "\tPSR disabled\n"); } -void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir) +void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir) { - enum transcoder cpu_transcoder = dev_priv->psr.transcoder; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + enum transcoder cpu_transcoder = intel_dp->psr.transcoder; enum transcoder trans_shift; i915_reg_t imr_reg; ktime_t time_ns = ktime_get(); if (INTEL_GEN(dev_priv) >= 12) { trans_shift = 0; - imr_reg = TRANS_PSR_IMR(dev_priv->psr.transcoder); + imr_reg = TRANS_PSR_IMR(intel_dp->psr.transcoder); } else { - trans_shift = dev_priv->psr.transcoder; + trans_shift = intel_dp->psr.transcoder; imr_reg = EDP_PSR_IMR; } if (psr_iir & EDP_PSR_PRE_ENTRY(trans_shift)) { - dev_priv->psr.last_entry_attempt = time_ns; - drm_dbg_kms(&dev_priv->drm, - "[transcoder %s] PSR entry attempt in 2 vblanks\n", - transcoder_name(cpu_transcoder)); + intel_dp->psr.last_entry_attempt = time_ns; + DRM_DEBUG_KMS("[transcoder %s] PSR entry attempt in 2 vblanks\n", + transcoder_name(cpu_transcoder)); } if (psr_iir & EDP_PSR_POST_EXIT(trans_shift)) { - dev_priv->psr.last_exit = time_ns; - drm_dbg_kms(&dev_priv->drm, - "[transcoder %s] PSR exit completed\n", - transcoder_name(cpu_transcoder)); + intel_dp->psr.last_exit = time_ns; + DRM_DEBUG_KMS("[transcoder %s] PSR exit completed\n", + transcoder_name(cpu_transcoder)); if (INTEL_GEN(dev_priv) >= 9) { u32 val = intel_de_read(dev_priv, PSR_EVENT(cpu_transcoder)); - bool psr2_enabled = dev_priv->psr.psr2_enabled; + bool psr2_enabled = intel_dp->psr.psr2_enabled; intel_de_write(dev_priv, PSR_EVENT(cpu_transcoder), val); @@ -213,10 +215,10 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir) if (psr_iir & EDP_PSR_ERROR(trans_shift)) { u32 val; - drm_warn(&dev_priv->drm, "[transcoder %s] PSR aux error\n", + DRM_WARN("[transcoder %s] PSR aux error\n", transcoder_name(cpu_transcoder)); - dev_priv->psr.irq_aux_error = true; + intel_dp->psr.irq_aux_error = true; /* * If this interruption is not masked it will keep @@ -230,7 +232,7 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir) val |= EDP_PSR_ERROR(trans_shift); intel_de_write(dev_priv, imr_reg, val); - schedule_work(&dev_priv->psr.work); + schedule_work(&intel_dp->psr.work); } } @@ -291,12 +293,6 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = to_i915(dp_to_dig_port(intel_dp)->base.base.dev); - if (dev_priv->psr.dp) { - drm_warn(&dev_priv->drm, - "More than one eDP panel found, PSR support should be extended\n"); - return; - } - drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd, sizeof(intel_dp->psr_dpcd)); @@ -317,12 +313,10 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) return; } - dev_priv->psr.sink_support = true; - dev_priv->psr.sink_sync_latency = + intel_dp->psr.sink_support = true; + intel_dp->psr.sink_sync_latency = intel_dp_get_sink_sync_latency(intel_dp); - dev_priv->psr.dp = intel_dp; - if (INTEL_GEN(dev_priv) >= 9 && (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) { bool y_req = intel_dp->psr_dpcd[1] & @@ -340,14 +334,14 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp) * Y-coordinate requirement panels we would need to enable * GTC first. */ - dev_priv->psr.sink_psr2_support = y_req && alpm; + intel_dp->psr.sink_psr2_support = y_req && alpm; drm_dbg_kms(&dev_priv->drm, "PSR2 %ssupported\n", - dev_priv->psr.sink_psr2_support ? "" : "not "); + intel_dp->psr.sink_psr2_support ? "" : "not "); - if (dev_priv->psr.sink_psr2_support) { - dev_priv->psr.colorimetry_support = + if (intel_dp->psr.sink_psr2_support) { + intel_dp->psr.colorimetry_support = intel_dp_get_colorimetry_status(intel_dp); - dev_priv->psr.su_x_granularity = + intel_dp->psr.su_x_granularity = intel_dp_get_su_x_granulartiy(intel_dp); } } @@ -373,7 +367,7 @@ static void hsw_psr_setup_aux(struct intel_dp *intel_dp) BUILD_BUG_ON(sizeof(aux_msg) > 20); for (i = 0; i < sizeof(aux_msg); i += 4) intel_de_write(dev_priv, - EDP_PSR_AUX_DATA(dev_priv->psr.transcoder, i >> 2), + EDP_PSR_AUX_DATA(intel_dp->psr.transcoder, i >> 2), intel_dp_pack_aux(&aux_msg[i], sizeof(aux_msg) - i)); aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0); @@ -384,7 +378,7 @@ static void hsw_psr_setup_aux(struct intel_dp *intel_dp) /* Select only valid bits for SRD_AUX_CTL */ aux_ctl &= psr_aux_mask; - intel_de_write(dev_priv, EDP_PSR_AUX_CTL(dev_priv->psr.transcoder), + intel_de_write(dev_priv, EDP_PSR_AUX_CTL(intel_dp->psr.transcoder), aux_ctl); } @@ -394,14 +388,14 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp) u8 dpcd_val = DP_PSR_ENABLE; /* Enable ALPM at sink for psr2 */ - if (dev_priv->psr.psr2_enabled) { + if (intel_dp->psr.psr2_enabled) { drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, DP_ALPM_ENABLE | DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE); dpcd_val |= DP_PSR_ENABLE_PSR2 | DP_PSR_IRQ_HPD_WITH_CRC_ERRORS; } else { - if (dev_priv->psr.link_standby) + if (intel_dp->psr.link_standby) dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; if (INTEL_GEN(dev_priv) >= 8) @@ -464,7 +458,7 @@ static u8 psr_compute_idle_frames(struct intel_dp *intel_dp) * off-by-one issue that HW has in some cases. */ idle_frames = max(6, dev_priv->vbt.psr.idle_frames); - idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency + 1); + idle_frames = max(idle_frames, intel_dp->psr.sink_sync_latency + 1); if (drm_WARN_ON(&dev_priv->drm, idle_frames > 0xf)) idle_frames = 0xf; @@ -484,7 +478,7 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp) if (IS_HASWELL(dev_priv)) val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; - if (dev_priv->psr.link_standby) + if (intel_dp->psr.link_standby) val |= EDP_PSR_LINK_STANDBY; val |= intel_psr1_get_tp_time(intel_dp); @@ -492,9 +486,9 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp) if (INTEL_GEN(dev_priv) >= 8) val |= EDP_PSR_CRC_ENABLE; - val |= (intel_de_read(dev_priv, EDP_PSR_CTL(dev_priv->psr.transcoder)) & + val |= (intel_de_read(dev_priv, EDP_PSR_CTL(intel_dp->psr.transcoder)) & EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK); - intel_de_write(dev_priv, EDP_PSR_CTL(dev_priv->psr.transcoder), val); + intel_de_write(dev_priv, EDP_PSR_CTL(intel_dp->psr.transcoder), val); } static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp) @@ -529,7 +523,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) val |= EDP_Y_COORDINATE_ENABLE; - val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1); + val |= EDP_PSR2_FRAME_BEFORE_SU(intel_dp->psr.sink_sync_latency + 1); val |= intel_psr2_get_tp_time(intel_dp); if (INTEL_GEN(dev_priv) >= 12) { @@ -548,7 +542,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= EDP_PSR2_FAST_WAKE(7); } - if (dev_priv->psr.psr2_sel_fetch_enabled) { + if (intel_dp->psr.psr2_sel_fetch_enabled) { /* WA 1408330847 */ if (IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0) || IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0)) @@ -557,20 +551,20 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) DIS_RAM_BYPASS_PSR2_MAN_TRACK); intel_de_write(dev_priv, - PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), + PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), PSR2_MAN_TRK_CTL_ENABLE); } else if (HAS_PSR2_SEL_FETCH(dev_priv)) { intel_de_write(dev_priv, - PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), 0); + PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), 0); } /* * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is * recommending keep this bit unset while PSR2 is enabled. */ - intel_de_write(dev_priv, EDP_PSR_CTL(dev_priv->psr.transcoder), 0); + intel_de_write(dev_priv, EDP_PSR_CTL(intel_dp->psr.transcoder), 0); - intel_de_write(dev_priv, EDP_PSR2_CTL(dev_priv->psr.transcoder), val); + intel_de_write(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder), val); } static bool @@ -593,55 +587,58 @@ static u32 intel_get_frame_time_us(const struct intel_crtc_state *cstate) drm_mode_vrefresh(&cstate->hw.adjusted_mode)); } -static void psr2_program_idle_frames(struct drm_i915_private *dev_priv, +static void psr2_program_idle_frames(struct intel_dp *intel_dp, u32 idle_frames) { + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); u32 val; idle_frames <<= EDP_PSR2_IDLE_FRAME_SHIFT; - val = intel_de_read(dev_priv, EDP_PSR2_CTL(dev_priv->psr.transcoder)); + val = intel_de_read(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder)); val &= ~EDP_PSR2_IDLE_FRAME_MASK; val |= idle_frames; - intel_de_write(dev_priv, EDP_PSR2_CTL(dev_priv->psr.transcoder), val); + intel_de_write(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder), val); } -static void tgl_psr2_enable_dc3co(struct drm_i915_private *dev_priv) +static void tgl_psr2_enable_dc3co(struct intel_dp *intel_dp) { - psr2_program_idle_frames(dev_priv, 0); + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + + psr2_program_idle_frames(intel_dp, 0); intel_display_power_set_target_dc_state(dev_priv, DC_STATE_EN_DC3CO); } -static void tgl_psr2_disable_dc3co(struct drm_i915_private *dev_priv) +static void tgl_psr2_disable_dc3co(struct intel_dp *intel_dp) { - struct intel_dp *intel_dp = dev_priv->psr.dp; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); intel_display_power_set_target_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); - psr2_program_idle_frames(dev_priv, psr_compute_idle_frames(intel_dp)); + psr2_program_idle_frames(intel_dp, psr_compute_idle_frames(intel_dp)); } static void tgl_dc3co_disable_work(struct work_struct *work) { - struct drm_i915_private *dev_priv = - container_of(work, typeof(*dev_priv), psr.dc3co_work.work); + struct intel_dp *intel_dp = + container_of(work, typeof(*intel_dp), psr.dc3co_work.work); - mutex_lock(&dev_priv->psr.lock); + mutex_lock(&intel_dp->psr.lock); /* If delayed work is pending, it is not idle */ - if (delayed_work_pending(&dev_priv->psr.dc3co_work)) + if (delayed_work_pending(&intel_dp->psr.dc3co_work)) goto unlock; - tgl_psr2_disable_dc3co(dev_priv); + tgl_psr2_disable_dc3co(intel_dp); unlock: - mutex_unlock(&dev_priv->psr.lock); + mutex_unlock(&intel_dp->psr.lock); } -static void tgl_disallow_dc3co_on_psr2_exit(struct drm_i915_private *dev_priv) +static void tgl_disallow_dc3co_on_psr2_exit(struct intel_dp *intel_dp) { - if (!dev_priv->psr.dc3co_enabled) + if (!intel_dp->psr.dc3co_enabled) return; - cancel_delayed_work(&dev_priv->psr.dc3co_work); + cancel_delayed_work(&intel_dp->psr.dc3co_work); /* Before PSR2 exit disallow dc3co*/ - tgl_psr2_disable_dc3co(dev_priv); + tgl_psr2_disable_dc3co(intel_dp); } static void @@ -714,7 +711,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay; int psr_max_h = 0, psr_max_v = 0, max_bpp = 0; - if (!dev_priv->psr.sink_psr2_support) + if (!intel_dp->psr.sink_psr2_support) return false; if (!transcoder_has_psr2(dev_priv, crtc_state->cpu_transcoder)) { @@ -724,7 +721,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } - if (!psr2_global_enabled(dev_priv)) { + if (!psr2_global_enabled(intel_dp)) { drm_dbg_kms(&dev_priv->drm, "PSR2 disabled by flag\n"); return false; } @@ -773,10 +770,10 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, * only need to validate the SU block width is a multiple of * x granularity. */ - if (crtc_hdisplay % dev_priv->psr.su_x_granularity) { + if (crtc_hdisplay % intel_dp->psr.su_x_granularity) { drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, hdisplay(%d) not multiple of %d\n", - crtc_hdisplay, dev_priv->psr.su_x_granularity); + crtc_hdisplay, intel_dp->psr.su_x_granularity); return false; } @@ -811,13 +808,10 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, &crtc_state->hw.adjusted_mode; int psr_setup_time; - if (!CAN_PSR(dev_priv)) + if (!CAN_PSR(intel_dp)) return; - if (intel_dp != dev_priv->psr.dp) - return; - - if (!psr_global_enabled(dev_priv)) { + if (!psr_global_enabled(intel_dp)) { drm_dbg_kms(&dev_priv->drm, "PSR disabled by flag\n"); return; } @@ -834,7 +828,7 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, return; } - if (dev_priv->psr.sink_not_reliable) { + if (intel_dp->psr.sink_not_reliable) { drm_dbg_kms(&dev_priv->drm, "PSR sink implementation is not reliable\n"); return; @@ -871,22 +865,22 @@ static void intel_psr_activate(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - if (transcoder_has_psr2(dev_priv, dev_priv->psr.transcoder)) + if (transcoder_has_psr2(dev_priv, intel_dp->psr.transcoder)) drm_WARN_ON(&dev_priv->drm, - intel_de_read(dev_priv, EDP_PSR2_CTL(dev_priv->psr.transcoder)) & EDP_PSR2_ENABLE); + intel_de_read(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder)) & EDP_PSR2_ENABLE); drm_WARN_ON(&dev_priv->drm, - intel_de_read(dev_priv, EDP_PSR_CTL(dev_priv->psr.transcoder)) & EDP_PSR_ENABLE); - drm_WARN_ON(&dev_priv->drm, dev_priv->psr.active); - lockdep_assert_held(&dev_priv->psr.lock); + intel_de_read(dev_priv, EDP_PSR_CTL(intel_dp->psr.transcoder)) & EDP_PSR_ENABLE); + drm_WARN_ON(&dev_priv->drm, intel_dp->psr.active); + lockdep_assert_held(&intel_dp->psr.lock); /* psr1 and psr2 are mutually exclusive.*/ - if (dev_priv->psr.psr2_enabled) + if (intel_dp->psr.psr2_enabled) hsw_activate_psr2(intel_dp); else hsw_activate_psr1(intel_dp); - dev_priv->psr.active = true; + intel_dp->psr.active = true; } static void intel_psr_enable_source(struct intel_dp *intel_dp, @@ -902,7 +896,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) hsw_psr_setup_aux(intel_dp); - if (dev_priv->psr.psr2_enabled && (IS_GEN(dev_priv, 9) && + if (intel_dp->psr.psr2_enabled && (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv))) { i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder); u32 chicken = intel_de_read(dev_priv, reg); @@ -926,10 +920,10 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, if (INTEL_GEN(dev_priv) < 11) mask |= EDP_PSR_DEBUG_MASK_DISP_REG_WRITE; - intel_de_write(dev_priv, EDP_PSR_DEBUG(dev_priv->psr.transcoder), + intel_de_write(dev_priv, EDP_PSR_DEBUG(intel_dp->psr.transcoder), mask); - psr_irq_control(dev_priv); + psr_irq_control(intel_dp); if (crtc_state->dc3co_exitline) { u32 val; @@ -947,30 +941,30 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, if (HAS_PSR_HW_TRACKING(dev_priv) && HAS_PSR2_SEL_FETCH(dev_priv)) intel_de_rmw(dev_priv, CHICKEN_PAR1_1, IGNORE_PSR2_HW_TRACKING, - dev_priv->psr.psr2_sel_fetch_enabled ? + intel_dp->psr.psr2_sel_fetch_enabled ? IGNORE_PSR2_HW_TRACKING : 0); } -static void intel_psr_enable_locked(struct drm_i915_private *dev_priv, +static void intel_psr_enable_locked(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct intel_dp *intel_dp = dev_priv->psr.dp; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct intel_encoder *encoder = &dig_port->base; u32 val; - drm_WARN_ON(&dev_priv->drm, dev_priv->psr.enabled); + drm_WARN_ON(&dev_priv->drm, intel_dp->psr.enabled); - dev_priv->psr.psr2_enabled = crtc_state->has_psr2; - dev_priv->psr.busy_frontbuffer_bits = 0; - dev_priv->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; - dev_priv->psr.dc3co_enabled = !!crtc_state->dc3co_exitline; - dev_priv->psr.transcoder = crtc_state->cpu_transcoder; + intel_dp->psr.psr2_enabled = crtc_state->has_psr2; + intel_dp->psr.busy_frontbuffer_bits = 0; + intel_dp->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe; + intel_dp->psr.dc3co_enabled = !!crtc_state->dc3co_exitline; + intel_dp->psr.transcoder = crtc_state->cpu_transcoder; /* DC5/DC6 requires at least 6 idle frames */ val = usecs_to_jiffies(intel_get_frame_time_us(crtc_state) * 6); - dev_priv->psr.dc3co_exit_delay = val; - dev_priv->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch; + intel_dp->psr.dc3co_exit_delay = val; + intel_dp->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch; /* * If a PSR error happened and the driver is reloaded, the EDP_PSR_IIR @@ -982,27 +976,27 @@ static void intel_psr_enable_locked(struct drm_i915_private *dev_priv, */ if (INTEL_GEN(dev_priv) >= 12) { val = intel_de_read(dev_priv, - TRANS_PSR_IIR(dev_priv->psr.transcoder)); + TRANS_PSR_IIR(intel_dp->psr.transcoder)); val &= EDP_PSR_ERROR(0); } else { val = intel_de_read(dev_priv, EDP_PSR_IIR); - val &= EDP_PSR_ERROR(dev_priv->psr.transcoder); + val &= EDP_PSR_ERROR(intel_dp->psr.transcoder); } if (val) { - dev_priv->psr.sink_not_reliable = true; + intel_dp->psr.sink_not_reliable = true; drm_dbg_kms(&dev_priv->drm, "PSR interruption error set, not enabling PSR\n"); return; } drm_dbg_kms(&dev_priv->drm, "Enabling PSR%s\n", - dev_priv->psr.psr2_enabled ? "2" : "1"); + intel_dp->psr.psr2_enabled ? "2" : "1"); intel_dp_compute_psr_vsc_sdp(intel_dp, crtc_state, conn_state, - &dev_priv->psr.vsc); - intel_write_dp_vsc_sdp(encoder, crtc_state, &dev_priv->psr.vsc); + &intel_dp->psr.vsc); + intel_write_dp_vsc_sdp(encoder, crtc_state, &intel_dp->psr.vsc); intel_psr_enable_sink(intel_dp); intel_psr_enable_source(intel_dp, crtc_state); - dev_priv->psr.enabled = true; + intel_dp->psr.enabled = true; intel_psr_activate(intel_dp); } @@ -1021,56 +1015,57 @@ void intel_psr_enable(struct intel_dp *intel_dp, { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - if (!CAN_PSR(dev_priv) || dev_priv->psr.dp != intel_dp) + if (!CAN_PSR(intel_dp)) return; - dev_priv->psr.force_mode_changed = false; + intel_dp->psr.force_mode_changed = false; if (!crtc_state->has_psr) return; drm_WARN_ON(&dev_priv->drm, dev_priv->drrs.dp); - mutex_lock(&dev_priv->psr.lock); - intel_psr_enable_locked(dev_priv, crtc_state, conn_state); - mutex_unlock(&dev_priv->psr.lock); + mutex_lock(&intel_dp->psr.lock); + intel_psr_enable_locked(intel_dp, crtc_state, conn_state); + mutex_unlock(&intel_dp->psr.lock); } -static void intel_psr_exit(struct drm_i915_private *dev_priv) +static void intel_psr_exit(struct intel_dp *intel_dp) { + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); u32 val; - if (!dev_priv->psr.active) { - if (transcoder_has_psr2(dev_priv, dev_priv->psr.transcoder)) { + if (!intel_dp->psr.active) { + if (transcoder_has_psr2(dev_priv, intel_dp->psr.transcoder)) { val = intel_de_read(dev_priv, - EDP_PSR2_CTL(dev_priv->psr.transcoder)); + EDP_PSR2_CTL(intel_dp->psr.transcoder)); drm_WARN_ON(&dev_priv->drm, val & EDP_PSR2_ENABLE); } val = intel_de_read(dev_priv, - EDP_PSR_CTL(dev_priv->psr.transcoder)); + EDP_PSR_CTL(intel_dp->psr.transcoder)); drm_WARN_ON(&dev_priv->drm, val & EDP_PSR_ENABLE); return; } - if (dev_priv->psr.psr2_enabled) { - tgl_disallow_dc3co_on_psr2_exit(dev_priv); + if (intel_dp->psr.psr2_enabled) { + tgl_disallow_dc3co_on_psr2_exit(intel_dp); val = intel_de_read(dev_priv, - EDP_PSR2_CTL(dev_priv->psr.transcoder)); + EDP_PSR2_CTL(intel_dp->psr.transcoder)); drm_WARN_ON(&dev_priv->drm, !(val & EDP_PSR2_ENABLE)); val &= ~EDP_PSR2_ENABLE; intel_de_write(dev_priv, - EDP_PSR2_CTL(dev_priv->psr.transcoder), val); + EDP_PSR2_CTL(intel_dp->psr.transcoder), val); } else { val = intel_de_read(dev_priv, - EDP_PSR_CTL(dev_priv->psr.transcoder)); + EDP_PSR_CTL(intel_dp->psr.transcoder)); drm_WARN_ON(&dev_priv->drm, !(val & EDP_PSR_ENABLE)); val &= ~EDP_PSR_ENABLE; intel_de_write(dev_priv, - EDP_PSR_CTL(dev_priv->psr.transcoder), val); + EDP_PSR_CTL(intel_dp->psr.transcoder), val); } - dev_priv->psr.active = false; + intel_dp->psr.active = false; } static void intel_psr_disable_locked(struct intel_dp *intel_dp) @@ -1079,21 +1074,21 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) i915_reg_t psr_status; u32 psr_status_mask; - lockdep_assert_held(&dev_priv->psr.lock); + lockdep_assert_held(&intel_dp->psr.lock); - if (!dev_priv->psr.enabled) + if (!intel_dp->psr.enabled) return; drm_dbg_kms(&dev_priv->drm, "Disabling PSR%s\n", - dev_priv->psr.psr2_enabled ? "2" : "1"); + intel_dp->psr.psr2_enabled ? "2" : "1"); - intel_psr_exit(dev_priv); + intel_psr_exit(intel_dp); - if (dev_priv->psr.psr2_enabled) { - psr_status = EDP_PSR2_STATUS(dev_priv->psr.transcoder); + if (intel_dp->psr.psr2_enabled) { + psr_status = EDP_PSR2_STATUS(intel_dp->psr.transcoder); psr_status_mask = EDP_PSR2_STATUS_STATE_MASK; } else { - psr_status = EDP_PSR_STATUS(dev_priv->psr.transcoder); + psr_status = EDP_PSR_STATUS(intel_dp->psr.transcoder); psr_status_mask = EDP_PSR_STATUS_STATE_MASK; } @@ -1103,7 +1098,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) drm_err(&dev_priv->drm, "Timed out waiting PSR idle state\n"); /* WA 1408330847 */ - if (dev_priv->psr.psr2_sel_fetch_enabled && + if (intel_dp->psr.psr2_sel_fetch_enabled && (IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0) || IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0))) intel_de_rmw(dev_priv, CHICKEN_PAR1_1, @@ -1112,10 +1107,10 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) /* Disable PSR on Sink */ drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); - if (dev_priv->psr.psr2_enabled) + if (intel_dp->psr.psr2_enabled) drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, 0); - dev_priv->psr.enabled = false; + intel_dp->psr.enabled = false; } /** @@ -1133,20 +1128,22 @@ void intel_psr_disable(struct intel_dp *intel_dp, if (!old_crtc_state->has_psr) return; - if (drm_WARN_ON(&dev_priv->drm, !CAN_PSR(dev_priv))) + if (drm_WARN_ON(&dev_priv->drm, !CAN_PSR(intel_dp))) return; - mutex_lock(&dev_priv->psr.lock); + mutex_lock(&intel_dp->psr.lock); intel_psr_disable_locked(intel_dp); - mutex_unlock(&dev_priv->psr.lock); - cancel_work_sync(&dev_priv->psr.work); - cancel_delayed_work_sync(&dev_priv->psr.dc3co_work); + mutex_unlock(&intel_dp->psr.lock); + cancel_work_sync(&intel_dp->psr.work); + cancel_delayed_work_sync(&intel_dp->psr.dc3co_work); } -static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv) +static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp) { + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + if (IS_TIGERLAKE(dev_priv)) /* * Writes to CURSURFLIVE in TGL are causing IOMMU errors and @@ -1160,7 +1157,7 @@ static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv) * So using this workaround until this issue is root caused * and a better fix is found. */ - intel_psr_exit(dev_priv); + intel_psr_exit(intel_dp); else if (INTEL_GEN(dev_priv) >= 9) /* * Display WA #0884: skl+ @@ -1171,13 +1168,13 @@ static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv) * but it makes more sense write to the current active * pipe. */ - intel_de_write(dev_priv, CURSURFLIVE(dev_priv->psr.pipe), 0); + intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0); else /* * A write to CURSURFLIVE do not cause HW tracking to exit PSR * on older gens so doing the manual exit instead. */ - intel_psr_exit(dev_priv); + intel_psr_exit(intel_dp); } void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane, @@ -1212,11 +1209,11 @@ void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane, intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_SIZE(pipe, plane->id), val); } -void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state) +void intel_psr2_program_trans_man_trk_ctl(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct i915_psr *psr = &dev_priv->psr; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_psr *psr = &intel_dp->psr; if (!HAS_PSR2_SEL_FETCH(dev_priv) || !crtc_state->enable_psr2_sel_fetch) @@ -1328,15 +1325,15 @@ void intel_psr_update(struct intel_dp *intel_dp, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct i915_psr *psr = &dev_priv->psr; + struct intel_psr *psr = &intel_dp->psr; bool enable, psr2_enable; - if (!CAN_PSR(dev_priv) || READ_ONCE(psr->dp) != intel_dp) + if (!CAN_PSR(intel_dp)) return; - dev_priv->psr.force_mode_changed = false; + intel_dp->psr.force_mode_changed = false; - mutex_lock(&dev_priv->psr.lock); + mutex_lock(&intel_dp->psr.lock); enable = crtc_state->has_psr; psr2_enable = crtc_state->has_psr2; @@ -1344,15 +1341,15 @@ void intel_psr_update(struct intel_dp *intel_dp, if (enable == psr->enabled && psr2_enable == psr->psr2_enabled) { /* Force a PSR exit when enabling CRC to avoid CRC timeouts */ if (crtc_state->crc_enabled && psr->enabled) - psr_force_hw_tracking_exit(dev_priv); + psr_force_hw_tracking_exit(intel_dp); else if (INTEL_GEN(dev_priv) < 9 && psr->enabled) { /* * Activate PSR again after a force exit when enabling * CRC in older gens */ - if (!dev_priv->psr.active && - !dev_priv->psr.busy_frontbuffer_bits) - schedule_work(&dev_priv->psr.work); + if (!intel_dp->psr.active && + !intel_dp->psr.busy_frontbuffer_bits) + schedule_work(&intel_dp->psr.work); } goto unlock; @@ -1362,34 +1359,23 @@ void intel_psr_update(struct intel_dp *intel_dp, intel_psr_disable_locked(intel_dp); if (enable) - intel_psr_enable_locked(dev_priv, crtc_state, conn_state); + intel_psr_enable_locked(intel_dp, crtc_state, conn_state); unlock: - mutex_unlock(&dev_priv->psr.lock); + mutex_unlock(&intel_dp->psr.lock); } /** - * intel_psr_wait_for_idle - wait for PSR1 to idle - * @new_crtc_state: new CRTC state + * psr_wait_for_idle - wait for PSR1 to idle + * @intel_dp: intel_dp * @out_value: PSR status in case of failure * - * This function is expected to be called from pipe_update_start() where it is - * not expected to race with PSR enable or disable. - * * Returns: 0 on success or -ETIMEOUT if PSR status does not idle. + * */ -int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state, - u32 *out_value) +static int psr_wait_for_idle(struct intel_dp *intel_dp, u32 *out_value) { - struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - - if (!dev_priv->psr.enabled || !new_crtc_state->has_psr) - return 0; - - /* FIXME: Update this for PSR2 if we need to wait for idle */ - if (READ_ONCE(dev_priv->psr.psr2_enabled)) - return 0; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); /* * From bspec: Panel Self Refresh (BDW+) @@ -1397,32 +1383,67 @@ int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state, * exit training time + 1.5 ms of aux channel handshake. 50 ms is * defensive enough to cover everything. */ - return __intel_wait_for_register(&dev_priv->uncore, - EDP_PSR_STATUS(dev_priv->psr.transcoder), + EDP_PSR_STATUS(intel_dp->psr.transcoder), EDP_PSR_STATUS_STATE_MASK, EDP_PSR_STATUS_STATE_IDLE, 2, 50, out_value); } -static bool __psr_wait_for_idle_locked(struct drm_i915_private *dev_priv) +/** + * intel_psr_wait_for_idle - wait for PSR1 to idle + * @new_crtc_state: new CRTC state + * + * This function is expected to be called from pipe_update_start() where it is + * not expected to race with PSR enable or disable. + */ +void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(new_crtc_state->uapi.crtc->dev); + struct intel_encoder *encoder; + u32 psr_status; + + if (!new_crtc_state->has_psr) + return; + + for_each_intel_dp(&dev_priv->drm, encoder) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + if (encoder->type != INTEL_OUTPUT_EDP) + continue; + + /* when the PSR1 is enabled */ + if (intel_dp->psr.enabled && !intel_dp->psr.psr2_enabled) { + if (psr_wait_for_idle(intel_dp, &psr_status)) + drm_err(&dev_priv->drm, + "PSR idle timed out 0x%x, atomic update may fail\n", + psr_status); + + /* only one trancoder can enable PSR1 */ + break; + } + } +} + +static bool __psr_wait_for_idle_locked(struct intel_dp *intel_dp) { i915_reg_t reg; u32 mask; int err; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - if (!dev_priv->psr.enabled) + if (!intel_dp->psr.enabled) return false; - if (dev_priv->psr.psr2_enabled) { - reg = EDP_PSR2_STATUS(dev_priv->psr.transcoder); + if (intel_dp->psr.psr2_enabled) { + reg = EDP_PSR2_STATUS(intel_dp->psr.transcoder); mask = EDP_PSR2_STATUS_STATE_MASK; } else { - reg = EDP_PSR_STATUS(dev_priv->psr.transcoder); + reg = EDP_PSR_STATUS(intel_dp->psr.transcoder); mask = EDP_PSR_STATUS_STATE_MASK; } - mutex_unlock(&dev_priv->psr.lock); + mutex_unlock(&intel_dp->psr.lock); err = intel_de_wait_for_clear(dev_priv, reg, mask, 50); if (err) @@ -1430,8 +1451,8 @@ static bool __psr_wait_for_idle_locked(struct drm_i915_private *dev_priv) "Timed out waiting for PSR Idle for re-enable\n"); /* After the unlocked wait, verify that PSR is still wanted! */ - mutex_lock(&dev_priv->psr.lock); - return err == 0 && dev_priv->psr.enabled; + mutex_lock(&intel_dp->psr.lock); + return err == 0 && intel_dp->psr.enabled; } static int intel_psr_fastset_force(struct drm_i915_private *dev_priv) @@ -1497,11 +1518,12 @@ static int intel_psr_fastset_force(struct drm_i915_private *dev_priv) return err; } -int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 val) +int intel_psr_debug_set(struct intel_dp *intel_dp, u64 val) { const u32 mode = val & I915_PSR_DEBUG_MODE_MASK; u32 old_mode; int ret; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); if (val & ~(I915_PSR_DEBUG_IRQ | I915_PSR_DEBUG_MODE_MASK) || mode > I915_PSR_DEBUG_FORCE_PSR1) { @@ -1509,21 +1531,21 @@ int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 val) return -EINVAL; } - ret = mutex_lock_interruptible(&dev_priv->psr.lock); + ret = mutex_lock_interruptible(&intel_dp->psr.lock); if (ret) return ret; - old_mode = dev_priv->psr.debug & I915_PSR_DEBUG_MODE_MASK; - dev_priv->psr.debug = val; + old_mode = intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK; + intel_dp->psr.debug = val; /* * Do it right away if it's already enabled, otherwise it will be done * when enabling the source. */ - if (dev_priv->psr.enabled) - psr_irq_control(dev_priv); + if (intel_dp->psr.enabled) + psr_irq_control(intel_dp); - mutex_unlock(&dev_priv->psr.lock); + mutex_unlock(&intel_dp->psr.lock); if (old_mode != mode) ret = intel_psr_fastset_force(dev_priv); @@ -1531,28 +1553,28 @@ int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 val) return ret; } -static void intel_psr_handle_irq(struct drm_i915_private *dev_priv) +static void intel_psr_handle_irq(struct intel_dp *intel_dp) { - struct i915_psr *psr = &dev_priv->psr; + struct intel_psr *psr = &intel_dp->psr; - intel_psr_disable_locked(psr->dp); + intel_psr_disable_locked(intel_dp); psr->sink_not_reliable = true; /* let's make sure that sink is awaken */ - drm_dp_dpcd_writeb(&psr->dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); } static void intel_psr_work(struct work_struct *work) { - struct drm_i915_private *dev_priv = - container_of(work, typeof(*dev_priv), psr.work); + struct intel_dp *intel_dp = + container_of(work, typeof(*intel_dp), psr.work); - mutex_lock(&dev_priv->psr.lock); + mutex_lock(&intel_dp->psr.lock); - if (!dev_priv->psr.enabled) + if (!intel_dp->psr.enabled) goto unlock; - if (READ_ONCE(dev_priv->psr.irq_aux_error)) - intel_psr_handle_irq(dev_priv); + if (READ_ONCE(intel_dp->psr.irq_aux_error)) + intel_psr_handle_irq(intel_dp); /* * We have to make sure PSR is ready for re-enable @@ -1560,7 +1582,7 @@ static void intel_psr_work(struct work_struct *work) * PSR might take some time to get fully disabled * and be ready for re-enable. */ - if (!__psr_wait_for_idle_locked(dev_priv)) + if (!__psr_wait_for_idle_locked(intel_dp)) goto unlock; /* @@ -1568,12 +1590,12 @@ static void intel_psr_work(struct work_struct *work) * recheck. Since psr_flush first clears this and then reschedules we * won't ever miss a flush when bailing out here. */ - if (dev_priv->psr.busy_frontbuffer_bits || dev_priv->psr.active) + if (intel_dp->psr.busy_frontbuffer_bits || intel_dp->psr.active) goto unlock; - intel_psr_activate(dev_priv->psr.dp); + intel_psr_activate(intel_dp); unlock: - mutex_unlock(&dev_priv->psr.lock); + mutex_unlock(&intel_dp->psr.lock); } /** @@ -1592,27 +1614,35 @@ static void intel_psr_work(struct work_struct *work) void intel_psr_invalidate(struct drm_i915_private *dev_priv, unsigned frontbuffer_bits, enum fb_op_origin origin) { - if (!CAN_PSR(dev_priv)) - return; + struct intel_encoder *encoder; + struct intel_dp *intel_dp; - if (origin == ORIGIN_FLIP) - return; + for_each_intel_dp(&dev_priv->drm, encoder) { - mutex_lock(&dev_priv->psr.lock); - if (!dev_priv->psr.enabled) { - mutex_unlock(&dev_priv->psr.lock); - return; - } + intel_dp = enc_to_intel_dp(encoder); + if (encoder->type != INTEL_OUTPUT_EDP) + continue; + if (!CAN_PSR(intel_dp)) + continue; + + if (origin == ORIGIN_FLIP) + continue; + + mutex_lock(&intel_dp->psr.lock); + if (!intel_dp->psr.enabled) { + mutex_unlock(&intel_dp->psr.lock); + continue; + } - frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(dev_priv->psr.pipe); - dev_priv->psr.busy_frontbuffer_bits |= frontbuffer_bits; + frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe); + intel_dp->psr.busy_frontbuffer_bits |= frontbuffer_bits; - if (frontbuffer_bits) - intel_psr_exit(dev_priv); + if (frontbuffer_bits) + intel_psr_exit(intel_dp); - mutex_unlock(&dev_priv->psr.lock); + mutex_unlock(&intel_dp->psr.lock); + } } - /* * When we will be completely rely on PSR2 S/W tracking in future, * intel_psr_flush() will invalidate and flush the PSR for ORIGIN_FLIP @@ -1620,15 +1650,15 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv, * accordingly in future. */ static void -tgl_dc3co_flush(struct drm_i915_private *dev_priv, - unsigned int frontbuffer_bits, enum fb_op_origin origin) +tgl_dc3co_flush(struct intel_dp *intel_dp, unsigned int frontbuffer_bits, + enum fb_op_origin origin) { - mutex_lock(&dev_priv->psr.lock); + mutex_lock(&intel_dp->psr.lock); - if (!dev_priv->psr.dc3co_enabled) + if (!intel_dp->psr.dc3co_enabled) goto unlock; - if (!dev_priv->psr.psr2_enabled || !dev_priv->psr.active) + if (!intel_dp->psr.psr2_enabled || !intel_dp->psr.active) goto unlock; /* @@ -1636,15 +1666,15 @@ tgl_dc3co_flush(struct drm_i915_private *dev_priv, * when delayed work schedules that means display has been idle. */ if (!(frontbuffer_bits & - INTEL_FRONTBUFFER_ALL_MASK(dev_priv->psr.pipe))) + INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe))) goto unlock; - tgl_psr2_enable_dc3co(dev_priv); - mod_delayed_work(system_wq, &dev_priv->psr.dc3co_work, - dev_priv->psr.dc3co_exit_delay); + tgl_psr2_enable_dc3co(intel_dp); + mod_delayed_work(system_wq, &intel_dp->psr.dc3co_work, + intel_dp->psr.dc3co_exit_delay); unlock: - mutex_unlock(&dev_priv->psr.lock); + mutex_unlock(&intel_dp->psr.lock); } /** @@ -1663,30 +1693,37 @@ tgl_dc3co_flush(struct drm_i915_private *dev_priv, void intel_psr_flush(struct drm_i915_private *dev_priv, unsigned frontbuffer_bits, enum fb_op_origin origin) { - if (!CAN_PSR(dev_priv)) - return; + struct intel_encoder *encoder; + struct intel_dp *intel_dp; - if (origin == ORIGIN_FLIP) { - tgl_dc3co_flush(dev_priv, frontbuffer_bits, origin); - return; - } + for_each_intel_dp(&dev_priv->drm, encoder) { + intel_dp = enc_to_intel_dp(encoder); - mutex_lock(&dev_priv->psr.lock); - if (!dev_priv->psr.enabled) { - mutex_unlock(&dev_priv->psr.lock); - return; - } + if (encoder->type == INTEL_OUTPUT_EDP && CAN_PSR(intel_dp)) { - frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(dev_priv->psr.pipe); - dev_priv->psr.busy_frontbuffer_bits &= ~frontbuffer_bits; + if (origin == ORIGIN_FLIP) { + tgl_dc3co_flush(intel_dp, frontbuffer_bits, origin); + continue; + } - /* By definition flush = invalidate + flush */ - if (frontbuffer_bits) - psr_force_hw_tracking_exit(dev_priv); + mutex_lock(&intel_dp->psr.lock); + if (!intel_dp->psr.enabled) { + mutex_unlock(&intel_dp->psr.lock); + continue; + } - if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits) - schedule_work(&dev_priv->psr.work); - mutex_unlock(&dev_priv->psr.lock); + frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe); + intel_dp->psr.busy_frontbuffer_bits &= ~frontbuffer_bits; + + /* By definition flush = invalidate + flush */ + if (frontbuffer_bits) + psr_force_hw_tracking_exit(intel_dp); + + if (!intel_dp->psr.active && !intel_dp->psr.busy_frontbuffer_bits) + schedule_work(&intel_dp->psr.work); + mutex_unlock(&intel_dp->psr.lock); + } + } } /** @@ -1696,12 +1733,14 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, * This function is called only once at driver load to initialize basic * PSR stuff. */ -void intel_psr_init(struct drm_i915_private *dev_priv) +void intel_psr_init(struct intel_dp *intel_dp) { + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + if (!HAS_PSR(dev_priv)) return; - if (!dev_priv->psr.sink_support) + if (!intel_dp->psr.sink_support) return; if (IS_HASWELL(dev_priv)) @@ -1719,14 +1758,14 @@ void intel_psr_init(struct drm_i915_private *dev_priv) /* Set link_standby x link_off defaults */ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) /* HSW and BDW require workarounds that we don't implement. */ - dev_priv->psr.link_standby = false; + intel_dp->psr.link_standby = false; else if (INTEL_GEN(dev_priv) < 12) /* For new platforms up to TGL let's respect VBT back again */ - dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link; + intel_dp->psr.link_standby = dev_priv->vbt.psr.full_link; - INIT_WORK(&dev_priv->psr.work, intel_psr_work); - INIT_DELAYED_WORK(&dev_priv->psr.dc3co_work, tgl_dc3co_disable_work); - mutex_init(&dev_priv->psr.lock); + INIT_WORK(&intel_dp->psr.work, intel_psr_work); + INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work, tgl_dc3co_disable_work); + mutex_init(&intel_dp->psr.lock); } static int psr_get_status_and_error_status(struct intel_dp *intel_dp, @@ -1752,7 +1791,7 @@ static void psr_alpm_check(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); struct drm_dp_aux *aux = &intel_dp->aux; - struct i915_psr *psr = &dev_priv->psr; + struct intel_psr *psr = &intel_dp->psr; u8 val; int r; @@ -1779,7 +1818,7 @@ static void psr_alpm_check(struct intel_dp *intel_dp) static void psr_capability_changed_check(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct i915_psr *psr = &dev_priv->psr; + struct intel_psr *psr = &intel_dp->psr; u8 val; int r; @@ -1803,18 +1842,18 @@ static void psr_capability_changed_check(struct intel_dp *intel_dp) void intel_psr_short_pulse(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - struct i915_psr *psr = &dev_priv->psr; + struct intel_psr *psr = &intel_dp->psr; u8 status, error_status; const u8 errors = DP_PSR_RFB_STORAGE_ERROR | DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR | DP_PSR_LINK_CRC_ERROR; - if (!CAN_PSR(dev_priv) || !intel_dp_is_edp(intel_dp)) + if (!CAN_PSR(intel_dp) || !intel_dp_is_edp(intel_dp)) return; mutex_lock(&psr->lock); - if (!psr->enabled || psr->dp != intel_dp) + if (!psr->enabled) goto exit; if (psr_get_status_and_error_status(intel_dp, &status, &error_status)) { @@ -1857,15 +1896,14 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp) bool intel_psr_enabled(struct intel_dp *intel_dp) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); bool ret; - if (!CAN_PSR(dev_priv) || !intel_dp_is_edp(intel_dp)) + if (!CAN_PSR(intel_dp) || !intel_dp_is_edp(intel_dp)) return false; - mutex_lock(&dev_priv->psr.lock); - ret = (dev_priv->psr.dp == intel_dp && dev_priv->psr.enabled); - mutex_unlock(&dev_priv->psr.lock); + mutex_lock(&intel_dp->psr.lock); + ret = intel_dp->psr.enabled; + mutex_unlock(&intel_dp->psr.lock); return ret; } @@ -1874,18 +1912,11 @@ void intel_psr_atomic_check(struct drm_connector *connector, struct drm_connector_state *old_state, struct drm_connector_state *new_state) { - struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_connector *intel_connector; - struct intel_digital_port *dig_port; struct drm_crtc_state *crtc_state; + struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector)); - if (!CAN_PSR(dev_priv) || !new_state->crtc || - !dev_priv->psr.force_mode_changed) - return; - - intel_connector = to_intel_connector(connector); - dig_port = enc_to_dig_port(to_intel_encoder(new_state->best_encoder)); - if (dev_priv->psr.dp != &dig_port->dp) + if (!CAN_PSR(intel_dp) || !new_state->crtc || + !intel_dp->psr.force_mode_changed) return; crtc_state = drm_atomic_get_new_crtc_state(new_state->state, @@ -1893,16 +1924,15 @@ void intel_psr_atomic_check(struct drm_connector *connector, crtc_state->mode_changed = true; } -void intel_psr_set_force_mode_changed(struct intel_dp *intel_dp) +/* After initializing PSR sink, it checks requiring of mode_changed */ +void intel_psr_set_force_mode_changed(struct drm_i915_private *i915) { - struct drm_i915_private *dev_priv; + struct intel_encoder *encoder; + struct intel_dp *intel_dp; - if (!intel_dp) - return; - - dev_priv = dp_to_i915(intel_dp); - if (!CAN_PSR(dev_priv) || intel_dp != dev_priv->psr.dp) - return; - - dev_priv->psr.force_mode_changed = true; + for_each_intel_dp(&i915->drm, encoder) { + intel_dp = enc_to_intel_dp(encoder); + if (CAN_PSR(intel_dp)) + intel_dp->psr.force_mode_changed = true; + } } diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index 3eca9dcec3c0..0c64a7832b75 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -18,7 +18,7 @@ struct intel_atomic_state; struct intel_plane_state; struct intel_plane; -#define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support) +#define CAN_PSR(intel_dp) (HAS_PSR(dp_to_i915(intel_dp)) && intel_dp->psr.sink_support) void intel_psr_init_dpcd(struct intel_dp *intel_dp); void intel_psr_enable(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state, @@ -28,28 +28,28 @@ void intel_psr_disable(struct intel_dp *intel_dp, void intel_psr_update(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); -int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 value); +int intel_psr_debug_set(struct intel_dp* intel_dp, u64 value); void intel_psr_invalidate(struct drm_i915_private *dev_priv, unsigned frontbuffer_bits, enum fb_op_origin origin); void intel_psr_flush(struct drm_i915_private *dev_priv, unsigned frontbuffer_bits, enum fb_op_origin origin); -void intel_psr_init(struct drm_i915_private *dev_priv); +void intel_psr_init(struct intel_dp *intel_dp); void intel_psr_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state); -void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir); +void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir); void intel_psr_short_pulse(struct intel_dp *intel_dp); -int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state, - u32 *out_value); +void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state); bool intel_psr_enabled(struct intel_dp *intel_dp); void intel_psr_atomic_check(struct drm_connector *connector, struct drm_connector_state *old_state, struct drm_connector_state *new_state); -void intel_psr_set_force_mode_changed(struct intel_dp *intel_dp); +void intel_psr_set_force_mode_changed(struct drm_i915_private *i915); int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, struct intel_crtc *crtc); -void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state); +void intel_psr2_program_trans_man_trk_ctl(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state, diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index b6deeb338477..ccd86f168357 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -92,7 +92,6 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI); DEFINE_WAIT(wait); - u32 psr_status; if (new_crtc_state->uapi.async_flip) return; @@ -117,10 +116,7 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state) * VBL interrupts will start the PSR exit and prevent a PSR * re-entry as well. */ - if (intel_psr_wait_for_idle(new_crtc_state, &psr_status)) - drm_err(&dev_priv->drm, - "PSR idle timed out 0x%x, atomic update may fail\n", - psr_status); + intel_psr_wait_for_idle(new_crtc_state); local_irq_disable(); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bcd8650603d8..2d96ba766c13 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -475,43 +475,6 @@ struct i915_drrs { enum drrs_support_type type; }; -struct i915_psr { - struct mutex lock; - -#define I915_PSR_DEBUG_MODE_MASK 0x0f -#define I915_PSR_DEBUG_DEFAULT 0x00 -#define I915_PSR_DEBUG_DISABLE 0x01 -#define I915_PSR_DEBUG_ENABLE 0x02 -#define I915_PSR_DEBUG_FORCE_PSR1 0x03 -#define I915_PSR_DEBUG_IRQ 0x10 - - u32 debug; - bool sink_support; - bool enabled; - struct intel_dp *dp; - enum pipe pipe; - enum transcoder transcoder; - bool active; - struct work_struct work; - unsigned busy_frontbuffer_bits; - bool sink_psr2_support; - bool link_standby; - bool colorimetry_support; - bool psr2_enabled; - bool psr2_sel_fetch_enabled; - u8 sink_sync_latency; - ktime_t last_entry_attempt; - ktime_t last_exit; - bool sink_not_reliable; - bool irq_aux_error; - u16 su_x_granularity; - bool dc3co_enabled; - u32 dc3co_exit_delay; - struct delayed_work dc3co_work; - bool force_mode_changed; - struct drm_dp_vsc_sdp vsc; -}; - #define QUIRK_LVDS_SSC_DISABLE (1<<1) #define QUIRK_INVERT_BRIGHTNESS (1<<2) #define QUIRK_BACKLIGHT_PRESENT (1<<3) @@ -1042,8 +1005,6 @@ struct drm_i915_private { struct i915_power_domains power_domains; - struct i915_psr psr; - struct i915_gpu_error gpu_error; struct drm_i915_gem_object *vlv_pctx; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e0eb32bd9607..6d43298c46dd 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2057,10 +2057,20 @@ static void ivb_display_irq_handler(struct drm_i915_private *dev_priv, ivb_err_int_handler(dev_priv); if (de_iir & DE_EDP_PSR_INT_HSW) { - u32 psr_iir = I915_READ(EDP_PSR_IIR); + struct intel_encoder *encoder; - intel_psr_irq_handler(dev_priv, psr_iir); - I915_WRITE(EDP_PSR_IIR, psr_iir); + for_each_intel_dp(&dev_priv->drm, encoder) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + if (encoder->type == INTEL_OUTPUT_EDP && + CAN_PSR(intel_dp)) { + u32 psr_iir = I915_READ(EDP_PSR_IIR); + + intel_psr_irq_handler(intel_dp, psr_iir); + I915_WRITE(EDP_PSR_IIR, psr_iir); + break; + } + } } if (de_iir & DE_AUX_CHANNEL_A_IVB) @@ -2268,21 +2278,34 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir) } if (iir & GEN8_DE_EDP_PSR) { + struct intel_encoder *encoder; u32 psr_iir; i915_reg_t iir_reg; - if (INTEL_GEN(dev_priv) >= 12) - iir_reg = TRANS_PSR_IIR(dev_priv->psr.transcoder); - else - iir_reg = EDP_PSR_IIR; + for_each_intel_dp(&dev_priv->drm, encoder) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - psr_iir = I915_READ(iir_reg); - I915_WRITE(iir_reg, psr_iir); + if (INTEL_GEN(dev_priv) >= 12 && CAN_PSR(intel_dp)) { + iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder); + } else if (encoder->type == INTEL_OUTPUT_EDP && + CAN_PSR(intel_dp)) { + iir_reg = EDP_PSR_IIR; + } else { + continue; + } + + psr_iir = I915_READ(iir_reg); + I915_WRITE(iir_reg, psr_iir); + + if (psr_iir) + found = true; - if (psr_iir) - found = true; + intel_psr_irq_handler(intel_dp, psr_iir); - intel_psr_irq_handler(dev_priv, psr_iir); + /* prior GEN12 only have one EDP PSR */ + if (INTEL_GEN(dev_priv) < 12) + break; + } } if (!found) From patchwork Tue Nov 3 01:50:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gwan-gyeong Mun X-Patchwork-Id: 11875733 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 41AA2C4742C for ; Tue, 3 Nov 2020 01:51:07 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D325C2074F for ; Tue, 3 Nov 2020 01:51:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D325C2074F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3E22A6E827; Tue, 3 Nov 2020 01:51:04 +0000 (UTC) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6E9956E81F for ; Tue, 3 Nov 2020 01:51:02 +0000 (UTC) IronPort-SDR: jBRnwqdztMpUYqvWqQpU3QoPZo4iK33RtLAWsQsFqxaZjWyaKILT0zuMOGwInAYYQoMABMC9Pz YZ8sl9ljd4Cw== X-IronPort-AV: E=McAfee;i="6000,8403,9793"; a="155971619" X-IronPort-AV: E=Sophos;i="5.77,446,1596524400"; d="scan'208";a="155971619" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Nov 2020 17:51:02 -0800 IronPort-SDR: OwTF62NOCPCtyizqYESEDxQbmclLqFevcJLZJv+PsqmTySHOXeOTA7mMiAWKVmgY1x3pfN8WmM YXb0yp7Qsm1A== X-IronPort-AV: E=Sophos;i="5.77,446,1596524400"; d="scan'208";a="470597857" Received: from helsinki.fi.intel.com ([10.237.66.162]) by orsmga004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Nov 2020 17:51:01 -0800 From: Gwan-gyeong Mun To: intel-gfx@lists.freedesktop.org Date: Tue, 3 Nov 2020 03:50:45 +0200 Message-Id: <20201103015045.109306-2-gwan-gyeong.mun@intel.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20201103015045.109306-1-gwan-gyeong.mun@intel.com> References: <20201103015045.109306-1-gwan-gyeong.mun@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 2/2] drm/i915/display: Support Multiple Transcoders' PSR status on debugfs X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" In order to support the PSR state of each transcoder, it adds i915_psr_status to sub-directory of each transcoder. Signed-off-by: Gwan-gyeong Mun Cc: José Roberto de Souza --- .../drm/i915/display/intel_display_debugfs.c | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index b87c321b2bf5..2c5c6097dfd2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -2091,6 +2091,23 @@ static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data) } DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability); +static int i915_psr_status_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + struct intel_dp *intel_dp = + intel_attached_dp(to_intel_connector(connector)); + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + + if (connector->status != connector_status_connected) + return -ENODEV; + + if (!HAS_PSR(dev_priv)) + return -ENODEV; + + return intel_psr_status(m, intel_dp); +} +DEFINE_SHOW_ATTRIBUTE(i915_psr_status); + #define LPSP_CAPABLE(COND) (COND ? seq_puts(m, "LPSP: capable\n") : \ seq_puts(m, "LPSP: incapable\n")) @@ -2266,6 +2283,12 @@ int intel_connector_debugfs_add(struct drm_connector *connector) connector, &i915_psr_sink_status_fops); } + if (INTEL_GEN(dev_priv) >= 12 && + connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + debugfs_create_file("i915_psr_status", S_IRUGO, root, + connector, &i915_psr_status_fops); + } + if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector->connector_type == DRM_MODE_CONNECTOR_HDMIA || connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {