All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] drm/i915: Clean up LVDS/PPS macros, suspend/resume logic
@ 2016-08-09 11:34 Imre Deak
  2016-08-09 11:34 ` [PATCH 1/6] drm/i915: Merge the PPS register definitions Imre Deak
                   ` (7 more replies)
  0 siblings, 8 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 11:34 UTC (permalink / raw)
  To: intel-gfx

Last time I happened to look at the LVDS code I came up with a few
cleanup patches removing the duplication when getting at the LVDS/PPS
registers and removing the opaque LVDS/PPS register save/restore during
system suspend/resume. This patchset is an improved version of that
where based on Ville's idea I unified the PPS register macro definitions
that exist now in 3 instances (for GEN<=4, PCH/BXT, VLV/CHV).

Imre Deak (6):
  drm/i915: Merge the PPS register definitions
  drm/i915: Merge TARGET_POWER_ON and PANEL_POWER_ON flag definitions
  drm/i915/lvds: Restore initial HW state during encoder enabling
  drm/i915/dp: Restore PPS HW state from the encoder resume hook
  drm/i915: Apply the PPS register unlock workaround more consistently
  drm/i915: Remove LVDS and PPS suspend time save/restore

 drivers/gpu/drm/i915/i915_drv.c         |   1 +
 drivers/gpu/drm/i915/i915_drv.h         |   9 +-
 drivers/gpu/drm/i915/i915_reg.h         | 145 +++++++++++++-------------------
 drivers/gpu/drm/i915/i915_suspend.c     |  41 ---------
 drivers/gpu/drm/i915/intel_display.c    |  50 +++++++++--
 drivers/gpu/drm/i915/intel_dp.c         |  60 +++++++------
 drivers/gpu/drm/i915/intel_drv.h        |   1 +
 drivers/gpu/drm/i915/intel_lvds.c       | 140 ++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_runtime_pm.c |   4 +
 9 files changed, 235 insertions(+), 216 deletions(-)

-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH 1/6] drm/i915: Merge the PPS register definitions
  2016-08-09 11:34 [PATCH 0/6] drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Imre Deak
@ 2016-08-09 11:34 ` Imre Deak
  2016-08-09 11:53   ` Ville Syrjälä
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
  2016-08-09 11:34 ` [PATCH 2/6] drm/i915: Merge TARGET_POWER_ON and PANEL_POWER_ON flag definitions Imre Deak
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 11:34 UTC (permalink / raw)
  To: intel-gfx

The PPS registers are pretty much the same everywhere, the differences
being:
- Register fields appearing, disappearing from one platform to the
  next: panel-reset-on-powerdown, backlight-on, panel-port,
  register-unlock
- Different register base addresses
- Different number of PPS instances: 2 on VLV/CHV/BXT, 1 everywhere
  else.

We can merge the separate set of PPS definitions by extending the PPS
instance argument to all platforms and using instance 0 on platforms
with a single instance. This means we'll need to calculate the register
addresses dynamically based on the given platform and PPS instance.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |   2 +
 drivers/gpu/drm/i915/i915_reg.h      | 145 ++++++++++++++---------------------
 drivers/gpu/drm/i915/i915_suspend.c  |  30 +++-----
 drivers/gpu/drm/i915/intel_display.c |  22 ++++--
 drivers/gpu/drm/i915/intel_dp.c      |  47 +++++-------
 drivers/gpu/drm/i915/intel_lvds.c    |  43 +++--------
 6 files changed, 119 insertions(+), 170 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c36d176..fddaec6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1749,6 +1749,8 @@ struct drm_i915_private {
 
 	uint32_t psr_mmio_base;
 
+	uint32_t pps_mmio_base;
+
 	wait_queue_head_t gmbus_wait_queue;
 
 	struct pci_dev *bridge_dev;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f38a5e2..b65fe50 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3660,8 +3660,17 @@ enum {
 #define   VIDEO_DIP_ENABLE_SPD_HSW	(1 << 0)
 
 /* Panel power sequencing */
-#define PP_STATUS	_MMIO(0x61200)
-#define   PP_ON		(1 << 31)
+#define PPS_BASE			0x61200
+#define VLV_PPS_BASE			(VLV_DISPLAY_BASE + PPS_BASE)
+#define PCH_PPS_BASE			0xC7200
+
+#define _MMIO_PPS(pps_idx, reg)		_MMIO(dev_priv->pps_mmio_base -	\
+					      PPS_BASE + (reg) +	\
+					      (pps_idx) * 0x100)
+
+#define _PP_STATUS			0x61200
+#define PP_STATUS(pps_idx)		_MMIO_PPS(pps_idx, _PP_STATUS)
+#define   PP_ON				(1 << 31)
 /*
  * Indicates that all dependencies of the panel are on:
  *
@@ -3669,14 +3678,14 @@ enum {
  * - pipe enabled
  * - LVDS/DVOB/DVOC on
  */
-#define   PP_READY		(1 << 30)
-#define   PP_SEQUENCE_NONE	(0 << 28)
-#define   PP_SEQUENCE_POWER_UP	(1 << 28)
-#define   PP_SEQUENCE_POWER_DOWN (2 << 28)
-#define   PP_SEQUENCE_MASK	(3 << 28)
-#define   PP_SEQUENCE_SHIFT	28
-#define   PP_CYCLE_DELAY_ACTIVE	(1 << 27)
-#define   PP_SEQUENCE_STATE_MASK 0x0000000f
+#define   PP_READY			(1 << 30)
+#define   PP_SEQUENCE_NONE		(0 << 28)
+#define   PP_SEQUENCE_POWER_UP		(1 << 28)
+#define   PP_SEQUENCE_POWER_DOWN	(2 << 28)
+#define   PP_SEQUENCE_MASK		(3 << 28)
+#define   PP_SEQUENCE_SHIFT		28
+#define   PP_CYCLE_DELAY_ACTIVE		(1 << 27)
+#define   PP_SEQUENCE_STATE_MASK	0x0000000f
 #define   PP_SEQUENCE_STATE_OFF_IDLE	(0x0 << 0)
 #define   PP_SEQUENCE_STATE_OFF_S0_1	(0x1 << 0)
 #define   PP_SEQUENCE_STATE_OFF_S0_2	(0x2 << 0)
@@ -3686,11 +3695,46 @@ enum {
 #define   PP_SEQUENCE_STATE_ON_S1_2	(0xa << 0)
 #define   PP_SEQUENCE_STATE_ON_S1_3	(0xb << 0)
 #define   PP_SEQUENCE_STATE_RESET	(0xf << 0)
-#define PP_CONTROL	_MMIO(0x61204)
-#define   POWER_TARGET_ON	(1 << 0)
-#define PP_ON_DELAYS	_MMIO(0x61208)
-#define PP_OFF_DELAYS	_MMIO(0x6120c)
-#define PP_DIVISOR	_MMIO(0x61210)
+
+#define _PP_CONTROL			0x61204
+#define PP_CONTROL(pps_idx)		_MMIO_PPS(pps_idx, _PP_CONTROL)
+#define  PANEL_UNLOCK_REGS		(0xabcd << 16)
+#define  PANEL_UNLOCK_MASK		(0xffff << 16)
+#define  BXT_POWER_CYCLE_DELAY_MASK	0x1f0
+#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
+#define  EDP_FORCE_VDD			(1 << 3)
+#define  EDP_BLC_ENABLE			(1 << 2)
+#define  PANEL_POWER_RESET		(1 << 1)
+#define  PANEL_POWER_OFF		(0 << 0)
+#define  PANEL_POWER_ON			(1 << 0)
+#define  POWER_TARGET_ON		(1 << 0)
+
+#define _PP_ON_DELAYS			0x61208
+#define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
+#define  PANEL_PORT_SELECT_MASK		(3 << 30)
+#define  PANEL_PORT_SELECT_LVDS		(0 << 30)
+#define  PANEL_PORT_SELECT_DPA		(1 << 30)
+#define  PANEL_PORT_SELECT_DPC		(2 << 30)
+#define  PANEL_PORT_SELECT_DPD		(3 << 30)
+#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
+#define  PANEL_POWER_UP_DELAY_MASK	0x1fff0000
+#define  PANEL_POWER_UP_DELAY_SHIFT	16
+#define  PANEL_LIGHT_ON_DELAY_MASK	0x1fff
+#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
+
+#define _PP_OFF_DELAYS			0x6120C
+#define PP_OFF_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_OFF_DELAYS)
+#define  PANEL_POWER_DOWN_DELAY_MASK	0x1fff0000
+#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
+#define  PANEL_LIGHT_OFF_DELAY_MASK	0x1fff
+#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
+
+#define _PP_DIVISOR			0x61210
+#define PP_DIVISOR(pps_idx)		_MMIO_PPS(pps_idx, _PP_DIVISOR)
+#define  PP_REFERENCE_DIVIDER_MASK	0xffffff00
+#define  PP_REFERENCE_DIVIDER_SHIFT	8
+#define  PANEL_POWER_CYCLE_DELAY_MASK	0x1f
+#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
 
 /* Panel fitting */
 #define PFIT_CONTROL	_MMIO(dev_priv->info.display_mmio_offset + 0x61230)
@@ -6750,77 +6794,6 @@ enum {
 #define PCH_LVDS	_MMIO(0xe1180)
 #define  LVDS_DETECTED	(1 << 1)
 
-/* vlv has 2 sets of panel control regs. */
-#define _PIPEA_PP_STATUS         (VLV_DISPLAY_BASE + 0x61200)
-#define _PIPEA_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61204)
-#define _PIPEA_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61208)
-#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
-#define _PIPEA_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6120c)
-#define _PIPEA_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61210)
-
-#define _PIPEB_PP_STATUS         (VLV_DISPLAY_BASE + 0x61300)
-#define _PIPEB_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61304)
-#define _PIPEB_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61308)
-#define _PIPEB_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6130c)
-#define _PIPEB_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61310)
-
-#define VLV_PIPE_PP_STATUS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_STATUS, _PIPEB_PP_STATUS)
-#define VLV_PIPE_PP_CONTROL(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_CONTROL, _PIPEB_PP_CONTROL)
-#define VLV_PIPE_PP_ON_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_ON_DELAYS, _PIPEB_PP_ON_DELAYS)
-#define VLV_PIPE_PP_OFF_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_OFF_DELAYS, _PIPEB_PP_OFF_DELAYS)
-#define VLV_PIPE_PP_DIVISOR(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_DIVISOR, _PIPEB_PP_DIVISOR)
-
-#define _PCH_PP_STATUS		0xc7200
-#define _PCH_PP_CONTROL		0xc7204
-#define  PANEL_UNLOCK_REGS	(0xabcd << 16)
-#define  PANEL_UNLOCK_MASK	(0xffff << 16)
-#define  BXT_POWER_CYCLE_DELAY_MASK	(0x1f0)
-#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
-#define  EDP_FORCE_VDD		(1 << 3)
-#define  EDP_BLC_ENABLE		(1 << 2)
-#define  PANEL_POWER_RESET	(1 << 1)
-#define  PANEL_POWER_OFF	(0 << 0)
-#define  PANEL_POWER_ON		(1 << 0)
-#define _PCH_PP_ON_DELAYS	0xc7208
-#define  PANEL_PORT_SELECT_MASK	(3 << 30)
-#define  PANEL_PORT_SELECT_LVDS	(0 << 30)
-#define  PANEL_PORT_SELECT_DPA	(1 << 30)
-#define  PANEL_PORT_SELECT_DPC	(2 << 30)
-#define  PANEL_PORT_SELECT_DPD	(3 << 30)
-#define  PANEL_POWER_UP_DELAY_MASK	(0x1fff0000)
-#define  PANEL_POWER_UP_DELAY_SHIFT	16
-#define  PANEL_LIGHT_ON_DELAY_MASK	(0x1fff)
-#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
-
-#define _PCH_PP_OFF_DELAYS		0xc720c
-#define  PANEL_POWER_DOWN_DELAY_MASK	(0x1fff0000)
-#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
-#define  PANEL_LIGHT_OFF_DELAY_MASK	(0x1fff)
-#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
-
-#define _PCH_PP_DIVISOR			0xc7210
-#define  PP_REFERENCE_DIVIDER_MASK	(0xffffff00)
-#define  PP_REFERENCE_DIVIDER_SHIFT	8
-#define  PANEL_POWER_CYCLE_DELAY_MASK	(0x1f)
-#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
-
-#define PCH_PP_STATUS			_MMIO(_PCH_PP_STATUS)
-#define PCH_PP_CONTROL			_MMIO(_PCH_PP_CONTROL)
-#define PCH_PP_ON_DELAYS		_MMIO(_PCH_PP_ON_DELAYS)
-#define PCH_PP_OFF_DELAYS		_MMIO(_PCH_PP_OFF_DELAYS)
-#define PCH_PP_DIVISOR			_MMIO(_PCH_PP_DIVISOR)
-
-/* BXT PPS changes - 2nd set of PPS registers */
-#define _BXT_PP_STATUS2 	0xc7300
-#define _BXT_PP_CONTROL2 	0xc7304
-#define _BXT_PP_ON_DELAYS2	0xc7308
-#define _BXT_PP_OFF_DELAYS2	0xc730c
-
-#define BXT_PP_STATUS(n)	_MMIO_PIPE(n, _PCH_PP_STATUS, _BXT_PP_STATUS2)
-#define BXT_PP_CONTROL(n)	_MMIO_PIPE(n, _PCH_PP_CONTROL, _BXT_PP_CONTROL2)
-#define BXT_PP_ON_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2)
-#define BXT_PP_OFF_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2)
-
 #define _PCH_DP_B		0xe4100
 #define PCH_DP_B		_MMIO(_PCH_DP_B)
 #define _PCH_DPB_AUX_CH_CTL	0xe4110
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 5cfe4c7..c826b69 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -44,16 +44,11 @@ static void i915_save_display(struct drm_device *dev)
 		dev_priv->regfile.saveLVDS = I915_READ(LVDS);
 
 	/* Panel power sequencer */
-	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
-		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
-		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
-		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
-	} else if (INTEL_INFO(dev)->gen <= 4) {
-		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
-		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
-		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
-		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
+	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
+		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL(0));
+		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS(0));
+		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS(0));
+		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR(0));
 	}
 
 	/* save FBC interval */
@@ -79,16 +74,11 @@ static void i915_restore_display(struct drm_device *dev)
 		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);
 
 	/* Panel power sequencer */
-	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
-		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
-		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
-		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
-	} else if (INTEL_INFO(dev)->gen <= 4) {
-		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
-		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
-		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
-		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
+	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
+		I915_WRITE(PP_ON_DELAYS(0), dev_priv->regfile.savePP_ON_DELAYS);
+		I915_WRITE(PP_OFF_DELAYS(0), dev_priv->regfile.savePP_OFF_DELAYS);
+		I915_WRITE(PP_DIVISOR(0), dev_priv->regfile.savePP_DIVISOR);
+		I915_WRITE(PP_CONTROL(0), dev_priv->regfile.savePP_CONTROL);
 	}
 
 	/* only restore FBC info on the platform that supports FBC*/
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c6f27ab..3d5fd06 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1202,8 +1202,8 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
 	if (HAS_PCH_SPLIT(dev)) {
 		u32 port_sel;
 
-		pp_reg = PCH_PP_CONTROL;
-		port_sel = I915_READ(PCH_PP_ON_DELAYS) & PANEL_PORT_SELECT_MASK;
+		pp_reg = PP_CONTROL(0);
+		port_sel = I915_READ(PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK;
 
 		if (port_sel == PANEL_PORT_SELECT_LVDS &&
 		    I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
@@ -1211,10 +1211,10 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
 		/* XXX: else fix for eDP */
 	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		/* presumably write lock depends on pipe, not port select */
-		pp_reg = VLV_PIPE_PP_CONTROL(pipe);
+		pp_reg = PP_CONTROL(pipe);
 		panel_pipe = pipe;
 	} else {
-		pp_reg = PP_CONTROL;
+		pp_reg = PP_CONTROL(0);
 		if (I915_READ(LVDS) & LVDS_PIPEB_SELECT)
 			panel_pipe = PIPE_B;
 	}
@@ -9411,7 +9411,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 	I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
 	I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
 	I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
-	I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
+	I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n");
 	I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
 	     "CPU PWM1 enabled\n");
 	if (IS_HASWELL(dev))
@@ -14635,12 +14635,24 @@ static bool intel_crt_present(struct drm_device *dev)
 	return true;
 }
 
+static void intel_pps_init(struct drm_i915_private *dev_priv)
+{
+	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
+		dev_priv->pps_mmio_base = PCH_PPS_BASE;
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		dev_priv->pps_mmio_base = VLV_PPS_BASE;
+	else
+		dev_priv->pps_mmio_base = PPS_BASE;
+}
+
 static void intel_setup_outputs(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_encoder *encoder;
 	bool dpd_is_edp = false;
 
+	intel_pps_init(dev_priv);
+
 	/*
 	 * intel_edp_init_connector() depends on this completing first, to
 	 * prevent the registeration of both eDP and LVDS and the incorrect
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 8fe2afa..a5cef91 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -463,13 +463,13 @@ typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
 static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
 			       enum pipe pipe)
 {
-	return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
+	return I915_READ(PP_STATUS(pipe)) & PP_ON;
 }
 
 static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
 				enum pipe pipe)
 {
-	return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
+	return I915_READ(PP_CONTROL(pipe)) & EDP_FORCE_VDD;
 }
 
 static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
@@ -486,7 +486,7 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
 	enum pipe pipe;
 
 	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
-		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
+		u32 port_sel = I915_READ(PP_ON_DELAYS(pipe)) &
 			PANEL_PORT_SELECT_MASK;
 
 		if (port_sel != PANEL_PORT_SELECT_VLV(port))
@@ -583,30 +583,23 @@ static void intel_pps_get_registers(struct drm_i915_private *dev_priv,
 				    struct intel_dp *intel_dp,
 				    struct pps_registers *regs)
 {
+	int pps_idx;
+
 	memset(regs, 0, sizeof(*regs));
 
-	if (IS_BROXTON(dev_priv)) {
-		int idx = bxt_power_sequencer_idx(intel_dp);
+	if (IS_BROXTON(dev_priv))
+		pps_idx = bxt_power_sequencer_idx(intel_dp);
+	else if (HAS_PCH_SPLIT(dev_priv))
+		pps_idx = 0;
+	else
+		pps_idx = vlv_power_sequencer_pipe(intel_dp);
 
-		regs->pp_ctrl = BXT_PP_CONTROL(idx);
-		regs->pp_stat = BXT_PP_STATUS(idx);
-		regs->pp_on = BXT_PP_ON_DELAYS(idx);
-		regs->pp_off = BXT_PP_OFF_DELAYS(idx);
-	} else if (HAS_PCH_SPLIT(dev_priv)) {
-		regs->pp_ctrl = PCH_PP_CONTROL;
-		regs->pp_stat = PCH_PP_STATUS;
-		regs->pp_on = PCH_PP_ON_DELAYS;
-		regs->pp_off = PCH_PP_OFF_DELAYS;
-		regs->pp_div = PCH_PP_DIVISOR;
-	} else {
-		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
-
-		regs->pp_ctrl = VLV_PIPE_PP_CONTROL(pipe);
-		regs->pp_stat = VLV_PIPE_PP_STATUS(pipe);
-		regs->pp_on = VLV_PIPE_PP_ON_DELAYS(pipe);
-		regs->pp_off = VLV_PIPE_PP_OFF_DELAYS(pipe);
-		regs->pp_div = VLV_PIPE_PP_DIVISOR(pipe);
-	}
+	regs->pp_ctrl = PP_CONTROL(pps_idx);
+	regs->pp_stat = PP_STATUS(pps_idx);
+	regs->pp_on = PP_ON_DELAYS(pps_idx);
+	regs->pp_off = PP_OFF_DELAYS(pps_idx);
+	if (!IS_BROXTON(dev_priv))
+		regs->pp_div = PP_DIVISOR(pps_idx);
 }
 
 static i915_reg_t
@@ -651,8 +644,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 		i915_reg_t pp_ctrl_reg, pp_div_reg;
 		u32 pp_div;
 
-		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
-		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
+		pp_ctrl_reg = PP_CONTROL(pipe);
+		pp_div_reg  = PP_DIVISOR(pipe);
 		pp_div = I915_READ(pp_div_reg);
 		pp_div &= PP_REFERENCE_DIVIDER_MASK;
 
@@ -2729,7 +2722,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 	enum pipe pipe = intel_dp->pps_pipe;
-	i915_reg_t pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
+	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
 
 	edp_panel_vdd_off_sync(intel_dp);
 
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 4955047..413e729 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -217,21 +217,12 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
 	struct intel_connector *intel_connector =
 		&lvds_encoder->attached_connector->base;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	i915_reg_t ctl_reg, stat_reg;
-
-	if (HAS_PCH_SPLIT(dev)) {
-		ctl_reg = PCH_PP_CONTROL;
-		stat_reg = PCH_PP_STATUS;
-	} else {
-		ctl_reg = PP_CONTROL;
-		stat_reg = PP_STATUS;
-	}
 
 	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
 
-	I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
+	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | POWER_TARGET_ON);
 	POSTING_READ(lvds_encoder->reg);
-	if (intel_wait_for_register(dev_priv, stat_reg, PP_ON, PP_ON, 1000))
+	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 1000))
 		DRM_ERROR("timed out waiting for panel to power on\n");
 
 	intel_panel_enable_backlight(intel_connector);
@@ -242,18 +233,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
 	struct drm_device *dev = encoder->base.dev;
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	i915_reg_t ctl_reg, stat_reg;
 
-	if (HAS_PCH_SPLIT(dev)) {
-		ctl_reg = PCH_PP_CONTROL;
-		stat_reg = PCH_PP_STATUS;
-	} else {
-		ctl_reg = PP_CONTROL;
-		stat_reg = PP_STATUS;
-	}
-
-	I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
-	if (intel_wait_for_register(dev_priv, stat_reg, PP_ON, 0, 1000))
+	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~POWER_TARGET_ON);
+	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, 0, 1000))
 		DRM_ERROR("timed out waiting for panel to power off\n");
 
 	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
@@ -904,13 +886,10 @@ void intel_lvds_init(struct drm_device *dev)
 	 * Unlock registers and just leave them unlocked. Do this before
 	 * checking quirk lists to avoid bogus WARNINGs.
 	 */
-	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PCH_PP_CONTROL,
-			   I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
-	} else if (INTEL_INFO(dev_priv)->gen < 5) {
-		I915_WRITE(PP_CONTROL,
-			   I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
-	}
+	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
+		I915_WRITE(PP_CONTROL(0),
+			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
+
 	if (!intel_lvds_supported(dev))
 		return;
 
@@ -945,12 +924,12 @@ void intel_lvds_init(struct drm_device *dev)
 
 	 /* Set the Panel Power On/Off timings if uninitialized. */
 	if (INTEL_INFO(dev_priv)->gen < 5 &&
-	    I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) {
+	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
 		/* Set T2 to 40ms and T5 to 200ms */
-		I915_WRITE(PP_ON_DELAYS, 0x019007d0);
+		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
 
 		/* Set T3 to 35ms and Tx to 200ms */
-		I915_WRITE(PP_OFF_DELAYS, 0x015e07d0);
+		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
 
 		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
 	}
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH 2/6] drm/i915: Merge TARGET_POWER_ON and PANEL_POWER_ON flag definitions
  2016-08-09 11:34 [PATCH 0/6] drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Imre Deak
  2016-08-09 11:34 ` [PATCH 1/6] drm/i915: Merge the PPS register definitions Imre Deak
@ 2016-08-09 11:34 ` Imre Deak
  2016-08-09 17:51   ` Ville Syrjälä
  2016-08-09 11:34 ` [PATCH 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling Imre Deak
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 30+ messages in thread
From: Imre Deak @ 2016-08-09 11:34 UTC (permalink / raw)
  To: intel-gfx

These two flags mean the same thing, so remove the duplication.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h   | 1 -
 drivers/gpu/drm/i915/intel_dp.c   | 6 +++---
 drivers/gpu/drm/i915/intel_lvds.c | 4 ++--
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b65fe50..889508f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3707,7 +3707,6 @@ enum {
 #define  PANEL_POWER_RESET		(1 << 1)
 #define  PANEL_POWER_OFF		(0 << 0)
 #define  PANEL_POWER_ON			(1 << 0)
-#define  POWER_TARGET_ON		(1 << 0)
 
 #define _PP_ON_DELAYS			0x61208
 #define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a5cef91..4796ad7 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1950,7 +1950,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 	DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
 	I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
 
-	if ((pp & POWER_TARGET_ON) == 0)
+	if ((pp & PANEL_POWER_ON) == 0)
 		intel_dp->panel_power_off_time = ktime_get_boottime();
 
 	power_domain = intel_display_port_aux_power_domain(intel_encoder);
@@ -2037,7 +2037,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)
 		POSTING_READ(pp_ctrl_reg);
 	}
 
-	pp |= POWER_TARGET_ON;
+	pp |= PANEL_POWER_ON;
 	if (!IS_GEN5(dev))
 		pp |= PANEL_POWER_RESET;
 
@@ -2089,7 +2089,7 @@ static void edp_panel_off(struct intel_dp *intel_dp)
 	pp = ironlake_get_pp_control(intel_dp);
 	/* We need to switch off panel power _and_ force vdd, for otherwise some
 	 * panels get very unhappy and cease to work. */
-	pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
+	pp &= ~(PANEL_POWER_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
 		EDP_BLC_ENABLE);
 
 	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 413e729..c5739fc 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -220,7 +220,7 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
 
 	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
 
-	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | POWER_TARGET_ON);
+	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | PANEL_POWER_ON);
 	POSTING_READ(lvds_encoder->reg);
 	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 1000))
 		DRM_ERROR("timed out waiting for panel to power on\n");
@@ -234,7 +234,7 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
-	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~POWER_TARGET_ON);
+	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~PANEL_POWER_ON);
 	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, 0, 1000))
 		DRM_ERROR("timed out waiting for panel to power off\n");
 
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling
  2016-08-09 11:34 [PATCH 0/6] drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Imre Deak
  2016-08-09 11:34 ` [PATCH 1/6] drm/i915: Merge the PPS register definitions Imre Deak
  2016-08-09 11:34 ` [PATCH 2/6] drm/i915: Merge TARGET_POWER_ON and PANEL_POWER_ON flag definitions Imre Deak
@ 2016-08-09 11:34 ` Imre Deak
  2016-08-09 12:48   ` Ville Syrjälä
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
  2016-08-09 11:34 ` [PATCH 4/6] drm/i915/dp: Restore PPS HW state from the encoder resume hook Imre Deak
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 11:34 UTC (permalink / raw)
  To: intel-gfx

