* [PATCH 0/4] drm/i915: CHV display PHY magic
@ 2015-02-11 14:59 ville.syrjala
2015-02-11 14:59 ` [PATCH 1/4] drm/i915: Implement chv display PHY lane stagger setup ville.syrjala
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: ville.syrjala @ 2015-02-11 14:59 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Here's the second part of my CHV display fixes pile. There are some really
weird things going on with the PHY, and this series includes whatever
workaround I managed to invent to overcome those issues.
The lane stagger setup I just gleaned from one of the docs, although I'm
not sure the magic numbers are even correct anymore. So not sure if it
helps with anything really. And the cmnlane glue revert is just to save a
bit more power when only one PHY is needed.
Ville Syrjälä (4):
drm/i915: Implement chv display PHY lane stagger setup
drm/i915: Add a hack to fix link training errors on pipe A+port B on
CHV
Revert "drm/i915: Hack to tie both common lanes together on chv"
drm/i915: Work around DISPLAY_PHY_CONTROL register corruption on CHV
drivers/gpu/drm/i915/i915_drv.h | 2 ++
drivers/gpu/drm/i915/i915_reg.h | 26 ++++++++++++++-
drivers/gpu/drm/i915/intel_dp.c | 58 +++++++++++++++++++++++++++++++--
drivers/gpu/drm/i915/intel_hdmi.c | 35 ++++++++++++++++++--
drivers/gpu/drm/i915/intel_runtime_pm.c | 38 ++++++++++++---------
5 files changed, 138 insertions(+), 21 deletions(-)
--
2.0.5
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/4] drm/i915: Implement chv display PHY lane stagger setup
2015-02-11 14:59 [PATCH 0/4] drm/i915: CHV display PHY magic ville.syrjala
@ 2015-02-11 14:59 ` ville.syrjala
2015-02-11 14:59 ` [PATCH 2/4] drm/i915: Add a hack to fix link training errors on pipe A+port B on CHV ville.syrjala
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: ville.syrjala @ 2015-02-11 14:59 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Set up the chv display PHY lane stagger registers according to
"Programming Guide for 1273 CHV eDP/DP/HDMI Display PHY" v1.04
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/i915_reg.h | 13 +++++++++++++
drivers/gpu/drm/i915/intel_dp.c | 35 +++++++++++++++++++++++++++++++++--
drivers/gpu/drm/i915/intel_hdmi.c | 35 +++++++++++++++++++++++++++++++++--
3 files changed, 79 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2196e57..4728dc2 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -933,6 +933,7 @@ enum skl_disp_power_wells {
#define _VLV_PCS_DW11_CH0 0x822c
#define _VLV_PCS_DW11_CH1 0x842c
+#define DPIO_TX2_STAGGER_MASK(x) ((x)<<24)
#define DPIO_LANEDESKEW_STRAP_OVRD (1<<3)
#define DPIO_LEFT_TXFIFO_RST_MASTER (1<<1)
#define DPIO_RIGHT_TXFIFO_RST_MASTER (1<<0)
@@ -945,8 +946,20 @@ enum skl_disp_power_wells {
#define VLV_PCS01_DW11(ch) _PORT(ch, _VLV_PCS01_DW11_CH0, _VLV_PCS01_DW11_CH1)
#define VLV_PCS23_DW11(ch) _PORT(ch, _VLV_PCS23_DW11_CH0, _VLV_PCS23_DW11_CH1)
+#define _VLV_PCS01_DW12_CH0 0x0230
+#define _VLV_PCS23_DW12_CH0 0x0430
+#define _VLV_PCS01_DW12_CH1 0x2630
+#define _VLV_PCS23_DW12_CH1 0x2830
+#define VLV_PCS01_DW12(ch) _PORT(ch, _VLV_PCS01_DW12_CH0, _VLV_PCS01_DW12_CH1)
+#define VLV_PCS23_DW12(ch) _PORT(ch, _VLV_PCS23_DW12_CH0, _VLV_PCS23_DW12_CH1)
+
#define _VLV_PCS_DW12_CH0 0x8230
#define _VLV_PCS_DW12_CH1 0x8430
+#define DPIO_TX2_STAGGER_MULT(x) ((x)<<20)
+#define DPIO_TX1_STAGGER_MULT(x) ((x)<<16)
+#define DPIO_TX1_STAGGER_MASK(x) ((x)<<8)
+#define DPIO_LANESTAGGER_STRAP_OVRD (1<<6)
+#define DPIO_LANESTAGGER_STRAP(x) ((x)<<0)
#define VLV_PCS_DW12(ch) _PORT(ch, _VLV_PCS_DW12_CH0, _VLV_PCS_DW12_CH1)
#define _VLV_PCS_DW14_CH0 0x8238
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index eea9e36..43129ed 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2524,7 +2524,7 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
to_intel_crtc(encoder->base.crtc);
enum dpio_channel ch = vlv_dport_to_channel(dport);
int pipe = intel_crtc->pipe;
- int data, i;
+ int data, i, stagger;
u32 val;
mutex_lock(&dev_priv->dpio_lock);
@@ -2569,7 +2569,38 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
}
/* Data lane stagger programming */
- /* FIXME: Fix up value only after power analysis */
+ if (intel_crtc->config->port_clock > 270000)
+ stagger = 0x18;
+ else if (intel_crtc->config->port_clock > 135000)
+ stagger = 0xd;
+ else if (intel_crtc->config->port_clock > 67500)
+ stagger = 0x7;
+ else if (intel_crtc->config->port_clock > 33750)
+ stagger = 0x4;
+ else
+ stagger = 0x2;
+
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch));
+ val |= DPIO_TX2_STAGGER_MASK(0x1f);
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val);
+
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
+ val |= DPIO_TX2_STAGGER_MASK(0x1f);
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
+
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW12(ch),
+ DPIO_LANESTAGGER_STRAP(stagger) |
+ DPIO_LANESTAGGER_STRAP_OVRD |
+ DPIO_TX1_STAGGER_MASK(0x1f) |
+ DPIO_TX1_STAGGER_MULT(6) |
+ DPIO_TX2_STAGGER_MULT(0));
+
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch),
+ DPIO_LANESTAGGER_STRAP(stagger) |
+ DPIO_LANESTAGGER_STRAP_OVRD |
+ DPIO_TX1_STAGGER_MASK(0x1f) |
+ DPIO_TX1_STAGGER_MULT(7) |
+ DPIO_TX2_STAGGER_MULT(5));
mutex_unlock(&dev_priv->dpio_lock);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 995c5b2..94da7fe 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1471,7 +1471,7 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
&intel_crtc->config->base.adjusted_mode;
enum dpio_channel ch = vlv_dport_to_channel(dport);
int pipe = intel_crtc->pipe;
- int data, i;
+ int data, i, stagger;
u32 val;
mutex_lock(&dev_priv->dpio_lock);
@@ -1516,7 +1516,38 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
}
/* Data lane stagger programming */
- /* FIXME: Fix up value only after power analysis */
+ if (intel_crtc->config->port_clock > 270000)
+ stagger = 0x18;
+ else if (intel_crtc->config->port_clock > 135000)
+ stagger = 0xd;
+ else if (intel_crtc->config->port_clock > 67500)
+ stagger = 0x7;
+ else if (intel_crtc->config->port_clock > 33750)
+ stagger = 0x4;
+ else
+ stagger = 0x2;
+
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch));
+ val |= DPIO_TX2_STAGGER_MASK(0x1f);
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val);
+
+ val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
+ val |= DPIO_TX2_STAGGER_MASK(0x1f);
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
+
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW12(ch),
+ DPIO_LANESTAGGER_STRAP(stagger) |
+ DPIO_LANESTAGGER_STRAP_OVRD |
+ DPIO_TX1_STAGGER_MASK(0x1f) |
+ DPIO_TX1_STAGGER_MULT(6) |
+ DPIO_TX2_STAGGER_MULT(0));
+
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch),
+ DPIO_LANESTAGGER_STRAP(stagger) |
+ DPIO_LANESTAGGER_STRAP_OVRD |
+ DPIO_TX1_STAGGER_MASK(0x1f) |
+ DPIO_TX1_STAGGER_MULT(7) |
+ DPIO_TX2_STAGGER_MULT(5));
/* Clear calc init */
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
--
2.0.5
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/4] drm/i915: Add a hack to fix link training errors on pipe A+port B on CHV
2015-02-11 14:59 [PATCH 0/4] drm/i915: CHV display PHY magic ville.syrjala
2015-02-11 14:59 ` [PATCH 1/4] drm/i915: Implement chv display PHY lane stagger setup ville.syrjala
@ 2015-02-11 14:59 ` ville.syrjala
2015-02-12 18:52 ` Ville Syrjälä
2015-02-11 14:59 ` [PATCH 3/4] Revert "drm/i915: Hack to tie both common lanes together on chv" ville.syrjala
2015-02-11 14:59 ` [PATCH 4/4] drm/i915: Work around DISPLAY_PHY_CONTROL register corruption on CHV ville.syrjala
3 siblings, 1 reply; 7+ messages in thread
From: ville.syrjala @ 2015-02-11 14:59 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
For some reason link training fails when port B is being driven by pipe
A, and was previously driven by port B or the common lane was previously
powered off.
After staring at some register dumps I noticed some oddness with the DCC
calibration status bits, and after some experimentation I came up with a
workaround that just involves toggling the DCC calibration bit for the
data lanes in chv_pre_enable_dp(). I also observed that doing the same
trick for pipe B resulted in a blinking display with pipe B + eDP port C.
So the I've limited the workaround to pipe A only for now, while not
caring which port is used.
Whether there are more factors in this mess is unclear. But for now
this seems to work at least on my BSW RVP.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/i915_reg.h | 8 ++++++++
drivers/gpu/drm/i915/intel_dp.c | 23 +++++++++++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 4728dc2..7546350 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -966,6 +966,14 @@ enum skl_disp_power_wells {
#define _VLV_PCS_DW14_CH1 0x8438
#define VLV_PCS_DW14(ch) _PORT(ch, _VLV_PCS_DW14_CH0, _VLV_PCS_DW14_CH1)
+#define _VLV_PCS_DW17_CH0 0x8244
+#define _VLV_PCS_DW17_CH1 0x8444
+#define DPIO_TX2_DCC_CALIB_DONE (1 << 3)
+#define DPIO_TX1_DCC_CALIB_DONE (1 << 2)
+#define DPIO_TX2_DCC_CALIB_ENABLE (1 << 1)
+#define DPIO_TX1_DCC_CALIB_ENABLE (1 << 0)
+#define VLV_PCS_DW17(ch) _PORT(ch, _VLV_PCS_DW17_CH0, _VLV_PCS_DW17_CH1)
+
#define _VLV_PCS_DW23_CH0 0x825c
#define _VLV_PCS_DW23_CH1 0x845c
#define VLV_PCS_DW23(ch) _PORT(ch, _VLV_PCS_DW23_CH0, _VLV_PCS_DW23_CH1)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 43129ed..2e3fb17 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2602,6 +2602,29 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
DPIO_TX1_STAGGER_MULT(7) |
DPIO_TX2_STAGGER_MULT(5));
+ /*
+ * FIXME: After port B has been driven by pipe B, or
+ * the common lane well has been powered down, trying to drive
+ * port B with pipe A results in a link training failure. Somehow
+ * toggling the DCC calibrate force bits before enabling the port
+ * fixes the problem. Neither pipe B or port C seem to suffer from
+ * this problem, however doing the toggle on pipe B seems to cause
+ * eDP port C to blink when driven by pipe B. So we only do the
+ * toggle for pipe A. It's untested whether pipe C + port D might
+ * also need something like this due to lack of a suitale board.
+ *
+ * Not sure if this is just a symptom of some problem with the PHY
+ * programming we do, but this seems to be a solid workaround so far.
+ *
+ * All of this was tested on a BSW RVP with DP on port B,
+ * eDP on port C, and HDMI on port D.
+ */
+ if (pipe == PIPE_A) {
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW17(ch),
+ DPIO_TX1_DCC_CALIB_ENABLE | DPIO_TX2_DCC_CALIB_ENABLE);
+ vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW17(ch), 0);
+ }
+
mutex_unlock(&dev_priv->dpio_lock);
intel_enable_dp(encoder);
--
2.0.5
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/4] Revert "drm/i915: Hack to tie both common lanes together on chv"
2015-02-11 14:59 [PATCH 0/4] drm/i915: CHV display PHY magic ville.syrjala
2015-02-11 14:59 ` [PATCH 1/4] drm/i915: Implement chv display PHY lane stagger setup ville.syrjala
2015-02-11 14:59 ` [PATCH 2/4] drm/i915: Add a hack to fix link training errors on pipe A+port B on CHV ville.syrjala
@ 2015-02-11 14:59 ` ville.syrjala
2015-02-11 14:59 ` [PATCH 4/4] drm/i915: Work around DISPLAY_PHY_CONTROL register corruption on CHV ville.syrjala
3 siblings, 0 replies; 7+ messages in thread
From: ville.syrjala @ 2015-02-11 14:59 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
With recent hardware/firmware there don't appear to be any glitches
on the other PHY when we toggle the cmnreset for the other PHY. So
detangle the cmnlane power wells from one another and let them be
controlled independently.
This reverts commit 3dd7b97458e8aa2d8985b46622d226fa635071e7.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_runtime_pm.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 6d8e29a..02b6b8f 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -1145,23 +1145,13 @@ static struct i915_power_well chv_power_wells[] = {
#endif
{
.name = "dpio-common-bc",
- /*
- * XXX: cmnreset for one PHY seems to disturb the other.
- * As a workaround keep both powered on at the same
- * time for now.
- */
- .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS | CHV_DPIO_CMN_D_POWER_DOMAINS,
+ .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS,
.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
.ops = &chv_dpio_cmn_power_well_ops,
},
{
.name = "dpio-common-d",
- /*
- * XXX: cmnreset for one PHY seems to disturb the other.
- * As a workaround keep both powered on at the same
- * time for now.
- */
- .domains = CHV_DPIO_CMN_BC_POWER_DOMAINS | CHV_DPIO_CMN_D_POWER_DOMAINS,
+ .domains = CHV_DPIO_CMN_D_POWER_DOMAINS,
.data = PUNIT_POWER_WELL_DPIO_CMN_D,
.ops = &chv_dpio_cmn_power_well_ops,
},
--
2.0.5
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/4] drm/i915: Work around DISPLAY_PHY_CONTROL register corruption on CHV
2015-02-11 14:59 [PATCH 0/4] drm/i915: CHV display PHY magic ville.syrjala
` (2 preceding siblings ...)
2015-02-11 14:59 ` [PATCH 3/4] Revert "drm/i915: Hack to tie both common lanes together on chv" ville.syrjala
@ 2015-02-11 14:59 ` ville.syrjala
2015-02-12 16:00 ` shuang.he
3 siblings, 1 reply; 7+ messages in thread
From: ville.syrjala @ 2015-02-11 14:59 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Sometimes (exactly when is a bit unclear) DISPLAY_PHY_CONTROL appears to
get corrupted. The values I've managed to read from it seem to have some
pattern but vary quite a lot. The corruption doesn't seem to just happen
when the register is accessed, but can also happen spontaneosly during
modeset. When this happens during a modeset things go south and the
display doesn't light up.
I've managed to hit the problemn when toggling HDMI on port D on and
off. When things get corrupted the display doesn't light up, but as soon
as I manually write the correct value to the register the display comes
up.
First I was suspicious that we ourselves accidentally overwrite it with
garbage, but didn't catch anything with the reg_rw tracepoint. Also I
sprinkled check all over the modeset path to see exactly when the
corruption happens, and eg. the read back value was fine just before
intel_dp_set_m(), and corrupted immediately after it. I also made my
check function repair the register value whenever it was wrong, and with
this approach the corruption repeated several times during the modeset
operation, always seeming to trigger in the same exact calls to the
check function, while other calls to the function never caught anything.
So far I've not seen this problem occurring when carefully avoiding all
read accesses to DISPLAY_PHY_CONTROL. Not sure if that's just pure luck
or an actual workaround, but we can hope it works. So let's avoid reading
the register and instead track the desired value of the register in dev_priv.
v2: Read out the power well state to determine initial register value
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 2 ++
drivers/gpu/drm/i915/i915_reg.h | 5 +++-
drivers/gpu/drm/i915/intel_runtime_pm.c | 41 +++++++++++++++++++++++++++++----
3 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b191b12..9a34cdf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1855,6 +1855,8 @@ struct drm_i915_private {
u32 fdi_rx_config;
+ u32 chv_phy_control;
+
u32 suspend_count;
struct i915_suspend_saved_registers regfile;
struct vlv_s0ix_state vlv_s0ix_state;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7546350..4b5900f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1848,7 +1848,10 @@ enum skl_disp_power_wells {
#define DPIO_PHY_STATUS (VLV_DISPLAY_BASE + 0x6240)
#define DPLL_PORTD_READY_MASK (0xf)
#define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100)
-#define PHY_COM_LANE_RESET_DEASSERT(phy) (1 << (phy))
+#define PHY_CH_SU_PSR 0x1
+#define PHY_CH_DEEP_PSR 0x7
+#define PHY_CH_POWER_MODE(mode, phy, ch) ((mode) << (6*(phy)+3*(ch)+2))
+#define PHY_COM_LANE_RESET_DEASSERT(phy) (1 << (phy))
#define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104)
#define PHY_POWERGOOD(phy) (((phy) == DPIO_PHY0) ? (1<<31) : (1<<30))
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 02b6b8f..4d5c7b5 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -630,8 +630,8 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1))
DRM_ERROR("Display PHY %d is not power up\n", phy);
- I915_WRITE(DISPLAY_PHY_CONTROL, I915_READ(DISPLAY_PHY_CONTROL) |
- PHY_COM_LANE_RESET_DEASSERT(phy));
+ dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy);
+ I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
}
static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
@@ -651,8 +651,8 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
assert_pll_disabled(dev_priv, PIPE_C);
}
- I915_WRITE(DISPLAY_PHY_CONTROL, I915_READ(DISPLAY_PHY_CONTROL) &
- ~PHY_COM_LANE_RESET_DEASSERT(phy));
+ dev_priv->chv_phy_control &= ~PHY_COM_LANE_RESET_DEASSERT(phy);
+ I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
vlv_set_power_well(dev_priv, power_well, false);
}
@@ -1355,6 +1355,35 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
mutex_unlock(&power_domains->lock);
}
+static void chv_phy_control_init(struct drm_i915_private *dev_priv)
+{
+ struct i915_power_well *cmn_bc =
+ lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
+ struct i915_power_well *cmn_d =
+ lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D);
+
+ /*
+ * DISPLAY_PHY_CONTROL sometimes gets corrupted if read. The
+ * read may still return the correct value, but somehow it
+ * kick starts a process that will eventually lead to the
+ * corruption. Looks like the corruption usually occurs
+ * during a modeset.
+ *
+ * As a workaround never ever read DISPLAY_PHY_CONTROL, and
+ * instead maintain a shadow copy ourselves. Use the actual
+ * power well state to reconstruct the expected initial
+ * value.
+ */
+ dev_priv->chv_phy_control =
+ PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, 0) |
+ PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, 1) |
+ PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY1, 0);
+ if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc))
+ dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY0);
+ if (cmn_d->ops->is_enabled(dev_priv, cmn_d))
+ dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY1);
+}
+
static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
{
struct i915_power_well *cmn =
@@ -1397,7 +1426,9 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
power_domains->initializing = true;
- if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
+ if (IS_CHERRYVIEW(dev)) {
+ chv_phy_control_init(dev_priv);
+ } else if (IS_VALLEYVIEW(dev)) {
mutex_lock(&power_domains->lock);
vlv_cmnlane_wa(dev_priv);
mutex_unlock(&power_domains->lock);
--
2.0.5
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 4/4] drm/i915: Work around DISPLAY_PHY_CONTROL register corruption on CHV
2015-02-11 14:59 ` [PATCH 4/4] drm/i915: Work around DISPLAY_PHY_CONTROL register corruption on CHV ville.syrjala
@ 2015-02-12 16:00 ` shuang.he
0 siblings, 0 replies; 7+ messages in thread
From: shuang.he @ 2015-02-12 16:00 UTC (permalink / raw)
To: shuang.he, ethan.gao, intel-gfx, ville.syrjala
Tested-By: PRC QA PRTS (Patch Regression Test System Contact: shuang.he@intel.com)
Task id: 5761
-------------------------------------Summary-------------------------------------
Platform Delta drm-intel-nightly Series Applied
PNV 282/282 282/282
ILK 313/313 313/313
SNB 309/323 309/323
IVB 380/380 380/380
BYT 296/296 296/296
HSW -2 425/425 423/425
BDW -1 318/318 317/318
-------------------------------------Detailed-------------------------------------
Platform Test drm-intel-nightly Series Applied
HSW igt_kms_flip_plain-flip-fb-recreate TIMEOUT(1)PASS(1) TIMEOUT(1)
HSW igt_kms_flip_plain-flip-fb-recreate-interruptible TIMEOUT(2)PASS(1) TIMEOUT(1)
*BDW igt_gem_gtt_hog PASS(6) DMESG_WARN(1)PASS(1)
Note: You need to pay more attention to line start with '*'
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/4] drm/i915: Add a hack to fix link training errors on pipe A+port B on CHV
2015-02-11 14:59 ` [PATCH 2/4] drm/i915: Add a hack to fix link training errors on pipe A+port B on CHV ville.syrjala
@ 2015-02-12 18:52 ` Ville Syrjälä
0 siblings, 0 replies; 7+ messages in thread
From: Ville Syrjälä @ 2015-02-12 18:52 UTC (permalink / raw)
To: intel-gfx
On Wed, Feb 11, 2015 at 04:59:48PM +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> For some reason link training fails when port B is being driven by pipe
> A, and was previously driven by port B or the common lane was previously
> powered off.
>
> After staring at some register dumps I noticed some oddness with the DCC
> calibration status bits, and after some experimentation I came up with a
> workaround that just involves toggling the DCC calibration bit for the
> data lanes in chv_pre_enable_dp(). I also observed that doing the same
> trick for pipe B resulted in a blinking display with pipe B + eDP port C.
> So the I've limited the workaround to pipe A only for now, while not
> caring which port is used.
>
> Whether there are more factors in this mess is unclear. But for now
> this seems to work at least on my BSW RVP.
Seems I've hit another one like this with another DP display. This time
it happens with pipe B + port B.
The same DCC trick doesn't help there. In fact it makes it worse by
failing every single time, whereas without applying the trick the
second modeset attempt will succeed. So I'm leaning towards something
in the PHY programming sequence being a bit off.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_reg.h | 8 ++++++++
> drivers/gpu/drm/i915/intel_dp.c | 23 +++++++++++++++++++++++
> 2 files changed, 31 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 4728dc2..7546350 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -966,6 +966,14 @@ enum skl_disp_power_wells {
> #define _VLV_PCS_DW14_CH1 0x8438
> #define VLV_PCS_DW14(ch) _PORT(ch, _VLV_PCS_DW14_CH0, _VLV_PCS_DW14_CH1)
>
> +#define _VLV_PCS_DW17_CH0 0x8244
> +#define _VLV_PCS_DW17_CH1 0x8444
> +#define DPIO_TX2_DCC_CALIB_DONE (1 << 3)
> +#define DPIO_TX1_DCC_CALIB_DONE (1 << 2)
> +#define DPIO_TX2_DCC_CALIB_ENABLE (1 << 1)
> +#define DPIO_TX1_DCC_CALIB_ENABLE (1 << 0)
> +#define VLV_PCS_DW17(ch) _PORT(ch, _VLV_PCS_DW17_CH0, _VLV_PCS_DW17_CH1)
> +
> #define _VLV_PCS_DW23_CH0 0x825c
> #define _VLV_PCS_DW23_CH1 0x845c
> #define VLV_PCS_DW23(ch) _PORT(ch, _VLV_PCS_DW23_CH0, _VLV_PCS_DW23_CH1)
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 43129ed..2e3fb17 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2602,6 +2602,29 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
> DPIO_TX1_STAGGER_MULT(7) |
> DPIO_TX2_STAGGER_MULT(5));
>
> + /*
> + * FIXME: After port B has been driven by pipe B, or
> + * the common lane well has been powered down, trying to drive
> + * port B with pipe A results in a link training failure. Somehow
> + * toggling the DCC calibrate force bits before enabling the port
> + * fixes the problem. Neither pipe B or port C seem to suffer from
> + * this problem, however doing the toggle on pipe B seems to cause
> + * eDP port C to blink when driven by pipe B. So we only do the
> + * toggle for pipe A. It's untested whether pipe C + port D might
> + * also need something like this due to lack of a suitale board.
> + *
> + * Not sure if this is just a symptom of some problem with the PHY
> + * programming we do, but this seems to be a solid workaround so far.
> + *
> + * All of this was tested on a BSW RVP with DP on port B,
> + * eDP on port C, and HDMI on port D.
> + */
> + if (pipe == PIPE_A) {
> + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW17(ch),
> + DPIO_TX1_DCC_CALIB_ENABLE | DPIO_TX2_DCC_CALIB_ENABLE);
> + vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW17(ch), 0);
> + }
> +
> mutex_unlock(&dev_priv->dpio_lock);
>
> intel_enable_dp(encoder);
> --
> 2.0.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-02-12 18:52 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-11 14:59 [PATCH 0/4] drm/i915: CHV display PHY magic ville.syrjala
2015-02-11 14:59 ` [PATCH 1/4] drm/i915: Implement chv display PHY lane stagger setup ville.syrjala
2015-02-11 14:59 ` [PATCH 2/4] drm/i915: Add a hack to fix link training errors on pipe A+port B on CHV ville.syrjala
2015-02-12 18:52 ` Ville Syrjälä
2015-02-11 14:59 ` [PATCH 3/4] Revert "drm/i915: Hack to tie both common lanes together on chv" ville.syrjala
2015-02-11 14:59 ` [PATCH 4/4] drm/i915: Work around DISPLAY_PHY_CONTROL register corruption on CHV ville.syrjala
2015-02-12 16:00 ` shuang.he
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox