All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/11] drm: Added SDP and VSC structures for handling PSR for eDP
@ 2013-06-26 21:55 Rodrigo Vivi
  2013-06-26 21:55 ` [PATCH 02/11] drm/i915: Read the EDP DPCD and PSR Capability Rodrigo Vivi
                   ` (9 more replies)
  0 siblings, 10 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: Shobhit Kumar, Sateesh Kavuri, Paulo Zanoni, dri-devel

From: Shobhit Kumar <shobhit.kumar@intel.com>

SDP header and SDP VSC header as per eDP 1.3 spec, section 3.5,
chapter "PSR Secondary Data Package Support".

v2: Modified and corrected the structures to be more in line for
kernel coding guidelines and rebased the code on Paulo's DP patchset
v3: removing unecessary identation at DP_RECEIVER_CAP_SIZE
v4: moving them to include/drm/drm_dp_helper.h and also already
    icluding EDP_PSR_RECEIVER_CAP_SIZE to add everything needed
    for PSR at once at drm_dp_helper.h
v5: Fix SDP VSC header and identation by (Paulo Zanoni) and
    remove i915 from title (Daniel Vetter)
v6: Fix spec version and move comments from code to commit message
    since numbers might change in the future (by Paulo Zanoni).

CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Sateesh Kavuri <sateesh.kavuri@intel.com>
Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 include/drm/drm_dp_helper.h | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index e8e1417..ae8dbfb 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -342,13 +342,42 @@ u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE],
 u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
 					  int lane);
 
-#define DP_RECEIVER_CAP_SIZE	0xf
+#define DP_RECEIVER_CAP_SIZE		0xf
+#define EDP_PSR_RECEIVER_CAP_SIZE	2
+
 void drm_dp_link_train_clock_recovery_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]);
 void drm_dp_link_train_channel_eq_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]);
 
 u8 drm_dp_link_rate_to_bw_code(int link_rate);
 int drm_dp_bw_code_to_link_rate(u8 link_bw);
 
+struct edp_sdp_header {
+	u8 HB0; /* Secondary Data Packet ID */
+	u8 HB1; /* Secondary Data Packet Type */
+	u8 HB2; /* 7:5 reserved, 4:0 revision number */
+	u8 HB3; /* 7:5 reserved, 4:0 number of valid data bytes */
+} __packed;
+
+#define EDP_SDP_HEADER_REVISION_MASK		0x1F
+#define EDP_SDP_HEADER_VALID_PAYLOAD_BYTES	0x1F
+
+struct edp_vsc_psr {
+	struct edp_sdp_header sdp_header;
+	u8 DB0; /* Stereo Interface */
+	u8 DB1; /* 0 - PSR State; 1 - Update RFB; 2 - CRC Valid */
+	u8 DB2; /* CRC value bits 7:0 of the R or Cr component */
+	u8 DB3; /* CRC value bits 15:8 of the R or Cr component */
+	u8 DB4; /* CRC value bits 7:0 of the G or Y component */
+	u8 DB5; /* CRC value bits 15:8 of the G or Y component */
+	u8 DB6; /* CRC value bits 7:0 of the B or Cb component */
+	u8 DB7; /* CRC value bits 15:8 of the B or Cb component */
+	u8 DB8_31[24]; /* Reserved */
+} __packed;
+
+#define EDP_VSC_PSR_STATE_ACTIVE	(1<<0)
+#define EDP_VSC_PSR_UPDATE_RFB		(1<<1)
+#define EDP_VSC_PSR_CRC_VALUES_VALID	(1<<2)
+
 static inline int
 drm_dp_max_link_rate(u8 dpcd[DP_RECEIVER_CAP_SIZE])
 {
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 02/11] drm/i915: Read the EDP DPCD and PSR Capability
  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 ` 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
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: Shobhit Kumar, dri-devel

From: Shobhit Kumar <shobhit.kumar@intel.com>

v2: reuse of just created is_edp_psr and put it at right place.
v3: move is_edp_psr above intel_edp_disable

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 13 +++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 24a44ed..709e9d9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1342,6 +1342,12 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
 	pipe_config->adjusted_mode.flags |= flags;
 }
 
+static bool is_edp_psr(struct intel_dp *intel_dp)
+{
+	return (is_edp(intel_dp) &&
+		(intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED));
+}
+
 static void intel_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -2255,6 +2261,13 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] == 0)
 		return false; /* DPCD not present */
 
+	/* Check if the panel supports PSR */
+	memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
+	intel_dp_aux_native_read_retry(intel_dp, DP_PSR_SUPPORT,
+				       intel_dp->psr_dpcd,
+				       sizeof(intel_dp->psr_dpcd));
+	if (is_edp_psr(intel_dp))
+		DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
 	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
 	      DP_DWN_STRM_PORT_PRESENT))
 		return true; /* native DP sink */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c5b463c..9b264ee 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -486,6 +486,7 @@ struct intel_dp {
 	uint8_t link_bw;
 	uint8_t lane_count;
 	uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
+	uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
 	uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
 	struct i2c_adapter adapter;
 	struct i2c_algo_dp_aux_data algo;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 03/11] drm/i915: split aux_clock_divider logic in a separated function for reuse.
  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-26 21:55 ` Rodrigo Vivi
  2013-06-26 21:55 ` [PATCH 04/11] drm/i915: Enable/Disable PSR Rodrigo Vivi
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Prep patch for reuse aux_clock_divider with EDP_PSR_AUX_CTL setup.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 58 +++++++++++++++++++++++------------------
 1 file changed, 33 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 709e9d9..5cd276b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -271,29 +271,12 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
 	return status;
 }
 
-static int
-intel_dp_aux_ch(struct intel_dp *intel_dp,
-		uint8_t *send, int send_bytes,
-		uint8_t *recv, int recv_size)
+static uint32_t get_aux_clock_divider(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg;
-	uint32_t ch_data = ch_ctl + 4;
-	int i, ret, recv_bytes;
-	uint32_t status;
-	uint32_t aux_clock_divider;
-	int try, precharge;
-	bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev);
 
-	/* dp aux is extremely sensitive to irq latency, hence request the
-	 * lowest possible wakeup latency and so prevent the cpu from going into
-	 * deep sleep states.
-	 */
-	pm_qos_update_request(&dev_priv->pm_qos, 0);
-
-	intel_dp_check_edp(intel_dp);
 	/* The clock divider is based off the hrawclk,
 	 * and would like to run at 2MHz. So, take the
 	 * hrawclk value and divide by 2 and use that
@@ -302,23 +285,48 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	 * clock divider.
 	 */
 	if (IS_VALLEYVIEW(dev)) {
-		aux_clock_divider = 100;
+		return 100;
 	} else if (intel_dig_port->port == PORT_A) {
 		if (HAS_DDI(dev))
-			aux_clock_divider = DIV_ROUND_CLOSEST(
+			return DIV_ROUND_CLOSEST(
 				intel_ddi_get_cdclk_freq(dev_priv), 2000);
 		else if (IS_GEN6(dev) || IS_GEN7(dev))
-			aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
+			return 200; /* SNB & IVB eDP input clock at 400Mhz */
 		else
-			aux_clock_divider = 225; /* eDP input clock at 450Mhz */
+			return 225; /* eDP input clock at 450Mhz */
 	} else if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
 		/* Workaround for non-ULT HSW */
-		aux_clock_divider = 74;
+		return 74;
 	} else if (HAS_PCH_SPLIT(dev)) {
-		aux_clock_divider = DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
+		return DIV_ROUND_UP(intel_pch_rawclk(dev), 2);
 	} else {
-		aux_clock_divider = intel_hrawclk(dev) / 2;
+		return intel_hrawclk(dev) / 2;
 	}
+}
+
+static int
+intel_dp_aux_ch(struct intel_dp *intel_dp,
+		uint8_t *send, int send_bytes,
+		uint8_t *recv, int recv_size)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t ch_ctl = intel_dp->aux_ch_ctl_reg;
+	uint32_t ch_data = ch_ctl + 4;
+	int i, ret, recv_bytes;
+	uint32_t status;
+	uint32_t aux_clock_divider = get_aux_clock_divider(intel_dp);
+	int try, precharge;
+	bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev);
+
+	/* dp aux is extremely sensitive to irq latency, hence request the
+	 * lowest possible wakeup latency and so prevent the cpu from going into
+	 * deep sleep states.
+	 */
+	pm_qos_update_request(&dev_priv->pm_qos, 0);
+
+	intel_dp_check_edp(intel_dp);
 
 	if (IS_GEN6(dev))
 		precharge = 3;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 04/11] drm/i915: Enable/Disable PSR
  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-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
  2013-06-28 17:16   ` [PATCH] " Rodrigo Vivi
  2013-06-26 21:55 ` [PATCH 05/11] drm/i915: Added debugfs support for PSR Status Rodrigo Vivi
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

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

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 05/11] drm/i915: Added debugfs support for PSR Status
  2013-06-26 21:55 [PATCH 01/11] drm: Added SDP and VSC structures for handling PSR for eDP Rodrigo Vivi
                   ` (2 preceding siblings ...)
  2013-06-26 21:55 ` [PATCH 04/11] drm/i915: Enable/Disable PSR Rodrigo Vivi
@ 2013-06-26 21:55 ` Rodrigo Vivi
  2013-06-28 17:29   ` [PATCH] " Rodrigo Vivi
  2013-06-26 21:55 ` [PATCH 06/11] drm/i915: Match all PSR mode entry conditions before enabling it Rodrigo Vivi
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni, dri-devel

Adding support for PSR Status, PSR entry counter and performance counters.
Heavily based on initial work from Shobhit.

v2: Fix PSR Status Link bits by Paulo Zanoni.

CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
Credits-by: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 90 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h     | 24 ++++++++++
 2 files changed, 114 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a188624..b81adf7 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1877,6 +1877,95 @@ static int i915_dpio_info(struct seq_file *m, void *data)
 	return 0;
 }
 
+static int i915_edp_psr_status(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 psrctl, psrstat, psrperf;
+
+	psrctl = I915_READ(EDP_PSR_CTL);
+	seq_printf(m, "PSR Enabled: %s\n",
+		   yesno(psrctl & EDP_PSR_ENABLE));
+
+	psrstat = I915_READ(EDP_PSR_STATUS_CTL);
+
+	seq_printf(m, "PSR Current State: ");
+	switch (psrstat & EDP_PSR_STATUS_STATE_MASK) {
+	case EDP_PSR_STATUS_STATE_IDLE:
+		seq_printf(m, "Reset state\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDONACK:
+		seq_printf(m, "Wait for TG/Stream to send on frame of data after SRD conditions are met\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDENT:
+		seq_printf(m, "SRD entry\n");
+		break;
+	case EDP_PSR_STATUS_STATE_BUFOFF:
+		seq_printf(m, "Wait for buffer turn off\n");
+		break;
+	case EDP_PSR_STATUS_STATE_BUFON:
+			seq_printf(m, "Wait for buffer turn on\n");
+		break;
+	case EDP_PSR_STATUS_STATE_AUXACK:
+			seq_printf(m, "Wait for AUX to acknowledge on SRD exit\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDOFFACK:
+			seq_printf(m, "Wait for TG/Stream to acknowledge the SRD VDM exit\n");
+		break;
+	default:
+		seq_printf(m, "Unknown\n");
+		break;
+	}
+
+	seq_printf(m, "Link Status: ");
+	switch (psrstat & EDP_PSR_STATUS_LINK_MASK) {
+	case EDP_PSR_STATUS_LINK_FULL_OFF:
+		seq_printf(m, "Link is fully off\n");
+		break;
+	case EDP_PSR_STATUS_LINK_FULL_ON:
+		seq_printf(m, "Link is fully on\n");
+		break;
+	case EDP_PSR_STATUS_LINK_STANDBY:
+		seq_printf(m, "Link is in standby\n");
+		break;
+	default:
+		seq_printf(m, "Unknown\n");
+		break;
+	}
+
+	seq_printf(m, "PSR Entry Count: %u\n",
+		   psrstat >> EDP_PSR_STATUS_COUNT_SHIFT &
+		   EDP_PSR_STATUS_COUNT_MASK);
+
+	seq_printf(m, "Max Sleep Timer Counter: %u\n",
+		   psrstat >> EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT &
+		   EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK);
+
+	seq_printf(m, "Had AUX error: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_AUX_ERROR));
+
+	seq_printf(m, "Sending AUX: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_AUX_SENDING));
+
+	seq_printf(m, "Sending Idle: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_IDLE));
+
+	seq_printf(m, "Sending TP2 TP3: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_TP2_TP3));
+
+	seq_printf(m, "Sending TP1: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_TP1));
+
+	seq_printf(m, "Idle Count: %u\n",
+		   psrstat & EDP_PSR_STATUS_IDLE_MASK);
+
+	psrperf = (I915_READ(EDP_PSR_PERF_CNT)) & EDP_PSR_PERF_CNT_MASK;
+	seq_printf(m, "Performance Counter: %u\n", psrperf);
+
+	return 0;
+}
+
 static int
 i915_wedged_get(void *data, u64 *val)
 {
@@ -2306,6 +2395,7 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_swizzle_info", i915_swizzle_info, 0},
 	{"i915_ppgtt_info", i915_ppgtt_info, 0},
 	{"i915_dpio", i915_dpio_info, 0},
+	{"i915_edp_psr_status", i915_edp_psr_status, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index caf57d8..ab5d597 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1812,6 +1812,30 @@
 
 #define EDP_PSR_STATUS_CTL			0x64840
 #define   EDP_PSR_STATUS_STATE_MASK		(7<<29)
+#define   EDP_PSR_STATUS_STATE_IDLE		(0<<29)
+#define   EDP_PSR_STATUS_STATE_SRDONACK		(1<<29)
+#define   EDP_PSR_STATUS_STATE_SRDENT		(2<<29)
+#define   EDP_PSR_STATUS_STATE_BUFOFF		(3<<29)
+#define   EDP_PSR_STATUS_STATE_BUFON		(4<<29)
+#define   EDP_PSR_STATUS_STATE_AUXACK		(5<<29)
+#define   EDP_PSR_STATUS_STATE_SRDOFFACK	(6<<29)
+#define   EDP_PSR_STATUS_LINK_MASK		(3<<26)
+#define   EDP_PSR_STATUS_LINK_FULL_OFF		(0<<26)
+#define   EDP_PSR_STATUS_LINK_FULL_ON		(1<<26)
+#define   EDP_PSR_STATUS_LINK_STANDBY		(2<<26)
+#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT 	20
+#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK 	0x1f
+#define   EDP_PSR_STATUS_COUNT_SHIFT		16
+#define   EDP_PSR_STATUS_COUNT_MASK		0xf
+#define   EDP_PSR_STATUS_AUX_ERROR		(1<<15)
+#define   EDP_PSR_STATUS_AUX_SENDING		(1<<12)
+#define   EDP_PSR_STATUS_SENDING_IDLE		(1<<9)
+#define   EDP_PSR_STATUS_SENDING_TP2_TP3	(1<<8)
+#define   EDP_PSR_STATUS_SENDING_TP1		(1<<4)
+#define   EDP_PSR_STATUS_IDLE_MASK		0xf
+
+#define EDP_PSR_PERF_CNT		0x64844
+#define   EDP_PSR_PERF_CNT_MASK		0xffffff
 
 #define EDP_PSR_DEBUG_CTL		0x64860
 #define   EDP_PSR_DEBUG_MASK_LPSP	(1<<27)
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 06/11] drm/i915: Match all PSR mode entry conditions before enabling it.
  2013-06-26 21:55 [PATCH 01/11] drm: Added SDP and VSC structures for handling PSR for eDP Rodrigo Vivi
                   ` (3 preceding siblings ...)
  2013-06-26 21:55 ` [PATCH 05/11] drm/i915: Added debugfs support for PSR Status Rodrigo Vivi
@ 2013-06-26 21:55 ` Rodrigo Vivi
  2013-06-28 17:36   ` [PATCH] " Rodrigo Vivi
  2013-06-26 21:55 ` [PATCH 07/11] drm/i915: add update function to disable/enable-back PSR Rodrigo Vivi
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 39 ++++++++++++++++++---
 drivers/gpu/drm/i915/i915_drv.h     | 12 +++++++
 drivers/gpu/drm/i915/intel_dp.c     | 68 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 114 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index b81adf7..85b7dd2 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1882,11 +1882,42 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 psrctl, psrstat, psrperf;
+	u32 psrstat, psrperf;
 
-	psrctl = I915_READ(EDP_PSR_CTL);
-	seq_printf(m, "PSR Enabled: %s\n",
-		   yesno(psrctl & EDP_PSR_ENABLE));
+	if (I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
+		seq_printf(m, "PSR enabled\n");
+	} else {
+		seq_printf(m, "PSR disabled: ");
+		switch (dev_priv->no_psr_reason) {
+		case PSR_NO_SOURCE:
+			seq_printf(m, "not supported on this platform");
+			break;
+		case PSR_NO_SINK:
+			seq_printf(m, "not supported by panel");
+			break;
+		case PSR_CRTC_NOT_ACTIVE:
+			seq_printf(m, "crtc not active");
+			break;
+		case PSR_PWR_WELL_ENABLED:
+			seq_printf(m, "power well enabled");
+			break;
+		case PSR_NOT_TILED:
+			seq_printf(m, "not tiled");
+			break;
+		case PSR_SPRITE_ENABLED:
+			seq_printf(m, "sprite enabled");
+			break;
+		case PSR_INTERLACED_ENABLED:
+			seq_printf(m, "interlaced enabled");
+			break;
+		case PSR_HSW_NOT_DDIA:
+			seq_printf(m, "HSW ties PSR to DDI A (eDP)");
+			break;
+		default:
+			seq_printf(m, "unknown reason");
+		}
+		seq_printf(m, "\n");
+	}
 
 	psrstat = I915_READ(EDP_PSR_STATUS_CTL);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 56bd82b..f08c1d9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -543,6 +543,17 @@ enum no_fbc_reason {
 	FBC_CHIP_DEFAULT, /* disabled by default on this chip */
 };
 
+enum no_psr_reason {
+	PSR_NO_SOURCE, /* Not supported on platform */
+	PSR_NO_SINK, /* Not supported by panel */
+	PSR_CRTC_NOT_ACTIVE,
+	PSR_PWR_WELL_ENABLED,
+	PSR_NOT_TILED,
+	PSR_SPRITE_ENABLED,
+	PSR_INTERLACED_ENABLED,
+	PSR_HSW_NOT_DDIA,
+};
+
 enum intel_pch {
 	PCH_NONE = 0,	/* No PCH present */
 	PCH_IBX,	/* Ibexpeak PCH */
@@ -1146,6 +1157,7 @@ typedef struct drm_i915_private {
 	struct i915_power_well power_well;
 
 	enum no_fbc_reason no_fbc_reason;
+	enum no_psr_reason no_psr_reason;
 
 	struct drm_mm_node *compressed_fb;
 	struct drm_mm_node *compressed_llb;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 144f216..13b0155 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1471,11 +1471,77 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
 		   EDP_PSR_ENABLE);
 }
 
+static bool intel_edp_psr_match_conditions(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 drm_crtc *crtc = dig_port->base.base.crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
+	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
+
+	if (!IS_HASWELL(dev)) {
+		DRM_DEBUG_KMS("PSR not supported on this platform\n");
+		dev_priv->no_psr_reason = PSR_NO_SOURCE;
+		return false;
+	}
+
+	if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
+	    (enc_to_dig_port(&intel_encoder->base)->port != PORT_A)) {
+		DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
+		dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
+		return false;
+	}
+
+	if (!is_edp_psr(intel_dp)) {
+		DRM_DEBUG_KMS("PSR not supported by this panel\n");
+		dev_priv->no_psr_reason = PSR_NO_SINK;
+		return false;
+	}
+
+	if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
+		DRM_DEBUG_KMS("crtc not active for PSR\n");
+		dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
+		return false;
+	}
+
+	if ((I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE) |
+	    (I915_READ(HSW_PWR_WELL_KVMR) & HSW_PWR_WELL_ENABLE)) {
+		DRM_DEBUG_KMS("PSR condition failed: Power Well is Enabled\n");
+		dev_priv->no_psr_reason = PSR_PWR_WELL_ENABLED;
+		return false;
+	}
+
+	if (obj->tiling_mode != I915_TILING_X ||
+	    obj->fence_reg == I915_FENCE_REG_NONE) {
+		DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
+		dev_priv->no_psr_reason = PSR_NOT_TILED;
+		return false;
+	}
+
+	if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
+		DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
+		dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
+		return false;
+	}
+
+	if ((I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
+	     PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
+		DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
+		dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
+		return false;
+	}
+
+	return true;
+}
+
 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))
+	if (!intel_edp_psr_match_conditions(intel_dp) ||
+	    intel_edp_is_psr_enabled(dev))
 		return;
 
 	/* Enable PSR on the panel */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 07/11] drm/i915: add update function to disable/enable-back PSR
  2013-06-26 21:55 [PATCH 01/11] drm: Added SDP and VSC structures for handling PSR for eDP Rodrigo Vivi
                   ` (4 preceding siblings ...)
  2013-06-26 21:55 ` [PATCH 06/11] drm/i915: Match all PSR mode entry conditions before enabling it Rodrigo Vivi
@ 2013-06-26 21:55 ` Rodrigo Vivi
  2013-06-28 17:44   ` [PATCH] " Rodrigo Vivi
  2013-06-26 21:55 ` [PATCH 08/11] drm/intel: add enable_psr module option Rodrigo Vivi
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Required function to disable PSR when going to console mode.
But also can be used whenever PSR mode entry conditions changed.

v2: Add it before PSR Hook. Update function not really been called yet.
---
 drivers/gpu/drm/i915/intel_dp.c  | 37 ++++++++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 13b0155..91ba018 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1536,14 +1536,8 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
 	return true;
 }
 
-void intel_edp_psr_enable(struct intel_dp* intel_dp)
+void intel_edp_psr_do_enable(struct intel_dp* intel_dp)
 {
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-
-	if (!intel_edp_psr_match_conditions(intel_dp) ||
-	    intel_edp_is_psr_enabled(dev))
-		return;
-
 	/* Enable PSR on the panel */
 	intel_edp_psr_enable_sink(intel_dp);
 
@@ -1551,6 +1545,15 @@ void intel_edp_psr_enable(struct intel_dp* intel_dp)
 	intel_edp_psr_enable_source(intel_dp);
 }
 
+void intel_edp_psr_enable(struct intel_dp* intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+
+	if (intel_edp_psr_match_conditions(intel_dp) &&
+	    !intel_edp_is_psr_enabled(dev))
+		intel_edp_psr_do_enable(intel_dp);
+}
+
 void intel_edp_psr_disable(struct intel_dp* intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -1573,6 +1576,26 @@ void intel_edp_psr_disable(struct intel_dp* intel_dp)
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
+void intel_edp_psr_update(struct drm_device *dev)
+{
+	struct intel_encoder *encoder;
+	struct intel_dp *intel_dp = NULL;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
+		if (encoder->type == INTEL_OUTPUT_EDP) {
+			intel_dp = enc_to_intel_dp(&encoder->base);
+
+			if (!is_edp_psr(intel_dp))
+				return;
+
+			if (!intel_edp_psr_match_conditions(intel_dp))
+				intel_edp_psr_disable(intel_dp);
+			else
+				if (!intel_edp_is_psr_enabled(dev))
+					intel_edp_psr_do_enable(intel_dp);
+		}
+}
+
 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 f86d9c5..69224d2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -842,5 +842,6 @@ extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
 
 extern void intel_edp_psr_enable(struct intel_dp* intel_dp);
 extern void intel_edp_psr_disable(struct intel_dp* intel_dp);
+extern void intel_edp_psr_update(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 08/11] drm/intel: add enable_psr module option
  2013-06-26 21:55 [PATCH 01/11] drm: Added SDP and VSC structures for handling PSR for eDP Rodrigo Vivi
                   ` (5 preceding siblings ...)
  2013-06-26 21:55 ` [PATCH 07/11] drm/i915: add update function to disable/enable-back PSR Rodrigo Vivi
@ 2013-06-26 21:55 ` Rodrigo Vivi
  2013-06-28 17:47   ` [PATCH] " Rodrigo Vivi
  2013-06-26 21:55 ` [PATCH 09/11] drm/i915: Adding global I915_PARAM for PSR ACTIVE Rodrigo Vivi
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

PSR is enabled by default but can be disabled.

Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 3 +++
 drivers/gpu/drm/i915/i915_drv.c     | 4 ++++
 drivers/gpu/drm/i915/i915_drv.h     | 2 ++
 drivers/gpu/drm/i915/intel_dp.c     | 6 ++++++
 4 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 85b7dd2..8b235c5 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1895,6 +1895,9 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 		case PSR_NO_SINK:
 			seq_printf(m, "not supported by panel");
 			break;
+		case PSR_MODULE_PARAM:
+			seq_printf(m, "disabled by flag");
+			break;
 		case PSR_CRTC_NOT_ACTIVE:
 			seq_printf(m, "crtc not active");
 			break;
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 062cbda..7920c6f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -118,6 +118,10 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
 MODULE_PARM_DESC(i915_enable_ppgtt,
 		"Enable PPGTT (default: true)");
 
+int i915_enable_psr __read_mostly = 1;
+module_param_named(enable_psr, i915_enable_psr, int, 0600);
+MODULE_PARM_DESC(enable_psr, "Enable PSR (default: true)");
+
 unsigned int i915_preliminary_hw_support __read_mostly = 0;
 module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
 MODULE_PARM_DESC(preliminary_hw_support,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f08c1d9..dda992a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -546,6 +546,7 @@ enum no_fbc_reason {
 enum no_psr_reason {
 	PSR_NO_SOURCE, /* Not supported on platform */
 	PSR_NO_SINK, /* Not supported by panel */
+	PSR_MODULE_PARAM,
 	PSR_CRTC_NOT_ACTIVE,
 	PSR_PWR_WELL_ENABLED,
 	PSR_NOT_TILED,
@@ -1555,6 +1556,7 @@ extern int i915_enable_rc6 __read_mostly;
 extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
+extern int i915_enable_psr __read_mostly;
 extern unsigned int i915_preliminary_hw_support __read_mostly;
 extern int i915_disable_power_well __read_mostly;
 extern int i915_enable_ips __read_mostly;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 91ba018..91d3bd6 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1500,6 +1500,12 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
 		return false;
 	}
 
+	if (!i915_enable_psr) {
+		DRM_DEBUG_KMS("PSR disable by flag\n");
+		dev_priv->no_psr_reason = PSR_MODULE_PARAM;
+		return false;
+	}
+
 	if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
 		DRM_DEBUG_KMS("crtc not active for PSR\n");
 		dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 09/11] drm/i915: Adding global I915_PARAM for PSR ACTIVE.
  2013-06-26 21:55 [PATCH 01/11] drm: Added SDP and VSC structures for handling PSR for eDP Rodrigo Vivi
                   ` (6 preceding siblings ...)
  2013-06-26 21:55 ` [PATCH 08/11] drm/intel: add enable_psr module option Rodrigo Vivi
@ 2013-06-26 21:55 ` Rodrigo Vivi
  2013-06-26 22:18   ` Chris Wilson
  2013-06-26 21:55 ` [PATCH 10/11] drm/i915: Add functions to force psr exit Rodrigo Vivi
  2013-06-26 21:55 ` [PATCH 11/11] drm/i915: Hook PSR functionality Rodrigo Vivi
  9 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

This global value allows userspace know when PSR is enabled and active,
i.e. in SRD entry state.
This will allow userspace emit more busy_ioctl when doing directly copy_area
operations through scanout allowing forced psr exit.

Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_dma.c | 3 +++
 include/uapi/drm/i915_drm.h     | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index adb319b..de20c4a 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1000,6 +1000,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_EXEC_HANDLE_LUT:
 		value = 1;
 		break;
+	case I915_PARAM_PSR_ACTIVE:
+		value = I915_READ(EDP_PSR_STATUS_CTL) & EDP_PSR_STATUS_STATE_SRDENT;
+		break;
 	default:
 		DRM_DEBUG("Unknown parameter %d\n", param->param);
 		return -EINVAL;
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 923ed7f..191a7fc 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -310,6 +310,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_PINNED_BATCHES	 24
 #define I915_PARAM_HAS_EXEC_NO_RELOC	 25
 #define I915_PARAM_HAS_EXEC_HANDLE_LUT   26
+#define I915_PARAM_PSR_ACTIVE		 27
 
 typedef struct drm_i915_getparam {
 	int param;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 10/11] drm/i915: Add functions to force psr exit
  2013-06-26 21:55 [PATCH 01/11] drm: Added SDP and VSC structures for handling PSR for eDP Rodrigo Vivi
                   ` (7 preceding siblings ...)
  2013-06-26 21:55 ` [PATCH 09/11] drm/i915: Adding global I915_PARAM for PSR ACTIVE Rodrigo Vivi
@ 2013-06-26 21:55 ` Rodrigo Vivi
  2013-06-27 13:03   ` [PATCH] " Rodrigo Vivi
  2013-06-26 21:55 ` [PATCH 11/11] drm/i915: Hook PSR functionality Rodrigo Vivi
  9 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

PSR tracking engine in HSW doesn't detect automagically some directly copy area
operations through scanout so we will have to kick it manually and
reschedule it to come back to normal operation as soon as possible.

v2: Before PSR Hook. Don't force it when busy yet.

Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_dp.c  | 59 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |  4 +++
 3 files changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ab5d597..cea646b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1838,6 +1838,7 @@
 #define   EDP_PSR_PERF_CNT_MASK		0xffffff
 
 #define EDP_PSR_DEBUG_CTL		0x64860
+#define   EDP_PSR_DEBUG_FORCE_EXIT	(3<<30)
 #define   EDP_PSR_DEBUG_MASK_LPSP	(1<<27)
 #define   EDP_PSR_DEBUG_MASK_MEMUP	(1<<26)
 #define   EDP_PSR_DEBUG_MASK_HPD	(1<<25)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 91d3bd6..9986484 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1366,6 +1366,48 @@ static bool intel_edp_is_psr_enabled(struct drm_device *dev)
 	return I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
 }
 
+static void intel_edp_psr_delayed_normal_work(struct work_struct *__work)
+{
+	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
+						 struct intel_dp,
+						 edp_psr_delayed_normal_work);
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&intel_dp->psr_exit_mutex);
+	I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) &
+		   ~EDP_PSR_DEBUG_FORCE_EXIT);
+	mutex_unlock(&intel_dp->psr_exit_mutex);
+}
+
+void intel_edp_psr_force_exit(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *encoder;
+	struct intel_dp *intel_dp = NULL;
+
+	if (!intel_edp_is_psr_enabled(dev))
+		return;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
+		if (encoder->type == INTEL_OUTPUT_EDP)
+			intel_dp = enc_to_intel_dp(&encoder->base);
+
+	if (!intel_dp)
+		return;
+
+	if (WARN_ON(!intel_dp->psr_setup_done))
+		return;
+
+	mutex_lock(&intel_dp->psr_exit_mutex);
+	I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) |
+		   EDP_PSR_DEBUG_FORCE_EXIT);
+	mutex_unlock(&intel_dp->psr_exit_mutex);
+
+	schedule_delayed_work(&intel_dp->edp_psr_delayed_normal_work,
+			      msecs_to_jiffies(100));
+}
+
 void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
 			     struct edp_vsc_psr *vsc_psr)
 {
@@ -1400,6 +1442,18 @@ void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
 	POSTING_READ(ctl_reg);
 }
 
+static void intel_edp_psr_setup(struct intel_dp *intel_dp)
+{
+	if (intel_dp->psr_setup_done)
+		return;
+
+	INIT_DELAYED_WORK(&intel_dp->edp_psr_delayed_normal_work,
+			  intel_edp_psr_delayed_normal_work);
+	mutex_init(&intel_dp->psr_exit_mutex);
+
+	intel_dp->psr_setup_done = true;
+}
+
 static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -1544,6 +1598,9 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
 
 void intel_edp_psr_do_enable(struct intel_dp* intel_dp)
 {
+	/* Setup PSR once */
+	intel_edp_psr_setup(intel_dp);
+
 	/* Enable PSR on the panel */
 	intel_edp_psr_enable_sink(intel_dp);
 
@@ -3413,6 +3470,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
 	     error, port_name(port));
 
+	intel_dp->psr_setup_done = false;
+
 	if (!intel_edp_init_connector(intel_dp, intel_connector)) {
 		i2c_del_adapter(&intel_dp->adapter);
 		if (is_edp(intel_dp)) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 69224d2..b3d5a97 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -497,6 +497,9 @@ struct intel_dp {
 	int backlight_on_delay;
 	int backlight_off_delay;
 	struct delayed_work panel_vdd_work;
+	struct delayed_work edp_psr_delayed_normal_work;
+	struct mutex psr_exit_mutex;
+	bool psr_setup_done;
 	bool want_panel_vdd;
 	struct intel_connector *attached_connector;
 };
@@ -843,5 +846,6 @@ extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
 extern void intel_edp_psr_enable(struct intel_dp* intel_dp);
 extern void intel_edp_psr_disable(struct intel_dp* intel_dp);
 extern void intel_edp_psr_update(struct drm_device *dev);
+extern void intel_edp_psr_force_exit(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 11/11] drm/i915: Hook PSR functionality
  2013-06-26 21:55 [PATCH 01/11] drm: Added SDP and VSC structures for handling PSR for eDP Rodrigo Vivi
                   ` (8 preceding siblings ...)
  2013-06-26 21:55 ` [PATCH 10/11] drm/i915: Add functions to force psr exit Rodrigo Vivi
@ 2013-06-26 21:55 ` Rodrigo Vivi
  2013-06-28 21:00   ` Paulo Zanoni
  9 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 21:55 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni, dri-devel

PSR must be enabled after transcoder and port are running.
And it is only available for HSW.

v2: move enable/disable to intel_ddi
v3: The spec suggests PSR should be disabled even before backlight (by pzanoni)
v4: also disabling and enabling whenever panel is disabled/enabled.
v5: make it last patch to avoid breaking whenever bisecting. So calling for
    update and force exit came to this patch along with enable/disable calls.

CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_gem.c      | 2 ++
 drivers/gpu/drm/i915/intel_ddi.c     | 2 ++
 drivers/gpu/drm/i915/intel_display.c | 1 +
 drivers/gpu/drm/i915/intel_dp.c      | 2 ++
 4 files changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index c68b90f..f2e135b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3786,6 +3786,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 		goto unlock;
 	}
 
+	intel_edp_psr_force_exit(dev);
+
 	/* Count all active objects as busy, even if they are currently not used
 	 * by the gpu. Users of this interface expect objects to eventually
 	 * become non-busy without any further actions, therefore emit any
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 324211a..4211925 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1117,6 +1117,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
 			intel_dp_stop_link_train(intel_dp);
 
 		ironlake_edp_backlight_on(intel_dp);
+		intel_edp_psr_enable(intel_dp);
 	}
 
 	if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
@@ -1147,6 +1148,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
 	if (type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
+		intel_edp_psr_disable(intel_dp);
 		ironlake_edp_backlight_off(intel_dp);
 	}
 }
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6fafa43..5bbfed0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2236,6 +2236,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 	}
 
 	intel_update_fbc(dev);
+	intel_edp_psr_update(dev);
 	mutex_unlock(&dev->struct_mutex);
 
 	intel_crtc_update_sarea_pos(crtc, x, y);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9986484..019b1ff 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1668,6 +1668,7 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 	/* Make sure the panel is off before trying to change the mode. But also
 	 * ensure that we have vdd while we switch off the panel. */
 	ironlake_edp_panel_vdd_on(intel_dp);
+	intel_edp_psr_disable(intel_dp);
 	ironlake_edp_backlight_off(intel_dp);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	ironlake_edp_panel_off(intel_dp);
@@ -1708,6 +1709,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	intel_dp_complete_link_train(intel_dp);
 	intel_dp_stop_link_train(intel_dp);
 	ironlake_edp_backlight_on(intel_dp);
+	intel_edp_psr_enable(intel_dp);
 
 	if (IS_VALLEYVIEW(dev)) {
 		struct intel_digital_port *dport =
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH 09/11] drm/i915: Adding global I915_PARAM for PSR ACTIVE.
  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
  0 siblings, 1 reply; 53+ messages in thread
From: Chris Wilson @ 2013-06-26 22:18 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, dri-devel

On Wed, Jun 26, 2013 at 06:55:20PM -0300, Rodrigo Vivi wrote:
> This global value allows userspace know when PSR is enabled and active,
> i.e. in SRD entry state.
> This will allow userspace emit more busy_ioctl when doing directly copy_area
> operations through scanout allowing forced psr exit.

I don't want PSR_ACTIVE, but PSR_ENABLED. I'd rather check once after
updating the mode configuration instead of everytime the ddx is about to
sleep.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Adding global I915_PARAM for PSR ENABLED.
  2013-06-26 22:18   ` Chris Wilson
@ 2013-06-26 23:23     ` Rodrigo Vivi
  2013-06-27 12:51       ` Rodrigo Vivi
  0 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-26 23:23 UTC (permalink / raw)
  To: intel-gfx

This global value allows userspace know when PSR is enabled.

This will allow userspace emit more busy_ioctl when doing directly copy_area
operations through scanout allowing forced psr exit.

v2: Check for PSR enabled instead of active. (by Chris Wilson)

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_dma.c | 4 ++++
 include/uapi/drm/i915_drm.h     | 1 +
 2 files changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index adb319b..f924388 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1000,6 +1000,10 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_EXEC_HANDLE_LUT:
 		value = 1;
 		break;
+	case I915_PARAM_PSR_ENABLED:
+		value = IS_HASWELL(dev) &&
+			I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
+		break;
 	default:
 		DRM_DEBUG("Unknown parameter %d\n", param->param);
 		return -EINVAL;
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 923ed7f..a5db73b 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -310,6 +310,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_PINNED_BATCHES	 24
 #define I915_PARAM_HAS_EXEC_NO_RELOC	 25
 #define I915_PARAM_HAS_EXEC_HANDLE_LUT   26
+#define I915_PARAM_PSR_ENABLED		 27
 
 typedef struct drm_i915_getparam {
 	int param;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Adding global I915_PARAM for PSR ENABLED.
  2013-06-26 23:23     ` [PATCH] drm/i915: Adding global I915_PARAM for PSR ENABLED Rodrigo Vivi
@ 2013-06-27 12:51       ` Rodrigo Vivi
  0 siblings, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-27 12:51 UTC (permalink / raw)
  To: intel-gfx

This global value allows userspace know when PSR is enabled.

This will allow userspace emit more busy_ioctl when doing directly copy_area
operations through scanout allowing forced psr exit.

v2: Check for PSR enabled instead of active. (by Chris Wilson)
v3: Use existing intel_edp_is_psr_enabled function.

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_dma.c  | 3 +++
 drivers/gpu/drm/i915/intel_dp.c  | 2 +-
 drivers/gpu/drm/i915/intel_drv.h | 1 +
 include/uapi/drm/i915_drm.h      | 1 +
 4 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index adb319b..fcff947 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1000,6 +1000,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_EXEC_HANDLE_LUT:
 		value = 1;
 		break;
+	case I915_PARAM_PSR_ENABLED:
+		value = intel_edp_is_psr_enabled(dev);
+		break;
 	default:
 		DRM_DEBUG("Unknown parameter %d\n", param->param);
 		return -EINVAL;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 91d3bd6..a5c9567 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1356,7 +1356,7 @@ 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)
+bool intel_edp_is_psr_enabled(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 69224d2..4369324 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -843,5 +843,6 @@ extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
 extern void intel_edp_psr_enable(struct intel_dp* intel_dp);
 extern void intel_edp_psr_disable(struct intel_dp* intel_dp);
 extern void intel_edp_psr_update(struct drm_device *dev);
+extern bool intel_edp_is_psr_enabled(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 923ed7f..a5db73b 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -310,6 +310,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_PINNED_BATCHES	 24
 #define I915_PARAM_HAS_EXEC_NO_RELOC	 25
 #define I915_PARAM_HAS_EXEC_HANDLE_LUT   26
+#define I915_PARAM_PSR_ENABLED		 27
 
 typedef struct drm_i915_getparam {
 	int param;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Add functions to force psr exit
  2013-06-26 21:55 ` [PATCH 10/11] drm/i915: Add functions to force psr exit Rodrigo Vivi
@ 2013-06-27 13:03   ` Rodrigo Vivi
  2013-06-28 17:52     ` Rodrigo Vivi
  0 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-27 13:03 UTC (permalink / raw)
  To: intel-gfx

PSR tracking engine in HSW doesn't detect automagically some directly copy area
operations through scanout so we will have to kick it manually and
reschedule it to come back to normal operation as soon as possible.

v2: Before PSR Hook. Don't force it when busy yet.
v3: Solved small conflict.

Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_dp.c  | 59 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |  4 +++
 3 files changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ab5d597..cea646b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1838,6 +1838,7 @@
 #define   EDP_PSR_PERF_CNT_MASK		0xffffff
 
 #define EDP_PSR_DEBUG_CTL		0x64860
+#define   EDP_PSR_DEBUG_FORCE_EXIT	(3<<30)
 #define   EDP_PSR_DEBUG_MASK_LPSP	(1<<27)
 #define   EDP_PSR_DEBUG_MASK_MEMUP	(1<<26)
 #define   EDP_PSR_DEBUG_MASK_HPD	(1<<25)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a5c9567..aa6812c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1366,6 +1366,48 @@ bool intel_edp_is_psr_enabled(struct drm_device *dev)
 	return I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
 }
 