Atm the LVDS encoder depends on the PPS HW context being saved/restored
from generic suspend/resume code. Since the PPS is specific to the LVDS
and eDP encoders a cleaner way is to reinitialize it during encoder
enabling, so do this here for LVDS. Follow-up patches will init the PPS
for the eDP encoder similarly and remove the suspend/resume time save /
restore.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h   |   1 +
 drivers/gpu/drm/i915/intel_lvds.c | 103 +++++++++++++++++++++++++++++++++-----
 2 files changed, 91 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 889508f..da82744 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3710,6 +3710,7 @@ enum {
 
 #define _PP_ON_DELAYS			0x61208
 #define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
+#define  PANEL_PORT_SELECT_SHIFT	30
 #define  PANEL_PORT_SELECT_MASK		(3 << 30)
 #define  PANEL_PORT_SELECT_LVDS		(0 << 30)
 #define  PANEL_PORT_SELECT_DPA		(1 << 30)
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index c5739fc..d5158e5 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -48,6 +48,20 @@ struct intel_lvds_connector {
 	struct notifier_block lid_notifier;
 };
 
+struct intel_lvds_pps {
+	/* 100us units */
+	int t1_t2;
+	int t3;
+	int t4;
+	int t5;
+	int tx;
+
+	int divider;
+
+	int port;
+	bool reset_on_powerdown;
+};
+
 struct intel_lvds_encoder {
 	struct intel_encoder base;
 
@@ -55,6 +69,9 @@ struct intel_lvds_encoder {
 	i915_reg_t reg;
 	u32 a3_power;
 
+	struct intel_lvds_pps init_pps;
+	u32 init_lvds_val;
+
 	struct intel_lvds_connector *attached_connector;
 };
 
@@ -136,6 +153,72 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
 	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
 }
 
+static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
+					struct intel_lvds_pps *pps)
+{
+	u32 val;
+
+	pps->reset_on_powerdown = I915_READ(PP_CONTROL(0)) & PANEL_POWER_RESET;
+
+	val = I915_READ(PP_ON_DELAYS(0));
+	pps->port = (val & PANEL_PORT_SELECT_MASK) >>
+		    PANEL_PORT_SELECT_SHIFT;
+	pps->t1_t2 = (val & PANEL_POWER_UP_DELAY_MASK) >>
+		     PANEL_POWER_UP_DELAY_SHIFT;
+	pps->t5 = (val & PANEL_LIGHT_ON_DELAY_MASK) >>
+		  PANEL_LIGHT_ON_DELAY_SHIFT;
+
+	val = I915_READ(PP_OFF_DELAYS(0));
+	pps->t3 = (val & PANEL_POWER_DOWN_DELAY_MASK) >>
+		  PANEL_POWER_DOWN_DELAY_SHIFT;
+	pps->tx = (val & PANEL_LIGHT_OFF_DELAY_MASK) >>
+		  PANEL_LIGHT_OFF_DELAY_SHIFT;
+
+	val = I915_READ(PP_DIVISOR(0));
+	pps->divider = (val & PP_REFERENCE_DIVIDER_MASK) >>
+		       PP_REFERENCE_DIVIDER_SHIFT;
+	/* Convert from 100ms to 100us units */
+	pps->t4 = ((val & PANEL_POWER_CYCLE_DELAY_MASK) >>
+		   PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
+
+	if (INTEL_INFO(dev_priv)->gen <= 4 &&
+	    pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
+		DRM_DEBUG_KMS("Panel power timings uninitialized, "
+			      "setting defaults\n");
+		/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
+		pps->t1_t2 = 40 * 10;
+		pps->t5 = 200 * 10;
+		/* Set T3 to 35ms and Tx to 200ms in 100 usec units */
+		pps->t3 = 35 * 10;
+		pps->tx = 200 * 10;
+	}
+
+	DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
+			 "divider %d port %d reset_on_powerdown %d\n",
+			 pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
+			 pps->divider, pps->port, pps->reset_on_powerdown);
+}
+
+static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
+				   struct intel_lvds_pps *pps)
+{
+	u32 val;
+
+	val = I915_READ(PP_CONTROL(0));
+	WARN_ON((val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);
+	if (pps->reset_on_powerdown)
+		val |= PANEL_POWER_RESET;
+	I915_WRITE(PP_CONTROL(0), val);
+
+	I915_WRITE(PP_ON_DELAYS(0), (pps->port << PANEL_PORT_SELECT_SHIFT) |
+				    (pps->t1_t2 << PANEL_POWER_UP_DELAY_SHIFT) |
+				    (pps->t5 << PANEL_LIGHT_ON_DELAY_SHIFT));
+	I915_WRITE(PP_OFF_DELAYS(0), (pps->t3 << PANEL_POWER_DOWN_DELAY_SHIFT) |
+				     (pps->tx << PANEL_LIGHT_OFF_DELAY_SHIFT));
+	I915_WRITE(PP_DIVISOR(0), (pps->divider << PP_REFERENCE_DIVIDER_SHIFT) |
+				  ((pps->t4 / 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT));
+}
+
 static void intel_pre_enable_lvds(struct intel_encoder *encoder)
 {
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
@@ -154,7 +237,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder)
 		assert_pll_disabled(dev_priv, pipe);
 	}
 
-	temp = I915_READ(lvds_encoder->reg);
+	intel_lvds_pps_init_hw(dev_priv, &lvds_encoder->init_pps);
+
+	temp = lvds_encoder->init_lvds_val;
 	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
 
 	if (HAS_PCH_CPT(dev)) {
@@ -922,18 +1007,6 @@ void intel_lvds_init(struct drm_device *dev)
 		DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
 	}
 
-	 /* Set the Panel Power On/Off timings if uninitialized. */
-	if (INTEL_INFO(dev_priv)->gen < 5 &&
-	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
-		/* Set T2 to 40ms and T5 to 200ms */
-		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
-
-		/* Set T3 to 35ms and Tx to 200ms */
-		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
-
-		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
-	}
-
 	lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
 	if (!lvds_encoder)
 		return;
@@ -999,6 +1072,10 @@ void intel_lvds_init(struct drm_device *dev)
 				      dev->mode_config.scaling_mode_property,
 				      DRM_MODE_SCALE_ASPECT);
 	intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
+
+	intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps);
+	lvds_encoder->init_lvds_val = lvds;
+
 	/*
 	 * LVDS discovery:
 	 * 1) check for EDID on DDC
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH 4/6] drm/i915/dp: Restore PPS HW state from the encoder resume hook
  2016-08-09 11:34 [PATCH 0/6] drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Imre Deak
                   ` (2 preceding siblings ...)
  2016-08-09 11:34 ` [PATCH 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling Imre Deak
@ 2016-08-09 11:34 ` Imre Deak
  2016-08-09 12:52   ` Ville Syrjälä
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
  2016-08-09 11:34 ` [PATCH 5/6] drm/i915: Apply the PPS register unlock workaround more consistently Imre Deak
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 11:34 UTC (permalink / raw)
  To: intel-gfx

Similarly to the previous patch, initialize the PPS from the DP
encoder's resume hook. Note that as opposed to LVDS we can't do this
during encoder enabling, since we need the PPS for DP detection as well.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4796ad7..76f5b72 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4665,6 +4665,9 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 	 */
 	if (IS_VALLEYVIEW(encoder->dev) || IS_CHERRYVIEW(encoder->dev))
 		vlv_initial_power_sequencer_setup(intel_dp);
+	else
+		intel_dp_init_panel_power_sequencer_registers(encoder->dev,
+							      intel_dp);
 
 	intel_edp_panel_vdd_sanitize(intel_dp);
 
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH 5/6] drm/i915: Apply the PPS register unlock workaround more consistently
  2016-08-09 11:34 [PATCH 0/6] drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Imre Deak
                   ` (3 preceding siblings ...)
  2016-08-09 11:34 ` [PATCH 4/6] drm/i915/dp: Restore PPS HW state from the encoder resume hook Imre Deak
@ 2016-08-09 11:34 ` Imre Deak
  2016-08-09 13:01   ` Ville Syrjälä
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
  2016-08-09 11:34 ` [PATCH 6/6] drm/i915: Remove LVDS and PPS suspend time save/restore Imre Deak
                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 11:34 UTC (permalink / raw)
  To: intel-gfx

Atm, we apply this workaround somewhat inconsistently at the following
points: driver loading, LVDS init, eDP PPS init, system resume. As this
workaround also affects registers other than PPS (timing, PLL) a more
consistent way is to apply it early after the PPS HW context is known to
be lost: driver loading, system resume and on VLV/CHV/BXT when turning
on power domains.

This is needed by the next patch that removes saving/restoring of the
PP_CONTROL register.

This also removes the incorrect programming of the workaround on HSW+
PCH platforms which don't have the register locking mechanism.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c         |  1 +
 drivers/gpu/drm/i915/intel_display.c    | 28 ++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_dp.c         |  4 +++-
 drivers/gpu/drm/i915/intel_drv.h        |  1 +
 drivers/gpu/drm/i915/intel_lvds.c       |  8 --------
 drivers/gpu/drm/i915/intel_runtime_pm.c |  4 ++++
 6 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 8cfc264..0fcd1c0 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1560,6 +1560,7 @@ static int i915_drm_resume(struct drm_device *dev)
 	i915_gem_resume(dev);
 
 	i915_restore_state(dev);
+	intel_pps_unlock_regs_wa(dev_priv);
 	intel_opregion_setup(dev_priv);
 
 	intel_init_pch_refclk(dev);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3d5fd06..dc4e600 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14635,6 +14635,32 @@ static bool intel_crt_present(struct drm_device *dev)
 	return true;
 }
 
+void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
+{
+	int pps_num;
+	int pps_idx;
+
+	/*
+	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
+	 * everywhere where registers can be write protected.
+	 */
+	if (INTEL_GEN(dev_priv) <= 4 ||
+	    HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
+		pps_num = 1;
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv) ||
+		 IS_BROXTON(dev_priv))
+		pps_num = 2;
+	else
+		pps_num = 0;
+
+	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
+		u32 val = I915_READ(PP_CONTROL(pps_idx));
+
+		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
+		I915_WRITE(PP_CONTROL(pps_idx), val);
+	}
+}
+
 static void intel_pps_init(struct drm_i915_private *dev_priv)
 {
 	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
@@ -14643,6 +14669,8 @@ static void intel_pps_init(struct drm_i915_private *dev_priv)
 		dev_priv->pps_mmio_base = VLV_PPS_BASE;
 	else
 		dev_priv->pps_mmio_base = PPS_BASE;
+
+	intel_pps_unlock_regs_wa(dev_priv);
 }
 
 static void intel_setup_outputs(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 76f5b72..b27f1c5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1829,7 +1829,9 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
 	control = I915_READ(_pp_ctrl_reg(intel_dp));
-	if (!IS_BROXTON(dev)) {
+	if (WARN_ON((HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) ||
+		     IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+		     (control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
 		control &= ~PANEL_UNLOCK_MASK;
 		control |= PANEL_UNLOCK_REGS;
 	}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c29a429..cbce786 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1159,6 +1159,7 @@ void intel_mark_busy(struct drm_i915_private *dev_priv);
 void intel_mark_idle(struct drm_i915_private *dev_priv);
 void intel_crtc_restore_mode(struct drm_crtc *crtc);
 int intel_display_suspend(struct drm_device *dev);
+void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
 void intel_encoder_destroy(struct drm_encoder *encoder);
 int intel_connector_init(struct intel_connector *);
 struct intel_connector *intel_connector_alloc(void);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index d5158e5..9a6e1ad 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -967,14 +967,6 @@ void intel_lvds_init(struct drm_device *dev)
 	int pipe;
 	u8 pin;
 
-	/*
-	 * Unlock registers and just leave them unlocked. Do this before
-	 * checking quirk lists to avoid bogus WARNINGs.
-	 */
-	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
-		I915_WRITE(PP_CONTROL(0),
-			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
-
 	if (!intel_lvds_supported(dev))
 		return;
 
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 1c603bb..8f51ae3 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -592,6 +592,8 @@ void bxt_disable_dc9(struct drm_i915_private *dev_priv)
 	DRM_DEBUG_KMS("Disabling DC9\n");
 
 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+	intel_pps_unlock_regs_wa(dev_priv);
 }
 
 static void assert_csr_loaded(struct drm_i915_private *dev_priv)
@@ -1145,6 +1147,8 @@ static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
 	vlv_set_power_well(dev_priv, power_well, true);
 
 	vlv_display_power_well_init(dev_priv);
+
+	intel_pps_unlock_regs_wa(dev_priv);
 }
 
 static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH 6/6] drm/i915: Remove LVDS and PPS suspend time save/restore
  2016-08-09 11:34 [PATCH 0/6] drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Imre Deak
                   ` (4 preceding siblings ...)
  2016-08-09 11:34 ` [PATCH 5/6] drm/i915: Apply the PPS register unlock workaround more consistently Imre Deak
@ 2016-08-09 11:34 ` Imre Deak
  2016-08-09 18:44   ` Ville Syrjälä
  2016-08-09 12:05 ` ✓ Ro.CI.BAT: success for drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Patchwork
  2016-08-10  9:35 ` ✗ Ro.CI.BAT: failure for drm/i915: Clean up LVDS/PPS macros, suspend/resume logic (rev7) Patchwork
  7 siblings, 1 reply; 30+ messages in thread
From: Imre Deak @ 2016-08-09 11:34 UTC (permalink / raw)
  To: intel-gfx

In the preceeding patches we made sure that:
- the LVDS encoder takes care of reiniting both the LVDS register
and its PPS
- the eDP encoder takes care of reiniting its PPS
- the PPS register unlocking workaround is applied explicitly whenever
the PPS context is lost

Based on the above we can safely remove the opaque LVDS and PPS save /
restore from generic code.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h     |  7 -------
 drivers/gpu/drm/i915/i915_suspend.c | 31 -------------------------------
 2 files changed, 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index fddaec6..a83c0a6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1061,13 +1061,6 @@ struct intel_gmbus {
 
 struct i915_suspend_saved_registers {
 	u32 saveDSPARB;
-	u32 saveLVDS;
-	u32 savePP_ON_DELAYS;
-	u32 savePP_OFF_DELAYS;
-	u32 savePP_ON;
-	u32 savePP_OFF;
-	u32 savePP_CONTROL;
-	u32 savePP_DIVISOR;
 	u32 saveFBC_CONTROL;
 	u32 saveCACHE_MODE_0;
 	u32 saveMI_ARB_STATE;
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index c826b69..4f27277 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -37,20 +37,6 @@ static void i915_save_display(struct drm_device *dev)
 	if (INTEL_INFO(dev)->gen <= 4)
 		dev_priv->regfile.saveDSPARB = I915_READ(DSPARB);
 
-	/* LVDS state */
-	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
-		dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
-	else if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
-		dev_priv->regfile.saveLVDS = I915_READ(LVDS);
-
-	/* Panel power sequencer */
-	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
-		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL(0));
-		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS(0));
-		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS(0));
-		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR(0));
-	}
-
 	/* save FBC interval */
 	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev))
 		dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
@@ -59,28 +45,11 @@ static void i915_save_display(struct drm_device *dev)
 static void i915_restore_display(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	u32 mask = 0xffffffff;
 
 	/* Display arbitration */
 	if (INTEL_INFO(dev)->gen <= 4)
 		I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB);
 
-	mask = ~LVDS_PORT_EN;
-
-	/* LVDS state */
-	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
-		I915_WRITE(PCH_LVDS, dev_priv->regfile.saveLVDS & mask);
-	else if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
-		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);
-
-	/* Panel power sequencer */
-	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
-		I915_WRITE(PP_ON_DELAYS(0), dev_priv->regfile.savePP_ON_DELAYS);
-		I915_WRITE(PP_OFF_DELAYS(0), dev_priv->regfile.savePP_OFF_DELAYS);
-		I915_WRITE(PP_DIVISOR(0), dev_priv->regfile.savePP_DIVISOR);
-		I915_WRITE(PP_CONTROL(0), dev_priv->regfile.savePP_CONTROL);
-	}
-
 	/* only restore FBC info on the platform that supports FBC*/
 	intel_fbc_global_disable(dev_priv);
 
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 1/6] drm/i915: Merge the PPS register definitions
  2016-08-09 11:34 ` [PATCH 1/6] drm/i915: Merge the PPS register definitions Imre Deak
@ 2016-08-09 11:53   ` Ville Syrjälä
  2016-08-09 13:24     ` Imre Deak
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
  1 sibling, 1 reply; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 11:53 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 02:34:07PM +0300, Imre Deak wrote:
> The PPS registers are pretty much the same everywhere, the differences
> being:
> - Register fields appearing, disappearing from one platform to the
>   next: panel-reset-on-powerdown, backlight-on, panel-port,
>   register-unlock
> - Different register base addresses
> - Different number of PPS instances: 2 on VLV/CHV/BXT, 1 everywhere
>   else.
> 
> We can merge the separate set of PPS definitions by extending the PPS
> instance argument to all platforms and using instance 0 on platforms
> with a single instance. This means we'll need to calculate the register
> addresses dynamically based on the given platform and PPS instance.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      |   2 +
>  drivers/gpu/drm/i915/i915_reg.h      | 145 ++++++++++++++---------------------
>  drivers/gpu/drm/i915/i915_suspend.c  |  30 +++-----
>  drivers/gpu/drm/i915/intel_display.c |  22 ++++--
>  drivers/gpu/drm/i915/intel_dp.c      |  47 +++++-------
>  drivers/gpu/drm/i915/intel_lvds.c    |  43 +++--------
>  6 files changed, 119 insertions(+), 170 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index c36d176..fddaec6 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1749,6 +1749,8 @@ struct drm_i915_private {
>  
>  	uint32_t psr_mmio_base;
>  
> +	uint32_t pps_mmio_base;
> +
>  	wait_queue_head_t gmbus_wait_queue;
>  
>  	struct pci_dev *bridge_dev;
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index f38a5e2..b65fe50 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3660,8 +3660,17 @@ enum {
>  #define   VIDEO_DIP_ENABLE_SPD_HSW	(1 << 0)
>  
>  /* Panel power sequencing */
> -#define PP_STATUS	_MMIO(0x61200)
> -#define   PP_ON		(1 << 31)
> +#define PPS_BASE			0x61200
> +#define VLV_PPS_BASE			(VLV_DISPLAY_BASE + PPS_BASE)
> +#define PCH_PPS_BASE			0xC7200
> +
> +#define _MMIO_PPS(pps_idx, reg)		_MMIO(dev_priv->pps_mmio_base -	\
> +					      PPS_BASE + (reg) +	\
> +					      (pps_idx) * 0x100)
> +
> +#define _PP_STATUS			0x61200
> +#define PP_STATUS(pps_idx)		_MMIO_PPS(pps_idx, _PP_STATUS)
> +#define   PP_ON				(1 << 31)
>  /*
>   * Indicates that all dependencies of the panel are on:
>   *
> @@ -3669,14 +3678,14 @@ enum {
>   * - pipe enabled
>   * - LVDS/DVOB/DVOC on
>   */
> -#define   PP_READY		(1 << 30)
> -#define   PP_SEQUENCE_NONE	(0 << 28)
> -#define   PP_SEQUENCE_POWER_UP	(1 << 28)
> -#define   PP_SEQUENCE_POWER_DOWN (2 << 28)
> -#define   PP_SEQUENCE_MASK	(3 << 28)
> -#define   PP_SEQUENCE_SHIFT	28
> -#define   PP_CYCLE_DELAY_ACTIVE	(1 << 27)
> -#define   PP_SEQUENCE_STATE_MASK 0x0000000f
> +#define   PP_READY			(1 << 30)
> +#define   PP_SEQUENCE_NONE		(0 << 28)
> +#define   PP_SEQUENCE_POWER_UP		(1 << 28)
> +#define   PP_SEQUENCE_POWER_DOWN	(2 << 28)
> +#define   PP_SEQUENCE_MASK		(3 << 28)
> +#define   PP_SEQUENCE_SHIFT		28
> +#define   PP_CYCLE_DELAY_ACTIVE		(1 << 27)
> +#define   PP_SEQUENCE_STATE_MASK	0x0000000f
>  #define   PP_SEQUENCE_STATE_OFF_IDLE	(0x0 << 0)
>  #define   PP_SEQUENCE_STATE_OFF_S0_1	(0x1 << 0)
>  #define   PP_SEQUENCE_STATE_OFF_S0_2	(0x2 << 0)
> @@ -3686,11 +3695,46 @@ enum {
>  #define   PP_SEQUENCE_STATE_ON_S1_2	(0xa << 0)
>  #define   PP_SEQUENCE_STATE_ON_S1_3	(0xb << 0)
>  #define   PP_SEQUENCE_STATE_RESET	(0xf << 0)
> -#define PP_CONTROL	_MMIO(0x61204)
> -#define   POWER_TARGET_ON	(1 << 0)
> -#define PP_ON_DELAYS	_MMIO(0x61208)
> -#define PP_OFF_DELAYS	_MMIO(0x6120c)
> -#define PP_DIVISOR	_MMIO(0x61210)
> +
> +#define _PP_CONTROL			0x61204
> +#define PP_CONTROL(pps_idx)		_MMIO_PPS(pps_idx, _PP_CONTROL)
> +#define  PANEL_UNLOCK_REGS		(0xabcd << 16)
> +#define  PANEL_UNLOCK_MASK		(0xffff << 16)
> +#define  BXT_POWER_CYCLE_DELAY_MASK	0x1f0
> +#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
> +#define  EDP_FORCE_VDD			(1 << 3)
> +#define  EDP_BLC_ENABLE			(1 << 2)
> +#define  PANEL_POWER_RESET		(1 << 1)
> +#define  PANEL_POWER_OFF		(0 << 0)
> +#define  PANEL_POWER_ON			(1 << 0)
> +#define  POWER_TARGET_ON		(1 << 0)
> +
> +#define _PP_ON_DELAYS			0x61208
> +#define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
> +#define  PANEL_PORT_SELECT_MASK		(3 << 30)
> +#define  PANEL_PORT_SELECT_LVDS		(0 << 30)
> +#define  PANEL_PORT_SELECT_DPA		(1 << 30)
> +#define  PANEL_PORT_SELECT_DPC		(2 << 30)
> +#define  PANEL_PORT_SELECT_DPD		(3 << 30)
> +#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
> +#define  PANEL_POWER_UP_DELAY_MASK	0x1fff0000
> +#define  PANEL_POWER_UP_DELAY_SHIFT	16
> +#define  PANEL_LIGHT_ON_DELAY_MASK	0x1fff
> +#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
> +
> +#define _PP_OFF_DELAYS			0x6120C
> +#define PP_OFF_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_OFF_DELAYS)
> +#define  PANEL_POWER_DOWN_DELAY_MASK	0x1fff0000
> +#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
> +#define  PANEL_LIGHT_OFF_DELAY_MASK	0x1fff
> +#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
> +
> +#define _PP_DIVISOR			0x61210
> +#define PP_DIVISOR(pps_idx)		_MMIO_PPS(pps_idx, _PP_DIVISOR)
> +#define  PP_REFERENCE_DIVIDER_MASK	0xffffff00
> +#define  PP_REFERENCE_DIVIDER_SHIFT	8
> +#define  PANEL_POWER_CYCLE_DELAY_MASK	0x1f
> +#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
>  
>  /* Panel fitting */
>  #define PFIT_CONTROL	_MMIO(dev_priv->info.display_mmio_offset + 0x61230)
> @@ -6750,77 +6794,6 @@ enum {
>  #define PCH_LVDS	_MMIO(0xe1180)
>  #define  LVDS_DETECTED	(1 << 1)
>  
> -/* vlv has 2 sets of panel control regs. */
> -#define _PIPEA_PP_STATUS         (VLV_DISPLAY_BASE + 0x61200)
> -#define _PIPEA_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61204)
> -#define _PIPEA_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61208)
> -#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
> -#define _PIPEA_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6120c)
> -#define _PIPEA_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61210)
> -
> -#define _PIPEB_PP_STATUS         (VLV_DISPLAY_BASE + 0x61300)
> -#define _PIPEB_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61304)
> -#define _PIPEB_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61308)
> -#define _PIPEB_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6130c)
> -#define _PIPEB_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61310)
> -
> -#define VLV_PIPE_PP_STATUS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_STATUS, _PIPEB_PP_STATUS)
> -#define VLV_PIPE_PP_CONTROL(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_CONTROL, _PIPEB_PP_CONTROL)
> -#define VLV_PIPE_PP_ON_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_ON_DELAYS, _PIPEB_PP_ON_DELAYS)
> -#define VLV_PIPE_PP_OFF_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_OFF_DELAYS, _PIPEB_PP_OFF_DELAYS)
> -#define VLV_PIPE_PP_DIVISOR(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_DIVISOR, _PIPEB_PP_DIVISOR)
> -
> -#define _PCH_PP_STATUS		0xc7200
> -#define _PCH_PP_CONTROL		0xc7204
> -#define  PANEL_UNLOCK_REGS	(0xabcd << 16)
> -#define  PANEL_UNLOCK_MASK	(0xffff << 16)
> -#define  BXT_POWER_CYCLE_DELAY_MASK	(0x1f0)
> -#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
> -#define  EDP_FORCE_VDD		(1 << 3)
> -#define  EDP_BLC_ENABLE		(1 << 2)
> -#define  PANEL_POWER_RESET	(1 << 1)
> -#define  PANEL_POWER_OFF	(0 << 0)
> -#define  PANEL_POWER_ON		(1 << 0)
> -#define _PCH_PP_ON_DELAYS	0xc7208
> -#define  PANEL_PORT_SELECT_MASK	(3 << 30)
> -#define  PANEL_PORT_SELECT_LVDS	(0 << 30)
> -#define  PANEL_PORT_SELECT_DPA	(1 << 30)
> -#define  PANEL_PORT_SELECT_DPC	(2 << 30)
> -#define  PANEL_PORT_SELECT_DPD	(3 << 30)
> -#define  PANEL_POWER_UP_DELAY_MASK	(0x1fff0000)
> -#define  PANEL_POWER_UP_DELAY_SHIFT	16
> -#define  PANEL_LIGHT_ON_DELAY_MASK	(0x1fff)
> -#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
> -
> -#define _PCH_PP_OFF_DELAYS		0xc720c
> -#define  PANEL_POWER_DOWN_DELAY_MASK	(0x1fff0000)
> -#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
> -#define  PANEL_LIGHT_OFF_DELAY_MASK	(0x1fff)
> -#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
> -
> -#define _PCH_PP_DIVISOR			0xc7210
> -#define  PP_REFERENCE_DIVIDER_MASK	(0xffffff00)
> -#define  PP_REFERENCE_DIVIDER_SHIFT	8
> -#define  PANEL_POWER_CYCLE_DELAY_MASK	(0x1f)
> -#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
> -
> -#define PCH_PP_STATUS			_MMIO(_PCH_PP_STATUS)
> -#define PCH_PP_CONTROL			_MMIO(_PCH_PP_CONTROL)
> -#define PCH_PP_ON_DELAYS		_MMIO(_PCH_PP_ON_DELAYS)
> -#define PCH_PP_OFF_DELAYS		_MMIO(_PCH_PP_OFF_DELAYS)
> -#define PCH_PP_DIVISOR			_MMIO(_PCH_PP_DIVISOR)
> -
> -/* BXT PPS changes - 2nd set of PPS registers */
> -#define _BXT_PP_STATUS2 	0xc7300
> -#define _BXT_PP_CONTROL2 	0xc7304
> -#define _BXT_PP_ON_DELAYS2	0xc7308
> -#define _BXT_PP_OFF_DELAYS2	0xc730c
> -
> -#define BXT_PP_STATUS(n)	_MMIO_PIPE(n, _PCH_PP_STATUS, _BXT_PP_STATUS2)
> -#define BXT_PP_CONTROL(n)	_MMIO_PIPE(n, _PCH_PP_CONTROL, _BXT_PP_CONTROL2)
> -#define BXT_PP_ON_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2)
> -#define BXT_PP_OFF_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2)
> -
>  #define _PCH_DP_B		0xe4100
>  #define PCH_DP_B		_MMIO(_PCH_DP_B)
>  #define _PCH_DPB_AUX_CH_CTL	0xe4110
> diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
> index 5cfe4c7..c826b69 100644
> --- a/drivers/gpu/drm/i915/i915_suspend.c
> +++ b/drivers/gpu/drm/i915/i915_suspend.c
> @@ -44,16 +44,11 @@ static void i915_save_display(struct drm_device *dev)
>  		dev_priv->regfile.saveLVDS = I915_READ(LVDS);
>  
>  	/* Panel power sequencer */
> -	if (HAS_PCH_SPLIT(dev)) {
> -		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
> -		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
> -		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
> -		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
> -	} else if (INTEL_INFO(dev)->gen <= 4) {
> -		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
> -		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
> -		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
> -		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
> +	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
> +		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL(0));
> +		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS(0));
> +		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS(0));
> +		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR(0));
>  	}
>  
>  	/* save FBC interval */
> @@ -79,16 +74,11 @@ static void i915_restore_display(struct drm_device *dev)
>  		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);
>  
>  	/* Panel power sequencer */
> -	if (HAS_PCH_SPLIT(dev)) {
> -		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
> -		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
> -		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
> -		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
> -	} else if (INTEL_INFO(dev)->gen <= 4) {
> -		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
> -		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
> -		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
> -		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
> +	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
> +		I915_WRITE(PP_ON_DELAYS(0), dev_priv->regfile.savePP_ON_DELAYS);
> +		I915_WRITE(PP_OFF_DELAYS(0), dev_priv->regfile.savePP_OFF_DELAYS);
> +		I915_WRITE(PP_DIVISOR(0), dev_priv->regfile.savePP_DIVISOR);
> +		I915_WRITE(PP_CONTROL(0), dev_priv->regfile.savePP_CONTROL);
>  	}
>  
>  	/* only restore FBC info on the platform that supports FBC*/
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c6f27ab..3d5fd06 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1202,8 +1202,8 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
>  	if (HAS_PCH_SPLIT(dev)) {
>  		u32 port_sel;
>  
> -		pp_reg = PCH_PP_CONTROL;
> -		port_sel = I915_READ(PCH_PP_ON_DELAYS) & PANEL_PORT_SELECT_MASK;
> +		pp_reg = PP_CONTROL(0);
> +		port_sel = I915_READ(PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK;
>  
>  		if (port_sel == PANEL_PORT_SELECT_LVDS &&
>  		    I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
> @@ -1211,10 +1211,10 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
>  		/* XXX: else fix for eDP */
>  	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
>  		/* presumably write lock depends on pipe, not port select */
> -		pp_reg = VLV_PIPE_PP_CONTROL(pipe);
> +		pp_reg = PP_CONTROL(pipe);
>  		panel_pipe = pipe;
>  	} else {
> -		pp_reg = PP_CONTROL;
> +		pp_reg = PP_CONTROL(0);
>  		if (I915_READ(LVDS) & LVDS_PIPEB_SELECT)
>  			panel_pipe = PIPE_B;
>  	}
> @@ -9411,7 +9411,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
>  	I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
>  	I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
>  	I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
> -	I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
> +	I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n");
>  	I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
>  	     "CPU PWM1 enabled\n");
>  	if (IS_HASWELL(dev))
> @@ -14635,12 +14635,24 @@ static bool intel_crt_present(struct drm_device *dev)
>  	return true;
>  }
>  
> +static void intel_pps_init(struct drm_i915_private *dev_priv)
> +{
> +	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
> +		dev_priv->pps_mmio_base = PCH_PPS_BASE;
> +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		dev_priv->pps_mmio_base = VLV_PPS_BASE;
> +	else
> +		dev_priv->pps_mmio_base = PPS_BASE;
> +}
> +
>  static void intel_setup_outputs(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct intel_encoder *encoder;
>  	bool dpd_is_edp = false;
>  
> +	intel_pps_init(dev_priv);
> +
>  	/*
>  	 * intel_edp_init_connector() depends on this completing first, to
>  	 * prevent the registeration of both eDP and LVDS and the incorrect
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 8fe2afa..a5cef91 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -463,13 +463,13 @@ typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
>  static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
>  			       enum pipe pipe)
>  {
> -	return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
> +	return I915_READ(PP_STATUS(pipe)) & PP_ON;
>  }
>  
>  static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
>  				enum pipe pipe)
>  {
> -	return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
> +	return I915_READ(PP_CONTROL(pipe)) & EDP_FORCE_VDD;
>  }
>  
>  static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
> @@ -486,7 +486,7 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
>  	enum pipe pipe;
>  
>  	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
> -		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
> +		u32 port_sel = I915_READ(PP_ON_DELAYS(pipe)) &
>  			PANEL_PORT_SELECT_MASK;
>  
>  		if (port_sel != PANEL_PORT_SELECT_VLV(port))
> @@ -583,30 +583,23 @@ static void intel_pps_get_registers(struct drm_i915_private *dev_priv,
>  				    struct intel_dp *intel_dp,
>  				    struct pps_registers *regs)
>  {
> +	int pps_idx;
> +
>  	memset(regs, 0, sizeof(*regs));
>  
> -	if (IS_BROXTON(dev_priv)) {
> -		int idx = bxt_power_sequencer_idx(intel_dp);
> +	if (IS_BROXTON(dev_priv))
> +		pps_idx = bxt_power_sequencer_idx(intel_dp);
> +	else if (HAS_PCH_SPLIT(dev_priv))
> +		pps_idx = 0;

int pps_idx = 0;

if (BXT)
	...
else if (VLV||CHV)
	...

is how I'd write this.

> +	else
> +		pps_idx = vlv_power_sequencer_pipe(intel_dp);
>  
> -		regs->pp_ctrl = BXT_PP_CONTROL(idx);
> -		regs->pp_stat = BXT_PP_STATUS(idx);
> -		regs->pp_on = BXT_PP_ON_DELAYS(idx);
> -		regs->pp_off = BXT_PP_OFF_DELAYS(idx);
> -	} else if (HAS_PCH_SPLIT(dev_priv)) {
> -		regs->pp_ctrl = PCH_PP_CONTROL;
> -		regs->pp_stat = PCH_PP_STATUS;
> -		regs->pp_on = PCH_PP_ON_DELAYS;
> -		regs->pp_off = PCH_PP_OFF_DELAYS;
> -		regs->pp_div = PCH_PP_DIVISOR;
> -	} else {
> -		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> -
> -		regs->pp_ctrl = VLV_PIPE_PP_CONTROL(pipe);
> -		regs->pp_stat = VLV_PIPE_PP_STATUS(pipe);
> -		regs->pp_on = VLV_PIPE_PP_ON_DELAYS(pipe);
> -		regs->pp_off = VLV_PIPE_PP_OFF_DELAYS(pipe);
> -		regs->pp_div = VLV_PIPE_PP_DIVISOR(pipe);
> -	}
> +	regs->pp_ctrl = PP_CONTROL(pps_idx);
> +	regs->pp_stat = PP_STATUS(pps_idx);
> +	regs->pp_on = PP_ON_DELAYS(pps_idx);
> +	regs->pp_off = PP_OFF_DELAYS(pps_idx);
> +	if (!IS_BROXTON(dev_priv))
> +		regs->pp_div = PP_DIVISOR(pps_idx);
>  }
>  
>  static i915_reg_t
> @@ -651,8 +644,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
>  		i915_reg_t pp_ctrl_reg, pp_div_reg;
>  		u32 pp_div;
>  
> -		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> -		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> +		pp_ctrl_reg = PP_CONTROL(pipe);
> +		pp_div_reg  = PP_DIVISOR(pipe);
>  		pp_div = I915_READ(pp_div_reg);
>  		pp_div &= PP_REFERENCE_DIVIDER_MASK;
>  
> @@ -2729,7 +2722,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>  	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
>  	enum pipe pipe = intel_dp->pps_pipe;
> -	i915_reg_t pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
> +	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
>  
>  	edp_panel_vdd_off_sync(intel_dp);
>  
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 4955047..413e729 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -217,21 +217,12 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
>  	struct intel_connector *intel_connector =
>  		&lvds_encoder->attached_connector->base;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> -	i915_reg_t ctl_reg, stat_reg;
> -
> -	if (HAS_PCH_SPLIT(dev)) {
> -		ctl_reg = PCH_PP_CONTROL;
> -		stat_reg = PCH_PP_STATUS;
> -	} else {
> -		ctl_reg = PP_CONTROL;
> -		stat_reg = PP_STATUS;
> -	}
>  
>  	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
>  
> -	I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
> +	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | POWER_TARGET_ON);
>  	POSTING_READ(lvds_encoder->reg);
> -	if (intel_wait_for_register(dev_priv, stat_reg, PP_ON, PP_ON, 1000))
> +	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 1000))
>  		DRM_ERROR("timed out waiting for panel to power on\n");
>  
>  	intel_panel_enable_backlight(intel_connector);
> @@ -242,18 +233,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
>  	struct drm_device *dev = encoder->base.dev;
>  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> -	i915_reg_t ctl_reg, stat_reg;
>  
> -	if (HAS_PCH_SPLIT(dev)) {
> -		ctl_reg = PCH_PP_CONTROL;
> -		stat_reg = PCH_PP_STATUS;
> -	} else {
> -		ctl_reg = PP_CONTROL;
> -		stat_reg = PP_STATUS;
> -	}
> -
> -	I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
> -	if (intel_wait_for_register(dev_priv, stat_reg, PP_ON, 0, 1000))
> +	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~POWER_TARGET_ON);
> +	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, 0, 1000))
>  		DRM_ERROR("timed out waiting for panel to power off\n");
>  
>  	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
> @@ -904,13 +886,10 @@ void intel_lvds_init(struct drm_device *dev)
>  	 * Unlock registers and just leave them unlocked. Do this before
>  	 * checking quirk lists to avoid bogus WARNINGs.
>  	 */
> -	if (HAS_PCH_SPLIT(dev)) {
> -		I915_WRITE(PCH_PP_CONTROL,
> -			   I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
> -	} else if (INTEL_INFO(dev_priv)->gen < 5) {
> -		I915_WRITE(PP_CONTROL,
> -			   I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
> -	}
> +	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
> +		I915_WRITE(PP_CONTROL(0),
> +			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
> +
>  	if (!intel_lvds_supported(dev))
>  		return;
>  
> @@ -945,12 +924,12 @@ void intel_lvds_init(struct drm_device *dev)
>  
>  	 /* Set the Panel Power On/Off timings if uninitialized. */
>  	if (INTEL_INFO(dev_priv)->gen < 5 &&
> -	    I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) {
> +	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
>  		/* Set T2 to 40ms and T5 to 200ms */
> -		I915_WRITE(PP_ON_DELAYS, 0x019007d0);
> +		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
>  
>  		/* Set T3 to 35ms and Tx to 200ms */
> -		I915_WRITE(PP_OFF_DELAYS, 0x015e07d0);
> +		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
>  
>  		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
>  	}
> -- 
> 2.5.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✓ Ro.CI.BAT: success for drm/i915: Clean up LVDS/PPS macros, suspend/resume logic
  2016-08-09 11:34 [PATCH 0/6] drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Imre Deak
                   ` (5 preceding siblings ...)
  2016-08-09 11:34 ` [PATCH 6/6] drm/i915: Remove LVDS and PPS suspend time save/restore Imre Deak
@ 2016-08-09 12:05 ` Patchwork
  2016-08-10  9:35 ` ✗ Ro.CI.BAT: failure for drm/i915: Clean up LVDS/PPS macros, suspend/resume logic (rev7) Patchwork
  7 siblings, 0 replies; 30+ messages in thread
From: Patchwork @ 2016-08-09 12:05 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Clean up LVDS/PPS macros, suspend/resume logic
URL   : https://patchwork.freedesktop.org/series/10838/
State : success

== Summary ==

Series 10838v1 drm/i915: Clean up LVDS/PPS macros, suspend/resume logic
http://patchwork.freedesktop.org/api/1.0/series/10838/revisions/1/mbox


fi-hsw-i7-4770k  total:107  pass:91   dwarn:0   dfail:0   fail:0   skip:15 
fi-kbl-qkkr      total:107  pass:83   dwarn:0   dfail:0   fail:0   skip:23 
fi-skl-i5-6260u  total:107  pass:98   dwarn:0   dfail:0   fail:0   skip:8  
fi-skl-i7-6700k  total:107  pass:84   dwarn:0   dfail:0   fail:0   skip:22 
fi-snb-i7-2600   total:107  pass:77   dwarn:0   dfail:0   fail:0   skip:29 
ro-bdw-i5-5250u  total:107  pass:97   dwarn:0   dfail:0   fail:0   skip:9  
ro-bdw-i7-5557U  total:107  pass:97   dwarn:0   dfail:0   fail:0   skip:9  
ro-bdw-i7-5600u  total:107  pass:79   dwarn:0   dfail:0   fail:0   skip:27 
ro-bsw-n3050     total:240  pass:193  dwarn:0   dfail:0   fail:4   skip:43 
ro-byt-n2820     total:240  pass:197  dwarn:0   dfail:0   fail:3   skip:40 
ro-ilk1-i5-650   total:235  pass:173  dwarn:0   dfail:0   fail:2   skip:60 
ro-ivb-i7-3770   total:107  pass:80   dwarn:0   dfail:0   fail:0   skip:26 
ro-skl3-i5-6260u total:107  pass:98   dwarn:0   dfail:0   fail:0   skip:8  
ro-hsw-i3-4010u failed to connect after reboot
ro-hsw-i7-4770r failed to connect after reboot
ro-ivb2-i7-3770 failed to connect after reboot

Results at /archive/results/CI_IGT_test/RO_Patchwork_1778/

e220d47 drm-intel-nightly: 2016y-08m-09d-09h-18m-12s UTC integration manifest
ecf84d4 drm/i915: Remove LVDS and PPS suspend time save/restore
b90c74e drm/i915: Apply the PPS register unlock workaround more consistently
c4e2d16 drm/i915/dp: Restore PPS HW state from the encoder resume hook
a905ae5 drm/i915/lvds: Restore initial HW state during encoder enabling
1f1025b drm/i915: Merge TARGET_POWER_ON and PANEL_POWER_ON flag definitions
be99d98 drm/i915: Merge the PPS register definitions

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling
  2016-08-09 11:34 ` [PATCH 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling Imre Deak
@ 2016-08-09 12:48   ` Ville Syrjälä
  2016-08-09 14:40     ` Imre Deak
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
  1 sibling, 1 reply; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 12:48 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 02:34:09PM +0300, Imre Deak wrote:
> Atm the LVDS encoder depends on the PPS HW context being saved/restored
> from generic suspend/resume code. Since the PPS is specific to the LVDS
> and eDP encoders a cleaner way is to reinitialize it during encoder
> enabling, so do this here for LVDS. Follow-up patches will init the PPS
> for the eDP encoder similarly and remove the suspend/resume time save /
> restore.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h   |   1 +
>  drivers/gpu/drm/i915/intel_lvds.c | 103 +++++++++++++++++++++++++++++++++-----
>  2 files changed, 91 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 889508f..da82744 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3710,6 +3710,7 @@ enum {
>  
>  #define _PP_ON_DELAYS			0x61208
>  #define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
> +#define  PANEL_PORT_SELECT_SHIFT	30
>  #define  PANEL_PORT_SELECT_MASK		(3 << 30)
>  #define  PANEL_PORT_SELECT_LVDS		(0 << 30)
>  #define  PANEL_PORT_SELECT_DPA		(1 << 30)
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index c5739fc..d5158e5 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -48,6 +48,20 @@ struct intel_lvds_connector {
>  	struct notifier_block lid_notifier;
>  };
>  
> +struct intel_lvds_pps {
> +	/* 100us units */
> +	int t1_t2;
> +	int t3;
> +	int t4;
> +	int t5;
> +	int tx;
> +
> +	int divider;
> +
> +	int port;
> +	bool reset_on_powerdown;
> +};
> +
>  struct intel_lvds_encoder {
>  	struct intel_encoder base;
>  
> @@ -55,6 +69,9 @@ struct intel_lvds_encoder {
>  	i915_reg_t reg;
>  	u32 a3_power;
>  
> +	struct intel_lvds_pps init_pps;
> +	u32 init_lvds_val;
> +
>  	struct intel_lvds_connector *attached_connector;
>  };
>  
> @@ -136,6 +153,72 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
>  	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
>  }
>  
> +static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
> +					struct intel_lvds_pps *pps)
> +{
> +	u32 val;
> +
> +	pps->reset_on_powerdown = I915_READ(PP_CONTROL(0)) & PANEL_POWER_RESET;
> +
> +	val = I915_READ(PP_ON_DELAYS(0));
> +	pps->port = (val & PANEL_PORT_SELECT_MASK) >>
> +		    PANEL_PORT_SELECT_SHIFT;
> +	pps->t1_t2 = (val & PANEL_POWER_UP_DELAY_MASK) >>
> +		     PANEL_POWER_UP_DELAY_SHIFT;
> +	pps->t5 = (val & PANEL_LIGHT_ON_DELAY_MASK) >>
> +		  PANEL_LIGHT_ON_DELAY_SHIFT;
> +
> +	val = I915_READ(PP_OFF_DELAYS(0));
> +	pps->t3 = (val & PANEL_POWER_DOWN_DELAY_MASK) >>
> +		  PANEL_POWER_DOWN_DELAY_SHIFT;
> +	pps->tx = (val & PANEL_LIGHT_OFF_DELAY_MASK) >>
> +		  PANEL_LIGHT_OFF_DELAY_SHIFT;
> +
> +	val = I915_READ(PP_DIVISOR(0));
> +	pps->divider = (val & PP_REFERENCE_DIVIDER_MASK) >>
> +		       PP_REFERENCE_DIVIDER_SHIFT;
> +	/* Convert from 100ms to 100us units */
> +	pps->t4 = ((val & PANEL_POWER_CYCLE_DELAY_MASK) >>
> +		   PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;

This should have the +1 offset handling I think. Hmm. Looks like we mess
that up even for eDP :(

> +
> +	if (INTEL_INFO(dev_priv)->gen <= 4 &&
> +	    pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
> +		DRM_DEBUG_KMS("Panel power timings uninitialized, "
> +			      "setting defaults\n");
> +		/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
> +		pps->t1_t2 = 40 * 10;
> +		pps->t5 = 200 * 10;
> +		/* Set T3 to 35ms and Tx to 200ms in 100 usec units */
> +		pps->t3 = 35 * 10;
> +		pps->tx = 200 * 10;

Not sure where these came from originally. The spgw spec tells us:

min	max
t1	0.5	10
t2	0	50
t3	0	50
t4	200	-
t5	200	-
t6	200	-
t7	0	10

So maybe we should at least set t4=200 here based on the minimum t4
delay in the spec, probably should add the max t7 time there as well
as that's what the power cycle delays seems to be really: t4+t7.
Bspec seems to claim that spgw spec has an upper limit of 400 for this,
but I can't see that at least in the copy I found.

And maybe bump up t1_t2=60 and t3=50 based on the max delay for those
in the spec?

Anyways, this is all material for a separate patch for sure.

> +	}
> +
> +	DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
> +			 "divider %d port %d reset_on_powerdown %d\n",
> +			 pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
> +			 pps->divider, pps->port, pps->reset_on_powerdown);
> +}
> +
> +static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
> +				   struct intel_lvds_pps *pps)
> +{
> +	u32 val;
> +
> +	val = I915_READ(PP_CONTROL(0));
> +	WARN_ON((val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);
> +	if (pps->reset_on_powerdown)
> +		val |= PANEL_POWER_RESET;

Hmm. Maybe we can just always set this bit? Hmm, we also totally fail to
deal with the related IBX w/a in the LVDS code. Should probably fix that
up as well as a followup.

> +	I915_WRITE(PP_CONTROL(0), val);
> +
> +	I915_WRITE(PP_ON_DELAYS(0), (pps->port << PANEL_PORT_SELECT_SHIFT) |
> +				    (pps->t1_t2 << PANEL_POWER_UP_DELAY_SHIFT) |
> +				    (pps->t5 << PANEL_LIGHT_ON_DELAY_SHIFT));
> +	I915_WRITE(PP_OFF_DELAYS(0), (pps->t3 << PANEL_POWER_DOWN_DELAY_SHIFT) |
> +				     (pps->tx << PANEL_LIGHT_OFF_DELAY_SHIFT));
> +	I915_WRITE(PP_DIVISOR(0), (pps->divider << PP_REFERENCE_DIVIDER_SHIFT) |
> +				  ((pps->t4 / 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT));

DIV_ROUND_UP() I think, and maybe the +1 handling. Though I can't really
tell if the spec has intended the +1 to be a replacement for rounding
up, or do we need to do both. Both would seem like the safe choice. Gen2
Bspec doesn't mention the +1, but it says writing 0 will even abort any
ongoing delay.

> +}
> +
>  static void intel_pre_enable_lvds(struct intel_encoder *encoder)
>  {
>  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
> @@ -154,7 +237,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder)
>  		assert_pll_disabled(dev_priv, pipe);
>  	}
>  
> -	temp = I915_READ(lvds_encoder->reg);
> +	intel_lvds_pps_init_hw(dev_priv, &lvds_encoder->init_pps);
> +
> +	temp = lvds_encoder->init_lvds_val;
>  	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
>  
>  	if (HAS_PCH_CPT(dev)) {
> @@ -922,18 +1007,6 @@ void intel_lvds_init(struct drm_device *dev)
>  		DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
>  	}
>  
> -	 /* Set the Panel Power On/Off timings if uninitialized. */
> -	if (INTEL_INFO(dev_priv)->gen < 5 &&
> -	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
> -		/* Set T2 to 40ms and T5 to 200ms */
> -		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
> -
> -		/* Set T3 to 35ms and Tx to 200ms */
> -		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
> -
> -		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
> -	}
> -
>  	lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
>  	if (!lvds_encoder)
>  		return;
> @@ -999,6 +1072,10 @@ void intel_lvds_init(struct drm_device *dev)
>  				      dev->mode_config.scaling_mode_property,
>  				      DRM_MODE_SCALE_ASPECT);
>  	intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
> +
> +	intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps);
> +	lvds_encoder->init_lvds_val = lvds;
> +
>  	/*
>  	 * LVDS discovery:
>  	 * 1) check for EDID on DDC
> -- 
> 2.5.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 4/6] drm/i915/dp: Restore PPS HW state from the encoder resume hook
  2016-08-09 11:34 ` [PATCH 4/6] drm/i915/dp: Restore PPS HW state from the encoder resume hook Imre Deak
@ 2016-08-09 12:52   ` Ville Syrjälä
  2016-08-09 15:15     ` Imre Deak
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
  1 sibling, 1 reply; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 12:52 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 02:34:10PM +0300, Imre Deak wrote:
> Similarly to the previous patch, initialize the PPS from the DP
> encoder's resume hook. Note that as opposed to LVDS we can't do this
> during encoder enabling, since we need the PPS for DP detection as well.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 4796ad7..76f5b72 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -4665,6 +4665,9 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
>  	 */
>  	if (IS_VALLEYVIEW(encoder->dev) || IS_CHERRYVIEW(encoder->dev))
>  		vlv_initial_power_sequencer_setup(intel_dp);
> +	else
> +		intel_dp_init_panel_power_sequencer_registers(encoder->dev,
> +							      intel_dp);

This is almosts the same code as we have in intel_edp_init_connector(),
excep not calling intel_dp_init_panel_power_sequencer() for !VLV/CHV.

intel_dp_init_panel_power_sequencer() should be safe to call multiple
times since it checks if things were already initialized, and we already
call it here for VLV/CHV. So I think we should just be able share the
code for init and resume?

>  
>  	intel_edp_panel_vdd_sanitize(intel_dp);
>  
> -- 
> 2.5.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 5/6] drm/i915: Apply the PPS register unlock workaround more consistently
  2016-08-09 11:34 ` [PATCH 5/6] drm/i915: Apply the PPS register unlock workaround more consistently Imre Deak
@ 2016-08-09 13:01   ` Ville Syrjälä
  2016-08-09 15:17     ` Imre Deak
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
  1 sibling, 1 reply; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 13:01 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 02:34:11PM +0300, Imre Deak wrote:
> Atm, we apply this workaround somewhat inconsistently at the following
> points: driver loading, LVDS init, eDP PPS init, system resume. As this
> workaround also affects registers other than PPS (timing, PLL) a more
> consistent way is to apply it early after the PPS HW context is known to
> be lost: driver loading, system resume and on VLV/CHV/BXT when turning
> on power domains.
> 
> This is needed by the next patch that removes saving/restoring of the
> PP_CONTROL register.
> 
> This also removes the incorrect programming of the workaround on HSW+
> PCH platforms which don't have the register locking mechanism.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c         |  1 +
>  drivers/gpu/drm/i915/intel_display.c    | 28 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_dp.c         |  4 +++-
>  drivers/gpu/drm/i915/intel_drv.h        |  1 +
>  drivers/gpu/drm/i915/intel_lvds.c       |  8 --------
>  drivers/gpu/drm/i915/intel_runtime_pm.c |  4 ++++
>  6 files changed, 37 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 8cfc264..0fcd1c0 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1560,6 +1560,7 @@ static int i915_drm_resume(struct drm_device *dev)
>  	i915_gem_resume(dev);
>  
>  	i915_restore_state(dev);
> +	intel_pps_unlock_regs_wa(dev_priv);
>  	intel_opregion_setup(dev_priv);
>  
>  	intel_init_pch_refclk(dev);
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3d5fd06..dc4e600 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -14635,6 +14635,32 @@ static bool intel_crt_present(struct drm_device *dev)
>  	return true;
>  }
>  
> +void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
> +{
> +	int pps_num;
> +	int pps_idx;
> +
> +	/*
> +	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
> +	 * everywhere where registers can be write protected.
> +	 */
> +	if (INTEL_GEN(dev_priv) <= 4 ||
> +	    HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
> +		pps_num = 1;
> +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv) ||
> +		 IS_BROXTON(dev_priv))
> +		pps_num = 2;
> +	else
> +		pps_num = 0;

BXT shouldn't need the unlock, I think.

So I believe we just want

if (HAS_DDI())
	return;

if (VLV||CHV)
	num = 2;
else
	num = 1;

> +
> +	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
> +		u32 val = I915_READ(PP_CONTROL(pps_idx));
> +
> +		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
> +		I915_WRITE(PP_CONTROL(pps_idx), val);
> +	}
> +}
> +
>  static void intel_pps_init(struct drm_i915_private *dev_priv)
>  {
>  	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
> @@ -14643,6 +14669,8 @@ static void intel_pps_init(struct drm_i915_private *dev_priv)
>  		dev_priv->pps_mmio_base = VLV_PPS_BASE;
>  	else
>  		dev_priv->pps_mmio_base = PPS_BASE;
> +
> +	intel_pps_unlock_regs_wa(dev_priv);
>  }
>  
>  static void intel_setup_outputs(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 76f5b72..b27f1c5 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1829,7 +1829,9 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
>  	control = I915_READ(_pp_ctrl_reg(intel_dp));
> -	if (!IS_BROXTON(dev)) {
> +	if (WARN_ON((HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) ||
> +		     IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&

!HAS_DDI

> +		     (control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
>  		control &= ~PANEL_UNLOCK_MASK;
>  		control |= PANEL_UNLOCK_REGS;
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index c29a429..cbce786 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1159,6 +1159,7 @@ void intel_mark_busy(struct drm_i915_private *dev_priv);
>  void intel_mark_idle(struct drm_i915_private *dev_priv);
>  void intel_crtc_restore_mode(struct drm_crtc *crtc);
>  int intel_display_suspend(struct drm_device *dev);
> +void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
>  void intel_encoder_destroy(struct drm_encoder *encoder);
>  int intel_connector_init(struct intel_connector *);
>  struct intel_connector *intel_connector_alloc(void);
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index d5158e5..9a6e1ad 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -967,14 +967,6 @@ void intel_lvds_init(struct drm_device *dev)
>  	int pipe;
>  	u8 pin;
>  
> -	/*
> -	 * Unlock registers and just leave them unlocked. Do this before
> -	 * checking quirk lists to avoid bogus WARNINGs.
> -	 */
> -	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
> -		I915_WRITE(PP_CONTROL(0),
> -			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
> -
>  	if (!intel_lvds_supported(dev))
>  		return;
>  
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 1c603bb..8f51ae3 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -592,6 +592,8 @@ void bxt_disable_dc9(struct drm_i915_private *dev_priv)
>  	DRM_DEBUG_KMS("Disabling DC9\n");
>  
>  	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
> +
> +	intel_pps_unlock_regs_wa(dev_priv);
>  }
>  
>  static void assert_csr_loaded(struct drm_i915_private *dev_priv)
> @@ -1145,6 +1147,8 @@ static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
>  	vlv_set_power_well(dev_priv, power_well, true);
>  
>  	vlv_display_power_well_init(dev_priv);
> +
> +	intel_pps_unlock_regs_wa(dev_priv);
>  }
>  
>  static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
> -- 
> 2.5.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 1/6] drm/i915: Merge the PPS register definitions
  2016-08-09 11:53   ` Ville Syrjälä
@ 2016-08-09 13:24     ` Imre Deak
  0 siblings, 0 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 13:24 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On ti, 2016-08-09 at 14:53 +0300, Ville Syrjälä wrote:
> On Tue, Aug 09, 2016 at 02:34:07PM +0300, Imre Deak wrote:
> > The PPS registers are pretty much the same everywhere, the differences
> > being:
> > - Register fields appearing, disappearing from one platform to the
> >   next: panel-reset-on-powerdown, backlight-on, panel-port,
> >   register-unlock
> > - Different register base addresses
> > - Different number of PPS instances: 2 on VLV/CHV/BXT, 1 everywhere
> >   else.
> > 
> > We can merge the separate set of PPS definitions by extending the PPS
> > instance argument to all platforms and using instance 0 on platforms
> > with a single instance. This means we'll need to calculate the register
> > addresses dynamically based on the given platform and PPS instance.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.h      |   2 +
> >  drivers/gpu/drm/i915/i915_reg.h      | 145 ++++++++++++++---------------------
> >  drivers/gpu/drm/i915/i915_suspend.c  |  30 +++-----
> >  drivers/gpu/drm/i915/intel_display.c |  22 ++++--
> >  drivers/gpu/drm/i915/intel_dp.c      |  47 +++++-------
> >  drivers/gpu/drm/i915/intel_lvds.c    |  43 +++--------
> >  6 files changed, 119 insertions(+), 170 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index c36d176..fddaec6 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1749,6 +1749,8 @@ struct drm_i915_private {
> >  
> >  	uint32_t psr_mmio_base;
> >  
> > +	uint32_t pps_mmio_base;
> > +
> >  	wait_queue_head_t gmbus_wait_queue;
> >  
> >  	struct pci_dev *bridge_dev;
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index f38a5e2..b65fe50 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -3660,8 +3660,17 @@ enum {
> >  #define   VIDEO_DIP_ENABLE_SPD_HSW	(1 << 0)
> >  
> >  /* Panel power sequencing */
> > -#define PP_STATUS	_MMIO(0x61200)
> > -#define   PP_ON		(1 << 31)
> > +#define PPS_BASE			0x61200
> > +#define VLV_PPS_BASE			(VLV_DISPLAY_BASE + PPS_BASE)
> > +#define PCH_PPS_BASE			0xC7200
> > +
> > +#define _MMIO_PPS(pps_idx, reg)		_MMIO(dev_priv->pps_mmio_base -	\
> > +					      PPS_BASE + (reg) +	\
> > +					      (pps_idx) * 0x100)
> > +
> > +#define _PP_STATUS			0x61200
> > +#define PP_STATUS(pps_idx)		_MMIO_PPS(pps_idx, _PP_STATUS)
> > +#define   PP_ON				(1 << 31)
> >  /*
> >   * Indicates that all dependencies of the panel are on:
> >   *
> > @@ -3669,14 +3678,14 @@ enum {
> >   * - pipe enabled
> >   * - LVDS/DVOB/DVOC on
> >   */
> > -#define   PP_READY		(1 << 30)
> > -#define   PP_SEQUENCE_NONE	(0 << 28)
> > -#define   PP_SEQUENCE_POWER_UP	(1 << 28)
> > -#define   PP_SEQUENCE_POWER_DOWN (2 << 28)
> > -#define   PP_SEQUENCE_MASK	(3 << 28)
> > -#define   PP_SEQUENCE_SHIFT	28
> > -#define   PP_CYCLE_DELAY_ACTIVE	(1 << 27)
> > -#define   PP_SEQUENCE_STATE_MASK 0x0000000f
> > +#define   PP_READY			(1 << 30)
> > +#define   PP_SEQUENCE_NONE		(0 << 28)
> > +#define   PP_SEQUENCE_POWER_UP		(1 << 28)
> > +#define   PP_SEQUENCE_POWER_DOWN	(2 << 28)
> > +#define   PP_SEQUENCE_MASK		(3 << 28)
> > +#define   PP_SEQUENCE_SHIFT		28
> > +#define   PP_CYCLE_DELAY_ACTIVE		(1 << 27)
> > +#define   PP_SEQUENCE_STATE_MASK	0x0000000f
> >  #define   PP_SEQUENCE_STATE_OFF_IDLE	(0x0 << 0)
> >  #define   PP_SEQUENCE_STATE_OFF_S0_1	(0x1 << 0)
> >  #define   PP_SEQUENCE_STATE_OFF_S0_2	(0x2 << 0)
> > @@ -3686,11 +3695,46 @@ enum {
> >  #define   PP_SEQUENCE_STATE_ON_S1_2	(0xa << 0)
> >  #define   PP_SEQUENCE_STATE_ON_S1_3	(0xb << 0)
> >  #define   PP_SEQUENCE_STATE_RESET	(0xf << 0)
> > -#define PP_CONTROL	_MMIO(0x61204)
> > -#define   POWER_TARGET_ON	(1 << 0)
> > -#define PP_ON_DELAYS	_MMIO(0x61208)
> > -#define PP_OFF_DELAYS	_MMIO(0x6120c)
> > -#define PP_DIVISOR	_MMIO(0x61210)
> > +
> > +#define _PP_CONTROL			0x61204
> > +#define PP_CONTROL(pps_idx)		_MMIO_PPS(pps_idx, _PP_CONTROL)
> > +#define  PANEL_UNLOCK_REGS		(0xabcd << 16)
> > +#define  PANEL_UNLOCK_MASK		(0xffff << 16)
> > +#define  BXT_POWER_CYCLE_DELAY_MASK	0x1f0
> > +#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
> > +#define  EDP_FORCE_VDD			(1 << 3)
> > +#define  EDP_BLC_ENABLE			(1 << 2)
> > +#define  PANEL_POWER_RESET		(1 << 1)
> > +#define  PANEL_POWER_OFF		(0 << 0)
> > +#define  PANEL_POWER_ON			(1 << 0)
> > +#define  POWER_TARGET_ON		(1 << 0)
> > +
> > +#define _PP_ON_DELAYS			0x61208
> > +#define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
> > +#define  PANEL_PORT_SELECT_MASK		(3 << 30)
> > +#define  PANEL_PORT_SELECT_LVDS		(0 << 30)
> > +#define  PANEL_PORT_SELECT_DPA		(1 << 30)
> > +#define  PANEL_PORT_SELECT_DPC		(2 << 30)
> > +#define  PANEL_PORT_SELECT_DPD		(3 << 30)
> > +#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
> > +#define  PANEL_POWER_UP_DELAY_MASK	0x1fff0000
> > +#define  PANEL_POWER_UP_DELAY_SHIFT	16
> > +#define  PANEL_LIGHT_ON_DELAY_MASK	0x1fff
> > +#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
> > +
> > +#define _PP_OFF_DELAYS			0x6120C
> > +#define PP_OFF_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_OFF_DELAYS)
> > +#define  PANEL_POWER_DOWN_DELAY_MASK	0x1fff0000
> > +#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
> > +#define  PANEL_LIGHT_OFF_DELAY_MASK	0x1fff
> > +#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
> > +
> > +#define _PP_DIVISOR			0x61210
> > +#define PP_DIVISOR(pps_idx)		_MMIO_PPS(pps_idx, _PP_DIVISOR)
> > +#define  PP_REFERENCE_DIVIDER_MASK	0xffffff00
> > +#define  PP_REFERENCE_DIVIDER_SHIFT	8
> > +#define  PANEL_POWER_CYCLE_DELAY_MASK	0x1f
> > +#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
> >  
> >  /* Panel fitting */
> >  #define PFIT_CONTROL	_MMIO(dev_priv->info.display_mmio_offset + 0x61230)
> > @@ -6750,77 +6794,6 @@ enum {
> >  #define PCH_LVDS	_MMIO(0xe1180)
> >  #define  LVDS_DETECTED	(1 << 1)
> >  
> > -/* vlv has 2 sets of panel control regs. */
> > -#define _PIPEA_PP_STATUS         (VLV_DISPLAY_BASE + 0x61200)
> > -#define _PIPEA_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61204)
> > -#define _PIPEA_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61208)
> > -#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
> > -#define _PIPEA_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6120c)
> > -#define _PIPEA_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61210)
> > -
> > -#define _PIPEB_PP_STATUS         (VLV_DISPLAY_BASE + 0x61300)
> > -#define _PIPEB_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61304)
> > -#define _PIPEB_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61308)
> > -#define _PIPEB_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6130c)
> > -#define _PIPEB_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61310)
> > -
> > -#define VLV_PIPE_PP_STATUS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_STATUS, _PIPEB_PP_STATUS)
> > -#define VLV_PIPE_PP_CONTROL(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_CONTROL, _PIPEB_PP_CONTROL)
> > -#define VLV_PIPE_PP_ON_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_ON_DELAYS, _PIPEB_PP_ON_DELAYS)
> > -#define VLV_PIPE_PP_OFF_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_OFF_DELAYS, _PIPEB_PP_OFF_DELAYS)
> > -#define VLV_PIPE_PP_DIVISOR(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_DIVISOR, _PIPEB_PP_DIVISOR)
> > -
> > -#define _PCH_PP_STATUS		0xc7200
> > -#define _PCH_PP_CONTROL		0xc7204
> > -#define  PANEL_UNLOCK_REGS	(0xabcd << 16)
> > -#define  PANEL_UNLOCK_MASK	(0xffff << 16)
> > -#define  BXT_POWER_CYCLE_DELAY_MASK	(0x1f0)
> > -#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
> > -#define  EDP_FORCE_VDD		(1 << 3)
> > -#define  EDP_BLC_ENABLE		(1 << 2)
> > -#define  PANEL_POWER_RESET	(1 << 1)
> > -#define  PANEL_POWER_OFF	(0 << 0)
> > -#define  PANEL_POWER_ON		(1 << 0)
> > -#define _PCH_PP_ON_DELAYS	0xc7208
> > -#define  PANEL_PORT_SELECT_MASK	(3 << 30)
> > -#define  PANEL_PORT_SELECT_LVDS	(0 << 30)
> > -#define  PANEL_PORT_SELECT_DPA	(1 << 30)
> > -#define  PANEL_PORT_SELECT_DPC	(2 << 30)
> > -#define  PANEL_PORT_SELECT_DPD	(3 << 30)
> > -#define  PANEL_POWER_UP_DELAY_MASK	(0x1fff0000)
> > -#define  PANEL_POWER_UP_DELAY_SHIFT	16
> > -#define  PANEL_LIGHT_ON_DELAY_MASK	(0x1fff)
> > -#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
> > -
> > -#define _PCH_PP_OFF_DELAYS		0xc720c
> > -#define  PANEL_POWER_DOWN_DELAY_MASK	(0x1fff0000)
> > -#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
> > -#define  PANEL_LIGHT_OFF_DELAY_MASK	(0x1fff)
> > -#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
> > -
> > -#define _PCH_PP_DIVISOR			0xc7210
> > -#define  PP_REFERENCE_DIVIDER_MASK	(0xffffff00)
> > -#define  PP_REFERENCE_DIVIDER_SHIFT	8
> > -#define  PANEL_POWER_CYCLE_DELAY_MASK	(0x1f)
> > -#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
> > -
> > -#define PCH_PP_STATUS			_MMIO(_PCH_PP_STATUS)
> > -#define PCH_PP_CONTROL			_MMIO(_PCH_PP_CONTROL)
> > -#define PCH_PP_ON_DELAYS		_MMIO(_PCH_PP_ON_DELAYS)
> > -#define PCH_PP_OFF_DELAYS		_MMIO(_PCH_PP_OFF_DELAYS)
> > -#define PCH_PP_DIVISOR			_MMIO(_PCH_PP_DIVISOR)
> > -
> > -/* BXT PPS changes - 2nd set of PPS registers */
> > -#define _BXT_PP_STATUS2 	0xc7300
> > -#define _BXT_PP_CONTROL2 	0xc7304
> > -#define _BXT_PP_ON_DELAYS2	0xc7308
> > -#define _BXT_PP_OFF_DELAYS2	0xc730c
> > -
> > -#define BXT_PP_STATUS(n)	_MMIO_PIPE(n, _PCH_PP_STATUS, _BXT_PP_STATUS2)
> > -#define BXT_PP_CONTROL(n)	_MMIO_PIPE(n, _PCH_PP_CONTROL, _BXT_PP_CONTROL2)
> > -#define BXT_PP_ON_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2)
> > -#define BXT_PP_OFF_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2)
> > -
> >  #define _PCH_DP_B		0xe4100
> >  #define PCH_DP_B		_MMIO(_PCH_DP_B)
> >  #define _PCH_DPB_AUX_CH_CTL	0xe4110
> > diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
> > index 5cfe4c7..c826b69 100644
> > --- a/drivers/gpu/drm/i915/i915_suspend.c
> > +++ b/drivers/gpu/drm/i915/i915_suspend.c
> > @@ -44,16 +44,11 @@ static void i915_save_display(struct drm_device *dev)
> >  		dev_priv->regfile.saveLVDS = I915_READ(LVDS);
> >  
> >  	/* Panel power sequencer */
> > -	if (HAS_PCH_SPLIT(dev)) {
> > -		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
> > -		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
> > -		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
> > -		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
> > -	} else if (INTEL_INFO(dev)->gen <= 4) {
> > -		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
> > -		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
> > -		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
> > -		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
> > +	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
> > +		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL(0));
> > +		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS(0));
> > +		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS(0));
> > +		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR(0));
> >  	}
> >  
> >  	/* save FBC interval */
> > @@ -79,16 +74,11 @@ static void i915_restore_display(struct drm_device *dev)
> >  		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);
> >  
> >  	/* Panel power sequencer */
> > -	if (HAS_PCH_SPLIT(dev)) {
> > -		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
> > -		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
> > -		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
> > -		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
> > -	} else if (INTEL_INFO(dev)->gen <= 4) {
> > -		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
> > -		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
> > -		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
> > -		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
> > +	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
> > +		I915_WRITE(PP_ON_DELAYS(0), dev_priv->regfile.savePP_ON_DELAYS);
> > +		I915_WRITE(PP_OFF_DELAYS(0), dev_priv->regfile.savePP_OFF_DELAYS);
> > +		I915_WRITE(PP_DIVISOR(0), dev_priv->regfile.savePP_DIVISOR);
> > +		I915_WRITE(PP_CONTROL(0), dev_priv->regfile.savePP_CONTROL);
> >  	}
> >  
> >  	/* only restore FBC info on the platform that supports FBC*/
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index c6f27ab..3d5fd06 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -1202,8 +1202,8 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
> >  	if (HAS_PCH_SPLIT(dev)) {
> >  		u32 port_sel;
> >  
> > -		pp_reg = PCH_PP_CONTROL;
> > -		port_sel = I915_READ(PCH_PP_ON_DELAYS) & PANEL_PORT_SELECT_MASK;
> > +		pp_reg = PP_CONTROL(0);
> > +		port_sel = I915_READ(PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK;
> >  
> >  		if (port_sel == PANEL_PORT_SELECT_LVDS &&
> >  		    I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
> > @@ -1211,10 +1211,10 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
> >  		/* XXX: else fix for eDP */
> >  	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
> >  		/* presumably write lock depends on pipe, not port select */
> > -		pp_reg = VLV_PIPE_PP_CONTROL(pipe);
> > +		pp_reg = PP_CONTROL(pipe);
> >  		panel_pipe = pipe;
> >  	} else {
> > -		pp_reg = PP_CONTROL;
> > +		pp_reg = PP_CONTROL(0);
> >  		if (I915_READ(LVDS) & LVDS_PIPEB_SELECT)
> >  			panel_pipe = PIPE_B;
> >  	}
> > @@ -9411,7 +9411,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
> >  	I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
> >  	I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
> >  	I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
> > -	I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
> > +	I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n");
> >  	I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
> >  	     "CPU PWM1 enabled\n");
> >  	if (IS_HASWELL(dev))
> > @@ -14635,12 +14635,24 @@ static bool intel_crt_present(struct drm_device *dev)
> >  	return true;
> >  }
> >  
> > +static void intel_pps_init(struct drm_i915_private *dev_priv)
> > +{
> > +	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
> > +		dev_priv->pps_mmio_base = PCH_PPS_BASE;
> > +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> > +		dev_priv->pps_mmio_base = VLV_PPS_BASE;
> > +	else
> > +		dev_priv->pps_mmio_base = PPS_BASE;
> > +}
> > +
> >  static void intel_setup_outputs(struct drm_device *dev)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	struct intel_encoder *encoder;
> >  	bool dpd_is_edp = false;
> >  
> > +	intel_pps_init(dev_priv);
> > +
> >  	/*
> >  	 * intel_edp_init_connector() depends on this completing first, to
> >  	 * prevent the registeration of both eDP and LVDS and the incorrect
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 8fe2afa..a5cef91 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -463,13 +463,13 @@ typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
> >  static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
> >  			       enum pipe pipe)
> >  {
> > -	return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
> > +	return I915_READ(PP_STATUS(pipe)) & PP_ON;
> >  }
> >  
> >  static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
> >  				enum pipe pipe)
> >  {
> > -	return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
> > +	return I915_READ(PP_CONTROL(pipe)) & EDP_FORCE_VDD;
> >  }
> >  
> >  static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
> > @@ -486,7 +486,7 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
> >  	enum pipe pipe;
> >  
> >  	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
> > -		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
> > +		u32 port_sel = I915_READ(PP_ON_DELAYS(pipe)) &
> >  			PANEL_PORT_SELECT_MASK;
> >  
> >  		if (port_sel != PANEL_PORT_SELECT_VLV(port))
> > @@ -583,30 +583,23 @@ static void intel_pps_get_registers(struct drm_i915_private *dev_priv,
> >  				    struct intel_dp *intel_dp,
> >  				    struct pps_registers *regs)
> >  {
> > +	int pps_idx;
> > +
> >  	memset(regs, 0, sizeof(*regs));
> >  
> > -	if (IS_BROXTON(dev_priv)) {
> > -		int idx = bxt_power_sequencer_idx(intel_dp);
> > +	if (IS_BROXTON(dev_priv))
> > +		pps_idx = bxt_power_sequencer_idx(intel_dp);
> > +	else if (HAS_PCH_SPLIT(dev_priv))
> > +		pps_idx = 0;
> 
> int pps_idx = 0;
> 
> if (BXT)
> 	...
> else if (VLV||CHV)
> 	...
> 
> is how I'd write this.

Ok, will change it.

> 
> > +	else
> > +		pps_idx = vlv_power_sequencer_pipe(intel_dp);
> >  
> > -		regs->pp_ctrl = BXT_PP_CONTROL(idx);
> > -		regs->pp_stat = BXT_PP_STATUS(idx);
> > -		regs->pp_on = BXT_PP_ON_DELAYS(idx);
> > -		regs->pp_off = BXT_PP_OFF_DELAYS(idx);
> > -	} else if (HAS_PCH_SPLIT(dev_priv)) {
> > -		regs->pp_ctrl = PCH_PP_CONTROL;
> > -		regs->pp_stat = PCH_PP_STATUS;
> > -		regs->pp_on = PCH_PP_ON_DELAYS;
> > -		regs->pp_off = PCH_PP_OFF_DELAYS;
> > -		regs->pp_div = PCH_PP_DIVISOR;
> > -	} else {
> > -		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> > -
> > -		regs->pp_ctrl = VLV_PIPE_PP_CONTROL(pipe);
> > -		regs->pp_stat = VLV_PIPE_PP_STATUS(pipe);
> > -		regs->pp_on = VLV_PIPE_PP_ON_DELAYS(pipe);
> > -		regs->pp_off = VLV_PIPE_PP_OFF_DELAYS(pipe);
> > -		regs->pp_div = VLV_PIPE_PP_DIVISOR(pipe);
> > -	}
> > +	regs->pp_ctrl = PP_CONTROL(pps_idx);
> > +	regs->pp_stat = PP_STATUS(pps_idx);
> > +	regs->pp_on = PP_ON_DELAYS(pps_idx);
> > +	regs->pp_off = PP_OFF_DELAYS(pps_idx);
> > +	if (!IS_BROXTON(dev_priv))
> > +		regs->pp_div = PP_DIVISOR(pps_idx);
> >  }
> >  
> >  static i915_reg_t
> > @@ -651,8 +644,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
> >  		i915_reg_t pp_ctrl_reg, pp_div_reg;
> >  		u32 pp_div;
> >  
> > -		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> > -		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> > +		pp_ctrl_reg = PP_CONTROL(pipe);
> > +		pp_div_reg  = PP_DIVISOR(pipe);
> >  		pp_div = I915_READ(pp_div_reg);
> >  		pp_div &= PP_REFERENCE_DIVIDER_MASK;
> >  
> > @@ -2729,7 +2722,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
> >  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> >  	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
> >  	enum pipe pipe = intel_dp->pps_pipe;
> > -	i915_reg_t pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
> > +	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
> >  
> >  	edp_panel_vdd_off_sync(intel_dp);
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> > index 4955047..413e729 100644
> > --- a/drivers/gpu/drm/i915/intel_lvds.c
> > +++ b/drivers/gpu/drm/i915/intel_lvds.c
> > @@ -217,21 +217,12 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
> >  	struct intel_connector *intel_connector =
> >  		&lvds_encoder->attached_connector->base;
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> > -	i915_reg_t ctl_reg, stat_reg;
> > -
> > -	if (HAS_PCH_SPLIT(dev)) {
> > -		ctl_reg = PCH_PP_CONTROL;
> > -		stat_reg = PCH_PP_STATUS;
> > -	} else {
> > -		ctl_reg = PP_CONTROL;
> > -		stat_reg = PP_STATUS;
> > -	}
> >  
> >  	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
> >  
> > -	I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
> > +	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | POWER_TARGET_ON);
> >  	POSTING_READ(lvds_encoder->reg);
> > -	if (intel_wait_for_register(dev_priv, stat_reg, PP_ON, PP_ON, 1000))
> > +	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 1000))
> >  		DRM_ERROR("timed out waiting for panel to power on\n");
> >  
> >  	intel_panel_enable_backlight(intel_connector);
> > @@ -242,18 +233,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
> >  	struct drm_device *dev = encoder->base.dev;
> >  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> > -	i915_reg_t ctl_reg, stat_reg;
> >  
> > -	if (HAS_PCH_SPLIT(dev)) {
> > -		ctl_reg = PCH_PP_CONTROL;
> > -		stat_reg = PCH_PP_STATUS;
> > -	} else {
> > -		ctl_reg = PP_CONTROL;
> > -		stat_reg = PP_STATUS;
> > -	}
> > -
> > -	I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
> > -	if (intel_wait_for_register(dev_priv, stat_reg, PP_ON, 0, 1000))
> > +	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~POWER_TARGET_ON);
> > +	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, 0, 1000))
> >  		DRM_ERROR("timed out waiting for panel to power off\n");
> >  
> >  	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
> > @@ -904,13 +886,10 @@ void intel_lvds_init(struct drm_device *dev)
> >  	 * Unlock registers and just leave them unlocked. Do this before
> >  	 * checking quirk lists to avoid bogus WARNINGs.
> >  	 */
> > -	if (HAS_PCH_SPLIT(dev)) {
> > -		I915_WRITE(PCH_PP_CONTROL,
> > -			   I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
> > -	} else if (INTEL_INFO(dev_priv)->gen < 5) {
> > -		I915_WRITE(PP_CONTROL,
> > -			   I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
> > -	}
> > +	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
> > +		I915_WRITE(PP_CONTROL(0),
> > +			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
> > +
> >  	if (!intel_lvds_supported(dev))
> >  		return;
> >  
> > @@ -945,12 +924,12 @@ void intel_lvds_init(struct drm_device *dev)
> >  
> >  	 /* Set the Panel Power On/Off timings if uninitialized. */
> >  	if (INTEL_INFO(dev_priv)->gen < 5 &&
> > -	    I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) {
> > +	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
> >  		/* Set T2 to 40ms and T5 to 200ms */
> > -		I915_WRITE(PP_ON_DELAYS, 0x019007d0);
> > +		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
> >  
> >  		/* Set T3 to 35ms and Tx to 200ms */
> > -		I915_WRITE(PP_OFF_DELAYS, 0x015e07d0);
> > +		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
> >  
> >  		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
> >  	}
> > -- 
> > 2.5.0
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling
  2016-08-09 12:48   ` Ville Syrjälä
@ 2016-08-09 14:40     ` Imre Deak
  2016-08-09 14:55       ` Ville Syrjälä
  0 siblings, 1 reply; 30+ messages in thread
From: Imre Deak @ 2016-08-09 14:40 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On ti, 2016-08-09 at 15:48 +0300, Ville Syrjälä wrote:
> On Tue, Aug 09, 2016 at 02:34:09PM +0300, Imre Deak wrote:
> > Atm the LVDS encoder depends on the PPS HW context being saved/restored
> > from generic suspend/resume code. Since the PPS is specific to the LVDS
> > and eDP encoders a cleaner way is to reinitialize it during encoder
> > enabling, so do this here for LVDS. Follow-up patches will init the PPS
> > for the eDP encoder similarly and remove the suspend/resume time save /
> > restore.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_reg.h   |   1 +
> >  drivers/gpu/drm/i915/intel_lvds.c | 103 +++++++++++++++++++++++++++++++++-----
> >  2 files changed, 91 insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 889508f..da82744 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -3710,6 +3710,7 @@ enum {
> >  
> >  #define _PP_ON_DELAYS			0x61208
> >  #define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
> > +#define  PANEL_PORT_SELECT_SHIFT	30
> >  #define  PANEL_PORT_SELECT_MASK		(3 << 30)
> >  #define  PANEL_PORT_SELECT_LVDS		(0 << 30)
> >  #define  PANEL_PORT_SELECT_DPA		(1 << 30)
> > diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> > index c5739fc..d5158e5 100644
> > --- a/drivers/gpu/drm/i915/intel_lvds.c
> > +++ b/drivers/gpu/drm/i915/intel_lvds.c
> > @@ -48,6 +48,20 @@ struct intel_lvds_connector {
> >  	struct notifier_block lid_notifier;
> >  };
> >  
> > +struct intel_lvds_pps {
> > +	/* 100us units */
> > +	int t1_t2;
> > +	int t3;
> > +	int t4;
> > +	int t5;
> > +	int tx;
> > +
> > +	int divider;
> > +
> > +	int port;
> > +	bool reset_on_powerdown;
> > +};
> > +
> >  struct intel_lvds_encoder {
> >  	struct intel_encoder base;
> >  
> > @@ -55,6 +69,9 @@ struct intel_lvds_encoder {
> >  	i915_reg_t reg;
> >  	u32 a3_power;
> >  
> > +	struct intel_lvds_pps init_pps;
> > +	u32 init_lvds_val;
> > +
> >  	struct intel_lvds_connector *attached_connector;
> >  };
> >  
> > @@ -136,6 +153,72 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
> >  	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
> >  }
> >  
> > +static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
> > +					struct intel_lvds_pps *pps)
> > +{
> > +	u32 val;
> > +
> > +	pps->reset_on_powerdown = I915_READ(PP_CONTROL(0)) & PANEL_POWER_RESET;
> > +
> > +	val = I915_READ(PP_ON_DELAYS(0));
> > +	pps->port = (val & PANEL_PORT_SELECT_MASK) >>
> > +		    PANEL_PORT_SELECT_SHIFT;
> > +	pps->t1_t2 = (val & PANEL_POWER_UP_DELAY_MASK) >>
> > +		     PANEL_POWER_UP_DELAY_SHIFT;
> > +	pps->t5 = (val & PANEL_LIGHT_ON_DELAY_MASK) >>
> > +		  PANEL_LIGHT_ON_DELAY_SHIFT;
> > +
> > +	val = I915_READ(PP_OFF_DELAYS(0));
> > +	pps->t3 = (val & PANEL_POWER_DOWN_DELAY_MASK) >>
> > +		  PANEL_POWER_DOWN_DELAY_SHIFT;
> > +	pps->tx = (val & PANEL_LIGHT_OFF_DELAY_MASK) >>
> > +		  PANEL_LIGHT_OFF_DELAY_SHIFT;
> > +
> > +	val = I915_READ(PP_DIVISOR(0));
> > +	pps->divider = (val & PP_REFERENCE_DIVIDER_MASK) >>
> > +		       PP_REFERENCE_DIVIDER_SHIFT;
> > +	/* Convert from 100ms to 100us units */
> > +	pps->t4 = ((val & PANEL_POWER_CYCLE_DELAY_MASK) >>
> > +		   PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
> 
> This should have the +1 offset handling I think.

Ok, will add that.

> Hmm. Looks like we mess that up even for eDP :(
> > +
> > +	if (INTEL_INFO(dev_priv)->gen <= 4 &&
> > +	    pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
> > +		DRM_DEBUG_KMS("Panel power timings uninitialized, "
> > +			      "setting defaults\n");
> > +		/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
> > +		pps->t1_t2 = 40 * 10;
> > +		pps->t5 = 200 * 10;
> > +		/* Set T3 to 35ms and Tx to 200ms in 100 usec units */
> > +		pps->t3 = 35 * 10;
> > +		pps->tx = 200 * 10;
> 
> Not sure where these came from originally. The spgw spec tells us:
> 
> min	max
> t1	0.5	10
> t2	0	50
> t3	0	50
> t4	200	-
> t5	200	-
> t6	200	-
> t7	0	10
> 
> So maybe we should at least set t4=200 here based on the minimum t4
> delay in the spec, probably should add the max t7 time there as well
> as that's what the power cycle delays seems to be really: t4+t7.
> Bspec seems to claim that spgw spec has an upper limit of 400 for this,
> but I can't see that at least in the copy I found.
> 
> And maybe bump up t1_t2=60 and t3=50 based on the max delay for those
> in the spec?

Haven't found yet the spec, but the above seem like reasonable
defaults.

> 
> Anyways, this is all material for a separate patch for sure.

Yep, I kept the behavior here as-is.

> 
> > +	}
> > +
> > +	DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
> > +			 "divider %d port %d reset_on_powerdown %d\n",
> > +			 pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
> > +			 pps->divider, pps->port, pps->reset_on_powerdown);
> > +}
> > +
> > +static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
> > +				   struct intel_lvds_pps *pps)
> > +{
> > +	u32 val;
> > +
> > +	val = I915_READ(PP_CONTROL(0));
> > +	WARN_ON((val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);
> > +	if (pps->reset_on_powerdown)
> > +		val |= PANEL_POWER_RESET;
> 
> Hmm. Maybe we can just always set this bit?

Seems reasonable (for GEN3+), but as also as a follow-up. I just wonder
if the w/a below should be then also applied at the same time. BSpec
doesn't specify the w/a except for IBX, but it seems like the safer
thing to do.

> Hmm, we also totally fail to deal with the related IBX w/a
> in the LVDS code. Should probably fix that up as well as a
> followup.

Ok.

> > +	I915_WRITE(PP_CONTROL(0), val);
> > +
> > +	I915_WRITE(PP_ON_DELAYS(0), (pps->port << PANEL_PORT_SELECT_SHIFT) |
> > +				    (pps->t1_t2 << PANEL_POWER_UP_DELAY_SHIFT) |
> > +				    (pps->t5 << PANEL_LIGHT_ON_DELAY_SHIFT));
> > +	I915_WRITE(PP_OFF_DELAYS(0), (pps->t3 << PANEL_POWER_DOWN_DELAY_SHIFT) |
> > +				     (pps->tx << PANEL_LIGHT_OFF_DELAY_SHIFT));
> > +	I915_WRITE(PP_DIVISOR(0), (pps->divider << PP_REFERENCE_DIVIDER_SHIFT) |
> > +				  ((pps->t4 / 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT));
> 
> DIV_ROUND_UP() I think, and maybe the +1 handling. Though I can't really
> tell if the spec has intended the +1 to be a replacement for rounding
> up, or do we need to do both. Both would seem like the safe choice. Gen2
> Bspec doesn't mention the +1, but it says writing 0 will even abort any
> ongoing delay.

Ok, will change it doing both rounding and +1.

> 
> > +}
> > +
> >  static void intel_pre_enable_lvds(struct intel_encoder *encoder)
> >  {
> >  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
> > @@ -154,7 +237,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder)
> >  		assert_pll_disabled(dev_priv, pipe);
> >  	}
> >  
> > -	temp = I915_READ(lvds_encoder->reg);
> > +	intel_lvds_pps_init_hw(dev_priv, &lvds_encoder->init_pps);
> > +
> > +	temp = lvds_encoder->init_lvds_val;
> >  	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
> >  
> >  	if (HAS_PCH_CPT(dev)) {
> > @@ -922,18 +1007,6 @@ void intel_lvds_init(struct drm_device *dev)
> >  		DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
> >  	}
> >  
> > -	 /* Set the Panel Power On/Off timings if uninitialized. */
> > -	if (INTEL_INFO(dev_priv)->gen < 5 &&
> > -	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
> > -		/* Set T2 to 40ms and T5 to 200ms */
> > -		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
> > -
> > -		/* Set T3 to 35ms and Tx to 200ms */
> > -		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
> > -
> > -		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
> > -	}
> > -
> >  	lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
> >  	if (!lvds_encoder)
> >  		return;
> > @@ -999,6 +1072,10 @@ void intel_lvds_init(struct drm_device *dev)
> >  				      dev->mode_config.scaling_mode_property,
> >  				      DRM_MODE_SCALE_ASPECT);
> >  	intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
> > +
> > +	intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps);
> > +	lvds_encoder->init_lvds_val = lvds;
> > +
> >  	/*
> >  	 * LVDS discovery:
> >  	 * 1) check for EDID on DDC
> > -- 
> > 2.5.0
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling
  2016-08-09 14:40     ` Imre Deak
@ 2016-08-09 14:55       ` Ville Syrjälä
  0 siblings, 0 replies; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 14:55 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 05:40:32PM +0300, Imre Deak wrote:
> On ti, 2016-08-09 at 15:48 +0300, Ville Syrjälä wrote:
> > On Tue, Aug 09, 2016 at 02:34:09PM +0300, Imre Deak wrote:
> > > Atm the LVDS encoder depends on the PPS HW context being saved/restored
> > > from generic suspend/resume code. Since the PPS is specific to the LVDS
> > > and eDP encoders a cleaner way is to reinitialize it during encoder
> > > enabling, so do this here for LVDS. Follow-up patches will init the PPS
> > > for the eDP encoder similarly and remove the suspend/resume time save /
> > > restore.
> > > 
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/i915_reg.h   |   1 +
> > >  drivers/gpu/drm/i915/intel_lvds.c | 103 +++++++++++++++++++++++++++++++++-----
> > >  2 files changed, 91 insertions(+), 13 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > > index 889508f..da82744 100644
> > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > @@ -3710,6 +3710,7 @@ enum {
> > >  
> > >  #define _PP_ON_DELAYS			0x61208
> > >  #define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
> > > +#define  PANEL_PORT_SELECT_SHIFT	30
> > >  #define  PANEL_PORT_SELECT_MASK		(3 << 30)
> > >  #define  PANEL_PORT_SELECT_LVDS		(0 << 30)
> > >  #define  PANEL_PORT_SELECT_DPA		(1 << 30)
> > > diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> > > index c5739fc..d5158e5 100644
> > > --- a/drivers/gpu/drm/i915/intel_lvds.c
> > > +++ b/drivers/gpu/drm/i915/intel_lvds.c
> > > @@ -48,6 +48,20 @@ struct intel_lvds_connector {
> > >  	struct notifier_block lid_notifier;
> > >  };
> > >  
> > > +struct intel_lvds_pps {
> > > +	/* 100us units */
> > > +	int t1_t2;
> > > +	int t3;
> > > +	int t4;
> > > +	int t5;
> > > +	int tx;
> > > +
> > > +	int divider;
> > > +
> > > +	int port;
> > > +	bool reset_on_powerdown;
> > > +};
> > > +
> > >  struct intel_lvds_encoder {
> > >  	struct intel_encoder base;
> > >  
> > > @@ -55,6 +69,9 @@ struct intel_lvds_encoder {
> > >  	i915_reg_t reg;
> > >  	u32 a3_power;
> > >  
> > > +	struct intel_lvds_pps init_pps;
> > > +	u32 init_lvds_val;
> > > +
> > >  	struct intel_lvds_connector *attached_connector;
> > >  };
> > >  
> > > @@ -136,6 +153,72 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
> > >  	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
> > >  }
> > >  
> > > +static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
> > > +					struct intel_lvds_pps *pps)
> > > +{
> > > +	u32 val;
> > > +
> > > +	pps->reset_on_powerdown = I915_READ(PP_CONTROL(0)) & PANEL_POWER_RESET;
> > > +
> > > +	val = I915_READ(PP_ON_DELAYS(0));
> > > +	pps->port = (val & PANEL_PORT_SELECT_MASK) >>
> > > +		    PANEL_PORT_SELECT_SHIFT;
> > > +	pps->t1_t2 = (val & PANEL_POWER_UP_DELAY_MASK) >>
> > > +		     PANEL_POWER_UP_DELAY_SHIFT;
> > > +	pps->t5 = (val & PANEL_LIGHT_ON_DELAY_MASK) >>
> > > +		  PANEL_LIGHT_ON_DELAY_SHIFT;
> > > +
> > > +	val = I915_READ(PP_OFF_DELAYS(0));
> > > +	pps->t3 = (val & PANEL_POWER_DOWN_DELAY_MASK) >>
> > > +		  PANEL_POWER_DOWN_DELAY_SHIFT;
> > > +	pps->tx = (val & PANEL_LIGHT_OFF_DELAY_MASK) >>
> > > +		  PANEL_LIGHT_OFF_DELAY_SHIFT;
> > > +
> > > +	val = I915_READ(PP_DIVISOR(0));
> > > +	pps->divider = (val & PP_REFERENCE_DIVIDER_MASK) >>
> > > +		       PP_REFERENCE_DIVIDER_SHIFT;
> > > +	/* Convert from 100ms to 100us units */
> > > +	pps->t4 = ((val & PANEL_POWER_CYCLE_DELAY_MASK) >>
> > > +		   PANEL_POWER_CYCLE_DELAY_SHIFT) * 1000;
> > 
> > This should have the +1 offset handling I think.
> 
> Ok, will add that.
> 
> > Hmm. Looks like we mess that up even for eDP :(
> > > +
> > > +	if (INTEL_INFO(dev_priv)->gen <= 4 &&
> > > +	    pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
> > > +		DRM_DEBUG_KMS("Panel power timings uninitialized, "
> > > +			      "setting defaults\n");
> > > +		/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
> > > +		pps->t1_t2 = 40 * 10;
> > > +		pps->t5 = 200 * 10;
> > > +		/* Set T3 to 35ms and Tx to 200ms in 100 usec units */
> > > +		pps->t3 = 35 * 10;
> > > +		pps->tx = 200 * 10;
> > 
> > Not sure where these came from originally. The spgw spec tells us:
> > 
> > min	max
> > t1	0.5	10
> > t2	0	50
> > t3	0	50
> > t4	200	-
> > t5	200	-
> > t6	200	-
> > t7	0	10
> > 
> > So maybe we should at least set t4=200 here based on the minimum t4
> > delay in the spec, probably should add the max t7 time there as well
> > as that's what the power cycle delays seems to be really: t4+t7.
> > Bspec seems to claim that spgw spec has an upper limit of 400 for this,
> > but I can't see that at least in the copy I found.
> > 
> > And maybe bump up t1_t2=60 and t3=50 based on the max delay for those
> > in the spec?
> 
> Haven't found yet the spec, but the above seem like reasonable
> defaults.
> 
> > 
> > Anyways, this is all material for a separate patch for sure.
> 
> Yep, I kept the behavior here as-is.
> 
> > 
> > > +	}
> > > +
> > > +	DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
> > > +			 "divider %d port %d reset_on_powerdown %d\n",
> > > +			 pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
> > > +			 pps->divider, pps->port, pps->reset_on_powerdown);
> > > +}
> > > +
> > > +static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
> > > +				   struct intel_lvds_pps *pps)
> > > +{
> > > +	u32 val;
> > > +
> > > +	val = I915_READ(PP_CONTROL(0));
> > > +	WARN_ON((val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);
> > > +	if (pps->reset_on_powerdown)
> > > +		val |= PANEL_POWER_RESET;
> > 
> > Hmm. Maybe we can just always set this bit?
> 
> Seems reasonable (for GEN3+), but as also as a follow-up. I just wonder
> if the w/a below should be then also applied at the same time. BSpec
> doesn't specify the w/a except for IBX, but it seems like the safer
> thing to do.

The problem with the w/a is that it opens up a time window when a reset
will then not initiate a power down cycle. Not sure that's a huge
concern though since the hardware can't apparently guarantee that any
power down cycle initiated via a reset is actually long enough.

The notes in the spec do not indicate that the problem would have been
observed on any other platform.

> 
> > Hmm, we also totally fail to deal with the related IBX w/a
> > in the LVDS code. Should probably fix that up as well as a
> > followup.
> 
> Ok.
> 
> > > +	I915_WRITE(PP_CONTROL(0), val);
> > > +
> > > +	I915_WRITE(PP_ON_DELAYS(0), (pps->port << PANEL_PORT_SELECT_SHIFT) |
> > > +				    (pps->t1_t2 << PANEL_POWER_UP_DELAY_SHIFT) |
> > > +				    (pps->t5 << PANEL_LIGHT_ON_DELAY_SHIFT));
> > > +	I915_WRITE(PP_OFF_DELAYS(0), (pps->t3 << PANEL_POWER_DOWN_DELAY_SHIFT) |
> > > +				     (pps->tx << PANEL_LIGHT_OFF_DELAY_SHIFT));
> > > +	I915_WRITE(PP_DIVISOR(0), (pps->divider << PP_REFERENCE_DIVIDER_SHIFT) |
> > > +				  ((pps->t4 / 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT));
> > 
> > DIV_ROUND_UP() I think, and maybe the +1 handling. Though I can't really
> > tell if the spec has intended the +1 to be a replacement for rounding
> > up, or do we need to do both. Both would seem like the safe choice. Gen2
> > Bspec doesn't mention the +1, but it says writing 0 will even abort any
> > ongoing delay.
> 
> Ok, will change it doing both rounding and +1.
> 
> > 
> > > +}
> > > +
> > >  static void intel_pre_enable_lvds(struct intel_encoder *encoder)
> > >  {
> > >  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
> > > @@ -154,7 +237,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder)
> > >  		assert_pll_disabled(dev_priv, pipe);
> > >  	}
> > >  
> > > -	temp = I915_READ(lvds_encoder->reg);
> > > +	intel_lvds_pps_init_hw(dev_priv, &lvds_encoder->init_pps);
> > > +
> > > +	temp = lvds_encoder->init_lvds_val;
> > >  	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
> > >  
> > >  	if (HAS_PCH_CPT(dev)) {
> > > @@ -922,18 +1007,6 @@ void intel_lvds_init(struct drm_device *dev)
> > >  		DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
> > >  	}
> > >  
> > > -	 /* Set the Panel Power On/Off timings if uninitialized. */
> > > -	if (INTEL_INFO(dev_priv)->gen < 5 &&
> > > -	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
> > > -		/* Set T2 to 40ms and T5 to 200ms */
> > > -		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
> > > -
> > > -		/* Set T3 to 35ms and Tx to 200ms */
> > > -		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
> > > -
> > > -		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
> > > -	}
> > > -
> > >  	lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
> > >  	if (!lvds_encoder)
> > >  		return;
> > > @@ -999,6 +1072,10 @@ void intel_lvds_init(struct drm_device *dev)
> > >  				      dev->mode_config.scaling_mode_property,
> > >  				      DRM_MODE_SCALE_ASPECT);
> > >  	intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
> > > +
> > > +	intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps);
> > > +	lvds_encoder->init_lvds_val = lvds;
> > > +
> > >  	/*
> > >  	 * LVDS discovery:
> > >  	 * 1) check for EDID on DDC
> > > -- 
> > > 2.5.0
> > > 
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > 

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 4/6] drm/i915/dp: Restore PPS HW state from the encoder resume hook
  2016-08-09 12:52   ` Ville Syrjälä
@ 2016-08-09 15:15     ` Imre Deak
  0 siblings, 0 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 15:15 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On ti, 2016-08-09 at 15:52 +0300, Ville Syrjälä wrote:
> On Tue, Aug 09, 2016 at 02:34:10PM +0300, Imre Deak wrote:
> > Similarly to the previous patch, initialize the PPS from the DP
> > encoder's resume hook. Note that as opposed to LVDS we can't do this
> > during encoder enabling, since we need the PPS for DP detection as well.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 4796ad7..76f5b72 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -4665,6 +4665,9 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
> >  	 */
> >  	if (IS_VALLEYVIEW(encoder->dev) || IS_CHERRYVIEW(encoder->dev))
> >  		vlv_initial_power_sequencer_setup(intel_dp);
> > +	else
> > +		intel_dp_init_panel_power_sequencer_registers(encoder->dev,
> > +							      intel_dp);
> 
> This is almosts the same code as we have in intel_edp_init_connector(),
> excep not calling intel_dp_init_panel_power_sequencer() for !VLV/CHV.
> 
> intel_dp_init_panel_power_sequencer() should be safe to call multiple
> times since it checks if things were already initialized, and we already
> call it here for VLV/CHV. So I think we should just be able share the
> code for init and resume?

