intel-gfx.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes
@ 2012-08-28 22:06 Paulo Zanoni
  2012-08-28 22:06 ` [RFC 01/30] drm/i915: rewrite the LCPLL code Paulo Zanoni
                   ` (29 more replies)
  0 siblings, 30 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Hi

I've been working on this patch series for some time, and even though it's not
100% bug free yet, I feel it's ready to get some feedback, so I'm sending it as
an RFC. The ultimate goal is to make clocking+HDMI+DP+eDP work flawlessly and
without hanging the machine.

What's the current dinq status?
  - Only HDMI works, but it only uses WRPLL1 for everything, so dual screen
    doesn't exactly work everywhere.
  - DP and eDP patches were sent a long time ago, but they were dropped for not
    being the ideal solution. Also, code to properly detect if the monitor on a
    given port is DP or HDMI was never written.
  - We have problems dealing with the port/pipe clocks and newer SDVs completely
    freeze when booting.
  - We are nowhere near to being compliant with the "mode set/unset sequences"
    our documentation provides. And not following the mode set sequence is the
    cause of all the current issues we have.

This patch series is still based on dinq and not on Daniel's modeset-rework
patches. I did this because then I could be 100% sure that any problems were
actually introduced by me and not by the modeset-rework branch. I know I will
have to rewrite these patches on top of the modeset-rework branch, but, well,
it's the path I chose and I knew this (in addition, I get to learn more about
both worlds).

What does the patch series do?

  - The first 5 patches try to fix our clock handing and HDMI "mode unset". The
    patches are mixed because the goal of the "mode unset" changes is to give
    back the PLLs used so the clocking code can use it. I already discussed
    these with Daniel and it seems we'll still change these patches even more.
  - Then there is the DP series. Since DP and HDMI mode set/unset sequences are
    almost the same (they even share the same registers), I just made the HDMI
    code also work with DP instead of adding new DP-specific functions. It's a
    slow series where we add DP support to many functions without actually ever
    exposing DP by calling intel_dp_init.
  - Then there are the 2 patches that enable eDP. The second one actually starts
    exposing eDP on port A. I'm sure I'm still missing some bits of the eDP
    enablement, but at least my eDP panel works now.
  - Then the last patches make the DDI code properly detect if DP or HDMI is
    connected and make things work as expected. The big problem here is that DP
    and HDMI share the same registers, so you just can't call intel_dp_init and
    intel_hdmi_init passing the same port as the port argument. What I did here
    was to split intel_{dp,hdmi}_init_connector from intel_{dp,hdmi}_init, and
    created DDI's own encoder. So the legacy code still have an 1:1
    encoder:connector relationship, but the DDI encoder has 2 connectors: a DP
    connector and an HDMI connector.

What is still missing?

  - I still need to write a few more assertions and warnings in case things are
    not as we expect. Also, more debug output will be helpful.
  - As I already said, there are still some bugs when disabling things.

Comments, suggestions? Which color should we paint this?

Paulo Zanoni (30):
  drm/i915: rewrite the LCPLL code
  drm/i915: disable DDI pipes and ports when initializing
  drm/i915: wait for idle DDI_BUF_CTL after disabling it
  drm/i915: implement DDI disable function
  drm/i915: implement intel_ddi_pll_mode_set
  drm/i915: extract intel_ddi_enable pipe from intel_ddi_mode_set
  drm/i915: make intel_ddi_enable_pipe work on DP
  drm/i915: don't sleep after selecting the DDI pipe clock
  drm/i915: add DP support to intel_ddi_pll_mode_set
  drm/i915: add DP support to intel_ddi_disable_port
  drm/i915: add DP support to intel_ddi_mode_set
  drm/i915: add basic Haswell DP link train bits
  drm/i915: add intel_ddi_commit
  drm/i915: fix Haswell M/N registers
  drm/i915: fix DP AUX register definitions on Haswell
  drm/i915: disable DDI on intel_dp_link_down
  drm/i915: add intel_ddi_prepare_link_retrain
  drm/i915: add DP support to intel_ddi_disable
  drm/i915: add Haswell DP encoder_helper function definitions
  drm/i915: add TRANSCODER_EDP
  drm/i915: enable eDP on Haswell
  drm/i915: don't run PCH code on non-PCH ports
  drm/i915: init DP on port B
  drm/i915: simplify assignments inside intel_dp.c
  drm/i915: add intel_dp_to_dev and intel_hdmi_to_dev
  drm/i915: create intel_digital_port and use it
  drm/i915: remove encoder args from intel_{dp,hdmi}_add_properties
  drm/i915: split intel_hdmi_init into encoder and connector pieces
  drm/i915: split intel_dp_commit into encoder and connector pieces
  drm/i915: make DDI an encoder

 drivers/gpu/drm/i915/i915_drv.h      |   8 +
 drivers/gpu/drm/i915/i915_irq.c      |   7 +-
 drivers/gpu/drm/i915/i915_reg.h      |  79 ++--
 drivers/gpu/drm/i915/intel_ddi.c     | 705 +++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_display.c | 150 +++++---
 drivers/gpu/drm/i915/intel_dp.c      | 407 ++++++++++++++------
 drivers/gpu/drm/i915/intel_drv.h     |  64 +++-
 drivers/gpu/drm/i915/intel_hdmi.c    | 121 +++---
 drivers/gpu/drm/i915/intel_sprite.c  |   6 +-
 9 files changed, 1177 insertions(+), 370 deletions(-)

-- 
1.7.11.2

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

