From: Rodrigo Vivi <rodrigo.vivi@gmail.com>
To: intel-gfx@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
Subject: [PATCH 04/11] drm/i915: Enable/Disable PSR
Date: Wed, 26 Jun 2013 18:55:15 -0300 [thread overview]
Message-ID: <1372283722-12988-4-git-send-email-rodrigo.vivi@gmail.com> (raw)
In-Reply-To: <1372283722-12988-1-git-send-email-rodrigo.vivi@gmail.com>
Adding Enable and Disable PSR functionalities. This includes setting the
PSR configuration over AUX, sending SDP VSC DIP over the eDP PIPE config,
enabling PSR in the sink via DPCD register and finally enabling PSR on
the host.
This patch is based on initial PSR code by Sateesh Kavuri and Kumar Shobhit
but in a different implementation.
v2: * moved functions around and changed its names.
* removed VSC DIP unset from disable.
* remove FBC wa.
* don't mask LSPS anymore.
* incorporate new crtc usage after a rebase.
v3: Make a clear separation between Sink (Panel) and Source (HW) enabling.
Credits-by: Sateesh Kavuri <sateesh.kavuri@intel.com>
Credits-by: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
drivers/gpu/drm/i915/i915_reg.h | 42 +++++++++++
drivers/gpu/drm/i915/intel_dp.c | 151 +++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_drv.h | 3 +
3 files changed, 196 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 137be4c..caf57d8 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1777,6 +1777,47 @@
#define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
#define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
+/* HSW eDP PSR registers */
+#define EDP_PSR_CTL 0x64800
+#define EDP_PSR_ENABLE (1<<31)
+#define EDP_PSR_LINK_DISABLE (0<<27)
+#define EDP_PSR_LINK_STANDBY (1<<27)
+#define EDP_PSR_MIN_LINK_ENTRY_TIME_MASK (3<<25)
+#define EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES (0<<25)
+#define EDP_PSR_MIN_LINK_ENTRY_TIME_4_LINES (1<<25)
+#define EDP_PSR_MIN_LINK_ENTRY_TIME_2_LINES (2<<25)
+#define EDP_PSR_MIN_LINK_ENTRY_TIME_0_LINES (3<<25)
+#define EDP_PSR_MAX_SLEEP_TIME_SHIFT 20
+#define EDP_PSR_SKIP_AUX_EXIT (1<<12)
+#define EDP_PSR_TP1_TP2_SEL (0<<11)
+#define EDP_PSR_TP1_TP3_SEL (1<<11)
+#define EDP_PSR_TP2_TP3_TIME_500us (0<<8)
+#define EDP_PSR_TP2_TP3_TIME_100us (1<<8)
+#define EDP_PSR_TP2_TP3_TIME_2500us (2<<8)
+#define EDP_PSR_TP2_TP3_TIME_0us (3<<8)
+#define EDP_PSR_TP1_TIME_500us (0<<4)
+#define EDP_PSR_TP1_TIME_100us (1<<4)
+#define EDP_PSR_TP1_TIME_2500us (2<<4)
+#define EDP_PSR_TP1_TIME_0us (3<<4)
+#define EDP_PSR_IDLE_FRAME_SHIFT 0
+
+#define EDP_PSR_AUX_CTL 0x64810
+#define EDP_PSR_AUX_DATA1 0x64814
+#define EDP_PSR_DPCD_COMMAND 0x80060000
+#define EDP_PSR_AUX_DATA2 0x64818
+#define EDP_PSR_DPCD_NORMAL_OPERATION (1<<24)
+#define EDP_PSR_AUX_DATA3 0x6481c
+#define EDP_PSR_AUX_DATA4 0x64820
+#define EDP_PSR_AUX_DATA5 0x64824
+
+#define EDP_PSR_STATUS_CTL 0x64840
+#define EDP_PSR_STATUS_STATE_MASK (7<<29)
+
+#define EDP_PSR_DEBUG_CTL 0x64860
+#define EDP_PSR_DEBUG_MASK_LPSP (1<<27)
+#define EDP_PSR_DEBUG_MASK_MEMUP (1<<26)
+#define EDP_PSR_DEBUG_MASK_HPD (1<<25)
+
/* VGA port control */
#define ADPA 0x61100
#define PCH_ADPA 0xe1100
@@ -2046,6 +2087,7 @@
* (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each byte
* of the infoframe structure specified by CEA-861. */
#define VIDEO_DIP_DATA_SIZE 32
+#define VIDEO_DIP_VSC_DATA_SIZE 36
#define VIDEO_DIP_CTL 0x61170
/* Pre HSW: */
#define VIDEO_DIP_ENABLE (1 << 31)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 5cd276b..144f216 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1356,6 +1356,157 @@ static bool is_edp_psr(struct intel_dp *intel_dp)
(intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED));
}
+static bool intel_edp_is_psr_enabled(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (!IS_HASWELL(dev))
+ return false;
+
+ return I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
+}
+
+void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
+ struct edp_vsc_psr *vsc_psr)
+{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc);
+
+ u32 ctl_reg = HSW_TVIDEO_DIP_CTL(crtc->config.cpu_transcoder);
+ u32 data_reg = HSW_TVIDEO_DIP_VSC_DATA(crtc->config.cpu_transcoder);
+ uint32_t *data = (uint32_t *) vsc_psr;
+ unsigned int i;
+ u32 val = I915_READ(ctl_reg);
+
+ /* As per eDP spec, wait for vblank to send SDP VSC packet */
+ intel_wait_for_vblank(dev, crtc->pipe);
+
+ /* As per BSPec (Pipe Video Data Island Packet), besides wait for
+ vsync we need to disable the video DIP being updated before program
+ video DIP data buffer registers for DIP being updated.*/
+ I915_WRITE(ctl_reg, val & ~VIDEO_DIP_ENABLE_VSC_HSW);
+ POSTING_READ(ctl_reg);
+
+ for (i = 0; i < VIDEO_DIP_VSC_DATA_SIZE; i += 4) {
+ if (i < sizeof(struct edp_vsc_psr))
+ I915_WRITE(data_reg + i, *data++);
+ else
+ I915_WRITE(data_reg + i, 0);
+ }
+
+ I915_WRITE(ctl_reg, val | VIDEO_DIP_ENABLE_VSC_HSW);
+ POSTING_READ(ctl_reg);
+}
+
+static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct edp_vsc_psr psr_vsc;
+ uint32_t aux_clock_divider = get_aux_clock_divider(intel_dp);
+ int precharge = 0x3;
+ int msg_size = 5; /* Header(4) + Message(1) */
+
+ /* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */
+ memset(&psr_vsc, 0, sizeof(psr_vsc));
+ psr_vsc.sdp_header.HB0 = 0;
+ psr_vsc.sdp_header.HB1 = 0x7;
+ psr_vsc.sdp_header.HB2 = 0x2;
+ psr_vsc.sdp_header.HB3 = 0x8;
+ intel_edp_psr_write_vsc(intel_dp, &psr_vsc);
+
+ /* Enable PSR in sink */
+ if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT)
+ intel_dp_aux_native_write_1(intel_dp, DP_PSR_EN_CFG,
+ DP_PSR_ENABLE &
+ ~DP_PSR_MAIN_LINK_ACTIVE);
+ else
+ intel_dp_aux_native_write_1(intel_dp, DP_PSR_EN_CFG,
+ DP_PSR_ENABLE |
+ DP_PSR_MAIN_LINK_ACTIVE);
+
+ /* Setup AUX registers */
+ I915_WRITE(EDP_PSR_AUX_DATA1, EDP_PSR_DPCD_COMMAND);
+ I915_WRITE(EDP_PSR_AUX_DATA2, EDP_PSR_DPCD_NORMAL_OPERATION);
+ I915_WRITE(EDP_PSR_AUX_CTL,
+ DP_AUX_CH_CTL_TIME_OUT_400us |
+ (msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+ (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+ (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT));
+}
+
+static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ uint32_t max_sleep_time = 0x1f;
+ uint32_t idle_frames = 1;
+ uint32_t val = 0x0;
+
+ if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT) {
+ val |= EDP_PSR_LINK_STANDBY;
+ val |= EDP_PSR_TP2_TP3_TIME_0us;
+ val |= EDP_PSR_TP1_TIME_0us;
+ val |= EDP_PSR_SKIP_AUX_EXIT;
+ } else {
+ val |= EDP_PSR_LINK_DISABLE;
+ val |= EDP_PSR_TP1_TIME_500us;
+ val |= EDP_PSR_TP2_TP3_TIME_500us;
+ }
+
+ /* Avoid continuous PSR exit by masking memup and hpd */
+ I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP |
+ EDP_PSR_DEBUG_MASK_HPD);
+
+ /* Disable unused interrupts */
+ I915_WRITE(GEN6_PMINTRMSK, GEN6_PM_RP_UP_EI_EXPIRED |
+ GEN6_PM_RP_DOWN_EI_EXPIRED);
+
+ I915_WRITE(EDP_PSR_CTL, val |
+ EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES |
+ max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT |
+ idle_frames << EDP_PSR_IDLE_FRAME_SHIFT |
+ EDP_PSR_ENABLE);
+}
+
+void intel_edp_psr_enable(struct intel_dp* intel_dp)
+{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+
+ if (!is_edp_psr(intel_dp) || intel_edp_is_psr_enabled(dev))
+ return;
+
+ /* Enable PSR on the panel */
+ intel_edp_psr_enable_sink(intel_dp);
+
+ /* Enable PSR on the host */
+ intel_edp_psr_enable_source(intel_dp);
+}
+
+void intel_edp_psr_disable(struct intel_dp* intel_dp)
+{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
+ uint32_t val;
+
+ if (!intel_edp_is_psr_enabled(dev))
+ return;
+
+ val = I915_READ(EDP_PSR_CTL);
+ I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_ENABLE);
+
+ /* Wait till PSR is idle */
+ if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL) &
+ EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
+ DRM_ERROR("Timed out waiting for PSR Idle State\n");
+
+ intel_wait_for_vblank(dev, intel_crtc->pipe);
+}
+
static void intel_disable_dp(struct intel_encoder *encoder)
{
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9b264ee..f86d9c5 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -840,4 +840,7 @@ extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
enum transcoder pch_transcoder,
bool enable);
+extern void intel_edp_psr_enable(struct intel_dp* intel_dp);
+extern void intel_edp_psr_disable(struct intel_dp* intel_dp);
+
#endif /* __INTEL_DRV_H__ */
--
1.8.1.4
next prev parent reply other threads:[~2013-06-26 21:55 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-26 21:55 [PATCH 01/11] drm: Added SDP and VSC structures for handling PSR for eDP Rodrigo Vivi
2013-06-26 21:55 ` [PATCH 02/11] drm/i915: Read the EDP DPCD and PSR Capability Rodrigo Vivi
2013-06-28 16:57 ` [PATCH] " Rodrigo Vivi
2013-06-26 21:55 ` [PATCH 03/11] drm/i915: split aux_clock_divider logic in a separated function for reuse Rodrigo Vivi
2013-06-26 21:55 ` Rodrigo Vivi [this message]
2013-06-28 17:16 ` [PATCH] drm/i915: Enable/Disable PSR Rodrigo Vivi
2013-06-28 19:31 ` Paulo Zanoni
2013-07-01 20:40 ` Rodrigo Vivi
2013-07-05 21:58 ` Paulo Zanoni
2013-07-05 22:14 ` Daniel Vetter
2013-07-08 22:09 ` Rodrigo Vivi
2013-07-02 0:29 ` Rodrigo Vivi
2013-07-05 22:20 ` Paulo Zanoni
2013-06-26 21:55 ` [PATCH 05/11] drm/i915: Added debugfs support for PSR Status Rodrigo Vivi
2013-06-28 17:29 ` [PATCH] " Rodrigo Vivi
2013-06-28 20:08 ` Paulo Zanoni
2013-06-28 20:14 ` Paulo Zanoni
2013-07-02 0:46 ` Rodrigo Vivi
2013-06-26 21:55 ` [PATCH 06/11] drm/i915: Match all PSR mode entry conditions before enabling it Rodrigo Vivi
2013-06-28 17:36 ` [PATCH] " Rodrigo Vivi
2013-06-28 20:46 ` Paulo Zanoni
2013-07-01 20:47 ` Rodrigo Vivi
2013-07-05 20:32 ` Daniel Vetter
2013-07-08 22:25 ` Rodrigo Vivi
2013-07-11 18:09 ` Rodrigo Vivi
2013-07-02 0:50 ` Rodrigo Vivi
2013-06-26 21:55 ` [PATCH 07/11] drm/i915: add update function to disable/enable-back PSR Rodrigo Vivi
2013-06-28 17:44 ` [PATCH] " Rodrigo Vivi
2013-07-05 22:48 ` Paulo Zanoni
2013-07-08 21:52 ` Rodrigo Vivi
2013-06-26 21:55 ` [PATCH 08/11] drm/intel: add enable_psr module option Rodrigo Vivi
2013-06-28 17:47 ` [PATCH] " Rodrigo Vivi
2013-07-08 12:45 ` Paulo Zanoni
2013-06-26 21:55 ` [PATCH 09/11] drm/i915: Adding global I915_PARAM for PSR ACTIVE Rodrigo Vivi
2013-06-26 22:18 ` Chris Wilson
2013-06-26 23:23 ` [PATCH] drm/i915: Adding global I915_PARAM for PSR ENABLED Rodrigo Vivi
2013-06-27 12:51 ` Rodrigo Vivi
2013-06-26 21:55 ` [PATCH 10/11] drm/i915: Add functions to force psr exit Rodrigo Vivi
2013-06-27 13:03 ` [PATCH] " Rodrigo Vivi
2013-06-28 17:52 ` Rodrigo Vivi
2013-06-28 17:57 ` Chris Wilson
2013-06-28 18:05 ` Rodrigo Vivi
2013-07-08 13:03 ` Paulo Zanoni
2013-07-08 21:48 ` Rodrigo Vivi
2013-06-26 21:55 ` [PATCH 11/11] drm/i915: Hook PSR functionality Rodrigo Vivi
2013-06-28 21:00 ` Paulo Zanoni
2013-07-02 0:52 ` [PATCH] " Rodrigo Vivi
2013-07-08 13:13 ` Paulo Zanoni
2013-07-08 19:46 ` Daniel Vetter
2013-07-08 21:40 ` Rodrigo Vivi
2013-07-11 21:44 [PATCH 00/11] Enable PSR on Haswell Rodrigo Vivi
2013-07-11 21:44 ` [PATCH 04/11] drm/i915: Enable/Disable PSR Rodrigo Vivi
2013-07-17 17:02 ` Paulo Zanoni
2013-07-18 7:56 ` Daniel Vetter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1372283722-12988-4-git-send-email-rodrigo.vivi@gmail.com \
--to=rodrigo.vivi@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.