Ok, can factor these out to a new helper. Btw, would it make sense to
call intel_dp_init_panel_power_sequencer_registers()
from intel_dp_init_panel_power() directly, they are not called
separately any more.

> 
> >  
> >  	intel_edp_panel_vdd_sanitize(intel_dp);
> >  
> > -- 
> > 2.5.0
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 5/6] drm/i915: Apply the PPS register unlock workaround more consistently
  2016-08-09 13:01   ` Ville Syrjälä
@ 2016-08-09 15:17     ` Imre Deak
  0 siblings, 0 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 15:17 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On ti, 2016-08-09 at 16:01 +0300, Ville Syrjälä wrote:
> On Tue, Aug 09, 2016 at 02:34:11PM +0300, Imre Deak wrote:
> > Atm, we apply this workaround somewhat inconsistently at the following
> > points: driver loading, LVDS init, eDP PPS init, system resume. As this
> > workaround also affects registers other than PPS (timing, PLL) a more
> > consistent way is to apply it early after the PPS HW context is known to
> > be lost: driver loading, system resume and on VLV/CHV/BXT when turning
> > on power domains.
> > 
> > This is needed by the next patch that removes saving/restoring of the
> > PP_CONTROL register.
> > 
> > This also removes the incorrect programming of the workaround on HSW+
> > PCH platforms which don't have the register locking mechanism.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c         |  1 +
> >  drivers/gpu/drm/i915/intel_display.c    | 28 ++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_dp.c         |  4 +++-
> >  drivers/gpu/drm/i915/intel_drv.h        |  1 +
> >  drivers/gpu/drm/i915/intel_lvds.c       |  8 --------
> >  drivers/gpu/drm/i915/intel_runtime_pm.c |  4 ++++
> >  6 files changed, 37 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index 8cfc264..0fcd1c0 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -1560,6 +1560,7 @@ static int i915_drm_resume(struct drm_device *dev)
> >  	i915_gem_resume(dev);
> >  
> >  	i915_restore_state(dev);
> > +	intel_pps_unlock_regs_wa(dev_priv);
> >  	intel_opregion_setup(dev_priv);
> >  
> >  	intel_init_pch_refclk(dev);
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 3d5fd06..dc4e600 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -14635,6 +14635,32 @@ static bool intel_crt_present(struct drm_device *dev)
> >  	return true;
> >  }
> >  
> > +void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
> > +{
> > +	int pps_num;
> > +	int pps_idx;
> > +
> > +	/*
> > +	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
> > +	 * everywhere where registers can be write protected.
> > +	 */
> > +	if (INTEL_GEN(dev_priv) <= 4 ||
> > +	    HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
> > +		pps_num = 1;
> > +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv) ||
> > +		 IS_BROXTON(dev_priv))
> > +		pps_num = 2;
> > +	else
> > +		pps_num = 0;
> 
> BXT shouldn't need the unlock, I think.