+static void intel_edp_psr_delayed_normal_work(struct work_struct *__work)
+{
+	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
+						 struct intel_dp,
+						 edp_psr_delayed_normal_work);
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&intel_dp->psr_exit_mutex);
+	I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) &
+		   ~EDP_PSR_DEBUG_FORCE_EXIT);
+	mutex_unlock(&intel_dp->psr_exit_mutex);
+}
+
+void intel_edp_psr_force_exit(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *encoder;
+	struct intel_dp *intel_dp = NULL;
+
+	if (!intel_edp_is_psr_enabled(dev))
+		return;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
+		if (encoder->type == INTEL_OUTPUT_EDP)
+			intel_dp = enc_to_intel_dp(&encoder->base);
+
+	if (!intel_dp)
+		return;
+
+	if (WARN_ON(!intel_dp->psr_setup_done))
+		return;
+
+	mutex_lock(&intel_dp->psr_exit_mutex);
+	I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) |
+		   EDP_PSR_DEBUG_FORCE_EXIT);
+	mutex_unlock(&intel_dp->psr_exit_mutex);
+
+	schedule_delayed_work(&intel_dp->edp_psr_delayed_normal_work,
+			      msecs_to_jiffies(100));
+}
+
 void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
 			     struct edp_vsc_psr *vsc_psr)
 {
@@ -1400,6 +1442,18 @@ void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
 	POSTING_READ(ctl_reg);
 }
 
+static void intel_edp_psr_setup(struct intel_dp *intel_dp)
+{
+	if (intel_dp->psr_setup_done)
+		return;
+
+	INIT_DELAYED_WORK(&intel_dp->edp_psr_delayed_normal_work,
+			  intel_edp_psr_delayed_normal_work);
+	mutex_init(&intel_dp->psr_exit_mutex);
+
+	intel_dp->psr_setup_done = true;
+}
+
 static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -1544,6 +1598,9 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
 
 void intel_edp_psr_do_enable(struct intel_dp* intel_dp)
 {
+	/* Setup PSR once */
+	intel_edp_psr_setup(intel_dp);
+
 	/* Enable PSR on the panel */
 	intel_edp_psr_enable_sink(intel_dp);
 
@@ -3413,6 +3470,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
 	     error, port_name(port));
 
+	intel_dp->psr_setup_done = false;
+
 	if (!intel_edp_init_connector(intel_dp, intel_connector)) {
 		i2c_del_adapter(&intel_dp->adapter);
 		if (is_edp(intel_dp)) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4369324..11ae3ea 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -497,6 +497,9 @@ struct intel_dp {
 	int backlight_on_delay;
 	int backlight_off_delay;
 	struct delayed_work panel_vdd_work;
+	struct delayed_work edp_psr_delayed_normal_work;
+	struct mutex psr_exit_mutex;
+	bool psr_setup_done;
 	bool want_panel_vdd;
 	struct intel_connector *attached_connector;
 };
@@ -844,5 +847,6 @@ extern void intel_edp_psr_enable(struct intel_dp* intel_dp);
 extern void intel_edp_psr_disable(struct intel_dp* intel_dp);
 extern void intel_edp_psr_update(struct drm_device *dev);
 extern bool intel_edp_is_psr_enabled(struct drm_device *dev);
+extern void intel_edp_psr_force_exit(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Read the EDP DPCD and PSR Capability
  2013-06-26 21:55 ` [PATCH 02/11] drm/i915: Read the EDP DPCD and PSR Capability Rodrigo Vivi
@ 2013-06-28 16:57   ` Rodrigo Vivi
  0 siblings, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-28 16:57 UTC (permalink / raw)
  To: intel-gfx

From: Shobhit Kumar <shobhit.kumar@intel.com>

v2: reuse of just created is_edp_psr and put it at right place.
v3: move is_edp_psr above intel_edp_disable
v4: remove parentheses. Noticed by Paulo.

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 13 +++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 24a44ed..d961ed5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1342,6 +1342,12 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
 	pipe_config->adjusted_mode.flags |= flags;
 }
 
+static bool is_edp_psr(struct intel_dp *intel_dp)
+{
+	return is_edp(intel_dp) &&
+		intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED;
+}
+
 static void intel_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -2255,6 +2261,13 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] == 0)
 		return false; /* DPCD not present */
 
+	/* Check if the panel supports PSR */
+	memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
+	intel_dp_aux_native_read_retry(intel_dp, DP_PSR_SUPPORT,
+				       intel_dp->psr_dpcd,
+				       sizeof(intel_dp->psr_dpcd));
+	if (is_edp_psr(intel_dp))
+		DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
 	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
 	      DP_DWN_STRM_PORT_PRESENT))
 		return true; /* native DP sink */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c5b463c..9b264ee 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -486,6 +486,7 @@ struct intel_dp {
 	uint8_t link_bw;
 	uint8_t lane_count;
 	uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
+	uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
 	uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
 	struct i2c_adapter adapter;
 	struct i2c_algo_dp_aux_data algo;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Enable/Disable PSR
  2013-06-26 21:55 ` [PATCH 04/11] drm/i915: Enable/Disable PSR Rodrigo Vivi
@ 2013-06-28 17:16   ` Rodrigo Vivi
  2013-06-28 19:31     ` Paulo Zanoni
  0 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-28 17:16 UTC (permalink / raw)
  To: intel-gfx

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.
v4: Fix identation and other style issues raised by checkpatch (by Paulo).

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 dca8fa6..c10be94 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..ff09c4c 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

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Added debugfs support for PSR Status
  2013-06-26 21:55 ` [PATCH 05/11] drm/i915: Added debugfs support for PSR Status Rodrigo Vivi
@ 2013-06-28 17:29   ` Rodrigo Vivi
  2013-06-28 20:08     ` Paulo Zanoni
  0 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-28 17:29 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

Adding support for PSR Status, PSR entry counter and performance counters.
Heavily based on initial work from Shobhit.

v2: Fix PSR Status Link bits by Paulo Zanoni.
v3: Prefer seq_puts to seq_printf by Paulo Zanoni.

CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
Credits-by: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 90 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h     | 24 ++++++++++
 2 files changed, 114 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a188624..67c777f 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1877,6 +1877,95 @@ static int i915_dpio_info(struct seq_file *m, void *data)
 	return 0;
 }
 