* [RFC 01/30] drm/i915: rewrite the LCPLL code
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 02/30] drm/i915: disable DDI pipes and ports when initializing Paulo Zanoni
                   ` (28 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Right now, we're trying to enable LCPLL at every mode set, but we're
never disabling it. Also, we really don't want to be disabling LCPLL
since it requires a very complex disable sequence. So instead of
enabling it at every mode set, enable it once.

Also, we are currently not checking if the desired values are the ones
we're actually reading/writing, so add some code to check the values
and give us warning messages.

Since the disable/enable sequence is very complex, I am not sure that
the single I915_WRITE we have is enough, but keep it for now to avoid
regressions since everybody's machines seem to be working.

The plan is to add even more code to intel_ddi_pll_init later.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      |  7 ++++++
 drivers/gpu/drm/i915/intel_ddi.c     | 46 +++++++++++++++++++++++++++++++-----
 drivers/gpu/drm/i915/intel_display.c |  7 ++++++
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 4 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 4dd9eb8..2eed9d4 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4516,8 +4516,15 @@
 #define LCPLL_CTL			0x130040
 #define  LCPLL_PLL_DISABLE		(1<<31)
 #define  LCPLL_PLL_LOCK			(1<<30)
+#define  LCPLL_CLK_FREQ_MASK		(3<<26)
+#define  LCPLL_CLK_FREQ_450		(0<<26)
+#define  LCPLL_CLK_FREQ_540		(1<<26)
 #define  LCPLL_CD_CLOCK_DISABLE		(1<<25)
 #define  LCPLL_CD2X_CLOCK_DISABLE	(1<<23)
+#define  LCPLL_CD_SOURCE_FCLK		(1<<21)
+
+#define CDCLK_FREQ			0x46200
+#define  CDCLK_FREQ_MASK		0x3FF
 
 /* Pipe WM_LINETIME - watermark line time */
 #define PIPE_WM_LINETIME_A		0x45270
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 170e386..18ebf15 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -682,12 +682,6 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	DRM_DEBUG_KMS("WR PLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
 		      crtc->mode.clock, p, n2, r2);
 
-	/* Enable LCPLL if disabled */
-	temp = I915_READ(LCPLL_CTL);
-	if (temp & LCPLL_PLL_DISABLE)
-		I915_WRITE(LCPLL_CTL,
-				temp & ~LCPLL_PLL_DISABLE);
-
 	/* Configure WR PLL 1, program the correct divider values for
 	 * the desired frequency and wait for warmup */
 	I915_WRITE(WRPLL_CTL1,
@@ -780,3 +774,43 @@ void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 	I915_WRITE(DDI_BUF_CTL(port),
 			temp);
 }
+
+void intel_ddi_pll_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t lcpll_val, clk_val, temp;
+	bool lcpll_needs_change = false;
+
+	/* Check the LCPLL state and fix it if needed. */
+	lcpll_val = I915_READ(LCPLL_CTL);
+	clk_val = I915_READ(CDCLK_FREQ) & CDCLK_FREQ_MASK;
+	DRM_DEBUG_KMS("CDCLK running at %dMHz\n", clk_val + 1);
+
+	temp = lcpll_val & LCPLL_CLK_FREQ_MASK;
+	if ((clk_val == 449 && (temp != LCPLL_CLK_FREQ_450)) ||
+	    (clk_val == 539 && (temp != LCPLL_CLK_FREQ_540))) {
+		DRM_ERROR("LCPLL and CDCLK frequencies don't match\n");
+		lcpll_needs_change = true;
+
+		lcpll_val &= ~LCPLL_CLK_FREQ_MASK;
+		if (clk_val == 449)
+			lcpll_val |= LCPLL_CLK_FREQ_450;
+		else
+			lcpll_val |= LCPLL_CLK_FREQ_540;
+	}
+
+	if (lcpll_val & LCPLL_CD_SOURCE_FCLK) {
+		DRM_ERROR("LCPLL is disabled\n");
+		lcpll_needs_change = true;
+		lcpll_val &= ~LCPLL_PLL_DISABLE;
+	}
+
+	if (lcpll_val & LCPLL_PLL_DISABLE) {
+		DRM_ERROR("LCPLL is disabled\n");
+		lcpll_needs_change = true;
+		lcpll_val &= ~LCPLL_PLL_DISABLE;
+	}
+
+	if (lcpll_needs_change)
+		I915_WRITE(LCPLL_CTL, lcpll_val);
+}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 42c5758..11687d2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6601,6 +6601,12 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
 	.page_flip = intel_crtc_page_flip,
 };
 
+static void intel_cpu_pll_init(struct drm_device *dev)
+{
+	if (IS_HASWELL(dev))
+		intel_ddi_pll_init(dev);
+}
+
 static void intel_pch_pll_init(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -7219,6 +7225,7 @@ void intel_modeset_init(struct drm_device *dev)
 			DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret);
 	}
 
+	intel_cpu_pll_init(dev);
 	intel_pch_pll_init(dev);
 
 	/* Just disable it once at startup */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 95f635b..cf9a1ad 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -521,5 +521,6 @@ extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode);
 extern void intel_ddi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode);
+extern void intel_ddi_pll_init(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.11.2

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

* [RFC 02/30] drm/i915: disable DDI pipes and ports when initializing
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
  2012-08-28 22:06 ` [RFC 01/30] drm/i915: rewrite the LCPLL code Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 03/30] drm/i915: wait for idle DDI_BUF_CTL after disabling it Paulo Zanoni
                   ` (27 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

This is required to prevent hanging the machine on Haswell. We need to
disable everything so when we start using we only enable/disable
exactly what we are using.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      |  2 +
 drivers/gpu/drm/i915/intel_ddi.c     | 74 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c |  7 ++--
 drivers/gpu/drm/i915/intel_drv.h     |  4 ++
 drivers/gpu/drm/i915/intel_sprite.c  |  6 +--
 5 files changed, 86 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2eed9d4..ee70588 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4375,6 +4375,7 @@
 #define  PIPE_DDI_FUNC_ENABLE		(1<<31)
 /* Those bits are ignored by pipe EDP since it can only connect to DDI A */
 #define  PIPE_DDI_PORT_MASK		(7<<28)
+#define  PIPE_DDI_PORT_NONE		(0<<28)
 #define  PIPE_DDI_SELECT_PORT(x)	((x)<<28)
 #define  PIPE_DDI_MODE_SELECT_MASK	(7<<24)
 #define  PIPE_DDI_MODE_SELECT_HDMI	(0<<24)
@@ -4503,6 +4504,7 @@
 #define  PORT_CLK_SEL_SPLL		(3<<29)
 #define  PORT_CLK_SEL_WRPLL1		(4<<29)
 #define  PORT_CLK_SEL_WRPLL2		(5<<29)
+#define  PORT_CLK_SEL_NONE		(7<<29)
 
 /* Pipe clock selection */
 #define PIPE_CLK_SEL_A			0x46140
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 18ebf15..b8b7670 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -751,6 +751,20 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
+static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
+				    enum port port)
+{
+	uint32_t reg = DDI_BUF_CTL(port);
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		udelay(1);
+		if (I915_READ(reg) & DDI_BUF_IS_IDLE)
+			return;
+	}
+	DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port));
+}
+
 void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
@@ -775,11 +789,71 @@ void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 			temp);
 }
 
+static void intel_ddi_disable_pipe(struct drm_i915_private *dev_priv,
+				   enum pipe pipe)
+{
+	uint32_t temp;
+
+	temp = I915_READ(DDI_FUNC_CTL(pipe));
+	temp &= ~(PIPE_DDI_FUNC_ENABLE | PIPE_DDI_PORT_MASK);
+	temp |= PIPE_DDI_PORT_NONE;
+	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+
+	I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_DISABLED);
+}
+
+static void intel_ddi_disable_port(struct drm_i915_private *dev_priv,
+				   enum port port)
+{
+	uint32_t reg, val;
+
+	reg = DDI_BUF_CTL(port);
+	val = I915_READ(reg);
+	if (val & DDI_BUF_CTL_ENABLE) {
+		val &= ~DDI_BUF_CTL_ENABLE;
+		I915_WRITE(reg, val);
+		intel_wait_ddi_buf_idle(dev_priv, port);
+	}
+
+	switch (I915_READ(PORT_CLK_SEL(port))) {
+	case PORT_CLK_SEL_WRPLL1:
+		reg = WRPLL_CTL1;
+		val = I915_READ(reg) & ~WRPLL_PLL_ENABLE;
+		break;
+	case PORT_CLK_SEL_WRPLL2:
+		reg = WRPLL_CTL2;
+		val = I915_READ(reg) & ~WRPLL_PLL_ENABLE;
+		break;
+	case PORT_CLK_SEL_SPLL:
+		reg = SPLL_CTL;
+		val = I915_READ(reg) & ~SPLL_PLL_ENABLE;
+		break;
+	default: /* LCPLL or none or reserved */
+		reg = 0;
+	}
+
+	if (reg)
+		I915_WRITE(reg, val);
+
+	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
+}
+
 void intel_ddi_pll_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t lcpll_val, clk_val, temp;
 	bool lcpll_needs_change = false;
+	int i;
+
+	/* Reset all pipe clocks and ports so we don't hang the machine later */
+	for (i = PIPE_A; i <= PIPE_C; i++) {
+		intel_disable_plane(dev_priv, i, i);
+		intel_disable_pipe(dev_priv, i);
+		intel_ddi_disable_pipe(dev_priv, i);
+	}
+
+	for (i = PORT_A; i <= PORT_E; i++)
+		intel_ddi_disable_port(dev_priv, i);
 
 	/* Check the LCPLL state and fix it if needed. */
 	lcpll_val = I915_READ(LCPLL_CTL);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 11687d2..33eebcb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1773,8 +1773,7 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
  *
  * Will wait until the pipe has shut down before returning.
  */
-static void intel_disable_pipe(struct drm_i915_private *dev_priv,
-			       enum pipe pipe)
+void intel_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
 	int reg;
 	u32 val;
@@ -1844,8 +1843,8 @@ static void intel_enable_plane(struct drm_i915_private *dev_priv,
  *
  * Disable @plane; should be an independent operation.
  */
-static void intel_disable_plane(struct drm_i915_private *dev_priv,
-				enum plane plane, enum pipe pipe)
+void intel_disable_plane(struct drm_i915_private *dev_priv,
+			 enum plane plane, enum pipe pipe)
 {
 	int reg;
 	u32 val;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cf9a1ad..2578158 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -390,6 +390,10 @@ extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder);
 extern int intel_plane_init(struct drm_device *dev, enum pipe pipe);
 extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
 				      enum plane plane);
+extern void intel_disable_plane(struct drm_i915_private *dev_priv,
+				enum plane plane, enum pipe pipe);
+extern void intel_disable_pipe(struct drm_i915_private *dev_priv,
+			       enum pipe pipe);
 
 /* intel_panel.c */
 extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index cc8df4d..4737303 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -531,7 +531,7 @@ out:
 }
 
 static int
-intel_disable_plane(struct drm_plane *plane)
+intel_disable_drm_plane(struct drm_plane *plane)
 {
 	struct drm_device *dev = plane->dev;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
@@ -556,7 +556,7 @@ out:
 static void intel_destroy_plane(struct drm_plane *plane)
 {
 	struct intel_plane *intel_plane = to_intel_plane(plane);
-	intel_disable_plane(plane);
+	intel_disable_drm_plane(plane);
 	drm_plane_cleanup(plane);
 	kfree(intel_plane);
 }
@@ -625,7 +625,7 @@ out_unlock:
 
 static const struct drm_plane_funcs intel_plane_funcs = {
 	.update_plane = intel_update_plane,
-	.disable_plane = intel_disable_plane,
+	.disable_plane = intel_disable_drm_plane,
 	.destroy = intel_destroy_plane,
 };
 
-- 
1.7.11.2

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

* [RFC 03/30] drm/i915: wait for idle DDI_BUF_CTL after disabling it
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
  2012-08-28 22:06 ` [RFC 01/30] drm/i915: rewrite the LCPLL code Paulo Zanoni
  2012-08-28 22:06 ` [RFC 02/30] drm/i915: disable DDI pipes and ports when initializing Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 04/30] drm/i915: implement DDI disable function Paulo Zanoni
                   ` (26 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Missing from intel_ddi_dpms.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index b8b7670..4fd22ae 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -787,6 +787,9 @@ void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 	 */
 	I915_WRITE(DDI_BUF_CTL(port),
 			temp);
+
+	if (mode != DRM_MODE_DPMS_ON && (temp & DDI_BUF_CTL_ENABLE))
+		intel_wait_ddi_buf_idle(dev_priv, port);
 }
 
 static void intel_ddi_disable_pipe(struct drm_i915_private *dev_priv,
-- 
1.7.11.2

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

* [RFC 04/30] drm/i915: implement DDI disable function
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (2 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 03/30] drm/i915: wait for idle DDI_BUF_CTL after disabling it Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 05/30] drm/i915: implement intel_ddi_pll_mode_set Paulo Zanoni
                   ` (25 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

It follows the "mode unset" sequence recommended by the documentation.
This is necessary so we can make PLLs available for the other mode
sets and it also helps preventing machine hangs.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c  | 31 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h  |  1 +
 drivers/gpu/drm/i915/intel_hdmi.c |  1 +
 3 files changed, 33 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 4fd22ae..e3dac45 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -841,6 +841,37 @@ static void intel_ddi_disable_port(struct drm_i915_private *dev_priv,
 	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
 }
 
+static bool intel_ddi_port_disabled(struct drm_i915_private *dev_priv,
+				    enum port port)
+{
+	return (I915_READ(PORT_CLK_SEL(port)) == PORT_CLK_SEL_NONE);
+}
+
+void intel_ddi_disable(struct drm_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+	struct drm_crtc *crtc = encoder->crtc;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	int port = intel_hdmi->ddi_port;
+
+	if (intel_ddi_port_disabled(dev_priv, port))
+		return;
+
+	if (!crtc) {
+		WARN(1, "Disabling encoder on port %c without CRTC\n",
+		     port_name(port));
+	} else {
+		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+		int pipe = intel_crtc->pipe;
+		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+
+		(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
+		intel_ddi_disable_pipe(dev_priv, pipe);
+	}
+
+	intel_ddi_disable_port(dev_priv, port);
+}
+
 void intel_ddi_pll_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 2578158..b99af38 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -526,5 +526,6 @@ extern void intel_ddi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode);
 extern void intel_ddi_pll_init(struct drm_device *dev);
+extern void intel_ddi_disable(struct drm_encoder *encoder);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index e4c37bb..c56d213 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -854,6 +854,7 @@ static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
 	.prepare = intel_encoder_prepare,
 	.mode_set = intel_ddi_mode_set,
 	.commit = intel_encoder_commit,
+	.disable = intel_ddi_disable,
 };
 
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
-- 
1.7.11.2

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

* [RFC 05/30] drm/i915: implement intel_ddi_pll_mode_set
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (3 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 04/30] drm/i915: implement DDI disable function Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 06/30] drm/i915: extract intel_ddi_enable pipe from intel_ddi_mode_set Paulo Zanoni
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Previously we were setting the PLLs at encoder->mode_set. This was a
problem because there's no way to fail and return error codes from
encoder->mode_set.

So now we follow the example of the previous gens and try to set the
PLLs inside ironlake_crtc_mode_set, properly failing when we need to
fail.

In addition to moving the DDI PLL code from hsw_fdi_link_train and
intel_ddi_mode_set to the new intel_ddi_pll_mode_set, we now try to
use WR PLL 2 when it's available.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c     | 168 +++++++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_display.c |   4 +
 drivers/gpu/drm/i915/intel_drv.h     |   1 +
 3 files changed, 128 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index e3dac45..a29c1e7 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -136,15 +136,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 	int pipe = intel_crtc->pipe;
 	u32 reg, temp, i;
 
-	/* Configure CPU PLL, wait for warmup */
-	I915_WRITE(SPLL_CTL,
-			SPLL_PLL_ENABLE |
-			SPLL_PLL_FREQ_1350MHz |
-			SPLL_PLL_SCC);
-
-	/* Use SPLL to drive the output when in FDI mode */
-	I915_WRITE(PORT_CLK_SEL(PORT_E),
-			PORT_CLK_SEL_SPLL);
 	I915_WRITE(PIPE_CLK_SEL(pipe),
 			PIPE_CLK_SEL_PORT(PORT_E));
 
@@ -645,6 +636,128 @@ static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
 	{298000,	2,	21,	19},
 };
 
+bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *intel_encoder;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	bool is_hdmi = false, is_crt = false;
+	int port, i, to_use, num_encoders = 0;
+	bool wrpll_used[] = {false, false};
+	bool spll_used = false;
+	uint32_t wrpll_reg[] = {WRPLL_CTL1, WRPLL_CTL2};
+	uint32_t wrpll_sel[] = {PORT_CLK_SEL_WRPLL1, PORT_CLK_SEL_WRPLL2};
+	uint32_t temp;
+
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		struct intel_hdmi *intel_hdmi;
+
+		switch (intel_encoder->type) {
+		case INTEL_OUTPUT_HDMI:
+			is_hdmi = true;
+			intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
+			port = intel_hdmi->ddi_port;
+			break;
+		case INTEL_OUTPUT_ANALOG:
+			is_crt = true;
+			port = PORT_E;
+			break;
+		default:
+			WARN(1, "Invalid encoder type %d on crtc for pipe %d\n",
+			     intel_encoder->type, intel_crtc->pipe);
+			return false;
+		}
+
+		num_encoders++;
+	}
+
+	if (num_encoders != 1) {
+		WARN(1, "%d encoders on crtc for pipe %d\n", num_encoders,
+		     intel_crtc->pipe);
+		return false;
+	}
+
+	for (i = PORT_A; i <= PORT_E; i++) {
+		if (i == port)
+			continue;
+
+		switch (I915_READ(PORT_CLK_SEL(i))) {
+		case PORT_CLK_SEL_WRPLL1:
+			wrpll_used[0] = true;
+			break;
+		case PORT_CLK_SEL_WRPLL2:
+			wrpll_used[1] = true;
+			break;
+		case PORT_CLK_SEL_SPLL:
+			spll_used = true;
+			break;
+		}
+	}
+
+	if (is_hdmi) {
+		int p, n2, r2;
+
+		for (i = 0; i < ARRAY_SIZE(wrpll_reg); i++)
+			if (!wrpll_used[i])
+				break;
+		if (i == ARRAY_SIZE(wrpll_reg)) {
+			DRM_ERROR("No WRPLL available\n");
+			return false;
+		}
+		to_use = i;
+
+		temp = I915_READ(wrpll_reg[to_use]);
+		if (temp & WRPLL_PLL_ENABLE) {
+			WARN(1, "WR PLL is enabled\n");
+			temp &= ~WRPLL_PLL_ENABLE;
+			I915_WRITE(wrpll_reg[to_use], temp);
+			POSTING_READ(wrpll_reg[to_use]);
+		}
+
+		for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++)
+			if (crtc->mode.clock <= wrpll_tmds_clock_table[i].clock)
+				break;
+		if (i == ARRAY_SIZE(wrpll_tmds_clock_table))
+			i--;
+
+		p = wrpll_tmds_clock_table[i].p;
+		n2 = wrpll_tmds_clock_table[i].n2;
+		r2 = wrpll_tmds_clock_table[i].r2;
+
+		if (wrpll_tmds_clock_table[i].clock != crtc->mode.clock)
+			DRM_INFO("WRPLL: using %dKHz settings on %dKHz mode\n",
+				 wrpll_tmds_clock_table[i].clock,
+				 crtc->mode.clock);
+
+		DRM_DEBUG_KMS("WRPLL %d: %dKHz with p=%d, n2=%d r2=%d\n",
+			      to_use +1, crtc->mode.clock, p, n2, r2);
+
+		I915_WRITE(wrpll_reg[to_use],
+			   WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+			   WRPLL_DIVIDER_REFERENCE(r2) |
+			   WRPLL_DIVIDER_FEEDBACK(n2) |
+			   WRPLL_DIVIDER_POST(p));
+
+		udelay(20);
+
+		I915_WRITE(PORT_CLK_SEL(port), wrpll_sel[to_use]);
+
+	} else if (is_crt) {
+		if (spll_used) {
+			DRM_ERROR("SPLL not available\n");
+			return false;
+		}
+
+		I915_WRITE(SPLL_CTL, SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz |
+				     SPLL_PLL_SCC);
+
+		I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_SPLL);
+	}
+
+	return true;
+}
+
 void intel_ddi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
@@ -656,48 +769,13 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 	int port = intel_hdmi->ddi_port;
 	int pipe = intel_crtc->pipe;
-	int p, n2, r2;
-	u32 temp, i;
+	u32 temp;
 
 	/* On Haswell, we need to enable the clocks and prepare DDI function to
 	 * work in HDMI mode for this pipe.
 	 */
 	DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));
 
-	for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++)
-		if (crtc->mode.clock <= wrpll_tmds_clock_table[i].clock)
-			break;
-
-	if (i == ARRAY_SIZE(wrpll_tmds_clock_table))
-		i--;
-
-	p = wrpll_tmds_clock_table[i].p;
-	n2 = wrpll_tmds_clock_table[i].n2;
-	r2 = wrpll_tmds_clock_table[i].r2;
-
-	if (wrpll_tmds_clock_table[i].clock != crtc->mode.clock)
-		DRM_INFO("WR PLL: using settings for %dKHz on %dKHz mode\n",
-			 wrpll_tmds_clock_table[i].clock, crtc->mode.clock);
-
-	DRM_DEBUG_KMS("WR PLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
-		      crtc->mode.clock, p, n2, r2);
-
-	/* Configure WR PLL 1, program the correct divider values for
-	 * the desired frequency and wait for warmup */
-	I915_WRITE(WRPLL_CTL1,
-			WRPLL_PLL_ENABLE |
-			WRPLL_PLL_SELECT_LCPLL_2700 |
-			WRPLL_DIVIDER_REFERENCE(r2) |
-			WRPLL_DIVIDER_FEEDBACK(n2) |
-			WRPLL_DIVIDER_POST(p));
-
-	udelay(20);
-
-	/* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use
-	 * this port for connection.
-	 */
-	I915_WRITE(PORT_CLK_SEL(port),
-			PORT_CLK_SEL_WRPLL1);
 	I915_WRITE(PIPE_CLK_SEL(pipe),
 			PIPE_CLK_SEL_PORT(port));
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 33eebcb..cd506bb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4627,6 +4627,10 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		num_connectors++;
 	}
 
+	if (IS_HASWELL(dev))
+		if (!intel_ddi_pll_mode_set(crtc))
+			return -EINVAL;
+
 	refclk = ironlake_get_refclk(crtc);
 
 	/*
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index b99af38..aa62439 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -522,6 +522,7 @@ extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv);
 extern void ironlake_teardown_rc6(struct drm_device *dev);
 
 extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode);
+extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc);
 extern void intel_ddi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode);
-- 
1.7.11.2

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

* [RFC 06/30] drm/i915: extract intel_ddi_enable pipe from intel_ddi_mode_set
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (4 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 05/30] drm/i915: implement intel_ddi_pll_mode_set Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 07/30] drm/i915: make intel_ddi_enable_pipe work on DP Paulo Zanoni
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

We already have intel_ddi_disable_pipe, let's also have
intel_ddi_enable_pipe.

After we implement DP link train we'll have to call this function from
another place.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 34 +++++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index a29c1e7..0c83ffa 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -758,26 +758,20 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
 	return true;
 }
 
-void intel_ddi_mode_set(struct drm_encoder *encoder,
-				struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode)
+static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder,
+				  struct drm_display_mode *adjusted_mode)
 {
+	struct drm_encoder *encoder = &intel_encoder->base;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 	int port = intel_hdmi->ddi_port;
 	int pipe = intel_crtc->pipe;
 	u32 temp;
 
-	/* On Haswell, we need to enable the clocks and prepare DDI function to
-	 * work in HDMI mode for this pipe.
-	 */
-	DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));
-
-	I915_WRITE(PIPE_CLK_SEL(pipe),
-			PIPE_CLK_SEL_PORT(port));
+	I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_PORT(port));
 
 	udelay(20);
 
@@ -829,6 +823,24 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
+void intel_ddi_mode_set(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct drm_crtc *crtc = encoder->crtc;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	int port = intel_hdmi->ddi_port;
+	int pipe = intel_crtc->pipe;
+
+	/* On Haswell, we need to enable the clocks and prepare DDI function to
+	 * work in HDMI mode for this pipe.
+	 */
+	DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));
+
+	intel_ddi_enable_pipe(&intel_hdmi->base, adjusted_mode);
+}
+
 static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
 				    enum port port)
 {
-- 
1.7.11.2

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

* [RFC 07/30] drm/i915: make intel_ddi_enable_pipe work on DP
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (5 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 06/30] drm/i915: extract intel_ddi_enable pipe from intel_ddi_mode_set Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 08/30] drm/i915: don't sleep after selecting the DDI pipe clock Paulo Zanoni
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Not just HDMI/DVI.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h  | 10 +++++
 drivers/gpu/drm/i915/intel_ddi.c | 95 +++++++++++++++++++++++++++-------------
 drivers/gpu/drm/i915/intel_dp.c  |  5 ---
 drivers/gpu/drm/i915/intel_drv.h |  4 ++
 4 files changed, 79 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ee70588..9d34a2e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4514,6 +4514,16 @@
 #define  PIPE_CLK_SEL_DISABLED		(0x0<<29)
 #define  PIPE_CLK_SEL_PORT(x)		((x+1)<<29)
 
+#define _PIPEA_MSA_MISC			0x60410
+#define _PIPEB_MSA_MISC			0x61410
+#define PIPE_MSA_MISC(pipe) _PIPE(pipe, _PIPEA_MSA_MISC, _PIPEB_MSA_MISC)
+#define  PIPE_MSA_SYNC_CLK		(1<<0)
+#define  PIPE_MSA_6_BPC			(0<<5)
+#define  PIPE_MSA_8_BPC			(1<<5)
+#define  PIPE_MSA_10_BPC		(2<<5)
+#define  PIPE_MSA_12_BPC		(3<<5)
+#define  PIPE_MSA_16_BPC		(3<<5)
+
 /* LCPLL Control */
 #define LCPLL_CTL			0x130040
 #define  LCPLL_PLL_DISABLE		(1<<31)
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 0c83ffa..208f13f 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -762,65 +762,100 @@ static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder,
 				  struct drm_display_mode *adjusted_mode)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int port = intel_hdmi->ddi_port;
+	int port;
 	int pipe = intel_crtc->pipe;
-	u32 temp;
+	u32 func_val, msa_val;
+	struct intel_hdmi *intel_hdmi = NULL;
+	struct intel_dp *intel_dp = NULL;
+
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+		intel_hdmi = enc_to_intel_hdmi(encoder);
+		port = intel_hdmi->ddi_port;
+	} else {
+		intel_dp = enc_to_intel_dp(encoder);
+		port = intel_dp->port;
+	}
 
 	I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_PORT(port));
 
 	udelay(20);
 
-	if (intel_hdmi->has_audio) {
-		/* Proper support for digital audio needs a new logic and a new set
-		 * of registers, so we leave it for future patch bombing.
-		 */
-		DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n",
-				 pipe_name(intel_crtc->pipe));
-
-		/* write eld */
-		DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
-		intel_write_eld(encoder, adjusted_mode);
-	}
-
-	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
-	temp = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
+	func_val = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
+	msa_val = PIPE_MSA_SYNC_CLK;
 
 	switch (intel_crtc->bpp) {
 	case 18:
-		temp |= PIPE_DDI_BPC_6;
+		func_val |= PIPE_DDI_BPC_6;
+		msa_val |= PIPE_MSA_6_BPC;
 		break;
 	case 24:
-		temp |= PIPE_DDI_BPC_8;
+		func_val |= PIPE_DDI_BPC_8;
+		msa_val |= PIPE_MSA_8_BPC;
 		break;
 	case 30:
-		temp |= PIPE_DDI_BPC_10;
+		func_val |= PIPE_DDI_BPC_10;
+		msa_val |= PIPE_MSA_10_BPC;
 		break;
 	case 36:
-		temp |= PIPE_DDI_BPC_12;
+		func_val |= PIPE_DDI_BPC_12;
+		msa_val |= PIPE_MSA_12_BPC;
 		break;
 	default:
 		WARN(1, "%d bpp unsupported by pipe DDI function\n",
 		     intel_crtc->bpp);
 	}
 
-	if (intel_hdmi->has_hdmi_sink)
-		temp |= PIPE_DDI_MODE_SELECT_HDMI;
-	else
-		temp |= PIPE_DDI_MODE_SELECT_DVI;
-
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-		temp |= PIPE_DDI_PVSYNC;
+		func_val |= PIPE_DDI_PVSYNC;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-		temp |= PIPE_DDI_PHSYNC;
+		func_val |= PIPE_DDI_PHSYNC;
 
-	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+		if (intel_hdmi->has_hdmi_sink)
+			func_val |= PIPE_DDI_MODE_SELECT_HDMI;
+		else
+			func_val |= PIPE_DDI_MODE_SELECT_DVI;
+	} else {
+		func_val |= PIPE_DDI_MODE_SELECT_DP_SST;
 
-	intel_hdmi->set_infoframes(encoder, adjusted_mode);
+		switch (intel_dp->lane_count) {
+		case 1:
+			func_val |= PIPE_DDI_PORT_WIDTH_X1;
+			break;
+		case 2:
+			func_val |= PIPE_DDI_PORT_WIDTH_X2;
+			break;
+		case 4:
+			func_val |= PIPE_DDI_PORT_WIDTH_X4;
+			break;
+		default:
+			WARN(1, "Unsupported lane count %d\n",
+			     intel_dp->lane_count);
+		}
+
+		I915_WRITE(PIPE_MSA_MISC(pipe), msa_val);
+	}
+
+	I915_WRITE(DDI_FUNC_CTL(pipe), func_val);
+
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+		if (intel_hdmi->has_audio) {
+			DRM_DEBUG_KMS("HDMI audio on pipe %c on DDI\n",
+				      pipe_name(intel_crtc->pipe));
+
+			DRM_DEBUG_KMS("HDMI audio: write eld information\n");
+			intel_write_eld(encoder, adjusted_mode);
+		}
+
+		intel_hdmi->set_infoframes(encoder, adjusted_mode);
+	} else {
+		if (intel_dp->has_audio)
+			DRM_DEBUG_KMS("DP audio not supported yet\n");
+	}
 }
 
 void intel_ddi_mode_set(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 977d9d2..31d6e78 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -76,11 +76,6 @@ static bool is_cpu_edp(struct intel_dp *intel_dp)
 	return is_edp(intel_dp) && !is_pch_edp(intel_dp);
 }
 
-static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
-{
-	return container_of(encoder, struct intel_dp, base.base);
-}
-
 static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
 {
 	return container_of(intel_attached_encoder(connector),
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index aa62439..52c7547 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -420,6 +420,10 @@ static inline struct intel_encoder *intel_attached_encoder(struct drm_connector
 {
 	return to_intel_connector(connector)->encoder;
 }
+static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct intel_dp, base.base);
+}
 
 extern void intel_connector_attach_encoder(struct intel_connector *connector,
 					   struct intel_encoder *encoder);
-- 
1.7.11.2

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

* [RFC 08/30] drm/i915: don't sleep after selecting the DDI pipe clock
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (6 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 07/30] drm/i915: make intel_ddi_enable_pipe work on DP Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 09/30] drm/i915: add DP support to intel_ddi_pll_mode_set Paulo Zanoni
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

This is not needed. This sleep is probably here due to the many code
changes that happened to the old intel_ddi_mode_set. We should sleep
20us after turning the PLLs on, and this is already implemented.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 208f13f..33b3a75 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -782,8 +782,6 @@ static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder,
 
 	I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_PORT(port));
 
-	udelay(20);
-
 	func_val = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
 	msa_val = PIPE_MSA_SYNC_CLK;
 
-- 
1.7.11.2

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

* [RFC 09/30] drm/i915: add DP support to intel_ddi_pll_mode_set
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (7 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 08/30] drm/i915: don't sleep after selecting the DDI pipe clock Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 10/30] drm/i915: add DP support to intel_ddi_disable_port Paulo Zanoni
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 33b3a75..dd28e35 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -642,18 +642,23 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_encoder *intel_encoder;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	bool is_hdmi = false, is_crt = false;
-	int port, i, to_use, num_encoders = 0;
+	bool is_hdmi = false, is_crt = false, is_dp = false;
+	int port = I915_MAX_PORTS, i, to_use, num_encoders = 0;
 	bool wrpll_used[] = {false, false};
 	bool spll_used = false;
 	uint32_t wrpll_reg[] = {WRPLL_CTL1, WRPLL_CTL2};
 	uint32_t wrpll_sel[] = {PORT_CLK_SEL_WRPLL1, PORT_CLK_SEL_WRPLL2};
 	uint32_t temp;
+	struct intel_dp *intel_dp = NULL;
+	struct intel_hdmi *intel_hdmi = NULL;
 
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
-		struct intel_hdmi *intel_hdmi;
-
 		switch (intel_encoder->type) {
+		case INTEL_OUTPUT_DISPLAYPORT:
+			is_dp = true;
+			intel_dp = enc_to_intel_dp(&intel_encoder->base);
+			port = intel_dp->port;
+			break;
 		case INTEL_OUTPUT_HDMI:
 			is_hdmi = true;
 			intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
@@ -678,6 +683,11 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
 		return false;
 	}
 
+	if (port == I915_MAX_PORTS) {
+		WARN(1, "No port selected\n");
+		return false;
+	}
+
 	for (i = PORT_A; i <= PORT_E; i++) {
 		if (i == port)
 			continue;
@@ -695,7 +705,26 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
 		}
 	}
 
-	if (is_hdmi) {
+	if (is_dp) {
+		switch (intel_dp->link_bw) {
+		case DP_LINK_BW_1_62:
+			temp = PORT_CLK_SEL_LCPLL_810;
+			break;
+		case DP_LINK_BW_2_7:
+			temp = PORT_CLK_SEL_LCPLL_1350;
+			break;
+		case DP_LINK_BW_5_4:
+			temp = PORT_CLK_SEL_LCPLL_2700;
+			break;
+		default:
+			DRM_ERROR("Link bandwidth %d unsupported\n",
+				  intel_dp->link_bw);
+			return false;
+		}
+
+		I915_WRITE(PORT_CLK_SEL(port), temp);
+
+	} else if (is_hdmi) {
 		int p, n2, r2;
 
 		for (i = 0; i < ARRAY_SIZE(wrpll_reg); i++)
-- 
1.7.11.2

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

* [RFC 10/30] drm/i915: add DP support to intel_ddi_disable_port
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (8 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 09/30] drm/i915: add DP support to intel_ddi_pll_mode_set Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 11/30] drm/i915: add DP support to intel_ddi_mode_set Paulo Zanoni
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Just a missing register. There is no problem to run this code when the
output is HDMI.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index dd28e35..fed7856 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -961,15 +961,25 @@ static void intel_ddi_disable_port(struct drm_i915_private *dev_priv,
 				   enum port port)
 {
 	uint32_t reg, val;
+	bool wait = false;
 
 	reg = DDI_BUF_CTL(port);
 	val = I915_READ(reg);
 	if (val & DDI_BUF_CTL_ENABLE) {
 		val &= ~DDI_BUF_CTL_ENABLE;
 		I915_WRITE(reg, val);
-		intel_wait_ddi_buf_idle(dev_priv, port);
+		wait = true;
 	}
 
+	reg = DP_TP_CTL(port);
+	val = I915_READ(reg);
+	val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
+	val |= DP_TP_CTL_LINK_TRAIN_PAT1;
+	I915_WRITE(reg, val);
+
+	if (wait)
+		intel_wait_ddi_buf_idle(dev_priv, port);
+
 	switch (I915_READ(PORT_CLK_SEL(port))) {
 	case PORT_CLK_SEL_WRPLL1:
 		reg = WRPLL_CTL1;
-- 
1.7.11.2

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

* [RFC 11/30] drm/i915: add DP support to intel_ddi_mode_set
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (9 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 10/30] drm/i915: add DP support to intel_ddi_disable_port Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 12/30] drm/i915: add basic Haswell DP link train bits Paulo Zanoni
                   ` (18 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 44 +++++++++++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_dp.c  | 28 +++++++++++++++----------
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 3 files changed, 55 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index fed7856..23ec6a2 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -891,16 +891,46 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 {
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
-	int port = intel_hdmi->ddi_port;
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+	struct intel_hdmi *intel_hdmi = NULL;
+	struct intel_dp *intel_dp = NULL;
+	int port;
 	int pipe = intel_crtc->pipe;
 
-	/* On Haswell, we need to enable the clocks and prepare DDI function to
-	 * work in HDMI mode for this pipe.
-	 */
-	DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+		intel_hdmi = enc_to_intel_hdmi(encoder);
+		port = intel_hdmi->ddi_port;
+	} else {
+		intel_dp = enc_to_intel_dp(encoder);
+		port = intel_dp->port;
+	}
+
+	DRM_DEBUG_KMS("Preparing DDI mode for Haswell on port %c, pipe %c\n",
+		      port_name(port), pipe_name(pipe));
+
+	if (intel_encoder->type != INTEL_OUTPUT_HDMI) {
+		intel_dp->DP = DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
+		switch (intel_dp->lane_count) {
+		case 1:
+			intel_dp->DP |= DDI_PORT_WIDTH_X1;
+			break;
+		case 2:
+			intel_dp->DP |= DDI_PORT_WIDTH_X2;
+			break;
+		case 4:
+			intel_dp->DP |= DDI_PORT_WIDTH_X4;
+			break;
+		default:
+			intel_dp->DP |= DDI_PORT_WIDTH_X4;
+			WARN(1, "Unexpected DP lane count %d\n",
+			     intel_dp->lane_count);
+			break;
+		}
+
+		intel_dp_init_link_config(intel_dp);
+	}
 
-	intel_ddi_enable_pipe(&intel_hdmi->base, adjusted_mode);
+	intel_ddi_enable_pipe(intel_encoder, adjusted_mode);
 }
 
 static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 31d6e78..4cd85f7 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -806,6 +806,21 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 static void ironlake_edp_pll_on(struct drm_encoder *encoder);
 static void ironlake_edp_pll_off(struct drm_encoder *encoder);
 