Yes, got that wrong.

> 
> So I believe we just want
> 
> if (HAS_DDI())
> 	return;
> 
> if (VLV||CHV)
> 	num = 2;
> else
> 	num = 1;

Ok.

> 
> > +
> > +	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
> > +		u32 val = I915_READ(PP_CONTROL(pps_idx));
> > +
> > +		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
> > +		I915_WRITE(PP_CONTROL(pps_idx), val);
> > +	}
> > +}
> > +
> >  static void intel_pps_init(struct drm_i915_private *dev_priv)
> >  {
> >  	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
> > @@ -14643,6 +14669,8 @@ static void intel_pps_init(struct drm_i915_private *dev_priv)
> >  		dev_priv->pps_mmio_base = VLV_PPS_BASE;
> >  	else
> >  		dev_priv->pps_mmio_base = PPS_BASE;
> > +
> > +	intel_pps_unlock_regs_wa(dev_priv);
> >  }
> >  
> >  static void intel_setup_outputs(struct drm_device *dev)
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 76f5b72..b27f1c5 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1829,7 +1829,9 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
> >  	lockdep_assert_held(&dev_priv->pps_mutex);
> >  
> >  	control = I915_READ(_pp_ctrl_reg(intel_dp));
> > -	if (!IS_BROXTON(dev)) {
> > +	if (WARN_ON((HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) ||
> > +		     IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> 
> !HAS_DDI

Heh, was thinking of a shorter way, but this didn't occur to me. Will
change it.

> 
> > +		     (control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
> >  		control &= ~PANEL_UNLOCK_MASK;
> >  		control |= PANEL_UNLOCK_REGS;
> >  	}
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index c29a429..cbce786 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1159,6 +1159,7 @@ void intel_mark_busy(struct drm_i915_private *dev_priv);
> >  void intel_mark_idle(struct drm_i915_private *dev_priv);
> >  void intel_crtc_restore_mode(struct drm_crtc *crtc);
> >  int intel_display_suspend(struct drm_device *dev);
> > +void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
> >  void intel_encoder_destroy(struct drm_encoder *encoder);
> >  int intel_connector_init(struct intel_connector *);
> >  struct intel_connector *intel_connector_alloc(void);
> > diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> > index d5158e5..9a6e1ad 100644
> > --- a/drivers/gpu/drm/i915/intel_lvds.c
> > +++ b/drivers/gpu/drm/i915/intel_lvds.c
> > @@ -967,14 +967,6 @@ void intel_lvds_init(struct drm_device *dev)
> >  	int pipe;
> >  	u8 pin;
> >  
> > -	/*
> > -	 * Unlock registers and just leave them unlocked. Do this before
> > -	 * checking quirk lists to avoid bogus WARNINGs.
> > -	 */
> > -	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
> > -		I915_WRITE(PP_CONTROL(0),
> > -			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
> > -
> >  	if (!intel_lvds_supported(dev))
> >  		return;
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > index 1c603bb..8f51ae3 100644
> > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > @@ -592,6 +592,8 @@ void bxt_disable_dc9(struct drm_i915_private *dev_priv)
> >  	DRM_DEBUG_KMS("Disabling DC9\n");
> >  
> >  	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
> > +
> > +	intel_pps_unlock_regs_wa(dev_priv);
> >  }
> >  
> >  static void assert_csr_loaded(struct drm_i915_private *dev_priv)
> > @@ -1145,6 +1147,8 @@ static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
> >  	vlv_set_power_well(dev_priv, power_well, true);
> >  
> >  	vlv_display_power_well_init(dev_priv);
> > +
> > +	intel_pps_unlock_regs_wa(dev_priv);
> >  }
> >  
> >  static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
> > -- 
> > 2.5.0
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v2 1/6] drm/i915: Merge the PPS register definitions
  2016-08-09 11:34 ` [PATCH 1/6] drm/i915: Merge the PPS register definitions Imre Deak
  2016-08-09 11:53   ` Ville Syrjälä
@ 2016-08-09 17:21   ` Imre Deak
  2016-08-09 17:50     ` Ville Syrjälä
  1 sibling, 1 reply; 30+ messages in thread
From: Imre Deak @ 2016-08-09 17:21 UTC (permalink / raw)
  To: intel-gfx

The PPS registers are pretty much the same everywhere, the differences
being:
- Register fields appearing, disappearing from one platform to the
  next: panel-reset-on-powerdown, backlight-on, panel-port,
  register-unlock
- Different register base addresses
- Different number of PPS instances: 2 on VLV/CHV/BXT, 1 everywhere
  else.

We can merge the separate set of PPS definitions by extending the PPS
instance argument to all platforms and using instance 0 on platforms
with a single instance. This means we'll need to calculate the register
addresses dynamically based on the given platform and PPS instance.

v2:
- Simplify if ladder in intel_pps_get_registers(). (Ville)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |   2 +
 drivers/gpu/drm/i915/i915_reg.h      | 145 ++++++++++++++---------------------
 drivers/gpu/drm/i915/i915_suspend.c  |  30 +++-----
 drivers/gpu/drm/i915/intel_display.c |  22 ++++--
 drivers/gpu/drm/i915/intel_dp.c      |  45 +++++------
 drivers/gpu/drm/i915/intel_lvds.c    |  43 +++--------
 6 files changed, 117 insertions(+), 170 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c36d176..fddaec6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1749,6 +1749,8 @@ struct drm_i915_private {
 
 	uint32_t psr_mmio_base;
 
+	uint32_t pps_mmio_base;
+
 	wait_queue_head_t gmbus_wait_queue;
 
 	struct pci_dev *bridge_dev;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f38a5e2..b65fe50 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3660,8 +3660,17 @@ enum {
 #define   VIDEO_DIP_ENABLE_SPD_HSW	(1 << 0)
 
 /* Panel power sequencing */
-#define PP_STATUS	_MMIO(0x61200)
-#define   PP_ON		(1 << 31)
+#define PPS_BASE			0x61200
+#define VLV_PPS_BASE			(VLV_DISPLAY_BASE + PPS_BASE)
+#define PCH_PPS_BASE			0xC7200
+
+#define _MMIO_PPS(pps_idx, reg)		_MMIO(dev_priv->pps_mmio_base -	\
+					      PPS_BASE + (reg) +	\
+					      (pps_idx) * 0x100)
+
+#define _PP_STATUS			0x61200
+#define PP_STATUS(pps_idx)		_MMIO_PPS(pps_idx, _PP_STATUS)
+#define   PP_ON				(1 << 31)
 /*
  * Indicates that all dependencies of the panel are on:
  *
@@ -3669,14 +3678,14 @@ enum {
  * - pipe enabled
  * - LVDS/DVOB/DVOC on
  */
-#define   PP_READY		(1 << 30)
-#define   PP_SEQUENCE_NONE	(0 << 28)
-#define   PP_SEQUENCE_POWER_UP	(1 << 28)
-#define   PP_SEQUENCE_POWER_DOWN (2 << 28)
-#define   PP_SEQUENCE_MASK	(3 << 28)
-#define   PP_SEQUENCE_SHIFT	28
-#define   PP_CYCLE_DELAY_ACTIVE	(1 << 27)
-#define   PP_SEQUENCE_STATE_MASK 0x0000000f
+#define   PP_READY			(1 << 30)
+#define   PP_SEQUENCE_NONE		(0 << 28)
+#define   PP_SEQUENCE_POWER_UP		(1 << 28)
+#define   PP_SEQUENCE_POWER_DOWN	(2 << 28)
+#define   PP_SEQUENCE_MASK		(3 << 28)
+#define   PP_SEQUENCE_SHIFT		28
+#define   PP_CYCLE_DELAY_ACTIVE		(1 << 27)
+#define   PP_SEQUENCE_STATE_MASK	0x0000000f
 #define   PP_SEQUENCE_STATE_OFF_IDLE	(0x0 << 0)
 #define   PP_SEQUENCE_STATE_OFF_S0_1	(0x1 << 0)
 #define   PP_SEQUENCE_STATE_OFF_S0_2	(0x2 << 0)
@@ -3686,11 +3695,46 @@ enum {
 #define   PP_SEQUENCE_STATE_ON_S1_2	(0xa << 0)
 #define   PP_SEQUENCE_STATE_ON_S1_3	(0xb << 0)
 #define   PP_SEQUENCE_STATE_RESET	(0xf << 0)
-#define PP_CONTROL	_MMIO(0x61204)
-#define   POWER_TARGET_ON	(1 << 0)
-#define PP_ON_DELAYS	_MMIO(0x61208)
-#define PP_OFF_DELAYS	_MMIO(0x6120c)
-#define PP_DIVISOR	_MMIO(0x61210)
+
+#define _PP_CONTROL			0x61204
+#define PP_CONTROL(pps_idx)		_MMIO_PPS(pps_idx, _PP_CONTROL)
+#define  PANEL_UNLOCK_REGS		(0xabcd << 16)
+#define  PANEL_UNLOCK_MASK		(0xffff << 16)
+#define  BXT_POWER_CYCLE_DELAY_MASK	0x1f0
+#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
+#define  EDP_FORCE_VDD			(1 << 3)
+#define  EDP_BLC_ENABLE			(1 << 2)
+#define  PANEL_POWER_RESET		(1 << 1)
+#define  PANEL_POWER_OFF		(0 << 0)
+#define  PANEL_POWER_ON			(1 << 0)
+#define  POWER_TARGET_ON		(1 << 0)
+
+#define _PP_ON_DELAYS			0x61208
+#define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
+#define  PANEL_PORT_SELECT_MASK		(3 << 30)
+#define  PANEL_PORT_SELECT_LVDS		(0 << 30)
+#define  PANEL_PORT_SELECT_DPA		(1 << 30)
+#define  PANEL_PORT_SELECT_DPC		(2 << 30)
+#define  PANEL_PORT_SELECT_DPD		(3 << 30)
+#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
+#define  PANEL_POWER_UP_DELAY_MASK	0x1fff0000
+#define  PANEL_POWER_UP_DELAY_SHIFT	16
+#define  PANEL_LIGHT_ON_DELAY_MASK	0x1fff
+#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
+
+#define _PP_OFF_DELAYS			0x6120C
+#define PP_OFF_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_OFF_DELAYS)
+#define  PANEL_POWER_DOWN_DELAY_MASK	0x1fff0000
+#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
+#define  PANEL_LIGHT_OFF_DELAY_MASK	0x1fff
+#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
+
+#define _PP_DIVISOR			0x61210
+#define PP_DIVISOR(pps_idx)		_MMIO_PPS(pps_idx, _PP_DIVISOR)
+#define  PP_REFERENCE_DIVIDER_MASK	0xffffff00
+#define  PP_REFERENCE_DIVIDER_SHIFT	8
+#define  PANEL_POWER_CYCLE_DELAY_MASK	0x1f
+#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
 
 /* Panel fitting */
 #define PFIT_CONTROL	_MMIO(dev_priv->info.display_mmio_offset + 0x61230)
@@ -6750,77 +6794,6 @@ enum {
 #define PCH_LVDS	_MMIO(0xe1180)
 #define  LVDS_DETECTED	(1 << 1)
 
-/* vlv has 2 sets of panel control regs. */
-#define _PIPEA_PP_STATUS         (VLV_DISPLAY_BASE + 0x61200)
-#define _PIPEA_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61204)
-#define _PIPEA_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61208)
-#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
-#define _PIPEA_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6120c)
-#define _PIPEA_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61210)
-
-#define _PIPEB_PP_STATUS         (VLV_DISPLAY_BASE + 0x61300)
-#define _PIPEB_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61304)
-#define _PIPEB_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61308)
-#define _PIPEB_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6130c)
-#define _PIPEB_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61310)
-
-#define VLV_PIPE_PP_STATUS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_STATUS, _PIPEB_PP_STATUS)
-#define VLV_PIPE_PP_CONTROL(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_CONTROL, _PIPEB_PP_CONTROL)
-#define VLV_PIPE_PP_ON_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_ON_DELAYS, _PIPEB_PP_ON_DELAYS)
-#define VLV_PIPE_PP_OFF_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_OFF_DELAYS, _PIPEB_PP_OFF_DELAYS)
-#define VLV_PIPE_PP_DIVISOR(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_DIVISOR, _PIPEB_PP_DIVISOR)
-
-#define _PCH_PP_STATUS		0xc7200
-#define _PCH_PP_CONTROL		0xc7204
-#define  PANEL_UNLOCK_REGS	(0xabcd << 16)
-#define  PANEL_UNLOCK_MASK	(0xffff << 16)
-#define  BXT_POWER_CYCLE_DELAY_MASK	(0x1f0)
-#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
-#define  EDP_FORCE_VDD		(1 << 3)
-#define  EDP_BLC_ENABLE		(1 << 2)
-#define  PANEL_POWER_RESET	(1 << 1)
-#define  PANEL_POWER_OFF	(0 << 0)
-#define  PANEL_POWER_ON		(1 << 0)
-#define _PCH_PP_ON_DELAYS	0xc7208
-#define  PANEL_PORT_SELECT_MASK	(3 << 30)
-#define  PANEL_PORT_SELECT_LVDS	(0 << 30)
-#define  PANEL_PORT_SELECT_DPA	(1 << 30)
-#define  PANEL_PORT_SELECT_DPC	(2 << 30)
-#define  PANEL_PORT_SELECT_DPD	(3 << 30)
-#define  PANEL_POWER_UP_DELAY_MASK	(0x1fff0000)
-#define  PANEL_POWER_UP_DELAY_SHIFT	16
-#define  PANEL_LIGHT_ON_DELAY_MASK	(0x1fff)
-#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
-
-#define _PCH_PP_OFF_DELAYS		0xc720c
-#define  PANEL_POWER_DOWN_DELAY_MASK	(0x1fff0000)
-#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
-#define  PANEL_LIGHT_OFF_DELAY_MASK	(0x1fff)
-#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
-
-#define _PCH_PP_DIVISOR			0xc7210
-#define  PP_REFERENCE_DIVIDER_MASK	(0xffffff00)
-#define  PP_REFERENCE_DIVIDER_SHIFT	8
-#define  PANEL_POWER_CYCLE_DELAY_MASK	(0x1f)
-#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
-
-#define PCH_PP_STATUS			_MMIO(_PCH_PP_STATUS)
-#define PCH_PP_CONTROL			_MMIO(_PCH_PP_CONTROL)
-#define PCH_PP_ON_DELAYS		_MMIO(_PCH_PP_ON_DELAYS)
-#define PCH_PP_OFF_DELAYS		_MMIO(_PCH_PP_OFF_DELAYS)
-#define PCH_PP_DIVISOR			_MMIO(_PCH_PP_DIVISOR)
-
-/* BXT PPS changes - 2nd set of PPS registers */
-#define _BXT_PP_STATUS2 	0xc7300
-#define _BXT_PP_CONTROL2 	0xc7304
-#define _BXT_PP_ON_DELAYS2	0xc7308
-#define _BXT_PP_OFF_DELAYS2	0xc730c
-
-#define BXT_PP_STATUS(n)	_MMIO_PIPE(n, _PCH_PP_STATUS, _BXT_PP_STATUS2)
-#define BXT_PP_CONTROL(n)	_MMIO_PIPE(n, _PCH_PP_CONTROL, _BXT_PP_CONTROL2)
-#define BXT_PP_ON_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2)
-#define BXT_PP_OFF_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2)
-
 #define _PCH_DP_B		0xe4100
 #define PCH_DP_B		_MMIO(_PCH_DP_B)
 #define _PCH_DPB_AUX_CH_CTL	0xe4110
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 5cfe4c7..c826b69 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -44,16 +44,11 @@ static void i915_save_display(struct drm_device *dev)
 		dev_priv->regfile.saveLVDS = I915_READ(LVDS);
 
 	/* Panel power sequencer */
-	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
-		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
-		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
-		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
-	} else if (INTEL_INFO(dev)->gen <= 4) {
-		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
-		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
-		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
-		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
+	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
+		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL(0));
+		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS(0));
+		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS(0));
+		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR(0));
 	}
 
 	/* save FBC interval */