+static int i915_edp_psr_status(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 psrctl, psrstat, psrperf;
+
+	psrctl = I915_READ(EDP_PSR_CTL);
+	seq_printf(m, "PSR Enabled: %s\n",
+		   yesno(psrctl & EDP_PSR_ENABLE));
+
+	psrstat = I915_READ(EDP_PSR_STATUS_CTL);
+
+	seq_puts(m, "PSR Current State: ");
+	switch (psrstat & EDP_PSR_STATUS_STATE_MASK) {
+	case EDP_PSR_STATUS_STATE_IDLE:
+		seq_puts(m, "Reset state\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDONACK:
+		seq_puts(m, "Wait for TG/Stream to send on frame of data after SRD conditions are met\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDENT:
+		seq_puts(m, "SRD entry\n");
+		break;
+	case EDP_PSR_STATUS_STATE_BUFOFF:
+		seq_puts(m, "Wait for buffer turn off\n");
+		break;
+	case EDP_PSR_STATUS_STATE_BUFON:
+			seq_puts(m, "Wait for buffer turn on\n");
+		break;
+	case EDP_PSR_STATUS_STATE_AUXACK:
+			seq_puts(m, "Wait for AUX to acknowledge on SRD exit\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDOFFACK:
+			seq_puts(m, "Wait for TG/Stream to acknowledge the SRD VDM exit\n");
+		break;
+	default:
+		seq_puts(m, "Unknown\n");
+		break;
+	}
+
+	seq_puts(m, "Link Status: ");
+	switch (psrstat & EDP_PSR_STATUS_LINK_MASK) {
+	case EDP_PSR_STATUS_LINK_FULL_OFF:
+		seq_puts(m, "Link is fully off\n");
+		break;
+	case EDP_PSR_STATUS_LINK_FULL_ON:
+		seq_puts(m, "Link is fully on\n");
+		break;
+	case EDP_PSR_STATUS_LINK_STANDBY:
+		seq_puts(m, "Link is in standby\n");
+		break;
+	default:
+		seq_puts(m, "Unknown\n");
+		break;
+	}
+
+	seq_printf(m, "PSR Entry Count: %u\n",
+		   psrstat >> EDP_PSR_STATUS_COUNT_SHIFT &
+		   EDP_PSR_STATUS_COUNT_MASK);
+
+	seq_printf(m, "Max Sleep Timer Counter: %u\n",
+		   psrstat >> EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT &
+		   EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK);
+
+	seq_printf(m, "Had AUX error: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_AUX_ERROR));
+
+	seq_printf(m, "Sending AUX: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_AUX_SENDING));
+
+	seq_printf(m, "Sending Idle: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_IDLE));
+
+	seq_printf(m, "Sending TP2 TP3: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_TP2_TP3));
+
+	seq_printf(m, "Sending TP1: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_TP1));
+
+	seq_printf(m, "Idle Count: %u\n",
+		   psrstat & EDP_PSR_STATUS_IDLE_MASK);
+
+	psrperf = (I915_READ(EDP_PSR_PERF_CNT)) & EDP_PSR_PERF_CNT_MASK;
+	seq_printf(m, "Performance Counter: %u\n", psrperf);
+
+	return 0;
+}
+
 static int
 i915_wedged_get(void *data, u64 *val)
 {
@@ -2306,6 +2395,7 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_swizzle_info", i915_swizzle_info, 0},
 	{"i915_ppgtt_info", i915_ppgtt_info, 0},
 	{"i915_dpio", i915_dpio_info, 0},
+	{"i915_edp_psr_status", i915_edp_psr_status, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index caf57d8..833cc97 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1812,6 +1812,30 @@
 
 #define EDP_PSR_STATUS_CTL			0x64840
 #define   EDP_PSR_STATUS_STATE_MASK		(7<<29)
+#define   EDP_PSR_STATUS_STATE_IDLE		(0<<29)
+#define   EDP_PSR_STATUS_STATE_SRDONACK		(1<<29)
+#define   EDP_PSR_STATUS_STATE_SRDENT		(2<<29)
+#define   EDP_PSR_STATUS_STATE_BUFOFF		(3<<29)
+#define   EDP_PSR_STATUS_STATE_BUFON		(4<<29)
+#define   EDP_PSR_STATUS_STATE_AUXACK		(5<<29)
+#define   EDP_PSR_STATUS_STATE_SRDOFFACK	(6<<29)
+#define   EDP_PSR_STATUS_LINK_MASK		(3<<26)
+#define   EDP_PSR_STATUS_LINK_FULL_OFF		(0<<26)
+#define   EDP_PSR_STATUS_LINK_FULL_ON		(1<<26)
+#define   EDP_PSR_STATUS_LINK_STANDBY		(2<<26)
+#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT	20
+#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK	0x1f
+#define   EDP_PSR_STATUS_COUNT_SHIFT		16
+#define   EDP_PSR_STATUS_COUNT_MASK		0xf
+#define   EDP_PSR_STATUS_AUX_ERROR		(1<<15)
+#define   EDP_PSR_STATUS_AUX_SENDING		(1<<12)
+#define   EDP_PSR_STATUS_SENDING_IDLE		(1<<9)
+#define   EDP_PSR_STATUS_SENDING_TP2_TP3	(1<<8)
+#define   EDP_PSR_STATUS_SENDING_TP1		(1<<4)
+#define   EDP_PSR_STATUS_IDLE_MASK		0xf
+
+#define EDP_PSR_PERF_CNT		0x64844
+#define   EDP_PSR_PERF_CNT_MASK		0xffffff
 
 #define EDP_PSR_DEBUG_CTL		0x64860
 #define   EDP_PSR_DEBUG_MASK_LPSP	(1<<27)
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Match all PSR mode entry conditions before enabling it.
  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   ` Rodrigo Vivi
  2013-06-28 20:46     ` Paulo Zanoni
  0 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-28 17:36 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

v2: Prefer seq_puts to seq_printf by Paulo Zanoni.

Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 39 ++++++++++++++++++---
 drivers/gpu/drm/i915/i915_drv.h     | 12 +++++++
 drivers/gpu/drm/i915/intel_dp.c     | 68 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 114 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 67c777f..95b27ac 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1882,11 +1882,42 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 psrctl, psrstat, psrperf;
+	u32 psrstat, psrperf;
 
-	psrctl = I915_READ(EDP_PSR_CTL);
-	seq_printf(m, "PSR Enabled: %s\n",
-		   yesno(psrctl & EDP_PSR_ENABLE));
+	if (I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
+		seq_puts(m, "PSR enabled\n");
+	} else {
+		seq_puts(m, "PSR disabled: ");
+		switch (dev_priv->no_psr_reason) {
+		case PSR_NO_SOURCE:
+			seq_puts(m, "not supported on this platform");
+			break;
+		case PSR_NO_SINK:
+			seq_puts(m, "not supported by panel");
+			break;
+		case PSR_CRTC_NOT_ACTIVE:
+			seq_puts(m, "crtc not active");
+			break;
+		case PSR_PWR_WELL_ENABLED:
+			seq_puts(m, "power well enabled");
+			break;
+		case PSR_NOT_TILED:
+			seq_puts(m, "not tiled");
+			break;
+		case PSR_SPRITE_ENABLED:
+			seq_puts(m, "sprite enabled");
+			break;
+		case PSR_INTERLACED_ENABLED:
+			seq_puts(m, "interlaced enabled");
+			break;
+		case PSR_HSW_NOT_DDIA:
+			seq_puts(m, "HSW ties PSR to DDI A (eDP)");
+			break;
+		default:
+			seq_puts(m, "unknown reason");
+		}
+		seq_puts(m, "\n");
+	}
 
 	psrstat = I915_READ(EDP_PSR_STATUS_CTL);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 56bd82b..f08c1d9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -543,6 +543,17 @@ enum no_fbc_reason {
 	FBC_CHIP_DEFAULT, /* disabled by default on this chip */
 };
 
+enum no_psr_reason {
+	PSR_NO_SOURCE, /* Not supported on platform */
+	PSR_NO_SINK, /* Not supported by panel */
+	PSR_CRTC_NOT_ACTIVE,
+	PSR_PWR_WELL_ENABLED,
+	PSR_NOT_TILED,
+	PSR_SPRITE_ENABLED,
+	PSR_INTERLACED_ENABLED,
+	PSR_HSW_NOT_DDIA,
+};
+
 enum intel_pch {
 	PCH_NONE = 0,	/* No PCH present */
 	PCH_IBX,	/* Ibexpeak PCH */
@@ -1146,6 +1157,7 @@ typedef struct drm_i915_private {
 	struct i915_power_well power_well;
 
 	enum no_fbc_reason no_fbc_reason;
+	enum no_psr_reason no_psr_reason;
 
 	struct drm_mm_node *compressed_fb;
 	struct drm_mm_node *compressed_llb;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index c10be94..9730d6b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1471,11 +1471,77 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
 		   EDP_PSR_ENABLE);
 }
 
+static bool intel_edp_psr_match_conditions(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 drm_crtc *crtc = dig_port->base.base.crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
+	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
+
+	if (!IS_HASWELL(dev)) {
+		DRM_DEBUG_KMS("PSR not supported on this platform\n");
+		dev_priv->no_psr_reason = PSR_NO_SOURCE;
+		return false;
+	}
+
+	if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
+	    (enc_to_dig_port(&intel_encoder->base)->port != PORT_A)) {
+		DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
+		dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
+		return false;
+	}
+
+	if (!is_edp_psr(intel_dp)) {
+		DRM_DEBUG_KMS("PSR not supported by this panel\n");
+		dev_priv->no_psr_reason = PSR_NO_SINK;
+		return false;
+	}
+
+	if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
+		DRM_DEBUG_KMS("crtc not active for PSR\n");
+		dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
+		return false;
+	}
+
+	if ((I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE) |
+	    (I915_READ(HSW_PWR_WELL_KVMR) & HSW_PWR_WELL_ENABLE)) {
+		DRM_DEBUG_KMS("PSR condition failed: Power Well is Enabled\n");
+		dev_priv->no_psr_reason = PSR_PWR_WELL_ENABLED;
+		return false;
+	}
+
+	if (obj->tiling_mode != I915_TILING_X ||
+	    obj->fence_reg == I915_FENCE_REG_NONE) {
+		DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
+		dev_priv->no_psr_reason = PSR_NOT_TILED;
+		return false;
+	}
+
+	if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
+		DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
+		dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
+		return false;
+	}
+
+	if ((I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
+	     PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
+		DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
+		dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
+		return false;
+	}
+
+	return true;
+}
+
 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))
+	if (!intel_edp_psr_match_conditions(intel_dp) ||
+	    intel_edp_is_psr_enabled(dev))
 		return;
 
 	/* Enable PSR on the panel */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: add update function to disable/enable-back PSR
  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   ` Rodrigo Vivi
  2013-07-05 22:48     ` Paulo Zanoni
  0 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-28 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

Required function to disable PSR when going to console mode.
But also can be used whenever PSR mode entry conditions changed.

v2: Add it before PSR Hook. Update function not really been called yet.
v3: Fix coding style detected by checkpatch by Paulo Zanoni.

Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 37 ++++++++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9730d6b..86c1a7d 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1536,14 +1536,8 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
 	return true;
 }
 
-void intel_edp_psr_enable(struct intel_dp *intel_dp)
+void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-
-	if (!intel_edp_psr_match_conditions(intel_dp) ||
-	    intel_edp_is_psr_enabled(dev))
-		return;
-
 	/* Enable PSR on the panel */
 	intel_edp_psr_enable_sink(intel_dp);
 
@@ -1551,6 +1545,15 @@ void intel_edp_psr_enable(struct intel_dp *intel_dp)
 	intel_edp_psr_enable_source(intel_dp);
 }
 
+void intel_edp_psr_enable(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+
+	if (intel_edp_psr_match_conditions(intel_dp) &&
+	    !intel_edp_is_psr_enabled(dev))
+		intel_edp_psr_do_enable(intel_dp);
+}
+
 void intel_edp_psr_disable(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -1573,6 +1576,26 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
+void intel_edp_psr_update(struct drm_device *dev)
+{
+	struct intel_encoder *encoder;
+	struct intel_dp *intel_dp = NULL;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
+		if (encoder->type == INTEL_OUTPUT_EDP) {
+			intel_dp = enc_to_intel_dp(&encoder->base);
+
+			if (!is_edp_psr(intel_dp))
+				return;
+
+			if (!intel_edp_psr_match_conditions(intel_dp))
+				intel_edp_psr_disable(intel_dp);
+			else
+				if (!intel_edp_is_psr_enabled(dev))
+					intel_edp_psr_do_enable(intel_dp);
+		}
+}
+
 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 ff09c4c..1f638cf 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -842,5 +842,6 @@ extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
 
 extern void intel_edp_psr_enable(struct intel_dp *intel_dp);
 extern void intel_edp_psr_disable(struct intel_dp *intel_dp);
+extern void intel_edp_psr_update(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/intel: add enable_psr module option
  2013-06-26 21:55 ` [PATCH 08/11] drm/intel: add enable_psr module option Rodrigo Vivi
@ 2013-06-28 17:47   ` Rodrigo Vivi
  2013-07-08 12:45     ` Paulo Zanoni
  0 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-28 17:47 UTC (permalink / raw)
  To: intel-gfx

PSR is enabled by default but can be disabled.

v2: prefer seq_puts to seq_printf detected by Paulo Zanoni.

Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 3 +++
 drivers/gpu/drm/i915/i915_drv.c     | 4 ++++
 drivers/gpu/drm/i915/i915_drv.h     | 2 ++
 drivers/gpu/drm/i915/intel_dp.c     | 6 ++++++
 4 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 95b27ac..9d8d789 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1895,6 +1895,9 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 		case PSR_NO_SINK:
 			seq_puts(m, "not supported by panel");
 			break;
+		case PSR_MODULE_PARAM:
+			seq_puts(m, "disabled by flag");
+			break;
 		case PSR_CRTC_NOT_ACTIVE:
 			seq_puts(m, "crtc not active");
 			break;
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 062cbda..7920c6f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -118,6 +118,10 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
 MODULE_PARM_DESC(i915_enable_ppgtt,
 		"Enable PPGTT (default: true)");
 
+int i915_enable_psr __read_mostly = 1;
+module_param_named(enable_psr, i915_enable_psr, int, 0600);
+MODULE_PARM_DESC(enable_psr, "Enable PSR (default: true)");
+
 unsigned int i915_preliminary_hw_support __read_mostly = 0;
 module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
 MODULE_PARM_DESC(preliminary_hw_support,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f08c1d9..dda992a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -546,6 +546,7 @@ enum no_fbc_reason {
 enum no_psr_reason {
 	PSR_NO_SOURCE, /* Not supported on platform */
 	PSR_NO_SINK, /* Not supported by panel */
+	PSR_MODULE_PARAM,
 	PSR_CRTC_NOT_ACTIVE,
 	PSR_PWR_WELL_ENABLED,
 	PSR_NOT_TILED,
@@ -1555,6 +1556,7 @@ extern int i915_enable_rc6 __read_mostly;
 extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
+extern int i915_enable_psr __read_mostly;
 extern unsigned int i915_preliminary_hw_support __read_mostly;
 extern int i915_disable_power_well __read_mostly;
 extern int i915_enable_ips __read_mostly;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 86c1a7d..5d961cb 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1500,6 +1500,12 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
 		return false;
 	}
 
+	if (!i915_enable_psr) {
+		DRM_DEBUG_KMS("PSR disable by flag\n");
+		dev_priv->no_psr_reason = PSR_MODULE_PARAM;
+		return false;
+	}
+
 	if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
 		DRM_DEBUG_KMS("crtc not active for PSR\n");
 		dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Add functions to force psr exit
  2013-06-27 13:03   ` [PATCH] " Rodrigo Vivi
@ 2013-06-28 17:52     ` Rodrigo Vivi
  2013-06-28 17:57       ` Chris Wilson
  2013-07-08 13:03       ` Paulo Zanoni
  0 siblings, 2 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-28 17:52 UTC (permalink / raw)
  To: intel-gfx

PSR tracking engine in HSW doesn't detect automagically some directly copy area
operations through scanout so we will have to kick it manually and
reschedule it to come back to normal operation as soon as possible.

v2: Before PSR Hook. Don't force it when busy yet.
v3/v4: Solved small conflict.

Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_dp.c  | 59 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |  4 +++
 3 files changed, 64 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 833cc97..a19245b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1838,6 +1838,7 @@
 #define   EDP_PSR_PERF_CNT_MASK		0xffffff
 
 #define EDP_PSR_DEBUG_CTL		0x64860
+#define   EDP_PSR_DEBUG_FORCE_EXIT	(3<<30)
 #define   EDP_PSR_DEBUG_MASK_LPSP	(1<<27)
 #define   EDP_PSR_DEBUG_MASK_MEMUP	(1<<26)
 #define   EDP_PSR_DEBUG_MASK_HPD	(1<<25)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 68c81ab..5001fd9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1366,6 +1366,48 @@ bool intel_edp_is_psr_enabled(struct drm_device *dev)
 	return I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
 }
 
+static void intel_edp_psr_delayed_normal_work(struct work_struct *__work)
+{
+	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
+						 struct intel_dp,
+						 edp_psr_delayed_normal_work);
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&intel_dp->psr_exit_mutex);
+	I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) &
+		   ~EDP_PSR_DEBUG_FORCE_EXIT);
+	mutex_unlock(&intel_dp->psr_exit_mutex);
+}
+
+void intel_edp_psr_force_exit(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *encoder;
+	struct intel_dp *intel_dp = NULL;
+
+	if (!intel_edp_is_psr_enabled(dev))
+		return;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
+		if (encoder->type == INTEL_OUTPUT_EDP)
+			intel_dp = enc_to_intel_dp(&encoder->base);
+
+	if (!intel_dp)
+		return;
+
+	if (WARN_ON(!intel_dp->psr_setup_done))
+		return;
+
+	mutex_lock(&intel_dp->psr_exit_mutex);
+	I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) |
+		   EDP_PSR_DEBUG_FORCE_EXIT);
+	mutex_unlock(&intel_dp->psr_exit_mutex);
+
+	schedule_delayed_work(&intel_dp->edp_psr_delayed_normal_work,
+			      msecs_to_jiffies(100));
+}
+
 void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
 			     struct edp_vsc_psr *vsc_psr)
 {
@@ -1400,6 +1442,18 @@ void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
 	POSTING_READ(ctl_reg);
 }
 
+static void intel_edp_psr_setup(struct intel_dp *intel_dp)
+{
+	if (intel_dp->psr_setup_done)
+		return;
+
+	INIT_DELAYED_WORK(&intel_dp->edp_psr_delayed_normal_work,
+			  intel_edp_psr_delayed_normal_work);
+	mutex_init(&intel_dp->psr_exit_mutex);
+
+	intel_dp->psr_setup_done = true;
+}
+
 static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -1544,6 +1598,9 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
 
 void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
 {
+	/* Setup PSR once */
+	intel_edp_psr_setup(intel_dp);
+
 	/* Enable PSR on the panel */
 	intel_edp_psr_enable_sink(intel_dp);
 
@@ -3413,6 +3470,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
 	     error, port_name(port));
 
+	intel_dp->psr_setup_done = false;
+
 	if (!intel_edp_init_connector(intel_dp, intel_connector)) {
 		i2c_del_adapter(&intel_dp->adapter);
 		if (is_edp(intel_dp)) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 65f5001..3b2ccaa 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -497,6 +497,9 @@ struct intel_dp {
 	int backlight_on_delay;
 	int backlight_off_delay;
 	struct delayed_work panel_vdd_work;
+	struct delayed_work edp_psr_delayed_normal_work;
+	struct mutex psr_exit_mutex;
+	bool psr_setup_done;
 	bool want_panel_vdd;
 	struct intel_connector *attached_connector;
 };
@@ -844,5 +847,6 @@ extern void intel_edp_psr_enable(struct intel_dp *intel_dp);
 extern void intel_edp_psr_disable(struct intel_dp *intel_dp);
 extern void intel_edp_psr_update(struct drm_device *dev);
 extern bool intel_edp_is_psr_enabled(struct drm_device *dev);
+extern void intel_edp_psr_force_exit(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Add functions to force psr exit
  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
  1 sibling, 1 reply; 53+ messages in thread
From: Chris Wilson @ 2013-06-28 17:57 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx

On Fri, Jun 28, 2013 at 02:52:10PM -0300, Rodrigo Vivi wrote:
> PSR tracking engine in HSW doesn't detect automagically some directly copy area
> operations through scanout so we will have to kick it manually and
> reschedule it to come back to normal operation as soon as possible.

Does force_exit correspond with any names/actions in the documentation?
If not, care to consider intel_edp_psr_wakeup() as a less confusing name?
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Add functions to force psr exit
  2013-06-28 17:57       ` Chris Wilson
@ 2013-06-28 18:05         ` Rodrigo Vivi
  0 siblings, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-06-28 18:05 UTC (permalink / raw)
  To: Chris Wilson, Rodrigo Vivi, intel-gfx

On Fri, Jun 28, 2013 at 2:57 PM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> On Fri, Jun 28, 2013 at 02:52:10PM -0300, Rodrigo Vivi wrote:
>> PSR tracking engine in HSW doesn't detect automagically some directly copy area
>> operations through scanout so we will have to kick it manually and
>> reschedule it to come back to normal operation as soon as possible.
>
> Does force_exit correspond with any names/actions in the documentation?
> If not, care to consider intel_edp_psr_wakeup() as a less confusing name?

Yes, it correspond to name of setting 11 to bits 31:30 of 0x64860.
Besides to be honest wakeup confuses me more.
It seems ambiguous, I mean wake up from srd state (force exit) or wake
up psr functionality (normal)?

> -Chris
>
> --
> Chris Wilson, Intel Open Source Technology Centre



--
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Enable/Disable PSR
  2013-06-28 17:16   ` [PATCH] " Rodrigo Vivi
@ 2013-06-28 19:31     ` Paulo Zanoni
  2013-07-01 20:40       ` Rodrigo Vivi
  2013-07-02  0:29       ` Rodrigo Vivi
  0 siblings, 2 replies; 53+ messages in thread
From: Paulo Zanoni @ 2013-06-28 19:31 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx

Hi

2013/6/28 Rodrigo Vivi <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.
> v4: Fix identation and other style issues raised by checkpatch (by Paulo).
>

A few of the comments here were already present in previous reviews.
If you think they're not needed, please reply saying why.


> 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)

I know our documentation explicitly says "0x80060000" and
"0x01000000", but to me these magic values are just magic... I think
we could try to reuse the same mechanism we use for the other aux
messages. Check the usage of pack_aux inside intel_dp_aux_ch and also
intel_dp_aux_native_write. Maybe this could be done in a follow-up
patch. Jani gave a suggestion on how to implement this, see email "Re:
[PATCH 5/9] drm/i915: Setup EDP PSR AUX Registers" from January 31.


> +#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 dca8fa6..c10be94 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)

This function should be static (or included in a .h file).


> +{
> +       struct drm_device *dev = intel_dp_to_dev(intel_dp);

Function intel_dp_to_dev calls dp_to_dig_port, but you're already
calling dp_to_dig_port below. You could remove this intel_dp_to_dev
call by reordering the definitions.


> +       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);

We don't use this register for anything else on eDP, so instead of
preserving its contents with this read we should just set the bits we
want, zeroing everything else. We don't want to preserve bogus values.
Also, read below: if we move this code to mode_set time it will make
even more sense.


> +
> +       /* As per eDP spec, wait for vblank to send SDP VSC packet */
> +       intel_wait_for_vblank(dev, crtc->pipe);

The spec says the SDP VSC packets should be sent during the vblank,
but the HW does this automatically and intel_wait_for_vblank doesn't
guarantee us anything regarding that. So that wait seems useless.


> +
> +       /* 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.*/

My interpretation of the spec is that we need to wait until exactly
after the VSync so we don't send incomplete packets, but we don't have
a good way to do this, and intel_wait_for_vblank doesn't help us with
that. If you take a look at the HDMI code you'll notice that we set
the video DIP registers inside intel_hdmi_mode_set, because at that
point the pipe is stopped and we don't need to worry about waiting for
the exact vblank period. Perhaps we should do the same here: load the
contents of the video dip registers at mode_set time? Is there any
problem in keeping those values there even when PSR or the pipe is
disabled?


> +       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);

The PSR enabling documentation says that the "HW also enables VSC DIP
when required", so maybe we should not turn the
VIDEO_DIP_ENABLE_VSC_HSW bit and see if the HW does that for us? My
fear is that setting this unconditionally may make some panels
confused. But I'm not really sure if the HW really sets this bit for
us or just sends/stops-sending the DIP in case this bit is on.


> +       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) */

If you implement our suggestion of replacing the magic 0x80060000
value with code this magic msg_size will also disappear.


> +
> +       /* 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;

Why are we using these 500us values? I couldn't find a place that
tells us which ones to use.


> +       }
> +
> +       /* 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);

Do we have a workaround name for the line above? Damien recently made
a nice effort to document all the WA names we implement. We should at
least say this is a WA.


> +
> +       /* Disable unused interrupts */
> +       I915_WRITE(GEN6_PMINTRMSK, GEN6_PM_RP_UP_EI_EXPIRED |
> +                  GEN6_PM_RP_DOWN_EI_EXPIRED);

The line above needs a very big comment explaining it. Also, I'm not
sure the code is correct. Don't we need irq_lock or rps_lock, also
adjust some dev_priv->xyz_iir variable? I'll leave the review of this
line to Ben and Daniel since they're currently touching these things.


> +
> +       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))

One of the nice things about the modeset rework is that, for most of
the display code, we don't call "enable" twice of "disable" twice. On
a brief look at patch 11 it seems we do respect this, so how about you
turn this check for intel_edp_is_psr_enabled into a WARN?


> +               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);

Same as above: you could avoid intel_dp_to_dev since you're already
calling dp_to_dig_port.


> +       struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
> +       uint32_t val;
> +
> +       if (!intel_edp_is_psr_enabled(dev))
> +               return;

Same as above: replace the check above with a WARN?


> +
> +       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);

The spec says we need to wait for a vblank and then disable the VSC
DIP. As stated above, it is not clear whether the hardware does this
automatically or not. Also, do we need this at all? I imagine the spec
says we need to wait for a vblank just to avoid sending incomplete
DIPs, but on this case the intel_wait_for_vblank won't help us here.
Maybe we could fully just enable/disable the bit at mode_set time and
not worry about it later?


> +}
> +
>  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..ff09c4c 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
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Added debugfs support for PSR Status
  2013-06-28 17:29   ` [PATCH] " Rodrigo Vivi
@ 2013-06-28 20:08     ` Paulo Zanoni
  2013-06-28 20:14       ` Paulo Zanoni
  0 siblings, 1 reply; 53+ messages in thread
From: Paulo Zanoni @ 2013-06-28 20:08 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> Adding support for PSR Status, PSR entry counter and performance counters.
> Heavily based on initial work from Shobhit.
>
> v2: Fix PSR Status Link bits by Paulo Zanoni.
> v3: Prefer seq_puts to seq_printf by Paulo Zanoni.
>
> CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Credits-by: Shobhit Kumar <shobhit.kumar@intel.com>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 90 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_reg.h     | 24 ++++++++++
>  2 files changed, 114 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index a188624..67c777f 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1877,6 +1877,95 @@ static int i915_dpio_info(struct seq_file *m, void *data)
>         return 0;
>  }
>
> +static int i915_edp_psr_status(struct seq_file *m, void *data)
> +{
> +       struct drm_info_node *node = m->private;
> +       struct drm_device *dev = node->minor->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       u32 psrctl, psrstat, psrperf;
> +
> +       psrctl = I915_READ(EDP_PSR_CTL);
> +       seq_printf(m, "PSR Enabled: %s\n",
> +                  yesno(psrctl & EDP_PSR_ENABLE));
> +
> +       psrstat = I915_READ(EDP_PSR_STATUS_CTL);
> +
> +       seq_puts(m, "PSR Current State: ");
> +       switch (psrstat & EDP_PSR_STATUS_STATE_MASK) {
> +       case EDP_PSR_STATUS_STATE_IDLE:
> +               seq_puts(m, "Reset state\n");
> +               break;
> +       case EDP_PSR_STATUS_STATE_SRDONACK:
> +               seq_puts(m, "Wait for TG/Stream to send on frame of data after SRD conditions are met\n");
> +               break;
> +       case EDP_PSR_STATUS_STATE_SRDENT:
> +               seq_puts(m, "SRD entry\n");
> +               break;
> +       case EDP_PSR_STATUS_STATE_BUFOFF:
> +               seq_puts(m, "Wait for buffer turn off\n");
> +               break;
> +       case EDP_PSR_STATUS_STATE_BUFON:
> +                       seq_puts(m, "Wait for buffer turn on\n");

Wrong indentation above.

> +               break;
> +       case EDP_PSR_STATUS_STATE_AUXACK:
> +                       seq_puts(m, "Wait for AUX to acknowledge on SRD exit\n");

Wrong indentation above.

> +               break;
> +       case EDP_PSR_STATUS_STATE_SRDOFFACK:
> +                       seq_puts(m, "Wait for TG/Stream to acknowledge the SRD VDM exit\n");

Wrong indentation above.

Everything else looks correct. With that fixed:
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> +               break;
> +       default:
> +               seq_puts(m, "Unknown\n");
> +               break;
> +       }
> +
> +       seq_puts(m, "Link Status: ");
> +       switch (psrstat & EDP_PSR_STATUS_LINK_MASK) {
> +       case EDP_PSR_STATUS_LINK_FULL_OFF:
> +               seq_puts(m, "Link is fully off\n");
> +               break;
> +       case EDP_PSR_STATUS_LINK_FULL_ON:
> +               seq_puts(m, "Link is fully on\n");
> +               break;
> +       case EDP_PSR_STATUS_LINK_STANDBY:
> +               seq_puts(m, "Link is in standby\n");
> +               break;
> +       default:
> +               seq_puts(m, "Unknown\n");
> +               break;
> +       }
> +
> +       seq_printf(m, "PSR Entry Count: %u\n",
> +                  psrstat >> EDP_PSR_STATUS_COUNT_SHIFT &
> +                  EDP_PSR_STATUS_COUNT_MASK);
> +
> +       seq_printf(m, "Max Sleep Timer Counter: %u\n",
> +                  psrstat >> EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT &
> +                  EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK);
> +
> +       seq_printf(m, "Had AUX error: %s\n",
> +                  yesno(psrstat & EDP_PSR_STATUS_AUX_ERROR));
> +
> +       seq_printf(m, "Sending AUX: %s\n",
> +                  yesno(psrstat & EDP_PSR_STATUS_AUX_SENDING));
> +
> +       seq_printf(m, "Sending Idle: %s\n",
> +                  yesno(psrstat & EDP_PSR_STATUS_SENDING_IDLE));
> +
> +       seq_printf(m, "Sending TP2 TP3: %s\n",
> +                  yesno(psrstat & EDP_PSR_STATUS_SENDING_TP2_TP3));
> +
> +       seq_printf(m, "Sending TP1: %s\n",
> +                  yesno(psrstat & EDP_PSR_STATUS_SENDING_TP1));
> +
> +       seq_printf(m, "Idle Count: %u\n",
> +                  psrstat & EDP_PSR_STATUS_IDLE_MASK);
> +
> +       psrperf = (I915_READ(EDP_PSR_PERF_CNT)) & EDP_PSR_PERF_CNT_MASK;
> +       seq_printf(m, "Performance Counter: %u\n", psrperf);
> +
> +       return 0;
> +}
> +
>  static int
>  i915_wedged_get(void *data, u64 *val)
>  {
> @@ -2306,6 +2395,7 @@ static struct drm_info_list i915_debugfs_list[] = {
>         {"i915_swizzle_info", i915_swizzle_info, 0},
>         {"i915_ppgtt_info", i915_ppgtt_info, 0},
>         {"i915_dpio", i915_dpio_info, 0},
> +       {"i915_edp_psr_status", i915_edp_psr_status, 0},
>  };
>  #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index caf57d8..833cc97 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1812,6 +1812,30 @@
>
>  #define EDP_PSR_STATUS_CTL                     0x64840
>  #define   EDP_PSR_STATUS_STATE_MASK            (7<<29)
> +#define   EDP_PSR_STATUS_STATE_IDLE            (0<<29)
> +#define   EDP_PSR_STATUS_STATE_SRDONACK                (1<<29)
> +#define   EDP_PSR_STATUS_STATE_SRDENT          (2<<29)
> +#define   EDP_PSR_STATUS_STATE_BUFOFF          (3<<29)
> +#define   EDP_PSR_STATUS_STATE_BUFON           (4<<29)
> +#define   EDP_PSR_STATUS_STATE_AUXACK          (5<<29)
> +#define   EDP_PSR_STATUS_STATE_SRDOFFACK       (6<<29)
> +#define   EDP_PSR_STATUS_LINK_MASK             (3<<26)
> +#define   EDP_PSR_STATUS_LINK_FULL_OFF         (0<<26)
> +#define   EDP_PSR_STATUS_LINK_FULL_ON          (1<<26)
> +#define   EDP_PSR_STATUS_LINK_STANDBY          (2<<26)
> +#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT 20
> +#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK  0x1f
> +#define   EDP_PSR_STATUS_COUNT_SHIFT           16
> +#define   EDP_PSR_STATUS_COUNT_MASK            0xf
> +#define   EDP_PSR_STATUS_AUX_ERROR             (1<<15)
> +#define   EDP_PSR_STATUS_AUX_SENDING           (1<<12)
> +#define   EDP_PSR_STATUS_SENDING_IDLE          (1<<9)
> +#define   EDP_PSR_STATUS_SENDING_TP2_TP3       (1<<8)
> +#define   EDP_PSR_STATUS_SENDING_TP1           (1<<4)
> +#define   EDP_PSR_STATUS_IDLE_MASK             0xf
> +
> +#define EDP_PSR_PERF_CNT               0x64844
> +#define   EDP_PSR_PERF_CNT_MASK                0xffffff
>
>  #define EDP_PSR_DEBUG_CTL              0x64860
>  #define   EDP_PSR_DEBUG_MASK_LPSP      (1<<27)
> --
> 1.8.1.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Added debugfs support for PSR Status
  2013-06-28 20:08     ` Paulo Zanoni
@ 2013-06-28 20:14       ` Paulo Zanoni
  2013-07-02  0:46         ` Rodrigo Vivi
  0 siblings, 1 reply; 53+ messages in thread
From: Paulo Zanoni @ 2013-06-28 20:14 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

2013/6/28 Paulo Zanoni <przanoni@gmail.com>:
> 2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>> Adding support for PSR Status, PSR entry counter and performance counters.
>> Heavily based on initial work from Shobhit.
>>
>> v2: Fix PSR Status Link bits by Paulo Zanoni.
>> v3: Prefer seq_puts to seq_printf by Paulo Zanoni.
>>
>> CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> Credits-by: Shobhit Kumar <shobhit.kumar@intel.com>
>> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>> ---
>>  drivers/gpu/drm/i915/i915_debugfs.c | 90 +++++++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/i915_reg.h     | 24 ++++++++++
>>  2 files changed, 114 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
>> index a188624..67c777f 100644
>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> @@ -1877,6 +1877,95 @@ static int i915_dpio_info(struct seq_file *m, void *data)
>>         return 0;
>>  }
>>
>> +static int i915_edp_psr_status(struct seq_file *m, void *data)
>> +{
>> +       struct drm_info_node *node = m->private;
>> +       struct drm_device *dev = node->minor->dev;
>> +       struct drm_i915_private *dev_priv = dev->dev_private;
>> +       u32 psrctl, psrstat, psrperf;
>> +
>> +       psrctl = I915_READ(EDP_PSR_CTL);
>> +       seq_printf(m, "PSR Enabled: %s\n",
>> +                  yesno(psrctl & EDP_PSR_ENABLE));
>> +
>> +       psrstat = I915_READ(EDP_PSR_STATUS_CTL);
>> +
>> +       seq_puts(m, "PSR Current State: ");
>> +       switch (psrstat & EDP_PSR_STATUS_STATE_MASK) {
>> +       case EDP_PSR_STATUS_STATE_IDLE:
>> +               seq_puts(m, "Reset state\n");
>> +               break;
>> +       case EDP_PSR_STATUS_STATE_SRDONACK:
>> +               seq_puts(m, "Wait for TG/Stream to send on frame of data after SRD conditions are met\n");
>> +               break;
>> +       case EDP_PSR_STATUS_STATE_SRDENT:
>> +               seq_puts(m, "SRD entry\n");
>> +               break;
>> +       case EDP_PSR_STATUS_STATE_BUFOFF:
>> +               seq_puts(m, "Wait for buffer turn off\n");
>> +               break;
>> +       case EDP_PSR_STATUS_STATE_BUFON:
>> +                       seq_puts(m, "Wait for buffer turn on\n");
>
> Wrong indentation above.
>
>> +               break;
>> +       case EDP_PSR_STATUS_STATE_AUXACK:
>> +                       seq_puts(m, "Wait for AUX to acknowledge on SRD exit\n");
>
> Wrong indentation above.
>
>> +               break;
>> +       case EDP_PSR_STATUS_STATE_SRDOFFACK:
>> +                       seq_puts(m, "Wait for TG/Stream to acknowledge the SRD VDM exit\n");
>
> Wrong indentation above.
>
> Everything else looks correct. With that fixed:
> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Actually no. With this patch, we'll read non-existing registers on
platforms that don't support PSR. We need an early return for that
case.

>
>> +               break;
>> +       default:
>> +               seq_puts(m, "Unknown\n");
>> +               break;
>> +       }
>> +
>> +       seq_puts(m, "Link Status: ");
>> +       switch (psrstat & EDP_PSR_STATUS_LINK_MASK) {
>> +       case EDP_PSR_STATUS_LINK_FULL_OFF:
>> +               seq_puts(m, "Link is fully off\n");
>> +               break;
>> +       case EDP_PSR_STATUS_LINK_FULL_ON:
>> +               seq_puts(m, "Link is fully on\n");
>> +               break;
>> +       case EDP_PSR_STATUS_LINK_STANDBY:
>> +               seq_puts(m, "Link is in standby\n");
>> +               break;
>> +       default:
>> +               seq_puts(m, "Unknown\n");
>> +               break;
>> +       }
>> +
>> +       seq_printf(m, "PSR Entry Count: %u\n",
>> +                  psrstat >> EDP_PSR_STATUS_COUNT_SHIFT &
>> +                  EDP_PSR_STATUS_COUNT_MASK);
>> +
>> +       seq_printf(m, "Max Sleep Timer Counter: %u\n",
>> +                  psrstat >> EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT &
>> +                  EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK);
>> +
>> +       seq_printf(m, "Had AUX error: %s\n",
>> +                  yesno(psrstat & EDP_PSR_STATUS_AUX_ERROR));
>> +
>> +       seq_printf(m, "Sending AUX: %s\n",
>> +                  yesno(psrstat & EDP_PSR_STATUS_AUX_SENDING));
>> +
>> +       seq_printf(m, "Sending Idle: %s\n",
>> +                  yesno(psrstat & EDP_PSR_STATUS_SENDING_IDLE));
>> +
>> +       seq_printf(m, "Sending TP2 TP3: %s\n",
>> +                  yesno(psrstat & EDP_PSR_STATUS_SENDING_TP2_TP3));
>> +
>> +       seq_printf(m, "Sending TP1: %s\n",
>> +                  yesno(psrstat & EDP_PSR_STATUS_SENDING_TP1));
>> +
>> +       seq_printf(m, "Idle Count: %u\n",
>> +                  psrstat & EDP_PSR_STATUS_IDLE_MASK);
>> +
>> +       psrperf = (I915_READ(EDP_PSR_PERF_CNT)) & EDP_PSR_PERF_CNT_MASK;
>> +       seq_printf(m, "Performance Counter: %u\n", psrperf);
>> +
>> +       return 0;
>> +}
>> +
>>  static int
>>  i915_wedged_get(void *data, u64 *val)
>>  {
>> @@ -2306,6 +2395,7 @@ static struct drm_info_list i915_debugfs_list[] = {
>>         {"i915_swizzle_info", i915_swizzle_info, 0},
>>         {"i915_ppgtt_info", i915_ppgtt_info, 0},
>>         {"i915_dpio", i915_dpio_info, 0},
>> +       {"i915_edp_psr_status", i915_edp_psr_status, 0},
>>  };
>>  #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
>> index caf57d8..833cc97 100644
>> --- a/drivers/gpu/drm/i915/i915_reg.h
>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>> @@ -1812,6 +1812,30 @@
>>
>>  #define EDP_PSR_STATUS_CTL                     0x64840
>>  #define   EDP_PSR_STATUS_STATE_MASK            (7<<29)
>> +#define   EDP_PSR_STATUS_STATE_IDLE            (0<<29)
>> +#define   EDP_PSR_STATUS_STATE_SRDONACK                (1<<29)
>> +#define   EDP_PSR_STATUS_STATE_SRDENT          (2<<29)
>> +#define   EDP_PSR_STATUS_STATE_BUFOFF          (3<<29)
>> +#define   EDP_PSR_STATUS_STATE_BUFON           (4<<29)
>> +#define   EDP_PSR_STATUS_STATE_AUXACK          (5<<29)
>> +#define   EDP_PSR_STATUS_STATE_SRDOFFACK       (6<<29)
>> +#define   EDP_PSR_STATUS_LINK_MASK             (3<<26)
>> +#define   EDP_PSR_STATUS_LINK_FULL_OFF         (0<<26)
>> +#define   EDP_PSR_STATUS_LINK_FULL_ON          (1<<26)
>> +#define   EDP_PSR_STATUS_LINK_STANDBY          (2<<26)
>> +#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT 20
>> +#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK  0x1f
>> +#define   EDP_PSR_STATUS_COUNT_SHIFT           16
>> +#define   EDP_PSR_STATUS_COUNT_MASK            0xf
>> +#define   EDP_PSR_STATUS_AUX_ERROR             (1<<15)
>> +#define   EDP_PSR_STATUS_AUX_SENDING           (1<<12)
>> +#define   EDP_PSR_STATUS_SENDING_IDLE          (1<<9)
>> +#define   EDP_PSR_STATUS_SENDING_TP2_TP3       (1<<8)
>> +#define   EDP_PSR_STATUS_SENDING_TP1           (1<<4)
>> +#define   EDP_PSR_STATUS_IDLE_MASK             0xf
>> +
>> +#define EDP_PSR_PERF_CNT               0x64844
>> +#define   EDP_PSR_PERF_CNT_MASK                0xffffff
>>
>>  #define EDP_PSR_DEBUG_CTL              0x64860
>>  #define   EDP_PSR_DEBUG_MASK_LPSP      (1<<27)
>> --
>> 1.8.1.4
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
>
> --
> Paulo Zanoni



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Match all PSR mode entry conditions before enabling it.
  2013-06-28 17:36   ` [PATCH] " Rodrigo Vivi
@ 2013-06-28 20:46     ` Paulo Zanoni
  2013-07-01 20:47       ` Rodrigo Vivi
  2013-07-02  0:50       ` Rodrigo Vivi
  0 siblings, 2 replies; 53+ messages in thread
From: Paulo Zanoni @ 2013-06-28 20:46 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> v2: Prefer seq_puts to seq_printf by Paulo Zanoni.
>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 39 ++++++++++++++++++---
>  drivers/gpu/drm/i915/i915_drv.h     | 12 +++++++
>  drivers/gpu/drm/i915/intel_dp.c     | 68 ++++++++++++++++++++++++++++++++++++-
>  3 files changed, 114 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 67c777f..95b27ac 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1882,11 +1882,42 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>         struct drm_info_node *node = m->private;
>         struct drm_device *dev = node->minor->dev;
>         struct drm_i915_private *dev_priv = dev->dev_private;
> -       u32 psrctl, psrstat, psrperf;
> +       u32 psrstat, psrperf;
>
> -       psrctl = I915_READ(EDP_PSR_CTL);
> -       seq_printf(m, "PSR Enabled: %s\n",
> -                  yesno(psrctl & EDP_PSR_ENABLE));
> +       if (I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
> +               seq_puts(m, "PSR enabled\n");
> +       } else {
> +               seq_puts(m, "PSR disabled: ");
> +               switch (dev_priv->no_psr_reason) {
> +               case PSR_NO_SOURCE:
> +                       seq_puts(m, "not supported on this platform");
> +                       break;
> +               case PSR_NO_SINK:
> +                       seq_puts(m, "not supported by panel");
> +                       break;
> +               case PSR_CRTC_NOT_ACTIVE:
> +                       seq_puts(m, "crtc not active");
> +                       break;
> +               case PSR_PWR_WELL_ENABLED:
> +                       seq_puts(m, "power well enabled");
> +                       break;
> +               case PSR_NOT_TILED:
> +                       seq_puts(m, "not tiled");
> +                       break;
> +               case PSR_SPRITE_ENABLED:
> +                       seq_puts(m, "sprite enabled");
> +                       break;
> +               case PSR_INTERLACED_ENABLED:
> +                       seq_puts(m, "interlaced enabled");
> +                       break;
> +               case PSR_HSW_NOT_DDIA:
> +                       seq_puts(m, "HSW ties PSR to DDI A (eDP)");
> +                       break;
> +               default:
> +                       seq_puts(m, "unknown reason");
> +               }
> +               seq_puts(m, "\n");
> +       }
>
>         psrstat = I915_READ(EDP_PSR_STATUS_CTL);
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 56bd82b..f08c1d9 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -543,6 +543,17 @@ enum no_fbc_reason {
>         FBC_CHIP_DEFAULT, /* disabled by default on this chip */
>  };
>
> +enum no_psr_reason {
> +       PSR_NO_SOURCE, /* Not supported on platform */
> +       PSR_NO_SINK, /* Not supported by panel */
> +       PSR_CRTC_NOT_ACTIVE,
> +       PSR_PWR_WELL_ENABLED,
> +       PSR_NOT_TILED,
> +       PSR_SPRITE_ENABLED,
> +       PSR_INTERLACED_ENABLED,
> +       PSR_HSW_NOT_DDIA,

I see you left a few reasons listed on the spec, for example S3D,
which we don't support yet. I'm pretty sure that when we implement S3D
we'll totally forget about adding the PSR_S3D_ENABLED condition, so
shouldn't we do it now? Also, why did we not add the eDP hotplug
reason?


> +};
> +
>  enum intel_pch {
>         PCH_NONE = 0,   /* No PCH present */
>         PCH_IBX,        /* Ibexpeak PCH */
> @@ -1146,6 +1157,7 @@ typedef struct drm_i915_private {
>         struct i915_power_well power_well;
>
>         enum no_fbc_reason no_fbc_reason;
> +       enum no_psr_reason no_psr_reason;
>
>         struct drm_mm_node *compressed_fb;
>         struct drm_mm_node *compressed_llb;
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index c10be94..9730d6b 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1471,11 +1471,77 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
>                    EDP_PSR_ENABLE);
>  }
>
> +static bool intel_edp_psr_match_conditions(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 drm_crtc *crtc = dig_port->base.base.crtc;
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +       struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
> +       struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;

Again, you have intel_dp_to_dev and also call dp_to_dig_port twice.


> +
> +       if (!IS_HASWELL(dev)) {
> +               DRM_DEBUG_KMS("PSR not supported on this platform\n");
> +               dev_priv->no_psr_reason = PSR_NO_SOURCE;
> +               return false;
> +       }
> +
> +       if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
> +           (enc_to_dig_port(&intel_encoder->base)->port != PORT_A)) {

Here you're calling enc_to_dig_port, but you already defined dig_port
above. Use it.


> +               DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
> +               dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
> +               return false;
> +       }
> +
> +       if (!is_edp_psr(intel_dp)) {
> +               DRM_DEBUG_KMS("PSR not supported by this panel\n");
> +               dev_priv->no_psr_reason = PSR_NO_SINK;
> +               return false;
> +       }
> +
> +       if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {

Why do we check for crtc->fb and crtc->mode.clock here? Also, there's
intel_crtc->primary_disabled which you could use.


> +               DRM_DEBUG_KMS("crtc not active for PSR\n");
> +               dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
> +               return false;
> +       }
> +
> +       if ((I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE) |

I'd  use "||" instead of "|" at the end of the line since this is a
logical statement.


> +           (I915_READ(HSW_PWR_WELL_KVMR) & HSW_PWR_WELL_ENABLE)) {

I know the spec says we should check for this, but there's absolutely
no guarantee that the KVMr won't be enabled exactly after we read this
bit. I don't know if there's a sane way to check for an active KVMr
session. We should also probably get an interrupt somehow if someone
enables KVMr after PSR is enabled.


> +               DRM_DEBUG_KMS("PSR condition failed: Power Well is Enabled\n");
> +               dev_priv->no_psr_reason = PSR_PWR_WELL_ENABLED;
> +               return false;
> +       }
> +
> +       if (obj->tiling_mode != I915_TILING_X ||
> +           obj->fence_reg == I915_FENCE_REG_NONE) {
> +               DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
> +               dev_priv->no_psr_reason = PSR_NOT_TILED;
> +               return false;
> +       }
> +
> +       if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {

We should probably check "struct intel_plane" instead of I915_READ here.


> +               DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
> +               dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
> +               return false;
> +       }
> +
> +       if ((I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
> +            PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {

I'd prefer checking for "crtc->mode.flags & DRM_MODE_FLAG_INTERLACE".


> +               DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
> +               dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
> +               return false;
> +       }
> +
> +       return true;
> +}
> +
>  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))
> +       if (!intel_edp_psr_match_conditions(intel_dp) ||
> +           intel_edp_is_psr_enabled(dev))
>                 return;
>
>         /* Enable PSR on the panel */
> --
> 1.8.1.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 11/11] drm/i915: Hook PSR functionality
  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
  0 siblings, 1 reply; 53+ messages in thread
From: Paulo Zanoni @ 2013-06-28 21:00 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni, dri-devel

2013/6/26 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> PSR must be enabled after transcoder and port are running.
> And it is only available for HSW.
>
> v2: move enable/disable to intel_ddi
> v3: The spec suggests PSR should be disabled even before backlight (by pzanoni)
> v4: also disabling and enabling whenever panel is disabled/enabled.
> v5: make it last patch to avoid breaking whenever bisecting. So calling for
>     update and force exit came to this patch along with enable/disable calls.
>
> CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> ---
>  drivers/gpu/drm/i915/i915_gem.c      | 2 ++
>  drivers/gpu/drm/i915/intel_ddi.c     | 2 ++
>  drivers/gpu/drm/i915/intel_display.c | 1 +
>  drivers/gpu/drm/i915/intel_dp.c      | 2 ++
>  4 files changed, 7 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index c68b90f..f2e135b 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -3786,6 +3786,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
>                 goto unlock;
>         }
>
> +       intel_edp_psr_force_exit(dev);
> +
>         /* Count all active objects as busy, even if they are currently not used
>          * by the gpu. Users of this interface expect objects to eventually
>          * become non-busy without any further actions, therefore emit any
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 324211a..4211925 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1117,6 +1117,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
>                         intel_dp_stop_link_train(intel_dp);
>
>                 ironlake_edp_backlight_on(intel_dp);
> +               intel_edp_psr_enable(intel_dp);
>         }
>
>         if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
> @@ -1147,6 +1148,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
>         if (type == INTEL_OUTPUT_EDP) {
>                 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>
> +               intel_edp_psr_disable(intel_dp);
>                 ironlake_edp_backlight_off(intel_dp);
>         }
>  }
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 6fafa43..5bbfed0 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2236,6 +2236,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>         }
>
>         intel_update_fbc(dev);
> +       intel_edp_psr_update(dev);
>         mutex_unlock(&dev->struct_mutex);
>
>         intel_crtc_update_sarea_pos(crtc, x, y);
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 9986484..019b1ff 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1668,6 +1668,7 @@ static void intel_disable_dp(struct intel_encoder *encoder)
>         /* Make sure the panel is off before trying to change the mode. But also
>          * ensure that we have vdd while we switch off the panel. */
>         ironlake_edp_panel_vdd_on(intel_dp);
> +       intel_edp_psr_disable(intel_dp);
>         ironlake_edp_backlight_off(intel_dp);
>         intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
>         ironlake_edp_panel_off(intel_dp);
> @@ -1708,6 +1709,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
>         intel_dp_complete_link_train(intel_dp);
>         intel_dp_stop_link_train(intel_dp);
>         ironlake_edp_backlight_on(intel_dp);
> +       intel_edp_psr_enable(intel_dp);
>
>         if (IS_VALLEYVIEW(dev)) {
>                 struct intel_digital_port *dport =

Functions intel_enable_dp and intel_disable_dp are not used on
Haswell, so I guess we don't need those calls, right?

> --
> 1.8.1.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Enable/Disable PSR
  2013-06-28 19:31     ` Paulo Zanoni
@ 2013-07-01 20:40       ` Rodrigo Vivi
  2013-07-05 21:58         ` Paulo Zanoni
  2013-07-02  0:29       ` Rodrigo Vivi
  1 sibling, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-01 20:40 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, Jun 28, 2013 at 4:31 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> Hi
>
> 2013/6/28 Rodrigo Vivi <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.
>> v4: Fix identation and other style issues raised by checkpatch (by Paulo).
>>
>
> A few of the comments here were already present in previous reviews.
> If you think they're not needed, please reply saying why.

Thank you very much for reviewing it and for including old comments I
had missed.
I'm replying this email saying what I changed and explaining what I didn't.
updated patch coming later.

>
>
>> 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)
>
> I know our documentation explicitly says "0x80060000" and
> "0x01000000", but to me these magic values are just magic... I think
> we could try to reuse the same mechanism we use for the other aux
> messages. Check the usage of pack_aux inside intel_dp_aux_ch and also
> intel_dp_aux_native_write. Maybe this could be done in a follow-up
> patch. Jani gave a suggestion on how to implement this, see email "Re:
> [PATCH 5/9] drm/i915: Setup EDP PSR AUX Registers" from January 31.

I know this is just magic, but writing some values in some specific
aux dst is obfuscated magic.
At least the magic implemented here is documented somewhere and more
easy to understand.

>
>
>> +#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 dca8fa6..c10be94 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)
>
> This function should be static (or included in a .h file).

done.

>
>
>> +{
>> +       struct drm_device *dev = intel_dp_to_dev(intel_dp);
>
> Function intel_dp_to_dev calls dp_to_dig_port, but you're already
> calling dp_to_dig_port below. You could remove this intel_dp_to_dev
> call by reordering the definitions.

done.

>
>
>> +       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);
>
> We don't use this register for anything else on eDP, so instead of
> preserving its contents with this read we should just set the bits we
> want, zeroing everything else. We don't want to preserve bogus values.

done.

> Also, read below: if we move this code to mode_set time it will make
> even more sense.
>
>
>> +
>> +       /* As per eDP spec, wait for vblank to send SDP VSC packet */
>> +       intel_wait_for_vblank(dev, crtc->pipe);
>
> The spec says the SDP VSC packets should be sent during the vblank,
> but the HW does this automatically and intel_wait_for_vblank doesn't
> guarantee us anything regarding that. So that wait seems useless.
>
>
>> +
>> +       /* 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.*/
>
> My interpretation of the spec is that we need to wait until exactly
> after the VSync so we don't send incomplete packets, but we don't have
> a good way to do this, and intel_wait_for_vblank doesn't help us with
> that. If you take a look at the HDMI code you'll notice that we set
> the video DIP registers inside intel_hdmi_mode_set, because at that
> point the pipe is stopped and we don't need to worry about waiting for
> the exact vblank period. Perhaps we should do the same here: load the
> contents of the video dip registers at mode_set time? Is there any
> problem in keeping those values there even when PSR or the pipe is
> disabled?


By moving it to mode_set time I started to get some other bugs when
exiting PSR state.
Also on mode_set time you don't know if psr will be enabled or not and
maybe writting this vsc will be useless.
I understand vblank is not ideal, but it works and since we don't have
a wait_for_vsync implemented I prefer to stay with this version that
works.

>
>
>> +       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);
>
> The PSR enabling documentation says that the "HW also enables VSC DIP
> when required", so maybe we should not turn the
> VIDEO_DIP_ENABLE_VSC_HSW bit and see if the HW does that for us? My
> fear is that setting this unconditionally may make some panels
> confused. But I'm not really sure if the HW really sets this bit for
> us or just sends/stops-sending the DIP in case this bit is on.

unfortunately it didn't worked. we have to manually enable it back
when manually disabling it.

>
>
>> +       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) */
>
> If you implement our suggestion of replacing the magic 0x80060000
> value with code this magic msg_size will also disappear.

I don't see how. This is aux ctl, not aux data. Besides it is the same
used on dp_aux.

>
>
>> +
>> +       /* 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;
>
> Why are we using these 500us values? I couldn't find a place that
> tells us which ones to use.

just the default... useless and already removed.

>
>
>> +       }
>> +
>> +       /* 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);
>
> Do we have a workaround name for the line above? Damien recently made
> a nice effort to document all the WA names we implement. We should at
> least say this is a WA.

Unfortunately it is not documented on WA database.
MEM up mask came only from PM guide doc and HPD came from the hardest path...
I had to mask everything and unmasking one by one to find out why we
were getting the continuous psr exit.
I tried to unsed long and short hpd pulse as described in pm guide,
but it refuses to change. So I decided to mask that.

>
>
>> +
>> +       /* Disable unused interrupts */
>> +       I915_WRITE(GEN6_PMINTRMSK, GEN6_PM_RP_UP_EI_EXPIRED |
>> +                  GEN6_PM_RP_DOWN_EI_EXPIRED);
>
> The line above needs a very big comment explaining it. Also, I'm not
> sure the code is correct. Don't we need irq_lock or rps_lock, also
> adjust some dev_priv->xyz_iir variable? I'll leave the review of this
> line to Ben and Daniel since they're currently touching these things.

I checked this is useless in our case. removed.

>
>
>> +
>> +       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))
>
> One of the nice things about the modeset rework is that, for most of
> the display code, we don't call "enable" twice of "disable" twice. On
> a brief look at patch 11 it seems we do respect this, so how about you
> turn this check for intel_edp_is_psr_enabled into a WARN?

I tried to put WARN_ON but started to get warnings... not sure if this
is working.
Anyway, after I created update_psr, this can be enabled by disabled at
any time we need.
So I prefer to let it as it is.

>
>
>> +               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);
>
> Same as above: you could avoid intel_dp_to_dev since you're already
> calling dp_to_dig_port.

done.

>
>
>> +       struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
>> +       uint32_t val;
>> +
>> +       if (!intel_edp_is_psr_enabled(dev))
>> +               return;
>
> Same as above: replace the check above with a WARN?

same as above.

>
>
>> +
>> +       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);
>
> The spec says we need to wait for a vblank and then disable the VSC
> DIP. As stated above, it is not clear whether the hardware does this
> automatically or not. Also, do we need this at all? I imagine the spec
> says we need to wait for a vblank just to avoid sending incomplete
> DIPs, but on this case the intel_wait_for_vblank won't help us here.
> Maybe we could fully just enable/disable the bit at mode_set time and
> not worry about it later?

checked and removed. useless wait.

>
>
>> +}
>> +
>>  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..ff09c4c 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
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
>
> --
> Paulo Zanoni



--
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Match all PSR mode entry conditions before enabling it.
  2013-06-28 20:46     ` Paulo Zanoni
@ 2013-07-01 20:47       ` Rodrigo Vivi
  2013-07-05 20:32         ` Daniel Vetter
  2013-07-02  0:50       ` Rodrigo Vivi
  1 sibling, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-01 20:47 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Again, Thank you very much for your comments.

Replying what I did and why I didn't here and patches coming later.


On Fri, Jun 28, 2013 at 5:46 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> 2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>> v2: Prefer seq_puts to seq_printf by Paulo Zanoni.
>>
>> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>> ---
>>  drivers/gpu/drm/i915/i915_debugfs.c | 39 ++++++++++++++++++---
>>  drivers/gpu/drm/i915/i915_drv.h     | 12 +++++++
>>  drivers/gpu/drm/i915/intel_dp.c     | 68 ++++++++++++++++++++++++++++++++++++-
>>  3 files changed, 114 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
>> index 67c777f..95b27ac 100644
>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> @@ -1882,11 +1882,42 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>>         struct drm_info_node *node = m->private;
>>         struct drm_device *dev = node->minor->dev;
>>         struct drm_i915_private *dev_priv = dev->dev_private;
>> -       u32 psrctl, psrstat, psrperf;
>> +       u32 psrstat, psrperf;
>>
>> -       psrctl = I915_READ(EDP_PSR_CTL);
>> -       seq_printf(m, "PSR Enabled: %s\n",
>> -                  yesno(psrctl & EDP_PSR_ENABLE));
>> +       if (I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
>> +               seq_puts(m, "PSR enabled\n");
>> +       } else {
>> +               seq_puts(m, "PSR disabled: ");
>> +               switch (dev_priv->no_psr_reason) {
>> +               case PSR_NO_SOURCE:
>> +                       seq_puts(m, "not supported on this platform");
>> +                       break;
>> +               case PSR_NO_SINK:
>> +                       seq_puts(m, "not supported by panel");
>> +                       break;
>> +               case PSR_CRTC_NOT_ACTIVE:
>> +                       seq_puts(m, "crtc not active");
>> +                       break;
>> +               case PSR_PWR_WELL_ENABLED:
>> +                       seq_puts(m, "power well enabled");
>> +                       break;
>> +               case PSR_NOT_TILED:
>> +                       seq_puts(m, "not tiled");
>> +                       break;
>> +               case PSR_SPRITE_ENABLED:
>> +                       seq_puts(m, "sprite enabled");
>> +                       break;
>> +               case PSR_INTERLACED_ENABLED:
>> +                       seq_puts(m, "interlaced enabled");
>> +                       break;
>> +               case PSR_HSW_NOT_DDIA:
>> +                       seq_puts(m, "HSW ties PSR to DDI A (eDP)");
>> +                       break;
>> +               default:
>> +                       seq_puts(m, "unknown reason");
>> +               }
>> +               seq_puts(m, "\n");
>> +       }
>>
>>         psrstat = I915_READ(EDP_PSR_STATUS_CTL);
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index 56bd82b..f08c1d9 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -543,6 +543,17 @@ enum no_fbc_reason {
>>         FBC_CHIP_DEFAULT, /* disabled by default on this chip */
>>  };
>>
>> +enum no_psr_reason {
>> +       PSR_NO_SOURCE, /* Not supported on platform */
>> +       PSR_NO_SINK, /* Not supported by panel */
>> +       PSR_CRTC_NOT_ACTIVE,
>> +       PSR_PWR_WELL_ENABLED,
>> +       PSR_NOT_TILED,
>> +       PSR_SPRITE_ENABLED,
>> +       PSR_INTERLACED_ENABLED,
>> +       PSR_HSW_NOT_DDIA,
>
> I see you left a few reasons listed on the spec, for example S3D,
> which we don't support yet. I'm pretty sure that when we implement S3D
> we'll totally forget about adding the PSR_S3D_ENABLED condition, so
> shouldn't we do it now? Also, why did we not add the eDP hotplug
> reason?

Since it isn't implemented I'm not sure how to check that.
Maybe we will have a function, maybe just a bit in some register or
maybe somehow else.
So I prefer to stay without it until we have a proper way.

>
>
>> +};
>> +
>>  enum intel_pch {
>>         PCH_NONE = 0,   /* No PCH present */
>>         PCH_IBX,        /* Ibexpeak PCH */
>> @@ -1146,6 +1157,7 @@ typedef struct drm_i915_private {
>>         struct i915_power_well power_well;
>>
>>         enum no_fbc_reason no_fbc_reason;
>> +       enum no_psr_reason no_psr_reason;
>>
>>         struct drm_mm_node *compressed_fb;
>>         struct drm_mm_node *compressed_llb;
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index c10be94..9730d6b 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -1471,11 +1471,77 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
>>                    EDP_PSR_ENABLE);
>>  }
>>
>> +static bool intel_edp_psr_match_conditions(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 drm_crtc *crtc = dig_port->base.base.crtc;
>> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>> +       struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
>> +       struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
>
> Again, you have intel_dp_to_dev and also call dp_to_dig_port twice.

done.

>
>
>> +
>> +       if (!IS_HASWELL(dev)) {
>> +               DRM_DEBUG_KMS("PSR not supported on this platform\n");
>> +               dev_priv->no_psr_reason = PSR_NO_SOURCE;
>> +               return false;
>> +       }
>> +
>> +       if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
>> +           (enc_to_dig_port(&intel_encoder->base)->port != PORT_A)) {
>
> Here you're calling enc_to_dig_port, but you already defined dig_port
> above. Use it.

done

>
>
>> +               DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
>> +               dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
>> +               return false;
>> +       }
>> +
>> +       if (!is_edp_psr(intel_dp)) {
>> +               DRM_DEBUG_KMS("PSR not supported by this panel\n");
>> +               dev_priv->no_psr_reason = PSR_NO_SINK;
>> +               return false;
>> +       }
>> +
>> +       if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
>
> Why do we check for crtc->fb and crtc->mode.clock here? Also, there's
> intel_crtc->primary_disabled which you could use.

This is how it is done at update_fbc checking for active crtc and it
is properly workig.
So I prefer to let it like this.

>
>
>> +               DRM_DEBUG_KMS("crtc not active for PSR\n");
>> +               dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
>> +               return false;
>> +       }
>> +
>> +       if ((I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE) |
>
> I'd  use "||" instead of "|" at the end of the line since this is a
> logical statement.

done

>
>
>> +           (I915_READ(HSW_PWR_WELL_KVMR) & HSW_PWR_WELL_ENABLE)) {
>
> I know the spec says we should check for this, but there's absolutely
> no guarantee that the KVMr won't be enabled exactly after we read this
> bit. I don't know if there's a sane way to check for an active KVMr
> session. We should also probably get an interrupt somehow if someone
> enables KVMr after PSR is enabled.

You are right, it can be enabled by someone else later, but this will
only cause the continue PSR exit like mem up and hpd if they weren't
being masked.
So, this is just a check saying psr wont work if this is enabled but
not really needed to worry if this is enabled later. Wont break
anything for sure.

>
>
>> +               DRM_DEBUG_KMS("PSR condition failed: Power Well is Enabled\n");
>> +               dev_priv->no_psr_reason = PSR_PWR_WELL_ENABLED;
>> +               return false;
>> +       }
>> +
>> +       if (obj->tiling_mode != I915_TILING_X ||
>> +           obj->fence_reg == I915_FENCE_REG_NONE) {
>> +               DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
>> +               dev_priv->no_psr_reason = PSR_NOT_TILED;
>> +               return false;
>> +       }
>> +
>> +       if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
>
> We should probably check "struct intel_plane" instead of I915_READ here.

I prefer to stay this way that is the way used on
asser_sprite_disabled in intel_display.

>
>
>> +               DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
>> +               dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
>> +               return false;
>> +       }
>> +
>> +       if ((I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
>> +            PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
>
> I'd prefer checking for "crtc->mode.flags & DRM_MODE_FLAG_INTERLACE".

I prefer to stay this way that is the way used in intel_display.

>
>
>> +               DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
>> +               dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
>> +               return false;
>> +       }
>> +
>> +       return true;
>> +}
>> +
>>  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))
>> +       if (!intel_edp_psr_match_conditions(intel_dp) ||
>> +           intel_edp_is_psr_enabled(dev))
>>                 return;
>>
>>         /* Enable PSR on the panel */
>> --
>> 1.8.1.4
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
>
> --
> Paulo Zanoni



--
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Enable/Disable PSR
  2013-06-28 19:31     ` Paulo Zanoni
  2013-07-01 20:40       ` Rodrigo Vivi
@ 2013-07-02  0:29       ` Rodrigo Vivi
  2013-07-05 22:20         ` Paulo Zanoni
  1 sibling, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-02  0:29 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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.
v4: Fix identation and other style issues raised by checkpatch (by Paulo).
v5: Changes according to Paulo's review:
    static on write_vsc;
    avoid using dp_to_dev when already calling dp_to_dig_port;
    remove unecessary TP default time setting;
    remove unecessary interrupts disabling;
    remove unecessary wait_for_vblank whend disabling psr;

Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
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  | 136 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |   3 +
 3 files changed, 181 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 dca8fa6..5b49e31 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1356,6 +1356,142 @@ 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;
+}
+
+static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
+			     struct edp_vsc_psr *vsc_psr)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	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;
+
+	/* 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, ~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, 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;
+
+	/* 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);
+
+	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;
+
+	if (!intel_edp_is_psr_enabled(dev))
+		return;
+
+	I915_WRITE(EDP_PSR_CTL, I915_READ(EDP_PSR_CTL) & ~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");
+}
+
 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..ff09c4c 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

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Added debugfs support for PSR Status
  2013-06-28 20:14       ` Paulo Zanoni
@ 2013-07-02  0:46         ` Rodrigo Vivi
  0 siblings, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-02  0:46 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

Adding support for PSR Status, PSR entry counter and performance counters.
Heavily based on initial work from Shobhit.

v2: Fix PSR Status Link bits by Paulo Zanoni.
v3: Prefer seq_puts to seq_printf by Paulo Zanoni.
v4: Fix identation by Paulo Zanoni.
v5: Return earlier if it isn't Haswell in order to avoid reading non-existing
    registers - by Paulo Zanoni.

CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Credits-by: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 95 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h     | 24 ++++++++++
 2 files changed, 119 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a188624..bbdcdae 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1877,6 +1877,100 @@ static int i915_dpio_info(struct seq_file *m, void *data)
 	return 0;
 }
 
+static int i915_edp_psr_status(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 psrctl, psrstat, psrperf;
+
+	if (!IS_HASWELL(dev)) {
+		seq_puts(m, "PSR not supported on this platform\n");
+		return 0;
+	}
+
+	psrctl = I915_READ(EDP_PSR_CTL);
+	seq_printf(m, "PSR Enabled: %s\n",
+		   yesno(psrctl & EDP_PSR_ENABLE));
+
+	psrstat = I915_READ(EDP_PSR_STATUS_CTL);
+
+	seq_puts(m, "PSR Current State: ");
+	switch (psrstat & EDP_PSR_STATUS_STATE_MASK) {
+	case EDP_PSR_STATUS_STATE_IDLE:
+		seq_puts(m, "Reset state\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDONACK:
+		seq_puts(m, "Wait for TG/Stream to send on frame of data after SRD conditions are met\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDENT:
+		seq_puts(m, "SRD entry\n");
+		break;
+	case EDP_PSR_STATUS_STATE_BUFOFF:
+		seq_puts(m, "Wait for buffer turn off\n");
+		break;
+	case EDP_PSR_STATUS_STATE_BUFON:
+		seq_puts(m, "Wait for buffer turn on\n");
+		break;
+	case EDP_PSR_STATUS_STATE_AUXACK:
+		seq_puts(m, "Wait for AUX to acknowledge on SRD exit\n");
+		break;
+	case EDP_PSR_STATUS_STATE_SRDOFFACK:
+		seq_puts(m, "Wait for TG/Stream to acknowledge the SRD VDM exit\n");
+		break;
+	default:
+		seq_puts(m, "Unknown\n");
+		break;
+	}
+
+	seq_puts(m, "Link Status: ");
+	switch (psrstat & EDP_PSR_STATUS_LINK_MASK) {
+	case EDP_PSR_STATUS_LINK_FULL_OFF:
+		seq_puts(m, "Link is fully off\n");
+		break;
+	case EDP_PSR_STATUS_LINK_FULL_ON:
+		seq_puts(m, "Link is fully on\n");
+		break;
+	case EDP_PSR_STATUS_LINK_STANDBY:
+		seq_puts(m, "Link is in standby\n");
+		break;
+	default:
+		seq_puts(m, "Unknown\n");
+		break;
+	}
+
+	seq_printf(m, "PSR Entry Count: %u\n",
+		   psrstat >> EDP_PSR_STATUS_COUNT_SHIFT &
+		   EDP_PSR_STATUS_COUNT_MASK);
+
+	seq_printf(m, "Max Sleep Timer Counter: %u\n",
+		   psrstat >> EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT &
+		   EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK);
+
+	seq_printf(m, "Had AUX error: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_AUX_ERROR));
+
+	seq_printf(m, "Sending AUX: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_AUX_SENDING));
+
+	seq_printf(m, "Sending Idle: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_IDLE));
+
+	seq_printf(m, "Sending TP2 TP3: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_TP2_TP3));
+
+	seq_printf(m, "Sending TP1: %s\n",
+		   yesno(psrstat & EDP_PSR_STATUS_SENDING_TP1));
+
+	seq_printf(m, "Idle Count: %u\n",
+		   psrstat & EDP_PSR_STATUS_IDLE_MASK);
+
+	psrperf = (I915_READ(EDP_PSR_PERF_CNT)) & EDP_PSR_PERF_CNT_MASK;
+	seq_printf(m, "Performance Counter: %u\n", psrperf);
+
+	return 0;
+}
+
 static int
 i915_wedged_get(void *data, u64 *val)
 {
@@ -2306,6 +2400,7 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_swizzle_info", i915_swizzle_info, 0},
 	{"i915_ppgtt_info", i915_ppgtt_info, 0},
 	{"i915_dpio", i915_dpio_info, 0},
+	{"i915_edp_psr_status", i915_edp_psr_status, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index caf57d8..833cc97 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1812,6 +1812,30 @@
 
 #define EDP_PSR_STATUS_CTL			0x64840
 #define   EDP_PSR_STATUS_STATE_MASK		(7<<29)
+#define   EDP_PSR_STATUS_STATE_IDLE		(0<<29)
+#define   EDP_PSR_STATUS_STATE_SRDONACK		(1<<29)
+#define   EDP_PSR_STATUS_STATE_SRDENT		(2<<29)
+#define   EDP_PSR_STATUS_STATE_BUFOFF		(3<<29)
+#define   EDP_PSR_STATUS_STATE_BUFON		(4<<29)
+#define   EDP_PSR_STATUS_STATE_AUXACK		(5<<29)
+#define   EDP_PSR_STATUS_STATE_SRDOFFACK	(6<<29)
+#define   EDP_PSR_STATUS_LINK_MASK		(3<<26)
+#define   EDP_PSR_STATUS_LINK_FULL_OFF		(0<<26)
+#define   EDP_PSR_STATUS_LINK_FULL_ON		(1<<26)
+#define   EDP_PSR_STATUS_LINK_STANDBY		(2<<26)
+#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT	20
+#define   EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK	0x1f
+#define   EDP_PSR_STATUS_COUNT_SHIFT		16
+#define   EDP_PSR_STATUS_COUNT_MASK		0xf
+#define   EDP_PSR_STATUS_AUX_ERROR		(1<<15)
+#define   EDP_PSR_STATUS_AUX_SENDING		(1<<12)
+#define   EDP_PSR_STATUS_SENDING_IDLE		(1<<9)
+#define   EDP_PSR_STATUS_SENDING_TP2_TP3	(1<<8)
+#define   EDP_PSR_STATUS_SENDING_TP1		(1<<4)
+#define   EDP_PSR_STATUS_IDLE_MASK		0xf
+
+#define EDP_PSR_PERF_CNT		0x64844
+#define   EDP_PSR_PERF_CNT_MASK		0xffffff
 
 #define EDP_PSR_DEBUG_CTL		0x64860
 #define   EDP_PSR_DEBUG_MASK_LPSP	(1<<27)
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Match all PSR mode entry conditions before enabling it.
  2013-06-28 20:46     ` Paulo Zanoni
  2013-07-01 20:47       ` Rodrigo Vivi
@ 2013-07-02  0:50       ` Rodrigo Vivi
  1 sibling, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-02  0:50 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

v2: Prefer seq_puts to seq_printf by Paulo Zanoni.
v3: small changes like avoiding calling dp_to_dig_port twice as noticed by
    Paulo Zanoni.
v4: Avoiding reading non-existent registers - noticed by Paulo
    on first psr debugfs patch.

Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 41 ++++++++++++++++++----
 drivers/gpu/drm/i915/i915_drv.h     | 12 +++++++
 drivers/gpu/drm/i915/intel_dp.c     | 68 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 113 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index bbdcdae..154bd99 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1882,17 +1882,44 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 psrctl, psrstat, psrperf;
+	u32 psrstat, psrperf;
 
-	if (!IS_HASWELL(dev)) {
-		seq_puts(m, "PSR not supported on this platform\n");
+	if (IS_HASWELL(dev) && I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
+		seq_puts(m, "PSR enabled\n");
+	} else {
+		seq_puts(m, "PSR disabled: ");
+		switch (dev_priv->no_psr_reason) {
+		case PSR_NO_SOURCE:
+			seq_puts(m, "not supported on this platform");
+			break;
+		case PSR_NO_SINK:
+			seq_puts(m, "not supported by panel");
+			break;
+		case PSR_CRTC_NOT_ACTIVE:
+			seq_puts(m, "crtc not active");
+			break;
+		case PSR_PWR_WELL_ENABLED:
+			seq_puts(m, "power well enabled");
+			break;
+		case PSR_NOT_TILED:
+			seq_puts(m, "not tiled");
+			break;
+		case PSR_SPRITE_ENABLED:
+			seq_puts(m, "sprite enabled");
+			break;
+		case PSR_INTERLACED_ENABLED:
+			seq_puts(m, "interlaced enabled");
+			break;
+		case PSR_HSW_NOT_DDIA:
+			seq_puts(m, "HSW ties PSR to DDI A (eDP)");
+			break;
+		default:
+			seq_puts(m, "unknown reason");
+		}
+		seq_puts(m, "\n");
 		return 0;
 	}
 
-	psrctl = I915_READ(EDP_PSR_CTL);
-	seq_printf(m, "PSR Enabled: %s\n",
-		   yesno(psrctl & EDP_PSR_ENABLE));
-
 	psrstat = I915_READ(EDP_PSR_STATUS_CTL);
 
 	seq_puts(m, "PSR Current State: ");
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 56bd82b..f08c1d9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -543,6 +543,17 @@ enum no_fbc_reason {
 	FBC_CHIP_DEFAULT, /* disabled by default on this chip */
 };
 
+enum no_psr_reason {
+	PSR_NO_SOURCE, /* Not supported on platform */
+	PSR_NO_SINK, /* Not supported by panel */
+	PSR_CRTC_NOT_ACTIVE,
+	PSR_PWR_WELL_ENABLED,
+	PSR_NOT_TILED,
+	PSR_SPRITE_ENABLED,
+	PSR_INTERLACED_ENABLED,
+	PSR_HSW_NOT_DDIA,
+};
+
 enum intel_pch {
 	PCH_NONE = 0,	/* No PCH present */
 	PCH_IBX,	/* Ibexpeak PCH */
@@ -1146,6 +1157,7 @@ typedef struct drm_i915_private {
 	struct i915_power_well power_well;
 
 	enum no_fbc_reason no_fbc_reason;
+	enum no_psr_reason no_psr_reason;
 
 	struct drm_mm_node *compressed_fb;
 	struct drm_mm_node *compressed_llb;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 5b49e31..54e4c35 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1462,11 +1462,77 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
 		   EDP_PSR_ENABLE);
 }
 
+static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = dig_port->base.base.crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
+	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
+
+	if (!IS_HASWELL(dev)) {
+		DRM_DEBUG_KMS("PSR not supported on this platform\n");
+		dev_priv->no_psr_reason = PSR_NO_SOURCE;
+		return false;
+	}
+
+	if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
+	    (dig_port->port != PORT_A)) {
+		DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
+		dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
+		return false;
+	}
+
+	if (!is_edp_psr(intel_dp)) {
+		DRM_DEBUG_KMS("PSR not supported by this panel\n");
+		dev_priv->no_psr_reason = PSR_NO_SINK;
+		return false;
+	}
+
+	if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
+		DRM_DEBUG_KMS("crtc not active for PSR\n");
+		dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
+		return false;
+	}
+
+	if ((I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE) ||
+	    (I915_READ(HSW_PWR_WELL_KVMR) & HSW_PWR_WELL_ENABLE)) {
+		DRM_DEBUG_KMS("PSR condition failed: Power Well is Enabled\n");
+		dev_priv->no_psr_reason = PSR_PWR_WELL_ENABLED;
+		return false;
+	}
+
+	if (obj->tiling_mode != I915_TILING_X ||
+	    obj->fence_reg == I915_FENCE_REG_NONE) {
+		DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
+		dev_priv->no_psr_reason = PSR_NOT_TILED;
+		return false;
+	}
+
+	if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
+		DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
+		dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
+		return false;
+	}
+
+	if ((I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
+	     PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
+		DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
+		dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
+		return false;
+	}
+
+	return true;
+}
+
 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))
+	if (!intel_edp_psr_match_conditions(intel_dp) ||
+	    intel_edp_is_psr_enabled(dev))
 		return;
 
 	/* Enable PSR on the panel */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH] drm/i915: Hook PSR functionality
  2013-06-28 21:00   ` Paulo Zanoni
@ 2013-07-02  0:52     ` Rodrigo Vivi
  2013-07-08 13:13       ` Paulo Zanoni
  0 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-02  0:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

PSR must be enabled after transcoder and port are running.
And it is only available for HSW.

v2: move enable/disable to intel_ddi
v3: The spec suggests PSR should be disabled even before backlight (by pzanoni)
v4: also disabling and enabling whenever panel is disabled/enabled.
v5: make it last patch to avoid breaking whenever bisecting. So calling for
    update and force exit came to this patch along with enable/disable calls.
v6: Remove unused and unecessary psr_enable/disable calls, as notice by Paulo.

CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
---
 drivers/gpu/drm/i915/i915_gem.c      | 2 ++
 drivers/gpu/drm/i915/intel_ddi.c     | 2 ++
 drivers/gpu/drm/i915/intel_display.c | 1 +
 3 files changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index c68b90f..f2e135b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3786,6 +3786,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 		goto unlock;
 	}
 
+	intel_edp_psr_force_exit(dev);
+
 	/* Count all active objects as busy, even if they are currently not used
 	 * by the gpu. Users of this interface expect objects to eventually
 	 * become non-busy without any further actions, therefore emit any
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 324211a..4211925 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1117,6 +1117,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
 			intel_dp_stop_link_train(intel_dp);
 
 		ironlake_edp_backlight_on(intel_dp);
+		intel_edp_psr_enable(intel_dp);
 	}
 
 	if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
@@ -1147,6 +1148,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
 	if (type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
+		intel_edp_psr_disable(intel_dp);
 		ironlake_edp_backlight_off(intel_dp);
 	}
 }
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6fafa43..5bbfed0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2236,6 +2236,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 	}
 
 	intel_update_fbc(dev);
+	intel_edp_psr_update(dev);
 	mutex_unlock(&dev->struct_mutex);
 
 	intel_crtc_update_sarea_pos(crtc, x, y);
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Match all PSR mode entry conditions before enabling it.
  2013-07-01 20:47       ` Rodrigo Vivi
@ 2013-07-05 20:32         ` Daniel Vetter
  2013-07-08 22:25           ` Rodrigo Vivi
  0 siblings, 1 reply; 53+ messages in thread
From: Daniel Vetter @ 2013-07-05 20:32 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

On Mon, Jul 01, 2013 at 05:47:39PM -0300, Rodrigo Vivi wrote:
> Again, Thank you very much for your comments.
> 
> Replying what I did and why I didn't here and patches coming later.

Paulo asked me to drop by maintainer bikeshed on this patch. So here I'l
comply ;-)