+void intel_dp_init_link_config(struct intel_dp *intel_dp)
+{
+	memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
+	intel_dp->link_configuration[0] = intel_dp->link_bw;
+	intel_dp->link_configuration[1] = intel_dp->lane_count;
+	intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
+	/*
+	 * Check for DPCD version > 1.1 and enhanced framing support
+	 */
+	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
+	    (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
+		intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+	}
+}
+
 static void
 intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		  struct drm_display_mode *adjusted_mode)
@@ -868,17 +883,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
 		intel_write_eld(encoder, adjusted_mode);
 	}
-	memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
-	intel_dp->link_configuration[0] = intel_dp->link_bw;
-	intel_dp->link_configuration[1] = intel_dp->lane_count;
-	intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
-	/*
-	 * Check for DPCD version > 1.1 and enhanced framing support
-	 */
-	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
-	    (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
-		intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
-	}
+
+	intel_dp_init_link_config(intel_dp);
 
 	/* Split out the IBX/CPU vs CPT settings */
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 52c7547..1b9c549 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -382,6 +382,7 @@ extern void intel_dp_init(struct drm_device *dev, int output_reg,
 void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode);
+extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
 extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
 extern int intel_edp_target_clock(struct intel_encoder *,
-- 
1.7.11.2

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

* [RFC 12/30] drm/i915: add basic Haswell DP link train bits
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (10 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 11/30] drm/i915: add DP support to intel_ddi_mode_set Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 13/30] drm/i915: add intel_ddi_commit Paulo Zanoni
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Previously, the DP register was used for everything. On Haswell, it
was split into DDI_BUF_CTL (which is the new intel_dp->DP register)
and DP_TP_CTL.

The logic behind this patch is based on a patch written by Shobhit
Kumar, but the way the code was written is very different.

Credits-to: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h |   4 ++
 drivers/gpu/drm/i915/intel_dp.c | 104 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 102 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 9d34a2e..8f84216 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4407,12 +4407,16 @@
 #define  DP_TP_CTL_LINK_TRAIN_MASK		(7<<8)
 #define  DP_TP_CTL_LINK_TRAIN_PAT1		(0<<8)
 #define  DP_TP_CTL_LINK_TRAIN_PAT2		(1<<8)
+#define  DP_TP_CTL_LINK_TRAIN_PAT3		(4<<8)
+#define  DP_TP_CTL_LINK_TRAIN_IDLE		(2<<8)
 #define  DP_TP_CTL_LINK_TRAIN_NORMAL		(3<<8)
+#define  DP_TP_CTL_SCRAMBLE_DISABLE		(1<<7)
 
 /* DisplayPort Transport Status */
 #define DP_TP_STATUS_A			0x64044
 #define DP_TP_STATUS_B			0x64144
 #define DP_TP_STATUS(port) _PORT(port, DP_TP_STATUS_A, DP_TP_STATUS_B)
+#define  DP_TP_STATUS_IDLE_DONE		(1<<25)
 #define  DP_TP_STATUS_AUTOTRAIN_DONE	(1<<12)
 
 /* DDI Buffer Control */
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4cd85f7..a7a5178 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1426,7 +1426,19 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
 {
 	struct drm_device *dev = intel_dp->base.base.dev;
 
-	if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+	if (IS_HASWELL(dev)) {
+		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+		case DP_TRAIN_VOLTAGE_SWING_400:
+			return DP_TRAIN_PRE_EMPHASIS_9_5;
+		case DP_TRAIN_VOLTAGE_SWING_600:
+			return DP_TRAIN_PRE_EMPHASIS_6;
+		case DP_TRAIN_VOLTAGE_SWING_800:
+			return DP_TRAIN_PRE_EMPHASIS_3_5;
+		case DP_TRAIN_VOLTAGE_SWING_1200:
+		default:
+			return DP_TRAIN_PRE_EMPHASIS_0;
+		}
+	} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 		case DP_TRAIN_VOLTAGE_SWING_400:
 			return DP_TRAIN_PRE_EMPHASIS_6;
@@ -1580,6 +1592,40 @@ intel_gen7_edp_signal_levels(uint8_t train_set)
 	}
 }
 
+/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */
+static uint32_t
+intel_dp_signal_levels_hsw(uint8_t train_set)
+{
+	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
+					 DP_TRAIN_PRE_EMPHASIS_MASK);
+	switch (signal_levels) {
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
+		return DDI_BUF_EMP_400MV_0DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return DDI_BUF_EMP_400MV_3_5DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
+		return DDI_BUF_EMP_400MV_6DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_9_5:
+		return DDI_BUF_EMP_400MV_9_5DB_HSW;
+
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0:
+		return DDI_BUF_EMP_600MV_0DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return DDI_BUF_EMP_600MV_3_5DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_6:
+		return DDI_BUF_EMP_600MV_6DB_HSW;
+
+	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
+		return DDI_BUF_EMP_800MV_0DB_HSW;
+	case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5:
+		return DDI_BUF_EMP_800MV_3_5DB_HSW;
+	default:
+		DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
+			      "0x%x\n", signal_levels);
+		return DDI_BUF_EMP_400MV_0DB_HSW;
+	}
+}
+
 static uint8_t
 intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
 		      int lane)
@@ -1636,8 +1682,44 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
+	uint32_t temp;
 
-	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
+	if (IS_HASWELL(dev)) {
+		temp = I915_READ(DP_TP_CTL(intel_dp->port));
+
+		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
+			temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
+		else
+			temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
+
+		temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
+		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+		case DP_TRAINING_PATTERN_DISABLE:
+			temp |= DP_TP_CTL_LINK_TRAIN_IDLE;
+			I915_WRITE(DP_TP_CTL(intel_dp->port), temp);
+
+			if (wait_for((I915_READ(DP_TP_STATUS(intel_dp->port)) &
+				      DP_TP_STATUS_IDLE_DONE) == 0, 1))
+				DRM_ERROR("Timed out waiting for DP idle patterns\n");
+
+			temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
+			temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
+
+			break;
+		case DP_TRAINING_PATTERN_1:
+			temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
+			break;
+		case DP_TRAINING_PATTERN_2:
+			temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
+			break;
+		case DP_TRAINING_PATTERN_3:
+			temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
+			break;
+		}
+		I915_WRITE(DP_TP_CTL(intel_dp->port), temp);
+
+	} else if (HAS_PCH_CPT(dev) &&
+		   (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
 		dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT;
 
 		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
@@ -1737,8 +1819,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 		uint8_t	    link_status[DP_LINK_STATUS_SIZE];
 		uint32_t    signal_levels;
 
-
-		if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+		if (IS_HASWELL(dev)) {
+			signal_levels = intel_dp_signal_levels_hsw(
+							intel_dp->train_set[0]);
+			DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels;
+		} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
 			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
 		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
@@ -1746,9 +1831,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
 		} else {
 			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
-			DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels);
 			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
 		}
+		DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n",
+			      signal_levels);
 
 		if (!intel_dp_set_link_train(intel_dp, DP,
 					     DP_TRAINING_PATTERN_1 |
@@ -1824,7 +1910,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 			break;
 		}
 
-		if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+		if (IS_HASWELL(dev)) {
+			signal_levels = intel_dp_signal_levels_hsw(intel_dp->train_set[0]);
+			DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels;
+		} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
 			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
 		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
@@ -1871,6 +1960,9 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 		++tries;
 	}
 
+	if (channel_eq)
+		DRM_DEBUG_KMS("Channel EQ done. DP Training successfull\n");
+
 	intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE);
 }
 
-- 
1.7.11.2

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

* [RFC 13/30] drm/i915: add intel_ddi_commit
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (11 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 12/30] drm/i915: add basic Haswell DP link train bits Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 14/30] drm/i915: fix Haswell M/N registers Paulo Zanoni
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

On DDI code we should only enable the DDI pipe registers after the
link train, so adjust the code in a way that makes this possible. Also
use intel_ddi_commit for the HDMI mode.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c  | 27 +++++++++++++++++++--------
 drivers/gpu/drm/i915/intel_dp.c   |  2 +-
 drivers/gpu/drm/i915/intel_drv.h  |  2 ++
 drivers/gpu/drm/i915/intel_hdmi.c |  2 +-
 4 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 23ec6a2..151963e 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -787,14 +787,14 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
 	return true;
 }
 
-static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder,
-				  struct drm_display_mode *adjusted_mode)
+static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_display_mode *mode = &crtc->mode;
 	int port;
 	int pipe = intel_crtc->pipe;
 	u32 func_val, msa_val;
@@ -836,9 +836,9 @@ static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder,
 		     intel_crtc->bpp);
 	}
 
-	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
 		func_val |= PIPE_DDI_PVSYNC;
-	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
 		func_val |= PIPE_DDI_PHSYNC;
 
 	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
@@ -875,10 +875,10 @@ static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder,
 				      pipe_name(intel_crtc->pipe));
 
 			DRM_DEBUG_KMS("HDMI audio: write eld information\n");
-			intel_write_eld(encoder, adjusted_mode);
+			intel_write_eld(encoder, mode);
 		}
 
-		intel_hdmi->set_infoframes(encoder, adjusted_mode);
+		intel_hdmi->set_infoframes(encoder, mode);
 	} else {
 		if (intel_dp->has_audio)
 			DRM_DEBUG_KMS("DP audio not supported yet\n");
@@ -929,8 +929,6 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 
 		intel_dp_init_link_config(intel_dp);
 	}
-
-	intel_ddi_enable_pipe(intel_encoder, adjusted_mode);
 }
 
 static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
@@ -974,6 +972,19 @@ void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 		intel_wait_ddi_buf_idle(dev_priv, port);
 }
 
+void intel_ddi_commit(struct drm_encoder *encoder)
+{
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+
+	if (intel_encoder->type != INTEL_OUTPUT_HDMI)
+		intel_dp_commit(encoder);
+
+	intel_ddi_enable_pipe(intel_encoder);
+
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI)
+		intel_ddi_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
 static void intel_ddi_disable_pipe(struct drm_i915_private *dev_priv,
 				   enum pipe pipe)
 {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a7a5178..24c699a 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1265,7 +1265,7 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
 	intel_dp_link_down(intel_dp);
 }
 
-static void intel_dp_commit(struct drm_encoder *encoder)
+void intel_dp_commit(struct drm_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct drm_device *dev = encoder->dev;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1b9c549..f3f5b83 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -383,6 +383,7 @@ void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode);
 extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
+extern void intel_dp_commit(struct drm_encoder *encoder);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
 extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
 extern int intel_edp_target_clock(struct intel_encoder *,
@@ -533,5 +534,6 @@ extern void intel_ddi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *adjusted_mode);
 extern void intel_ddi_pll_init(struct drm_device *dev);
 extern void intel_ddi_disable(struct drm_encoder *encoder);
+extern void intel_ddi_commit(struct drm_encoder *encoder);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index c56d213..ad58bec 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -853,7 +853,7 @@ static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
 	.mode_fixup = intel_hdmi_mode_fixup,
 	.prepare = intel_encoder_prepare,
 	.mode_set = intel_ddi_mode_set,
-	.commit = intel_encoder_commit,
+	.commit = intel_ddi_commit,
 	.disable = intel_ddi_disable,
 };
 
-- 
1.7.11.2

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

* [RFC 14/30] drm/i915: fix Haswell M/N registers
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (12 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 13/30] drm/i915: add intel_ddi_commit Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 15/30] drm/i915: fix DP AUX register definitions on Haswell Paulo Zanoni
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