@@ -79,16 +74,11 @@ static void i915_restore_display(struct drm_device *dev)
 		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);
 
 	/* Panel power sequencer */
-	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
-		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
-		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
-		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
-	} else if (INTEL_INFO(dev)->gen <= 4) {
-		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
-		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
-		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
-		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
+	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
+		I915_WRITE(PP_ON_DELAYS(0), dev_priv->regfile.savePP_ON_DELAYS);
+		I915_WRITE(PP_OFF_DELAYS(0), dev_priv->regfile.savePP_OFF_DELAYS);
+		I915_WRITE(PP_DIVISOR(0), dev_priv->regfile.savePP_DIVISOR);
+		I915_WRITE(PP_CONTROL(0), dev_priv->regfile.savePP_CONTROL);
 	}
 
 	/* only restore FBC info on the platform that supports FBC*/
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c6f27ab..3d5fd06 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1202,8 +1202,8 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
 	if (HAS_PCH_SPLIT(dev)) {
 		u32 port_sel;
 
-		pp_reg = PCH_PP_CONTROL;
-		port_sel = I915_READ(PCH_PP_ON_DELAYS) & PANEL_PORT_SELECT_MASK;
+		pp_reg = PP_CONTROL(0);
+		port_sel = I915_READ(PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK;
 
 		if (port_sel == PANEL_PORT_SELECT_LVDS &&
 		    I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
@@ -1211,10 +1211,10 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
 		/* XXX: else fix for eDP */
 	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		/* presumably write lock depends on pipe, not port select */
-		pp_reg = VLV_PIPE_PP_CONTROL(pipe);
+		pp_reg = PP_CONTROL(pipe);
 		panel_pipe = pipe;
 	} else {
-		pp_reg = PP_CONTROL;
+		pp_reg = PP_CONTROL(0);
 		if (I915_READ(LVDS) & LVDS_PIPEB_SELECT)
 			panel_pipe = PIPE_B;
 	}
@@ -9411,7 +9411,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 	I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
 	I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
 	I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
-	I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
+	I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n");
 	I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
 	     "CPU PWM1 enabled\n");
 	if (IS_HASWELL(dev))
@@ -14635,12 +14635,24 @@ static bool intel_crt_present(struct drm_device *dev)
 	return true;
 }
 