> 
> 
> On Fri, Jun 28, 2013 at 5:46 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> > 2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> >> v2: Prefer seq_puts to seq_printf by Paulo Zanoni.
> >>
> >> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> >> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> >> ---
> >>  drivers/gpu/drm/i915/i915_debugfs.c | 39 ++++++++++++++++++---
> >>  drivers/gpu/drm/i915/i915_drv.h     | 12 +++++++
> >>  drivers/gpu/drm/i915/intel_dp.c     | 68 ++++++++++++++++++++++++++++++++++++-
> >>  3 files changed, 114 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> >> index 67c777f..95b27ac 100644
> >> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> >> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> >> @@ -1882,11 +1882,42 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
> >>         struct drm_info_node *node = m->private;
> >>         struct drm_device *dev = node->minor->dev;
> >>         struct drm_i915_private *dev_priv = dev->dev_private;
> >> -       u32 psrctl, psrstat, psrperf;
> >> +       u32 psrstat, psrperf;
> >>
> >> -       psrctl = I915_READ(EDP_PSR_CTL);
> >> -       seq_printf(m, "PSR Enabled: %s\n",
> >> -                  yesno(psrctl & EDP_PSR_ENABLE));
> >> +       if (I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
> >> +               seq_puts(m, "PSR enabled\n");
> >> +       } else {
> >> +               seq_puts(m, "PSR disabled: ");
> >> +               switch (dev_priv->no_psr_reason) {
> >> +               case PSR_NO_SOURCE:
> >> +                       seq_puts(m, "not supported on this platform");
> >> +                       break;
> >> +               case PSR_NO_SINK:
> >> +                       seq_puts(m, "not supported by panel");
> >> +                       break;
> >> +               case PSR_CRTC_NOT_ACTIVE:
> >> +                       seq_puts(m, "crtc not active");
> >> +                       break;
> >> +               case PSR_PWR_WELL_ENABLED:
> >> +                       seq_puts(m, "power well enabled");
> >> +                       break;
> >> +               case PSR_NOT_TILED:
> >> +                       seq_puts(m, "not tiled");
> >> +                       break;
> >> +               case PSR_SPRITE_ENABLED:
> >> +                       seq_puts(m, "sprite enabled");
> >> +                       break;
> >> +               case PSR_INTERLACED_ENABLED:
> >> +                       seq_puts(m, "interlaced enabled");
> >> +                       break;
> >> +               case PSR_HSW_NOT_DDIA:
> >> +                       seq_puts(m, "HSW ties PSR to DDI A (eDP)");
> >> +                       break;
> >> +               default:
> >> +                       seq_puts(m, "unknown reason");
> >> +               }
> >> +               seq_puts(m, "\n");
> >> +       }
> >>
> >>         psrstat = I915_READ(EDP_PSR_STATUS_CTL);
> >>
> >> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> >> index 56bd82b..f08c1d9 100644
> >> --- a/drivers/gpu/drm/i915/i915_drv.h
> >> +++ b/drivers/gpu/drm/i915/i915_drv.h
> >> @@ -543,6 +543,17 @@ enum no_fbc_reason {
> >>         FBC_CHIP_DEFAULT, /* disabled by default on this chip */
> >>  };
> >>
> >> +enum no_psr_reason {
> >> +       PSR_NO_SOURCE, /* Not supported on platform */
> >> +       PSR_NO_SINK, /* Not supported by panel */
> >> +       PSR_CRTC_NOT_ACTIVE,
> >> +       PSR_PWR_WELL_ENABLED,
> >> +       PSR_NOT_TILED,
> >> +       PSR_SPRITE_ENABLED,
> >> +       PSR_INTERLACED_ENABLED,
> >> +       PSR_HSW_NOT_DDIA,
> >
> > I see you left a few reasons listed on the spec, for example S3D,
> > which we don't support yet. I'm pretty sure that when we implement S3D
> > we'll totally forget about adding the PSR_S3D_ENABLED condition, so
> > shouldn't we do it now? Also, why did we not add the eDP hotplug
> > reason?
> 
> Since it isn't implemented I'm not sure how to check that.
> Maybe we will have a function, maybe just a bit in some register or
> maybe somehow else.
> So I prefer to stay without it until we have a proper way.

Imo adding the S3D_ENABLED reason is good, since that increases the
chances that we won'd forget about it. Maybe even add a comment in the
psr_match_conditions function below saying that we need to do this.

Wrt hotplug I've just chatted a bit and it sounds like the hw doesn't like
our hpd setup for port A. I guess we should fix that up first ...

> 
> >
> >
> >> +};
> >> +
> >>  enum intel_pch {
> >>         PCH_NONE = 0,   /* No PCH present */
> >>         PCH_IBX,        /* Ibexpeak PCH */
> >> @@ -1146,6 +1157,7 @@ typedef struct drm_i915_private {
> >>         struct i915_power_well power_well;
> >>
> >>         enum no_fbc_reason no_fbc_reason;
> >> +       enum no_psr_reason no_psr_reason;
> >>
> >>         struct drm_mm_node *compressed_fb;
> >>         struct drm_mm_node *compressed_llb;
> >> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> >> index c10be94..9730d6b 100644
> >> --- a/drivers/gpu/drm/i915/intel_dp.c
> >> +++ b/drivers/gpu/drm/i915/intel_dp.c
> >> @@ -1471,11 +1471,77 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
> >>                    EDP_PSR_ENABLE);
> >>  }
> >>
> >> +static bool intel_edp_psr_match_conditions(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 drm_crtc *crtc = dig_port->base.base.crtc;
> >> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >> +       struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
> >> +       struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
> >
> > Again, you have intel_dp_to_dev and also call dp_to_dig_port twice.
> 
> done.
> 
> >
> >
> >> +
> >> +       if (!IS_HASWELL(dev)) {
> >> +               DRM_DEBUG_KMS("PSR not supported on this platform\n");
> >> +               dev_priv->no_psr_reason = PSR_NO_SOURCE;
> >> +               return false;
> >> +       }
> >> +
> >> +       if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
> >> +           (enc_to_dig_port(&intel_encoder->base)->port != PORT_A)) {
> >
> > Here you're calling enc_to_dig_port, but you already defined dig_port
> > above. Use it.
> 
> done

Just to check: Does this really work for DDI port D with dekstop eDP? I'm
pretty sure you actually want to check for cpu_transcoder = EPD here ...

> 
> >
> >
> >> +               DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
> >> +               dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
> >> +               return false;
> >> +       }
> >> +
> >> +       if (!is_edp_psr(intel_dp)) {
> >> +               DRM_DEBUG_KMS("PSR not supported by this panel\n");
> >> +               dev_priv->no_psr_reason = PSR_NO_SINK;
> >> +               return false;
> >> +       }
> >> +
> >> +       if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
> >
> > Why do we check for crtc->fb and crtc->mode.clock here? Also, there's
> > intel_crtc->primary_disabled which you could use.
> 
> This is how it is done at update_fbc checking for active crtc and it
> is properly workig.
> So I prefer to let it like this.