We have to write the correct values inside intel_dp_set_m_n and then
we have to prevent ironlake_crtc_mode_set from overwriting the correct
values with wrong ones.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 10 ++++++----
 drivers/gpu/drm/i915/intel_dp.c      |  9 ++++++++-
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cd506bb..986d790 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4949,10 +4949,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(PIPESRC(pipe),
 		   ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
 
-	I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
-	I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
-	I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
-	I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
+	if (!(IS_HASWELL(dev) && is_dp)) {
+		I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
+		I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
+		I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
+		I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
+	}
 
 	if (is_cpu_edp)
 		ironlake_set_pll_edp(crtc, adjusted_mode->clock);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 24c699a..94fad89 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -786,7 +786,14 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	intel_dp_compute_m_n(intel_crtc->bpp, lane_count,
 			     mode->clock, adjusted_mode->clock, &m_n);
 
-	if (HAS_PCH_SPLIT(dev)) {
+	if (IS_HASWELL(dev)) {
+		I915_WRITE(PIPE_DATA_M1(pipe),
+			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+			   m_n.gmch_m);
+		I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
+		I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
+		I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
+	} else if (HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(TRANSDATA_M1(pipe),
 			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
 			   m_n.gmch_m);
-- 
1.7.11.2

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

* [RFC 15/30] drm/i915: fix DP AUX register definitions on Haswell
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (13 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 14/30] drm/i915: fix Haswell M/N registers Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 16/30] drm/i915: disable DDI on intel_dp_link_down Paulo Zanoni
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

The old rule that the AUX registers are just an offset (+4 and +10)
from output_reg is not true anymore, since output_reg in on the CPU
and some AUX regs are on the PCH.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h |  8 ++++++++
 drivers/gpu/drm/i915/intel_dp.c | 24 ++++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 8f84216..9c9f288 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2538,6 +2538,14 @@
 #define DPD_AUX_CH_DATA4		0x64320
 #define DPD_AUX_CH_DATA5		0x64324
 
+#define PCH_DPB_AUX_CH_CTL		0xe4110
+#define PCH_DPC_AUX_CH_CTL		0xe4210
+#define PCH_DPD_AUX_CH_CTL		0xe4310
+
+#define PCH_DPB_AUX_CH_DATA		0xe4114
+#define PCH_DPC_AUX_CH_DATA		0xe4214
+#define PCH_DPD_AUX_CH_DATA		0xe4314
+
 #define   DP_AUX_CH_CTL_SEND_BUSY	    (1 << 31)
 #define   DP_AUX_CH_CTL_DONE		    (1 << 30)
 #define   DP_AUX_CH_CTL_INTERRUPT	    (1 << 29)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 94fad89..3c6b94c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -351,6 +351,30 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	uint32_t aux_clock_divider;
 	int try, precharge;
 
+	if (IS_HASWELL(dev)) {
+		switch (intel_dp->port) {
+		case PORT_A:
+			ch_ctl = DPA_AUX_CH_CTL;
+			ch_data = DPA_AUX_CH_DATA1;
+			break;
+		case PORT_B:
+			ch_ctl = PCH_DPB_AUX_CH_CTL;
+			ch_data = PCH_DPB_AUX_CH_DATA;
+			break;
+		case PORT_C:
+			ch_ctl = PCH_DPC_AUX_CH_CTL;
+			ch_data = PCH_DPC_AUX_CH_DATA;
+			break;
+		case PORT_D:
+			ch_ctl = PCH_DPD_AUX_CH_CTL;
+			ch_data = PCH_DPD_AUX_CH_DATA;
+			break;
+		default:
+			WARN(1, "Invalid port %c\n", port_name(intel_dp->port));
+			break;
+		}
+	}
+
 	intel_dp_check_edp(intel_dp);
 	/* The clock divider is based off the hrawclk,
 	 * and would like to run at 2MHz. So, take the
-- 
1.7.11.2

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

* [RFC 16/30] drm/i915: disable DDI on intel_dp_link_down
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (14 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 15/30] drm/i915: fix DP AUX register definitions on Haswell Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 17/30] drm/i915: add intel_ddi_prepare_link_retrain Paulo Zanoni
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

It requires a full disable of everything.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3c6b94c..e59d676 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2004,6 +2004,11 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t DP = intel_dp->DP;
 
+	if (IS_HASWELL(dev)) {
+		intel_ddi_disable(&intel_dp->base.base);
+		return;
+	}
+
 	if ((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
 		return;
 
-- 
1.7.11.2

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

* [RFC 17/30] drm/i915: add intel_ddi_prepare_link_retrain
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (15 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 16/30] drm/i915: disable DDI on intel_dp_link_down Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 18/30] drm/i915: add DP support to intel_ddi_disable Paulo Zanoni
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

In order to retrain the link we have to disable everything, then
reenable.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 43 ++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_dp.c  | 17 +++++++++-------
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 3 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 151963e..ed38bb3 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1125,3 +1125,46 @@ void intel_ddi_pll_init(struct drm_device *dev)
 	if (lcpll_needs_change)
 		I915_WRITE(LCPLL_CTL, lcpll_val);
 }
+
+static void intel_ddi_enable_dp_port(struct intel_encoder *intel_encoder)
+{
+	struct drm_device *dev = intel_encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	int port = intel_dp->port;
+	uint32_t tp_val;
+
+	tp_val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST |
+		 DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
+	if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
+		tp_val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
+	I915_WRITE(DP_TP_CTL(port), tp_val);
+	POSTING_READ(DP_TP_CTL(port));
+
+	intel_dp->DP |= DDI_BUF_CTL_ENABLE;
+	I915_WRITE(DDI_BUF_CTL(port), intel_dp->DP);
+	POSTING_READ(DDI_BUF_CTL(port));
+
+	udelay(600);
+}
+
+void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
+{
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+	struct drm_crtc *crtc = encoder->crtc;
+	struct drm_crtc_helper_funcs *crtc_funcs;
+
+	if (!crtc) {
+		WARN(1, "Retraining encoder without crtc\n");
+		return;
+	}
+
+	crtc_funcs = crtc->helper_private;
+
+	intel_ddi_disable(encoder);
+
+	intel_ddi_pll_mode_set(crtc);
+	intel_ddi_enable_dp_port(intel_encoder);
+	intel_ddi_enable_pipe(intel_encoder);
+	(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_ON);
+}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e59d676..1feeac5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1813,7 +1813,8 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 static void
 intel_dp_start_link_train(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_encoder *encoder = &intel_dp->base.base;
+	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
 	int i;
@@ -1822,12 +1823,14 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 	int voltage_tries, loop_tries;
 	uint32_t DP = intel_dp->DP;
 
-	/*
-	 * On CPT we have to enable the port in training pattern 1, which
-	 * will happen below in intel_dp_set_link_train.  Otherwise, enable
-	 * the port and wait for it to become active.
-	 */
-	if (!HAS_PCH_CPT(dev)) {
+	if (IS_HASWELL(dev)) {
+		intel_ddi_prepare_link_retrain(encoder);
+	} else if (!HAS_PCH_CPT(dev)) {
+		/*
+		 * On CPT we have to enable the port in training pattern 1,
+		 * which will happen below in intel_dp_set_link_train.
+		 * Otherwise, enable the port and wait for it to become active.
+		 */
 		I915_WRITE(intel_dp->output_reg, intel_dp->DP);
 		POSTING_READ(intel_dp->output_reg);
 		intel_wait_for_vblank(dev, intel_crtc->pipe);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f3f5b83..a8ef8ca 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -535,5 +535,6 @@ extern void intel_ddi_mode_set(struct drm_encoder *encoder,
 extern void intel_ddi_pll_init(struct drm_device *dev);
 extern void intel_ddi_disable(struct drm_encoder *encoder);
 extern void intel_ddi_commit(struct drm_encoder *encoder);
+extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.11.2

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

* [RFC 18/30] drm/i915: add DP support to intel_ddi_disable
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (16 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 17/30] drm/i915: add intel_ddi_prepare_link_retrain Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 19/30] drm/i915: add Haswell DP encoder_helper function definitions Paulo Zanoni
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index ed38bb3..c2377b0 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1054,8 +1054,16 @@ void intel_ddi_disable(struct drm_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
 	struct drm_crtc *crtc = encoder->crtc;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
-	int port = intel_hdmi->ddi_port;
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+	int port;
+
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+		port = intel_hdmi->ddi_port;
+	} else {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+		port = intel_dp->port;
+	}
 
 	if (intel_ddi_port_disabled(dev_priv, port))
 		return;
-- 
1.7.11.2

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

* [RFC 19/30] drm/i915: add Haswell DP encoder_helper function definitions
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (17 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 18/30] drm/i915: add DP support to intel_ddi_disable Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 20/30] drm/i915: add TRANSCODER_EDP Paulo Zanoni
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1feeac5..531d49c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2478,6 +2478,15 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 	kfree(intel_dp);
 }
 
+static const struct drm_encoder_helper_funcs intel_dp_helper_funcs_hsw = {
+	.dpms = intel_dp_dpms,
+	.mode_fixup = intel_dp_mode_fixup,
+	.prepare = intel_dp_prepare,
+	.mode_set = intel_ddi_mode_set,
+	.commit = intel_ddi_commit,
+	.disable = intel_ddi_disable,
+};
+
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
 	.dpms = intel_dp_dpms,
 	.mode_fixup = intel_dp_mode_fixup,
@@ -2613,7 +2622,13 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 
 	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
 			 DRM_MODE_ENCODER_TMDS);
-	drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
+
+	if (IS_HASWELL(dev))
+		drm_encoder_helper_add(&intel_encoder->base,
+				       &intel_dp_helper_funcs_hsw);
+	else
+		drm_encoder_helper_add(&intel_encoder->base,
+				       &intel_dp_helper_funcs);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	drm_sysfs_connector_add(connector);
-- 
1.7.11.2

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

* [RFC 20/30] drm/i915: add TRANSCODER_EDP
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (18 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 19/30] drm/i915: add Haswell DP encoder_helper function definitions Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 21/30] drm/i915: enable eDP on Haswell Paulo Zanoni
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Before Haswell we used to have 3 pipes (A, B and C) and 3 transcoders
(A, B and C), and there was an 1:1 mapping on then. Because of this
mapping, every register that was actually part of the transcoder was
called PIPE_SOMETHING instead of TRANSCODER_SOMETHING and its
definition used the PIPE macro.

Starting from Haswell, we have 3 pipes (A, B and C) but 4 transcoders
(A, B, C and EDP). Transcoder EDP can be connected to any of the 3
pipes, and as its name says, it is used by EDP.

So what we do here is:
  - Create "enum transcoder" just like "enum pipe", but with the
    additional TRANSCODER_EDP definition.
  - Make "enum transcoder" be part of "struct intel_crtc".
  - Create a TRANSCODER macro just like the PIPE macro.
  - Convert the transcoder registers to use the TRANSCODER macro
    instead of the PIPE macro.
  - Create the pipe_to_transcoder function to get the transcoder
    associated to a given pipe.
  - Make the code use the transcoder variable instead of pipe.
  - Correct assign TRANSCODER_EDP when needed.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |   8 +++
 drivers/gpu/drm/i915/i915_irq.c      |   7 ++-
 drivers/gpu/drm/i915/i915_reg.h      |  47 ++++++++--------
 drivers/gpu/drm/i915/intel_ddi.c     |  10 ++--
 drivers/gpu/drm/i915/intel_display.c | 104 +++++++++++++++++++++++------------
 drivers/gpu/drm/i915/intel_dp.c      |   9 +--
 drivers/gpu/drm/i915/intel_drv.h     |   3 +
 7 files changed, 119 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f5bbd1a..ceef8f5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -58,6 +58,14 @@ enum pipe {
 };
 #define pipe_name(p) ((p) + 'A')
 
+enum transcoder {
+	TRANSCODER_A = 0,
+	TRANSCODER_B,
+	TRANSCODER_C,
+	TRANSCODER_EDP = 0xF,
+};
+#define transcoder_name(t) ((t) + 'A')
+
 enum plane {
 	PLANE_A = 0,
 	PLANE_B,
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 0c8cb7f..d67d7eb 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -123,7 +123,9 @@ static int
 i915_pipe_enabled(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	return I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE;
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
+
+	return I915_READ(PIPECONF(transcoder)) & PIPECONF_ENABLE;
 }
 
 /* Called from drm generic code, passed a 'crtc', which
@@ -179,6 +181,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
 			     int *vpos, int *hpos)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 	u32 vbl = 0, position = 0;
 	int vbl_start, vbl_end, htotal, vtotal;
 	bool in_vbl = true;
@@ -211,7 +214,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
 		 */
 		position = (I915_READ(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT;
 
-		htotal = 1 + ((I915_READ(HTOTAL(pipe)) >> 16) & 0x1fff);
+		htotal = 1 + ((I915_READ(HTOTAL(transcoder)) >> 16) & 0x1fff);
 		*vpos = position / htotal;
 		*hpos = position - (*vpos * htotal);
 	}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 9c9f288..4bf4cc9 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -29,6 +29,8 @@
 
 #define _PORT(port, a, b) ((a) + (port)*((b)-(a)))
 
+#define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a)))
+
 #define _MASKED_BIT_ENABLE(a) (((a) << 16) | (a))
 #define _MASKED_BIT_DISABLE(a) ((a) << 16)
 
@@ -1550,15 +1552,14 @@
 #define _BCLRPAT_B	0x61020
 #define _VSYNCSHIFT_B	0x61028
 
-
-#define HTOTAL(pipe) _PIPE(pipe, _HTOTAL_A, _HTOTAL_B)
-#define HBLANK(pipe) _PIPE(pipe, _HBLANK_A, _HBLANK_B)
-#define HSYNC(pipe) _PIPE(pipe, _HSYNC_A, _HSYNC_B)
-#define VTOTAL(pipe) _PIPE(pipe, _VTOTAL_A, _VTOTAL_B)
-#define VBLANK(pipe) _PIPE(pipe, _VBLANK_A, _VBLANK_B)
-#define VSYNC(pipe) _PIPE(pipe, _VSYNC_A, _VSYNC_B)
-#define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
-#define VSYNCSHIFT(pipe) _PIPE(pipe, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
+#define HTOTAL(tran)	_TRANSCODER(tran, _HTOTAL_A, _HTOTAL_B)
+#define HBLANK(tran)	_TRANSCODER(tran, _HBLANK_A, _HBLANK_B)
+#define HSYNC(tran)	_TRANSCODER(tran, _HSYNC_A, _HSYNC_B)
+#define VTOTAL(tran)	_TRANSCODER(tran, _VTOTAL_A, _VTOTAL_B)
+#define VBLANK(tran)	_TRANSCODER(tran, _VBLANK_A, _VBLANK_B)
+#define VSYNC(tran)	_TRANSCODER(tran, _VSYNC_A, _VSYNC_B)
+#define BCLRPAT(pipe)	_PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
+#define VSYNCSHIFT(tran) _TRANSCODER(tran, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
 
 /* VGA port control */
 #define ADPA			0x61100
@@ -2707,7 +2708,7 @@
 #define   PIPE_12BPC				(3 << 5)
 
 #define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC)
-#define PIPECONF(pipe) _PIPE(pipe, _PIPEACONF, _PIPEBCONF)
+#define PIPECONF(tran) _TRANSCODER(tran, _PIPEACONF, _PIPEBCONF)
 #define PIPEDSL(pipe)  _PIPE(pipe, _PIPEADSL, _PIPEBDSL)
 #define PIPEFRAME(pipe) _PIPE(pipe, _PIPEAFRAMEHIGH, _PIPEBFRAMEHIGH)
 #define PIPEFRAMEPIXEL(pipe)  _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL)
@@ -3297,14 +3298,14 @@
 #define _PIPEB_LINK_M2           0x61048
 #define _PIPEB_LINK_N2           0x6104c
 
-#define PIPE_DATA_M1(pipe) _PIPE(pipe, _PIPEA_DATA_M1, _PIPEB_DATA_M1)
-#define PIPE_DATA_N1(pipe) _PIPE(pipe, _PIPEA_DATA_N1, _PIPEB_DATA_N1)
-#define PIPE_DATA_M2(pipe) _PIPE(pipe, _PIPEA_DATA_M2, _PIPEB_DATA_M2)
-#define PIPE_DATA_N2(pipe) _PIPE(pipe, _PIPEA_DATA_N2, _PIPEB_DATA_N2)
-#define PIPE_LINK_M1(pipe) _PIPE(pipe, _PIPEA_LINK_M1, _PIPEB_LINK_M1)
-#define PIPE_LINK_N1(pipe) _PIPE(pipe, _PIPEA_LINK_N1, _PIPEB_LINK_N1)
-#define PIPE_LINK_M2(pipe) _PIPE(pipe, _PIPEA_LINK_M2, _PIPEB_LINK_M2)
-#define PIPE_LINK_N2(pipe) _PIPE(pipe, _PIPEA_LINK_N2, _PIPEB_LINK_N2)
+#define PIPE_DATA_M1(tran) _TRANSCODER(tran, _PIPEA_DATA_M1, _PIPEB_DATA_M1)
+#define PIPE_DATA_N1(tran) _TRANSCODER(tran, _PIPEA_DATA_N1, _PIPEB_DATA_N1)
+#define PIPE_DATA_M2(tran) _TRANSCODER(tran, _PIPEA_DATA_M2, _PIPEB_DATA_M2)
+#define PIPE_DATA_N2(tran) _TRANSCODER(tran, _PIPEA_DATA_N2, _PIPEB_DATA_N2)
+#define PIPE_LINK_M1(tran) _TRANSCODER(tran, _PIPEA_LINK_M1, _PIPEB_LINK_M1)
+#define PIPE_LINK_N1(tran) _TRANSCODER(tran, _PIPEA_LINK_N1, _PIPEB_LINK_N1)
+#define PIPE_LINK_M2(tran) _TRANSCODER(tran, _PIPEA_LINK_M2, _PIPEB_LINK_M2)
+#define PIPE_LINK_N2(tran) _TRANSCODER(tran, _PIPEA_LINK_N2, _PIPEB_LINK_N2)
 
 /* CPU panel fitter */
 /* IVB+ has 3 fitters, 0 is 7x5 capable, the other two only 3x3 */
@@ -3724,8 +3725,8 @@
 #define HSW_VIDEO_DIP_VSC_ECC_B		0x61344
 #define HSW_VIDEO_DIP_GCP_B		0x61210
 
-#define HSW_TVIDEO_DIP_CTL(pipe) \
-	 _PIPE(pipe, HSW_VIDEO_DIP_CTL_A, HSW_VIDEO_DIP_CTL_B)
+#define HSW_TVIDEO_DIP_CTL(tran) \
+	 _TRANSCODER(tran, HSW_VIDEO_DIP_CTL_A, HSW_VIDEO_DIP_CTL_B)
 #define HSW_TVIDEO_DIP_AVI_DATA(pipe) \
 	 _PIPE(pipe, HSW_VIDEO_DIP_AVI_DATA_A, HSW_VIDEO_DIP_AVI_DATA_B)
 #define HSW_TVIDEO_DIP_SPD_DATA(pipe) \
@@ -4378,8 +4379,8 @@
 #define PIPE_DDI_FUNC_CTL_B		0x61400
 #define PIPE_DDI_FUNC_CTL_C		0x62400
 #define PIPE_DDI_FUNC_CTL_EDP		0x6F400
-#define DDI_FUNC_CTL(pipe) _PIPE(pipe, PIPE_DDI_FUNC_CTL_A, \
-				       PIPE_DDI_FUNC_CTL_B)
+#define DDI_FUNC_CTL(tran) _TRANSCODER(tran, PIPE_DDI_FUNC_CTL_A, \
+					     PIPE_DDI_FUNC_CTL_B)
 #define  PIPE_DDI_FUNC_ENABLE		(1<<31)
 /* Those bits are ignored by pipe EDP since it can only connect to DDI A */
 #define  PIPE_DDI_PORT_MASK		(7<<28)
@@ -4528,7 +4529,7 @@
 
 #define _PIPEA_MSA_MISC			0x60410
 #define _PIPEB_MSA_MISC			0x61410