+static void intel_pps_init(struct drm_i915_private *dev_priv)
+{
+	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
+		dev_priv->pps_mmio_base = PCH_PPS_BASE;
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		dev_priv->pps_mmio_base = VLV_PPS_BASE;
+	else
+		dev_priv->pps_mmio_base = PPS_BASE;
+}
+
 static void intel_setup_outputs(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_encoder *encoder;
 	bool dpd_is_edp = false;
 
+	intel_pps_init(dev_priv);
+
 	/*
 	 * intel_edp_init_connector() depends on this completing first, to
 	 * prevent the registeration of both eDP and LVDS and the incorrect
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 8fe2afa..15aff93 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -463,13 +463,13 @@ typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
 static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
 			       enum pipe pipe)
 {
-	return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
+	return I915_READ(PP_STATUS(pipe)) & PP_ON;
 }
 
 static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
 				enum pipe pipe)
 {
-	return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
+	return I915_READ(PP_CONTROL(pipe)) & EDP_FORCE_VDD;
 }
 
 static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
@@ -486,7 +486,7 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
 	enum pipe pipe;
 
 	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
-		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
+		u32 port_sel = I915_READ(PP_ON_DELAYS(pipe)) &
 			PANEL_PORT_SELECT_MASK;
 
 		if (port_sel != PANEL_PORT_SELECT_VLV(port))
@@ -583,30 +583,21 @@ static void intel_pps_get_registers(struct drm_i915_private *dev_priv,
 				    struct intel_dp *intel_dp,
 				    struct pps_registers *regs)
 {
+	int pps_idx = 0;
+
 	memset(regs, 0, sizeof(*regs));
 
-	if (IS_BROXTON(dev_priv)) {
-		int idx = bxt_power_sequencer_idx(intel_dp);
+	if (IS_BROXTON(dev_priv))
+		pps_idx = bxt_power_sequencer_idx(intel_dp);
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		pps_idx = vlv_power_sequencer_pipe(intel_dp);
 
-		regs->pp_ctrl = BXT_PP_CONTROL(idx);
-		regs->pp_stat = BXT_PP_STATUS(idx);
-		regs->pp_on = BXT_PP_ON_DELAYS(idx);
-		regs->pp_off = BXT_PP_OFF_DELAYS(idx);
-	} else if (HAS_PCH_SPLIT(dev_priv)) {
-		regs->pp_ctrl = PCH_PP_CONTROL;
-		regs->pp_stat = PCH_PP_STATUS;
-		regs->pp_on = PCH_PP_ON_DELAYS;
-		regs->pp_off = PCH_PP_OFF_DELAYS;
-		regs->pp_div = PCH_PP_DIVISOR;
-	} else {
-		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
-
-		regs->pp_ctrl = VLV_PIPE_PP_CONTROL(pipe);
-		regs->pp_stat = VLV_PIPE_PP_STATUS(pipe);
-		regs->pp_on = VLV_PIPE_PP_ON_DELAYS(pipe);
-		regs->pp_off = VLV_PIPE_PP_OFF_DELAYS(pipe);
-		regs->pp_div = VLV_PIPE_PP_DIVISOR(pipe);
-	}
+	regs->pp_ctrl = PP_CONTROL(pps_idx);
+	regs->pp_stat = PP_STATUS(pps_idx);
+	regs->pp_on = PP_ON_DELAYS(pps_idx);
+	regs->pp_off = PP_OFF_DELAYS(pps_idx);
+	if (!IS_BROXTON(dev_priv))
+		regs->pp_div = PP_DIVISOR(pps_idx);
 }
 
 static i915_reg_t
@@ -651,8 +642,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 		i915_reg_t pp_ctrl_reg, pp_div_reg;
 		u32 pp_div;
 
-		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
-		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
+		pp_ctrl_reg = PP_CONTROL(pipe);
+		pp_div_reg  = PP_DIVISOR(pipe);
 		pp_div = I915_READ(pp_div_reg);
 		pp_div &= PP_REFERENCE_DIVIDER_MASK;
 
@@ -2729,7 +2720,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 	enum pipe pipe = intel_dp->pps_pipe;
-	i915_reg_t pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
+	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
 
 	edp_panel_vdd_off_sync(intel_dp);
 
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 4955047..413e729 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -217,21 +217,12 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
 	struct intel_connector *intel_connector =
 		&lvds_encoder->attached_connector->base;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	i915_reg_t ctl_reg, stat_reg;
-
-	if (HAS_PCH_SPLIT(dev)) {
-		ctl_reg = PCH_PP_CONTROL;
-		stat_reg = PCH_PP_STATUS;
-	} else {
-		ctl_reg = PP_CONTROL;
-		stat_reg = PP_STATUS;
-	}
 
 	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
 
-	I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
+	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | POWER_TARGET_ON);
 	POSTING_READ(lvds_encoder->reg);
-	if (intel_wait_for_register(dev_priv, stat_reg, PP_ON, PP_ON, 1000))
+	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 1000))
 		DRM_ERROR("timed out waiting for panel to power on\n");
 
 	intel_panel_enable_backlight(intel_connector);
@@ -242,18 +233,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
 	struct drm_device *dev = encoder->base.dev;
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	i915_reg_t ctl_reg, stat_reg;
 
-	if (HAS_PCH_SPLIT(dev)) {
-		ctl_reg = PCH_PP_CONTROL;
-		stat_reg = PCH_PP_STATUS;
-	} else {
-		ctl_reg = PP_CONTROL;
-		stat_reg = PP_STATUS;
-	}
-
-	I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
-	if (intel_wait_for_register(dev_priv, stat_reg, PP_ON, 0, 1000))
+	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~POWER_TARGET_ON);
+	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, 0, 1000))
 		DRM_ERROR("timed out waiting for panel to power off\n");
 
 	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
@@ -904,13 +886,10 @@ void intel_lvds_init(struct drm_device *dev)
 	 * Unlock registers and just leave them unlocked. Do this before
 	 * checking quirk lists to avoid bogus WARNINGs.
 	 */
-	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PCH_PP_CONTROL,
-			   I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
-	} else if (INTEL_INFO(dev_priv)->gen < 5) {
-		I915_WRITE(PP_CONTROL,
-			   I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
-	}
+	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
+		I915_WRITE(PP_CONTROL(0),
+			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
+
 	if (!intel_lvds_supported(dev))
 		return;
 
@@ -945,12 +924,12 @@ void intel_lvds_init(struct drm_device *dev)
 
 	 /* Set the Panel Power On/Off timings if uninitialized. */
 	if (INTEL_INFO(dev_priv)->gen < 5 &&
-	    I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) {
+	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
 		/* Set T2 to 40ms and T5 to 200ms */
-		I915_WRITE(PP_ON_DELAYS, 0x019007d0);
+		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
 
 		/* Set T3 to 35ms and Tx to 200ms */
-		I915_WRITE(PP_OFF_DELAYS, 0x015e07d0);
+		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
 
 		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
 	}
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v2 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling
  2016-08-09 11:34 ` [PATCH 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling Imre Deak
  2016-08-09 12:48   ` Ville Syrjälä
@ 2016-08-09 17:21   ` Imre Deak
  2016-08-09 17:46     ` Ville Syrjälä
  2016-08-09 18:59     ` [PATCH v3 " Imre Deak
  1 sibling, 2 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 17:21 UTC (permalink / raw)
  To: intel-gfx

Atm the LVDS encoder depends on the PPS HW context being saved/restored
from generic suspend/resume code. Since the PPS is specific to the LVDS
and eDP encoders a cleaner way is to reinitialize it during encoder
enabling, so do this here for LVDS. Follow-up patches will init the PPS
for the eDP encoder similarly and remove the suspend/resume time save /
restore.

v2:
- Apply BSpec +1 offset and use DIV_ROUND_UP() when programming the
power cycle delay. (Ville)

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h   |   1 +
 drivers/gpu/drm/i915/intel_lvds.c | 113 +++++++++++++++++++++++++++++++++-----
 2 files changed, 101 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 889508f..da82744 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3710,6 +3710,7 @@ enum {
 
 #define _PP_ON_DELAYS			0x61208
 #define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
+#define  PANEL_PORT_SELECT_SHIFT	30
 #define  PANEL_PORT_SELECT_MASK		(3 << 30)
 #define  PANEL_PORT_SELECT_LVDS		(0 << 30)
 #define  PANEL_PORT_SELECT_DPA		(1 << 30)
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index c5739fc..939f51f 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -48,6 +48,20 @@ struct intel_lvds_connector {
 	struct notifier_block lid_notifier;
 };
 
+struct intel_lvds_pps {
+	/* 100us units */
+	int t1_t2;
+	int t3;
+	int t4;
+	int t5;
+	int tx;
+
+	int divider;
+
+	int port;
+	bool reset_on_powerdown;
+};
+
 struct intel_lvds_encoder {
 	struct intel_encoder base;
 
@@ -55,6 +69,9 @@ struct intel_lvds_encoder {
 	i915_reg_t reg;
 	u32 a3_power;
 
+	struct intel_lvds_pps init_pps;
+	u32 init_lvds_val;
+
 	struct intel_lvds_connector *attached_connector;
 };
 
@@ -136,6 +153,82 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
 	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
 }
 
+static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
+					struct intel_lvds_pps *pps)
+{
+	u32 val;
+
+	pps->reset_on_powerdown = I915_READ(PP_CONTROL(0)) & PANEL_POWER_RESET;
+
+	val = I915_READ(PP_ON_DELAYS(0));
+	pps->port = (val & PANEL_PORT_SELECT_MASK) >>
+		    PANEL_PORT_SELECT_SHIFT;
+	pps->t1_t2 = (val & PANEL_POWER_UP_DELAY_MASK) >>
+		     PANEL_POWER_UP_DELAY_SHIFT;
+	pps->t5 = (val & PANEL_LIGHT_ON_DELAY_MASK) >>
+		  PANEL_LIGHT_ON_DELAY_SHIFT;
+
+	val = I915_READ(PP_OFF_DELAYS(0));
+	pps->t3 = (val & PANEL_POWER_DOWN_DELAY_MASK) >>
+		  PANEL_POWER_DOWN_DELAY_SHIFT;
+	pps->tx = (val & PANEL_LIGHT_OFF_DELAY_MASK) >>
+		  PANEL_LIGHT_OFF_DELAY_SHIFT;
+
+	val = I915_READ(PP_DIVISOR(0));
+	pps->divider = (val & PP_REFERENCE_DIVIDER_MASK) >>
+		       PP_REFERENCE_DIVIDER_SHIFT;
+	val = (val & PANEL_POWER_CYCLE_DELAY_MASK) >>
+	      PANEL_POWER_CYCLE_DELAY_SHIFT;
+	/*
+	 * Remove the BSpec specified +1 (100ms) offset that accounts for a
+	 * too short power-cycle delay due to the asynchronous programming of
+	 * the register.
+	 */
+	if (val)
+		val--;
+	/* Convert from 100ms to 100us units */
+	pps->t4 = val * 1000;
+
+	if (INTEL_INFO(dev_priv)->gen <= 4 &&
+	    pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
+		DRM_DEBUG_KMS("Panel power timings uninitialized, "
+			      "setting defaults\n");
+		/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
+		pps->t1_t2 = 40 * 10;
+		pps->t5 = 200 * 10;
+		/* Set T3 to 35ms and Tx to 200ms in 100 usec units */
+		pps->t3 = 35 * 10;
+		pps->tx = 200 * 10;
+	}
+
+	DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
+			 "divider %d port %d reset_on_powerdown %d\n",
+			 pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
+			 pps->divider, pps->port, pps->reset_on_powerdown);
+}
+
+static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
+				   struct intel_lvds_pps *pps)
+{
+	u32 val;
+
+	val = I915_READ(PP_CONTROL(0));
+	WARN_ON((val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);
+	if (pps->reset_on_powerdown)
+		val |= PANEL_POWER_RESET;
+	I915_WRITE(PP_CONTROL(0), val);
+
+	I915_WRITE(PP_ON_DELAYS(0), (pps->port << PANEL_PORT_SELECT_SHIFT) |
+				    (pps->t1_t2 << PANEL_POWER_UP_DELAY_SHIFT) |
+				    (pps->t5 << PANEL_LIGHT_ON_DELAY_SHIFT));
+	I915_WRITE(PP_OFF_DELAYS(0), (pps->t3 << PANEL_POWER_DOWN_DELAY_SHIFT) |
+				     (pps->tx << PANEL_LIGHT_OFF_DELAY_SHIFT));
+
+	val = pps->divider << PP_REFERENCE_DIVIDER_SHIFT;
+	val |= DIV_ROUND_UP(pps->t4 + 1, 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT;
+	I915_WRITE(PP_DIVISOR(0), val);
+}
+
 static void intel_pre_enable_lvds(struct intel_encoder *encoder)
 {
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
@@ -154,7 +247,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder)
 		assert_pll_disabled(dev_priv, pipe);
 	}
 
-	temp = I915_READ(lvds_encoder->reg);
+	intel_lvds_pps_init_hw(dev_priv, &lvds_encoder->init_pps);
+
+	temp = lvds_encoder->init_lvds_val;
 	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
 
 	if (HAS_PCH_CPT(dev)) {
@@ -922,18 +1017,6 @@ void intel_lvds_init(struct drm_device *dev)
 		DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
 	}
 
-	 /* Set the Panel Power On/Off timings if uninitialized. */
-	if (INTEL_INFO(dev_priv)->gen < 5 &&
-	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
-		/* Set T2 to 40ms and T5 to 200ms */
-		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
-
-		/* Set T3 to 35ms and Tx to 200ms */
-		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
-
-		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
-	}
-
 	lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
 	if (!lvds_encoder)
 		return;
@@ -999,6 +1082,10 @@ void intel_lvds_init(struct drm_device *dev)
 				      dev->mode_config.scaling_mode_property,
 				      DRM_MODE_SCALE_ASPECT);
 	intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
+
+	intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps);
+	lvds_encoder->init_lvds_val = lvds;
+
 	/*
 	 * LVDS discovery:
 	 * 1) check for EDID on DDC
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v2 4/6] drm/i915/dp: Restore PPS HW state from the encoder resume hook
  2016-08-09 11:34 ` [PATCH 4/6] drm/i915/dp: Restore PPS HW state from the encoder resume hook Imre Deak
  2016-08-09 12:52   ` Ville Syrjälä
@ 2016-08-09 17:21   ` Imre Deak
  2016-08-09 17:49     ` Ville Syrjälä
  1 sibling, 1 reply; 30+ messages in thread
From: Imre Deak @ 2016-08-09 17:21 UTC (permalink / raw)
  To: intel-gfx

Similarly to the previous patch, initialize the PPS from the DP
encoder's resume hook. Note that as opposed to LVDS we can't do this
during encoder enabling, since we need the PPS for DP detection as well.
The PPS init code is now the same for init and resume, so factor out a
new intel_dp_pps_init() helper for this.

v2:
- Factor out intel_dp_pps_init() (Ville).

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a20faa0..2ef7b14 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -256,6 +256,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
 static void
 intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 					      struct intel_dp *intel_dp);
+static void
+intel_dp_pps_init(struct drm_device *dev, struct intel_dp *intel_dp);
 
 static void pps_lock(struct intel_dp *intel_dp)
 {
@@ -4657,13 +4659,8 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 
 	pps_lock(intel_dp);
 
-	/*
-	 * Read out the current power sequencer assignment,
-	 * in case the BIOS did something with it.
-	 */
-	if (IS_VALLEYVIEW(encoder->dev) || IS_CHERRYVIEW(encoder->dev))
-		vlv_initial_power_sequencer_setup(intel_dp);
-
+	/* Reinit the power sequencer, in case BIOS did something with it. */
+	intel_dp_pps_init(encoder->dev, intel_dp);
 	intel_edp_panel_vdd_sanitize(intel_dp);
 
 	pps_unlock(intel_dp);
@@ -5011,6 +5008,17 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 		      I915_READ(regs.pp_div));
 }
 
+static void intel_dp_pps_init(struct drm_device *dev,
+			      struct intel_dp *intel_dp)
+{
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+		vlv_initial_power_sequencer_setup(intel_dp);
+	} else {
+		intel_dp_init_panel_power_sequencer(dev, intel_dp);
+		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+	}
+}
+
 /**
  * intel_dp_set_drrs_state - program registers for RR switch to take effect
  * @dev: DRM device
@@ -5425,14 +5433,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	pps_lock(intel_dp);
 
 	intel_dp_init_panel_power_timestamps(intel_dp);
-
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
-		vlv_initial_power_sequencer_setup(intel_dp);
-	} else {
-		intel_dp_init_panel_power_sequencer(dev, intel_dp);
-		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
-	}
-
+	intel_dp_pps_init(dev, intel_dp);
 	intel_edp_panel_vdd_sanitize(intel_dp);
 
 	pps_unlock(intel_dp);
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v2 5/6] drm/i915: Apply the PPS register unlock workaround more consistently
  2016-08-09 11:34 ` [PATCH 5/6] drm/i915: Apply the PPS register unlock workaround more consistently Imre Deak
  2016-08-09 13:01   ` Ville Syrjälä
@ 2016-08-09 17:21   ` Imre Deak
  2016-08-09 17:46     ` Ville Syrjälä
  2016-08-09 18:59     ` [PATCH v3 " Imre Deak
  1 sibling, 2 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 17:21 UTC (permalink / raw)
  To: intel-gfx

Atm, we apply this workaround somewhat inconsistently at the following
points: driver loading, LVDS init, eDP PPS init, system resume. As this
workaround also affects registers other than PPS (timing, PLL) a more
consistent way is to apply it early after the PPS HW context is known to
be lost: driver loading, system resume and on VLV/CHV/BXT when turning
on power domains.

This is needed by the next patch that removes saving/restoring of the
PP_CONTROL register.

This also removes the incorrect programming of the workaround on HSW+
PCH platforms which don't have the register locking mechanism.

v2: (Ville)
- Don't apply the workaround on BXT.
- Simplify platform checks using HAS_DDI().

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c         |  1 +
 drivers/gpu/drm/i915/intel_display.c    | 26 ++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_dp.c         |  3 ++-
 drivers/gpu/drm/i915/intel_drv.h        |  1 +
 drivers/gpu/drm/i915/intel_lvds.c       |  8 --------
 drivers/gpu/drm/i915/intel_runtime_pm.c |  4 ++++
 6 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 8cfc264..0fcd1c0 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1560,6 +1560,7 @@ static int i915_drm_resume(struct drm_device *dev)
 	i915_gem_resume(dev);
 
 	i915_restore_state(dev);
+	intel_pps_unlock_regs_wa(dev_priv);
 	intel_opregion_setup(dev_priv);
 
 	intel_init_pch_refclk(dev);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3d5fd06..bcbf277 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14635,6 +14635,30 @@ static bool intel_crt_present(struct drm_device *dev)
 	return true;
 }
 
+void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
+{
+	int pps_num;
+	int pps_idx;
+
+	if (HAS_DDI(dev_priv))
+		return;
+	/*
+	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
+	 * everywhere where registers can be write protected.
+	 */
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		pps_num = 2;
+	else
+		pps_num = 1;
+
+	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
+		u32 val = I915_READ(PP_CONTROL(pps_idx));
+
+		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
+		I915_WRITE(PP_CONTROL(pps_idx), val);
+	}
+}
+
 static void intel_pps_init(struct drm_i915_private *dev_priv)
 {
 	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
@@ -14643,6 +14667,8 @@ static void intel_pps_init(struct drm_i915_private *dev_priv)
 		dev_priv->pps_mmio_base = VLV_PPS_BASE;
 	else
 		dev_priv->pps_mmio_base = PPS_BASE;
+
+	intel_pps_unlock_regs_wa(dev_priv);
 }
 
 static void intel_setup_outputs(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 2ef7b14..3d3d3fb 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1829,7 +1829,8 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
 	control = I915_READ(_pp_ctrl_reg(intel_dp));
-	if (!IS_BROXTON(dev)) {
+	if (WARN_ON(!HAS_DDI(dev_priv) &&
+		     (control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
 		control &= ~PANEL_UNLOCK_MASK;
 		control |= PANEL_UNLOCK_REGS;
 	}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c29a429..cbce786 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1159,6 +1159,7 @@ void intel_mark_busy(struct drm_i915_private *dev_priv);
 void intel_mark_idle(struct drm_i915_private *dev_priv);
 void intel_crtc_restore_mode(struct drm_crtc *crtc);
 int intel_display_suspend(struct drm_device *dev);
+void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
 void intel_encoder_destroy(struct drm_encoder *encoder);
 int intel_connector_init(struct intel_connector *);
 struct intel_connector *intel_connector_alloc(void);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 939f51f..35d55f1 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -977,14 +977,6 @@ void intel_lvds_init(struct drm_device *dev)
 	int pipe;
 	u8 pin;
 
-	/*
-	 * Unlock registers and just leave them unlocked. Do this before
-	 * checking quirk lists to avoid bogus WARNINGs.
-	 */
-	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
-		I915_WRITE(PP_CONTROL(0),
-			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
-
 	if (!intel_lvds_supported(dev))
 		return;
 
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 1c603bb..8f51ae3 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -592,6 +592,8 @@ void bxt_disable_dc9(struct drm_i915_private *dev_priv)
 	DRM_DEBUG_KMS("Disabling DC9\n");
 
 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+	intel_pps_unlock_regs_wa(dev_priv);
 }
 
 static void assert_csr_loaded(struct drm_i915_private *dev_priv)
@@ -1145,6 +1147,8 @@ static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
 	vlv_set_power_well(dev_priv, power_well, true);
 
 	vlv_display_power_well_init(dev_priv);
+
+	intel_pps_unlock_regs_wa(dev_priv);
 }
 
 static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 5/6] drm/i915: Apply the PPS register unlock workaround more consistently
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
@ 2016-08-09 17:46     ` Ville Syrjälä
  2016-08-09 18:59     ` [PATCH v3 " Imre Deak
  1 sibling, 0 replies; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 17:46 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 08:21:34PM +0300, Imre Deak wrote:
> Atm, we apply this workaround somewhat inconsistently at the following
> points: driver loading, LVDS init, eDP PPS init, system resume. As this
> workaround also affects registers other than PPS (timing, PLL) a more
> consistent way is to apply it early after the PPS HW context is known to
> be lost: driver loading, system resume and on VLV/CHV/BXT when turning
> on power domains.
> 
> This is needed by the next patch that removes saving/restoring of the
> PP_CONTROL register.
> 
> This also removes the incorrect programming of the workaround on HSW+
> PCH platforms which don't have the register locking mechanism.
> 
> v2: (Ville)
> - Don't apply the workaround on BXT.
> - Simplify platform checks using HAS_DDI().
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c         |  1 +
>  drivers/gpu/drm/i915/intel_display.c    | 26 ++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_dp.c         |  3 ++-
>  drivers/gpu/drm/i915/intel_drv.h        |  1 +
>  drivers/gpu/drm/i915/intel_lvds.c       |  8 --------
>  drivers/gpu/drm/i915/intel_runtime_pm.c |  4 ++++
>  6 files changed, 34 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 8cfc264..0fcd1c0 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1560,6 +1560,7 @@ static int i915_drm_resume(struct drm_device *dev)
>  	i915_gem_resume(dev);
>  
>  	i915_restore_state(dev);
> +	intel_pps_unlock_regs_wa(dev_priv);
>  	intel_opregion_setup(dev_priv);
>  
>  	intel_init_pch_refclk(dev);
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3d5fd06..bcbf277 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -14635,6 +14635,30 @@ static bool intel_crt_present(struct drm_device *dev)
>  	return true;
>  }
>  
> +void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
> +{
> +	int pps_num;
> +	int pps_idx;
> +
> +	if (HAS_DDI(dev_priv))
> +		return;
> +	/*
> +	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
> +	 * everywhere where registers can be write protected.
> +	 */
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		pps_num = 2;
> +	else
> +		pps_num = 1;
> +
> +	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
> +		u32 val = I915_READ(PP_CONTROL(pps_idx));
> +
> +		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
> +		I915_WRITE(PP_CONTROL(pps_idx), val);
> +	}
> +}
> +
>  static void intel_pps_init(struct drm_i915_private *dev_priv)
>  {
>  	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
> @@ -14643,6 +14667,8 @@ static void intel_pps_init(struct drm_i915_private *dev_priv)
>  		dev_priv->pps_mmio_base = VLV_PPS_BASE;
>  	else
>  		dev_priv->pps_mmio_base = PPS_BASE;
> +
> +	intel_pps_unlock_regs_wa(dev_priv);
>  }
>  
>  static void intel_setup_outputs(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 2ef7b14..3d3d3fb 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1829,7 +1829,8 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
>  	control = I915_READ(_pp_ctrl_reg(intel_dp));
> -	if (!IS_BROXTON(dev)) {
> +	if (WARN_ON(!HAS_DDI(dev_priv) &&
> +		     (control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
>  		control &= ~PANEL_UNLOCK_MASK;
>  		control |= PANEL_UNLOCK_REGS;
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index c29a429..cbce786 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1159,6 +1159,7 @@ void intel_mark_busy(struct drm_i915_private *dev_priv);
>  void intel_mark_idle(struct drm_i915_private *dev_priv);
>  void intel_crtc_restore_mode(struct drm_crtc *crtc);
>  int intel_display_suspend(struct drm_device *dev);
> +void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
>  void intel_encoder_destroy(struct drm_encoder *encoder);
>  int intel_connector_init(struct intel_connector *);
>  struct intel_connector *intel_connector_alloc(void);
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 939f51f..35d55f1 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -977,14 +977,6 @@ void intel_lvds_init(struct drm_device *dev)
>  	int pipe;
>  	u8 pin;
>  
> -	/*
> -	 * Unlock registers and just leave them unlocked. Do this before
> -	 * checking quirk lists to avoid bogus WARNINGs.
> -	 */
> -	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
> -		I915_WRITE(PP_CONTROL(0),
> -			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
> -
>  	if (!intel_lvds_supported(dev))
>  		return;
>  
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 1c603bb..8f51ae3 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -592,6 +592,8 @@ void bxt_disable_dc9(struct drm_i915_private *dev_priv)
>  	DRM_DEBUG_KMS("Disabling DC9\n");
>  
>  	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
> +
> +	intel_pps_unlock_regs_wa(dev_priv);
>  }
>  
>  static void assert_csr_loaded(struct drm_i915_private *dev_priv)
> @@ -1145,6 +1147,8 @@ static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
>  	vlv_set_power_well(dev_priv, power_well, true);
>  
>  	vlv_display_power_well_init(dev_priv);
> +
> +	intel_pps_unlock_regs_wa(dev_priv);

I'd put the call inside vlv_display_power_well_init(). That's where we
initialize all the other display registers.

Either way
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

>  }
>  
>  static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
> -- 
> 2.5.0

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
@ 2016-08-09 17:46     ` Ville Syrjälä
  2016-08-09 18:59     ` [PATCH v3 " Imre Deak
  1 sibling, 0 replies; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 17:46 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 08:21:32PM +0300, Imre Deak wrote:
> Atm the LVDS encoder depends on the PPS HW context being saved/restored
> from generic suspend/resume code. Since the PPS is specific to the LVDS
> and eDP encoders a cleaner way is to reinitialize it during encoder
> enabling, so do this here for LVDS. Follow-up patches will init the PPS
> for the eDP encoder similarly and remove the suspend/resume time save /
> restore.
> 
> v2:
> - Apply BSpec +1 offset and use DIV_ROUND_UP() when programming the
> power cycle delay. (Ville)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h   |   1 +
>  drivers/gpu/drm/i915/intel_lvds.c | 113 +++++++++++++++++++++++++++++++++-----
>  2 files changed, 101 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 889508f..da82744 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3710,6 +3710,7 @@ enum {
>  
>  #define _PP_ON_DELAYS			0x61208
>  #define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
> +#define  PANEL_PORT_SELECT_SHIFT	30
>  #define  PANEL_PORT_SELECT_MASK		(3 << 30)
>  #define  PANEL_PORT_SELECT_LVDS		(0 << 30)
>  #define  PANEL_PORT_SELECT_DPA		(1 << 30)
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index c5739fc..939f51f 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -48,6 +48,20 @@ struct intel_lvds_connector {
>  	struct notifier_block lid_notifier;
>  };
>  
> +struct intel_lvds_pps {
> +	/* 100us units */
> +	int t1_t2;
> +	int t3;
> +	int t4;
> +	int t5;
> +	int tx;
> +
> +	int divider;
> +
> +	int port;
> +	bool reset_on_powerdown;

powerdown_on_reset?

> +};
> +
>  struct intel_lvds_encoder {
>  	struct intel_encoder base;
>  
> @@ -55,6 +69,9 @@ struct intel_lvds_encoder {
>  	i915_reg_t reg;
>  	u32 a3_power;
>  
> +	struct intel_lvds_pps init_pps;
> +	u32 init_lvds_val;
> +
>  	struct intel_lvds_connector *attached_connector;
>  };
>  
> @@ -136,6 +153,82 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
>  	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
>  }
>  
> +static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
> +					struct intel_lvds_pps *pps)
> +{
> +	u32 val;
> +
> +	pps->reset_on_powerdown = I915_READ(PP_CONTROL(0)) & PANEL_POWER_RESET;
> +
> +	val = I915_READ(PP_ON_DELAYS(0));
> +	pps->port = (val & PANEL_PORT_SELECT_MASK) >>
> +		    PANEL_PORT_SELECT_SHIFT;
> +	pps->t1_t2 = (val & PANEL_POWER_UP_DELAY_MASK) >>
> +		     PANEL_POWER_UP_DELAY_SHIFT;
> +	pps->t5 = (val & PANEL_LIGHT_ON_DELAY_MASK) >>
> +		  PANEL_LIGHT_ON_DELAY_SHIFT;
> +
> +	val = I915_READ(PP_OFF_DELAYS(0));
> +	pps->t3 = (val & PANEL_POWER_DOWN_DELAY_MASK) >>
> +		  PANEL_POWER_DOWN_DELAY_SHIFT;
> +	pps->tx = (val & PANEL_LIGHT_OFF_DELAY_MASK) >>
> +		  PANEL_LIGHT_OFF_DELAY_SHIFT;
> +
> +	val = I915_READ(PP_DIVISOR(0));
> +	pps->divider = (val & PP_REFERENCE_DIVIDER_MASK) >>
> +		       PP_REFERENCE_DIVIDER_SHIFT;
> +	val = (val & PANEL_POWER_CYCLE_DELAY_MASK) >>
> +	      PANEL_POWER_CYCLE_DELAY_SHIFT;
> +	/*
> +	 * Remove the BSpec specified +1 (100ms) offset that accounts for a
> +	 * too short power-cycle delay due to the asynchronous programming of
> +	 * the register.
> +	 */
> +	if (val)
> +		val--;
> +	/* Convert from 100ms to 100us units */
> +	pps->t4 = val * 1000;
> +
> +	if (INTEL_INFO(dev_priv)->gen <= 4 &&
> +	    pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
> +		DRM_DEBUG_KMS("Panel power timings uninitialized, "
> +			      "setting defaults\n");
> +		/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
> +		pps->t1_t2 = 40 * 10;
> +		pps->t5 = 200 * 10;
> +		/* Set T3 to 35ms and Tx to 200ms in 100 usec units */
> +		pps->t3 = 35 * 10;
> +		pps->tx = 200 * 10;
> +	}
> +
> +	DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
> +			 "divider %d port %d reset_on_powerdown %d\n",
> +			 pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
> +			 pps->divider, pps->port, pps->reset_on_powerdown);
> +}
> +
> +static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
> +				   struct intel_lvds_pps *pps)
> +{
> +	u32 val;
> +
> +	val = I915_READ(PP_CONTROL(0));
> +	WARN_ON((val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);
> +	if (pps->reset_on_powerdown)
> +		val |= PANEL_POWER_RESET;
> +	I915_WRITE(PP_CONTROL(0), val);
> +
> +	I915_WRITE(PP_ON_DELAYS(0), (pps->port << PANEL_PORT_SELECT_SHIFT) |
> +				    (pps->t1_t2 << PANEL_POWER_UP_DELAY_SHIFT) |
> +				    (pps->t5 << PANEL_LIGHT_ON_DELAY_SHIFT));
> +	I915_WRITE(PP_OFF_DELAYS(0), (pps->t3 << PANEL_POWER_DOWN_DELAY_SHIFT) |
> +				     (pps->tx << PANEL_LIGHT_OFF_DELAY_SHIFT));
> +
> +	val = pps->divider << PP_REFERENCE_DIVIDER_SHIFT;
> +	val |= DIV_ROUND_UP(pps->t4 + 1, 1000) << PANEL_POWER_CYCLE_DELAY_SHIFT;

+1 vs. div in the wrong order

With that fixed
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> +	I915_WRITE(PP_DIVISOR(0), val);
> +}
> +
>  static void intel_pre_enable_lvds(struct intel_encoder *encoder)
>  {
>  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
> @@ -154,7 +247,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder)
>  		assert_pll_disabled(dev_priv, pipe);
>  	}
>  
> -	temp = I915_READ(lvds_encoder->reg);
> +	intel_lvds_pps_init_hw(dev_priv, &lvds_encoder->init_pps);
> +
> +	temp = lvds_encoder->init_lvds_val;
>  	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
>  
>  	if (HAS_PCH_CPT(dev)) {
> @@ -922,18 +1017,6 @@ void intel_lvds_init(struct drm_device *dev)
>  		DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
>  	}
>  
> -	 /* Set the Panel Power On/Off timings if uninitialized. */
> -	if (INTEL_INFO(dev_priv)->gen < 5 &&
> -	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
> -		/* Set T2 to 40ms and T5 to 200ms */
> -		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
> -
> -		/* Set T3 to 35ms and Tx to 200ms */
> -		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
> -
> -		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
> -	}
> -
>  	lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
>  	if (!lvds_encoder)
>  		return;
> @@ -999,6 +1082,10 @@ void intel_lvds_init(struct drm_device *dev)
>  				      dev->mode_config.scaling_mode_property,
>  				      DRM_MODE_SCALE_ASPECT);
>  	intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
> +
> +	intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps);
> +	lvds_encoder->init_lvds_val = lvds;
> +
>  	/*
>  	 * LVDS discovery:
>  	 * 1) check for EDID on DDC
> -- 
> 2.5.0

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 4/6] drm/i915/dp: Restore PPS HW state from the encoder resume hook
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
@ 2016-08-09 17:49     ` Ville Syrjälä
  0 siblings, 0 replies; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 17:49 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 08:21:33PM +0300, Imre Deak wrote:
> Similarly to the previous patch, initialize the PPS from the DP
> encoder's resume hook. Note that as opposed to LVDS we can't do this
> during encoder enabling, since we need the PPS for DP detection as well.
> The PPS init code is now the same for init and resume, so factor out a
> new intel_dp_pps_init() helper for this.
> 
> v2:
> - Factor out intel_dp_pps_init() (Ville).
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/intel_dp.c | 31 ++++++++++++++++---------------
>  1 file changed, 16 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index a20faa0..2ef7b14 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -256,6 +256,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
>  static void
>  intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>  					      struct intel_dp *intel_dp);
> +static void
> +intel_dp_pps_init(struct drm_device *dev, struct intel_dp *intel_dp);
>  
>  static void pps_lock(struct intel_dp *intel_dp)
>  {
> @@ -4657,13 +4659,8 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
>  
>  	pps_lock(intel_dp);
>  
> -	/*
> -	 * Read out the current power sequencer assignment,
> -	 * in case the BIOS did something with it.
> -	 */
> -	if (IS_VALLEYVIEW(encoder->dev) || IS_CHERRYVIEW(encoder->dev))
> -		vlv_initial_power_sequencer_setup(intel_dp);
> -
> +	/* Reinit the power sequencer, in case BIOS did something with it. */
> +	intel_dp_pps_init(encoder->dev, intel_dp);
>  	intel_edp_panel_vdd_sanitize(intel_dp);
>  
>  	pps_unlock(intel_dp);
> @@ -5011,6 +5008,17 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>  		      I915_READ(regs.pp_div));
>  }
>  
> +static void intel_dp_pps_init(struct drm_device *dev,
> +			      struct intel_dp *intel_dp)
> +{
> +	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
> +		vlv_initial_power_sequencer_setup(intel_dp);
> +	} else {
> +		intel_dp_init_panel_power_sequencer(dev, intel_dp);
> +		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
> +	}
> +}
> +
>  /**
>   * intel_dp_set_drrs_state - program registers for RR switch to take effect
>   * @dev: DRM device
> @@ -5425,14 +5433,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	pps_lock(intel_dp);
>  
>  	intel_dp_init_panel_power_timestamps(intel_dp);
> -
> -	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
> -		vlv_initial_power_sequencer_setup(intel_dp);
> -	} else {
> -		intel_dp_init_panel_power_sequencer(dev, intel_dp);
> -		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
> -	}
> -
> +	intel_dp_pps_init(dev, intel_dp);
>  	intel_edp_panel_vdd_sanitize(intel_dp);
>  
>  	pps_unlock(intel_dp);
> -- 
> 2.5.0

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v2 1/6] drm/i915: Merge the PPS register definitions
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
@ 2016-08-09 17:50     ` Ville Syrjälä
  0 siblings, 0 replies; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 17:50 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 08:21:31PM +0300, Imre Deak wrote:
> The PPS registers are pretty much the same everywhere, the differences
> being:
> - Register fields appearing, disappearing from one platform to the
>   next: panel-reset-on-powerdown, backlight-on, panel-port,
>   register-unlock
> - Different register base addresses
> - Different number of PPS instances: 2 on VLV/CHV/BXT, 1 everywhere
>   else.
> 
> We can merge the separate set of PPS definitions by extending the PPS
> instance argument to all platforms and using instance 0 on platforms
> with a single instance. This means we'll need to calculate the register
> addresses dynamically based on the given platform and PPS instance.
> 
> v2:
> - Simplify if ladder in intel_pps_get_registers(). (Ville)
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/i915_drv.h      |   2 +
>  drivers/gpu/drm/i915/i915_reg.h      | 145 ++++++++++++++---------------------
>  drivers/gpu/drm/i915/i915_suspend.c  |  30 +++-----
>  drivers/gpu/drm/i915/intel_display.c |  22 ++++--
>  drivers/gpu/drm/i915/intel_dp.c      |  45 +++++------
>  drivers/gpu/drm/i915/intel_lvds.c    |  43 +++--------
>  6 files changed, 117 insertions(+), 170 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index c36d176..fddaec6 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1749,6 +1749,8 @@ struct drm_i915_private {
>  
>  	uint32_t psr_mmio_base;
>  
> +	uint32_t pps_mmio_base;
> +
>  	wait_queue_head_t gmbus_wait_queue;
>  
>  	struct pci_dev *bridge_dev;
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index f38a5e2..b65fe50 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3660,8 +3660,17 @@ enum {
>  #define   VIDEO_DIP_ENABLE_SPD_HSW	(1 << 0)
>  
>  /* Panel power sequencing */
> -#define PP_STATUS	_MMIO(0x61200)
> -#define   PP_ON		(1 << 31)
> +#define PPS_BASE			0x61200
> +#define VLV_PPS_BASE			(VLV_DISPLAY_BASE + PPS_BASE)
> +#define PCH_PPS_BASE			0xC7200
> +
> +#define _MMIO_PPS(pps_idx, reg)		_MMIO(dev_priv->pps_mmio_base -	\
> +					      PPS_BASE + (reg) +	\
> +					      (pps_idx) * 0x100)
> +
> +#define _PP_STATUS			0x61200
> +#define PP_STATUS(pps_idx)		_MMIO_PPS(pps_idx, _PP_STATUS)
> +#define   PP_ON				(1 << 31)
>  /*
>   * Indicates that all dependencies of the panel are on:
>   *
> @@ -3669,14 +3678,14 @@ enum {
>   * - pipe enabled
>   * - LVDS/DVOB/DVOC on
>   */
> -#define   PP_READY		(1 << 30)
> -#define   PP_SEQUENCE_NONE	(0 << 28)
> -#define   PP_SEQUENCE_POWER_UP	(1 << 28)
> -#define   PP_SEQUENCE_POWER_DOWN (2 << 28)
> -#define   PP_SEQUENCE_MASK	(3 << 28)
> -#define   PP_SEQUENCE_SHIFT	28
> -#define   PP_CYCLE_DELAY_ACTIVE	(1 << 27)
> -#define   PP_SEQUENCE_STATE_MASK 0x0000000f
> +#define   PP_READY			(1 << 30)
> +#define   PP_SEQUENCE_NONE		(0 << 28)
> +#define   PP_SEQUENCE_POWER_UP		(1 << 28)
> +#define   PP_SEQUENCE_POWER_DOWN	(2 << 28)
> +#define   PP_SEQUENCE_MASK		(3 << 28)
> +#define   PP_SEQUENCE_SHIFT		28
> +#define   PP_CYCLE_DELAY_ACTIVE		(1 << 27)
> +#define   PP_SEQUENCE_STATE_MASK	0x0000000f
>  #define   PP_SEQUENCE_STATE_OFF_IDLE	(0x0 << 0)
>  #define   PP_SEQUENCE_STATE_OFF_S0_1	(0x1 << 0)
>  #define   PP_SEQUENCE_STATE_OFF_S0_2	(0x2 << 0)
> @@ -3686,11 +3695,46 @@ enum {
>  #define   PP_SEQUENCE_STATE_ON_S1_2	(0xa << 0)
>  #define   PP_SEQUENCE_STATE_ON_S1_3	(0xb << 0)
>  #define   PP_SEQUENCE_STATE_RESET	(0xf << 0)
> -#define PP_CONTROL	_MMIO(0x61204)
> -#define   POWER_TARGET_ON	(1 << 0)
> -#define PP_ON_DELAYS	_MMIO(0x61208)
> -#define PP_OFF_DELAYS	_MMIO(0x6120c)
> -#define PP_DIVISOR	_MMIO(0x61210)
> +
> +#define _PP_CONTROL			0x61204
> +#define PP_CONTROL(pps_idx)		_MMIO_PPS(pps_idx, _PP_CONTROL)
> +#define  PANEL_UNLOCK_REGS		(0xabcd << 16)
> +#define  PANEL_UNLOCK_MASK		(0xffff << 16)
> +#define  BXT_POWER_CYCLE_DELAY_MASK	0x1f0
> +#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
> +#define  EDP_FORCE_VDD			(1 << 3)
> +#define  EDP_BLC_ENABLE			(1 << 2)
> +#define  PANEL_POWER_RESET		(1 << 1)
> +#define  PANEL_POWER_OFF		(0 << 0)
> +#define  PANEL_POWER_ON			(1 << 0)
> +#define  POWER_TARGET_ON		(1 << 0)
> +
> +#define _PP_ON_DELAYS			0x61208
> +#define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
> +#define  PANEL_PORT_SELECT_MASK		(3 << 30)
> +#define  PANEL_PORT_SELECT_LVDS		(0 << 30)
> +#define  PANEL_PORT_SELECT_DPA		(1 << 30)
> +#define  PANEL_PORT_SELECT_DPC		(2 << 30)
> +#define  PANEL_PORT_SELECT_DPD		(3 << 30)
> +#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
> +#define  PANEL_POWER_UP_DELAY_MASK	0x1fff0000
> +#define  PANEL_POWER_UP_DELAY_SHIFT	16
> +#define  PANEL_LIGHT_ON_DELAY_MASK	0x1fff
> +#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
> +
> +#define _PP_OFF_DELAYS			0x6120C
> +#define PP_OFF_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_OFF_DELAYS)
> +#define  PANEL_POWER_DOWN_DELAY_MASK	0x1fff0000
> +#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
> +#define  PANEL_LIGHT_OFF_DELAY_MASK	0x1fff
> +#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
> +
> +#define _PP_DIVISOR			0x61210
> +#define PP_DIVISOR(pps_idx)		_MMIO_PPS(pps_idx, _PP_DIVISOR)
> +#define  PP_REFERENCE_DIVIDER_MASK	0xffffff00
> +#define  PP_REFERENCE_DIVIDER_SHIFT	8
> +#define  PANEL_POWER_CYCLE_DELAY_MASK	0x1f
> +#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
>  
>  /* Panel fitting */
>  #define PFIT_CONTROL	_MMIO(dev_priv->info.display_mmio_offset + 0x61230)
> @@ -6750,77 +6794,6 @@ enum {
>  #define PCH_LVDS	_MMIO(0xe1180)
>  #define  LVDS_DETECTED	(1 << 1)
>  
> -/* vlv has 2 sets of panel control regs. */
> -#define _PIPEA_PP_STATUS         (VLV_DISPLAY_BASE + 0x61200)
> -#define _PIPEA_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61204)
> -#define _PIPEA_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61208)
> -#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
> -#define _PIPEA_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6120c)
> -#define _PIPEA_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61210)
> -
> -#define _PIPEB_PP_STATUS         (VLV_DISPLAY_BASE + 0x61300)
> -#define _PIPEB_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61304)
> -#define _PIPEB_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61308)
> -#define _PIPEB_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6130c)
> -#define _PIPEB_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61310)
> -
> -#define VLV_PIPE_PP_STATUS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_STATUS, _PIPEB_PP_STATUS)
> -#define VLV_PIPE_PP_CONTROL(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_CONTROL, _PIPEB_PP_CONTROL)
> -#define VLV_PIPE_PP_ON_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_ON_DELAYS, _PIPEB_PP_ON_DELAYS)
> -#define VLV_PIPE_PP_OFF_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_OFF_DELAYS, _PIPEB_PP_OFF_DELAYS)
> -#define VLV_PIPE_PP_DIVISOR(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_DIVISOR, _PIPEB_PP_DIVISOR)
> -
> -#define _PCH_PP_STATUS		0xc7200
> -#define _PCH_PP_CONTROL		0xc7204
> -#define  PANEL_UNLOCK_REGS	(0xabcd << 16)
> -#define  PANEL_UNLOCK_MASK	(0xffff << 16)
> -#define  BXT_POWER_CYCLE_DELAY_MASK	(0x1f0)
> -#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
> -#define  EDP_FORCE_VDD		(1 << 3)
> -#define  EDP_BLC_ENABLE		(1 << 2)
> -#define  PANEL_POWER_RESET	(1 << 1)
> -#define  PANEL_POWER_OFF	(0 << 0)
> -#define  PANEL_POWER_ON		(1 << 0)
> -#define _PCH_PP_ON_DELAYS	0xc7208
> -#define  PANEL_PORT_SELECT_MASK	(3 << 30)
> -#define  PANEL_PORT_SELECT_LVDS	(0 << 30)
> -#define  PANEL_PORT_SELECT_DPA	(1 << 30)
> -#define  PANEL_PORT_SELECT_DPC	(2 << 30)
> -#define  PANEL_PORT_SELECT_DPD	(3 << 30)
> -#define  PANEL_POWER_UP_DELAY_MASK	(0x1fff0000)
> -#define  PANEL_POWER_UP_DELAY_SHIFT	16
> -#define  PANEL_LIGHT_ON_DELAY_MASK	(0x1fff)
> -#define  PANEL_LIGHT_ON_DELAY_SHIFT	0
> -
> -#define _PCH_PP_OFF_DELAYS		0xc720c
> -#define  PANEL_POWER_DOWN_DELAY_MASK	(0x1fff0000)
> -#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
> -#define  PANEL_LIGHT_OFF_DELAY_MASK	(0x1fff)
> -#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0
> -
> -#define _PCH_PP_DIVISOR			0xc7210
> -#define  PP_REFERENCE_DIVIDER_MASK	(0xffffff00)
> -#define  PP_REFERENCE_DIVIDER_SHIFT	8
> -#define  PANEL_POWER_CYCLE_DELAY_MASK	(0x1f)
> -#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
> -
> -#define PCH_PP_STATUS			_MMIO(_PCH_PP_STATUS)
> -#define PCH_PP_CONTROL			_MMIO(_PCH_PP_CONTROL)
> -#define PCH_PP_ON_DELAYS		_MMIO(_PCH_PP_ON_DELAYS)
> -#define PCH_PP_OFF_DELAYS		_MMIO(_PCH_PP_OFF_DELAYS)
> -#define PCH_PP_DIVISOR			_MMIO(_PCH_PP_DIVISOR)
> -
> -/* BXT PPS changes - 2nd set of PPS registers */
> -#define _BXT_PP_STATUS2 	0xc7300
> -#define _BXT_PP_CONTROL2 	0xc7304
> -#define _BXT_PP_ON_DELAYS2	0xc7308
> -#define _BXT_PP_OFF_DELAYS2	0xc730c
> -
> -#define BXT_PP_STATUS(n)	_MMIO_PIPE(n, _PCH_PP_STATUS, _BXT_PP_STATUS2)
> -#define BXT_PP_CONTROL(n)	_MMIO_PIPE(n, _PCH_PP_CONTROL, _BXT_PP_CONTROL2)
> -#define BXT_PP_ON_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2)
> -#define BXT_PP_OFF_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2)
> -
>  #define _PCH_DP_B		0xe4100
>  #define PCH_DP_B		_MMIO(_PCH_DP_B)
>  #define _PCH_DPB_AUX_CH_CTL	0xe4110
> diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
> index 5cfe4c7..c826b69 100644
> --- a/drivers/gpu/drm/i915/i915_suspend.c
> +++ b/drivers/gpu/drm/i915/i915_suspend.c
> @@ -44,16 +44,11 @@ static void i915_save_display(struct drm_device *dev)
>  		dev_priv->regfile.saveLVDS = I915_READ(LVDS);
>  
>  	/* Panel power sequencer */
> -	if (HAS_PCH_SPLIT(dev)) {
> -		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
> -		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
> -		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
> -		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
> -	} else if (INTEL_INFO(dev)->gen <= 4) {
> -		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
> -		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
> -		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
> -		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
> +	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
> +		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL(0));
> +		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS(0));
> +		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS(0));
> +		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR(0));
>  	}
>  
>  	/* save FBC interval */
> @@ -79,16 +74,11 @@ static void i915_restore_display(struct drm_device *dev)
>  		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);
>  
>  	/* Panel power sequencer */
> -	if (HAS_PCH_SPLIT(dev)) {
> -		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
> -		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
> -		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
> -		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
> -	} else if (INTEL_INFO(dev)->gen <= 4) {
> -		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
> -		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
> -		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
> -		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
> +	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
> +		I915_WRITE(PP_ON_DELAYS(0), dev_priv->regfile.savePP_ON_DELAYS);
> +		I915_WRITE(PP_OFF_DELAYS(0), dev_priv->regfile.savePP_OFF_DELAYS);
> +		I915_WRITE(PP_DIVISOR(0), dev_priv->regfile.savePP_DIVISOR);
> +		I915_WRITE(PP_CONTROL(0), dev_priv->regfile.savePP_CONTROL);
>  	}
>  
>  	/* only restore FBC info on the platform that supports FBC*/
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c6f27ab..3d5fd06 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1202,8 +1202,8 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
>  	if (HAS_PCH_SPLIT(dev)) {
>  		u32 port_sel;
>  
> -		pp_reg = PCH_PP_CONTROL;
> -		port_sel = I915_READ(PCH_PP_ON_DELAYS) & PANEL_PORT_SELECT_MASK;
> +		pp_reg = PP_CONTROL(0);
> +		port_sel = I915_READ(PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK;
>  
>  		if (port_sel == PANEL_PORT_SELECT_LVDS &&
>  		    I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
> @@ -1211,10 +1211,10 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
>  		/* XXX: else fix for eDP */
>  	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
>  		/* presumably write lock depends on pipe, not port select */
> -		pp_reg = VLV_PIPE_PP_CONTROL(pipe);
> +		pp_reg = PP_CONTROL(pipe);
>  		panel_pipe = pipe;
>  	} else {
> -		pp_reg = PP_CONTROL;
> +		pp_reg = PP_CONTROL(0);
>  		if (I915_READ(LVDS) & LVDS_PIPEB_SELECT)
>  			panel_pipe = PIPE_B;
>  	}
> @@ -9411,7 +9411,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
>  	I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
>  	I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
>  	I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
> -	I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
> +	I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n");
>  	I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
>  	     "CPU PWM1 enabled\n");
>  	if (IS_HASWELL(dev))
> @@ -14635,12 +14635,24 @@ static bool intel_crt_present(struct drm_device *dev)
>  	return true;
>  }
>  
> +static void intel_pps_init(struct drm_i915_private *dev_priv)
> +{
> +	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
> +		dev_priv->pps_mmio_base = PCH_PPS_BASE;
> +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		dev_priv->pps_mmio_base = VLV_PPS_BASE;
> +	else
> +		dev_priv->pps_mmio_base = PPS_BASE;
> +}
> +
>  static void intel_setup_outputs(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct intel_encoder *encoder;
>  	bool dpd_is_edp = false;
>  
> +	intel_pps_init(dev_priv);
> +
>  	/*
>  	 * intel_edp_init_connector() depends on this completing first, to
>  	 * prevent the registeration of both eDP and LVDS and the incorrect
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 8fe2afa..15aff93 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -463,13 +463,13 @@ typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
>  static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
>  			       enum pipe pipe)
>  {
> -	return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
> +	return I915_READ(PP_STATUS(pipe)) & PP_ON;
>  }
>  
>  static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
>  				enum pipe pipe)
>  {
> -	return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
> +	return I915_READ(PP_CONTROL(pipe)) & EDP_FORCE_VDD;
>  }
>  
>  static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
> @@ -486,7 +486,7 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
>  	enum pipe pipe;
>  
>  	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
> -		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
> +		u32 port_sel = I915_READ(PP_ON_DELAYS(pipe)) &
>  			PANEL_PORT_SELECT_MASK;
>  
>  		if (port_sel != PANEL_PORT_SELECT_VLV(port))
> @@ -583,30 +583,21 @@ static void intel_pps_get_registers(struct drm_i915_private *dev_priv,
>  				    struct intel_dp *intel_dp,
>  				    struct pps_registers *regs)
>  {
> +	int pps_idx = 0;
> +
>  	memset(regs, 0, sizeof(*regs));
>  
> -	if (IS_BROXTON(dev_priv)) {
> -		int idx = bxt_power_sequencer_idx(intel_dp);
> +	if (IS_BROXTON(dev_priv))
> +		pps_idx = bxt_power_sequencer_idx(intel_dp);
> +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		pps_idx = vlv_power_sequencer_pipe(intel_dp);
>  
> -		regs->pp_ctrl = BXT_PP_CONTROL(idx);
> -		regs->pp_stat = BXT_PP_STATUS(idx);
> -		regs->pp_on = BXT_PP_ON_DELAYS(idx);
> -		regs->pp_off = BXT_PP_OFF_DELAYS(idx);
> -	} else if (HAS_PCH_SPLIT(dev_priv)) {
> -		regs->pp_ctrl = PCH_PP_CONTROL;
> -		regs->pp_stat = PCH_PP_STATUS;
> -		regs->pp_on = PCH_PP_ON_DELAYS;
> -		regs->pp_off = PCH_PP_OFF_DELAYS;
> -		regs->pp_div = PCH_PP_DIVISOR;
> -	} else {
> -		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> -
> -		regs->pp_ctrl = VLV_PIPE_PP_CONTROL(pipe);
> -		regs->pp_stat = VLV_PIPE_PP_STATUS(pipe);
> -		regs->pp_on = VLV_PIPE_PP_ON_DELAYS(pipe);
> -		regs->pp_off = VLV_PIPE_PP_OFF_DELAYS(pipe);
> -		regs->pp_div = VLV_PIPE_PP_DIVISOR(pipe);
> -	}
> +	regs->pp_ctrl = PP_CONTROL(pps_idx);
> +	regs->pp_stat = PP_STATUS(pps_idx);
> +	regs->pp_on = PP_ON_DELAYS(pps_idx);
> +	regs->pp_off = PP_OFF_DELAYS(pps_idx);
> +	if (!IS_BROXTON(dev_priv))
> +		regs->pp_div = PP_DIVISOR(pps_idx);
>  }
>  
>  static i915_reg_t
> @@ -651,8 +642,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
>  		i915_reg_t pp_ctrl_reg, pp_div_reg;
>  		u32 pp_div;
>  
> -		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> -		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> +		pp_ctrl_reg = PP_CONTROL(pipe);
> +		pp_div_reg  = PP_DIVISOR(pipe);
>  		pp_div = I915_READ(pp_div_reg);
>  		pp_div &= PP_REFERENCE_DIVIDER_MASK;
>  
> @@ -2729,7 +2720,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>  	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
>  	enum pipe pipe = intel_dp->pps_pipe;
> -	i915_reg_t pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
> +	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
>  
>  	edp_panel_vdd_off_sync(intel_dp);
>  
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 4955047..413e729 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -217,21 +217,12 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
>  	struct intel_connector *intel_connector =
>  		&lvds_encoder->attached_connector->base;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> -	i915_reg_t ctl_reg, stat_reg;
> -
> -	if (HAS_PCH_SPLIT(dev)) {
> -		ctl_reg = PCH_PP_CONTROL;
> -		stat_reg = PCH_PP_STATUS;
> -	} else {
> -		ctl_reg = PP_CONTROL;
> -		stat_reg = PP_STATUS;
> -	}
>  
>  	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
>  
> -	I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
> +	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | POWER_TARGET_ON);
>  	POSTING_READ(lvds_encoder->reg);
> -	if (intel_wait_for_register(dev_priv, stat_reg, PP_ON, PP_ON, 1000))
> +	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 1000))
>  		DRM_ERROR("timed out waiting for panel to power on\n");
>  
>  	intel_panel_enable_backlight(intel_connector);
> @@ -242,18 +233,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
>  	struct drm_device *dev = encoder->base.dev;
>  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> -	i915_reg_t ctl_reg, stat_reg;
>  
> -	if (HAS_PCH_SPLIT(dev)) {
> -		ctl_reg = PCH_PP_CONTROL;
> -		stat_reg = PCH_PP_STATUS;
> -	} else {
> -		ctl_reg = PP_CONTROL;
> -		stat_reg = PP_STATUS;
> -	}
> -
> -	I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
> -	if (intel_wait_for_register(dev_priv, stat_reg, PP_ON, 0, 1000))
> +	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~POWER_TARGET_ON);
> +	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, 0, 1000))
>  		DRM_ERROR("timed out waiting for panel to power off\n");
>  
>  	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
> @@ -904,13 +886,10 @@ void intel_lvds_init(struct drm_device *dev)
>  	 * Unlock registers and just leave them unlocked. Do this before
>  	 * checking quirk lists to avoid bogus WARNINGs.
>  	 */
> -	if (HAS_PCH_SPLIT(dev)) {
> -		I915_WRITE(PCH_PP_CONTROL,
> -			   I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
> -	} else if (INTEL_INFO(dev_priv)->gen < 5) {
> -		I915_WRITE(PP_CONTROL,
> -			   I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
> -	}
> +	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
> +		I915_WRITE(PP_CONTROL(0),
> +			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
> +
>  	if (!intel_lvds_supported(dev))
>  		return;
>  
> @@ -945,12 +924,12 @@ void intel_lvds_init(struct drm_device *dev)
>  
>  	 /* Set the Panel Power On/Off timings if uninitialized. */
>  	if (INTEL_INFO(dev_priv)->gen < 5 &&
> -	    I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) {
> +	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
>  		/* Set T2 to 40ms and T5 to 200ms */
> -		I915_WRITE(PP_ON_DELAYS, 0x019007d0);
> +		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
>  
>  		/* Set T3 to 35ms and Tx to 200ms */
> -		I915_WRITE(PP_OFF_DELAYS, 0x015e07d0);
> +		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
>  
>  		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
>  	}
> -- 
> 2.5.0

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 2/6] drm/i915: Merge TARGET_POWER_ON and PANEL_POWER_ON flag definitions
  2016-08-09 11:34 ` [PATCH 2/6] drm/i915: Merge TARGET_POWER_ON and PANEL_POWER_ON flag definitions Imre Deak
@ 2016-08-09 17:51   ` Ville Syrjälä
  0 siblings, 0 replies; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 17:51 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 02:34:08PM +0300, Imre Deak wrote:
> These two flags mean the same thing, so remove the duplication.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/i915_reg.h   | 1 -
>  drivers/gpu/drm/i915/intel_dp.c   | 6 +++---
>  drivers/gpu/drm/i915/intel_lvds.c | 4 ++--
>  3 files changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index b65fe50..889508f 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3707,7 +3707,6 @@ enum {
>  #define  PANEL_POWER_RESET		(1 << 1)
>  #define  PANEL_POWER_OFF		(0 << 0)
>  #define  PANEL_POWER_ON			(1 << 0)
> -#define  POWER_TARGET_ON		(1 << 0)
>  
>  #define _PP_ON_DELAYS			0x61208
>  #define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index a5cef91..4796ad7 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1950,7 +1950,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
>  	DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
>  	I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
>  
> -	if ((pp & POWER_TARGET_ON) == 0)
> +	if ((pp & PANEL_POWER_ON) == 0)
>  		intel_dp->panel_power_off_time = ktime_get_boottime();
>  
>  	power_domain = intel_display_port_aux_power_domain(intel_encoder);
> @@ -2037,7 +2037,7 @@ static void edp_panel_on(struct intel_dp *intel_dp)
>  		POSTING_READ(pp_ctrl_reg);
>  	}
>  
> -	pp |= POWER_TARGET_ON;
> +	pp |= PANEL_POWER_ON;
>  	if (!IS_GEN5(dev))
>  		pp |= PANEL_POWER_RESET;
>  
> @@ -2089,7 +2089,7 @@ static void edp_panel_off(struct intel_dp *intel_dp)
>  	pp = ironlake_get_pp_control(intel_dp);
>  	/* We need to switch off panel power _and_ force vdd, for otherwise some
>  	 * panels get very unhappy and cease to work. */
> -	pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
> +	pp &= ~(PANEL_POWER_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
>  		EDP_BLC_ENABLE);
>  
>  	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 413e729..c5739fc 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -220,7 +220,7 @@ static void intel_enable_lvds(struct intel_encoder *encoder)
>  
>  	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
>  
> -	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | POWER_TARGET_ON);
> +	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | PANEL_POWER_ON);
>  	POSTING_READ(lvds_encoder->reg);
>  	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 1000))
>  		DRM_ERROR("timed out waiting for panel to power on\n");
> @@ -234,7 +234,7 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
>  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  
> -	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~POWER_TARGET_ON);
> +	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~PANEL_POWER_ON);
>  	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, 0, 1000))
>  		DRM_ERROR("timed out waiting for panel to power off\n");
>  
> -- 
> 2.5.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 6/6] drm/i915: Remove LVDS and PPS suspend time save/restore
  2016-08-09 11:34 ` [PATCH 6/6] drm/i915: Remove LVDS and PPS suspend time save/restore Imre Deak
@ 2016-08-09 18:44   ` Ville Syrjälä
  0 siblings, 0 replies; 30+ messages in thread