That check is to avoid division-by-zero on state we've taken over from the
BIOS. Since we should only ever enable psr after a modeset that should be
a problem.

Now one thing which is a bit urky here with the psr code (same
comment applies to the fbc code really) is that a lot of the conditions
here _never_ change between modesets. So I think a ->fbc_possible and a
->psr_possible flag in pipe_config would make an awful lot of sense.

But I guess we can do that later on, once it's a bit clearer how this will
all work out.

> 
> >
> >
> >> +               DRM_DEBUG_KMS("crtc not active for PSR\n");
> >> +               dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
> >> +               return false;
> >> +       }
> >> +
> >> +       if ((I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE) |
> >
> > I'd  use "||" instead of "|" at the end of the line since this is a
> > logical statement.
> 
> done
> 
> >
> >
> >> +           (I915_READ(HSW_PWR_WELL_KVMR) & HSW_PWR_WELL_ENABLE)) {
> >
> > I know the spec says we should check for this, but there's absolutely
> > no guarantee that the KVMr won't be enabled exactly after we read this
> > bit. I don't know if there's a sane way to check for an active KVMr
> > session. We should also probably get an interrupt somehow if someone
> > enables KVMr after PSR is enabled.
> 
> You are right, it can be enabled by someone else later, but this will
> only cause the continue PSR exit like mem up and hpd if they weren't
> being masked.
> So, this is just a check saying psr wont work if this is enabled but
> not really needed to worry if this is enabled later. Wont break
> anything for sure.

tbh I don't understand why we need to check for the power well at all.
Is this really a hw requirement?

Paulo is right that we can't check for the power well enabling from the
kvmr in a race-free manner, so this needs some more thinking.

> 
> >
> >
> >> +               DRM_DEBUG_KMS("PSR condition failed: Power Well is Enabled\n");
> >> +               dev_priv->no_psr_reason = PSR_PWR_WELL_ENABLED;
> >> +               return false;
> >> +       }
> >> +
> >> +       if (obj->tiling_mode != I915_TILING_X ||
> >> +           obj->fence_reg == I915_FENCE_REG_NONE) {
> >> +               DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
> >> +               dev_priv->no_psr_reason = PSR_NOT_TILED;
> >> +               return false;
> >> +       }
> >> +
> >> +       if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
> >
> > We should probably check "struct intel_plane" instead of I915_READ here.
> 
> I prefer to stay this way that is the way used on
> asser_sprite_disabled in intel_display.

I agree with paulo, pls check sw tracked state, not hw state. If we move
to state precomputation and similar tricks you simply can't rely on the hw
state. Similar comment applies to the power well check above (if we really
need that one, I kinda expect that this is not so).

> 
> >
> >
> >> +               DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
> >> +               dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
> >> +               return false;
> >> +       }
> >> +
> >> +       if ((I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
> >> +            PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
> >
> > I'd prefer checking for "crtc->mode.flags & DRM_MODE_FLAG_INTERLACE".
> 
> I prefer to stay this way that is the way used in intel_display.

Where? Again I think we should use sw tracked state ...

> 
> >
> >
> >> +               DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
> >> +               dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
> >> +               return false;
> >> +       }
> >> +
> >> +       return true;
> >> +}
> >> +
> >>  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))
> >> +       if (!intel_edp_psr_match_conditions(intel_dp) ||
> >> +           intel_edp_is_psr_enabled(dev))
> >>                 return;
> >>
> >>         /* Enable PSR on the panel */
> >> --
> >> 1.8.1.4
> >>
> >> _______________________________________________
> >> Intel-gfx mailing list
> >> Intel-gfx@lists.freedesktop.org
> >> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> >
> >
> >
> > --
> > Paulo Zanoni
> 
> 
> 
> --
> Rodrigo Vivi
> Blog: http://blog.vivi.eng.br
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Enable/Disable PSR
  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
  0 siblings, 2 replies; 53+ messages in thread
From: Paulo Zanoni @ 2013-07-05 21:58 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx

Hi

Sorry for the delay.

2013/7/1 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> On Fri, Jun 28, 2013 at 4:31 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>> Hi
>>
>> 2013/6/28 Rodrigo Vivi <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.
>>> v4: Fix identation and other style issues raised by checkpatch (by Paulo).
>>>
>>
>> A few of the comments here were already present in previous reviews.
>> If you think they're not needed, please reply saying why.
>
> Thank you very much for reviewing it and for including old comments I
> had missed.
> I'm replying this email saying what I changed and explaining what I didn't.
> updated patch coming later.
>
>>
>>
>>> 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)
>>
>> I know our documentation explicitly says "0x80060000" and
>> "0x01000000", but to me these magic values are just magic... I think
>> we could try to reuse the same mechanism we use for the other aux
>> messages. Check the usage of pack_aux inside intel_dp_aux_ch and also
>> intel_dp_aux_native_write. Maybe this could be done in a follow-up
>> patch. Jani gave a suggestion on how to implement this, see email "Re:
>> [PATCH 5/9] drm/i915: Setup EDP PSR AUX Registers" from January 31.
>
> I know this is just magic, but writing some values in some specific
> aux dst is obfuscated magic.
> At least the magic implemented here is documented somewhere and more
> easy to understand.
>
>>
>>
>>> +#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 dca8fa6..c10be94 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)
>>
>> This function should be static (or included in a .h file).
>
> done.
>
>>
>>
>>> +{
>>> +       struct drm_device *dev = intel_dp_to_dev(intel_dp);
>>
>> Function intel_dp_to_dev calls dp_to_dig_port, but you're already
>> calling dp_to_dig_port below. You could remove this intel_dp_to_dev
>> call by reordering the definitions.
>
> done.
>
>>
>>
>>> +       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);
>>
>> We don't use this register for anything else on eDP, so instead of
>> preserving its contents with this read we should just set the bits we
>> want, zeroing everything else. We don't want to preserve bogus values.
>
> done.
>
>> Also, read below: if we move this code to mode_set time it will make
>> even more sense.
>>
>>
>>> +
>>> +       /* As per eDP spec, wait for vblank to send SDP VSC packet */
>>> +       intel_wait_for_vblank(dev, crtc->pipe);
>>
>> The spec says the SDP VSC packets should be sent during the vblank,
>> but the HW does this automatically and intel_wait_for_vblank doesn't
>> guarantee us anything regarding that. So that wait seems useless.
>>
>>
>>> +
>>> +       /* 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.*/
>>
>> My interpretation of the spec is that we need to wait until exactly
>> after the VSync so we don't send incomplete packets, but we don't have
>> a good way to do this, and intel_wait_for_vblank doesn't help us with
>> that. If you take a look at the HDMI code you'll notice that we set
>> the video DIP registers inside intel_hdmi_mode_set, because at that
>> point the pipe is stopped and we don't need to worry about waiting for
>> the exact vblank period. Perhaps we should do the same here: load the
>> contents of the video dip registers at mode_set time? Is there any
>> problem in keeping those values there even when PSR or the pipe is
>> disabled?
>
>
> By moving it to mode_set time I started to get some other bugs when
> exiting PSR state.
> Also on mode_set time you don't know if psr will be enabled or not and
> maybe writting this vsc will be useless.
> I understand vblank is not ideal, but it works and since we don't have
> a wait_for_vsync implemented I prefer to stay with this version that
> works.