-#define PIPE_MSA_MISC(pipe) _PIPE(pipe, _PIPEA_MSA_MISC, _PIPEB_MSA_MISC)
+#define PIPE_MSA_MISC(tran) _TRANSCODER(tran, _PIPEA_MSA_MISC, _PIPEB_MSA_MISC)
 #define  PIPE_MSA_SYNC_CLK		(1<<0)
 #define  PIPE_MSA_6_BPC			(0<<5)
 #define  PIPE_MSA_8_BPC			(1<<5)
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index c2377b0..ad1fb5f 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -797,6 +797,7 @@ static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder)
 	struct drm_display_mode *mode = &crtc->mode;
 	int port;
 	int pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	u32 func_val, msa_val;
 	struct intel_hdmi *intel_hdmi = NULL;
 	struct intel_dp *intel_dp = NULL;
@@ -864,10 +865,10 @@ static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder)
 			     intel_dp->lane_count);
 		}
 
-		I915_WRITE(PIPE_MSA_MISC(pipe), msa_val);
+		I915_WRITE(PIPE_MSA_MISC(transcoder), msa_val);
 	}
 
-	I915_WRITE(DDI_FUNC_CTL(pipe), func_val);
+	I915_WRITE(DDI_FUNC_CTL(transcoder), func_val);
 
 	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
 		if (intel_hdmi->has_audio) {
@@ -988,12 +989,13 @@ void intel_ddi_commit(struct drm_encoder *encoder)
 static void intel_ddi_disable_pipe(struct drm_i915_private *dev_priv,
 				   enum pipe pipe)
 {
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 	uint32_t temp;
 
-	temp = I915_READ(DDI_FUNC_CTL(pipe));
+	temp = I915_READ(DDI_FUNC_CTL(transcoder));
 	temp &= ~(PIPE_DDI_FUNC_ENABLE | PIPE_DDI_PORT_MASK);
 	temp |= PIPE_DDI_PORT_NONE;
-	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+	I915_WRITE(DDI_FUNC_CTL(transcoder), temp);
 
 	I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_DISABLED);
 }
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 986d790..c7ba7ad 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -927,6 +927,15 @@ intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
 	return true;
 }
 
+enum transcoder pipe_to_transcoder(struct drm_i915_private *dev_priv,
+				   enum pipe pipe)
+{
+	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	return intel_crtc->transcoder;
+}
+
 static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -999,9 +1008,10 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
 void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 
 	if (INTEL_INFO(dev)->gen >= 4) {
-		int reg = PIPECONF(pipe);
+		int reg = PIPECONF(transcoder);
 
 		/* Wait for the Pipe State to go off */
 		if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0,
@@ -1100,13 +1110,14 @@ static void assert_pch_pll(struct drm_i915_private *dev_priv,
 static void assert_fdi_tx(struct drm_i915_private *dev_priv,
 			  enum pipe pipe, bool state)
 {
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 	int reg;
 	u32 val;
 	bool cur_state;
 
 	if (IS_HASWELL(dev_priv->dev)) {
 		/* On Haswell, DDI is used instead of FDI_TX_CTL */
-		reg = DDI_FUNC_CTL(pipe);
+		reg = DDI_FUNC_CTL(transcoder);
 		val = I915_READ(reg);
 		cur_state = !!(val & PIPE_DDI_FUNC_ENABLE);
 	} else {
@@ -1209,6 +1220,7 @@ static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
 void assert_pipe(struct drm_i915_private *dev_priv,
 		 enum pipe pipe, bool state)
 {
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 	int reg;
 	u32 val;
 	bool cur_state;
@@ -1217,7 +1229,7 @@ void assert_pipe(struct drm_i915_private *dev_priv,
 	if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
 		state = true;
 
-	reg = PIPECONF(pipe);
+	reg = PIPECONF(transcoder);
 	val = I915_READ(reg);
 	cur_state = !!(val & PIPECONF_ENABLE);
 	WARN(cur_state != state,
@@ -1649,6 +1661,7 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
 	int reg;
 	u32 val, pipeconf_val;
 	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 
 	/* PCH only available on ILK+ */
 	BUG_ON(dev_priv->info->gen < 5);
@@ -1668,7 +1681,7 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
 	}
 	reg = TRANSCONF(pipe);
 	val = I915_READ(reg);
-	pipeconf_val = I915_READ(PIPECONF(pipe));
+	pipeconf_val = I915_READ(PIPECONF(transcoder));
 
 	if (HAS_PCH_IBX(dev_priv->dev)) {
 		/*
@@ -1733,6 +1746,7 @@ static void intel_disable_transcoder(struct drm_i915_private *dev_priv,
 static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 			      bool pch_port)
 {
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 	int reg;
 	u32 val;
 
@@ -1752,7 +1766,7 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 		/* FIXME: assert CPU port conditions for SNB+ */
 	}
 
-	reg = PIPECONF(pipe);
+	reg = PIPECONF(transcoder);
 	val = I915_READ(reg);
 	if (val & PIPECONF_ENABLE)
 		return;
@@ -1775,6 +1789,7 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
  */
 void intel_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 	int reg;
 	u32 val;
 
@@ -1788,7 +1803,7 @@ void intel_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 	if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
 		return;
 
-	reg = PIPECONF(pipe);
+	reg = PIPECONF(transcoder);
 	val = I915_READ(reg);
 	if ((val & PIPECONF_ENABLE) == 0)
 		return;
@@ -2713,6 +2728,7 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
 	struct drm_device *dev = intel_crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	u32 reg, temp;
 
 	/* Write the TU size bits so error detection works */
@@ -2724,7 +2740,7 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
 	temp = I915_READ(reg);
 	temp &= ~((0x7 << 19) | (0x7 << 16));
 	temp |= (intel_crtc->fdi_lanes - 1) << 19;
-	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+	temp |= (I915_READ(PIPECONF(transcoder)) & PIPE_BPC_MASK) << 11;
 	I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE);
 
 	POSTING_READ(reg);
@@ -2798,6 +2814,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	u32 reg, temp;
 
 	/* disable CPU FDI tx and PCH FDI rx */
@@ -2809,7 +2826,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
 	reg = FDI_RX_CTL(pipe);
 	temp = I915_READ(reg);
 	temp &= ~(0x7 << 16);
-	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+	temp |= (I915_READ(PIPECONF(transcoder)) & PIPE_BPC_MASK) << 11;
 	I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
 
 	POSTING_READ(reg);
@@ -2843,7 +2860,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
 	}
 	/* BPC in FDI rx is consistent with that in PIPECONF */
 	temp &= ~(0x07 << 16);
-	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+	temp |= (I915_READ(PIPECONF(transcoder)) & PIPE_BPC_MASK) << 11;
 	I915_WRITE(reg, temp);
 
 	POSTING_READ(reg);
@@ -3005,6 +3022,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	u32 reg, temp;
 
 	assert_transcoder_disabled(dev_priv, pipe);
@@ -3045,14 +3063,14 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 
 	/* set transcoder timing, panel must allow it */
 	assert_panel_unlocked(dev_priv, pipe);
-	I915_WRITE(TRANS_HTOTAL(pipe), I915_READ(HTOTAL(pipe)));
-	I915_WRITE(TRANS_HBLANK(pipe), I915_READ(HBLANK(pipe)));
-	I915_WRITE(TRANS_HSYNC(pipe),  I915_READ(HSYNC(pipe)));
+	I915_WRITE(TRANS_HTOTAL(pipe), I915_READ(HTOTAL(transcoder)));
+	I915_WRITE(TRANS_HBLANK(pipe), I915_READ(HBLANK(transcoder)));
+	I915_WRITE(TRANS_HSYNC(pipe),  I915_READ(HSYNC(transcoder)));
 
-	I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(pipe)));
-	I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe)));
-	I915_WRITE(TRANS_VSYNC(pipe),  I915_READ(VSYNC(pipe)));
-	I915_WRITE(TRANS_VSYNCSHIFT(pipe),  I915_READ(VSYNCSHIFT(pipe)));
+	I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(transcoder)));
+	I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(transcoder)));
+	I915_WRITE(TRANS_VSYNC(pipe),  I915_READ(VSYNC(transcoder)));
+	I915_WRITE(TRANS_VSYNCSHIFT(pipe), I915_READ(VSYNCSHIFT(transcoder)));
 
 	if (!IS_HASWELL(dev))
 		intel_fdi_normal_train(crtc);
@@ -3061,7 +3079,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 	if (HAS_PCH_CPT(dev) &&
 	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
 	     intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
-		u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
+		u32 bpc = (I915_READ(PIPECONF(transcoder)) & PIPE_BPC_MASK) >> 5;
 		reg = TRANS_DP_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~(TRANS_DP_PORT_SEL_MASK |
@@ -4579,6 +4597,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
+	enum transcoder transcoder;
 	int refclk, num_connectors = 0;
 	intel_clock_t clock, reduced_clock;
 	u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf;
@@ -4627,10 +4646,17 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		num_connectors++;
 	}
 
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev)) {
 		if (!intel_ddi_pll_mode_set(crtc))
 			return -EINVAL;
 
+		if (is_cpu_edp)
+			intel_crtc->transcoder = TRANSCODER_EDP;
+		else
+			intel_crtc->transcoder = pipe;
+	}
+	transcoder = intel_crtc->transcoder;
+
 	refclk = ironlake_get_refclk(crtc);
 
 	/*
@@ -4694,7 +4720,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		target_clock = adjusted_mode->clock;
 
 	/* determine panel color depth */
-	temp = I915_READ(PIPECONF(pipe));
+	temp = I915_READ(PIPECONF(transcoder));
 	temp &= ~PIPE_BPC_MASK;
 	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
 	switch (pipe_bpp) {
@@ -4719,7 +4745,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	}
 
 	intel_crtc->bpp = pipe_bpp;
-	I915_WRITE(PIPECONF(pipe), temp);
+	I915_WRITE(PIPECONF(transcoder), temp);
 
 	if (!lane) {
 		/*
@@ -4804,7 +4830,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		dpll |= PLL_REF_INPUT_DREFCLK;
 
 	/* setup pipeconf */
-	pipeconf = I915_READ(PIPECONF(pipe));
+	pipeconf = I915_READ(PIPECONF(transcoder));
 
 	/* Set up the display plane register */
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -4915,31 +4941,31 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		/* the chip adds 2 halflines automatically */
 		adjusted_mode->crtc_vtotal -= 1;
 		adjusted_mode->crtc_vblank_end -= 1;
-		I915_WRITE(VSYNCSHIFT(pipe),
+		I915_WRITE(VSYNCSHIFT(transcoder),
 			   adjusted_mode->crtc_hsync_start
 			   - adjusted_mode->crtc_htotal/2);
 	} else {
 		pipeconf |= PIPECONF_PROGRESSIVE;
-		I915_WRITE(VSYNCSHIFT(pipe), 0);
+		I915_WRITE(VSYNCSHIFT(transcoder), 0);
 	}
 
-	I915_WRITE(HTOTAL(pipe),
+	I915_WRITE(HTOTAL(transcoder),
 		   (adjusted_mode->crtc_hdisplay - 1) |
 		   ((adjusted_mode->crtc_htotal - 1) << 16));
-	I915_WRITE(HBLANK(pipe),
+	I915_WRITE(HBLANK(transcoder),
 		   (adjusted_mode->crtc_hblank_start - 1) |
 		   ((adjusted_mode->crtc_hblank_end - 1) << 16));
-	I915_WRITE(HSYNC(pipe),
+	I915_WRITE(HSYNC(transcoder),
 		   (adjusted_mode->crtc_hsync_start - 1) |
 		   ((adjusted_mode->crtc_hsync_end - 1) << 16));
 
-	I915_WRITE(VTOTAL(pipe),
+	I915_WRITE(VTOTAL(transcoder),
 		   (adjusted_mode->crtc_vdisplay - 1) |
 		   ((adjusted_mode->crtc_vtotal - 1) << 16));
-	I915_WRITE(VBLANK(pipe),
+	I915_WRITE(VBLANK(transcoder),
 		   (adjusted_mode->crtc_vblank_start - 1) |
 		   ((adjusted_mode->crtc_vblank_end - 1) << 16));
-	I915_WRITE(VSYNC(pipe),
+	I915_WRITE(VSYNC(transcoder),
 		   (adjusted_mode->crtc_vsync_start - 1) |
 		   ((adjusted_mode->crtc_vsync_end - 1) << 16));
 
@@ -4959,8 +4985,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	if (is_cpu_edp)
 		ironlake_set_pll_edp(crtc, adjusted_mode->clock);
 
-	I915_WRITE(PIPECONF(pipe), pipeconf);
-	POSTING_READ(PIPECONF(pipe));
+	I915_WRITE(PIPECONF(transcoder), pipeconf);
+	POSTING_READ(PIPECONF(transcoder));
 
 	intel_wait_for_vblank(dev, pipe);
 
@@ -5911,12 +5937,12 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	struct drm_display_mode *mode;
-	int htot = I915_READ(HTOTAL(pipe));
-	int hsync = I915_READ(HSYNC(pipe));
-	int vtot = I915_READ(VTOTAL(pipe));
-	int vsync = I915_READ(VSYNC(pipe));
+	int htot = I915_READ(HTOTAL(transcoder));
+	int hsync = I915_READ(HSYNC(transcoder));
+	int vtot = I915_READ(VTOTAL(transcoder));
+	int vsync = I915_READ(VSYNC(transcoder));
 
 	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
 	if (!mode)
@@ -6539,6 +6565,11 @@ static void intel_sanitize_modesetting(struct drm_device *dev,
 		reg = PIPECONF(i);
 		I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
 	}
+	if (IS_HASWELL(dev)) {
+		reg = PIPECONF(TRANSCODER_EDP);
+		I915_WRITE(reg,
+			   I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+	}
 
 	if (HAS_PCH_SPLIT(dev))
 		return;
@@ -6651,6 +6682,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	/* Swap pipes & planes for FBC on pre-965 */
 	intel_crtc->pipe = pipe;
 	intel_crtc->plane = pipe;
+	intel_crtc->transcoder = pipe;
 	if (IS_MOBILE(dev) && IS_GEN3(dev)) {
 		DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
 		intel_crtc->plane = !pipe;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 531d49c..11c7d08 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -787,6 +787,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	int lane_count = 4;
 	struct intel_dp_m_n m_n;
 	int pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 
 	/*
 	 * Find the lane count in the intel_encoder private
@@ -811,12 +812,12 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 			     mode->clock, adjusted_mode->clock, &m_n);
 
 	if (IS_HASWELL(dev)) {
-		I915_WRITE(PIPE_DATA_M1(pipe),
+		I915_WRITE(PIPE_DATA_M1(transcoder),
 			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
 			   m_n.gmch_m);
-		I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n);
-		I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m);
-		I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
+		I915_WRITE(PIPE_DATA_N1(transcoder), m_n.gmch_n);
+		I915_WRITE(PIPE_LINK_M1(transcoder), m_n.link_m);
+		I915_WRITE(PIPE_LINK_N1(transcoder), m_n.link_n);
 	} else if (HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(TRANSDATA_M1(pipe),
 			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a8ef8ca..01173d4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -153,6 +153,7 @@ struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
 	enum plane plane;
+	enum transcoder transcoder;
 	u8 lut_r[256], lut_g[256], lut_b[256];
 	int dpms_mode;
 	bool active; /* is the crtc on? independent of the dpms mode */
@@ -435,6 +436,8 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 						    struct drm_crtc *crtc);
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
+extern enum transcoder pipe_to_transcoder(struct drm_i915_private *dev_priv,
+					  enum pipe pipe);
 extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
 extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
 
-- 
1.7.11.2

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

* [RFC 21/30] drm/i915: enable eDP on Haswell
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (19 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 20/30] drm/i915: add TRANSCODER_EDP Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 22/30] drm/i915: don't run PCH code on non-PCH ports Paulo Zanoni
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h  |  3 +++
 drivers/gpu/drm/i915/intel_ddi.c | 20 ++++++++++++++++++--
 drivers/gpu/drm/i915/intel_dp.c  |  2 +-
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 4bf4cc9..56f8617 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4399,6 +4399,9 @@
 #define  PIPE_DDI_BPC_12		(3<<20)
 #define  PIPE_DDI_PVSYNC		(1<<17)
 #define  PIPE_DDI_PHSYNC		(1<<16)
+#define  PIPE_DDI_INPUT_A_ONOFF		(4<<12)
+#define  PIPE_DDI_INPUT_B_ONOFF		(5<<12)
+#define  PIPE_DDI_INPUT_C_ONOFF		(6<<12)
 #define  PIPE_DDI_BFI_ENABLE		(1<<4)
 #define  PIPE_DDI_PORT_WIDTH_X1		(0<<1)
 #define  PIPE_DDI_PORT_WIDTH_X2		(1<<1)
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index ad1fb5f..44bf9e6 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -236,6 +236,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 	case PORT_A:
 		/* We don't handle eDP and DP yet */
 		DRM_DEBUG_DRIVER("Found digital output on DDI port A\n");
+		intel_dp_init(dev, DDI_BUF_CTL_A, PORT_A);
 		break;
 	/* Assume that the  ports B, C and D are working in HDMI mode for now */
 	case PORT_B:
@@ -655,6 +656,7 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
 		switch (intel_encoder->type) {
 		case INTEL_OUTPUT_DISPLAYPORT:
+		case INTEL_OUTPUT_EDP:
 			is_dp = true;
 			intel_dp = enc_to_intel_dp(&intel_encoder->base);
 			port = intel_dp->port;
@@ -810,7 +812,8 @@ static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder)
 		port = intel_dp->port;
 	}
 
-	I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_PORT(port));
+	if (transcoder != TRANSCODER_EDP)
+		I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_PORT(port));
 
 	func_val = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
 	msa_val = PIPE_MSA_SYNC_CLK;
@@ -842,6 +845,18 @@ static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder)
 	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
 		func_val |= PIPE_DDI_PHSYNC;
 
+	switch (pipe) {
+	case PIPE_A:
+		func_val |= PIPE_DDI_INPUT_A_ONOFF;
+		break;
+	case PIPE_B:
+		func_val |= PIPE_DDI_INPUT_B_ONOFF;
+		break;
+	case PIPE_C:
+		func_val |= PIPE_DDI_INPUT_C_ONOFF;
+		break;
+	}
+
 	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
 		if (intel_hdmi->has_hdmi_sink)
 			func_val |= PIPE_DDI_MODE_SELECT_HDMI;
@@ -997,7 +1012,8 @@ static void intel_ddi_disable_pipe(struct drm_i915_private *dev_priv,
 	temp |= PIPE_DDI_PORT_NONE;
 	I915_WRITE(DDI_FUNC_CTL(transcoder), temp);
 
-	I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_DISABLED);
+	if (transcoder != TRANSCODER_EDP)
+		I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_DISABLED);
 }
 
 static void intel_ddi_disable_port(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 11c7d08..afee975 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -384,7 +384,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	 * clock divider.
 	 */
 	if (is_cpu_edp(intel_dp)) {
-		if (IS_GEN6(dev) || IS_GEN7(dev))
+		if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_HASWELL(dev))
 			aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
 		else
 			aux_clock_divider = 225; /* eDP input clock at 450Mhz */
-- 
1.7.11.2

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

* [RFC 22/30] drm/i915: don't run PCH code on non-PCH ports
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (20 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 21/30] drm/i915: enable eDP on Haswell Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 23/30] drm/i915: init DP on port B Paulo Zanoni
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

This should fix the FDI assertions we're getting on Haswell.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c7ba7ad..4aa2c1d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3289,10 +3289,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	u32 reg, temp;
+	bool is_pch_port;
 
 	if (!intel_crtc->active)
 		return;
 
+	is_pch_port = intel_crtc_driving_pch(crtc);
+
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
@@ -3310,14 +3313,17 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
 	ironlake_fdi_disable(crtc);
 
-	/* This is a horrible layering violation; we should be doing this in
-	 * the connector/encoder ->prepare instead, but we don't always have
-	 * enough information there about the config to know whether it will
-	 * actually be necessary or just cause undesired flicker.
-	 */
-	intel_disable_pch_ports(dev_priv, pipe);
+	if (is_pch_port) {
+		/* This is a horrible layering violation; we should be doing
+		 * this in the connector/encoder ->prepare instead, but we don't
+		 * always have enough information there about the config to know
+		 * whether it will actually be necessary or just cause undesired
+		 * flicker.
+		 */
+		intel_disable_pch_ports(dev_priv, pipe);
 
-	intel_disable_transcoder(dev_priv, pipe);
+		intel_disable_transcoder(dev_priv, pipe);
+	}
 
 	if (HAS_PCH_CPT(dev)) {
 		/* disable TRANS_DP_CTL */
-- 
1.7.11.2

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

* [RFC 23/30] drm/i915: init DP on port B
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (21 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 22/30] drm/i915: don't run PCH code on non-PCH ports Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 24/30] drm/i915: simplify assignments inside intel_dp.c Paulo Zanoni
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

This is just for testing purposes. We need to properly detect if the
monitor connected on the port is actually DP or HDMI.

Not-signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 44bf9e6..055a1e8 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -240,6 +240,8 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 		break;
 	/* Assume that the  ports B, C and D are working in HDMI mode for now */
 	case PORT_B:
+		intel_dp_init(dev, DDI_BUF_CTL(port), port);
+		break;
 	case PORT_C:
 	case PORT_D:
 		intel_hdmi_init(dev, DDI_BUF_CTL(port), port);
-- 
1.7.11.2

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

* [RFC 24/30] drm/i915: simplify assignments inside intel_dp.c
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (22 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 23/30] drm/i915: init DP on port B Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 25/30] drm/i915: add intel_dp_to_dev and intel_hdmi_to_dev Paulo Zanoni
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Replace container_of with enc_to_intel_dp.
Walk through less structures when making assignments.
Rename some variables to keep our naming standards.

As a bonus, this will reduce the usage of "struct intel_dp", making
the future patch that introduces intel_digital_port smaller and easier
to review.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 43 +++++++++++++++++++++--------------------
 1 file changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index afee975..de9e54e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -78,8 +78,7 @@ static bool is_cpu_edp(struct intel_dp *intel_dp)
 
 static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
 {
-	return container_of(intel_attached_encoder(connector),
-			    struct intel_dp, base);
+	return enc_to_intel_dp(&intel_attached_encoder(connector)->base);
 }
 
 /**
@@ -109,7 +108,7 @@ void
 intel_edp_link_config(struct intel_encoder *intel_encoder,
 		       int *lane_num, int *link_bw)
 {
-	struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
 
 	*lane_num = intel_dp->lane_count;
 	if (intel_dp->link_bw == DP_LINK_BW_1_62)
@@ -122,7 +121,7 @@ int
 intel_edp_target_clock(struct intel_encoder *intel_encoder,
 		       struct drm_display_mode *mode)
 {
-	struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
 
 	if (intel_dp->panel_fixed_mode)
 		return intel_dp->panel_fixed_mode->clock;
@@ -781,7 +780,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = crtc->dev;
-	struct intel_encoder *encoder;
+	struct intel_encoder *intel_encoder;
+	struct intel_dp *intel_dp;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int lane_count = 4;
@@ -792,11 +792,11 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	/*
 	 * Find the lane count in the intel_encoder private
 	 */
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		intel_dp = enc_to_intel_dp(&intel_encoder->base);
 
-		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
-		    intel_dp->base.type == INTEL_OUTPUT_EDP)
+		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+		    intel_encoder->type == INTEL_OUTPUT_EDP)
 		{
 			lane_count = intel_dp->lane_count;
 			break;
@@ -860,7 +860,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-	struct drm_crtc *crtc = intel_dp->base.base.crtc;
+	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
 	/* Turn on the eDP PLL if needed */
@@ -1301,7 +1301,7 @@ void intel_dp_commit(struct drm_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct drm_device *dev = encoder->dev;
-	struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 
 	ironlake_edp_panel_vdd_on(intel_dp);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
@@ -2297,7 +2297,7 @@ static enum drm_connector_status
 intel_dp_detect(struct drm_connector *connector, bool force)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = connector->dev;
 	enum drm_connector_status status;
 	struct edid *edid = NULL;
 
@@ -2335,7 +2335,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 static int intel_dp_get_modes(struct drm_connector *connector)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
@@ -2517,7 +2517,7 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = {
 static void
 intel_dp_hot_plug(struct intel_encoder *intel_encoder)
 {
-	struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
 
 	intel_dp_check_link_status(intel_dp);
 }
@@ -2527,13 +2527,14 @@ int
 intel_trans_dp_port_sel(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-	struct intel_encoder *encoder;
+	struct intel_encoder *intel_encoder;
+	struct intel_dp *intel_dp;
 
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		intel_dp = enc_to_intel_dp(&intel_encoder->base);
 
-		if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
-		    intel_dp->base.type == INTEL_OUTPUT_EDP)
+		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+		    intel_encoder->type == INTEL_OUTPUT_EDP)
 			return intel_dp->output_reg;
 	}
 
@@ -2671,7 +2672,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 
 		if (!pp_on || !pp_off || !pp_div) {
 			DRM_INFO("bad panel power sequencing delays, disabling panel\n");
-			intel_dp_encoder_destroy(&intel_dp->base.base);
+			intel_dp_encoder_destroy(&intel_encoder->base);
 			intel_dp_destroy(&intel_connector->base);
 			return;
 		}
@@ -2727,7 +2728,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 		} else {
 			/* if this fails, presume the device is a ghost */
 			DRM_INFO("failed to retrieve link info, disabling eDP\n");
-			intel_dp_encoder_destroy(&intel_dp->base.base);
+			intel_dp_encoder_destroy(&intel_encoder->base);
 			intel_dp_destroy(&intel_connector->base);
 			return;
 		}