From: Ville Syrjälä @ 2016-08-09 18:44 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Aug 09, 2016 at 02:34:12PM +0300, Imre Deak wrote:
> In the preceeding patches we made sure that:
> - the LVDS encoder takes care of reiniting both the LVDS register
> and its PPS
> - the eDP encoder takes care of reiniting its PPS
> - the PPS register unlocking workaround is applied explicitly whenever
> the PPS context is lost
> 
> Based on the above we can safely remove the opaque LVDS and PPS save /
> restore from generic code.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h     |  7 -------
>  drivers/gpu/drm/i915/i915_suspend.c | 31 -------------------------------
>  2 files changed, 38 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index fddaec6..a83c0a6 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1061,13 +1061,6 @@ struct intel_gmbus {
>  
>  struct i915_suspend_saved_registers {
>  	u32 saveDSPARB;
> -	u32 saveLVDS;
> -	u32 savePP_ON_DELAYS;
> -	u32 savePP_OFF_DELAYS;
> -	u32 savePP_ON;
> -	u32 savePP_OFF;
> -	u32 savePP_CONTROL;
> -	u32 savePP_DIVISOR;

Sweet.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

>  	u32 saveFBC_CONTROL;
>  	u32 saveCACHE_MODE_0;
>  	u32 saveMI_ARB_STATE;
> diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
> index c826b69..4f27277 100644
> --- a/drivers/gpu/drm/i915/i915_suspend.c
> +++ b/drivers/gpu/drm/i915/i915_suspend.c
> @@ -37,20 +37,6 @@ static void i915_save_display(struct drm_device *dev)
>  	if (INTEL_INFO(dev)->gen <= 4)
>  		dev_priv->regfile.saveDSPARB = I915_READ(DSPARB);
>  
> -	/* LVDS state */
> -	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
> -		dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
> -	else if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
> -		dev_priv->regfile.saveLVDS = I915_READ(LVDS);
> -
> -	/* Panel power sequencer */
> -	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
> -		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL(0));
> -		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS(0));
> -		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS(0));
> -		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR(0));
> -	}
> -
>  	/* save FBC interval */
>  	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev))
>  		dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
> @@ -59,28 +45,11 @@ static void i915_save_display(struct drm_device *dev)
>  static void i915_restore_display(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> -	u32 mask = 0xffffffff;
>  
>  	/* Display arbitration */
>  	if (INTEL_INFO(dev)->gen <= 4)
>  		I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB);
>  
> -	mask = ~LVDS_PORT_EN;
> -
> -	/* LVDS state */
> -	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
> -		I915_WRITE(PCH_LVDS, dev_priv->regfile.saveLVDS & mask);
> -	else if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
> -		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);
> -
> -	/* Panel power sequencer */
> -	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
> -		I915_WRITE(PP_ON_DELAYS(0), dev_priv->regfile.savePP_ON_DELAYS);
> -		I915_WRITE(PP_OFF_DELAYS(0), dev_priv->regfile.savePP_OFF_DELAYS);
> -		I915_WRITE(PP_DIVISOR(0), dev_priv->regfile.savePP_DIVISOR);
> -		I915_WRITE(PP_CONTROL(0), dev_priv->regfile.savePP_CONTROL);
> -	}
> -
>  	/* only restore FBC info on the platform that supports FBC*/
>  	intel_fbc_global_disable(dev_priv);
>  
> -- 
> 2.5.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v3 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
  2016-08-09 17:46     ` Ville Syrjälä
@ 2016-08-09 18:59     ` Imre Deak
  1 sibling, 0 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 18:59 UTC (permalink / raw)
  To: intel-gfx

Atm the LVDS encoder depends on the PPS HW context being saved/restored
from generic suspend/resume code. Since the PPS is specific to the LVDS
and eDP encoders a cleaner way is to reinitialize it during encoder
enabling, so do this here for LVDS. Follow-up patches will init the PPS
for the eDP encoder similarly and remove the suspend/resume time save /
restore.

v2:
- Apply BSpec +1 offset and use DIV_ROUND_UP() when programming the
power cycle delay. (Ville)
v3: (Ville)
- Fix +1 vs. round-up order.
- s/reset_on_powerdown/powerdown_on_reset/

Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h   |   1 +
 drivers/gpu/drm/i915/intel_lvds.c | 114 +++++++++++++++++++++++++++++++++-----
 2 files changed, 102 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 889508f..da82744 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3710,6 +3710,7 @@ enum {
 
 #define _PP_ON_DELAYS			0x61208
 #define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
+#define  PANEL_PORT_SELECT_SHIFT	30
 #define  PANEL_PORT_SELECT_MASK		(3 << 30)
 #define  PANEL_PORT_SELECT_LVDS		(0 << 30)
 #define  PANEL_PORT_SELECT_DPA		(1 << 30)
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index c5739fc..e79fae4 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -48,6 +48,20 @@ struct intel_lvds_connector {
 	struct notifier_block lid_notifier;
 };
 
+struct intel_lvds_pps {
+	/* 100us units */
+	int t1_t2;
+	int t3;
+	int t4;
+	int t5;
+	int tx;
+
+	int divider;
+
+	int port;
+	bool powerdown_on_reset;
+};
+
 struct intel_lvds_encoder {
 	struct intel_encoder base;
 
@@ -55,6 +69,9 @@ struct intel_lvds_encoder {
 	i915_reg_t reg;
 	u32 a3_power;
 
+	struct intel_lvds_pps init_pps;
+	u32 init_lvds_val;
+
 	struct intel_lvds_connector *attached_connector;
 };
 
@@ -136,6 +153,83 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
 	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
 }
 
+static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
+					struct intel_lvds_pps *pps)
+{
+	u32 val;
+
+	pps->powerdown_on_reset = I915_READ(PP_CONTROL(0)) & PANEL_POWER_RESET;
+
+	val = I915_READ(PP_ON_DELAYS(0));
+	pps->port = (val & PANEL_PORT_SELECT_MASK) >>
+		    PANEL_PORT_SELECT_SHIFT;
+	pps->t1_t2 = (val & PANEL_POWER_UP_DELAY_MASK) >>
+		     PANEL_POWER_UP_DELAY_SHIFT;
+	pps->t5 = (val & PANEL_LIGHT_ON_DELAY_MASK) >>
+		  PANEL_LIGHT_ON_DELAY_SHIFT;
+
+	val = I915_READ(PP_OFF_DELAYS(0));
+	pps->t3 = (val & PANEL_POWER_DOWN_DELAY_MASK) >>
+		  PANEL_POWER_DOWN_DELAY_SHIFT;
+	pps->tx = (val & PANEL_LIGHT_OFF_DELAY_MASK) >>
+		  PANEL_LIGHT_OFF_DELAY_SHIFT;
+
+	val = I915_READ(PP_DIVISOR(0));
+	pps->divider = (val & PP_REFERENCE_DIVIDER_MASK) >>
+		       PP_REFERENCE_DIVIDER_SHIFT;
+	val = (val & PANEL_POWER_CYCLE_DELAY_MASK) >>
+	      PANEL_POWER_CYCLE_DELAY_SHIFT;
+	/*
+	 * Remove the BSpec specified +1 (100ms) offset that accounts for a
+	 * too short power-cycle delay due to the asynchronous programming of
+	 * the register.
+	 */
+	if (val)
+		val--;
+	/* Convert from 100ms to 100us units */
+	pps->t4 = val * 1000;
+
+	if (INTEL_INFO(dev_priv)->gen <= 4 &&
+	    pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
+		DRM_DEBUG_KMS("Panel power timings uninitialized, "
+			      "setting defaults\n");
+		/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
+		pps->t1_t2 = 40 * 10;
+		pps->t5 = 200 * 10;
+		/* Set T3 to 35ms and Tx to 200ms in 100 usec units */
+		pps->t3 = 35 * 10;
+		pps->tx = 200 * 10;
+	}
+
+	DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
+			 "divider %d port %d powerdown_on_reset %d\n",
+			 pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
+			 pps->divider, pps->port, pps->powerdown_on_reset);
+}
+
+static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
+				   struct intel_lvds_pps *pps)
+{
+	u32 val;
+
+	val = I915_READ(PP_CONTROL(0));
+	WARN_ON((val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);
+	if (pps->powerdown_on_reset)
+		val |= PANEL_POWER_RESET;
+	I915_WRITE(PP_CONTROL(0), val);
+
+	I915_WRITE(PP_ON_DELAYS(0), (pps->port << PANEL_PORT_SELECT_SHIFT) |
+				    (pps->t1_t2 << PANEL_POWER_UP_DELAY_SHIFT) |
+				    (pps->t5 << PANEL_LIGHT_ON_DELAY_SHIFT));
+	I915_WRITE(PP_OFF_DELAYS(0), (pps->t3 << PANEL_POWER_DOWN_DELAY_SHIFT) |
+				     (pps->tx << PANEL_LIGHT_OFF_DELAY_SHIFT));
+
+	val = pps->divider << PP_REFERENCE_DIVIDER_SHIFT;
+	val |= (DIV_ROUND_UP(pps->t4, 1000) + 1) <<
+	       PANEL_POWER_CYCLE_DELAY_SHIFT;
+	I915_WRITE(PP_DIVISOR(0), val);
+}
+
 static void intel_pre_enable_lvds(struct intel_encoder *encoder)
 {
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
@@ -154,7 +248,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder)
 		assert_pll_disabled(dev_priv, pipe);
 	}
 
-	temp = I915_READ(lvds_encoder->reg);
+	intel_lvds_pps_init_hw(dev_priv, &lvds_encoder->init_pps);
+
+	temp = lvds_encoder->init_lvds_val;
 	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
 
 	if (HAS_PCH_CPT(dev)) {
@@ -922,18 +1018,6 @@ void intel_lvds_init(struct drm_device *dev)
 		DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
 	}
 
-	 /* Set the Panel Power On/Off timings if uninitialized. */
-	if (INTEL_INFO(dev_priv)->gen < 5 &&
-	    I915_READ(PP_ON_DELAYS(0)) == 0 && I915_READ(PP_OFF_DELAYS(0)) == 0) {
-		/* Set T2 to 40ms and T5 to 200ms */
-		I915_WRITE(PP_ON_DELAYS(0), 0x019007d0);
-
-		/* Set T3 to 35ms and Tx to 200ms */
-		I915_WRITE(PP_OFF_DELAYS(0), 0x015e07d0);
-
-		DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
-	}
-
 	lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
 	if (!lvds_encoder)
 		return;
@@ -999,6 +1083,10 @@ void intel_lvds_init(struct drm_device *dev)
 				      dev->mode_config.scaling_mode_property,
 				      DRM_MODE_SCALE_ASPECT);
 	intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
+
+	intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps);
+	lvds_encoder->init_lvds_val = lvds;
+
 	/*
 	 * LVDS discovery:
 	 * 1) check for EDID on DDC
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v3 5/6] drm/i915: Apply the PPS register unlock workaround more consistently
  2016-08-09 17:21   ` [PATCH v2 " Imre Deak
  2016-08-09 17:46     ` Ville Syrjälä
@ 2016-08-09 18:59     ` Imre Deak
  1 sibling, 0 replies; 30+ messages in thread
From: Imre Deak @ 2016-08-09 18:59 UTC (permalink / raw)
  To: intel-gfx

Atm, we apply this workaround somewhat inconsistently at the following
points: driver loading, LVDS init, eDP PPS init, system resume. As this
workaround also affects registers other than PPS (timing, PLL) a more
consistent way is to apply it early after the PPS HW context is known to
be lost: driver loading, system resume and on VLV/CHV/BXT when turning
on power domains.

This is needed by the next patch that removes saving/restoring of the
PP_CONTROL register.

This also removes the incorrect programming of the workaround on HSW+
PCH platforms which don't have the register locking mechanism.

v2: (Ville)
- Don't apply the workaround on BXT.
- Simplify platform checks using HAS_DDI().
v3:
- Move the call of intel_pps_unlock_regs_wa() to the more
  logical vlv_display_power_well_init() (also fixing CHV) (Ville).

Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c         |  1 +
 drivers/gpu/drm/i915/intel_display.c    | 26 ++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_dp.c         |  3 ++-
 drivers/gpu/drm/i915/intel_drv.h        |  1 +
 drivers/gpu/drm/i915/intel_lvds.c       |  8 --------
 drivers/gpu/drm/i915/intel_runtime_pm.c |  4 ++++
 6 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 8cfc264..0fcd1c0 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1560,6 +1560,7 @@ static int i915_drm_resume(struct drm_device *dev)
 	i915_gem_resume(dev);
 
 	i915_restore_state(dev);
+	intel_pps_unlock_regs_wa(dev_priv);
 	intel_opregion_setup(dev_priv);
 
 	intel_init_pch_refclk(dev);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3d5fd06..bcbf277 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14635,6 +14635,30 @@ static bool intel_crt_present(struct drm_device *dev)
 	return true;
 }
 
+void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
+{
+	int pps_num;
+	int pps_idx;
+
+	if (HAS_DDI(dev_priv))
+		return;
+	/*
+	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
+	 * everywhere where registers can be write protected.
+	 */
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		pps_num = 2;
+	else
+		pps_num = 1;
+
+	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
+		u32 val = I915_READ(PP_CONTROL(pps_idx));
+
+		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
+		I915_WRITE(PP_CONTROL(pps_idx), val);
+	}
+}
+
 static void intel_pps_init(struct drm_i915_private *dev_priv)
 {
 	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(dev_priv))
@@ -14643,6 +14667,8 @@ static void intel_pps_init(struct drm_i915_private *dev_priv)
 		dev_priv->pps_mmio_base = VLV_PPS_BASE;
 	else
 		dev_priv->pps_mmio_base = PPS_BASE;
+
+	intel_pps_unlock_regs_wa(dev_priv);
 }
 
 static void intel_setup_outputs(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 2ef7b14..3d3d3fb 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1829,7 +1829,8 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
 	control = I915_READ(_pp_ctrl_reg(intel_dp));
-	if (!IS_BROXTON(dev)) {
+	if (WARN_ON(!HAS_DDI(dev_priv) &&
+		     (control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
 		control &= ~PANEL_UNLOCK_MASK;
 		control |= PANEL_UNLOCK_REGS;
 	}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c29a429..cbce786 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1159,6 +1159,7 @@ void intel_mark_busy(struct drm_i915_private *dev_priv);
 void intel_mark_idle(struct drm_i915_private *dev_priv);
 void intel_crtc_restore_mode(struct drm_crtc *crtc);
 int intel_display_suspend(struct drm_device *dev);
+void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
 void intel_encoder_destroy(struct drm_encoder *encoder);
 int intel_connector_init(struct intel_connector *);
 struct intel_connector *intel_connector_alloc(void);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index e79fae4..668eabb 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -978,14 +978,6 @@ void intel_lvds_init(struct drm_device *dev)
 	int pipe;
 	u8 pin;
 
-	/*
-	 * Unlock registers and just leave them unlocked. Do this before
-	 * checking quirk lists to avoid bogus WARNINGs.
-	 */
-	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4)
-		I915_WRITE(PP_CONTROL(0),
-			   I915_READ(PP_CONTROL(0)) | PANEL_UNLOCK_REGS);
-
 	if (!intel_lvds_supported(dev))
 		return;
 
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 1c603bb..d659d6f 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -592,6 +592,8 @@ void bxt_disable_dc9(struct drm_i915_private *dev_priv)
 	DRM_DEBUG_KMS("Disabling DC9\n");
 
 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+	intel_pps_unlock_regs_wa(dev_priv);
 }
 
 static void assert_csr_loaded(struct drm_i915_private *dev_priv)
@@ -1121,6 +1123,8 @@ static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
 	}
 
 	i915_redisable_vga_power_on(&dev_priv->drm);
+
+	intel_pps_unlock_regs_wa(dev_priv);
 }
 
 static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
-- 
2.5.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✗ Ro.CI.BAT: failure for drm/i915: Clean up LVDS/PPS macros, suspend/resume logic (rev7)
  2016-08-09 11:34 [PATCH 0/6] drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Imre Deak
                   ` (6 preceding siblings ...)
  2016-08-09 12:05 ` ✓ Ro.CI.BAT: success for drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Patchwork
@ 2016-08-10  9:35 ` Patchwork
  7 siblings, 0 replies; 30+ messages in thread
From: Patchwork @ 2016-08-10  9:35 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Clean up LVDS/PPS macros, suspend/resume logic (rev7)
URL   : https://patchwork.freedesktop.org/series/10838/
State : failure

== Summary ==

Applying: drm/i915: Apply the PPS register unlock workaround more consistently
fatal: sha1 information is lacking or useless (drivers/gpu/drm/i915/intel_dp.c).
error: could not build fake ancestor
Patch failed at 0001 drm/i915: Apply the PPS register unlock workaround more consistently
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

end of thread, other threads:[~2016-08-10  9:35 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-09 11:34 [PATCH 0/6] drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Imre Deak
2016-08-09 11:34 ` [PATCH 1/6] drm/i915: Merge the PPS register definitions Imre Deak
2016-08-09 11:53   ` Ville Syrjälä
2016-08-09 13:24     ` Imre Deak
2016-08-09 17:21   ` [PATCH v2 " Imre Deak
2016-08-09 17:50     ` Ville Syrjälä
2016-08-09 11:34 ` [PATCH 2/6] drm/i915: Merge TARGET_POWER_ON and PANEL_POWER_ON flag definitions Imre Deak
2016-08-09 17:51   ` Ville Syrjälä
2016-08-09 11:34 ` [PATCH 3/6] drm/i915/lvds: Restore initial HW state during encoder enabling Imre Deak
2016-08-09 12:48   ` Ville Syrjälä
2016-08-09 14:40     ` Imre Deak
2016-08-09 14:55       ` Ville Syrjälä
2016-08-09 17:21   ` [PATCH v2 " Imre Deak
2016-08-09 17:46     ` Ville Syrjälä
2016-08-09 18:59     ` [PATCH v3 " Imre Deak
2016-08-09 11:34 ` [PATCH 4/6] drm/i915/dp: Restore PPS HW state from the encoder resume hook Imre Deak
2016-08-09 12:52   ` Ville Syrjälä
2016-08-09 15:15     ` Imre Deak
2016-08-09 17:21   ` [PATCH v2 " Imre Deak
2016-08-09 17:49     ` Ville Syrjälä
2016-08-09 11:34 ` [PATCH 5/6] drm/i915: Apply the PPS register unlock workaround more consistently Imre Deak
2016-08-09 13:01   ` Ville Syrjälä
2016-08-09 15:17     ` Imre Deak
2016-08-09 17:21   ` [PATCH v2 " Imre Deak
2016-08-09 17:46     ` Ville Syrjälä
2016-08-09 18:59     ` [PATCH v3 " Imre Deak
2016-08-09 11:34 ` [PATCH 6/6] drm/i915: Remove LVDS and PPS suspend time save/restore Imre Deak
2016-08-09 18:44   ` Ville Syrjälä
2016-08-09 12:05 ` ✓ Ro.CI.BAT: success for drm/i915: Clean up LVDS/PPS macros, suspend/resume logic Patchwork
2016-08-10  9:35 ` ✗ Ro.CI.BAT: failure for drm/i915: Clean up LVDS/PPS macros, suspend/resume logic (rev7) Patchwork

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.