What if we just remove the wait_for_vblank line since it doesn't
really seem to help us and may make us skip a few frames? The best
thing is probably to write the wait_for_vsync function anyway.


>
>>
>>
>>> +       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);
>>
>> The PSR enabling documentation says that the "HW also enables VSC DIP
>> when required", so maybe we should not turn the
>> VIDEO_DIP_ENABLE_VSC_HSW bit and see if the HW does that for us? My
>> fear is that setting this unconditionally may make some panels
>> confused. But I'm not really sure if the HW really sets this bit for
>> us or just sends/stops-sending the DIP in case this bit is on.
>
> unfortunately it didn't worked. we have to manually enable it back
> when manually disabling it.
>
>>
>>
>>> +       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) */
>>
>> If you implement our suggestion of replacing the magic 0x80060000
>> value with code this magic msg_size will also disappear.
>
> I don't see how. This is aux ctl, not aux data. Besides it is the same
> used on dp_aux.
>
>>
>>
>>> +
>>> +       /* 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;
>>
>> Why are we using these 500us values? I couldn't find a place that
>> tells us which ones to use.
>
> just the default... useless and already removed.

I think we should try to discover what is the correct value to write here.


>
>>
>>
>>> +       }
>>> +
>>> +       /* 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);
>>
>> Do we have a workaround name for the line above? Damien recently made
>> a nice effort to document all the WA names we implement. We should at
>> least say this is a WA.
>
> Unfortunately it is not documented on WA database.
> MEM up mask came only from PM guide doc and HPD came from the hardest path...
> I had to mask everything and unmasking one by one to find out why we
> were getting the continuous psr exit.
> I tried to unsed long and short hpd pulse as described in pm guide,
> but it refuses to change. So I decided to mask that.

Did you check if we had a pending interrupt to clear?

>
>>
>>
>>> +
>>> +       /* Disable unused interrupts */
>>> +       I915_WRITE(GEN6_PMINTRMSK, GEN6_PM_RP_UP_EI_EXPIRED |
>>> +                  GEN6_PM_RP_DOWN_EI_EXPIRED);
>>
>> The line above needs a very big comment explaining it. Also, I'm not
>> sure the code is correct. Don't we need irq_lock or rps_lock, also
>> adjust some dev_priv->xyz_iir variable? I'll leave the review of this
>> line to Ben and Daniel since they're currently touching these things.
>
> I checked this is useless in our case. removed.
>

Ok, looks like it's just in case PSR is continuously existing...

>>
>>
>>> +
>>> +       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))
>>
>> One of the nice things about the modeset rework is that, for most of
>> the display code, we don't call "enable" twice of "disable" twice. On
>> a brief look at patch 11 it seems we do respect this, so how about you
>> turn this check for intel_edp_is_psr_enabled into a WARN?
>
> I tried to put WARN_ON but started to get warnings... not sure if this
> is working.
> Anyway, after I created update_psr, this can be enabled by disabled at
> any time we need.
> So I prefer to let it as it is.
>
>>
>>
>>> +               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);
>>
>> Same as above: you could avoid intel_dp_to_dev since you're already
>> calling dp_to_dig_port.
>
> done.
>
>>
>>
>>> +       struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
>>> +       uint32_t val;
>>> +
>>> +       if (!intel_edp_is_psr_enabled(dev))
>>> +               return;
>>
>> Same as above: replace the check above with a WARN?
>
> same as above.
>
>>
>>
>>> +
>>> +       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);
>>
>> The spec says we need to wait for a vblank and then disable the VSC
>> DIP. As stated above, it is not clear whether the hardware does this
>> automatically or not. Also, do we need this at all? I imagine the spec
>> says we need to wait for a vblank just to avoid sending incomplete
>> DIPs, but on this case the intel_wait_for_vblank won't help us here.
>> Maybe we could fully just enable/disable the bit at mode_set time and
>> not worry about it later?
>
> checked and removed. useless wait.

But now you're never disabling the VSC DIP bit.

Anyway, I re-applied your latest patches and had a few small conflicts
on many patches. Most of the conflicts were due to changes in your own
patches. Maybe it should be good to rebase everything and resend...

By the way, things are still working on my machine :)

>
>>
>>
>>> +}
>>> +
>>>  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..ff09c4c 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
>>>
>>> _______________________________________________
>>> Intel-gfx mailing list
>>> Intel-gfx@lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>>
>>
>> --
>> Paulo Zanoni
>
>
>
> --
> Rodrigo Vivi
> Blog: http://blog.vivi.eng.br



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Enable/Disable PSR
  2013-07-05 21:58         ` Paulo Zanoni
@ 2013-07-05 22:14           ` Daniel Vetter
  2013-07-08 22:09           ` Rodrigo Vivi
  1 sibling, 0 replies; 53+ messages in thread
From: Daniel Vetter @ 2013-07-05 22:14 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, Jul 5, 2013 at 11:58 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>>> My interpretation of the spec is that we need to wait until exactly
>>> after the VSync so we don't send incomplete packets, but we don't have
>>> a good way to do this, and intel_wait_for_vblank doesn't help us with
>>> that. If you take a look at the HDMI code you'll notice that we set
>>> the video DIP registers inside intel_hdmi_mode_set, because at that
>>> point the pipe is stopped and we don't need to worry about waiting for
>>> the exact vblank period. Perhaps we should do the same here: load the
>>> contents of the video dip registers at mode_set time? Is there any
>>> problem in keeping those values there even when PSR or the pipe is
>>> disabled?
>>
>>
>> By moving it to mode_set time I started to get some other bugs when
>> exiting PSR state.
>> Also on mode_set time you don't know if psr will be enabled or not and
>> maybe writting this vsc will be useless.
>> I understand vblank is not ideal, but it works and since we don't have
>> a wait_for_vsync implemented I prefer to stay with this version that
>> works.
>
> What if we just remove the wait_for_vblank line since it doesn't
> really seem to help us and may make us skip a few frames? The best
> thing is probably to write the wait_for_vsync function anyway.

Chris and Ville are both working on vblank_work and vblank_tasklets
that are fired off from the interrupt handler at vblank time. Those
could be rather useful, and I expect that we'll use them a _lot_ to
avoid many of the wait_vblanks we currently have towards the end of
our modeset sequence (e.g. for fbc, ips, infoframes if we start to set
them when the pipe is life, which we kinda have to for fastboot ...).
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Enable/Disable PSR
  2013-07-02  0:29       ` Rodrigo Vivi
@ 2013-07-05 22:20         ` Paulo Zanoni
  0 siblings, 0 replies; 53+ messages in thread
From: Paulo Zanoni @ 2013-07-05 22:20 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

2013/7/1 Rodrigo Vivi <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.
> v4: Fix identation and other style issues raised by checkpatch (by Paulo).
> v5: Changes according to Paulo's review:
>     static on write_vsc;
>     avoid using dp_to_dev when already calling dp_to_dig_port;
>     remove unecessary TP default time setting;
>     remove unecessary interrupts disabling;
>     remove unecessary wait_for_vblank whend disabling psr;
>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 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  | 136 +++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h |   3 +
>  3 files changed, 181 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 dca8fa6..5b49e31 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1356,6 +1356,142 @@ 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;
> +}
> +
> +static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
> +                            struct edp_vsc_psr *vsc_psr)
> +{
> +       struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +       struct drm_device *dev = dig_port->base.base.dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       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;
> +
> +       /* 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, ~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, 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;
> +
> +       /* 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);
> +
> +       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;
> +
> +       if (!intel_edp_is_psr_enabled(dev))
> +               return;
> +
> +       I915_WRITE(EDP_PSR_CTL, I915_READ(EDP_PSR_CTL) & ~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");

We do this wait while the pipe is running, right? I'm kinda afraid to
do these sleeps/waits after the mode set...


> +}
> +
>  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..ff09c4c 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
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: add update function to disable/enable-back PSR
  2013-06-28 17:44   ` [PATCH] " Rodrigo Vivi
@ 2013-07-05 22:48     ` Paulo Zanoni
  2013-07-08 21:52       ` Rodrigo Vivi
  0 siblings, 1 reply; 53+ messages in thread
From: Paulo Zanoni @ 2013-07-05 22:48 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> Required function to disable PSR when going to console mode.
> But also can be used whenever PSR mode entry conditions changed.
>
> v2: Add it before PSR Hook. Update function not really been called yet.
> v3: Fix coding style detected by checkpatch by Paulo Zanoni.
>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c  | 37 ++++++++++++++++++++++++++++++-------
>  drivers/gpu/drm/i915/intel_drv.h |  1 +
>  2 files changed, 31 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 9730d6b..86c1a7d 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1536,14 +1536,8 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
>         return true;
>  }
>
> -void intel_edp_psr_enable(struct intel_dp *intel_dp)
> +void intel_edp_psr_do_enable(struct intel_dp *intel_dp)

Then this function should become static.

So, how often do we disable/enable or update after a mode set? I see
that on enable_sink we reset the VSC header, rewrite the AUX
registers, also reset EDP_PSR_DEBUG_CTL and reupdate everything inside
EDP_PSR_CTL. Do we need to redo all this? Don't we just need to redo
the aux_native_write to DP_PSR_EN_CFG and re-enable EDP_PSR_ENABLE
since everything else might still be the same on the same mode-set?

>  {
> -       struct drm_device *dev = intel_dp_to_dev(intel_dp);
> -
> -       if (!intel_edp_psr_match_conditions(intel_dp) ||
> -           intel_edp_is_psr_enabled(dev))
> -               return;
> -
>         /* Enable PSR on the panel */
>         intel_edp_psr_enable_sink(intel_dp);
>
> @@ -1551,6 +1545,15 @@ void intel_edp_psr_enable(struct intel_dp *intel_dp)
>         intel_edp_psr_enable_source(intel_dp);
>  }
>
> +void intel_edp_psr_enable(struct intel_dp *intel_dp)
> +{
> +       struct drm_device *dev = intel_dp_to_dev(intel_dp);
> +
> +       if (intel_edp_psr_match_conditions(intel_dp) &&
> +           !intel_edp_is_psr_enabled(dev))
> +               intel_edp_psr_do_enable(intel_dp);
> +}
> +
>  void intel_edp_psr_disable(struct intel_dp *intel_dp)
>  {
>         struct drm_device *dev = intel_dp_to_dev(intel_dp);
> @@ -1573,6 +1576,26 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
>         intel_wait_for_vblank(dev, intel_crtc->pipe);
>  }
>
> +void intel_edp_psr_update(struct drm_device *dev)
> +{
> +       struct intel_encoder *encoder;
> +       struct intel_dp *intel_dp = NULL;
> +
> +       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
> +               if (encoder->type == INTEL_OUTPUT_EDP) {
> +                       intel_dp = enc_to_intel_dp(&encoder->base);
> +
> +                       if (!is_edp_psr(intel_dp))
> +                               return;
> +
> +                       if (!intel_edp_psr_match_conditions(intel_dp))
> +                               intel_edp_psr_disable(intel_dp);
> +                       else
> +                               if (!intel_edp_is_psr_enabled(dev))
> +                                       intel_edp_psr_do_enable(intel_dp);
> +               }
> +}
> +
>  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 ff09c4c..1f638cf 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -842,5 +842,6 @@ extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
>
>  extern void intel_edp_psr_enable(struct intel_dp *intel_dp);
>  extern void intel_edp_psr_disable(struct intel_dp *intel_dp);
> +extern void intel_edp_psr_update(struct drm_device *dev);
>
>  #endif /* __INTEL_DRV_H__ */
> --
> 1.8.1.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/intel: add enable_psr module option
  2013-06-28 17:47   ` [PATCH] " Rodrigo Vivi
@ 2013-07-08 12:45     ` Paulo Zanoni
  0 siblings, 0 replies; 53+ messages in thread
From: Paulo Zanoni @ 2013-07-08 12:45 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx

2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> PSR is enabled by default but can be disabled.
>
> v2: prefer seq_puts to seq_printf detected by Paulo Zanoni.
>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 3 +++
>  drivers/gpu/drm/i915/i915_drv.c     | 4 ++++
>  drivers/gpu/drm/i915/i915_drv.h     | 2 ++
>  drivers/gpu/drm/i915/intel_dp.c     | 6 ++++++
>  4 files changed, 15 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 95b27ac..9d8d789 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1895,6 +1895,9 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>                 case PSR_NO_SINK:
>                         seq_puts(m, "not supported by panel");
>                         break;
> +               case PSR_MODULE_PARAM:
> +                       seq_puts(m, "disabled by flag");
> +                       break;
>                 case PSR_CRTC_NOT_ACTIVE:
>                         seq_puts(m, "crtc not active");
>                         break;
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 062cbda..7920c6f 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -118,6 +118,10 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
>  MODULE_PARM_DESC(i915_enable_ppgtt,
>                 "Enable PPGTT (default: true)");
>
> +int i915_enable_psr __read_mostly = 1;
> +module_param_named(enable_psr, i915_enable_psr, int, 0600);
> +MODULE_PARM_DESC(enable_psr, "Enable PSR (default: true)");
> +
>  unsigned int i915_preliminary_hw_support __read_mostly = 0;
>  module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
>  MODULE_PARM_DESC(preliminary_hw_support,
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index f08c1d9..dda992a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -546,6 +546,7 @@ enum no_fbc_reason {
>  enum no_psr_reason {
>         PSR_NO_SOURCE, /* Not supported on platform */
>         PSR_NO_SINK, /* Not supported by panel */
> +       PSR_MODULE_PARAM,
>         PSR_CRTC_NOT_ACTIVE,
>         PSR_PWR_WELL_ENABLED,
>         PSR_NOT_TILED,
> @@ -1555,6 +1556,7 @@ extern int i915_enable_rc6 __read_mostly;
>  extern int i915_enable_fbc __read_mostly;
>  extern bool i915_enable_hangcheck __read_mostly;
>  extern int i915_enable_ppgtt __read_mostly;
> +extern int i915_enable_psr __read_mostly;
>  extern unsigned int i915_preliminary_hw_support __read_mostly;
>  extern int i915_disable_power_well __read_mostly;
>  extern int i915_enable_ips __read_mostly;
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 86c1a7d..5d961cb 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1500,6 +1500,12 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
>                 return false;
>         }
>
> +       if (!i915_enable_psr) {
> +               DRM_DEBUG_KMS("PSR disable by flag\n");

disableD by flag?

With that fixed: Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> +               dev_priv->no_psr_reason = PSR_MODULE_PARAM;
> +               return false;
> +       }
> +
>         if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
>                 DRM_DEBUG_KMS("crtc not active for PSR\n");
>                 dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
> --
> 1.8.1.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Add functions to force psr exit
  2013-06-28 17:52     ` Rodrigo Vivi
  2013-06-28 17:57       ` Chris Wilson
@ 2013-07-08 13:03       ` Paulo Zanoni
  2013-07-08 21:48         ` Rodrigo Vivi
  1 sibling, 1 reply; 53+ messages in thread
From: Paulo Zanoni @ 2013-07-08 13:03 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx

2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> PSR tracking engine in HSW doesn't detect automagically some directly copy area
> operations through scanout so we will have to kick it manually and
> reschedule it to come back to normal operation as soon as possible.
>
> v2: Before PSR Hook. Don't force it when busy yet.
> v3/v4: Solved small conflict.
>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h  |  1 +
>  drivers/gpu/drm/i915/intel_dp.c  | 59 ++++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h |  4 +++
>  3 files changed, 64 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 833cc97..a19245b 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1838,6 +1838,7 @@
>  #define   EDP_PSR_PERF_CNT_MASK                0xffffff
>
>  #define EDP_PSR_DEBUG_CTL              0x64860
> +#define   EDP_PSR_DEBUG_FORCE_EXIT     (3<<30)

Can you please explain why we're using the debug register here?
Usually the debug register is only used for debugging, not as part of
the normal operation. Why can't we do normal/full PSR exit/enter here
using SRD_CTL bit 31 and the enable/disable sequences? What is
different?


>  #define   EDP_PSR_DEBUG_MASK_LPSP      (1<<27)
>  #define   EDP_PSR_DEBUG_MASK_MEMUP     (1<<26)
>  #define   EDP_PSR_DEBUG_MASK_HPD       (1<<25)
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 68c81ab..5001fd9 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1366,6 +1366,48 @@ bool intel_edp_is_psr_enabled(struct drm_device *dev)
>         return I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
>  }
>
> +static void intel_edp_psr_delayed_normal_work(struct work_struct *__work)
> +{
> +       struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
> +                                                struct intel_dp,
> +                                                edp_psr_delayed_normal_work);
> +       struct drm_device *dev = intel_dp_to_dev(intel_dp);
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       mutex_lock(&intel_dp->psr_exit_mutex);
> +       I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) &
> +                  ~EDP_PSR_DEBUG_FORCE_EXIT);
> +       mutex_unlock(&intel_dp->psr_exit_mutex);
> +}
> +
> +void intel_edp_psr_force_exit(struct drm_device *dev)
> +{
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       struct intel_encoder *encoder;
> +       struct intel_dp *intel_dp = NULL;
> +
> +       if (!intel_edp_is_psr_enabled(dev))
> +               return;
> +
> +       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
> +               if (encoder->type == INTEL_OUTPUT_EDP)
> +                       intel_dp = enc_to_intel_dp(&encoder->base);
> +
> +       if (!intel_dp)
> +               return;
> +
> +       if (WARN_ON(!intel_dp->psr_setup_done))
> +               return;
> +
> +       mutex_lock(&intel_dp->psr_exit_mutex);
> +       I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) |
> +                  EDP_PSR_DEBUG_FORCE_EXIT);
> +       mutex_unlock(&intel_dp->psr_exit_mutex);
> +
> +       schedule_delayed_work(&intel_dp->edp_psr_delayed_normal_work,
> +                             msecs_to_jiffies(100));

Why 100ms?