-- 
1.7.11.2

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

* [RFC 25/30] drm/i915: add intel_dp_to_dev and intel_hdmi_to_dev
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (23 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 24/30] drm/i915: simplify assignments inside intel_dp.c Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 26/30] drm/i915: create intel_digital_port and use it Paulo Zanoni
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

When we add struct intel_digital_port, there will be no direct way of
going from intel_{dp,hdmi} to drm_device: we will need to call
container_of().

This patch adds functions to go from intel_{dp,hdmi} to drm_device.
The main goal here is to greatly reduce the size of the next patch,
where we will change the implementation of the functions just added
here.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c   | 44 ++++++++++++++++++++++-----------------
 drivers/gpu/drm/i915/intel_hdmi.c |  9 ++++++--
 2 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index de9e54e..ffe61a8 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -76,6 +76,11 @@ static bool is_cpu_edp(struct intel_dp *intel_dp)
 	return is_edp(intel_dp) && !is_pch_edp(intel_dp);
 }
 
+static struct drm_device *intel_dp_to_dev(struct intel_dp *intel_dp)
+{
+	return intel_dp->base.base.dev;
+}
+
 static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
 {
 	return enc_to_intel_dp(&intel_attached_encoder(connector)->base);
@@ -304,7 +309,7 @@ intel_hrawclk(struct drm_device *dev)
 
 static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	return (I915_READ(PCH_PP_STATUS) & PP_ON) != 0;
@@ -312,7 +317,7 @@ static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
 
 static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	return (I915_READ(PCH_PP_CONTROL) & EDP_FORCE_VDD) != 0;
@@ -321,7 +326,7 @@ static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
 static void
 intel_dp_check_edp(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (!is_edp(intel_dp))
@@ -340,7 +345,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 		uint8_t *recv, int recv_size)
 {
 	uint32_t output_reg = intel_dp->output_reg;
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t ch_ctl = output_reg + 0x10;
 	uint32_t ch_data = ch_ctl + 4;
@@ -979,7 +984,7 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
 				       u32 mask,
 				       u32 value)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
@@ -1028,7 +1033,7 @@ static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv)
 
 static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
@@ -1067,7 +1072,7 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 
 static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
@@ -1089,7 +1094,7 @@ static void ironlake_panel_vdd_work(struct work_struct *__work)
 {
 	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
 						 struct intel_dp, panel_vdd_work);
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
 	mutex_lock(&dev->mode_config.mutex);
 	ironlake_panel_vdd_off_sync(intel_dp);
@@ -1121,7 +1126,7 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 
 static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
@@ -1163,7 +1168,7 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 
 static void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
@@ -1188,7 +1193,7 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 
 static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
@@ -1211,7 +1216,7 @@ static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 
 static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
@@ -1443,7 +1448,7 @@ static char	*link_train_names[] = {
 static uint8_t
 intel_dp_voltage_max(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
 	if (IS_GEN7(dev) && is_cpu_edp(intel_dp))
 		return DP_TRAIN_VOLTAGE_SWING_800;
@@ -1456,7 +1461,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp)
 static uint8_t
 intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
 	if (IS_HASWELL(dev)) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
@@ -1711,7 +1716,7 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 			uint32_t dp_reg_value,
 			uint8_t dp_train_pat)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 	uint32_t temp;
@@ -1925,7 +1930,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 static void
 intel_dp_complete_link_train(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	bool channel_eq = false;
 	int tries, cr_tries;
 	uint32_t DP = intel_dp->DP;
@@ -2004,7 +2009,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 static void
 intel_dp_link_down(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t DP = intel_dp->DP;
 
@@ -2202,11 +2207,12 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 static enum drm_connector_status
 ironlake_dp_detect(struct intel_dp *intel_dp)
 {
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	enum drm_connector_status status;
 
 	/* Can't disconnect eDP, but you can close the lid... */
 	if (is_edp(intel_dp)) {
-		status = intel_panel_detect(intel_dp->base.base.dev);
+		status = intel_panel_detect(dev);
 		if (status == connector_status_unknown)
 			status = connector_status_connected;
 		return status;
@@ -2218,7 +2224,7 @@ ironlake_dp_detect(struct intel_dp *intel_dp)
 static enum drm_connector_status
 g4x_dp_detect(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t bit;
 
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index ad58bec..543b1f1 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -37,10 +37,15 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 
+static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)
+{
+	return intel_hdmi->base.base.dev;
+}
+
 static void
 assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
 {
-	struct drm_device *dev = intel_hdmi->base.base.dev;
+	struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t enabled_bits;
 
@@ -693,7 +698,7 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
 
 static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi)
 {
-	struct drm_device *dev = intel_hdmi->base.base.dev;
+	struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t bit;
 
-- 
1.7.11.2

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

* [RFC 26/30] drm/i915: create intel_digital_port and use it
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (24 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 25/30] drm/i915: add intel_dp_to_dev and intel_hdmi_to_dev Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 27/30] drm/i915: remove encoder args from intel_{dp, hdmi}_add_properties Paulo Zanoni
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

The goal is to have one single encoder capable of controlling both DP
and HDMI outputs. This patch just adds the initial infrastructure, no
functional changes.

Previously, both intel_dp and intel_hdmi were intel_encoders. Now,
these 2 structs do not have intel_encoder as members anymore. The new
struct intel_digital_port has intel_encoder as a member, and it also
includes intel_dp and intel_hdmi as members. See the changes inside
intel_drv.h: it's the most important change, everything else is only
to make it compile and work.

For now, each intel_digital_port is still only able to control one of
HDMI or DP, but not both together.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c  | 66 ++++++++++++++------------------------
 drivers/gpu/drm/i915/intel_dp.c   | 67 ++++++++++++++++++++++++---------------
 drivers/gpu/drm/i915/intel_drv.h  | 30 +++++++++++++++---
 drivers/gpu/drm/i915/intel_hdmi.c | 28 +++++++++-------
 4 files changed, 106 insertions(+), 85 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 055a1e8..c884b5c 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -652,21 +652,22 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
 	uint32_t wrpll_reg[] = {WRPLL_CTL1, WRPLL_CTL2};
 	uint32_t wrpll_sel[] = {PORT_CLK_SEL_WRPLL1, PORT_CLK_SEL_WRPLL2};
 	uint32_t temp;
+	struct intel_digital_port *intel_dig_port = NULL;
 	struct intel_dp *intel_dp = NULL;
-	struct intel_hdmi *intel_hdmi = NULL;
 
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
 		switch (intel_encoder->type) {
 		case INTEL_OUTPUT_DISPLAYPORT:
 		case INTEL_OUTPUT_EDP:
 			is_dp = true;
-			intel_dp = enc_to_intel_dp(&intel_encoder->base);
-			port = intel_dp->port;
+			intel_dig_port = enc_to_dig_port(&intel_encoder->base);
+			intel_dp = &intel_dig_port->dp;
+			port = intel_dig_port->port;
 			break;
 		case INTEL_OUTPUT_HDMI:
 			is_hdmi = true;
-			intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
-			port = intel_hdmi->ddi_port;
+			intel_dig_port = enc_to_dig_port(&intel_encoder->base);
+			port = intel_dig_port->port;
 			break;
 		case INTEL_OUTPUT_ANALOG:
 			is_crt = true;
@@ -799,20 +800,13 @@ static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder)
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_display_mode *mode = &crtc->mode;
-	int port;
 	int pipe = intel_crtc->pipe;
 	enum transcoder transcoder = intel_crtc->transcoder;
 	u32 func_val, msa_val;
-	struct intel_hdmi *intel_hdmi = NULL;
-	struct intel_dp *intel_dp = NULL;
-
-	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-		intel_hdmi = enc_to_intel_hdmi(encoder);
-		port = intel_hdmi->ddi_port;
-	} else {
-		intel_dp = enc_to_intel_dp(encoder);
-		port = intel_dp->port;
-	}
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	int port = intel_dig_port->port;
 
 	if (transcoder != TRANSCODER_EDP)
 		I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_PORT(port));
@@ -909,20 +903,12 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 {
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
-	struct intel_hdmi *intel_hdmi = NULL;
-	struct intel_dp *intel_dp = NULL;
-	int port;
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	int port = intel_dig_port->port;
 	int pipe = intel_crtc->pipe;
 
-	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-		intel_hdmi = enc_to_intel_hdmi(encoder);
-		port = intel_hdmi->ddi_port;
-	} else {
-		intel_dp = enc_to_intel_dp(encoder);
-		port = intel_dp->port;
-	}
-
 	DRM_DEBUG_KMS("Preparing DDI mode for Haswell on port %c, pipe %c\n",
 		      port_name(port), pipe_name(pipe));
 
@@ -967,8 +953,8 @@ void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
-	int port = intel_hdmi->ddi_port;
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+	int port = intel_dig_port->port;
 	u32 temp;
 
 	temp = I915_READ(DDI_BUF_CTL(port));
@@ -1074,16 +1060,8 @@ void intel_ddi_disable(struct drm_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
 	struct drm_crtc *crtc = encoder->crtc;
-	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
-	int port;
-
-	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
-		port = intel_hdmi->ddi_port;
-	} else {
-		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-		port = intel_dp->port;
-	}
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+	int port = intel_dig_port->port;
 
 	if (intel_ddi_port_disabled(dev_priv, port))
 		return;
@@ -1156,10 +1134,12 @@ void intel_ddi_pll_init(struct drm_device *dev)
 
 static void intel_ddi_enable_dp_port(struct intel_encoder *intel_encoder)
 {
-	struct drm_device *dev = intel_encoder->base.dev;
+	struct drm_encoder *encoder = &intel_encoder->base;
+	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
-	int port = intel_dp->port;
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	int port = intel_dig_port->port;
 	uint32_t tp_val;
 
 	tp_val = DP_TP_CTL_ENABLE | DP_TP_CTL_MODE_SST |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index ffe61a8..fad2959 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -49,7 +49,9 @@
  */
 static bool is_edp(struct intel_dp *intel_dp)
 {
-	return intel_dp->base.type == INTEL_OUTPUT_EDP;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+
+	return intel_dig_port->base.type == INTEL_OUTPUT_EDP;
 }
 
 /**
@@ -78,7 +80,9 @@ static bool is_cpu_edp(struct intel_dp *intel_dp)
 
 static struct drm_device *intel_dp_to_dev(struct intel_dp *intel_dp)
 {
-	return intel_dp->base.base.dev;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+
+	return intel_dig_port->base.base.dev;
 }
 
 static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
@@ -345,7 +349,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 		uint8_t *recv, int recv_size)
 {
 	uint32_t output_reg = intel_dp->output_reg;
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t ch_ctl = output_reg + 0x10;
 	uint32_t ch_data = ch_ctl + 4;
@@ -356,7 +361,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	int try, precharge;
 
 	if (IS_HASWELL(dev)) {
-		switch (intel_dp->port) {
+		switch (intel_dig_port->port) {
 		case PORT_A:
 			ch_ctl = DPA_AUX_CH_CTL;
 			ch_data = DPA_AUX_CH_DATA1;
@@ -374,7 +379,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 			ch_data = PCH_DPD_AUX_CH_DATA;
 			break;
 		default:
-			WARN(1, "Invalid port %c\n", port_name(intel_dp->port));
+			WARN(1, "Invalid port %c\n",
+			     port_name(intel_dig_port->port));
 			break;
 		}
 	}
@@ -1716,13 +1722,15 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 			uint32_t dp_reg_value,
 			uint8_t dp_train_pat)
 {
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum port port = intel_dig_port->port;
 	int ret;
 	uint32_t temp;
 
 	if (IS_HASWELL(dev)) {
-		temp = I915_READ(DP_TP_CTL(intel_dp->port));
+		temp = I915_READ(DP_TP_CTL(port));
 
 		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
 			temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
@@ -1733,9 +1741,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
 		case DP_TRAINING_PATTERN_DISABLE:
 			temp |= DP_TP_CTL_LINK_TRAIN_IDLE;
-			I915_WRITE(DP_TP_CTL(intel_dp->port), temp);
+			I915_WRITE(DP_TP_CTL(port), temp);
 
-			if (wait_for((I915_READ(DP_TP_STATUS(intel_dp->port)) &
+			if (wait_for((I915_READ(DP_TP_STATUS(port)) &
 				      DP_TP_STATUS_IDLE_DONE) == 0, 1))
 				DRM_ERROR("Timed out waiting for DP idle patterns\n");
 
@@ -1753,7 +1761,7 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 			temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
 			break;
 		}
-		I915_WRITE(DP_TP_CTL(intel_dp->port), temp);
+		I915_WRITE(DP_TP_CTL(port), temp);
 
 	} else if (HAS_PCH_CPT(dev) &&
 		   (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
@@ -1819,10 +1827,10 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 static void
 intel_dp_start_link_train(struct intel_dp *intel_dp)
 {
-	struct drm_encoder *encoder = &intel_dp->base.base;
+	struct drm_encoder *encoder = &dp_to_dig_port(intel_dp)->base.base;
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	int i;
 	uint8_t voltage;
 	bool clock_recovery = false;
@@ -2009,12 +2017,13 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 static void
 intel_dp_link_down(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
+	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t DP = intel_dp->DP;
 
 	if (IS_HASWELL(dev)) {
-		intel_ddi_disable(&intel_dp->base.base);
+		intel_ddi_disable(&intel_encoder->base);
 		return;
 	}
 
@@ -2050,7 +2059,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
 	if (HAS_PCH_IBX(dev) &&
 	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
-		struct drm_crtc *crtc = intel_dp->base.base.crtc;
+		struct drm_crtc *crtc = intel_encoder->base.crtc;
 
 		/* Hardware workaround: leaving our transcoder select
 		 * set to transcoder B while it's off will prevent the
@@ -2153,13 +2162,14 @@ intel_dp_handle_test_request(struct intel_dp *intel_dp)
 static void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
+	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
 	u8 sink_irq_vector;
 	u8 link_status[DP_LINK_STATUS_SIZE];
 
 	if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
 		return;
 
-	if (!intel_dp->base.base.crtc)
+	if (!intel_encoder->base.crtc)
 		return;
 
 	/* Try to read receiver status if the link appears to be up */
@@ -2190,7 +2200,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
 
 	if (!intel_channel_eq_ok(intel_dp, link_status)) {
 		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
-			      drm_get_encoder_name(&intel_dp->base.base));
+			      drm_get_encoder_name(&intel_encoder->base));
 		intel_dp_start_link_train(intel_dp);
 		intel_dp_complete_link_train(intel_dp);
 	}
@@ -2409,7 +2419,8 @@ intel_dp_set_property(struct drm_connector *connector,
 		      uint64_t val)
 {
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
-	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
 	int ret;
 
 	ret = drm_connector_property_set_value(connector, property, val);
@@ -2448,8 +2459,8 @@ intel_dp_set_property(struct drm_connector *connector,
 	return -EINVAL;
 
 done:
-	if (intel_dp->base.base.crtc) {
-		struct drm_crtc *crtc = intel_dp->base.base.crtc;
+	if (intel_encoder->base.crtc) {
+		struct drm_crtc *crtc = intel_encoder->base.crtc;
 		drm_crtc_helper_set_mode(crtc, &crtc->mode,
 					 crtc->x, crtc->y,
 					 crtc->fb);
@@ -2473,7 +2484,8 @@ intel_dp_destroy(struct drm_connector *connector)
 
 static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
 
 	i2c_del_adapter(&intel_dp->adapter);
 	drm_encoder_cleanup(encoder);
@@ -2482,7 +2494,7 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
 		ironlake_panel_vdd_off_sync(intel_dp);
 	}
-	kfree(intel_dp);
+	kfree(intel_dig_port);
 }
 
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs_hsw = {
@@ -2582,23 +2594,26 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 	struct intel_dp *intel_dp;
 	struct intel_encoder *intel_encoder;
 	struct intel_connector *intel_connector;
+	struct intel_digital_port *intel_dig_port;
 	const char *name = NULL;
 	int type;
 
-	intel_dp = kzalloc(sizeof(struct intel_dp), GFP_KERNEL);
-	if (!intel_dp)
+	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+	if (!intel_dig_port)
 		return;
 
+	intel_dig_port->port = port;
+
+	intel_dp = &intel_dig_port->dp;
 	intel_dp->output_reg = output_reg;
-	intel_dp->port = port;
 	intel_dp->dpms_mode = -1;
 
 	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
-		kfree(intel_dp);
+		kfree(intel_dig_port);
 		return;
 	}
-	intel_encoder = &intel_dp->base;
+	intel_encoder = &intel_dig_port->base;
 
 	if (HAS_PCH_SPLIT(dev) && output_reg == PCH_DP_D)
 		if (intel_dpd_is_edp(dev))
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 01173d4..d096d4d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -282,10 +282,8 @@ struct dip_infoframe {
 } __attribute__((packed));
 
 struct intel_hdmi {
-	struct intel_encoder base;
 	u32 sdvox_reg;
 	int ddc_bus;
-	int ddi_port;
 	uint32_t color_range;
 	bool has_hdmi_sink;
 	bool has_audio;
@@ -300,13 +298,11 @@ struct intel_hdmi {
 #define DP_LINK_CONFIGURATION_SIZE	9
 
 struct intel_dp {
-	struct intel_encoder base;
 	uint32_t output_reg;
 	uint32_t DP;
 	uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
 	bool has_audio;
 	enum hdmi_force_audio force_audio;
-	enum port port;
 	uint32_t color_range;
 	int dpms_mode;
 	uint8_t link_bw;
@@ -328,6 +324,13 @@ struct intel_dp {
 	int edid_mode_count;
 };
 
+struct intel_digital_port {
+	struct intel_encoder base;
+	enum port port;
+	struct intel_dp dp;
+	struct intel_hdmi hdmi;
+};
+
 static inline struct drm_crtc *
 intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
 {
@@ -425,7 +428,24 @@ static inline struct intel_encoder *intel_attached_encoder(struct drm_connector
 }
 static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
 {
-	return container_of(encoder, struct intel_dp, base.base);
+	struct intel_digital_port *intel_dig_port =
+		container_of(encoder, struct intel_digital_port, base.base);
+	return &intel_dig_port->dp;
+}
+static inline struct intel_digital_port *
+enc_to_dig_port(struct drm_encoder *encoder)
+{
+       return container_of(encoder, struct intel_digital_port, base.base);
+}
+static inline struct intel_digital_port *
+dp_to_dig_port(struct intel_dp *intel_dp)
+{
+       return container_of(intel_dp, struct intel_digital_port, dp);
+}
+static inline struct intel_digital_port *
+hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
+{
+       return container_of(intel_hdmi, struct intel_digital_port, hdmi);
 }
 
 extern void intel_connector_attach_encoder(struct intel_connector *connector,
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 543b1f1..97c01e8 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -39,7 +39,7 @@
 
 static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)
 {
-	return intel_hdmi->base.base.dev;
+	return hdmi_to_dig_port(intel_hdmi)->base.base.dev;
 }
 
 static void
@@ -57,13 +57,15 @@ assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
 
 struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
 {
-	return container_of(encoder, struct intel_hdmi, base.base);
+	struct intel_digital_port *intel_dig_port =
+		container_of(encoder, struct intel_digital_port, base.base);
+
+	return &intel_dig_port->hdmi;
 }
 
 static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
 {
-	return container_of(intel_attached_encoder(connector),
-			    struct intel_hdmi, base);
+	return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base);
 }
 
 void intel_dip_infoframe_csum(struct dip_infoframe *frame)
@@ -797,6 +799,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
 			uint64_t val)
 {
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+	struct intel_encoder *intel_encoder =
+		&hdmi_to_dig_port(intel_hdmi)->base;
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	int ret;
 
@@ -836,8 +840,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
 	return -EINVAL;
 
 done:
-	if (intel_hdmi->base.base.crtc) {
-		struct drm_crtc *crtc = intel_hdmi->base.base.crtc;
+	if (intel_encoder->base.crtc) {
+		struct drm_crtc *crtc = intel_encoder->base.crtc;
 		drm_crtc_helper_set_mode(crtc, &crtc->mode,
 					 crtc->x, crtc->y,
 					 crtc->fb);
@@ -901,19 +905,21 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 	struct drm_connector *connector;
 	struct intel_encoder *intel_encoder;
 	struct intel_connector *intel_connector;
+	struct intel_digital_port *intel_dig_port;
 	struct intel_hdmi *intel_hdmi;
 
-	intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
-	if (!intel_hdmi)
+	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+	if (!intel_dig_port)
 		return;
 
 	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
-		kfree(intel_hdmi);
+		kfree(intel_dig_port);
 		return;
 	}
 
-	intel_encoder = &intel_hdmi->base;
+	intel_hdmi = &intel_dig_port->hdmi;
+	intel_encoder = &intel_dig_port->base;
 	drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
 			 DRM_MODE_ENCODER_TMDS);
 
@@ -931,7 +937,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 
 	intel_encoder->cloneable = false;
 
-	intel_hdmi->ddi_port = port;
+	intel_dig_port->port = port;
 	switch (port) {
 	case PORT_B:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
-- 
1.7.11.2

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

* [RFC 27/30] drm/i915: remove encoder args from intel_{dp, hdmi}_add_properties
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (25 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 26/30] drm/i915: create intel_digital_port and use it Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:06 ` [RFC 28/30] drm/i915: split intel_hdmi_init into encoder and connector pieces Paulo Zanoni
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

They were unused.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c   | 4 ++--
 drivers/gpu/drm/i915/intel_hdmi.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index fad2959..314b4c7 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2580,7 +2580,7 @@ bool intel_dpd_is_edp(struct drm_device *dev)
 }
 
 static void
-intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector)
+intel_dp_add_properties(struct drm_connector *connector)
 {
 	intel_attach_force_audio_property(connector);
 	intel_attach_broadcast_rgb_property(connector);
@@ -2774,7 +2774,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 		intel_panel_setup_backlight(dev);
 	}
 
-	intel_dp_add_properties(intel_dp, connector);
+	intel_dp_add_properties(connector);
 
 	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
 	 * 0xd.  Failure to do so will result in spurious interrupts being
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 97c01e8..bb31a77 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -893,7 +893,7 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
 };
 
 static void
-intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
+intel_hdmi_add_properties(struct drm_connector *connector)
 {
 	intel_attach_force_audio_property(connector);
 	intel_attach_broadcast_rgb_property(connector);
@@ -981,7 +981,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 	else
 		drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
 
-	intel_hdmi_add_properties(intel_hdmi, connector);
+	intel_hdmi_add_properties(connector);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	drm_sysfs_connector_add(connector);
-- 
1.7.11.2

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

* [RFC 28/30] drm/i915: split intel_hdmi_init into encoder and connector pieces
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (26 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 27/30] drm/i915: remove encoder args from intel_{dp, hdmi}_add_properties Paulo Zanoni
@ 2012-08-28 22:06 ` Paulo Zanoni
  2012-08-28 22:07 ` [RFC 29/30] drm/i915: split intel_dp_commit " Paulo Zanoni
  2012-08-28 22:07 ` [RFC 30/30] drm/i915: make DDI an encoder Paulo Zanoni
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

We want to split the HDMI connector and encoder initialization because
in the future the DDI code will have its own "encoder init" function,
but it will still call intel_hdmi_init_connector. The DDI encoder will
actually have two connectors attached to it: HDMI and DP.

The best way to look at this patch is to imagine that we're renaming
intel_hdmi_init to intel_hdmi_init_connector and removing the
encoder-specific pieces and placing them into intel_hdmi_init.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_hdmi.c | 81 ++++++++++++++++++++++-----------------
 1 file changed, 46 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index bb31a77..5a78deb 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -899,45 +899,24 @@ intel_hdmi_add_properties(struct drm_connector *connector)
 	intel_attach_broadcast_rgb_property(connector);
 }
 
-void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
+static void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
+				      struct intel_connector *intel_connector)
 {
+	struct drm_connector *connector = &intel_connector->base;
+	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_connector *connector;
-	struct intel_encoder *intel_encoder;
-	struct intel_connector *intel_connector;
-	struct intel_digital_port *intel_dig_port;
-	struct intel_hdmi *intel_hdmi;
-
-	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
-	if (!intel_dig_port)
-		return;
-
-	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
-	if (!intel_connector) {
-		kfree(intel_dig_port);
-		return;
-	}
+	enum port port = intel_dig_port->port;
 
-	intel_hdmi = &intel_dig_port->hdmi;
-	intel_encoder = &intel_dig_port->base;
-	drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
-			 DRM_MODE_ENCODER_TMDS);
-
-	connector = &intel_connector->base;
 	drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
 			   DRM_MODE_CONNECTOR_HDMIA);
 	drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
 
-	intel_encoder->type = INTEL_OUTPUT_HDMI;
-
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->interlace_allowed = 1;
 	connector->doublescan_allowed = 0;
-	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
-
-	intel_encoder->cloneable = false;
 
-	intel_dig_port->port = port;
 	switch (port) {
 	case PORT_B:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
@@ -957,8 +936,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 		BUG();
 	}
 
-	intel_hdmi->sdvox_reg = sdvox_reg;
-
 	if (!HAS_PCH_SPLIT(dev)) {
 		intel_hdmi->write_infoframe = g4x_write_infoframe;
 		intel_hdmi->set_infoframes = g4x_set_infoframes;
@@ -976,11 +953,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 		intel_hdmi->set_infoframes = cpt_set_infoframes;
 	}
 
-	if (IS_HASWELL(dev))
-		drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs_hsw);
-	else
-		drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
-
 	intel_hdmi_add_properties(connector);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
@@ -995,3 +967,42 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
 }
+
+void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
+{
+	struct intel_digital_port *intel_dig_port;
+	struct intel_encoder *intel_encoder;
+	struct drm_encoder *encoder;
+	struct intel_connector *intel_connector;
+
+	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+	if (!intel_dig_port)
+		return;
+
+	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+	if (!intel_connector) {
+		kfree(intel_dig_port);
+		return;
+	}
+
+	intel_encoder = &intel_dig_port->base;
+	encoder = &intel_encoder->base;
+
+	drm_encoder_init(dev, encoder, &intel_hdmi_enc_funcs,
+			 DRM_MODE_ENCODER_TMDS);
+
+	if (IS_HASWELL(dev))
+		drm_encoder_helper_add(encoder, &intel_hdmi_helper_funcs_hsw);
+	else
+		drm_encoder_helper_add(encoder, &intel_hdmi_helper_funcs);
+
+	intel_dig_port->port = port;
+	intel_dig_port->hdmi.sdvox_reg = sdvox_reg;
+	intel_dig_port->dp.output_reg = 0;
+
+	intel_encoder->type = INTEL_OUTPUT_HDMI;
+	intel_encoder->crtc_mask =  (1 << 0) | (1 << 1) | (1 << 2);
+	intel_encoder->cloneable = false;
+
+	intel_hdmi_init_connector(intel_dig_port, intel_connector);
+}
-- 
1.7.11.2

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

* [RFC 29/30] drm/i915: split intel_dp_commit into encoder and connector pieces
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (27 preceding siblings ...)
  2012-08-28 22:06 ` [RFC 28/30] drm/i915: split intel_hdmi_init into encoder and connector pieces Paulo Zanoni
@ 2012-08-28 22:07 ` Paulo Zanoni
  2012-08-28 22:07 ` [RFC 30/30] drm/i915: make DDI an encoder Paulo Zanoni
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Same reason as the previous HDMI commit: the DDI code will have its
own encoder init function but still use the DP and HDMI connectors.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 91 ++++++++++++++++++++++-------------------
 1 file changed, 50 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 314b4c7..6cf3123 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2586,40 +2586,26 @@ intel_dp_add_properties(struct drm_connector *connector)
 	intel_attach_broadcast_rgb_property(connector);
 }
 
-void
-intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
+static void
+intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
+			struct intel_connector *intel_connector)
 {
+	struct drm_connector *connector = &intel_connector->base;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_connector *connector;
-	struct intel_dp *intel_dp;
-	struct intel_encoder *intel_encoder;
-	struct intel_connector *intel_connector;
-	struct intel_digital_port *intel_dig_port;
+	enum port port = intel_dig_port->port;
 	const char *name = NULL;
 	int type;
 
-	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
-	if (!intel_dig_port)
-		return;
-
-	intel_dig_port->port = port;
-
-	intel_dp = &intel_dig_port->dp;
-	intel_dp->output_reg = output_reg;
 	intel_dp->dpms_mode = -1;
 
-	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
-	if (!intel_connector) {
-		kfree(intel_dig_port);
-		return;
-	}
-	intel_encoder = &intel_dig_port->base;
-
-	if (HAS_PCH_SPLIT(dev) && output_reg == PCH_DP_D)
+	if (HAS_PCH_SPLIT(dev) && port == PORT_D)
 		if (intel_dpd_is_edp(dev))
 			intel_dp->is_pch_edp = true;
 
-	if (output_reg == DP_A || is_pch_edp(intel_dp)) {
+	if (port == PORT_A || is_pch_edp(intel_dp)) {
 		type = DRM_MODE_CONNECTOR_eDP;
 		intel_encoder->type = INTEL_OUTPUT_EDP;
 	} else {
@@ -2627,32 +2613,17 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
 	}
 
-	connector = &intel_connector->base;
 	drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
 	drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
 
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 
-	intel_encoder->cloneable = false;
-
 	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
 			  ironlake_panel_vdd_work);
 
-	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
-
 	connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
-	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
-			 DRM_MODE_ENCODER_TMDS);
-
-	if (IS_HASWELL(dev))
-		drm_encoder_helper_add(&intel_encoder->base,
-				       &intel_dp_helper_funcs_hsw);
-	else
-		drm_encoder_helper_add(&intel_encoder->base,
-				       &intel_dp_helper_funcs);
-
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	drm_sysfs_connector_add(connector);
 
@@ -2767,8 +2738,6 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 		ironlake_edp_panel_vdd_off(intel_dp, false);
 	}
 
-	intel_encoder->hot_plug = intel_dp_hot_plug;
-
 	if (is_edp(intel_dp)) {
 		dev_priv->int_edp_connector = connector;
 		intel_panel_setup_backlight(dev);
@@ -2785,3 +2754,43 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
 }
+
+void
+intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
+{
+	struct intel_digital_port *intel_dig_port;
+	struct intel_encoder *intel_encoder;
+	struct drm_encoder *encoder;
+	struct intel_connector *intel_connector;
+
+	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+	if (!intel_dig_port)
+		return;
+
+	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+	if (!intel_connector) {
+		kfree(intel_dig_port);
+		return;
+	}
+
+	intel_encoder = &intel_dig_port->base;
+	encoder = &intel_encoder->base;
+
+	drm_encoder_init(dev, encoder, &intel_dp_enc_funcs,
+			 DRM_MODE_ENCODER_TMDS);
+
+	if (IS_HASWELL(dev))
+		drm_encoder_helper_add(encoder, &intel_dp_helper_funcs_hsw);
+	else
+		drm_encoder_helper_add(encoder, &intel_dp_helper_funcs);
+
+	intel_dig_port->port = port;
+	intel_dig_port->hdmi.sdvox_reg = 0;
+	intel_dig_port->dp.output_reg = output_reg;
+
+	intel_encoder->crtc_mask =  (1 << 0) | (1 << 1) | (1 << 2);
+	intel_encoder->cloneable = false;
+	intel_encoder->hot_plug = intel_dp_hot_plug;
+
+	intel_dp_init_connector(intel_dig_port, intel_connector);
+}
-- 
1.7.11.2

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

* [RFC 30/30] drm/i915: make DDI an encoder
  2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
                   ` (28 preceding siblings ...)
  2012-08-28 22:07 ` [RFC 29/30] drm/i915: split intel_dp_commit " Paulo Zanoni
@ 2012-08-28 22:07 ` Paulo Zanoni
  29 siblings, 0 replies; 31+ messages in thread
From: Paulo Zanoni @ 2012-08-28 22:07 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Now intel_ddi_init is just like intel_hdmi_init and intel_dp_init: it
inits the encoder and then calls the proper init_connector functions.
Notice that for non-eDP ports we call both HDMI and DP connector init,
so we have 2 connectors attached to each DDI encoder.

We had to add some wrappers to choose which function we need to call
based on the connector connected, so a few HDMI/DP functions had to
become non-static. And since the drm_encoder_{,helper_}funcs are now
inside intel_ddi.c we also made some DDI functions become static.

Besides this, the only change is that now when we detect a connector
we write intel_encoder->type with the detected type. This should not
break older code because on this case we will just rewrite the value
that's already written there.

Now we can finally use both DP and HDMI on the same port on Haswell.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c  | 155 +++++++++++++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_dp.c   |  32 +++-----
 drivers/gpu/drm/i915/intel_drv.h  |  20 +++--
 drivers/gpu/drm/i915/intel_hdmi.c |  28 +++----
 4 files changed, 155 insertions(+), 80 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index c884b5c..458ebbd 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -221,38 +221,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 	DRM_DEBUG_KMS("FDI train done.\n");
 }
 
-/* For DDI connections, it is possible to support different outputs over the
- * same DDI port, such as HDMI or DP or even VGA via FDI. So we don't know by
- * the time the output is detected what exactly is on the other end of it. This
- * function aims at providing support for this detection and proper output
- * configuration.
- */
-void intel_ddi_init(struct drm_device *dev, enum port port)
-{
-	/* For now, we don't do any proper output detection and assume that we
-	 * handle HDMI only */
-
-	switch(port){
-	case PORT_A:
-		/* We don't handle eDP and DP yet */
-		DRM_DEBUG_DRIVER("Found digital output on DDI port A\n");
-		intel_dp_init(dev, DDI_BUF_CTL_A, PORT_A);
-		break;
-	/* Assume that the  ports B, C and D are working in HDMI mode for now */
-	case PORT_B:
-		intel_dp_init(dev, DDI_BUF_CTL(port), port);
-		break;
-	case PORT_C:
-	case PORT_D:
-		intel_hdmi_init(dev, DDI_BUF_CTL(port), port);
-		break;
-	default:
-		DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
-				port);
-		break;
-	}
-}
-
 /* WRPLL clock dividers */
 struct wrpll_tmds_clock {
 	u32 clock;
@@ -897,9 +865,9 @@ static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder)
 	}
 }
 