> +}
> +
>  void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
>                              struct edp_vsc_psr *vsc_psr)
>  {
> @@ -1400,6 +1442,18 @@ void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
>         POSTING_READ(ctl_reg);
>  }
>
> +static void intel_edp_psr_setup(struct intel_dp *intel_dp)
> +{
> +       if (intel_dp->psr_setup_done)
> +               return;
> +
> +       INIT_DELAYED_WORK(&intel_dp->edp_psr_delayed_normal_work,
> +                         intel_edp_psr_delayed_normal_work);
> +       mutex_init(&intel_dp->psr_exit_mutex);
> +
> +       intel_dp->psr_setup_done = true;
> +}
> +
>  static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
>  {
>         struct drm_device *dev = intel_dp_to_dev(intel_dp);
> @@ -1544,6 +1598,9 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
>
>  void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
>  {
> +       /* Setup PSR once */
> +       intel_edp_psr_setup(intel_dp);
> +
>         /* Enable PSR on the panel */
>         intel_edp_psr_enable_sink(intel_dp);
>
> @@ -3413,6 +3470,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>         WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
>              error, port_name(port));
>
> +       intel_dp->psr_setup_done = false;
> +
>         if (!intel_edp_init_connector(intel_dp, intel_connector)) {
>                 i2c_del_adapter(&intel_dp->adapter);
>                 if (is_edp(intel_dp)) {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 65f5001..3b2ccaa 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -497,6 +497,9 @@ struct intel_dp {
>         int backlight_on_delay;
>         int backlight_off_delay;
>         struct delayed_work panel_vdd_work;
> +       struct delayed_work edp_psr_delayed_normal_work;
> +       struct mutex psr_exit_mutex;
> +       bool psr_setup_done;
>         bool want_panel_vdd;
>         struct intel_connector *attached_connector;
>  };
> @@ -844,5 +847,6 @@ extern void intel_edp_psr_enable(struct intel_dp *intel_dp);
>  extern void intel_edp_psr_disable(struct intel_dp *intel_dp);
>  extern void intel_edp_psr_update(struct drm_device *dev);
>  extern bool intel_edp_is_psr_enabled(struct drm_device *dev);
> +extern void intel_edp_psr_force_exit(struct drm_device *dev);
>
>  #endif /* __INTEL_DRV_H__ */
> --
> 1.8.1.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Hook PSR functionality
  2013-07-02  0:52     ` [PATCH] " Rodrigo Vivi
@ 2013-07-08 13:13       ` Paulo Zanoni
  2013-07-08 19:46         ` Daniel Vetter
  0 siblings, 1 reply; 53+ messages in thread
From: Paulo Zanoni @ 2013-07-08 13:13 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

2013/7/1 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> PSR must be enabled after transcoder and port are running.
> And it is only available for HSW.
>
> v2: move enable/disable to intel_ddi
> v3: The spec suggests PSR should be disabled even before backlight (by pzanoni)
> v4: also disabling and enabling whenever panel is disabled/enabled.
> v5: make it last patch to avoid breaking whenever bisecting. So calling for
>     update and force exit came to this patch along with enable/disable calls.
> v6: Remove unused and unecessary psr_enable/disable calls, as notice by Paulo.
>
> CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> ---
>  drivers/gpu/drm/i915/i915_gem.c      | 2 ++
>  drivers/gpu/drm/i915/intel_ddi.c     | 2 ++
>  drivers/gpu/drm/i915/intel_display.c | 1 +
>  3 files changed, 5 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index c68b90f..f2e135b 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -3786,6 +3786,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
>                 goto unlock;
>         }
>
> +       intel_edp_psr_force_exit(dev);

Shouldn't we enter/leave PSR in exactly the same cases as we
enter/leave FBC? This function doesn't seem to touch FBC. I also see,
for example, intel_unpin_work_fn calling intel_update_fbc, but at that
point we don't update PSR. Also intel_enable_primary and
intel_disable_primary also call intel_update_fbc. If we conclude that
PSR and FBC need to be disabled/enabled at exactly the same places,
can we do some rework to unify this?


> +
>         /* Count all active objects as busy, even if they are currently not used
>          * by the gpu. Users of this interface expect objects to eventually
>          * become non-busy without any further actions, therefore emit any
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 324211a..4211925 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1117,6 +1117,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
>                         intel_dp_stop_link_train(intel_dp);
>
>                 ironlake_edp_backlight_on(intel_dp);
> +               intel_edp_psr_enable(intel_dp);
>         }
>
>         if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
> @@ -1147,6 +1148,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
>         if (type == INTEL_OUTPUT_EDP) {
>                 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>
> +               intel_edp_psr_disable(intel_dp);
>                 ironlake_edp_backlight_off(intel_dp);
>         }
>  }
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 6fafa43..5bbfed0 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2236,6 +2236,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>         }
>
>         intel_update_fbc(dev);
> +       intel_edp_psr_update(dev);
>         mutex_unlock(&dev->struct_mutex);
>
>         intel_crtc_update_sarea_pos(crtc, x, y);
> --
> 1.8.1.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Hook PSR functionality
  2013-07-08 13:13       ` Paulo Zanoni
@ 2013-07-08 19:46         ` Daniel Vetter
  2013-07-08 21:40           ` Rodrigo Vivi
  0 siblings, 1 reply; 53+ messages in thread
From: Daniel Vetter @ 2013-07-08 19:46 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Mon, Jul 08, 2013 at 10:13:30AM -0300, Paulo Zanoni wrote:
> 2013/7/1 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> > PSR must be enabled after transcoder and port are running.
> > And it is only available for HSW.
> >
> > v2: move enable/disable to intel_ddi
> > v3: The spec suggests PSR should be disabled even before backlight (by pzanoni)
> > v4: also disabling and enabling whenever panel is disabled/enabled.
> > v5: make it last patch to avoid breaking whenever bisecting. So calling for
> >     update and force exit came to this patch along with enable/disable calls.
> > v6: Remove unused and unecessary psr_enable/disable calls, as notice by Paulo.
> >
> > CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
> > ---
> >  drivers/gpu/drm/i915/i915_gem.c      | 2 ++
> >  drivers/gpu/drm/i915/intel_ddi.c     | 2 ++
> >  drivers/gpu/drm/i915/intel_display.c | 1 +
> >  3 files changed, 5 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> > index c68b90f..f2e135b 100644
> > --- a/drivers/gpu/drm/i915/i915_gem.c
> > +++ b/drivers/gpu/drm/i915/i915_gem.c
> > @@ -3786,6 +3786,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
> >                 goto unlock;
> >         }
> >
> > +       intel_edp_psr_force_exit(dev);
> 
> Shouldn't we enter/leave PSR in exactly the same cases as we
> enter/leave FBC? This function doesn't seem to touch FBC. I also see,
> for example, intel_unpin_work_fn calling intel_update_fbc, but at that
> point we don't update PSR. Also intel_enable_primary and
> intel_disable_primary also call intel_update_fbc. If we conclude that
> PSR and FBC need to be disabled/enabled at exactly the same places,
> can we do some rework to unify this?

I think there's some room for fbc and psr handling code to differ, since
fbc only works on the primary plane, whereas psr works on the entire
display (so also needs to update when cursor/sprites change or gamma table
changes or any other disaplay attribute). But I agree with you that we
should share calls to psr/fbc placed in common gem/modeset code as much as
possible.
-Daniel

> 
> 
> > +
> >         /* Count all active objects as busy, even if they are currently not used
> >          * by the gpu. Users of this interface expect objects to eventually
> >          * become non-busy without any further actions, therefore emit any
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index 324211a..4211925 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -1117,6 +1117,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
> >                         intel_dp_stop_link_train(intel_dp);
> >
> >                 ironlake_edp_backlight_on(intel_dp);
> > +               intel_edp_psr_enable(intel_dp);
> >         }
> >
> >         if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
> > @@ -1147,6 +1148,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
> >         if (type == INTEL_OUTPUT_EDP) {
> >                 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> >
> > +               intel_edp_psr_disable(intel_dp);
> >                 ironlake_edp_backlight_off(intel_dp);
> >         }
> >  }
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 6fafa43..5bbfed0 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2236,6 +2236,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> >         }
> >
> >         intel_update_fbc(dev);
> > +       intel_edp_psr_update(dev);
> >         mutex_unlock(&dev->struct_mutex);
> >
> >         intel_crtc_update_sarea_pos(crtc, x, y);
> > --
> > 1.8.1.4
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 
> -- 
> Paulo Zanoni
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Hook PSR functionality
  2013-07-08 19:46         ` Daniel Vetter
@ 2013-07-08 21:40           ` Rodrigo Vivi
  0 siblings, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-08 21:40 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, Paulo Zanoni

I tried to enable psr using fbc calls and all I got was a frozen machine...
I prefer to stay with the way I'm sure it works

On Mon, Jul 8, 2013 at 4:46 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Mon, Jul 08, 2013 at 10:13:30AM -0300, Paulo Zanoni wrote:
>> 2013/7/1 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>> > PSR must be enabled after transcoder and port are running.
>> > And it is only available for HSW.
>> >
>> > v2: move enable/disable to intel_ddi
>> > v3: The spec suggests PSR should be disabled even before backlight (by pzanoni)
>> > v4: also disabling and enabling whenever panel is disabled/enabled.
>> > v5: make it last patch to avoid breaking whenever bisecting. So calling for
>> >     update and force exit came to this patch along with enable/disable calls.
>> > v6: Remove unused and unecessary psr_enable/disable calls, as notice by Paulo.
>> >
>> > CC: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> > Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>> > ---
>> >  drivers/gpu/drm/i915/i915_gem.c      | 2 ++
>> >  drivers/gpu/drm/i915/intel_ddi.c     | 2 ++
>> >  drivers/gpu/drm/i915/intel_display.c | 1 +
>> >  3 files changed, 5 insertions(+)
>> >
>> > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
>> > index c68b90f..f2e135b 100644
>> > --- a/drivers/gpu/drm/i915/i915_gem.c
>> > +++ b/drivers/gpu/drm/i915/i915_gem.c
>> > @@ -3786,6 +3786,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
>> >                 goto unlock;
>> >         }
>> >
>> > +       intel_edp_psr_force_exit(dev);
>>
>> Shouldn't we enter/leave PSR in exactly the same cases as we
>> enter/leave FBC? This function doesn't seem to touch FBC. I also see,
>> for example, intel_unpin_work_fn calling intel_update_fbc, but at that
>> point we don't update PSR. Also intel_enable_primary and
>> intel_disable_primary also call intel_update_fbc. If we conclude that
>> PSR and FBC need to be disabled/enabled at exactly the same places,
>> can we do some rework to unify this?
>
> I think there's some room for fbc and psr handling code to differ, since
> fbc only works on the primary plane, whereas psr works on the entire
> display (so also needs to update when cursor/sprites change or gamma table
> changes or any other disaplay attribute). But I agree with you that we
> should share calls to psr/fbc placed in common gem/modeset code as much as
> possible.
> -Daniel
>
>>
>>
>> > +
>> >         /* Count all active objects as busy, even if they are currently not used
>> >          * by the gpu. Users of this interface expect objects to eventually
>> >          * become non-busy without any further actions, therefore emit any
>> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
>> > index 324211a..4211925 100644
>> > --- a/drivers/gpu/drm/i915/intel_ddi.c
>> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
>> > @@ -1117,6 +1117,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
>> >                         intel_dp_stop_link_train(intel_dp);
>> >
>> >                 ironlake_edp_backlight_on(intel_dp);
>> > +               intel_edp_psr_enable(intel_dp);
>> >         }
>> >
>> >         if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
>> > @@ -1147,6 +1148,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
>> >         if (type == INTEL_OUTPUT_EDP) {
>> >                 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>> >
>> > +               intel_edp_psr_disable(intel_dp);
>> >                 ironlake_edp_backlight_off(intel_dp);
>> >         }
>> >  }
>> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> > index 6fafa43..5bbfed0 100644
>> > --- a/drivers/gpu/drm/i915/intel_display.c
>> > +++ b/drivers/gpu/drm/i915/intel_display.c
>> > @@ -2236,6 +2236,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>> >         }
>> >
>> >         intel_update_fbc(dev);
>> > +       intel_edp_psr_update(dev);
>> >         mutex_unlock(&dev->struct_mutex);
>> >
>> >         intel_crtc_update_sarea_pos(crtc, x, y);
>> > --
>> > 1.8.1.4
>> >
>> > _______________________________________________
>> > Intel-gfx mailing list
>> > Intel-gfx@lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>>
>>
>> --
>> Paulo Zanoni
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Add functions to force psr exit
  2013-07-08 13:03       ` Paulo Zanoni
@ 2013-07-08 21:48         ` Rodrigo Vivi
  0 siblings, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-08 21:48 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Mon, Jul 8, 2013 at 10:03 AM, Paulo Zanoni <przanoni@gmail.com> wrote:
> 2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>> PSR tracking engine in HSW doesn't detect automagically some directly copy area
>> operations through scanout so we will have to kick it manually and
>> reschedule it to come back to normal operation as soon as possible.
>>
>> v2: Before PSR Hook. Don't force it when busy yet.
>> v3/v4: Solved small conflict.
>>
>> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>> ---
>>  drivers/gpu/drm/i915/i915_reg.h  |  1 +
>>  drivers/gpu/drm/i915/intel_dp.c  | 59 ++++++++++++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/i915/intel_drv.h |  4 +++
>>  3 files changed, 64 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
>> index 833cc97..a19245b 100644
>> --- a/drivers/gpu/drm/i915/i915_reg.h
>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>> @@ -1838,6 +1838,7 @@
>>  #define   EDP_PSR_PERF_CNT_MASK                0xffffff
>>
>>  #define EDP_PSR_DEBUG_CTL              0x64860
>> +#define   EDP_PSR_DEBUG_FORCE_EXIT     (3<<30)
>
> Can you please explain why we're using the debug register here?
> Usually the debug register is only used for debugging, not as part of
> the normal operation. Why can't we do normal/full PSR exit/enter here
> using SRD_CTL bit 31 and the enable/disable sequences? What is
> different?

I understand that, but I didn't see a better way to nuke PSR forcing
it to exit without using the DEBUG register.
Please let me know if there is a better way of doing that.
PSR functionality at haswell wasn't prepared to small directly rights
to scanout.
it tracks writes to some registers, mouse position updates, but
doesn't track small writes to scanout.
KDE and XDM do many small writes to scanout directly that doesn't
trigger psr exit on haswell...
in a long discussion with Chris we figure out that best place to force
an psr exit was at busy_ioctl...
and I really didn't want to disable it and enable on next plage flip
or what ever because this can wait forever and this is the most
efficient way of doing that in terms of power savings...

Besides, debug register was already been used on enable anyway... EWe
must to use it to disable memup tracking anyway, even if we fix
hotplug, we will never stop using this debug register... ever...

>
>
>>  #define   EDP_PSR_DEBUG_MASK_LPSP      (1<<27)
>>  #define   EDP_PSR_DEBUG_MASK_MEMUP     (1<<26)
>>  #define   EDP_PSR_DEBUG_MASK_HPD       (1<<25)
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index 68c81ab..5001fd9 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -1366,6 +1366,48 @@ bool intel_edp_is_psr_enabled(struct drm_device *dev)
>>         return I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
>>  }
>>
>> +static void intel_edp_psr_delayed_normal_work(struct work_struct *__work)
>> +{
>> +       struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
>> +                                                struct intel_dp,
>> +                                                edp_psr_delayed_normal_work);
>> +       struct drm_device *dev = intel_dp_to_dev(intel_dp);
>> +       struct drm_i915_private *dev_priv = dev->dev_private;
>> +
>> +       mutex_lock(&intel_dp->psr_exit_mutex);
>> +       I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) &
>> +                  ~EDP_PSR_DEBUG_FORCE_EXIT);
>> +       mutex_unlock(&intel_dp->psr_exit_mutex);
>> +}
>> +
>> +void intel_edp_psr_force_exit(struct drm_device *dev)
>> +{
>> +       struct drm_i915_private *dev_priv = dev->dev_private;
>> +       struct intel_encoder *encoder;
>> +       struct intel_dp *intel_dp = NULL;
>> +
>> +       if (!intel_edp_is_psr_enabled(dev))
>> +               return;
>> +
>> +       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
>> +               if (encoder->type == INTEL_OUTPUT_EDP)
>> +                       intel_dp = enc_to_intel_dp(&encoder->base);
>> +
>> +       if (!intel_dp)
>> +               return;
>> +
>> +       if (WARN_ON(!intel_dp->psr_setup_done))
>> +               return;
>> +
>> +       mutex_lock(&intel_dp->psr_exit_mutex);
>> +       I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) |
>> +                  EDP_PSR_DEBUG_FORCE_EXIT);
>> +       mutex_unlock(&intel_dp->psr_exit_mutex);
>> +
>> +       schedule_delayed_work(&intel_dp->edp_psr_delayed_normal_work,
>> +                             msecs_to_jiffies(100));
>
> Why 100ms?

because it works...

>
>
>> +}
>> +
>>  void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
>>                              struct edp_vsc_psr *vsc_psr)
>>  {
>> @@ -1400,6 +1442,18 @@ void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
>>         POSTING_READ(ctl_reg);
>>  }
>>
>> +static void intel_edp_psr_setup(struct intel_dp *intel_dp)
>> +{
>> +       if (intel_dp->psr_setup_done)
>> +               return;
>> +
>> +       INIT_DELAYED_WORK(&intel_dp->edp_psr_delayed_normal_work,
>> +                         intel_edp_psr_delayed_normal_work);
>> +       mutex_init(&intel_dp->psr_exit_mutex);
>> +
>> +       intel_dp->psr_setup_done = true;
>> +}
>> +
>>  static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
>>  {
>>         struct drm_device *dev = intel_dp_to_dev(intel_dp);
>> @@ -1544,6 +1598,9 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
>>
>>  void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
>>  {
>> +       /* Setup PSR once */
>> +       intel_edp_psr_setup(intel_dp);
>> +
>>         /* Enable PSR on the panel */
>>         intel_edp_psr_enable_sink(intel_dp);
>>
>> @@ -3413,6 +3470,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>>         WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
>>              error, port_name(port));
>>
>> +       intel_dp->psr_setup_done = false;
>> +
>>         if (!intel_edp_init_connector(intel_dp, intel_connector)) {
>>                 i2c_del_adapter(&intel_dp->adapter);
>>                 if (is_edp(intel_dp)) {
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index 65f5001..3b2ccaa 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -497,6 +497,9 @@ struct intel_dp {
>>         int backlight_on_delay;
>>         int backlight_off_delay;
>>         struct delayed_work panel_vdd_work;
>> +       struct delayed_work edp_psr_delayed_normal_work;
>> +       struct mutex psr_exit_mutex;
>> +       bool psr_setup_done;
>>         bool want_panel_vdd;
>>         struct intel_connector *attached_connector;
>>  };
>> @@ -844,5 +847,6 @@ extern void intel_edp_psr_enable(struct intel_dp *intel_dp);
>>  extern void intel_edp_psr_disable(struct intel_dp *intel_dp);
>>  extern void intel_edp_psr_update(struct drm_device *dev);
>>  extern bool intel_edp_is_psr_enabled(struct drm_device *dev);
>> +extern void intel_edp_psr_force_exit(struct drm_device *dev);
>>
>>  #endif /* __INTEL_DRV_H__ */
>> --
>> 1.8.1.4
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
>
> --
> Paulo Zanoni



--
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: add update function to disable/enable-back PSR
  2013-07-05 22:48     ` Paulo Zanoni
@ 2013-07-08 21:52       ` Rodrigo Vivi
  0 siblings, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-08 21:52 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Jul 5, 2013 at 7:48 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> 2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>> Required function to disable PSR when going to console mode.
>> But also can be used whenever PSR mode entry conditions changed.
>>
>> v2: Add it before PSR Hook. Update function not really been called yet.
>> v3: Fix coding style detected by checkpatch by Paulo Zanoni.
>>
>> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>> ---
>>  drivers/gpu/drm/i915/intel_dp.c  | 37 ++++++++++++++++++++++++++++++-------
>>  drivers/gpu/drm/i915/intel_drv.h |  1 +
>>  2 files changed, 31 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index 9730d6b..86c1a7d 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -1536,14 +1536,8 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
>>         return true;
>>  }
>>
>> -void intel_edp_psr_enable(struct intel_dp *intel_dp)
>> +void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
>
> Then this function should become static.
>
> So, how often do we disable/enable or update after a mode set? I see
> that on enable_sink we reset the VSC header, rewrite the AUX
> registers, also reset EDP_PSR_DEBUG_CTL and reupdate everything inside
> EDP_PSR_CTL. Do we need to redo all this? Don't we just need to redo
> the aux_native_write to DP_PSR_EN_CFG and re-enable EDP_PSR_ENABLE
> since everything else might still be the same on the same mode-set?

Agree, I'll try to move vsc header, aux sets, etc to setup function
that is executed only once
or something like this..
Thanks for the suggestion.

>
>>  {
>> -       struct drm_device *dev = intel_dp_to_dev(intel_dp);
>> -
>> -       if (!intel_edp_psr_match_conditions(intel_dp) ||
>> -           intel_edp_is_psr_enabled(dev))
>> -               return;
>> -
>>         /* Enable PSR on the panel */
>>         intel_edp_psr_enable_sink(intel_dp);
>>
>> @@ -1551,6 +1545,15 @@ void intel_edp_psr_enable(struct intel_dp *intel_dp)
>>         intel_edp_psr_enable_source(intel_dp);
>>  }
>>
>> +void intel_edp_psr_enable(struct intel_dp *intel_dp)
>> +{
>> +       struct drm_device *dev = intel_dp_to_dev(intel_dp);
>> +
>> +       if (intel_edp_psr_match_conditions(intel_dp) &&
>> +           !intel_edp_is_psr_enabled(dev))
>> +               intel_edp_psr_do_enable(intel_dp);
>> +}
>> +
>>  void intel_edp_psr_disable(struct intel_dp *intel_dp)
>>  {
>>         struct drm_device *dev = intel_dp_to_dev(intel_dp);
>> @@ -1573,6 +1576,26 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
>>         intel_wait_for_vblank(dev, intel_crtc->pipe);
>>  }
>>
>> +void intel_edp_psr_update(struct drm_device *dev)
>> +{
>> +       struct intel_encoder *encoder;
>> +       struct intel_dp *intel_dp = NULL;
>> +
>> +       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head)
>> +               if (encoder->type == INTEL_OUTPUT_EDP) {
>> +                       intel_dp = enc_to_intel_dp(&encoder->base);
>> +
>> +                       if (!is_edp_psr(intel_dp))
>> +                               return;
>> +
>> +                       if (!intel_edp_psr_match_conditions(intel_dp))
>> +                               intel_edp_psr_disable(intel_dp);
>> +                       else
>> +                               if (!intel_edp_is_psr_enabled(dev))
>> +                                       intel_edp_psr_do_enable(intel_dp);
>> +               }
>> +}
>> +
>>  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 ff09c4c..1f638cf 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -842,5 +842,6 @@ extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
>>
>>  extern void intel_edp_psr_enable(struct intel_dp *intel_dp);
>>  extern void intel_edp_psr_disable(struct intel_dp *intel_dp);
>> +extern void intel_edp_psr_update(struct drm_device *dev);
>>
>>  #endif /* __INTEL_DRV_H__ */
>> --
>> 1.8.1.4
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
>
> --
> Paulo Zanoni



--
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Enable/Disable PSR
  2013-07-05 21:58         ` Paulo Zanoni
  2013-07-05 22:14           ` Daniel Vetter
@ 2013-07-08 22:09           ` Rodrigo Vivi
  1 sibling, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-08 22:09 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, Jul 5, 2013 at 6:58 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> Hi
>
> Sorry for the delay.
>
> 2013/7/1 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>> On Fri, Jun 28, 2013 at 4:31 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>>> Hi
>>>
>>> 2013/6/28 Rodrigo Vivi <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.
>>>> v4: Fix identation and other style issues raised by checkpatch (by Paulo).
>>>>
>>>
>>> A few of the comments here were already present in previous reviews.
>>> If you think they're not needed, please reply saying why.
>>
>> Thank you very much for reviewing it and for including old comments I
>> had missed.
>> I'm replying this email saying what I changed and explaining what I didn't.
>> updated patch coming later.
>>
>>>
>>>
>>>> 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)
>>>
>>> I know our documentation explicitly says "0x80060000" and
>>> "0x01000000", but to me these magic values are just magic... I think
>>> we could try to reuse the same mechanism we use for the other aux
>>> messages. Check the usage of pack_aux inside intel_dp_aux_ch and also
>>> intel_dp_aux_native_write. Maybe this could be done in a follow-up
>>> patch. Jani gave a suggestion on how to implement this, see email "Re:
>>> [PATCH 5/9] drm/i915: Setup EDP PSR AUX Registers" from January 31.
>>
>> I know this is just magic, but writing some values in some specific
>> aux dst is obfuscated magic.
>> At least the magic implemented here is documented somewhere and more
>> easy to understand.
>>
>>>
>>>
>>>> +#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 dca8fa6..c10be94 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)
>>>
>>> This function should be static (or included in a .h file).
>>
>> done.
>>
>>>
>>>
>>>> +{
>>>> +       struct drm_device *dev = intel_dp_to_dev(intel_dp);
>>>
>>> Function intel_dp_to_dev calls dp_to_dig_port, but you're already
>>> calling dp_to_dig_port below. You could remove this intel_dp_to_dev
>>> call by reordering the definitions.
>>
>> done.
>>
>>>
>>>
>>>> +       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);
>>>
>>> We don't use this register for anything else on eDP, so instead of
>>> preserving its contents with this read we should just set the bits we
>>> want, zeroing everything else. We don't want to preserve bogus values.
>>
>> done.
>>
>>> Also, read below: if we move this code to mode_set time it will make
>>> even more sense.
>>>
>>>
>>>> +
>>>> +       /* As per eDP spec, wait for vblank to send SDP VSC packet */
>>>> +       intel_wait_for_vblank(dev, crtc->pipe);
>>>
>>> The spec says the SDP VSC packets should be sent during the vblank,
>>> but the HW does this automatically and intel_wait_for_vblank doesn't
>>> guarantee us anything regarding that. So that wait seems useless.
>>>
>>>
>>>> +
>>>> +       /* 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.*/
>>>
>>> My interpretation of the spec is that we need to wait until exactly
>>> after the VSync so we don't send incomplete packets, but we don't have
>>> a good way to do this, and intel_wait_for_vblank doesn't help us with
>>> that. If you take a look at the HDMI code you'll notice that we set
>>> the video DIP registers inside intel_hdmi_mode_set, because at that
>>> point the pipe is stopped and we don't need to worry about waiting for
>>> the exact vblank period. Perhaps we should do the same here: load the
>>> contents of the video dip registers at mode_set time? Is there any
>>> problem in keeping those values there even when PSR or the pipe is
>>> disabled?
>>
>>
>> By moving it to mode_set time I started to get some other bugs when
>> exiting PSR state.
>> Also on mode_set time you don't know if psr will be enabled or not and
>> maybe writting this vsc will be useless.
>> I understand vblank is not ideal, but it works and since we don't have
>> a wait_for_vsync implemented I prefer to stay with this version that
>> works.
>
> What if we just remove the wait_for_vblank line since it doesn't
> really seem to help us and may make us skip a few frames? The best
> thing is probably to write the wait_for_vsync function anyway.

ok, I'll try that

>
>>
>>>
>>>
>>>> +       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);
>>>
>>> The PSR enabling documentation says that the "HW also enables VSC DIP
>>> when required", so maybe we should not turn the
>>> VIDEO_DIP_ENABLE_VSC_HSW bit and see if the HW does that for us? My
>>> fear is that setting this unconditionally may make some panels
>>> confused. But I'm not really sure if the HW really sets this bit for
>>> us or just sends/stops-sending the DIP in case this bit is on.
>>
>> unfortunately it didn't worked. we have to manually enable it back
>> when manually disabling it.
>>
>>>
>>>
>>>> +       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) */
>>>
>>> If you implement our suggestion of replacing the magic 0x80060000
>>> value with code this magic msg_size will also disappear.
>>
>> I don't see how. This is aux ctl, not aux data. Besides it is the same
>> used on dp_aux.
>>
>>>
>>>
>>>> +
>>>> +       /* 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;
>>>
>>> Why are we using these 500us values? I couldn't find a place that
>>> tells us which ones to use.
>>
>> just the default... useless and already removed.
>
> I think we should try to discover what is the correct value to write here.

The correct are the default ones. The one that works already.
At some point in the future after we can finally get this feature
accepted I intend to rewrite that VBT patch and get this info from
VBT.  I just gave up on the patch that gets this value from vbt
because vbt was inconsistent regarding versions... that one you had
seem...

>
>
>>
>>>
>>>
>>>> +       }
>>>> +
>>>> +       /* 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);
>>>
>>> Do we have a workaround name for the line above? Damien recently made
>>> a nice effort to document all the WA names we implement. We should at
>>> least say this is a WA.
>>
>> Unfortunately it is not documented on WA database.
>> MEM up mask came only from PM guide doc and HPD came from the hardest path...
>> I had to mask everything and unmasking one by one to find out why we
>> were getting the continuous psr exit.
>> I tried to unsed long and short hpd pulse as described in pm guide,
>> but it refuses to change. So I decided to mask that.
>
> Did you check if we had a pending interrupt to clear?
>
>>
>>>
>>>
>>>> +
>>>> +       /* Disable unused interrupts */
>>>> +       I915_WRITE(GEN6_PMINTRMSK, GEN6_PM_RP_UP_EI_EXPIRED |
>>>> +                  GEN6_PM_RP_DOWN_EI_EXPIRED);
>>>
>>> The line above needs a very big comment explaining it. Also, I'm not
>>> sure the code is correct. Don't we need irq_lock or rps_lock, also
>>> adjust some dev_priv->xyz_iir variable? I'll leave the review of this
>>> line to Ben and Daniel since they're currently touching these things.
>>
>> I checked this is useless in our case. removed.
>>
>
> Ok, looks like it's just in case PSR is continuously existing...
>
>>>
>>>
>>>> +
>>>> +       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))
>>>
>>> One of the nice things about the modeset rework is that, for most of
>>> the display code, we don't call "enable" twice of "disable" twice. On
>>> a brief look at patch 11 it seems we do respect this, so how about you
>>> turn this check for intel_edp_is_psr_enabled into a WARN?
>>
>> I tried to put WARN_ON but started to get warnings... not sure if this
>> is working.
>> Anyway, after I created update_psr, this can be enabled by disabled at
>> any time we need.
>> So I prefer to let it as it is.
>>
>>>
>>>
>>>> +               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);
>>>
>>> Same as above: you could avoid intel_dp_to_dev since you're already
>>> calling dp_to_dig_port.
>>
>> done.
>>
>>>
>>>
>>>> +       struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
>>>> +       uint32_t val;
>>>> +
>>>> +       if (!intel_edp_is_psr_enabled(dev))
>>>> +               return;
>>>
>>> Same as above: replace the check above with a WARN?
>>
>> same as above.
>>
>>>
>>>
>>>> +
>>>> +       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);
>>>
>>> The spec says we need to wait for a vblank and then disable the VSC
>>> DIP. As stated above, it is not clear whether the hardware does this
>>> automatically or not. Also, do we need this at all? I imagine the spec
>>> says we need to wait for a vblank just to avoid sending incomplete
>>> DIPs, but on this case the intel_wait_for_vblank won't help us here.
>>> Maybe we could fully just enable/disable the bit at mode_set time and
>>> not worry about it later?
>>
>> checked and removed. useless wait.
>
> But now you're never disabling the VSC DIP bit.
>
> Anyway, I re-applied your latest patches and had a few small conflicts
> on many patches. Most of the conflicts were due to changes in your own
> patches. Maybe it should be good to rebase everything and resend...

Uhm dam... I tried to resend the one that I got conflict here but
cleared I missed few..
Next versions I'll resend the full series again to avoid loosing some patch

> By the way, things are still working on my machine :)

Thanks for checking that! ;)

>
>>
>>>
>>>
>>>> +}
>>>> +
>>>>  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..ff09c4c 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
>>>>
>>>> _______________________________________________
>>>> Intel-gfx mailing list
>>>> Intel-gfx@lists.freedesktop.org
>>>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>>
>>>
>>>
>>> --
>>> Paulo Zanoni
>>
>>
>>
>> --
>> Rodrigo Vivi
>> Blog: http://blog.vivi.eng.br
>
>
>
> --
> Paulo Zanoni



--
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Match all PSR mode entry conditions before enabling it.
  2013-07-05 20:32         ` Daniel Vetter
@ 2013-07-08 22:25           ` Rodrigo Vivi
  2013-07-11 18:09             ` Rodrigo Vivi
  0 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-08 22:25 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, Paulo Zanoni

On Fri, Jul 5, 2013 at 5:32 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Mon, Jul 01, 2013 at 05:47:39PM -0300, Rodrigo Vivi wrote:
>> Again, Thank you very much for your comments.
>>
>> Replying what I did and why I didn't here and patches coming later.
>
> Paulo asked me to drop by maintainer bikeshed on this patch. So here I'l
> comply ;-)

Mainteiner's complies are always good ;)
Thanks for jumping in this discussion

>
>>
>>
>> On Fri, Jun 28, 2013 at 5:46 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>> > 2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>> >> v2: Prefer seq_puts to seq_printf by Paulo Zanoni.
>> >>
>> >> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> >> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>> >> ---
>> >>  drivers/gpu/drm/i915/i915_debugfs.c | 39 ++++++++++++++++++---
>> >>  drivers/gpu/drm/i915/i915_drv.h     | 12 +++++++
>> >>  drivers/gpu/drm/i915/intel_dp.c     | 68 ++++++++++++++++++++++++++++++++++++-
>> >>  3 files changed, 114 insertions(+), 5 deletions(-)
>> >>
>> >> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
>> >> index 67c777f..95b27ac 100644
>> >> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> >> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> >> @@ -1882,11 +1882,42 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>> >>         struct drm_info_node *node = m->private;
>> >>         struct drm_device *dev = node->minor->dev;
>> >>         struct drm_i915_private *dev_priv = dev->dev_private;
>> >> -       u32 psrctl, psrstat, psrperf;
>> >> +       u32 psrstat, psrperf;
>> >>
>> >> -       psrctl = I915_READ(EDP_PSR_CTL);
>> >> -       seq_printf(m, "PSR Enabled: %s\n",
>> >> -                  yesno(psrctl & EDP_PSR_ENABLE));
>> >> +       if (I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
>> >> +               seq_puts(m, "PSR enabled\n");
>> >> +       } else {
>> >> +               seq_puts(m, "PSR disabled: ");
>> >> +               switch (dev_priv->no_psr_reason) {
>> >> +               case PSR_NO_SOURCE:
>> >> +                       seq_puts(m, "not supported on this platform");
>> >> +                       break;
>> >> +               case PSR_NO_SINK:
>> >> +                       seq_puts(m, "not supported by panel");
>> >> +                       break;
>> >> +               case PSR_CRTC_NOT_ACTIVE:
>> >> +                       seq_puts(m, "crtc not active");
>> >> +                       break;
>> >> +               case PSR_PWR_WELL_ENABLED:
>> >> +                       seq_puts(m, "power well enabled");
>> >> +                       break;
>> >> +               case PSR_NOT_TILED:
>> >> +                       seq_puts(m, "not tiled");
>> >> +                       break;
>> >> +               case PSR_SPRITE_ENABLED:
>> >> +                       seq_puts(m, "sprite enabled");
>> >> +                       break;
>> >> +               case PSR_INTERLACED_ENABLED:
>> >> +                       seq_puts(m, "interlaced enabled");
>> >> +                       break;
>> >> +               case PSR_HSW_NOT_DDIA:
>> >> +                       seq_puts(m, "HSW ties PSR to DDI A (eDP)");
>> >> +                       break;
>> >> +               default:
>> >> +                       seq_puts(m, "unknown reason");
>> >> +               }
>> >> +               seq_puts(m, "\n");
>> >> +       }
>> >>
>> >>         psrstat = I915_READ(EDP_PSR_STATUS_CTL);
>> >>
>> >> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> >> index 56bd82b..f08c1d9 100644
>> >> --- a/drivers/gpu/drm/i915/i915_drv.h
>> >> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> >> @@ -543,6 +543,17 @@ enum no_fbc_reason {
>> >>         FBC_CHIP_DEFAULT, /* disabled by default on this chip */
>> >>  };
>> >>
>> >> +enum no_psr_reason {
>> >> +       PSR_NO_SOURCE, /* Not supported on platform */
>> >> +       PSR_NO_SINK, /* Not supported by panel */
>> >> +       PSR_CRTC_NOT_ACTIVE,
>> >> +       PSR_PWR_WELL_ENABLED,
>> >> +       PSR_NOT_TILED,
>> >> +       PSR_SPRITE_ENABLED,
>> >> +       PSR_INTERLACED_ENABLED,
>> >> +       PSR_HSW_NOT_DDIA,
>> >
>> > I see you left a few reasons listed on the spec, for example S3D,
>> > which we don't support yet. I'm pretty sure that when we implement S3D
>> > we'll totally forget about adding the PSR_S3D_ENABLED condition, so
>> > shouldn't we do it now? Also, why did we not add the eDP hotplug
>> > reason?
>>
>> Since it isn't implemented I'm not sure how to check that.
>> Maybe we will have a function, maybe just a bit in some register or
>> maybe somehow else.
>> So I prefer to stay without it until we have a proper way.
>
> Imo adding the S3D_ENABLED reason is good, since that increases the
> chances that we won'd forget about it. Maybe even add a comment in the
> psr_match_conditions function below saying that we need to do this.

ok, I'll do that then.

>
> Wrt hotplug I've just chatted a bit and it sounds like the hw doesn't like
> our hpd setup for port A. I guess we should fix that up first ...

Since we don't have any known issue with psr, couldn't we just move
forward and after we get hotplug fixed we remove this workaround from
here?
Also, if we wait this we will have to say Chris and Ville finish that
rework with vblank waits you mentioned on the other email.

If you perfer, on next series I can send psr disabled by default.

>
>>
>> >
>> >
>> >> +};
>> >> +
>> >>  enum intel_pch {
>> >>         PCH_NONE = 0,   /* No PCH present */
>> >>         PCH_IBX,        /* Ibexpeak PCH */
>> >> @@ -1146,6 +1157,7 @@ typedef struct drm_i915_private {
>> >>         struct i915_power_well power_well;
>> >>
>> >>         enum no_fbc_reason no_fbc_reason;
>> >> +       enum no_psr_reason no_psr_reason;
>> >>
>> >>         struct drm_mm_node *compressed_fb;
>> >>         struct drm_mm_node *compressed_llb;
>> >> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> >> index c10be94..9730d6b 100644
>> >> --- a/drivers/gpu/drm/i915/intel_dp.c
>> >> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> >> @@ -1471,11 +1471,77 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
>> >>                    EDP_PSR_ENABLE);
>> >>  }
>> >>
>> >> +static bool intel_edp_psr_match_conditions(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 drm_crtc *crtc = dig_port->base.base.crtc;
>> >> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>> >> +       struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
>> >> +       struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
>> >
>> > Again, you have intel_dp_to_dev and also call dp_to_dig_port twice.
>>
>> done.
>>
>> >
>> >
>> >> +
>> >> +       if (!IS_HASWELL(dev)) {
>> >> +               DRM_DEBUG_KMS("PSR not supported on this platform\n");
>> >> +               dev_priv->no_psr_reason = PSR_NO_SOURCE;
>> >> +               return false;
>> >> +       }
>> >> +
>> >> +       if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
>> >> +           (enc_to_dig_port(&intel_encoder->base)->port != PORT_A)) {
>> >
>> > Here you're calling enc_to_dig_port, but you already defined dig_port
>> > above. Use it.
>>
>> done
>
> Just to check: Does this really work for DDI port D with dekstop eDP? I'm
> pretty sure you actually want to check for cpu_transcoder = EPD here ...

doc says psr on hsw is tied to DDI A (eDP)... I used same check Paulo
used on IPS.

>
>>
>> >
>> >
>> >> +               DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
>> >> +               dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
>> >> +               return false;
>> >> +       }
>> >> +
>> >> +       if (!is_edp_psr(intel_dp)) {
>> >> +               DRM_DEBUG_KMS("PSR not supported by this panel\n");
>> >> +               dev_priv->no_psr_reason = PSR_NO_SINK;
>> >> +               return false;
>> >> +       }
>> >> +
>> >> +       if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
>> >
>> > Why do we check for crtc->fb and crtc->mode.clock here? Also, there's
>> > intel_crtc->primary_disabled which you could use.
>>
>> This is how it is done at update_fbc checking for active crtc and it
>> is properly workig.
>> So I prefer to let it like this.
>
> That check is to avoid division-by-zero on state we've taken over from the
> BIOS. Since we should only ever enable psr after a modeset that should be
> a problem.
>
> Now one thing which is a bit urky here with the psr code (same
> comment applies to the fbc code really) is that a lot of the conditions
> here _never_ change between modesets. So I think a ->fbc_possible and a
> ->psr_possible flag in pipe_config would make an awful lot of sense.
>

I liked your _possible flag in pipe_config suggestion..

> But I guess we can do that later on, once it's a bit clearer how this will
> all work out.

... but yes, I think we can do this later and fix both psr and fbc


>
>>
>> >
>> >
>> >> +               DRM_DEBUG_KMS("crtc not active for PSR\n");
>> >> +               dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
>> >> +               return false;
>> >> +       }
>> >> +
>> >> +       if ((I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE) |
>> >
>> > I'd  use "||" instead of "|" at the end of the line since this is a
>> > logical statement.
>>
>> done
>>
>> >
>> >
>> >> +           (I915_READ(HSW_PWR_WELL_KVMR) & HSW_PWR_WELL_ENABLE)) {
>> >
>> > I know the spec says we should check for this, but there's absolutely
>> > no guarantee that the KVMr won't be enabled exactly after we read this
>> > bit. I don't know if there's a sane way to check for an active KVMr
>> > session. We should also probably get an interrupt somehow if someone
>> > enables KVMr after PSR is enabled.
>>
>> You are right, it can be enabled by someone else later, but this will
>> only cause the continue PSR exit like mem up and hpd if they weren't
>> being masked.
>> So, this is just a check saying psr wont work if this is enabled but
>> not really needed to worry if this is enabled later. Wont break
>> anything for sure.
>
> tbh I don't understand why we need to check for the power well at all.
> Is this really a hw requirement?

yes, it is... if it is on it forces psr exit by definition... so if it
is on since the begining it is not worth turn psr on...

>
> Paulo is right that we can't check for the power well enabling from the
> kvmr in a race-free manner, so this needs some more thinking.

also later? because as I said it doesn't cause any bug if power well
is on... it just forces psr exit state...

>
>>
>> >
>> >
>> >> +               DRM_DEBUG_KMS("PSR condition failed: Power Well is Enabled\n");
>> >> +               dev_priv->no_psr_reason = PSR_PWR_WELL_ENABLED;
>> >> +               return false;
>> >> +       }
>> >> +
>> >> +       if (obj->tiling_mode != I915_TILING_X ||
>> >> +           obj->fence_reg == I915_FENCE_REG_NONE) {
>> >> +               DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
>> >> +               dev_priv->no_psr_reason = PSR_NOT_TILED;
>> >> +               return false;
>> >> +       }
>> >> +
>> >> +       if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
>> >
>> > We should probably check "struct intel_plane" instead of I915_READ here.
>>
>> I prefer to stay this way that is the way used on
>> asser_sprite_disabled in intel_display.
>
> I agree with paulo, pls check sw tracked state, not hw state. If we move
> to state precomputation and similar tricks you simply can't rely on the hw
> state. Similar comment applies to the power well check above (if we really
> need that one, I kinda expect that this is not so).

I just don't understand why... Should we change the assert_sprite
also? is it wrong?

>
>>
>> >
>> >
>> >> +               DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
>> >> +               dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
>> >> +               return false;
>> >> +       }
>> >> +
>> >> +       if ((I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
>> >> +            PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
>> >
>> > I'd prefer checking for "crtc->mode.flags & DRM_MODE_FLAG_INTERLACE".
>>
>> I prefer to stay this way that is the way used in intel_display.
>
> Where? Again I think we should use sw tracked state ...

at ironlake_enable_pch_transcoder.... is it wrong there? should we fix?

but anyway, how is the correct way to check it in sw tracked state?

>
>>
>> >
>> >
>> >> +               DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
>> >> +               dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
>> >> +               return false;
>> >> +       }
>> >> +
>> >> +       return true;
>> >> +}
>> >> +
>> >>  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))
>> >> +       if (!intel_edp_psr_match_conditions(intel_dp) ||
>> >> +           intel_edp_is_psr_enabled(dev))
>> >>                 return;
>> >>
>> >>         /* Enable PSR on the panel */
>> >> --
>> >> 1.8.1.4
>> >>
>> >> _______________________________________________
>> >> Intel-gfx mailing list
>> >> Intel-gfx@lists.freedesktop.org
>> >> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>> >
>> >
>> >
>> > --
>> > Paulo Zanoni
>>
>>
>>
>> --
>> Rodrigo Vivi
>> Blog: http://blog.vivi.eng.br
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch



--
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH] drm/i915: Match all PSR mode entry conditions before enabling it.
  2013-07-08 22:25           ` Rodrigo Vivi
@ 2013-07-11 18:09             ` Rodrigo Vivi
  0 siblings, 0 replies; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-11 18:09 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, Paulo Zanoni

On Mon, Jul 8, 2013 at 7:25 PM, Rodrigo Vivi <rodrigo.vivi@gmail.com> wrote:
> On Fri, Jul 5, 2013 at 5:32 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
>> On Mon, Jul 01, 2013 at 05:47:39PM -0300, Rodrigo Vivi wrote:
>>> Again, Thank you very much for your comments.
>>>
>>> Replying what I did and why I didn't here and patches coming later.
>>
>> Paulo asked me to drop by maintainer bikeshed on this patch. So here I'l
>> comply ;-)
>
> Mainteiner's complies are always good ;)
> Thanks for jumping in this discussion
>
>>
>>>
>>>
>>> On Fri, Jun 28, 2013 at 5:46 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>>> > 2013/6/28 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
>>> >> v2: Prefer seq_puts to seq_printf by Paulo Zanoni.
>>> >>
>>> >> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>> >> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>>> >> ---
>>> >>  drivers/gpu/drm/i915/i915_debugfs.c | 39 ++++++++++++++++++---
>>> >>  drivers/gpu/drm/i915/i915_drv.h     | 12 +++++++
>>> >>  drivers/gpu/drm/i915/intel_dp.c     | 68 ++++++++++++++++++++++++++++++++++++-
>>> >>  3 files changed, 114 insertions(+), 5 deletions(-)
>>> >>
>>> >> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
>>> >> index 67c777f..95b27ac 100644
>>> >> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>>> >> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>>> >> @@ -1882,11 +1882,42 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>>> >>         struct drm_info_node *node = m->private;
>>> >>         struct drm_device *dev = node->minor->dev;
>>> >>         struct drm_i915_private *dev_priv = dev->dev_private;
>>> >> -       u32 psrctl, psrstat, psrperf;
>>> >> +       u32 psrstat, psrperf;
>>> >>
>>> >> -       psrctl = I915_READ(EDP_PSR_CTL);
>>> >> -       seq_printf(m, "PSR Enabled: %s\n",
>>> >> -                  yesno(psrctl & EDP_PSR_ENABLE));
>>> >> +       if (I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
>>> >> +               seq_puts(m, "PSR enabled\n");
>>> >> +       } else {
>>> >> +               seq_puts(m, "PSR disabled: ");
>>> >> +               switch (dev_priv->no_psr_reason) {
>>> >> +               case PSR_NO_SOURCE:
>>> >> +                       seq_puts(m, "not supported on this platform");
>>> >> +                       break;
>>> >> +               case PSR_NO_SINK:
>>> >> +                       seq_puts(m, "not supported by panel");
>>> >> +                       break;
>>> >> +               case PSR_CRTC_NOT_ACTIVE:
>>> >> +                       seq_puts(m, "crtc not active");
>>> >> +                       break;
>>> >> +               case PSR_PWR_WELL_ENABLED:
>>> >> +                       seq_puts(m, "power well enabled");
>>> >> +                       break;
>>> >> +               case PSR_NOT_TILED:
>>> >> +                       seq_puts(m, "not tiled");
>>> >> +                       break;
>>> >> +               case PSR_SPRITE_ENABLED:
>>> >> +                       seq_puts(m, "sprite enabled");
>>> >> +                       break;
>>> >> +               case PSR_INTERLACED_ENABLED:
>>> >> +                       seq_puts(m, "interlaced enabled");
>>> >> +                       break;
>>> >> +               case PSR_HSW_NOT_DDIA:
>>> >> +                       seq_puts(m, "HSW ties PSR to DDI A (eDP)");
>>> >> +                       break;
>>> >> +               default:
>>> >> +                       seq_puts(m, "unknown reason");
>>> >> +               }
>>> >> +               seq_puts(m, "\n");
>>> >> +       }
>>> >>
>>> >>         psrstat = I915_READ(EDP_PSR_STATUS_CTL);
>>> >>
>>> >> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>>> >> index 56bd82b..f08c1d9 100644
>>> >> --- a/drivers/gpu/drm/i915/i915_drv.h
>>> >> +++ b/drivers/gpu/drm/i915/i915_drv.h
>>> >> @@ -543,6 +543,17 @@ enum no_fbc_reason {
>>> >>         FBC_CHIP_DEFAULT, /* disabled by default on this chip */
>>> >>  };
>>> >>
>>> >> +enum no_psr_reason {
>>> >> +       PSR_NO_SOURCE, /* Not supported on platform */
>>> >> +       PSR_NO_SINK, /* Not supported by panel */
>>> >> +       PSR_CRTC_NOT_ACTIVE,
>>> >> +       PSR_PWR_WELL_ENABLED,
>>> >> +       PSR_NOT_TILED,
>>> >> +       PSR_SPRITE_ENABLED,
>>> >> +       PSR_INTERLACED_ENABLED,
>>> >> +       PSR_HSW_NOT_DDIA,
>>> >
>>> > I see you left a few reasons listed on the spec, for example S3D,
>>> > which we don't support yet. I'm pretty sure that when we implement S3D
>>> > we'll totally forget about adding the PSR_S3D_ENABLED condition, so
>>> > shouldn't we do it now? Also, why did we not add the eDP hotplug
>>> > reason?
>>>
>>> Since it isn't implemented I'm not sure how to check that.
>>> Maybe we will have a function, maybe just a bit in some register or
>>> maybe somehow else.
>>> So I prefer to stay without it until we have a proper way.
>>
>> Imo adding the S3D_ENABLED reason is good, since that increases the
>> chances that we won'd forget about it. Maybe even add a comment in the
>> psr_match_conditions function below saying that we need to do this.
>
> ok, I'll do that then.
>
>>
>> Wrt hotplug I've just chatted a bit and it sounds like the hw doesn't like
>> our hpd setup for port A. I guess we should fix that up first ...
>
> Since we don't have any known issue with psr, couldn't we just move
> forward and after we get hotplug fixed we remove this workaround from
> here?
> Also, if we wait this we will have to say Chris and Ville finish that
> rework with vblank waits you mentioned on the other email.
>
> If you perfer, on next series I can send psr disabled by default.
>
>>
>>>
>>> >
>>> >
>>> >> +};
>>> >> +
>>> >>  enum intel_pch {
>>> >>         PCH_NONE = 0,   /* No PCH present */
>>> >>         PCH_IBX,        /* Ibexpeak PCH */
>>> >> @@ -1146,6 +1157,7 @@ typedef struct drm_i915_private {
>>> >>         struct i915_power_well power_well;
>>> >>
>>> >>         enum no_fbc_reason no_fbc_reason;
>>> >> +       enum no_psr_reason no_psr_reason;
>>> >>
>>> >>         struct drm_mm_node *compressed_fb;
>>> >>         struct drm_mm_node *compressed_llb;
>>> >> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>>> >> index c10be94..9730d6b 100644
>>> >> --- a/drivers/gpu/drm/i915/intel_dp.c
>>> >> +++ b/drivers/gpu/drm/i915/intel_dp.c
>>> >> @@ -1471,11 +1471,77 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
>>> >>                    EDP_PSR_ENABLE);
>>> >>  }
>>> >>
>>> >> +static bool intel_edp_psr_match_conditions(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 drm_crtc *crtc = dig_port->base.base.crtc;
>>> >> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>>> >> +       struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
>>> >> +       struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
>>> >
>>> > Again, you have intel_dp_to_dev and also call dp_to_dig_port twice.
>>>
>>> done.
>>>
>>> >
>>> >
>>> >> +
>>> >> +       if (!IS_HASWELL(dev)) {
>>> >> +               DRM_DEBUG_KMS("PSR not supported on this platform\n");
>>> >> +               dev_priv->no_psr_reason = PSR_NO_SOURCE;
>>> >> +               return false;
>>> >> +       }
>>> >> +
>>> >> +       if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
>>> >> +           (enc_to_dig_port(&intel_encoder->base)->port != PORT_A)) {
>>> >
>>> > Here you're calling enc_to_dig_port, but you already defined dig_port
>>> > above. Use it.
>>>
>>> done
>>
>> Just to check: Does this really work for DDI port D with dekstop eDP? I'm
>> pretty sure you actually want to check for cpu_transcoder = EPD here ...
>
> doc says psr on hsw is tied to DDI A (eDP)... I used same check Paulo
> used on IPS.
>
>>
>>>
>>> >
>>> >
>>> >> +               DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
>>> >> +               dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
>>> >> +               return false;
>>> >> +       }
>>> >> +
>>> >> +       if (!is_edp_psr(intel_dp)) {
>>> >> +               DRM_DEBUG_KMS("PSR not supported by this panel\n");
>>> >> +               dev_priv->no_psr_reason = PSR_NO_SINK;
>>> >> +               return false;
>>> >> +       }
>>> >> +
>>> >> +       if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
>>> >
>>> > Why do we check for crtc->fb and crtc->mode.clock here? Also, there's
>>> > intel_crtc->primary_disabled which you could use.
>>>
>>> This is how it is done at update_fbc checking for active crtc and it
>>> is properly workig.
>>> So I prefer to let it like this.
>>
>> That check is to avoid division-by-zero on state we've taken over from the
>> BIOS. Since we should only ever enable psr after a modeset that should be
>> a problem.
>>
>> Now one thing which is a bit urky here with the psr code (same
>> comment applies to the fbc code really) is that a lot of the conditions
>> here _never_ change between modesets. So I think a ->fbc_possible and a
>> ->psr_possible flag in pipe_config would make an awful lot of sense.
>>
>
> I liked your _possible flag in pipe_config suggestion..
>
>> But I guess we can do that later on, once it's a bit clearer how this will
>> all work out.
>
> ... but yes, I think we can do this later and fix both psr and fbc
>
>
>>
>>>
>>> >
>>> >
>>> >> +               DRM_DEBUG_KMS("crtc not active for PSR\n");
>>> >> +               dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
>>> >> +               return false;
>>> >> +       }
>>> >> +
>>> >> +       if ((I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE) |
>>> >
>>> > I'd  use "||" instead of "|" at the end of the line since this is a
>>> > logical statement.
>>>
>>> done
>>>
>>> >
>>> >
>>> >> +           (I915_READ(HSW_PWR_WELL_KVMR) & HSW_PWR_WELL_ENABLE)) {
>>> >
>>> > I know the spec says we should check for this, but there's absolutely
>>> > no guarantee that the KVMr won't be enabled exactly after we read this
>>> > bit. I don't know if there's a sane way to check for an active KVMr
>>> > session. We should also probably get an interrupt somehow if someone
>>> > enables KVMr after PSR is enabled.
>>>
>>> You are right, it can be enabled by someone else later, but this will
>>> only cause the continue PSR exit like mem up and hpd if they weren't
>>> being masked.
>>> So, this is just a check saying psr wont work if this is enabled but
>>> not really needed to worry if this is enabled later. Wont break
>>> anything for sure.
>>
>> tbh I don't understand why we need to check for the power well at all.
>> Is this really a hw requirement?
>
> yes, it is... if it is on it forces psr exit by definition... so if it
> is on since the begining it is not worth turn psr on...
>
>>
>> Paulo is right that we can't check for the power well enabling from the
>> kvmr in a race-free manner, so this needs some more thinking.
>
> also later? because as I said it doesn't cause any bug if power well
> is on... it just forces psr exit state...
>
>>
>>>
>>> >
>>> >
>>> >> +               DRM_DEBUG_KMS("PSR condition failed: Power Well is Enabled\n");
>>> >> +               dev_priv->no_psr_reason = PSR_PWR_WELL_ENABLED;
>>> >> +               return false;
>>> >> +       }
>>> >> +
>>> >> +       if (obj->tiling_mode != I915_TILING_X ||
>>> >> +           obj->fence_reg == I915_FENCE_REG_NONE) {
>>> >> +               DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
>>> >> +               dev_priv->no_psr_reason = PSR_NOT_TILED;
>>> >> +               return false;
>>> >> +       }
>>> >> +
>>> >> +       if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
>>> >
>>> > We should probably check "struct intel_plane" instead of I915_READ here.
>>>
>>> I prefer to stay this way that is the way used on
>>> asser_sprite_disabled in intel_display.
>>
>> I agree with paulo, pls check sw tracked state, not hw state. If we move
>> to state precomputation and similar tricks you simply can't rely on the hw
>> state. Similar comment applies to the power well check above (if we really
>> need that one, I kinda expect that this is not so).
>
> I just don't understand why... Should we change the assert_sprite
> also? is it wrong?

I tried to find a way to do it with sw check with intel_plane, etc but
I didn't find any other way.
Do you have any other idea how to do that?

>
>>
>>>
>>> >
>>> >
>>> >> +               DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
>>> >> +               dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
>>> >> +               return false;
>>> >> +       }
>>> >> +
>>> >> +       if ((I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
>>> >> +            PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
>>> >
>>> > I'd prefer checking for "crtc->mode.flags & DRM_MODE_FLAG_INTERLACE".
>>>
>>> I prefer to stay this way that is the way used in intel_display.
>>
>> Where? Again I think we should use sw tracked state ...
>
> at ironlake_enable_pch_transcoder.... is it wrong there? should we fix?
>
> but anyway, how is the correct way to check it in sw tracked state?

Changed to check interlace flag as paulo suggested. Really much better ;)
Thanks

>
>>
>>>
>>> >
>>> >
>>> >> +               DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
>>> >> +               dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
>>> >> +               return false;
>>> >> +       }
>>> >> +
>>> >> +       return true;
>>> >> +}
>>> >> +
>>> >>  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))
>>> >> +       if (!intel_edp_psr_match_conditions(intel_dp) ||
>>> >> +           intel_edp_is_psr_enabled(dev))
>>> >>                 return;
>>> >>
>>> >>         /* Enable PSR on the panel */
>>> >> --
>>> >> 1.8.1.4
>>> >>
>>> >> _______________________________________________
>>> >> Intel-gfx mailing list
>>> >> Intel-gfx@lists.freedesktop.org
>>> >> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>> >
>>> >
>>> >
>>> > --
>>> > Paulo Zanoni
>>>
>>>
>>>
>>> --
>>> Rodrigo Vivi
>>> Blog: http://blog.vivi.eng.br
>>> _______________________________________________
>>> Intel-gfx mailing list
>>> Intel-gfx@lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>>
>> --
>> Daniel Vetter
>> Software Engineer, Intel Corporation
>> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
>
>
>
> --
> Rodrigo Vivi
> Blog: http://blog.vivi.eng.br



--
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/11] drm/i915: Enable/Disable PSR
  2013-07-17 17:02   ` Paulo Zanoni
@ 2013-07-18  7:56     ` Daniel Vetter
  0 siblings, 0 replies; 53+ messages in thread
From: Daniel Vetter @ 2013-07-18  7:56 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Wed, Jul 17, 2013 at 02:02:58PM -0300, Paulo Zanoni wrote:
> 2013/7/11 Rodrigo Vivi <rodrigo.vivi@gmail.com>:
> > +static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
> > +                                   struct edp_vsc_psr *vsc_psr)
> > +{
> > +       struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> > +       struct drm_device *dev = dig_port->base.base.dev;
> > +       struct drm_i915_private *dev_priv = dev->dev_private;
> > +       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;
> > +
> > +       /* As per BSPec (Pipe Video Data Island Packet), we need to disable
> > +          the video DIP being updated before program video DIP data buffer
> > +          registers for DIP being updated. */
> > +       I915_WRITE(ctl_reg, ~VIDEO_DIP_ENABLE_VSC_HSW);
> 
> This should be zero.With that fixed:

Fixed while applying.

> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Bikeshed: We now have two pieces of code writing DIPs, the other copy is
in intel_hdmi.c. And they don't match.

Slightly related, but: I'd really like to see our conversion to the common
infoframe helpers rsn ...

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/11] drm/i915: Enable/Disable PSR
  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
  0 siblings, 1 reply; 53+ messages in thread
From: Paulo Zanoni @ 2013-07-17 17:02 UTC (permalink / raw)
  To: Rodrigo Vivi; +Cc: intel-gfx, Paulo Zanoni

2013/7/11 Rodrigo Vivi <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.
> v4: Fix identation and other style issues raised by checkpatch (by Paulo).
> v5: Changes according to Paulo's review:
>     static on write_vsc;
>     avoid using dp_to_dev when already calling dp_to_dig_port;
>     remove unecessary TP default time setting;
>     remove unecessary interrupts disabling;
>     remove unecessary wait_for_vblank when disabling psr;
> v6: remove unecessary wait_for_vblank when writing vsc;
> v7: adding setup once function to avoid unnecessarily write to vsc
>     and set debug_ctl every time we enable or disable psr.
>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 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  | 149 +++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h |   4 ++
>  3 files changed, 195 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index dc3d6a7..31e4dbb 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1779,6 +1779,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
> @@ -2048,6 +2089,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 d273e36..d4b52a9 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1383,6 +1383,153 @@ 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;
> +}
> +
> +static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
> +                                   struct edp_vsc_psr *vsc_psr)
> +{
> +       struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +       struct drm_device *dev = dig_port->base.base.dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +       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;
> +
> +       /* As per BSPec (Pipe Video Data Island Packet), we need to disable
> +          the video DIP being updated before program video DIP data buffer
> +          registers for DIP being updated. */
> +       I915_WRITE(ctl_reg, ~VIDEO_DIP_ENABLE_VSC_HSW);

This should be zero.With that fixed:
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>


> +       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, VIDEO_DIP_ENABLE_VSC_HSW);
> +       POSTING_READ(ctl_reg);
> +}
> +
> +static void intel_edp_psr_setup(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;
> +
> +       if (intel_dp->psr_setup_done)
> +               return;
> +
> +       /* 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);
> +
> +       /* 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);
> +
> +       intel_dp->psr_setup_done = true;
> +}
> +
> +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;
> +       uint32_t aux_clock_divider = get_aux_clock_divider(intel_dp);
> +       int precharge = 0x3;
> +       int msg_size = 5;       /* Header(4) + Message(1) */
> +
> +       /* 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;
> +
> +       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;
> +
> +       /* Setup PSR once */
> +       intel_edp_psr_setup(intel_dp);
> +
> +       /* 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;
> +
> +       if (!intel_edp_is_psr_enabled(dev))
> +               return;
> +
> +       I915_WRITE(EDP_PSR_CTL, I915_READ(EDP_PSR_CTL) & ~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");
> +}
> +
>  static void intel_disable_dp(struct intel_encoder *encoder)
>  {
>         struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> @@ -3194,6 +3341,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>         WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
>              error, port_name(port));
>
> +       intel_dp->psr_setup_done = false;
> +
>         if (!intel_edp_init_connector(intel_dp, intel_connector)) {
>                 i2c_del_adapter(&intel_dp->adapter);
>                 if (is_edp(intel_dp)) {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d25726d..ff36a40 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -499,6 +499,7 @@ struct intel_dp {
>         int backlight_off_delay;
>         struct delayed_work panel_vdd_work;
>         bool want_panel_vdd;
> +       bool psr_setup_done;
>         struct intel_connector *attached_connector;
>  };
>
> @@ -834,4 +835,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.7.11.7
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 04/11] drm/i915: Enable/Disable PSR
  2013-07-11 21:44 [PATCH 00/11] Enable PSR on Haswell Rodrigo Vivi
@ 2013-07-11 21:44 ` Rodrigo Vivi
  2013-07-17 17:02   ` Paulo Zanoni
  0 siblings, 1 reply; 53+ messages in thread
From: Rodrigo Vivi @ 2013-07-11 21:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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.
v4: Fix identation and other style issues raised by checkpatch (by Paulo).
v5: Changes according to Paulo's review:
    static on write_vsc;
    avoid using dp_to_dev when already calling dp_to_dig_port;
    remove unecessary TP default time setting;
    remove unecessary interrupts disabling;
    remove unecessary wait_for_vblank when disabling psr;
v6: remove unecessary wait_for_vblank when writing vsc;
v7: adding setup once function to avoid unnecessarily write to vsc
    and set debug_ctl every time we enable or disable psr.

Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
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  | 149 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |   4 ++
 3 files changed, 195 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index dc3d6a7..31e4dbb 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1779,6 +1779,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
@@ -2048,6 +2089,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 d273e36..d4b52a9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1383,6 +1383,153 @@ 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;
+}
+
+static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
+				    struct edp_vsc_psr *vsc_psr)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	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;
+
+	/* As per BSPec (Pipe Video Data Island Packet), we need to disable
+	   the video DIP being updated before program video DIP data buffer
+	   registers for DIP being updated. */
+	I915_WRITE(ctl_reg, ~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, VIDEO_DIP_ENABLE_VSC_HSW);
+	POSTING_READ(ctl_reg);
+}
+
+static void intel_edp_psr_setup(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;
+
+	if (intel_dp->psr_setup_done)
+		return;
+
+	/* 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);
+
+	/* 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);
+
+	intel_dp->psr_setup_done = true;
+}
+
+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;
+	uint32_t aux_clock_divider = get_aux_clock_divider(intel_dp);
+	int precharge = 0x3;
+	int msg_size = 5;       /* Header(4) + Message(1) */
+
+	/* 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;
+
+	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;
+
+	/* Setup PSR once */
+	intel_edp_psr_setup(intel_dp);
+
+	/* 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;
+
+	if (!intel_edp_is_psr_enabled(dev))
+		return;
+
+	I915_WRITE(EDP_PSR_CTL, I915_READ(EDP_PSR_CTL) & ~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");
+}
+
 static void intel_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -3194,6 +3341,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
 	     error, port_name(port));
 
+	intel_dp->psr_setup_done = false;
+
 	if (!intel_edp_init_connector(intel_dp, intel_connector)) {
 		i2c_del_adapter(&intel_dp->adapter);
 		if (is_edp(intel_dp)) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d25726d..ff36a40 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -499,6 +499,7 @@ struct intel_dp {
 	int backlight_off_delay;
 	struct delayed_work panel_vdd_work;
 	bool want_panel_vdd;
+	bool psr_setup_done;
 	struct intel_connector *attached_connector;
 };
 
@@ -834,4 +835,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.7.11.7

^ permalink raw reply related	[flat|nested] 53+ messages in thread

end of thread, other threads:[~2013-07-18  7:56 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 04/11] drm/i915: Enable/Disable PSR Rodrigo Vivi
2013-06-28 17:16   ` [PATCH] " 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

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.