-void intel_ddi_mode_set(struct drm_encoder *encoder,
-				struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode)
+static void intel_ddi_mode_set(struct drm_encoder *encoder,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
 {
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -949,7 +917,7 @@ static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
 	DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port));
 }
 
-void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
+static void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -957,6 +925,11 @@ void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 	int port = intel_dig_port->port;
 	u32 temp;
 
+	if (intel_dig_port->base.type != INTEL_OUTPUT_HDMI) {
+		intel_dp_dpms(encoder, mode);
+		return;
+	}
+
 	temp = I915_READ(DDI_BUF_CTL(port));
 
 	if (mode != DRM_MODE_DPMS_ON) {
@@ -976,7 +949,7 @@ void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 		intel_wait_ddi_buf_idle(dev_priv, port);
 }
 
-void intel_ddi_commit(struct drm_encoder *encoder)
+static void intel_ddi_commit(struct drm_encoder *encoder)
 {
 	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
 
@@ -1176,3 +1149,111 @@ void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
 	intel_ddi_enable_pipe(intel_encoder);
 	(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_ON);
 }
+
+static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+
+	if (intel_encoder->type != INTEL_OUTPUT_HDMI)
+		intel_dp_check_link_status(intel_dp);
+}
+
+static void intel_ddi_destroy(struct drm_encoder *encoder)
+{
+	/* HDMI has nothing special to destroy, so we can go with this. */
+	intel_dp_encoder_destroy(encoder);
+}
+
+static bool intel_ddi_mode_fixup(struct drm_encoder *encoder,
+				 const struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode)
+{
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+
+	if (intel_encoder->type == INTEL_OUTPUT_UNKNOWN)
+		WARN(1, "mode_fixup() on unknown output!\n");
+
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI)
+		return intel_hdmi_mode_fixup(encoder, mode, adjusted_mode);
+	else
+		return intel_dp_mode_fixup(encoder, mode, adjusted_mode);
+}
+
+static void intel_ddi_prepare(struct drm_encoder *encoder)
+{
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+
+	if (intel_encoder->type == INTEL_OUTPUT_UNKNOWN)
+		WARN(1, "ddi_prepare_fixup() on unknown output!\n");
+
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI)
+		intel_encoder_prepare(encoder);
+	else
+		intel_dp_prepare(encoder);
+}
+
+static const struct drm_encoder_funcs intel_ddi_funcs = {
+	.destroy = intel_ddi_destroy,
+};
+
+static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = {
+	.dpms = intel_ddi_dpms,
+	.mode_fixup = intel_ddi_mode_fixup,
+	.prepare = intel_ddi_prepare,
+	.mode_set = intel_ddi_mode_set,
+	.commit = intel_ddi_commit,
+	.disable = intel_ddi_disable,
+};
+
+void intel_ddi_init(struct drm_device *dev, enum port port)
+{
+	struct intel_digital_port *intel_dig_port;
+	struct intel_encoder *intel_encoder;
+	struct drm_encoder *encoder;
+	struct intel_connector *hdmi_connector = NULL;
+	struct intel_connector *dp_connector = NULL;
+
+	intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+	if (!intel_dig_port)
+		return;
+
+	if (port != PORT_A) {
+		hdmi_connector = kzalloc(sizeof(struct intel_connector),
+				         GFP_KERNEL);
+		if (!hdmi_connector) {
+			kfree(intel_dig_port);
+			return;
+		}
+	}
+
+	dp_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+	if (!dp_connector) {
+		kfree(intel_dig_port);
+		if (hdmi_connector)
+			kfree(hdmi_connector);
+		return;
+	}
+
+	intel_encoder = &intel_dig_port->base;
+	encoder = &intel_encoder->base;
+
+	drm_encoder_init(dev, encoder, &intel_ddi_funcs,
+			 DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(encoder, &intel_ddi_helper_funcs);
+
+	intel_dig_port->port = port;
+	if (hdmi_connector)
+		intel_dig_port->hdmi.sdvox_reg = DDI_BUF_CTL(port);
+	else
+		intel_dig_port->hdmi.sdvox_reg = 0;
+	intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
+
+	intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
+	intel_encoder->crtc_mask =  (1 << 0) | (1 << 1) | (1 << 2);
+	intel_encoder->cloneable = false;
+	intel_encoder->hot_plug = intel_ddi_hot_plug;
+
+	if (hdmi_connector)
+		intel_hdmi_init_connector(intel_dig_port, hdmi_connector);
+	intel_dp_init_connector(intel_dig_port, dp_connector);
+}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6cf3123..f0559d9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -699,7 +699,7 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
 	return ret;
 }
 
-static bool
+bool
 intel_dp_mode_fixup(struct drm_encoder *encoder,
 		    const struct drm_display_mode *mode,
 		    struct drm_display_mode *adjusted_mode)
@@ -1294,7 +1294,7 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
 	}
 }
 
-static void intel_dp_prepare(struct drm_encoder *encoder)
+void intel_dp_prepare(struct drm_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
@@ -1328,7 +1328,7 @@ void intel_dp_commit(struct drm_encoder *encoder)
 		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
-static void
+void
 intel_dp_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@@ -2159,7 +2159,7 @@ intel_dp_handle_test_request(struct intel_dp *intel_dp)
  *  4. Check link status on receipt of hot-plug interrupt
  */
 
-static void
+void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
 	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
@@ -2313,6 +2313,8 @@ static enum drm_connector_status
 intel_dp_detect(struct drm_connector *connector, bool force)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	struct drm_device *dev = connector->dev;
 	enum drm_connector_status status;
 	struct edid *edid = NULL;
@@ -2345,6 +2347,8 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 		}
 	}
 
+	if (intel_encoder->type != INTEL_OUTPUT_EDP)
+		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
 	return connector_status_connected;
 }
 
@@ -2482,7 +2486,7 @@ intel_dp_destroy(struct drm_connector *connector)
 	kfree(connector);
 }
 
-static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
+void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 {
 	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
@@ -2497,15 +2501,6 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 	kfree(intel_dig_port);
 }
 
-static const struct drm_encoder_helper_funcs intel_dp_helper_funcs_hsw = {
-	.dpms = intel_dp_dpms,
-	.mode_fixup = intel_dp_mode_fixup,
-	.prepare = intel_dp_prepare,
-	.mode_set = intel_ddi_mode_set,
-	.commit = intel_ddi_commit,
-	.disable = intel_ddi_disable,
-};
-
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
 	.dpms = intel_dp_dpms,
 	.mode_fixup = intel_dp_mode_fixup,
@@ -2586,7 +2581,7 @@ intel_dp_add_properties(struct drm_connector *connector)
 	intel_attach_broadcast_rgb_property(connector);
 }
 
-static void
+void
 intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 			struct intel_connector *intel_connector)
 {
@@ -2610,7 +2605,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		intel_encoder->type = INTEL_OUTPUT_EDP;
 	} else {
 		type = DRM_MODE_CONNECTOR_DisplayPort;
-		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
 	}
 
 	drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
@@ -2779,10 +2773,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 	drm_encoder_init(dev, encoder, &intel_dp_enc_funcs,
 			 DRM_MODE_ENCODER_TMDS);
 
-	if (IS_HASWELL(dev))
-		drm_encoder_helper_add(encoder, &intel_dp_helper_funcs_hsw);
-	else
-		drm_encoder_helper_add(encoder, &intel_dp_helper_funcs);
+	drm_encoder_helper_add(encoder, &intel_dp_helper_funcs);
 
 	intel_dig_port->port = port;
 	intel_dig_port->hdmi.sdvox_reg = 0;
@@ -2790,6 +2781,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 
 	intel_encoder->crtc_mask =  (1 << 0) | (1 << 1) | (1 << 2);
 	intel_encoder->cloneable = false;
+	intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
 	intel_encoder->hot_plug = intel_dp_hot_plug;
 
 	intel_dp_init_connector(intel_dig_port, intel_connector);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d096d4d..4428d5f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -90,6 +90,7 @@
 #define INTEL_OUTPUT_HDMI 6
 #define INTEL_OUTPUT_DISPLAYPORT 7
 #define INTEL_OUTPUT_EDP 8
+#define INTEL_OUTPUT_UNKNOWN 9
 
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
@@ -371,6 +372,11 @@ extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev,
 			    int sdvox_reg, enum port port);
 extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
+extern void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
+				      struct intel_connector *intel_connector);
+extern bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
+				  const struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode);
 extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
 extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
 			    bool is_sdvob);
@@ -389,6 +395,15 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
 extern void intel_dp_commit(struct drm_encoder *encoder);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
+extern void intel_dp_dpms(struct drm_encoder *encoder, int mode);
+extern void intel_dp_check_link_status(struct intel_dp *intel_dp);
+extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);
+extern bool intel_dp_mode_fixup(struct drm_encoder *encoder,
+				const struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode);
+extern void intel_dp_prepare(struct drm_encoder *encoder);
+extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
+				    struct intel_connector *intel_connector);
 extern void intel_edp_link_config(struct intel_encoder *, int *, int *);
 extern int intel_edp_target_clock(struct intel_encoder *,
 				  struct drm_display_mode *mode);
@@ -550,14 +565,9 @@ extern void intel_disable_gt_powersave(struct drm_device *dev);
 extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv);
 extern void ironlake_teardown_rc6(struct drm_device *dev);
 
-extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode);
 extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc);
-extern void intel_ddi_mode_set(struct drm_encoder *encoder,
-				struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode);
 extern void intel_ddi_pll_init(struct drm_device *dev);
 extern void intel_ddi_disable(struct drm_encoder *encoder);
-extern void intel_ddi_commit(struct drm_encoder *encoder);
 extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 5a78deb..5a29fda 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -691,9 +691,9 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector,
 	return MODE_OK;
 }
 
-static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
-				  const struct drm_display_mode *mode,
-				  struct drm_display_mode *adjusted_mode)
+bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
+			   const struct drm_display_mode *mode,
+			   struct drm_display_mode *adjusted_mode)
 {
 	return true;
 }
@@ -723,6 +723,9 @@ static enum drm_connector_status
 intel_hdmi_detect(struct drm_connector *connector, bool force)
 {
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+	struct intel_digital_port *intel_dig_port =
+		hdmi_to_dig_port(intel_hdmi);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	struct edid *edid;
 	enum drm_connector_status status = connector_status_disconnected;
@@ -752,6 +755,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 		if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO)
 			intel_hdmi->has_audio =
 				(intel_hdmi->force_audio == HDMI_AUDIO_ON);
+		intel_encoder->type = INTEL_OUTPUT_HDMI;
 	}
 
 	return status;
@@ -857,15 +861,6 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
 	kfree(connector);
 }
 
-static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
-	.dpms = intel_ddi_dpms,
-	.mode_fixup = intel_hdmi_mode_fixup,
-	.prepare = intel_encoder_prepare,
-	.mode_set = intel_ddi_mode_set,
-	.commit = intel_ddi_commit,
-	.disable = intel_ddi_disable,
-};
-
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
 	.dpms = intel_hdmi_dpms,
 	.mode_fixup = intel_hdmi_mode_fixup,
@@ -899,8 +894,8 @@ intel_hdmi_add_properties(struct drm_connector *connector)
 	intel_attach_broadcast_rgb_property(connector);
 }
 
-static void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
-				      struct intel_connector *intel_connector)
+void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
+			       struct intel_connector *intel_connector)
 {
 	struct drm_connector *connector = &intel_connector->base;
 	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
@@ -991,10 +986,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 	drm_encoder_init(dev, encoder, &intel_hdmi_enc_funcs,
 			 DRM_MODE_ENCODER_TMDS);
 
-	if (IS_HASWELL(dev))
-		drm_encoder_helper_add(encoder, &intel_hdmi_helper_funcs_hsw);
-	else
-		drm_encoder_helper_add(encoder, &intel_hdmi_helper_funcs);
+	drm_encoder_helper_add(encoder, &intel_hdmi_helper_funcs);
 
 	intel_dig_port->port = port;
 	intel_dig_port->hdmi.sdvox_reg = sdvox_reg;
-- 
1.7.11.2

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

end of thread, other threads:[~2012-08-28 22:08 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-28 22:06 [RFC 00/30] Haswell clocking+HDMI+DP+eDP fixes Paulo Zanoni
2012-08-28 22:06 ` [RFC 01/30] drm/i915: rewrite the LCPLL code Paulo Zanoni
2012-08-28 22:06 ` [RFC 02/30] drm/i915: disable DDI pipes and ports when initializing Paulo Zanoni
2012-08-28 22:06 ` [RFC 03/30] drm/i915: wait for idle DDI_BUF_CTL after disabling it Paulo Zanoni
2012-08-28 22:06 ` [RFC 04/30] drm/i915: implement DDI disable function Paulo Zanoni
2012-08-28 22:06 ` [RFC 05/30] drm/i915: implement intel_ddi_pll_mode_set Paulo Zanoni
2012-08-28 22:06 ` [RFC 06/30] drm/i915: extract intel_ddi_enable pipe from intel_ddi_mode_set Paulo Zanoni
2012-08-28 22:06 ` [RFC 07/30] drm/i915: make intel_ddi_enable_pipe work on DP Paulo Zanoni
2012-08-28 22:06 ` [RFC 08/30] drm/i915: don't sleep after selecting the DDI pipe clock Paulo Zanoni
2012-08-28 22:06 ` [RFC 09/30] drm/i915: add DP support to intel_ddi_pll_mode_set Paulo Zanoni
2012-08-28 22:06 ` [RFC 10/30] drm/i915: add DP support to intel_ddi_disable_port Paulo Zanoni
2012-08-28 22:06 ` [RFC 11/30] drm/i915: add DP support to intel_ddi_mode_set Paulo Zanoni
2012-08-28 22:06 ` [RFC 12/30] drm/i915: add basic Haswell DP link train bits Paulo Zanoni
2012-08-28 22:06 ` [RFC 13/30] drm/i915: add intel_ddi_commit Paulo Zanoni
2012-08-28 22:06 ` [RFC 14/30] drm/i915: fix Haswell M/N registers Paulo Zanoni
2012-08-28 22:06 ` [RFC 15/30] drm/i915: fix DP AUX register definitions on Haswell Paulo Zanoni
2012-08-28 22:06 ` [RFC 16/30] drm/i915: disable DDI on intel_dp_link_down Paulo Zanoni
2012-08-28 22:06 ` [RFC 17/30] drm/i915: add intel_ddi_prepare_link_retrain Paulo Zanoni
2012-08-28 22:06 ` [RFC 18/30] drm/i915: add DP support to intel_ddi_disable Paulo Zanoni
2012-08-28 22:06 ` [RFC 19/30] drm/i915: add Haswell DP encoder_helper function definitions Paulo Zanoni
2012-08-28 22:06 ` [RFC 20/30] drm/i915: add TRANSCODER_EDP Paulo Zanoni
2012-08-28 22:06 ` [RFC 21/30] drm/i915: enable eDP on Haswell Paulo Zanoni
2012-08-28 22:06 ` [RFC 22/30] drm/i915: don't run PCH code on non-PCH ports Paulo Zanoni
2012-08-28 22:06 ` [RFC 23/30] drm/i915: init DP on port B Paulo Zanoni
2012-08-28 22:06 ` [RFC 24/30] drm/i915: simplify assignments inside intel_dp.c Paulo Zanoni
2012-08-28 22:06 ` [RFC 25/30] drm/i915: add intel_dp_to_dev and intel_hdmi_to_dev Paulo Zanoni
2012-08-28 22:06 ` [RFC 26/30] drm/i915: create intel_digital_port and use it Paulo Zanoni
2012-08-28 22:06 ` [RFC 27/30] drm/i915: remove encoder args from intel_{dp, hdmi}_add_properties Paulo Zanoni
2012-08-28 22:06 ` [RFC 28/30] drm/i915: split intel_hdmi_init into encoder and connector pieces Paulo Zanoni
2012-08-28 22:07 ` [RFC 29/30] drm/i915: split intel_dp_commit " Paulo Zanoni
2012-08-28 22:07 ` [RFC 30/30] drm/i915: make DDI an encoder Paulo Zanoni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).