All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support
@ 2012-10-02 20:51 Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 01/47] drm/i915: rewrite the LCPLL code Paulo Zanoni
                   ` (47 more replies)
  0 siblings, 48 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Hi

Some time ago I sent an RFC containing 30 patches fixing Haswell display. This
is a new version of that series. The main difference is that those patches were
on the pre-modeset-rework world and these are now on the post-modeset-rework
world. I have to say that the modeset-rework work simplified a lot of things and
now I am very happy with the result of my patches.

We are now following 95% of the "mode set sequence" described in our
documentation. What we still need to do is move some things from crtc_mode_set
to intel_ddi_set_pipe_settings (which is called by crtc_enable) and do a small
adjustment in the order we write to DP_TP_CTL when using eDP, but these patches
are not strictly necessary to make things work, so they can wait a little.

I spent a long time testing this series on my machine and it is working very
stable, I don't see any of the hangs I was seeing previously (when I sent the
RFC), so I believe any problems brought by this patch series should be small. I
also ran these patches on a SNB laptop and a quick check shows me it still
works, including DP and HDMI. The only real problem I am aware of is that DP
does not work on some specific HSW machines with some specific BIOS versions,
but even eDP works. I still don't have access to those machines, but when I do I
will send the fixes.

This patch series contains 4 sub-series:

  - Patches 1-10 contain fixes for the pipe mode-set sequence (which is the same
    on all encoders), a complete rewrite of how we handle our clocks and an
    HDMI-specific patch. The patches are organized in that specific order
    because I tried to not introduce any regression in the middle of the series.

  - Patches 11-24 add DP support. This is a long series of very small and boring
    patches. Some people may think there are too many patches and we should
    group some patches into bigger ones, I won't disagree. I wrote many tiny
    patches because IMHO this makes it easier to rebase and change things (and
    also review).

    Notice that after patch 24 you will still not have your DP outputs working.
    If you replace one of the "intel_hdmi_init" cals inside intel_ddi_init with
    "intel_dp_init" you will get your DP output working, but you will break
    HDMI. Making both DP and HDMI working on the same port is not simple and
    only works after patch 47.

  - Patches 25-38 make eDP work. Again, another slow series and maybe we could
    merge some of the small patches into bigger ones. After patch 38 eDP will
    actually start working (even though DP does not work yet).

  - Patches 39-47 add the magic to make both HDMI and DP outputs work on the
    same port. Just calling "intel_hdmi_init" and "intel_dp_init" on the same
    port won't work as the encoders use basically the same registers. These
    patches create a DDI encoder that has 2 connectors: a DP and an HDMI. To do
    this we had to change some code that runs on all gens, but I think it was
    worth the change.

And a last small detail: I implemented this series on top of
drm-intel-next-queued + patch "drm/i915: extract intel_set_pipe_timings from
crtc_mode_set".

Opinions?

Paulo Zanoni (47):
  drm/i915: rewrite the LCPLL code
  drm/i915: enable and disable DDI_FUNC_CTL at the right time
  drm/i915: enable and disable PIPE_CLK_SEL at the right time
  drm/i915: completely rewrite the Haswell PLL handling code
  drm/i915: don't rely on previous values set on DDI_BUF_CTL
  drm/i915: disable DDI_BUF_CTL at the correct time
  drm/i915: add haswell_crtc_mode_set
  drm/i915: add proper CPU/PCH checks to crtc_mode_set functions
  drm/i915: add haswell_set_pipeconf
  drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set
  drm/i915: add DP support to intel_ddi_enable_pipe_func
  drm/i915: add intel_ddi_set_pipe_settings
  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: use TU_SIZE macro at intel_dp_set_m_n
  drm/i915: fix Haswell DP M/N registers
  drm/i915: fix DP AUX register definitions on Haswell
  drm/i915: add DP support to intel_ddi_get_encoder_port
  drm/i915: add DP support to intel_ddi_get_hw_state
  drm/i915: add DP support to intel_enable_ddi
  drm/i915: implement Haswell DP link train sequence
  drm/i915: set the correct function pointers for Haswell DP
  drm/i915: add TRANSCODER_EDP
  drm/i915: convert PIPE_CLK_SEL to transcoder
  drm/i915: convert DDI_FUNC_CTL to transcoder
  drm/i915: check TRANSCODER_EDP on intel_modeset_setup_hw_state
  drm/i915: convert PIPECONF to use transcoder instead of pipe
  drm/i915: convert PIPE_MSA_MISC to transcoder
  drm/i915: convert CPU M/N timings to transcoder
  drm/i915: convert pipe timing definitions to transcoder
  drm/i915: implement workaround for VTOTAL when using TRANSCODER_EDP
  drm/i915: select the correct pipe when using TRANSCODER_EDP
  drm/i915: set the correct eDP aux channel clock divider on DDI
  drm/i915: set/unset the DDI eDP backlight
  drm/i915: turn the eDP DDI panel on/off
  drm/i915: enable DDI eDP
  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_init into encoder and connector pieces
  drm/i915: reset intel_encoder->type when DP or HDMI is detected
  drm/i915: add intel_ddi_connector_get_hw_state
  drm/i915: create the DDI encoder

 drivers/gpu/drm/i915/i915_drv.h      |   15 +
 drivers/gpu/drm/i915/i915_irq.c      |   11 +-
 drivers/gpu/drm/i915/i915_reg.h      |  139 +++--
 drivers/gpu/drm/i915/intel_crt.c     |   12 +-
 drivers/gpu/drm/i915/intel_ddi.c     |  935 ++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_display.c |  452 +++++++++++++---
 drivers/gpu/drm/i915/intel_dp.c      |  470 +++++++++++------
 drivers/gpu/drm/i915/intel_drv.h     |   82 ++-
 drivers/gpu/drm/i915/intel_hdmi.c    |  135 ++---
 drivers/gpu/drm/i915/intel_sprite.c  |    3 +-
 drivers/gpu/drm/i915/intel_tv.c      |    4 +-
 11 files changed, 1770 insertions(+), 488 deletions(-)

-- 
1.7.10.4

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

* [PATCH 01/47] drm/i915: rewrite the LCPLL code
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-03 16:47   ` Lespiau, Damien
  2012-10-02 20:51 ` [PATCH 02/47] drm/i915: enable and disable DDI_FUNC_CTL at the right time Paulo Zanoni
                   ` (46 subsequent siblings)
  47 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 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.

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 d17bef7..ab96706 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4527,8 +4527,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 bfe3754..34a73a1 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,
@@ -817,3 +811,43 @@ void intel_disable_ddi(struct intel_encoder *encoder)
 
 	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("CDCLK source is not LCPLL\n");
+		lcpll_needs_change = true;
+		lcpll_val &= ~LCPLL_CD_SOURCE_FCLK;
+	}
+
+	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 6cf0d00..40f98d1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7477,6 +7477,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;
@@ -8085,6 +8091,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 79f8ed6..57566b7 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -580,5 +580,6 @@ extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 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.10.4

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

* [PATCH 02/47] drm/i915: enable and disable DDI_FUNC_CTL at the right time
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 01/47] drm/i915: rewrite the LCPLL code Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-03 17:44   ` Lespiau, Damien
  2012-10-02 20:51 ` [PATCH 03/47] drm/i915: enable and disable PIPE_CLK_SEL " Paulo Zanoni
                   ` (45 subsequent siblings)
  47 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

And the right time is exactly after/before changing PIPE_CONF. See the
documentation about the mode set sequence.

This code is not inside any encoder-specific callback because
DDI_FUNC_CTL is part of the pipe, so it is used by all encoders.

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

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ab96706..499ca17 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4387,6 +4387,7 @@
 /* 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_SELECT_PORT(x)	((x)<<28)
+#define  PIPE_DDI_PORT_NONE		(0<<28)
 #define  PIPE_DDI_MODE_SELECT_MASK	(7<<24)
 #define  PIPE_DDI_MODE_SELECT_HDMI	(0<<24)
 #define  PIPE_DDI_MODE_SELECT_DVI	(1<<24)
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 34a73a1..137f3af 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -203,15 +203,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 						DP_TP_CTL_ENHANCED_FRAME_ENABLE |
 						DP_TP_CTL_ENABLE);
 
-			/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in FDI mode */
-			temp = I915_READ(DDI_FUNC_CTL(pipe));
-			temp &= ~PIPE_DDI_PORT_MASK;
-			temp |= PIPE_DDI_SELECT_PORT(PORT_E) |
-					PIPE_DDI_MODE_SELECT_FDI |
-					PIPE_DDI_FUNC_ENABLE |
-					PIPE_DDI_PORT_WIDTH_X2;
-			I915_WRITE(DDI_FUNC_CTL(pipe),
-					temp);
 			break;
 		} else {
 			DRM_ERROR("Error training BUF_CTL %d\n", i);
@@ -657,7 +648,7 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	int port = intel_hdmi->ddi_port;
 	int pipe = intel_crtc->pipe;
 	int p, n2, r2;
-	u32 temp, i;
+	u32 i;
 
 	/* On Haswell, we need to enable the clocks and prepare DDI function to
 	 * work in HDMI mode for this pipe.
@@ -715,8 +706,40 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 		intel_write_eld(encoder, adjusted_mode);
 	}
 
+	intel_hdmi->set_infoframes(encoder, adjusted_mode);
+}
+
+static struct intel_encoder *
+intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder, *ret = NULL;
+	int num_encoders = 0;
+
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		ret = intel_encoder;
+		num_encoders++;
+	}
+
+	if (num_encoders != 1)
+		WARN(1, "%d encoders on crtc for pipe %d\n", num_encoders,
+		     intel_crtc->pipe);
+
+	BUG_ON(ret == NULL);
+	return ret;
+}
+
+void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	enum pipe pipe = intel_crtc->pipe;
+	uint32_t temp;
+
 	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
-	temp = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
+	temp = PIPE_DDI_FUNC_ENABLE;
 
 	switch (intel_crtc->bpp) {
 	case 18:
@@ -736,19 +759,41 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 		     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)
+	if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
 		temp |= PIPE_DDI_PVSYNC;
-	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+	if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
 		temp |= PIPE_DDI_PHSYNC;
 
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi =
+			enc_to_intel_hdmi(&intel_encoder->base);
+
+		if (intel_hdmi->has_hdmi_sink)
+			temp |= PIPE_DDI_MODE_SELECT_HDMI;
+		else
+			temp |= PIPE_DDI_MODE_SELECT_DVI;
+
+		temp |= PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port);
+	} else if (intel_encoder->type == INTEL_OUTPUT_ANALOG) {
+		temp |= PIPE_DDI_MODE_SELECT_FDI;
+		temp |= PIPE_DDI_SELECT_PORT(PORT_E);
+	} else {
+		WARN(1, "Invalid encoder type %d for pipe %d\n",
+		     intel_encoder->type, pipe);
+	}
+
 	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+}
 
-	intel_hdmi->set_infoframes(encoder, adjusted_mode);
+void intel_ddi_disable_pipe_func(struct drm_i915_private *dev_priv,
+				 enum pipe pipe)
+{
+	uint32_t reg = DDI_FUNC_CTL(pipe);
+	uint32_t val = I915_READ(reg);
+
+	val &= ~(PIPE_DDI_FUNC_ENABLE | PIPE_DDI_PORT_MASK);
+	val |= PIPE_DDI_PORT_NONE;
+	I915_WRITE(reg, val);
 }
 
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 40f98d1..e4f07a2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3215,6 +3215,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	 */
 	intel_crtc_load_lut(crtc);
 
+	if (IS_HASWELL(dev))
+		intel_ddi_enable_pipe_func(crtc);
+
 	intel_enable_pipe(dev_priv, pipe, is_pch_port);
 	intel_enable_plane(dev_priv, plane, pipe);
 
@@ -3262,6 +3265,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
 	intel_disable_pipe(dev_priv, pipe);
 
+	if (IS_HASWELL(dev))
+		intel_ddi_disable_pipe_func(dev_priv, pipe);
+
 	/* Disable PF */
 	I915_WRITE(PF_CTL(pipe), 0);
 	I915_WRITE(PF_WIN_SZ(pipe), 0);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 57566b7..0253bb4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -581,5 +581,8 @@ 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_enable_pipe_func(struct drm_crtc *crtc);
+extern void intel_ddi_disable_pipe_func(struct drm_i915_private *dev_priv,
+					enum pipe pipe);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.10.4

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

* [PATCH 03/47] drm/i915: enable and disable PIPE_CLK_SEL at the right time
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 01/47] drm/i915: rewrite the LCPLL code Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 02/47] drm/i915: enable and disable DDI_FUNC_CTL at the right time Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-04 11:28   ` Lespiau, Damien
  2012-10-02 20:51 ` [PATCH 04/47] drm/i915: completely rewrite the Haswell PLL handling code Paulo Zanoni
                   ` (44 subsequent siblings)
  47 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Previously we were enabling it at mode_set but never disabling. Let's
follow the mode set sequence.

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 137f3af..f057e11 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -58,6 +58,22 @@ static const u32 hsw_ddi_translations_fdi[] = {
 	0x00FFFFFF, 0x00040006		/* HDMI parameters */
 };
 
+static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
+{
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi =
+			enc_to_intel_hdmi(&intel_encoder->base);
+		return intel_hdmi->ddi_port;
+	} else if (type == INTEL_OUTPUT_ANALOG) {
+		return PORT_E;
+	} else {
+		DRM_ERROR("Invalid DDI encoder type %d\n", type);
+		BUG();
+	}
+}
+
 /* On Haswell, DDI port buffers must be programmed with correct values
  * in advance. The buffer values are different for FDI and DP modes,
  * but the HDMI/DVI fields are shared among those. So we program the DDI
@@ -145,8 +161,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 	/* 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));
 
 	udelay(20);
 
@@ -689,8 +703,6 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	 */
 	I915_WRITE(PORT_CLK_SEL(port),
 			PORT_CLK_SEL_WRPLL1);
-	I915_WRITE(PIPE_CLK_SEL(pipe),
-			PIPE_CLK_SEL_PORT(port));
 
 	udelay(20);
 
@@ -825,6 +837,23 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
+{
+	struct drm_crtc *crtc = &intel_crtc->base;
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+
+	I915_WRITE(PIPE_CLK_SEL(intel_crtc->pipe), PIPE_CLK_SEL_PORT(port));
+}
+
+void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
+{
+	struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
+
+	I915_WRITE(PIPE_CLK_SEL(intel_crtc->pipe), PIPE_CLK_SEL_DISABLED);
+}
+
 void intel_enable_ddi(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e4f07a2..faa2013 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3197,6 +3197,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 		if (encoder->pre_enable)
 			encoder->pre_enable(encoder);
 
+	if (IS_HASWELL(dev))
+		intel_ddi_enable_pipe_clock(intel_crtc);
+
 	/* Enable panel fitting for LVDS */
 	if (dev_priv->pch_pf_size &&
 	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) {
@@ -3272,6 +3275,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	I915_WRITE(PF_CTL(pipe), 0);
 	I915_WRITE(PF_WIN_SZ(pipe), 0);
 
+	if (IS_HASWELL(dev))
+		intel_ddi_disable_pipe_clock(intel_crtc);
+
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->post_disable)
 			encoder->post_disable(encoder);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0253bb4..5de365d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -584,5 +584,7 @@ extern void intel_ddi_pll_init(struct drm_device *dev);
 extern void intel_ddi_enable_pipe_func(struct drm_crtc *crtc);
 extern void intel_ddi_disable_pipe_func(struct drm_i915_private *dev_priv,
 					enum pipe pipe);
+extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
+extern void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.10.4

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

* [PATCH 04/47] drm/i915: completely rewrite the Haswell PLL handling code
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (2 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 03/47] drm/i915: enable and disable PIPE_CLK_SEL " Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 05/47] drm/i915: don't rely on previous values set on DDI_BUF_CTL Paulo Zanoni
                   ` (43 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Problems with the previous code:
  - HDMI just uses WRPLL1 for everything, so dual head cases might not
    work sometimes.
  - At encoder->mode_set we just write the PLL register without doing
    any kind of check (e.g., check if the PLL is already being used).
  - There is no way to fail and return error codes at
    encoder->mode_set.
  - We write to PORT_CLK_SEL at mode_set and we never disable it.
  - Machines hang due to wrong clock enable/disable sequence.

So here we rewrite the code, making it a little more like the
pre-Haswell PLL mode set code:
  - Check PLL availability at ironlake_crtc_mode_set.
  - Try to use both WRPLLs.
  - Check if PLLs are used before actually trying to use them, and
    properly fail with error messages.
  - Enable/disable PORT_CLK_SEL at the right place.
  - Add some WARNs to check for bugs.

The next improvement will be to try to reuse PLLs if the timings
match, but this is content for another patch and it's already
documented with a TODO comment.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |    7 +
 drivers/gpu/drm/i915/i915_reg.h      |    1 +
 drivers/gpu/drm/i915/intel_ddi.c     |  263 +++++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_display.c |   17 ++-
 drivers/gpu/drm/i915/intel_drv.h     |    6 +
 drivers/gpu/drm/i915/intel_hdmi.c    |    2 +
 6 files changed, 242 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index af5ceb4..fc3761e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -93,6 +93,12 @@ struct intel_pch_pll {
 };
 #define I915_NUM_PLLS 2
 
+struct intel_ddi_plls {
+	int spll_refcount;
+	int wrpll1_refcount;
+	int wrpll2_refcount;
+};
+
 /* Interface history:
  *
  * 1.1: Original.
@@ -811,6 +817,7 @@ typedef struct drm_i915_private {
 	wait_queue_head_t pending_flip_queue;
 
 	struct intel_pch_pll pch_plls[I915_NUM_PLLS];
+	struct intel_ddi_plls ddi_plls;
 
 	/* Reclocking support */
 	bool render_reclock_avail;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 499ca17..2932cfc 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4515,6 +4515,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 f057e11..2986b73 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -152,18 +152,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);
-
-	udelay(20);
-
 	/* Start the training iterating through available voltages and emphasis */
 	for (i=0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values); i++) {
 		/* Configure DP_TP_CTL with auto-training */
@@ -654,58 +642,17 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
 {
-	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;
-	int p, n2, r2;
-	u32 i;
 
 	/* 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);
-
-	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.
@@ -742,6 +689,144 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
 	return ret;
 }
 
+void intel_ddi_put_crtc_pll(struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	uint32_t val;
+
+	switch (intel_crtc->ddi_pll_sel) {
+	case PORT_CLK_SEL_SPLL:
+		plls->spll_refcount--;
+		if (plls->spll_refcount == 0) {
+			DRM_DEBUG_KMS("Disabling SPLL\n");
+			val = I915_READ(SPLL_CTL);
+			WARN_ON(!(val & SPLL_PLL_ENABLE));
+			I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
+			POSTING_READ(SPLL_CTL);
+		}
+		break;
+	case PORT_CLK_SEL_WRPLL1:
+		plls->wrpll1_refcount--;
+		if (plls->wrpll1_refcount == 0) {
+			DRM_DEBUG_KMS("Disabling WRPLL 1\n");
+			val = I915_READ(WRPLL_CTL1);
+			WARN_ON(!(val & WRPLL_PLL_ENABLE));
+			I915_WRITE(WRPLL_CTL1, val & ~WRPLL_PLL_ENABLE);
+			POSTING_READ(WRPLL_CTL1);
+		}
+		break;
+	case PORT_CLK_SEL_WRPLL2:
+		plls->wrpll2_refcount--;
+		if (plls->wrpll2_refcount == 0) {
+			DRM_DEBUG_KMS("Disabling WRPLL 2\n");
+			val = I915_READ(WRPLL_CTL2);
+			WARN_ON(!(val & WRPLL_PLL_ENABLE));
+			I915_WRITE(WRPLL_CTL2, val & ~WRPLL_PLL_ENABLE);
+			POSTING_READ(WRPLL_CTL2);
+		}
+		break;
+	}
+
+	WARN(plls->spll_refcount < 0, "Invalid SPLL refcount\n");
+	WARN(plls->wrpll1_refcount < 0, "Invalid WRPLL1 refcount\n");
+	WARN(plls->wrpll2_refcount < 0, "Invalid WRPLL2 refcount\n");
+
+	intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
+}
+
+static void intel_ddi_calculate_wrpll(int clock, int *p, int *n2, int *r2)
+{
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++)
+		if (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 != clock)
+		DRM_INFO("WRPLL: using settings for %dKHz on %dKHz mode\n",
+			 wrpll_tmds_clock_table[i].clock, clock);
+
+	DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
+		      clock, *p, *n2, *r2);
+}
+
+bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
+	int type = intel_encoder->type;
+	enum pipe pipe = intel_crtc->pipe;
+	uint32_t reg, val;
+
+	/* TODO: reuse PLLs when possible (compare values) */
+
+	intel_ddi_put_crtc_pll(crtc);
+
+	if (type == INTEL_OUTPUT_HDMI) {
+		int p, n2, r2;
+
+		if (plls->wrpll1_refcount == 0) {
+			DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n",
+				      pipe_name(pipe));
+			plls->wrpll1_refcount++;
+			reg = WRPLL_CTL1;
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
+		} else if (plls->wrpll2_refcount == 0) {
+			DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n",
+				      pipe_name(pipe));
+			plls->wrpll2_refcount++;
+			reg = WRPLL_CTL2;
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
+		} else {
+			DRM_ERROR("No WRPLLs available!\n");
+			return false;
+		}
+
+		WARN(I915_READ(reg) & WRPLL_PLL_ENABLE,
+		     "WRPLL already enabled\n");
+
+		intel_ddi_calculate_wrpll(clock, &p, &n2, &r2);
+
+		val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
+		      WRPLL_DIVIDER_POST(p);
+
+	} else if (type == INTEL_OUTPUT_ANALOG) {
+		if (plls->spll_refcount == 0) {
+			DRM_DEBUG_KMS("Using SPLL on pipe %c\n",
+				      pipe_name(pipe));
+			plls->spll_refcount++;
+			reg = SPLL_CTL;
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
+		}
+
+		WARN(I915_READ(reg) & SPLL_PLL_ENABLE,
+		     "SPLL already enabled\n");
+
+		val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SCC;
+
+	} else {
+		WARN(1, "Invalid DDI encoder type %d\n", type);
+		return false;
+	}
+
+	I915_WRITE(reg, val);
+	udelay(20);
+
+	return true;
+}
+
 void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -837,6 +922,57 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv,
+				       enum pipe pipe)
+{
+	uint32_t temp, ret;
+	enum port port;
+	int i;
+
+	temp = I915_READ(DDI_FUNC_CTL(pipe));
+	temp &= PIPE_DDI_PORT_MASK;
+	for (i = PORT_A; i <= PORT_E; i++)
+		if (temp == PIPE_DDI_SELECT_PORT(i))
+			port = i;
+
+	ret = I915_READ(PORT_CLK_SEL(port));
+
+	DRM_DEBUG_KMS("Pipe %c connected to port %c using clock 0x%08x\n",
+		      pipe_name(pipe), port_name(port), ret);
+
+	return ret;
+}
+
+void intel_ddi_setup_hw_pll_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum pipe pipe;
+	struct intel_crtc *intel_crtc;
+
+	for_each_pipe(pipe) {
+		intel_crtc =
+			to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+
+		if (!intel_crtc->active)
+			continue;
+
+		intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv,
+								 pipe);
+
+		switch (intel_crtc->ddi_pll_sel) {
+		case PORT_CLK_SEL_SPLL:
+			dev_priv->ddi_plls.spll_refcount++;
+			break;
+		case PORT_CLK_SEL_WRPLL1:
+			dev_priv->ddi_plls.wrpll1_refcount++;
+			break;
+		case PORT_CLK_SEL_WRPLL2:
+			dev_priv->ddi_plls.wrpll2_refcount++;
+			break;
+		}
+	}
+}
+
 void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
 {
 	struct drm_crtc *crtc = &intel_crtc->base;
@@ -854,6 +990,27 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
 	I915_WRITE(PIPE_CLK_SEL(intel_crtc->pipe), PIPE_CLK_SEL_DISABLED);
 }
 
+void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
+{
+	struct drm_crtc *crtc = intel_encoder->base.crtc;
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+
+	WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
+
+	I915_WRITE(PORT_CLK_SEL(port), intel_crtc->ddi_pll_sel);
+}
+
+void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
+{
+	struct drm_encoder *encoder = &intel_encoder->base;
+	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+
+	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
+}
+
 void intel_enable_ddi(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index faa2013..b44d57b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3332,6 +3332,11 @@ static void ironlake_crtc_off(struct drm_crtc *crtc)
 	intel_put_pch_pll(intel_crtc);
 }
 
+static void haswell_crtc_off(struct drm_crtc *crtc)
+{
+	intel_ddi_put_crtc_pll(crtc);
+}
+
 static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
 {
 	if (!enable && intel_crtc->overlay) {
@@ -5002,6 +5007,10 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		num_connectors++;
 	}
 
+	if (IS_HASWELL(dev))
+		if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
+			return -EINVAL;
+
 	ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
 				     &has_reduced_clock, &reduced_clock);
 	if (!ok) {
@@ -7856,7 +7865,10 @@ static void intel_init_display(struct drm_device *dev)
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
 		dev_priv->display.crtc_enable = ironlake_crtc_enable;
 		dev_priv->display.crtc_disable = ironlake_crtc_disable;
-		dev_priv->display.off = ironlake_crtc_off;
+		if (IS_HASWELL(dev))
+			dev_priv->display.off = haswell_crtc_off;
+		else
+			dev_priv->display.off = ironlake_crtc_off;
 		dev_priv->display.update_plane = ironlake_update_plane;
 	} else {
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
@@ -8305,6 +8317,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 			      crtc->active ? "enabled" : "disabled");
 	}
 
+	if (IS_HASWELL(dev))
+		intel_ddi_setup_hw_pll_state(dev);
+
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
 			    base.head) {
 		pipe = 0;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5de365d..245319a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -212,6 +212,7 @@ struct intel_crtc {
 
 	/* We can share PLLs across outputs if the timings match */
 	struct intel_pch_pll *pch_pll;
+	uint32_t ddi_pll_sel;
 };
 
 struct intel_plane {
@@ -586,5 +587,10 @@ extern void intel_ddi_disable_pipe_func(struct drm_i915_private *dev_priv,
 					enum pipe pipe);
 extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
 extern void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
+extern void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
+extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock);
+extern void intel_ddi_pre_enable(struct intel_encoder *intel_encoder);
+extern void intel_ddi_post_disable(struct intel_encoder *intel_encoder);
+extern void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index f9fb47c..a6dd00d9 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1013,8 +1013,10 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 	}
 
 	if (IS_HASWELL(dev)) {
+		intel_encoder->pre_enable = intel_ddi_pre_enable;
 		intel_encoder->enable = intel_enable_ddi;
 		intel_encoder->disable = intel_disable_ddi;
+		intel_encoder->post_disable = intel_ddi_post_disable;
 		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
 		drm_encoder_helper_add(&intel_encoder->base,
 				       &intel_hdmi_helper_funcs_hsw);
-- 
1.7.10.4

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

* [PATCH 05/47] drm/i915: don't rely on previous values set on DDI_BUF_CTL
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (3 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 04/47] drm/i915: completely rewrite the Haswell PLL handling code Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 06/47] drm/i915: disable DDI_BUF_CTL at the correct time Paulo Zanoni
                   ` (42 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Just set the only bit we need, everything else is either ignored on
HDMI or should be set to zero.

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 2986b73..b5a1fdb 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1017,16 +1017,12 @@ void intel_enable_ddi(struct intel_encoder *encoder)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	int port = intel_hdmi->ddi_port;
-	u32 temp;
-
-	temp = I915_READ(DDI_BUF_CTL(port));
-	temp |= DDI_BUF_CTL_ENABLE;
 
 	/* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width,
 	 * and swing/emphasis values are ignored so nothing special needs
 	 * to be done besides enabling the port.
 	 */
-	I915_WRITE(DDI_BUF_CTL(port), temp);
+	I915_WRITE(DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE);
 }
 
 void intel_disable_ddi(struct intel_encoder *encoder)
-- 
1.7.10.4

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

* [PATCH 06/47] drm/i915: disable DDI_BUF_CTL at the correct time
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (4 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 05/47] drm/i915: don't rely on previous values set on DDI_BUF_CTL Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 07/47] drm/i915: add haswell_crtc_mode_set Paulo Zanoni
                   ` (41 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

And also properly wait for its idle bit.

You may notice that DDI_BUF_CTL is enabled in .enable but disabled in
.post_disable instead of .disable. Yes, the mode set sequence is not
exactly symmetrical, but let's assume the spec is correct unless we
can prove it's wrong.

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index b5a1fdb..2965fb7 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1002,11 +1002,33 @@ void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 	I915_WRITE(PORT_CLK_SEL(port), intel_crtc->ddi_pll_sel);
 }
 
+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_post_disable(struct intel_encoder *intel_encoder)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
 	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	uint32_t val;
+
+	val = I915_READ(DDI_BUF_CTL(port));
+	if (val & DDI_BUF_CTL_ENABLE) {
+		val &= ~DDI_BUF_CTL_ENABLE;
+		I915_WRITE(DDI_BUF_CTL(port), val);
+		intel_wait_ddi_buf_idle(dev_priv, port);
+	}
 
 	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
 }
@@ -1027,16 +1049,7 @@ void intel_enable_ddi(struct intel_encoder *encoder)
 
 void intel_disable_ddi(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
-	int port = intel_hdmi->ddi_port;
-	u32 temp;
-
-	temp = I915_READ(DDI_BUF_CTL(port));
-	temp &= ~DDI_BUF_CTL_ENABLE;
-
-	I915_WRITE(DDI_BUF_CTL(port), temp);
+	/* This will be needed in the future, so leave it here for now */
 }
 
 void intel_ddi_pll_init(struct drm_device *dev)
-- 
1.7.10.4

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

* [PATCH 07/47] drm/i915: add haswell_crtc_mode_set
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (5 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 06/47] drm/i915: disable DDI_BUF_CTL at the correct time Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-04 14:38   ` Lespiau, Damien
  2012-10-02 20:51 ` [PATCH 08/47] drm/i915: add proper CPU/PCH checks to crtc_mode_set functions Paulo Zanoni
                   ` (40 subsequent siblings)
  47 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

It's just a copy of ironlake_crtc_mode_set.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b44d57b..f7962e7 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5151,6 +5151,189 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	return ret;
 }
 
+static int haswell_crtc_mode_set(struct drm_crtc *crtc,
+				 struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode,
+				 int x, int y,
+				 struct drm_framebuffer *fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+	int num_connectors = 0;
+	intel_clock_t clock, reduced_clock;
+	u32 dpll, fp = 0, fp2 = 0;
+	bool ok, has_reduced_clock = false;
+	bool is_lvds = false, is_dp = false, is_cpu_edp = false;
+	struct intel_encoder *encoder;
+	u32 temp;
+	int ret;
+	bool dither;
+
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		switch (encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_DISPLAYPORT:
+			is_dp = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			is_dp = true;
+			if (!intel_encoder_is_pch_edp(&encoder->base))
+				is_cpu_edp = true;
+			break;
+		}
+
+		num_connectors++;
+	}
+
+	if (IS_HASWELL(dev))
+		if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
+			return -EINVAL;
+
+	ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+				     &has_reduced_clock, &reduced_clock);
+	if (!ok) {
+		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	/* Ensure that the cursor is valid for the new mode before changing... */
+	intel_crtc_update_cursor(crtc, true);
+
+	/* determine panel color depth */
+	dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp, mode);
+	if (is_lvds && dev_priv->lvds_dither)
+		dither = true;
+
+	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+	if (has_reduced_clock)
+		fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
+			reduced_clock.m2;
+
+	dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock, fp);
+
+	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
+	drm_mode_debug_printmodeline(mode);
+
+	/* CPU eDP is the only output that doesn't need a PCH PLL of its own on
+	 * pre-Haswell/LPT generation */
+	if (HAS_PCH_LPT(dev)) {
+		DRM_DEBUG_KMS("LPT detected: no PLL for pipe %d necessary\n",
+				pipe);
+	} else if (!is_cpu_edp) {
+		struct intel_pch_pll *pll;
+
+		pll = intel_get_pch_pll(intel_crtc, dpll, fp);
+		if (pll == NULL) {
+			DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
+					 pipe);
+			return -EINVAL;
+		}
+	} else
+		intel_put_pch_pll(intel_crtc);
+
+	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
+	 * This is an exception to the general rule that mode_set doesn't turn
+	 * things on.
+	 */
+	if (is_lvds) {
+		temp = I915_READ(PCH_LVDS);
+		temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
+		if (HAS_PCH_CPT(dev)) {
+			temp &= ~PORT_TRANS_SEL_MASK;
+			temp |= PORT_TRANS_SEL_CPT(pipe);
+		} else {
+			if (pipe == 1)
+				temp |= LVDS_PIPEB_SELECT;
+			else
+				temp &= ~LVDS_PIPEB_SELECT;
+		}
+
+		/* set the corresponsding LVDS_BORDER bit */
+		temp |= dev_priv->lvds_border_bits;
+		/* Set the B0-B3 data pairs corresponding to whether we're going to
+		 * set the DPLLs for dual-channel mode or not.
+		 */
+		if (clock.p2 == 7)
+			temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+		else
+			temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
+
+		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+		 * appropriately here, but we need to look more thoroughly into how
+		 * panels behave in the two modes.
+		 */
+		temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
+		if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+			temp |= LVDS_HSYNC_POLARITY;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+			temp |= LVDS_VSYNC_POLARITY;
+		I915_WRITE(PCH_LVDS, temp);
+	}
+
+	if (is_dp && !is_cpu_edp) {
+		intel_dp_set_m_n(crtc, mode, adjusted_mode);
+	} else {
+		/* For non-DP output, clear any trans DP clock recovery setting.*/
+		I915_WRITE(TRANSDATA_M1(pipe), 0);
+		I915_WRITE(TRANSDATA_N1(pipe), 0);
+		I915_WRITE(TRANSDPLINK_M1(pipe), 0);
+		I915_WRITE(TRANSDPLINK_N1(pipe), 0);
+	}
+
+	if (intel_crtc->pch_pll) {
+		I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+
+		/* Wait for the clocks to stabilize. */
+		POSTING_READ(intel_crtc->pch_pll->pll_reg);
+		udelay(150);
+
+		/* The pixel multiplier can only be updated once the
+		 * DPLL is enabled and the clocks are stable.
+		 *
+		 * So write it again.
+		 */
+		I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+	}
+
+	intel_crtc->lowfreq_avail = false;
+	if (intel_crtc->pch_pll) {
+		if (is_lvds && has_reduced_clock && i915_powersave) {
+			I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
+			intel_crtc->lowfreq_avail = true;
+		} else {
+			I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
+		}
+	}
+
+	intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
+
+	ironlake_set_m_n(crtc, mode, adjusted_mode);
+
+	if (is_cpu_edp)
+		ironlake_set_pll_edp(crtc, adjusted_mode->clock);
+
+	ironlake_set_pipeconf(crtc, adjusted_mode, dither);
+
+	intel_wait_for_vblank(dev, pipe);
+
+	/* Set up the display plane register */
+	I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
+	POSTING_READ(DSPCNTR(plane));
+
+	ret = intel_pipe_set_base(crtc, x, y, fb);
+
+	intel_update_watermarks(dev);
+
+	intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
+
+	return ret;
+}
+
 static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode,
@@ -7861,14 +8044,17 @@ static void intel_init_display(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* We always want a DPMS function */
-	if (HAS_PCH_SPLIT(dev)) {
+	if (IS_HASWELL(dev)) {
+		dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
+		dev_priv->display.crtc_enable = ironlake_crtc_enable;
+		dev_priv->display.crtc_disable = ironlake_crtc_disable;
+		dev_priv->display.off = haswell_crtc_off;
+		dev_priv->display.update_plane = ironlake_update_plane;
+	} else if (HAS_PCH_SPLIT(dev)) {
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
 		dev_priv->display.crtc_enable = ironlake_crtc_enable;
 		dev_priv->display.crtc_disable = ironlake_crtc_disable;
-		if (IS_HASWELL(dev))
-			dev_priv->display.off = haswell_crtc_off;
-		else
-			dev_priv->display.off = ironlake_crtc_off;
+		dev_priv->display.off = ironlake_crtc_off;
 		dev_priv->display.update_plane = ironlake_update_plane;
 	} else {
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
-- 
1.7.10.4

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

* [PATCH 08/47] drm/i915: add proper CPU/PCH checks to crtc_mode_set functions
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (6 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 07/47] drm/i915: add haswell_crtc_mode_set Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 09/47] drm/i915: add haswell_set_pipeconf Paulo Zanoni
                   ` (39 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

On ironlake_crtc_mode_set, WARN if not using IBX or CPT.

On haswell_crtc_mode_set, only run IBX/CPT code on IBX/CPT. I am still
not sure whether IBX/CPT will be possible with a Haswell CPU, so leave
the code there for now and put a WARN in case we spot it.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f7962e7..cd8ad15 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5007,9 +5007,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		num_connectors++;
 	}
 
-	if (IS_HASWELL(dev))
-		if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
-			return -EINVAL;
+	WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
+	     "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
 
 	ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
 				     &has_reduced_clock, &reduced_clock);
@@ -5036,12 +5035,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 	drm_mode_debug_printmodeline(mode);
 
-	/* CPU eDP is the only output that doesn't need a PCH PLL of its own on
-	 * pre-Haswell/LPT generation */
-	if (HAS_PCH_LPT(dev)) {
-		DRM_DEBUG_KMS("LPT detected: no PLL for pipe %d necessary\n",
-				pipe);
-	} else if (!is_cpu_edp) {
+	/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
+	if (!is_cpu_edp) {
 		struct intel_pch_pll *pll;
 
 		pll = intel_get_pch_pll(intel_crtc, dpll, fp);
@@ -5164,7 +5159,7 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	int plane = intel_crtc->plane;
 	int num_connectors = 0;
 	intel_clock_t clock, reduced_clock;
-	u32 dpll, fp = 0, fp2 = 0;
+	u32 dpll = 0, fp = 0, fp2 = 0;
 	bool ok, has_reduced_clock = false;
 	bool is_lvds = false, is_dp = false, is_cpu_edp = false;
 	struct intel_encoder *encoder;
@@ -5190,15 +5185,23 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 		num_connectors++;
 	}
 
-	if (IS_HASWELL(dev))
-		if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
-			return -EINVAL;
+	WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n",
+	     INTEL_PCH_TYPE(dev));
 
-	ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
-				     &has_reduced_clock, &reduced_clock);
-	if (!ok) {
-		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+	WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
+	     num_connectors, pipe_name(pipe));
+
+	if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
 		return -EINVAL;
+
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+		ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+					     &has_reduced_clock,
+					     &reduced_clock);
+		if (!ok) {
+			DRM_ERROR("Couldn't find PLL settings for mode!\n");
+			return -EINVAL;
+		}
 	}
 
 	/* Ensure that the cursor is valid for the new mode before changing... */
@@ -5209,104 +5212,112 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	if (is_lvds && dev_priv->lvds_dither)
 		dither = true;
 
-	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
-	if (has_reduced_clock)
-		fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
-			reduced_clock.m2;
-
-	dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock, fp);
-
 	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 	drm_mode_debug_printmodeline(mode);
 
-	/* CPU eDP is the only output that doesn't need a PCH PLL of its own on
-	 * pre-Haswell/LPT generation */
-	if (HAS_PCH_LPT(dev)) {
-		DRM_DEBUG_KMS("LPT detected: no PLL for pipe %d necessary\n",
-				pipe);
-	} else if (!is_cpu_edp) {
-		struct intel_pch_pll *pll;
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+		fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+		if (has_reduced_clock)
+			fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
+			      reduced_clock.m2;
+
+		dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock,
+					     fp);
+
+		/* CPU eDP is the only output that doesn't need a PCH PLL of its
+		 * own on pre-Haswell/LPT generation */
+		if (!is_cpu_edp) {
+			struct intel_pch_pll *pll;
+
+			pll = intel_get_pch_pll(intel_crtc, dpll, fp);
+			if (pll == NULL) {
+				DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
+						 pipe);
+				return -EINVAL;
+			}
+		} else
+			intel_put_pch_pll(intel_crtc);
 
-		pll = intel_get_pch_pll(intel_crtc, dpll, fp);
-		if (pll == NULL) {
-			DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
-					 pipe);
-			return -EINVAL;
-		}
-	} else
-		intel_put_pch_pll(intel_crtc);
+		/* The LVDS pin pair needs to be on before the DPLLs are
+		 * enabled.  This is an exception to the general rule that
+		 * mode_set doesn't turn things on.
+		 */
+		if (is_lvds) {
+			temp = I915_READ(PCH_LVDS);
+			temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
+			if (HAS_PCH_CPT(dev)) {
+				temp &= ~PORT_TRANS_SEL_MASK;
+				temp |= PORT_TRANS_SEL_CPT(pipe);
+			} else {
+				if (pipe == 1)
+					temp |= LVDS_PIPEB_SELECT;
+				else
+					temp &= ~LVDS_PIPEB_SELECT;
+			}
 
-	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
-	 * This is an exception to the general rule that mode_set doesn't turn
-	 * things on.
-	 */
-	if (is_lvds) {
-		temp = I915_READ(PCH_LVDS);
-		temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-		if (HAS_PCH_CPT(dev)) {
-			temp &= ~PORT_TRANS_SEL_MASK;
-			temp |= PORT_TRANS_SEL_CPT(pipe);
-		} else {
-			if (pipe == 1)
-				temp |= LVDS_PIPEB_SELECT;
+			/* set the corresponsding LVDS_BORDER bit */
+			temp |= dev_priv->lvds_border_bits;
+			/* Set the B0-B3 data pairs corresponding to whether
+			 * we're going to set the DPLLs for dual-channel mode or
+			 * not.
+			 */
+			if (clock.p2 == 7)
+				temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
 			else
-				temp &= ~LVDS_PIPEB_SELECT;
+				temp &= ~(LVDS_B0B3_POWER_UP |
+					  LVDS_CLKB_POWER_UP);
+
+			/* It would be nice to set 24 vs 18-bit mode
+			 * (LVDS_A3_POWER_UP) appropriately here, but we need to
+			 * look more thoroughly into how panels behave in the
+			 * two modes.
+			 */
+			temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
+			if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+				temp |= LVDS_HSYNC_POLARITY;
+			if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+				temp |= LVDS_VSYNC_POLARITY;
+			I915_WRITE(PCH_LVDS, temp);
 		}
-
-		/* set the corresponsding LVDS_BORDER bit */
-		temp |= dev_priv->lvds_border_bits;
-		/* Set the B0-B3 data pairs corresponding to whether we're going to
-		 * set the DPLLs for dual-channel mode or not.
-		 */
-		if (clock.p2 == 7)
-			temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
-		else
-			temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
-
-		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
-		 * appropriately here, but we need to look more thoroughly into how
-		 * panels behave in the two modes.
-		 */
-		temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
-		if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
-			temp |= LVDS_HSYNC_POLARITY;
-		if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
-			temp |= LVDS_VSYNC_POLARITY;
-		I915_WRITE(PCH_LVDS, temp);
 	}
 
 	if (is_dp && !is_cpu_edp) {
 		intel_dp_set_m_n(crtc, mode, adjusted_mode);
 	} else {
-		/* For non-DP output, clear any trans DP clock recovery setting.*/
-		I915_WRITE(TRANSDATA_M1(pipe), 0);
-		I915_WRITE(TRANSDATA_N1(pipe), 0);
-		I915_WRITE(TRANSDPLINK_M1(pipe), 0);
-		I915_WRITE(TRANSDPLINK_N1(pipe), 0);
-	}
-
-	if (intel_crtc->pch_pll) {
-		I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
-
-		/* Wait for the clocks to stabilize. */
-		POSTING_READ(intel_crtc->pch_pll->pll_reg);
-		udelay(150);
-
-		/* The pixel multiplier can only be updated once the
-		 * DPLL is enabled and the clocks are stable.
-		 *
-		 * So write it again.
-		 */
-		I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+		if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+			/* For non-DP output, clear any trans DP clock recovery
+			 * setting.*/
+			I915_WRITE(TRANSDATA_M1(pipe), 0);
+			I915_WRITE(TRANSDATA_N1(pipe), 0);
+			I915_WRITE(TRANSDPLINK_M1(pipe), 0);
+			I915_WRITE(TRANSDPLINK_N1(pipe), 0);
+		}
 	}
 
 	intel_crtc->lowfreq_avail = false;
-	if (intel_crtc->pch_pll) {
-		if (is_lvds && has_reduced_clock && i915_powersave) {
-			I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
-			intel_crtc->lowfreq_avail = true;
-		} else {
-			I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+		if (intel_crtc->pch_pll) {
+			I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+
+			/* Wait for the clocks to stabilize. */
+			POSTING_READ(intel_crtc->pch_pll->pll_reg);
+			udelay(150);
+
+			/* The pixel multiplier can only be updated once the
+			 * DPLL is enabled and the clocks are stable.
+			 *
+			 * So write it again.
+			 */
+			I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+		}
+
+		if (intel_crtc->pch_pll) {
+			if (is_lvds && has_reduced_clock && i915_powersave) {
+				I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
+				intel_crtc->lowfreq_avail = true;
+			} else {
+				I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
+			}
 		}
 	}
 
@@ -5314,8 +5325,9 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 
 	ironlake_set_m_n(crtc, mode, adjusted_mode);
 
-	if (is_cpu_edp)
-		ironlake_set_pll_edp(crtc, adjusted_mode->clock);
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+		if (is_cpu_edp)
+			ironlake_set_pll_edp(crtc, adjusted_mode->clock);
 
 	ironlake_set_pipeconf(crtc, adjusted_mode, dither);
 
-- 
1.7.10.4

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

* [PATCH 09/47] drm/i915: add haswell_set_pipeconf
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (7 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 08/47] drm/i915: add proper CPU/PCH checks to crtc_mode_set functions Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-04 14:36   ` Lespiau, Damien
  2012-10-02 20:51 ` [PATCH 10/47] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set Paulo Zanoni
                   ` (38 subsequent siblings)
  47 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

It's a copy of ironlake_set_pipeconf with 2 differences:
  - There is no BPC field to set.
  - The interlaced mask is now 2 bits instead of 3.

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

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2932cfc..ec58a23 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2638,6 +2638,7 @@
 #define   PIPECONF_GAMMA		(1<<24)
 #define   PIPECONF_FORCE_BORDER	(1<<25)
 #define   PIPECONF_INTERLACE_MASK	(7 << 21)
+#define   PIPECONF_INTERLACE_MASK_HSW	(3 << 21)
 /* Note that pre-gen3 does not support interlaced display directly. Panel
  * fitting must be disabled on pre-ilk for interlaced. */
 #define   PIPECONF_PROGRESSIVE			(0 << 21)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cd8ad15..a6562a8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4726,6 +4726,31 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
 	POSTING_READ(PIPECONF(pipe));
 }
 
+static void haswell_set_pipeconf(struct drm_crtc *crtc,
+				 struct drm_display_mode *adjusted_mode,
+				 bool dither)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	uint32_t val;
+
+	val = I915_READ(PIPECONF(pipe));
+
+	val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
+	if (dither)
+		val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
+
+	val &= ~PIPECONF_INTERLACE_MASK_HSW;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+		val |= PIPECONF_INTERLACED_ILK;
+	else
+		val |= PIPECONF_PROGRESSIVE;
+
+	I915_WRITE(PIPECONF(pipe), val);
+	POSTING_READ(PIPECONF(pipe));
+}
+
 static bool ironlake_compute_clocks(struct drm_crtc *crtc,
 				    struct drm_display_mode *adjusted_mode,
 				    intel_clock_t *clock,
@@ -5329,7 +5354,7 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 		if (is_cpu_edp)
 			ironlake_set_pll_edp(crtc, adjusted_mode->clock);
 
-	ironlake_set_pipeconf(crtc, adjusted_mode, dither);
+	haswell_set_pipeconf(crtc, adjusted_mode, dither);
 
 	intel_wait_for_vblank(dev, pipe);
 
-- 
1.7.10.4

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

* [PATCH 10/47] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (8 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 09/47] drm/i915: add haswell_set_pipeconf Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-04 14:14   ` Lespiau, Damien
  2012-10-02 20:51 ` [PATCH 11/47] drm/i915: add DP support to intel_ddi_enable_pipe_func Paulo Zanoni
                   ` (37 subsequent siblings)
  47 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

So WARN in case they're not. It also does not make any sense to
wait_for_vblank at this point.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a6562a8..5080b53 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5216,6 +5216,11 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
 	     num_connectors, pipe_name(pipe));
 
+	WARN_ON(I915_READ(PIPECONF(pipe)) &
+		(PIPECONF_ENABLE | I965_PIPECONF_ACTIVE));
+
+	WARN_ON(I915_READ(DSPCNTR(plane)) & DISPLAY_PLANE_ENABLE);
+
 	if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
 		return -EINVAL;
 
@@ -5356,8 +5361,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 
 	haswell_set_pipeconf(crtc, adjusted_mode, dither);
 
-	intel_wait_for_vblank(dev, pipe);
-
 	/* Set up the display plane register */
 	I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
 	POSTING_READ(DSPCNTR(plane));
-- 
1.7.10.4

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

* [PATCH 11/47] drm/i915: add DP support to intel_ddi_enable_pipe_func
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (9 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 10/47] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 12/47] drm/i915: add intel_ddi_set_pipe_settings Paulo Zanoni
                   ` (36 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 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 |   33 +++++++++++++++++++++++++++++----
 drivers/gpu/drm/i915/intel_dp.c  |    5 -----
 drivers/gpu/drm/i915/intel_drv.h |    5 +++++
 3 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 2965fb7..cf1bb99 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -831,8 +831,10 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 	enum pipe pipe = intel_crtc->pipe;
+	int type = intel_encoder->type;
 	uint32_t temp;
 
 	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
@@ -861,9 +863,8 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 	if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
 		temp |= PIPE_DDI_PHSYNC;
 
-	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-		struct intel_hdmi *intel_hdmi =
-			enc_to_intel_hdmi(&intel_encoder->base);
+	if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 
 		if (intel_hdmi->has_hdmi_sink)
 			temp |= PIPE_DDI_MODE_SELECT_HDMI;
@@ -871,9 +872,33 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 			temp |= PIPE_DDI_MODE_SELECT_DVI;
 
 		temp |= PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port);
-	} else if (intel_encoder->type == INTEL_OUTPUT_ANALOG) {
+
+	} else if (type == INTEL_OUTPUT_ANALOG) {
 		temp |= PIPE_DDI_MODE_SELECT_FDI;
 		temp |= PIPE_DDI_SELECT_PORT(PORT_E);
+
+	} else if (type == INTEL_OUTPUT_DISPLAYPORT ||
+		   type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		temp |= PIPE_DDI_MODE_SELECT_DP_SST;
+		temp |= PIPE_DDI_SELECT_PORT(intel_dp->port);
+
+		switch (intel_dp->lane_count) {
+		case 1:
+			temp |= PIPE_DDI_PORT_WIDTH_X1;
+			break;
+		case 2:
+			temp |= PIPE_DDI_PORT_WIDTH_X2;
+			break;
+		case 4:
+			temp |= PIPE_DDI_PORT_WIDTH_X4;
+			break;
+		default:
+			WARN(1, "Unsupported lane count %d\n",
+			     intel_dp->lane_count);
+		}
+
 	} else {
 		WARN(1, "Invalid encoder type %d for pipe %d\n",
 		     intel_encoder->type, pipe);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index fcce392..871bc17 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -77,11 +77,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 245319a..7e1e670 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -474,6 +474,11 @@ 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);
 extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
-- 
1.7.10.4

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

* [PATCH 12/47] drm/i915: add intel_ddi_set_pipe_settings
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (10 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 11/47] drm/i915: add DP support to intel_ddi_enable_pipe_func Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 13/47] drm/i915: add DP support to intel_ddi_pll_mode_set Paulo Zanoni
                   ` (35 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

In theory, all the DDI pipe settings should be set here, including
timing and M/N registers. For now, let's just set the DP MSA
attributes.

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     |   33 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c |    4 +++-
 drivers/gpu/drm/i915/intel_drv.h     |    1 +
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ec58a23..9318121 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4526,6 +4526,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 cf1bb99..fc6679c 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -827,6 +827,39 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
 	return true;
 }
 
+void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	enum pipe pipe = intel_crtc->pipe;
+	int type = intel_encoder->type;
+	uint32_t temp;
+
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
+
+		temp = PIPE_MSA_SYNC_CLK;
+		switch (intel_crtc->bpp) {
+		case 18:
+			temp |= PIPE_MSA_6_BPC;
+			break;
+		case 24:
+			temp |= PIPE_MSA_8_BPC;
+			break;
+		case 30:
+			temp |= PIPE_MSA_10_BPC;
+			break;
+		case 36:
+			temp |= PIPE_MSA_12_BPC;
+			break;
+		default:
+			WARN(1, "%d bpp unsupported by pipe DDI function\n",
+			     intel_crtc->bpp);
+		}
+		I915_WRITE(PIPE_MSA_MISC(pipe), temp);
+	}
+}
+
 void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5080b53..7f0016a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3218,8 +3218,10 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	 */
 	intel_crtc_load_lut(crtc);
 
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev)) {
+		intel_ddi_set_pipe_settings(crtc);
 		intel_ddi_enable_pipe_func(crtc);
+	}
 
 	intel_enable_pipe(dev_priv, pipe, is_pch_port);
 	intel_enable_plane(dev_priv, plane, pipe);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 7e1e670..ed75a36 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -597,5 +597,6 @@ extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock);
 extern void intel_ddi_pre_enable(struct intel_encoder *intel_encoder);
 extern void intel_ddi_post_disable(struct intel_encoder *intel_encoder);
 extern void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
+extern void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.10.4

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

* [PATCH 13/47] drm/i915: add DP support to intel_ddi_pll_mode_set
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (11 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 12/47] drm/i915: add intel_ddi_set_pipe_settings Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 14/47] drm/i915: add DP support to intel_ddi_disable_port Paulo Zanoni
                   ` (34 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 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 |   25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index fc6679c..ad3ecd6 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -763,6 +763,7 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
 	int type = intel_encoder->type;
@@ -773,7 +774,29 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
 
 	intel_ddi_put_crtc_pll(crtc);
 
-	if (type == INTEL_OUTPUT_HDMI) {
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		switch (intel_dp->link_bw) {
+		case DP_LINK_BW_1_62:
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
+			break;
+		case DP_LINK_BW_2_7:
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
+			break;
+		case DP_LINK_BW_5_4:
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
+			break;
+		default:
+			DRM_ERROR("Link bandwidth %d unsupported\n",
+				  intel_dp->link_bw);
+			return false;
+		}
+
+		/* We don't need to turn any PLL on because we'll use LCPLL. */
+		return true;
+
+	} else if (type == INTEL_OUTPUT_HDMI) {
 		int p, n2, r2;
 
 		if (plls->wrpll1_refcount == 0) {
-- 
1.7.10.4

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

* [PATCH 14/47] drm/i915: add DP support to intel_ddi_disable_port
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (12 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 13/47] drm/i915: add DP support to intel_ddi_pll_mode_set Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 15/47] drm/i915: add DP support to intel_ddi_mode_set Paulo Zanoni
                   ` (33 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 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 |   11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index ad3ecd6..03a9d34 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1103,14 +1103,23 @@ void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
 	enum port port = intel_ddi_get_encoder_port(intel_encoder);
 	uint32_t val;
+	bool wait = false;
 
 	val = I915_READ(DDI_BUF_CTL(port));
 	if (val & DDI_BUF_CTL_ENABLE) {
 		val &= ~DDI_BUF_CTL_ENABLE;
 		I915_WRITE(DDI_BUF_CTL(port), val);
-		intel_wait_ddi_buf_idle(dev_priv, port);
+		wait = true;
 	}
 
+	val = I915_READ(DP_TP_CTL(port));
+	val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
+	val |= DP_TP_CTL_LINK_TRAIN_PAT1;
+	I915_WRITE(DP_TP_CTL(port), val);
+
+	if (wait)
+		intel_wait_ddi_buf_idle(dev_priv, port);
+
 	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
 }
 
-- 
1.7.10.4

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

* [PATCH 15/47] drm/i915: add DP support to intel_ddi_mode_set
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (13 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 14/47] drm/i915: add DP support to intel_ddi_disable_port Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 16/47] drm/i915: add basic Haswell DP link train bits Paulo Zanoni
                   ` (32 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 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 |   61 +++++++++++++++++++++++++++-----------
 drivers/gpu/drm/i915/intel_dp.c  |   28 ++++++++++-------
 drivers/gpu/drm/i915/intel_drv.h |    1 +
 3 files changed, 62 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 03a9d34..7f30992 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -644,28 +644,55 @@ 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);
+	int port = intel_ddi_get_encoder_port(intel_encoder);
 	int pipe = intel_crtc->pipe;
+	int type = intel_encoder->type;
 
-	/* 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));
+	DRM_DEBUG_KMS("Preparing DDI mode for Haswell on port %c, pipe %c\n",
+		      port_name(port), pipe_name(pipe));
 
-	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));
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-		/* write eld */
-		DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
-		intel_write_eld(encoder, adjusted_mode);
-	}
+		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_hdmi->set_infoframes(encoder, adjusted_mode);
+	} else if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+
+		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);
+		}
+
+		intel_hdmi->set_infoframes(encoder, adjusted_mode);
+	}
 }
 
 static struct intel_encoder *
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 871bc17..3fa71cd 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -815,6 +815,21 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	}
 }
 
+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)
@@ -867,17 +882,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 ed75a36..d89d428 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -422,6 +422,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.10.4

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

* [PATCH 16/47] drm/i915: add basic Haswell DP link train bits
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (14 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 15/47] drm/i915: add DP support to intel_ddi_mode_set Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 17/47] drm/i915: use TU_SIZE macro at intel_dp_set_m_n Paulo Zanoni
                   ` (31 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 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 9318121..a907d5b0 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4419,12 +4419,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 3fa71cd..b10f35b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1476,7 +1476,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) && !IS_VALLEYVIEW(dev)) {
+	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) && !IS_VALLEYVIEW(dev)) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 		case DP_TRAIN_VOLTAGE_SWING_400:
 			return DP_TRAIN_PRE_EMPHASIS_6;
@@ -1630,6 +1642,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)
@@ -1686,8 +1732,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) {
@@ -1774,8 +1856,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) && !IS_VALLEYVIEW(dev)) {
+		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) && !IS_VALLEYVIEW(dev)) {
 			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)) {
@@ -1783,9 +1868,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 |
@@ -1861,7 +1947,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 			break;
 		}
 
-		if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) {
+		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) && !IS_VALLEYVIEW(dev)) {
 			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)) {
@@ -1908,6 +1997,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.10.4

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

* [PATCH 17/47] drm/i915: use TU_SIZE macro at intel_dp_set_m_n
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (15 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 16/47] drm/i915: add basic Haswell DP link train bits Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 18/47] drm/i915: fix Haswell DP M/N registers Paulo Zanoni
                   ` (30 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Much simpler and looks more like the M/N code inside intel_display.c.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b10f35b..52b5453 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -794,9 +794,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 			     mode->clock, adjusted_mode->clock, &m_n);
 
 	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);
+		I915_WRITE(TRANSDATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
 		I915_WRITE(TRANSDATA_N1(pipe), m_n.gmch_n);
 		I915_WRITE(TRANSDPLINK_M1(pipe), m_n.link_m);
 		I915_WRITE(TRANSDPLINK_N1(pipe), m_n.link_n);
@@ -807,8 +805,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n);
 	} else {
 		I915_WRITE(PIPE_GMCH_DATA_M(pipe),
-			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
-			   m_n.gmch_m);
+			   TU_SIZE(m_n.tu) | m_n.gmch_m);
 		I915_WRITE(PIPE_GMCH_DATA_N(pipe), m_n.gmch_n);
 		I915_WRITE(PIPE_DP_LINK_M(pipe), m_n.link_m);
 		I915_WRITE(PIPE_DP_LINK_N(pipe), m_n.link_n);
-- 
1.7.10.4

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

* [PATCH 18/47] drm/i915: fix Haswell DP M/N registers
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (16 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 17/47] drm/i915: use TU_SIZE macro at intel_dp_set_m_n Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 19/47] drm/i915: fix DP AUX register definitions on Haswell Paulo Zanoni
                   ` (29 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 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
prevent these values from being overwritten later.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7f0016a..a83cd99 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5355,7 +5355,8 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 
 	intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
 
-	ironlake_set_m_n(crtc, mode, adjusted_mode);
+	if (!(is_dp && !is_cpu_edp))
+		ironlake_set_m_n(crtc, mode, adjusted_mode);
 
 	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
 		if (is_cpu_edp)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 52b5453..22702df 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -793,7 +793,12 @@ 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), 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);
+	} else if (HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(TRANSDATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m);
 		I915_WRITE(TRANSDATA_N1(pipe), m_n.gmch_n);
 		I915_WRITE(TRANSDPLINK_M1(pipe), m_n.link_m);
-- 
1.7.10.4

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

* [PATCH 19/47] drm/i915: fix DP AUX register definitions on Haswell
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (17 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 18/47] drm/i915: fix Haswell DP M/N registers Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 20/47] drm/i915: add DP support to intel_ddi_get_encoder_port Paulo Zanoni
                   ` (28 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 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 a907d5b0..982985c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2547,6 +2547,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 22702df..a40df1e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -356,6 +356,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.10.4

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

* [PATCH 20/47] drm/i915: add DP support to intel_ddi_get_encoder_port
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (18 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 19/47] drm/i915: fix DP AUX register definitions on Haswell Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 21/47] drm/i915: add DP support to intel_ddi_get_hw_state Paulo Zanoni
                   ` (27 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 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, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 7f30992..60e089c 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -60,14 +60,20 @@ static const u32 hsw_ddi_translations_fdi[] = {
 
 static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
 {
+	struct drm_encoder *encoder = &intel_encoder->base;
 	int type = intel_encoder->type;
 
-	if (type == INTEL_OUTPUT_HDMI) {
-		struct intel_hdmi *intel_hdmi =
-			enc_to_intel_hdmi(&intel_encoder->base);
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+		return intel_dp->port;
+
+	} else if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 		return intel_hdmi->ddi_port;
+
 	} else if (type == INTEL_OUTPUT_ANALOG) {
 		return PORT_E;
+
 	} else {
 		DRM_ERROR("Invalid DDI encoder type %d\n", type);
 		BUG();
-- 
1.7.10.4

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

* [PATCH 21/47] drm/i915: add DP support to intel_ddi_get_hw_state
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (19 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 20/47] drm/i915: add DP support to intel_ddi_get_encoder_port Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 22/47] drm/i915: add DP support to intel_enable_ddi Paulo Zanoni
                   ` (26 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 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 |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 60e089c..57dd975 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1012,11 +1012,11 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 {
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	enum port port = intel_ddi_get_encoder_port(encoder);
 	u32 tmp;
 	int i;
 
-	tmp = I915_READ(DDI_BUF_CTL(intel_hdmi->ddi_port));
+	tmp = I915_READ(DDI_BUF_CTL(port));
 
 	if (!(tmp & DDI_BUF_CTL_ENABLE))
 		return false;
@@ -1025,13 +1025,13 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 		tmp = I915_READ(DDI_FUNC_CTL(i));
 
 		if ((tmp & PIPE_DDI_PORT_MASK)
-		    == PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port)) {
+		    == PIPE_DDI_SELECT_PORT(port)) {
 			*pipe = i;
 			return true;
 		}
 	}
 
-	DRM_DEBUG_KMS("No pipe for ddi port %i found\n", intel_hdmi->ddi_port);
+	DRM_DEBUG_KMS("No pipe for ddi port %i found\n", port);
 
 	return true;
 }
-- 
1.7.10.4

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

* [PATCH 22/47] drm/i915: add DP support to intel_enable_ddi
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (20 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 21/47] drm/i915: add DP support to intel_ddi_get_hw_state Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 23/47] drm/i915: implement Haswell DP link train sequence Paulo Zanoni
                   ` (25 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

We should only write the DDI_BUF_CTL at this point for HDMI/DVI. For
DP we need to do this earlier, and the values written to the register
are also different.

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 57dd975..154fec7 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1156,18 +1156,21 @@ void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
 	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
 }
 
-void intel_enable_ddi(struct intel_encoder *encoder)
+void intel_enable_ddi(struct intel_encoder *intel_encoder)
 {
-	struct drm_device *dev = 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_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
-	int port = intel_hdmi->ddi_port;
-
-	/* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width,
-	 * and swing/emphasis values are ignored so nothing special needs
-	 * to be done besides enabling the port.
-	 */
-	I915_WRITE(DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE);
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_HDMI) {
+		/* In HDMI/DVI mode, the port width, and swing/emphasis values
+		 * are ignored so nothing special needs to be done besides
+		 * enabling the port.
+		 */
+		I915_WRITE(DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE);
+	}
 }
 
 void intel_disable_ddi(struct intel_encoder *encoder)
-- 
1.7.10.4

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

* [PATCH 23/47] drm/i915: implement Haswell DP link train sequence
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (21 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 22/47] drm/i915: add DP support to intel_enable_ddi Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:51 ` [PATCH 24/47] drm/i915: set the correct function pointers for Haswell DP Paulo Zanoni
                   ` (24 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Previous patch "drm/i915: add basic Haswell DP link train bits"
implemented the basic structure to set the voltage levels and training
patterns. This patch adds the higher-level bits that are part of the
mode set sequence and hot plug.

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 154fec7..c014652 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1106,14 +1106,23 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
 
 void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 {
-	struct drm_crtc *crtc = intel_encoder->base.crtc;
-	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct drm_encoder *encoder = &intel_encoder->base;
+	struct drm_crtc *crtc = encoder->crtc;
+	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	enum port port = intel_ddi_get_encoder_port(intel_encoder);
 
 	WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
 
 	I915_WRITE(PORT_CLK_SEL(port), intel_crtc->ddi_pll_sel);
+
+	if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+		intel_dp_start_link_train(intel_dp);
+		intel_dp_complete_link_train(intel_dp);
+	}
 }
 
 static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
@@ -1217,3 +1226,43 @@ void intel_ddi_pll_init(struct drm_device *dev)
 	if (lcpll_needs_change)
 		I915_WRITE(LCPLL_CTL, lcpll_val);
 }
+
+void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+	enum port port = intel_dp->port;
+	bool wait;
+	uint32_t val;
+
+	if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) {
+		val = I915_READ(DDI_BUF_CTL(port));
+		if (val & DDI_BUF_CTL_ENABLE) {
+			val &= ~DDI_BUF_CTL_ENABLE;
+			I915_WRITE(DDI_BUF_CTL(port), val);
+			wait = true;
+		}
+
+		val = I915_READ(DP_TP_CTL(port));
+		val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
+		val |= DP_TP_CTL_LINK_TRAIN_PAT1;
+		I915_WRITE(DP_TP_CTL(port), val);
+		POSTING_READ(DP_TP_CTL(port));
+
+		if (wait)
+			intel_wait_ddi_buf_idle(dev_priv, port);
+	}
+
+	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)
+		val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
+	I915_WRITE(DP_TP_CTL(port), 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);
+}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a40df1e..72fc184 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -102,8 +102,6 @@ bool intel_encoder_is_pch_edp(struct drm_encoder *encoder)
 	return is_pch_edp(intel_dp);
 }
 
-static void intel_dp_start_link_train(struct intel_dp *intel_dp);
-static void intel_dp_complete_link_train(struct intel_dp *intel_dp);
 static void intel_dp_link_down(struct intel_dp *intel_dp);
 
 void
@@ -1267,7 +1265,7 @@ static void ironlake_edp_pll_off(struct intel_dp *intel_dp)
 }
 
 /* If the sink supports it, try to set the power state appropriately */
-static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
+void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
 {
 	int ret, i;
 
@@ -1855,16 +1853,20 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 }
 
 /* Enable corresponding port and start training pattern 1 */
-static void
+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;
 	int i;
 	uint8_t voltage;
 	bool clock_recovery = false;
 	int voltage_tries, loop_tries;
 	uint32_t DP = intel_dp->DP;
 
+	if (IS_HASWELL(dev))
+		intel_ddi_prepare_link_retrain(encoder);
+
 	/* Write the link configuration data */
 	intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
 				  intel_dp->link_configuration,
@@ -1950,7 +1952,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 	intel_dp->DP = DP;
 }
 
-static void
+void
 intel_dp_complete_link_train(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp->base.base.dev;
@@ -2036,6 +2038,24 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t DP = intel_dp->DP;
 
+	/*
+	 * DDI code has a strict mode set sequence and we should try to respect
+	 * it, otherwise we might hang the machine in many different ways. So we
+	 * really should be disabling the port only on a complete crtc_disable
+	 * sequence. This function is just called under two conditions on DDI
+	 * code:
+	 * - Link train failed while doing crtc_enable, and on this case we
+	 *   really should respect the mode set sequence and wait for a
+	 *   crtc_disable.
+	 * - Someone turned the monitor off and intel_dp_check_link_status
+	 *   called us. We don't need to disable the whole port on this case, so
+	 *   when someone turns the monitor on again,
+	 *   intel_ddi_prepare_link_retrain will take care of redoing the link
+	 *   train.
+	 */
+	if (IS_HASWELL(dev))
+		return;
+
 	if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0))
 		return;
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d89d428..95cbd67 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -423,6 +423,9 @@ 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_start_link_train(struct intel_dp *intel_dp);
+extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
+extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
 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 *,
@@ -599,5 +602,6 @@ extern void intel_ddi_pre_enable(struct intel_encoder *intel_encoder);
 extern void intel_ddi_post_disable(struct intel_encoder *intel_encoder);
 extern void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
 extern void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
+extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.10.4

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

* [PATCH 24/47] drm/i915: set the correct function pointers for Haswell DP
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (22 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 23/47] drm/i915: implement Haswell DP link train sequence Paulo Zanoni
@ 2012-10-02 20:51 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 25/47] drm/i915: add TRANSCODER_EDP Paulo Zanoni
                   ` (23 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:51 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

This is the final remaining piece of Haswell DP enablement. After this
patch, just calling intel_dp_init on any port will make DP work. We
still do not do this because we're currently initializing HDMI on all
the ports, so if we replace intel_hdmi_init with intel_dp_init, we
will break HDMI, and we can't call both because they share the same
registers.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 72fc184..a260531 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2554,6 +2554,12 @@ static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
 	.disable = intel_encoder_noop,
 };
 
+static const struct drm_encoder_helper_funcs intel_dp_helper_funcs_hsw = {
+	.mode_fixup = intel_dp_mode_fixup,
+	.mode_set = intel_ddi_mode_set,
+	.disable = intel_encoder_noop,
+};
+
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
 	.dpms = intel_connector_dpms,
 	.detect = intel_dp_detect,
@@ -2689,16 +2695,30 @@ 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);
 
-	intel_encoder->enable = intel_enable_dp;
-	intel_encoder->pre_enable = intel_pre_enable_dp;
-	intel_encoder->disable = intel_disable_dp;
-	intel_encoder->post_disable = intel_post_disable_dp;
-	intel_encoder->get_hw_state = intel_dp_get_hw_state;
+	if (IS_HASWELL(dev)) {
+		intel_encoder->enable = intel_enable_ddi;
+		intel_encoder->pre_enable = intel_ddi_pre_enable;
+		intel_encoder->disable = intel_disable_ddi;
+		intel_encoder->post_disable = intel_ddi_post_disable;
+		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
+	} else {
+		intel_encoder->enable = intel_enable_dp;
+		intel_encoder->pre_enable = intel_pre_enable_dp;
+		intel_encoder->disable = intel_disable_dp;
+		intel_encoder->post_disable = intel_post_disable_dp;
+		intel_encoder->get_hw_state = intel_dp_get_hw_state;
+	}
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	/* Set up the DDC bus. */
-- 
1.7.10.4

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

* [PATCH 25/47] drm/i915: add TRANSCODER_EDP
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (23 preceding siblings ...)
  2012-10-02 20:51 ` [PATCH 24/47] drm/i915: set the correct function pointers for Haswell DP Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 26/47] drm/i915: convert PIPE_CLK_SEL to transcoder Paulo Zanoni
                   ` (22 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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.

For now we're just creating the transcoder definitions and setting
transcoder to TRANSCODER_EDP on DDI eDP code, but none of the
registers was ported to use transcoder instead of pipe.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |    8 ++++++++
 drivers/gpu/drm/i915/i915_reg.h      |    1 +
 drivers/gpu/drm/i915/intel_display.c |   20 ++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    3 +++
 4 files changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index fc3761e..14ba368 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_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 982985c..de95698 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -26,6 +26,7 @@
 #define _I915_REG_H_
 
 #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
+#define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a)))
 
 #define _PORT(port, a, b) ((a) + (port)*((b)-(a)))
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a83cd99..0fccbe6 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;
@@ -3336,6 +3345,9 @@ static void ironlake_crtc_off(struct drm_crtc *crtc)
 
 static void haswell_crtc_off(struct drm_crtc *crtc)
 {
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	intel_crtc->transcoder = intel_crtc->pipe;
 	intel_ddi_put_crtc_pll(crtc);
 }
 
@@ -5184,6 +5196,7 @@ static int haswell_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 num_connectors = 0;
 	intel_clock_t clock, reduced_clock;
 	u32 dpll = 0, fp = 0, fp2 = 0;
@@ -5212,6 +5225,12 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 		num_connectors++;
 	}
 
+	if (is_cpu_edp)
+		transcoder = TRANSCODER_EDP;
+	else
+		transcoder = pipe;
+	intel_crtc->transcoder = transcoder;
+
 	WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n",
 	     INTEL_PCH_TYPE(dev));
 
@@ -7769,6 +7788,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_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 95cbd67..ca06ebb 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -185,6 +185,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];
 	/*
 	 * Whether the crtc and the connected output pipeline is active. Implies
@@ -491,6 +492,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.10.4

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

* [PATCH 26/47] drm/i915: convert PIPE_CLK_SEL to transcoder
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (24 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 25/47] drm/i915: add TRANSCODER_EDP Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 27/47] drm/i915: convert DDI_FUNC_CTL " Paulo Zanoni
                   ` (21 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

This register appeared in Haswell. It does not have an EDP version
because the EDP transcoder is always tied to the DDIA clock. Notice
that if we call PIPE_CLK_SEL(pipe) when pipe is PIPE_A and transcoder
is TRANSCODER_EDP we might introduce a bug, that's why this is a
transcoder register even though it does not have an EDP version.

Even though Haswell names this register PIPE_CLK_SEL, it will be
renamed to TRANS_CLK_SEL in the future, so let's just start using the
real name that makes more sense and avoids misusage.

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

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index de95698..1007f2d 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4531,13 +4531,13 @@
 #define  PORT_CLK_SEL_WRPLL2		(5<<29)
 #define  PORT_CLK_SEL_NONE		(7<<29)
 
-/* Pipe clock selection */
-#define PIPE_CLK_SEL_A			0x46140
-#define PIPE_CLK_SEL_B			0x46144
-#define PIPE_CLK_SEL(pipe) _PIPE(pipe, PIPE_CLK_SEL_A, PIPE_CLK_SEL_B)
-/* For each pipe, we need to select the corresponding port clock */
-#define  PIPE_CLK_SEL_DISABLED		(0x0<<29)
-#define  PIPE_CLK_SEL_PORT(x)		((x+1)<<29)
+/* Transcoder clock selection */
+#define TRANS_CLK_SEL_A			0x46140
+#define TRANS_CLK_SEL_B			0x46144
+#define TRANS_CLK_SEL(tran) _TRANSCODER(tran, TRANS_CLK_SEL_A, TRANS_CLK_SEL_B)
+/* For each transcoder, we need to select the corresponding port clock */
+#define  TRANS_CLK_SEL_DISABLED		(0x0<<29)
+#define  TRANS_CLK_SEL_PORT(x)		((x+1)<<29)
 
 #define _PIPEA_MSA_MISC			0x60410
 #define _PIPEB_MSA_MISC			0x61410
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index c014652..59d4999 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1093,15 +1093,19 @@ void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
 	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	enum transcoder transcoder = intel_crtc->transcoder;
 
-	I915_WRITE(PIPE_CLK_SEL(intel_crtc->pipe), PIPE_CLK_SEL_PORT(port));
+	if (transcoder != TRANSCODER_EDP)
+		I915_WRITE(TRANS_CLK_SEL(transcoder), TRANS_CLK_SEL_PORT(port));
 }
 
 void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
 {
 	struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
+	enum transcoder transcoder = intel_crtc->transcoder;
 
-	I915_WRITE(PIPE_CLK_SEL(intel_crtc->pipe), PIPE_CLK_SEL_DISABLED);
+	if (transcoder != TRANSCODER_EDP)
+		I915_WRITE(TRANS_CLK_SEL(transcoder), TRANS_CLK_SEL_DISABLED);
 }
 
 void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
-- 
1.7.10.4

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

* [PATCH 27/47] drm/i915: convert DDI_FUNC_CTL to transcoder
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (25 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 26/47] drm/i915: convert PIPE_CLK_SEL to transcoder Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 28/47] drm/i915: check TRANSCODER_EDP on intel_modeset_setup_hw_state Paulo Zanoni
                   ` (20 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Because there's one instance of the register per CPU transcoder and
not per CPU pipe. This is another register that appeared for the first
time on Haswell, and even though its Haswell name is
PIPE_DDI_FUNC_CTL, it will be renamed to TRANS_DDI_FUNC_CTL, so let's
just use the new naming scheme before it confuses more people.

Notice that there's a big improvement on intel_ddi_get_hw_state due to
the new TRANSCODER_EDP.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      |   59 ++++++++++----------
 drivers/gpu/drm/i915/intel_ddi.c     |   98 +++++++++++++++++++++-------------
 drivers/gpu/drm/i915/intel_display.c |    8 +--
 drivers/gpu/drm/i915/intel_drv.h     |    4 +-
 4 files changed, 101 insertions(+), 68 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 1007f2d..13d67c1 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4387,34 +4387,39 @@
 #define HSW_PWR_WELL_CTL6			0x45414
 
 /* Per-pipe DDI Function Control */
-#define PIPE_DDI_FUNC_CTL_A		0x60400
-#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  PIPE_DDI_FUNC_ENABLE		(1<<31)
+#define TRANS_DDI_FUNC_CTL_A		0x60400
+#define TRANS_DDI_FUNC_CTL_B		0x61400
+#define TRANS_DDI_FUNC_CTL_C		0x62400
+#define TRANS_DDI_FUNC_CTL_EDP		0x6F400
+#define DDI_FUNC_CTL(tran) _TRANSCODER(tran, TRANS_DDI_FUNC_CTL_A, \
+					     TRANS_DDI_FUNC_CTL_B)
+#define  TRANS_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_SELECT_PORT(x)	((x)<<28)
-#define  PIPE_DDI_PORT_NONE		(0<<28)
-#define  PIPE_DDI_MODE_SELECT_MASK	(7<<24)
-#define  PIPE_DDI_MODE_SELECT_HDMI	(0<<24)
-#define  PIPE_DDI_MODE_SELECT_DVI	(1<<24)
-#define  PIPE_DDI_MODE_SELECT_DP_SST	(2<<24)
-#define  PIPE_DDI_MODE_SELECT_DP_MST	(3<<24)
-#define  PIPE_DDI_MODE_SELECT_FDI	(4<<24)
-#define  PIPE_DDI_BPC_MASK		(7<<20)
-#define  PIPE_DDI_BPC_8			(0<<20)
-#define  PIPE_DDI_BPC_10		(1<<20)
-#define  PIPE_DDI_BPC_6			(2<<20)
-#define  PIPE_DDI_BPC_12		(3<<20)
-#define  PIPE_DDI_PVSYNC		(1<<17)
-#define  PIPE_DDI_PHSYNC		(1<<16)
-#define  PIPE_DDI_BFI_ENABLE		(1<<4)
-#define  PIPE_DDI_PORT_WIDTH_X1		(0<<1)
-#define  PIPE_DDI_PORT_WIDTH_X2		(1<<1)
-#define  PIPE_DDI_PORT_WIDTH_X4		(3<<1)
+#define  TRANS_DDI_PORT_MASK		(7<<28)
+#define  TRANS_DDI_SELECT_PORT(x)	((x)<<28)
+#define  TRANS_DDI_PORT_NONE		(0<<28)
+#define  TRANS_DDI_MODE_SELECT_MASK	(7<<24)
+#define  TRANS_DDI_MODE_SELECT_HDMI	(0<<24)
+#define  TRANS_DDI_MODE_SELECT_DVI	(1<<24)
+#define  TRANS_DDI_MODE_SELECT_DP_SST	(2<<24)
+#define  TRANS_DDI_MODE_SELECT_DP_MST	(3<<24)
+#define  TRANS_DDI_MODE_SELECT_FDI	(4<<24)
+#define  TRANS_DDI_BPC_MASK		(7<<20)
+#define  TRANS_DDI_BPC_8		(0<<20)
+#define  TRANS_DDI_BPC_10		(1<<20)
+#define  TRANS_DDI_BPC_6		(2<<20)
+#define  TRANS_DDI_BPC_12		(3<<20)
+#define  TRANS_DDI_PVSYNC		(1<<17)
+#define  TRANS_DDI_PHSYNC		(1<<16)
+#define  TRANS_DDI_EDP_INPUT_MASK	(7<<12)
+#define  TRANS_DDI_EDP_INPUT_A_ON	(0<<12)
+#define  TRANS_DDI_EDP_INPUT_A_ONOFF	(4<<12)
+#define  TRANS_DDI_EDP_INPUT_B_ONOFF	(5<<12)
+#define  TRANS_DDI_EDP_INPUT_C_ONOFF	(6<<12)
+#define  TRANS_DDI_BFI_ENABLE		(1<<4)
+#define  TRANS_DDI_PORT_WIDTH_X1	(0<<1)
+#define  TRANS_DDI_PORT_WIDTH_X2	(1<<1)
+#define  TRANS_DDI_PORT_WIDTH_X4	(3<<1)
 
 /* DisplayPort Transport Control */
 #define DP_TP_CTL_A			0x64040
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 59d4999..26aae8f 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -923,65 +923,66 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 	enum pipe pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	int type = intel_encoder->type;
 	uint32_t temp;
 
-	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
-	temp = PIPE_DDI_FUNC_ENABLE;
+	/* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */
+	temp = TRANS_DDI_FUNC_ENABLE;
 
 	switch (intel_crtc->bpp) {
 	case 18:
-		temp |= PIPE_DDI_BPC_6;
+		temp |= TRANS_DDI_BPC_6;
 		break;
 	case 24:
-		temp |= PIPE_DDI_BPC_8;
+		temp |= TRANS_DDI_BPC_8;
 		break;
 	case 30:
-		temp |= PIPE_DDI_BPC_10;
+		temp |= TRANS_DDI_BPC_10;
 		break;
 	case 36:
-		temp |= PIPE_DDI_BPC_12;
+		temp |= TRANS_DDI_BPC_12;
 		break;
 	default:
-		WARN(1, "%d bpp unsupported by pipe DDI function\n",
+		WARN(1, "%d bpp unsupported by transcoder DDI function\n",
 		     intel_crtc->bpp);
 	}
 
 	if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
-		temp |= PIPE_DDI_PVSYNC;
+		temp |= TRANS_DDI_PVSYNC;
 	if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
-		temp |= PIPE_DDI_PHSYNC;
+		temp |= TRANS_DDI_PHSYNC;
 
 	if (type == INTEL_OUTPUT_HDMI) {
 		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 
 		if (intel_hdmi->has_hdmi_sink)
-			temp |= PIPE_DDI_MODE_SELECT_HDMI;
+			temp |= TRANS_DDI_MODE_SELECT_HDMI;
 		else
-			temp |= PIPE_DDI_MODE_SELECT_DVI;
+			temp |= TRANS_DDI_MODE_SELECT_DVI;
 
-		temp |= PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port);
+		temp |= TRANS_DDI_SELECT_PORT(intel_hdmi->ddi_port);
 
 	} else if (type == INTEL_OUTPUT_ANALOG) {
-		temp |= PIPE_DDI_MODE_SELECT_FDI;
-		temp |= PIPE_DDI_SELECT_PORT(PORT_E);
+		temp |= TRANS_DDI_MODE_SELECT_FDI;
+		temp |= TRANS_DDI_SELECT_PORT(PORT_E);
 
 	} else if (type == INTEL_OUTPUT_DISPLAYPORT ||
 		   type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-		temp |= PIPE_DDI_MODE_SELECT_DP_SST;
-		temp |= PIPE_DDI_SELECT_PORT(intel_dp->port);
+		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
+		temp |= TRANS_DDI_SELECT_PORT(intel_dp->port);
 
 		switch (intel_dp->lane_count) {
 		case 1:
-			temp |= PIPE_DDI_PORT_WIDTH_X1;
+			temp |= TRANS_DDI_PORT_WIDTH_X1;
 			break;
 		case 2:
-			temp |= PIPE_DDI_PORT_WIDTH_X2;
+			temp |= TRANS_DDI_PORT_WIDTH_X2;
 			break;
 		case 4:
-			temp |= PIPE_DDI_PORT_WIDTH_X4;
+			temp |= TRANS_DDI_PORT_WIDTH_X4;
 			break;
 		default:
 			WARN(1, "Unsupported lane count %d\n",
@@ -993,17 +994,17 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 		     intel_encoder->type, pipe);
 	}
 
-	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+	I915_WRITE(DDI_FUNC_CTL(transcoder), temp);
 }
 
-void intel_ddi_disable_pipe_func(struct drm_i915_private *dev_priv,
-				 enum pipe pipe)
+void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
+				       enum transcoder transcoder)
 {
-	uint32_t reg = DDI_FUNC_CTL(pipe);
+	uint32_t reg = DDI_FUNC_CTL(transcoder);
 	uint32_t val = I915_READ(reg);
 
-	val &= ~(PIPE_DDI_FUNC_ENABLE | PIPE_DDI_PORT_MASK);
-	val |= PIPE_DDI_PORT_NONE;
+	val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK);
+	val |= TRANS_DDI_PORT_NONE;
 	I915_WRITE(reg, val);
 }
 
@@ -1021,13 +1022,32 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 	if (!(tmp & DDI_BUF_CTL_ENABLE))
 		return false;
 
-	for_each_pipe(i) {
-		tmp = I915_READ(DDI_FUNC_CTL(i));
+	if (port == PORT_A) {
+		tmp = I915_READ(DDI_FUNC_CTL(TRANSCODER_EDP));
 
-		if ((tmp & PIPE_DDI_PORT_MASK)
-		    == PIPE_DDI_SELECT_PORT(port)) {
-			*pipe = i;
-			return true;
+		switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
+		case TRANS_DDI_EDP_INPUT_A_ON:
+		case TRANS_DDI_EDP_INPUT_A_ONOFF:
+			*pipe = PIPE_A;
+			break;
+		case TRANS_DDI_EDP_INPUT_B_ONOFF:
+			*pipe = PIPE_B;
+			break;
+		case TRANS_DDI_EDP_INPUT_C_ONOFF:
+			*pipe = PIPE_C;
+			break;
+		}
+
+		return true;
+	} else {
+		for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) {
+			tmp = I915_READ(DDI_FUNC_CTL(i));
+
+			if ((tmp & TRANS_DDI_PORT_MASK)
+			    == TRANS_DDI_SELECT_PORT(port)) {
+				*pipe = i;
+				return true;
+			}
 		}
 	}
 
@@ -1041,13 +1061,19 @@ static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv,
 {
 	uint32_t temp, ret;
 	enum port port;
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 	int i;
 
-	temp = I915_READ(DDI_FUNC_CTL(pipe));
-	temp &= PIPE_DDI_PORT_MASK;
-	for (i = PORT_A; i <= PORT_E; i++)
-		if (temp == PIPE_DDI_SELECT_PORT(i))
-			port = i;
+	if (transcoder == TRANSCODER_EDP) {
+		port = PORT_A;
+	} else {
+		temp = I915_READ(DDI_FUNC_CTL(transcoder));
+		temp &= TRANS_DDI_PORT_MASK;
+
+		for (i = PORT_B; i <= PORT_E; i++)
+			if (temp == TRANS_DDI_SELECT_PORT(i))
+				port = i;
+	}
 
 	ret = I915_READ(PORT_CLK_SEL(port));
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0fccbe6..1f853f6 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1112,12 +1112,13 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
 	int reg;
 	u32 val;
 	bool cur_state;
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 
 	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);
+		cur_state = !!(val & TRANS_DDI_FUNC_ENABLE);
 	} else {
 		reg = FDI_TX_CTL(pipe);
 		val = I915_READ(reg);
@@ -3259,6 +3260,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	u32 reg, temp;
 
 
@@ -3280,7 +3282,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	intel_disable_pipe(dev_priv, pipe);
 
 	if (IS_HASWELL(dev))
-		intel_ddi_disable_pipe_func(dev_priv, pipe);
+		intel_ddi_disable_transcoder_func(dev_priv, transcoder);
 
 	/* Disable PF */
 	I915_WRITE(PF_CTL(pipe), 0);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ca06ebb..4afbf05 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -595,8 +595,8 @@ 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_enable_pipe_func(struct drm_crtc *crtc);
-extern void intel_ddi_disable_pipe_func(struct drm_i915_private *dev_priv,
-					enum pipe pipe);
+extern void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
+					      enum transcoder transcoder);
 extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
 extern void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
 extern void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
-- 
1.7.10.4

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

* [PATCH 28/47] drm/i915: check TRANSCODER_EDP on intel_modeset_setup_hw_state
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (26 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 27/47] drm/i915: convert DDI_FUNC_CTL " Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 29/47] drm/i915: convert PIPECONF to use transcoder instead of pipe Paulo Zanoni
                   ` (19 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

We need to check if any of the pipes is using TRANSCODER_EDP.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1f853f6..fac9dc7 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8552,6 +8552,31 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
 
+	if (IS_HASWELL(dev)) {
+		tmp = I915_READ(DDI_FUNC_CTL(TRANSCODER_EDP));
+
+		if (tmp & TRANS_DDI_FUNC_ENABLE) {
+			switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
+			case TRANS_DDI_EDP_INPUT_A_ON:
+			case TRANS_DDI_EDP_INPUT_A_ONOFF:
+				pipe = PIPE_A;
+				break;
+			case TRANS_DDI_EDP_INPUT_B_ONOFF:
+				pipe = PIPE_B;
+				break;
+			case TRANS_DDI_EDP_INPUT_C_ONOFF:
+				pipe = PIPE_C;
+				break;
+			}
+
+			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+			crtc->transcoder = TRANSCODER_EDP;
+
+			DRM_DEBUG_KMS("Pipe %c using transcoder EDP\n",
+				      pipe_name(pipe));
+		}
+	}
+
 	for_each_pipe(pipe) {
 		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 
-- 
1.7.10.4

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

* [PATCH 29/47] drm/i915: convert PIPECONF to use transcoder instead of pipe
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (27 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 28/47] drm/i915: check TRANSCODER_EDP on intel_modeset_setup_hw_state Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 30/47] drm/i915: convert PIPE_MSA_MISC to transcoder Paulo Zanoni
                   ` (18 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Because the PIPECONF register is actually part of the CPU transcoder,
not the CPU pipe.

Ideally we would also rename PIPECONF to TRANSCONF to remind people
that they should use the transcoder instead of the pipe, but let's
keep it like this for now since most Gens still name it PIPECONF.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c      |    4 ++-
 drivers/gpu/drm/i915/i915_reg.h      |    2 +-
 drivers/gpu/drm/i915/intel_crt.c     |    6 ++--
 drivers/gpu/drm/i915/intel_display.c |   60 ++++++++++++++++++++--------------
 drivers/gpu/drm/i915/intel_sprite.c  |    3 +-
 drivers/gpu/drm/i915/intel_tv.c      |    4 +--
 6 files changed, 48 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index f7ec794..024b08d 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
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 13d67c1..127e33f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2718,7 +2718,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)
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index c42b980..bc2a91f 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -463,7 +463,9 @@ intel_crt_load_detect(struct intel_crt *crt)
 {
 	struct drm_device *dev = crt->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t pipe = to_intel_crtc(crt->base.base.crtc)->pipe;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crt->base.base.crtc);
+	enum pipe pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	uint32_t save_bclrpat;
 	uint32_t save_vtotal;
 	uint32_t vtotal, vactive;
@@ -485,7 +487,7 @@ intel_crt_load_detect(struct intel_crt *crt)
 	vtotal_reg = VTOTAL(pipe);
 	vblank_reg = VBLANK(pipe);
 	vsync_reg = VSYNC(pipe);
-	pipeconf_reg = PIPECONF(pipe);
+	pipeconf_reg = PIPECONF(transcoder);
 	pipe_dsl_reg = PIPEDSL(pipe);
 
 	save_bclrpat = I915_READ(bclrpat_reg);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fac9dc7..f60ddfb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1008,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,
@@ -1222,12 +1223,13 @@ void assert_pipe(struct drm_i915_private *dev_priv,
 	int reg;
 	u32 val;
 	bool cur_state;
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 
 	/* if we need the pipe A quirk it must be always on */
 	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,
@@ -1661,6 +1663,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);
@@ -1680,7 +1683,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)) {
 		/*
@@ -1745,6 +1748,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;
 
@@ -1764,7 +1768,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;
@@ -1788,6 +1792,7 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 static 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;
 
@@ -1801,7 +1806,7 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
 	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;
@@ -2679,6 +2684,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 */
@@ -2690,7 +2696,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);
@@ -2764,6 +2770,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 */
@@ -2775,7 +2782,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);
@@ -2809,7 +2816,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);
@@ -2971,6 +2978,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);
@@ -3027,7 +3035,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 |
@@ -4383,6 +4391,7 @@ static int i9xx_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 = intel_crtc->transcoder;
 	int refclk, num_connectors = 0;
 	intel_clock_t clock, reduced_clock;
 	u32 dspcntr, pipeconf;
@@ -4463,7 +4472,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 				num_connectors);
 
 	/* setup pipeconf */
-	pipeconf = I915_READ(PIPECONF(pipe));
+	pipeconf = I915_READ(PIPECONF(transcoder));
 
 	/* Set up the display plane register */
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -4535,8 +4544,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 		   (mode->hdisplay - 1));
 	I915_WRITE(DSPPOS(plane), 0);
 
-	I915_WRITE(PIPECONF(pipe), pipeconf);
-	POSTING_READ(PIPECONF(pipe));
+	I915_WRITE(PIPECONF(transcoder), pipeconf);
+	POSTING_READ(PIPECONF(transcoder));
 	intel_enable_pipe(dev_priv, pipe, false);
 
 	intel_wait_for_vblank(dev, pipe);
@@ -4704,10 +4713,10 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	uint32_t val;
 
-	val = I915_READ(PIPECONF(pipe));
+	val = I915_READ(PIPECONF(transcoder));
 
 	val &= ~PIPE_BPC_MASK;
 	switch (intel_crtc->bpp) {
@@ -4738,8 +4747,8 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
 	else
 		val |= PIPECONF_PROGRESSIVE;
 
-	I915_WRITE(PIPECONF(pipe), val);
-	POSTING_READ(PIPECONF(pipe));
+	I915_WRITE(PIPECONF(transcoder), val);
+	POSTING_READ(PIPECONF(transcoder));
 }
 
 static void haswell_set_pipeconf(struct drm_crtc *crtc,
@@ -4748,10 +4757,10 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc,
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	uint32_t val;
 
-	val = I915_READ(PIPECONF(pipe));
+	val = I915_READ(PIPECONF(transcoder));
 
 	val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
 	if (dither)
@@ -4763,8 +4772,8 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc,
 	else
 		val |= PIPECONF_PROGRESSIVE;
 
-	I915_WRITE(PIPECONF(pipe), val);
-	POSTING_READ(PIPECONF(pipe));
+	I915_WRITE(PIPECONF(transcoder), val);
+	POSTING_READ(PIPECONF(transcoder));
 }
 
 static bool ironlake_compute_clocks(struct drm_crtc *crtc,
@@ -5239,7 +5248,7 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
 	     num_connectors, pipe_name(pipe));
 
-	WARN_ON(I915_READ(PIPECONF(pipe)) &
+	WARN_ON(I915_READ(PIPECONF(transcoder)) &
 		(PIPECONF_ENABLE | I965_PIPECONF_ACTIVE));
 
 	WARN_ON(I915_READ(DSPCNTR(plane)) & DISPLAY_PLANE_ENABLE);
@@ -8417,7 +8426,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 	u32 reg, val;
 
 	/* Clear any frame start delays used for debugging left by the BIOS */
-	reg = PIPECONF(crtc->pipe);
+	reg = PIPECONF(crtc->transcoder);
 	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
 
 	/* We need to sanitize the plane -> pipe mapping first because this will
@@ -8580,7 +8589,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 	for_each_pipe(pipe) {
 		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 
-		tmp = I915_READ(PIPECONF(pipe));
+		tmp = I915_READ(PIPECONF(crtc->transcoder));
 		if (tmp & PIPECONF_ENABLE)
 			crtc->active = true;
 		else
@@ -8772,6 +8781,7 @@ intel_display_capture_error_state(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_display_error_state *error;
+	enum transcoder transcoder;
 	int i;
 
 	error = kmalloc(sizeof(*error), GFP_ATOMIC);
@@ -8779,6 +8789,8 @@ intel_display_capture_error_state(struct drm_device *dev)
 		return NULL;
 
 	for_each_pipe(i) {
+		transcoder = pipe_to_transcoder(dev_priv, i);
+
 		error->cursor[i].control = I915_READ(CURCNTR(i));
 		error->cursor[i].position = I915_READ(CURPOS(i));
 		error->cursor[i].base = I915_READ(CURBASE(i));
@@ -8793,7 +8805,7 @@ intel_display_capture_error_state(struct drm_device *dev)
 			error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
 		}
 
-		error->pipe[i].conf = I915_READ(PIPECONF(i));
+		error->pipe[i].conf = I915_READ(PIPECONF(transcoder));
 		error->pipe[i].source = I915_READ(PIPESRC(i));
 		error->pipe[i].htotal = I915_READ(HTOTAL(i));
 		error->pipe[i].hblank = I915_READ(HBLANK(i));
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 7644f31..0a4922d 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -422,6 +422,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	struct intel_framebuffer *intel_fb;
 	struct drm_i915_gem_object *obj, *old_obj;
 	int pipe = intel_plane->pipe;
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 	int ret = 0;
 	int x = src_x >> 16, y = src_y >> 16;
 	int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
@@ -436,7 +437,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	src_h = src_h >> 16;
 
 	/* Pipe must be running... */
-	if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
+	if (!(I915_READ(PIPECONF(transcoder)) & PIPECONF_ENABLE))
 		return -EINVAL;
 
 	if (crtc_x >= primary_w || crtc_y >= primary_h)
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index d2c5c8f..a1dd4f9 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -941,7 +941,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 	const struct video_levels *video_levels;
 	const struct color_conversion *color_conversion;
 	bool burst_ena;
-	int pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 
 	if (!tv_mode)
 		return;	/* can't happen (mode_prepare prevents this) */
@@ -1085,7 +1085,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 			   ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
 			    (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
 	{
-		int pipeconf_reg = PIPECONF(pipe);
+		int pipeconf_reg = PIPECONF(transcoder);
 		int dspcntr_reg = DSPCNTR(intel_crtc->plane);
 		int pipeconf = I915_READ(pipeconf_reg);
 		int dspcntr = I915_READ(dspcntr_reg);
-- 
1.7.10.4

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

* [PATCH 30/47] drm/i915: convert PIPE_MSA_MISC to transcoder
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (28 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 29/47] drm/i915: convert PIPECONF to use transcoder instead of pipe Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 31/47] drm/i915: convert CPU M/N timings " Paulo Zanoni
                   ` (17 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Same as the other registers. This one also appeared on Haswell for the
first time, so that's why we are renaming it.

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

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 127e33f..b21d31c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4544,15 +4544,16 @@
 #define  TRANS_CLK_SEL_DISABLED		(0x0<<29)
 #define  TRANS_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)
+#define _TRANSA_MSA_MISC		0x60410
+#define _TRANSB_MSA_MISC		0x61410
+#define TRANS_MSA_MISC(tran) _TRANSCODER(tran, _TRANSA_MSA_MISC, \
+					       _TRANSB_MSA_MISC)
+#define  TRANS_MSA_SYNC_CLK		(1<<0)
+#define  TRANS_MSA_6_BPC		(0<<5)
+#define  TRANS_MSA_8_BPC		(1<<5)
+#define  TRANS_MSA_10_BPC		(2<<5)
+#define  TRANS_MSA_12_BPC		(3<<5)
+#define  TRANS_MSA_16_BPC		(3<<5)
 
 /* LCPLL Control */
 #define LCPLL_CTL			0x130040
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 26aae8f..980a591 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -888,31 +888,31 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
-	enum pipe pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	int type = intel_encoder->type;
 	uint32_t temp;
 
 	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
 
-		temp = PIPE_MSA_SYNC_CLK;
+		temp = TRANS_MSA_SYNC_CLK;
 		switch (intel_crtc->bpp) {
 		case 18:
-			temp |= PIPE_MSA_6_BPC;
+			temp |= TRANS_MSA_6_BPC;
 			break;
 		case 24:
-			temp |= PIPE_MSA_8_BPC;
+			temp |= TRANS_MSA_8_BPC;
 			break;
 		case 30:
-			temp |= PIPE_MSA_10_BPC;
+			temp |= TRANS_MSA_10_BPC;
 			break;
 		case 36:
-			temp |= PIPE_MSA_12_BPC;
+			temp |= TRANS_MSA_12_BPC;
 			break;
 		default:
-			WARN(1, "%d bpp unsupported by pipe DDI function\n",
+			WARN(1, "%d bpp unsupported by DDI function\n",
 			     intel_crtc->bpp);
 		}
-		I915_WRITE(PIPE_MSA_MISC(pipe), temp);
+		I915_WRITE(TRANS_MSA_MISC(transcoder), temp);
 	}
 }
 
-- 
1.7.10.4

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

* [PATCH 31/47] drm/i915: convert CPU M/N timings to transcoder
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (29 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 30/47] drm/i915: convert PIPE_MSA_MISC to transcoder Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 32/47] drm/i915: convert pipe timing definitions " Paulo Zanoni
                   ` (16 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Same thing as the previous commits. Not renaming this one since it
exists since way before Haswell.

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

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b21d31c..4715754 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3308,14 +3308,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 */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f60ddfb..aa5cc84 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2689,7 +2689,7 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
 
 	/* Write the TU size bits so error detection works */
 	I915_WRITE(FDI_RX_TUSIZE1(pipe),
-		   I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
+		   I915_READ(PIPE_DATA_M1(transcoder)) & TU_SIZE_MASK);
 
 	/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
 	reg = FDI_RX_CTL(pipe);
@@ -4846,7 +4846,7 @@ static void ironlake_set_m_n(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	enum pipe pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	struct intel_encoder *intel_encoder, *edp_encoder = NULL;
 	struct fdi_m_n m_n = {0};
 	int target_clock, pixel_multiplier, lane, link_bw;
@@ -4909,10 +4909,10 @@ static void ironlake_set_m_n(struct drm_crtc *crtc,
 	ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
 			     &m_n);
 
-	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);
+	I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n.tu) | m_n.gmch_m);
+	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);
 }
 
 static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a260531..2e4e588 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -792,6 +792,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
@@ -816,10 +817,11 @@ 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), 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);
+		I915_WRITE(PIPE_DATA_M1(transcoder),
+			   TU_SIZE(m_n.tu) | m_n.gmch_m);
+		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), TU_SIZE(m_n.tu) | m_n.gmch_m);
 		I915_WRITE(TRANSDATA_N1(pipe), m_n.gmch_n);
-- 
1.7.10.4

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

* [PATCH 32/47] drm/i915: convert pipe timing definitions to transcoder
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (30 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 31/47] drm/i915: convert CPU M/N timings " Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 33/47] drm/i915: implement workaround for VTOTAL when using TRANSCODER_EDP Paulo Zanoni
                   ` (15 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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_irq.c      |    7 +++--
 drivers/gpu/drm/i915/i915_reg.h      |   14 +++++-----
 drivers/gpu/drm/i915/intel_crt.c     |    6 ++--
 drivers/gpu/drm/i915/intel_display.c |   51 +++++++++++++++++-----------------
 4 files changed, 40 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 024b08d..09b3551 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -185,6 +185,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
 	int vbl_start, vbl_end, htotal, vtotal;
 	bool in_vbl = true;
 	int ret = 0;
+	enum transcoder transcoder = pipe_to_transcoder(dev_priv, pipe);
 
 	if (!i915_pipe_enabled(dev, pipe)) {
 		DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
@@ -193,7 +194,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
 	}
 
 	/* Get vtotal. */
-	vtotal = 1 + ((I915_READ(VTOTAL(pipe)) >> 16) & 0x1fff);
+	vtotal = 1 + ((I915_READ(VTOTAL(transcoder)) >> 16) & 0x1fff);
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		/* No obvious pixelcount register. Only query vertical
@@ -213,13 +214,13 @@ 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);
 	}
 
 	/* Query vblank area. */
-	vbl = I915_READ(VBLANK(pipe));
+	vbl = I915_READ(VBLANK(transcoder));
 
 	/* Test position against vblank region. */
 	vbl_start = vbl & 0x1fff;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 4715754..3b91031 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1561,14 +1561,14 @@
 #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 HTOTAL(trans) _TRANSCODER(trans, _HTOTAL_A, _HTOTAL_B)
+#define HBLANK(trans) _TRANSCODER(trans, _HBLANK_A, _HBLANK_B)
+#define HSYNC(trans) _TRANSCODER(trans, _HSYNC_A, _HSYNC_B)
+#define VTOTAL(trans) _TRANSCODER(trans, _VTOTAL_A, _VTOTAL_B)
+#define VBLANK(trans) _TRANSCODER(trans, _VBLANK_A, _VBLANK_B)
+#define VSYNC(trans) _TRANSCODER(trans, _VSYNC_A, _VSYNC_B)
 #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
-#define VSYNCSHIFT(pipe) _PIPE(pipe, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
+#define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
 
 /* VGA port control */
 #define ADPA			0x61100
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index bc2a91f..4f32ea9 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -484,9 +484,9 @@ intel_crt_load_detect(struct intel_crt *crt)
 	DRM_DEBUG_KMS("starting load-detect on CRT\n");
 
 	bclrpat_reg = BCLRPAT(pipe);
-	vtotal_reg = VTOTAL(pipe);
-	vblank_reg = VBLANK(pipe);
-	vsync_reg = VSYNC(pipe);
+	vtotal_reg = VTOTAL(transcoder);
+	vblank_reg = VBLANK(transcoder);
+	vsync_reg = VSYNC(transcoder);
 	pipeconf_reg = PIPECONF(transcoder);
 	pipe_dsl_reg = PIPEDSL(pipe);
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index aa5cc84..15b2a4f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3019,14 +3019,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);
@@ -4338,6 +4338,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
 	struct drm_device *dev = intel_crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum pipe pipe = intel_crtc->pipe;
+	enum transcoder transcoder = intel_crtc->transcoder;
 	uint32_t vsyncshift;
 
 	if (!IS_GEN2(dev) && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
@@ -4351,25 +4352,25 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
 	}
 
 	if (INTEL_INFO(dev)->gen > 3)
-		I915_WRITE(VSYNCSHIFT(pipe), vsyncshift);
+		I915_WRITE(VSYNCSHIFT(transcoder), vsyncshift);
 
-	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));
 
@@ -6333,12 +6334,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)
@@ -8807,12 +8808,12 @@ intel_display_capture_error_state(struct drm_device *dev)
 
 		error->pipe[i].conf = I915_READ(PIPECONF(transcoder));
 		error->pipe[i].source = I915_READ(PIPESRC(i));
-		error->pipe[i].htotal = I915_READ(HTOTAL(i));
-		error->pipe[i].hblank = I915_READ(HBLANK(i));
-		error->pipe[i].hsync = I915_READ(HSYNC(i));
-		error->pipe[i].vtotal = I915_READ(VTOTAL(i));
-		error->pipe[i].vblank = I915_READ(VBLANK(i));
-		error->pipe[i].vsync = I915_READ(VSYNC(i));
+		error->pipe[i].htotal = I915_READ(HTOTAL(transcoder));
+		error->pipe[i].hblank = I915_READ(HBLANK(transcoder));
+		error->pipe[i].hsync = I915_READ(HSYNC(transcoder));
+		error->pipe[i].vtotal = I915_READ(VTOTAL(transcoder));
+		error->pipe[i].vblank = I915_READ(VBLANK(transcoder));
+		error->pipe[i].vsync = I915_READ(VSYNC(transcoder));
 	}
 
 	return error;
-- 
1.7.10.4

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

* [PATCH 33/47] drm/i915: implement workaround for VTOTAL when using TRANSCODER_EDP
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (31 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 32/47] drm/i915: convert pipe timing definitions " Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 34/47] drm/i915: select the correct pipe " Paulo Zanoni
                   ` (14 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

See the documentation for the DDI_FUNC_CTL register, EDP Input Select
bits: when the EDP input selection is B, the VTOTAL_B must be
programmed with the VTOTAL_EDP value, same thing for selection C.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 15b2a4f..6878474 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4374,6 +4374,17 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
 		   (adjusted_mode->crtc_vsync_start - 1) |
 		   ((adjusted_mode->crtc_vsync_end - 1) << 16));
 
+	/* Workaround: when the EDP input selection is B, the VTOTAL_B must be
+	 * programmed with the VTOTAL_EDP value. Same for VTOTAL_C. This is
+	 * documented on the DDI_FUNC_CTL register description, EDP Input Select
+	 * bits. */
+	if (IS_HASWELL(dev) && transcoder == TRANSCODER_EDP &&
+	    (pipe == PIPE_B || pipe == PIPE_C)) {
+		I915_WRITE(VTOTAL(pipe),
+			   (adjusted_mode->crtc_vdisplay - 1) |
+			   ((adjusted_mode->crtc_vtotal - 1) << 16));
+	}
+
 	/* pipesrc controls the size that is scaled from, which should
 	 * always be the user's requested size.
 	 */
-- 
1.7.10.4

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

* [PATCH 34/47] drm/i915: select the correct pipe when using TRANSCODER_EDP
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (32 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 33/47] drm/i915: implement workaround for VTOTAL when using TRANSCODER_EDP Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 35/47] drm/i915: set the correct eDP aux channel clock divider on DDI Paulo Zanoni
                   ` (13 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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 |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 980a591..7bcc85d 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -953,6 +953,23 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 	if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
 		temp |= TRANS_DDI_PHSYNC;
 
+	if (transcoder == TRANSCODER_EDP) {
+		switch (pipe) {
+		case PIPE_A:
+			temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
+			break;
+		case PIPE_B:
+			temp |= TRANS_DDI_EDP_INPUT_B_ONOFF;
+			break;
+		case PIPE_C:
+			temp |= TRANS_DDI_EDP_INPUT_C_ONOFF;
+			break;
+		default:
+			BUG();
+			break;
+		}
+	}
+
 	if (type == INTEL_OUTPUT_HDMI) {
 		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 
-- 
1.7.10.4

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

* [PATCH 35/47] drm/i915: set the correct eDP aux channel clock divider on DDI
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (33 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 34/47] drm/i915: select the correct pipe " Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 36/47] drm/i915: set/unset the DDI eDP backlight Paulo Zanoni
                   ` (12 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

The cdclk frequency is not always the same, so the value here should
be adjusted to match it.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 2e4e588..cc9e5ab 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -351,7 +351,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	int i;
 	int recv_bytes;
 	uint32_t status;
-	uint32_t aux_clock_divider;
+	uint32_t aux_clock_divider, cdclk_freq;
 	int try, precharge;
 
 	if (IS_HASWELL(dev)) {
@@ -387,7 +387,10 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	 * clock divider.
 	 */
 	if (is_cpu_edp(intel_dp)) {
-		if (IS_VALLEYVIEW(dev))
+		if (IS_HASWELL(dev)) {
+			cdclk_freq = I915_READ(CDCLK_FREQ) & CDCLK_FREQ_MASK;
+			aux_clock_divider = (cdclk_freq + 1) >> 1;
+		} else if (IS_VALLEYVIEW(dev))
 			aux_clock_divider = 100;
 		else if (IS_GEN6(dev) || IS_GEN7(dev))
 			aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
-- 
1.7.10.4

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

* [PATCH 36/47] drm/i915: set/unset the DDI eDP backlight
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (34 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 35/47] drm/i915: set the correct eDP aux channel clock divider on DDI Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 37/47] drm/i915: turn the eDP DDI panel on/off Paulo Zanoni
                   ` (11 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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 |   15 +++++++++++++--
 drivers/gpu/drm/i915/intel_dp.c  |    4 ++--
 drivers/gpu/drm/i915/intel_drv.h |    6 ++++--
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 7bcc85d..24c7ced 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1226,12 +1226,23 @@ void intel_enable_ddi(struct intel_encoder *intel_encoder)
 		 * enabling the port.
 		 */
 		I915_WRITE(DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE);
+	} else if (type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		ironlake_edp_backlight_on(intel_dp);
 	}
 }
 
-void intel_disable_ddi(struct intel_encoder *encoder)
+void intel_disable_ddi(struct intel_encoder *intel_encoder)
 {
-	/* This will be needed in the future, so leave it here for now */
+	struct drm_encoder *encoder = &intel_encoder->base;
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		ironlake_edp_backlight_off(intel_dp);
+	}
 }
 
 void intel_ddi_pll_init(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index cc9e5ab..ca87034 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1180,7 +1180,7 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 	ironlake_wait_panel_off(intel_dp);
 }
 
-static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
+void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1203,7 +1203,7 @@ static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 	POSTING_READ(PCH_PP_CONTROL);
 }
 
-static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
+void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp->base.base.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 4afbf05..e672992 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -428,6 +428,8 @@ extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
 extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
 extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
+extern void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
+extern void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
 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);
@@ -586,8 +588,8 @@ 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_enable_ddi(struct intel_encoder *encoder);
-extern void intel_disable_ddi(struct intel_encoder *encoder);
+extern void intel_enable_ddi(struct intel_encoder *intel_encoder);
+extern void intel_disable_ddi(struct intel_encoder *intel_encoder);
 extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 				   enum pipe *pipe);
 extern void intel_ddi_mode_set(struct drm_encoder *encoder,
-- 
1.7.10.4

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

* [PATCH 37/47] drm/i915: turn the eDP DDI panel on/off
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (35 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 36/47] drm/i915: set/unset the DDI eDP backlight Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 38/47] drm/i915: enable DDI eDP Paulo Zanoni
                   ` (10 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

It's an important step :)

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 24c7ced..9bb8bba 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1158,12 +1158,19 @@ void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	int type = intel_encoder->type;
 
-	WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
+	if (type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+		ironlake_edp_panel_vdd_on(intel_dp);
+		ironlake_edp_panel_on(intel_dp);
+		ironlake_edp_panel_vdd_off(intel_dp, true);
+	}
 
+	WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
 	I915_WRITE(PORT_CLK_SEL(port), intel_crtc->ddi_pll_sel);
 
-	if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
 		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
@@ -1191,6 +1198,7 @@ void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
 	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	int type = intel_encoder->type;
 	uint32_t val;
 	bool wait = false;
 
@@ -1209,6 +1217,12 @@ void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
 	if (wait)
 		intel_wait_ddi_buf_idle(dev_priv, port);
 
+	if (type == INTEL_OUTPUT_EDP) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+		ironlake_edp_panel_vdd_on(intel_dp);
+		ironlake_edp_panel_off(intel_dp);
+	}
+
 	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index ca87034..a1ddd87 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -669,9 +669,6 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 	return -EREMOTEIO;
 }
 
-static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
-static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
-
 static int
 intel_dp_i2c_init(struct intel_dp *intel_dp,
 		  struct intel_connector *intel_connector, const char *name)
@@ -1020,7 +1017,7 @@ static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv)
 	return control;
 }
 
-static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
+void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1090,7 +1087,7 @@ static void ironlake_panel_vdd_work(struct work_struct *__work)
 	mutex_unlock(&dev->mode_config.mutex);
 }
 
-static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
 	if (!is_edp(intel_dp))
 		return;
@@ -1113,7 +1110,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)
+void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1155,7 +1152,7 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 	}
 }
 
-static void ironlake_edp_panel_off(struct intel_dp *intel_dp)
+void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp->base.base.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 e672992..73b4659 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -430,6 +430,10 @@ extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
 extern void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
 extern void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
+extern void ironlake_edp_panel_on(struct intel_dp *intel_dp);
+extern void ironlake_edp_panel_off(struct intel_dp *intel_dp);
+extern void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
+extern void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
 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);
-- 
1.7.10.4

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

* [PATCH 38/47] drm/i915: enable DDI eDP
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (36 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 37/47] drm/i915: turn the eDP DDI panel on/off Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 39/47] drm/i915: simplify assignments inside intel_dp.c Paulo Zanoni
                   ` (9 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Now that all the eDP enablement bits are there, we can actually try to
use the eDP.

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 9bb8bba..74e7615 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -242,8 +242,8 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 
 	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:
-- 
1.7.10.4

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

* [PATCH 39/47] drm/i915: simplify assignments inside intel_dp.c
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (37 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 38/47] drm/i915: enable DDI eDP Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 40/47] drm/i915: add intel_dp_to_dev and intel_hdmi_to_dev Paulo Zanoni
                   ` (8 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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 |   41 ++++++++++++++++++++-------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a1ddd87..51a3d97 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -79,8 +79,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);
 }
 
 /**
@@ -108,7 +107,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)
@@ -121,7 +120,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;
@@ -786,7 +785,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;
@@ -797,11 +797,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;
@@ -863,7 +863,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);
 
 	/*
@@ -2372,7 +2372,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;
 
@@ -2409,7 +2409,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;
 
@@ -2583,7 +2583,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);
 }
@@ -2593,13 +2593,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;
 	}
 
@@ -2756,7 +2757,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;
 		}
@@ -2819,7 +2820,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.10.4

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

* [PATCH 40/47] drm/i915: add intel_dp_to_dev and intel_hdmi_to_dev
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (38 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 39/47] drm/i915: simplify assignments inside intel_dp.c Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 41/47] drm/i915: create intel_digital_port and use it Paulo Zanoni
                   ` (7 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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 we just
added here.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 51a3d97..749ef1c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -77,6 +77,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);
@@ -307,7 +312,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;
@@ -315,7 +320,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;
@@ -324,7 +329,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))
@@ -343,7 +348,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;
@@ -970,7 +975,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",
@@ -1019,7 +1024,7 @@ static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv)
 
 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;
 
@@ -1058,7 +1063,7 @@ 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;
 
@@ -1080,7 +1085,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);
@@ -1112,7 +1117,7 @@ void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 
 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;
 
@@ -1154,7 +1159,7 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 
 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;
 
@@ -1179,7 +1184,7 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 
 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;
 
@@ -1202,7 +1207,7 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
 
 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;
 
@@ -1219,7 +1224,7 @@ void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 
 static void ironlake_edp_pll_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_crtc *crtc = intel_dp->base.base.crtc;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpa_ctl;
@@ -1244,7 +1249,7 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
 
 static void ironlake_edp_pll_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_crtc *crtc = intel_dp->base.base.crtc;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpa_ctl;
@@ -1487,7 +1492,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;
@@ -1500,7 +1505,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) {
@@ -1755,7 +1760,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;
@@ -1957,7 +1962,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 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;
@@ -2036,7 +2041,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;
 
@@ -2278,11 +2283,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;
@@ -2294,7 +2300,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 a6dd00d9..6c82bf7 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;
 
@@ -749,7 +754,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.10.4

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

* [PATCH 41/47] drm/i915: create intel_digital_port and use it
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (39 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 40/47] drm/i915: add intel_dp_to_dev and intel_hdmi_to_dev Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 42/47] drm/i915: remove encoder args from intel_{dp, hdmi}_add_properties Paulo Zanoni
                   ` (6 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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. In other words: 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  |   23 +++++------
 drivers/gpu/drm/i915/intel_dp.c   |   77 ++++++++++++++++++++++---------------
 drivers/gpu/drm/i915/intel_drv.h  |   33 +++++++++++++---
 drivers/gpu/drm/i915/intel_hdmi.c |   27 +++++++------
 4 files changed, 101 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 74e7615..beea8a6 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -63,13 +63,11 @@ static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
 	struct drm_encoder *encoder = &intel_encoder->base;
 	int type = intel_encoder->type;
 
-	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-		return intel_dp->port;
-
-	} else if (type == INTEL_OUTPUT_HDMI) {
-		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
-		return intel_hdmi->ddi_port;
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||
+	    type == INTEL_OUTPUT_HDMI) {
+		struct intel_digital_port *intel_dig_port =
+			enc_to_dig_port(encoder);
+		return intel_dig_port->port;
 
 	} else if (type == INTEL_OUTPUT_ANALOG) {
 		return PORT_E;
@@ -924,11 +922,13 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 	enum pipe pipe = intel_crtc->pipe;
 	enum transcoder transcoder = intel_crtc->transcoder;
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
 	int type = intel_encoder->type;
 	uint32_t temp;
 
 	/* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */
 	temp = TRANS_DDI_FUNC_ENABLE;
+	temp |= TRANS_DDI_SELECT_PORT(port);
 
 	switch (intel_crtc->bpp) {
 	case 18:
@@ -978,18 +978,14 @@ void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 		else
 			temp |= TRANS_DDI_MODE_SELECT_DVI;
 
-		temp |= TRANS_DDI_SELECT_PORT(intel_hdmi->ddi_port);
-
 	} else if (type == INTEL_OUTPUT_ANALOG) {
 		temp |= TRANS_DDI_MODE_SELECT_FDI;
-		temp |= TRANS_DDI_SELECT_PORT(PORT_E);
 
 	} else if (type == INTEL_OUTPUT_DISPLAYPORT ||
 		   type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
 		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
-		temp |= TRANS_DDI_SELECT_PORT(intel_dp->port);
 
 		switch (intel_dp->lane_count) {
 		case 1:
@@ -1301,9 +1297,10 @@ void intel_ddi_pll_init(struct drm_device *dev)
 
 void intel_ddi_prepare_link_retrain(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;
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
-	enum port port = intel_dp->port;
+	enum port port = intel_dig_port->port;
 	bool wait;
 	uint32_t val;
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 749ef1c..771a5a6 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -50,7 +50,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;
 }
 
 /**
@@ -79,7 +81,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)
@@ -348,7 +352,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;
@@ -359,7 +364,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;
@@ -377,7 +382,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;
 		}
 	}
@@ -1224,8 +1230,9 @@ void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 
 static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct drm_crtc *crtc = intel_dp->base.base.crtc;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpa_ctl;
 
@@ -1249,8 +1256,9 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
 
 static void ironlake_edp_pll_off(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct drm_crtc *crtc = intel_dp->base.base.crtc;
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpa_ctl;
 
@@ -1760,13 +1768,15 @@ 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_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;
+	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;
@@ -1777,9 +1787,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");
 
@@ -1797,7 +1807,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))) {
@@ -1863,7 +1873,7 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 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;
 	int i;
 	uint8_t voltage;
@@ -2041,7 +2051,8 @@ 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_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 DP = intel_dp->DP;
 
@@ -2081,7 +2092,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_dig_port->base.base.crtc;
 
 		/* Hardware workaround: leaving our transcoder select
 		 * set to transcoder B while it's off will prevent the
@@ -2197,13 +2208,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->base.connectors_active)
+	if (!intel_encoder->connectors_active)
 		return;
 
-	if (WARN_ON(!intel_dp->base.base.crtc))
+	if (WARN_ON(!intel_encoder->base.crtc))
 		return;
 
 	/* Try to read receiver status if the link appears to be up */
@@ -2234,7 +2246,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);
 	}
@@ -2481,7 +2493,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);
@@ -2520,8 +2533,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;
 		intel_set_mode(crtc, &crtc->mode,
 			       crtc->x, crtc->y, crtc->fb);
 	}
@@ -2544,7 +2557,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);
@@ -2553,7 +2567,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 = {
@@ -2648,24 +2662,27 @@ 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;
 	/* Preserve the current hw state. */
 	intel_dp->DP = I915_READ(intel_dp->output_reg);
 
 	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 73b4659..6803b99 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -319,10 +319,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;
@@ -338,13 +336,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;
 	uint8_t link_bw;
 	uint8_t lane_count;
@@ -366,6 +362,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)
 {
@@ -487,7 +490,27 @@ 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 6c82bf7..6045503 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,14 @@ 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)
@@ -850,6 +851,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
 			uint64_t val)
 {
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+	struct intel_digital_port *intel_dig_port =
+		hdmi_to_dig_port(intel_hdmi);
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	int ret;
 
@@ -889,8 +892,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_dig_port->base.base.crtc) {
+		struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
 		intel_set_mode(crtc, &crtc->mode,
 			       crtc->x, crtc->y, crtc->fb);
 	}
@@ -948,19 +951,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);
 
@@ -978,7 +983,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.10.4

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

* [PATCH 42/47] drm/i915: remove encoder args from intel_{dp, hdmi}_add_properties
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (40 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 41/47] drm/i915: create intel_digital_port and use it Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 43/47] drm/i915: split intel_hdmi_init into encoder and connector pieces Paulo Zanoni
                   ` (5 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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 771a5a6..d9655e5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2648,7 +2648,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);
@@ -2868,7 +2868,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 6045503..31ddb81 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -939,7 +939,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);
@@ -1040,7 +1040,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 
-	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.10.4

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

* [PATCH 43/47] drm/i915: split intel_hdmi_init into encoder and connector pieces
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (41 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 42/47] drm/i915: remove encoder args from intel_{dp, hdmi}_add_properties Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 44/47] drm/i915: split intel_dp_init " Paulo Zanoni
                   ` (4 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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 |   97 +++++++++++++++++++++----------------
 1 file changed, 54 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 31ddb81..b8882e6 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -945,45 +945,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;
-	}
-
-	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);
+	enum port port = intel_dig_port->port;
 
-	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;
@@ -1003,8 +982,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;
@@ -1022,6 +999,46 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 		intel_hdmi->set_infoframes = cpt_set_infoframes;
 	}
 
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
+
+	intel_hdmi_add_properties(connector);
+
+	intel_connector_attach_encoder(intel_connector, intel_encoder);
+	drm_sysfs_connector_add(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
+	 * generated on the port when a cable is not attached.
+	 */
+	if (IS_G4X(dev) && !IS_GM45(dev)) {
+		u32 temp = I915_READ(PEG_BAND_GAP_DATA);
+		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, &intel_encoder->base, &intel_hdmi_enc_funcs,
+			 DRM_MODE_ENCODER_TMDS);
+
 	if (IS_HASWELL(dev)) {
 		intel_encoder->pre_enable = intel_ddi_pre_enable;
 		intel_encoder->enable = intel_enable_ddi;
@@ -1037,20 +1054,14 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 		drm_encoder_helper_add(&intel_encoder->base,
 				       &intel_hdmi_helper_funcs);
 	}
-	intel_connector->get_hw_state = intel_connector_get_hw_state;
-
 
-	intel_hdmi_add_properties(connector);
+	intel_dig_port->port = port;
+	intel_dig_port->hdmi.sdvox_reg = sdvox_reg;
+	intel_dig_port->dp.output_reg = 0;
 
-	intel_connector_attach_encoder(intel_connector, intel_encoder);
-	drm_sysfs_connector_add(connector);
+	intel_encoder->type = INTEL_OUTPUT_HDMI;
+	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
+	intel_encoder->cloneable = false;
 
-	/* 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
-	 * generated on the port when a cable is not attached.
-	 */
-	if (IS_G4X(dev) && !IS_GM45(dev)) {
-		u32 temp = I915_READ(PEG_BAND_GAP_DATA);
-		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
-	}
+	intel_hdmi_init_connector(intel_dig_port, intel_connector);
 }
-- 
1.7.10.4

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

* [PATCH 44/47] drm/i915: split intel_dp_init into encoder and connector pieces
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (42 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 43/47] drm/i915: split intel_hdmi_init into encoder and connector pieces Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 45/47] drm/i915: reset intel_encoder->type when DP or HDMI is detected Paulo Zanoni
                   ` (3 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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 |  127 +++++++++++++++++++++------------------
 1 file changed, 69 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d9655e5..0a4ac6f 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2654,37 +2654,23 @@ 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;
 	/* Preserve the current hw state. */
 	intel_dp->DP = I915_READ(intel_dp->output_reg);
 
-	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;
 
@@ -2692,10 +2678,10 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 	 * FIXME : We need to initialize built-in panels before external panels.
 	 * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup
 	 */
-	if (IS_VALLEYVIEW(dev) && output_reg == DP_C) {
+	if (IS_VALLEYVIEW(dev) && port == PORT_C) {
 		type = DRM_MODE_CONNECTOR_eDP;
 		intel_encoder->type = INTEL_OUTPUT_EDP;
-	} else if (output_reg == DP_A || is_pch_edp(intel_dp)) {
+	} else if (port == PORT_A || is_pch_edp(intel_dp)) {
 		type = DRM_MODE_CONNECTOR_eDP;
 		intel_encoder->type = INTEL_OUTPUT_EDP;
 	} else {
@@ -2703,48 +2689,19 @@ 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);
+	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
+			  ironlake_panel_vdd_work);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	drm_sysfs_connector_add(connector);
 
-	if (IS_HASWELL(dev)) {
-		intel_encoder->enable = intel_enable_ddi;
-		intel_encoder->pre_enable = intel_ddi_pre_enable;
-		intel_encoder->disable = intel_disable_ddi;
-		intel_encoder->post_disable = intel_ddi_post_disable;
-		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
-	} else {
-		intel_encoder->enable = intel_enable_dp;
-		intel_encoder->pre_enable = intel_pre_enable_dp;
-		intel_encoder->disable = intel_disable_dp;
-		intel_encoder->post_disable = intel_post_disable_dp;
-		intel_encoder->get_hw_state = intel_dp_get_hw_state;
-	}
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	/* Set up the DDC bus. */
@@ -2861,8 +2818,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);
@@ -2879,3 +2834,59 @@ 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, &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);
+
+	if (IS_HASWELL(dev)) {
+		intel_encoder->enable = intel_enable_ddi;
+		intel_encoder->pre_enable = intel_ddi_pre_enable;
+		intel_encoder->disable = intel_disable_ddi;
+		intel_encoder->post_disable = intel_ddi_post_disable;
+		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
+	} else {
+		intel_encoder->enable = intel_enable_dp;
+		intel_encoder->pre_enable = intel_pre_enable_dp;
+		intel_encoder->disable = intel_disable_dp;
+		intel_encoder->post_disable = intel_post_disable_dp;
+		intel_encoder->get_hw_state = intel_dp_get_hw_state;
+	}
+
+	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.10.4

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

* [PATCH 45/47] drm/i915: reset intel_encoder->type when DP or HDMI is detected
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (43 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 44/47] drm/i915: split intel_dp_init " Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 46/47] drm/i915: add intel_ddi_connector_get_hw_state Paulo Zanoni
                   ` (2 subsequent siblings)
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

When intel_hdmi_detect detects a monitor, set intel_encoder->type with
INTEL_OUTPUT_HDMI. Same for DP.

This should not break the current code because these variables never
change. This will be used after we create the DDI encoder because it
will have both DP and HDMI connectors.

We won't support eDP+HDMI on the same port, so if an encoder is eDP we
should expect it to always remain eDP and never change.

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, 8 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0a4ac6f..eaed4ee 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2390,6 +2390,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;
@@ -2421,6 +2423,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;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index b8882e6..fe8b576 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -778,6 +778,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;
@@ -806,6 +809,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;
-- 
1.7.10.4

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

* [PATCH 46/47] drm/i915: add intel_ddi_connector_get_hw_state
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (44 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 45/47] drm/i915: reset intel_encoder->type when DP or HDMI is detected Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-02 20:52 ` [PATCH 47/47] drm/i915: create the DDI encoder Paulo Zanoni
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

We need this since now on DDI we will have 2 connectors on each
encoder.

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index beea8a6..81e9f06 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1021,6 +1021,46 @@ void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
 	I915_WRITE(reg, val);
 }
 
+bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
+{
+	struct drm_device *dev = intel_connector->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *intel_encoder = intel_connector->encoder;
+	int type = intel_connector->base.connector_type;
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	enum pipe pipe = 0;
+	enum transcoder transcoder;
+	uint32_t tmp;
+
+	if (!intel_encoder->get_hw_state(intel_encoder, &pipe))
+		return false;
+
+	if (port == PORT_A)
+		transcoder = TRANSCODER_EDP;
+	else
+		transcoder = pipe;
+
+	tmp = I915_READ(DDI_FUNC_CTL(transcoder));
+
+	switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
+	case TRANS_DDI_MODE_SELECT_HDMI:
+	case TRANS_DDI_MODE_SELECT_DVI:
+		return (type == DRM_MODE_CONNECTOR_HDMIA);
+
+	case TRANS_DDI_MODE_SELECT_DP_SST:
+		if (type == DRM_MODE_CONNECTOR_eDP)
+			return true;
+	case TRANS_DDI_MODE_SELECT_DP_MST:
+		return (type == DRM_MODE_CONNECTOR_DisplayPort);
+
+	case TRANS_DDI_MODE_SELECT_FDI:
+		return (type == DRM_MODE_CONNECTOR_VGA);
+
+	default:
+		return false;
+	}
+}
+
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 			    enum pipe *pipe)
 {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index eaed4ee..fba96c6 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2706,7 +2706,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	drm_sysfs_connector_add(connector);
 
-	intel_connector->get_hw_state = intel_connector_get_hw_state;
+	if (IS_HASWELL(dev))
+		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
+	else
+		intel_connector->get_hw_state = intel_connector_get_hw_state;
+
 
 	/* Set up the DDC bus. */
 	switch (port) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 6803b99..402fe70 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -635,5 +635,6 @@ extern void intel_ddi_post_disable(struct intel_encoder *intel_encoder);
 extern void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
 extern void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
 extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
+bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index fe8b576..ae5ee37 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1003,7 +1003,10 @@ static void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 		intel_hdmi->set_infoframes = cpt_set_infoframes;
 	}
 
-	intel_connector->get_hw_state = intel_connector_get_hw_state;
+	if (IS_HASWELL(dev))
+		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
+	else
+		intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	intel_hdmi_add_properties(connector);
 
-- 
1.7.10.4

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

* [PATCH 47/47] drm/i915: create the DDI encoder
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (45 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 46/47] drm/i915: add intel_ddi_connector_get_hw_state Paulo Zanoni
@ 2012-10-02 20:52 ` Paulo Zanoni
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
  47 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-02 20:52 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.

After this change, intel_hdmi_init and intel_dp_init are only called
by Ivy Bridge and earlier, while hardware containing DDI outputs
should call intel_ddi_init.

Added/removed quite a few "static" keywords due to the fact that some
function pointers were moved from intel_dp.c and intel_hdmi.c to
intel_ddi.c.

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  |  149 +++++++++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_dp.c   |   44 ++++-------
 drivers/gpu/drm/i915/intel_drv.h  |   22 +++---
 drivers/gpu/drm/i915/intel_hdmi.c |   35 +++------
 4 files changed, 145 insertions(+), 105 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 81e9f06..6aca985 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -64,7 +64,7 @@ static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
 	int type = intel_encoder->type;
 
 	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP ||
-	    type == INTEL_OUTPUT_HDMI) {
+	    type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_UNKNOWN) {
 		struct intel_digital_port *intel_dig_port =
 			enc_to_dig_port(encoder);
 		return intel_dig_port->port;
@@ -227,35 +227,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:
-		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:
-	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;
@@ -642,9 +613,9 @@ static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
 	{298000,	2,	21,	19},
 };
 
-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);
@@ -1061,8 +1032,8 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
 	}
 }
 
-bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
-			    enum pipe *pipe)
+static bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
+				   enum pipe *pipe)
 {
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1187,7 +1158,7 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
 		I915_WRITE(TRANS_CLK_SEL(transcoder), TRANS_CLK_SEL_DISABLED);
 }
 
-void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
+static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_crtc *crtc = encoder->crtc;
@@ -1229,7 +1200,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_post_disable(struct intel_encoder *intel_encoder)
+static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
@@ -1262,7 +1233,7 @@ void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
 	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
 }
 
-void intel_enable_ddi(struct intel_encoder *intel_encoder)
+static void intel_enable_ddi(struct intel_encoder *intel_encoder)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_device *dev = encoder->dev;
@@ -1283,7 +1254,7 @@ void intel_enable_ddi(struct intel_encoder *intel_encoder)
 	}
 }
 
-void intel_disable_ddi(struct intel_encoder *intel_encoder)
+static void intel_disable_ddi(struct intel_encoder *intel_encoder)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
 	int type = intel_encoder->type;
@@ -1375,3 +1346,103 @@ void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
 
 	udelay(600);
 }
+
+static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP)
+		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);
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_UNKNOWN)
+		WARN(1, "mode_fixup() on unknown output!\n");
+
+	if (type == INTEL_OUTPUT_HDMI)
+		return intel_hdmi_mode_fixup(encoder, mode, adjusted_mode);
+	else
+		return intel_dp_mode_fixup(encoder, mode, adjusted_mode);
+}
+
+static const struct drm_encoder_funcs intel_ddi_funcs = {
+	.destroy = intel_ddi_destroy,
+};
+
+static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = {
+	.mode_fixup = intel_ddi_mode_fixup,
+	.mode_set = intel_ddi_mode_set,
+	.disable = intel_encoder_noop,
+};
+
+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_encoder->enable = intel_enable_ddi;
+	intel_encoder->pre_enable = intel_ddi_pre_enable;
+	intel_encoder->disable = intel_disable_ddi;
+	intel_encoder->post_disable = intel_ddi_post_disable;
+	intel_encoder->get_hw_state = intel_ddi_get_hw_state;
+
+	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 fba96c6..65a121e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -704,7 +704,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)
@@ -2205,7 +2205,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;
@@ -2559,7 +2559,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;
@@ -2580,12 +2580,6 @@ static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
 	.disable = intel_encoder_noop,
 };
 
-static const struct drm_encoder_helper_funcs intel_dp_helper_funcs_hsw = {
-	.mode_fixup = intel_dp_mode_fixup,
-	.mode_set = intel_ddi_mode_set,
-	.disable = intel_encoder_noop,
-};
-
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
 	.dpms = intel_connector_dpms,
 	.detect = intel_dp_detect,
@@ -2658,7 +2652,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)
 {
@@ -2690,7 +2684,8 @@ 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;
+		/* The intel_encoder->type value may be UNKNOWN for DDI or DP
+		 * for the older gens, so don't rewrite it. */
 	}
 
 	drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
@@ -2866,32 +2861,19 @@ 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);
-
-	if (IS_HASWELL(dev)) {
-		intel_encoder->enable = intel_enable_ddi;
-		intel_encoder->pre_enable = intel_ddi_pre_enable;
-		intel_encoder->disable = intel_disable_ddi;
-		intel_encoder->post_disable = intel_ddi_post_disable;
-		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
-	} else {
-		intel_encoder->enable = intel_enable_dp;
-		intel_encoder->pre_enable = intel_pre_enable_dp;
-		intel_encoder->disable = intel_disable_dp;
-		intel_encoder->post_disable = intel_post_disable_dp;
-		intel_encoder->get_hw_state = intel_dp_get_hw_state;
-	}
+	intel_encoder->enable = intel_enable_dp;
+	intel_encoder->pre_enable = intel_pre_enable_dp;
+	intel_encoder->disable = intel_disable_dp;
+	intel_encoder->post_disable = intel_post_disable_dp;
+	intel_encoder->get_hw_state = intel_dp_get_hw_state;
 
 	intel_dig_port->port = port;
 	intel_dig_port->hdmi.sdvox_reg = 0;
 	intel_dig_port->dp.output_reg = output_reg;
 
+	intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 	intel_encoder->cloneable = false;
 	intel_encoder->hot_plug = intel_dp_hot_plug;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 402fe70..67dbb1f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -94,6 +94,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
@@ -410,7 +411,12 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector)
 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 void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
+				      struct intel_connector *intel_connector);
 extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
+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);
@@ -423,6 +429,8 @@ extern void intel_mark_fb_idle(struct drm_i915_gem_object *obj);
 extern bool intel_lvds_init(struct drm_device *dev);
 extern void intel_dp_init(struct drm_device *dev, int output_reg,
 			  enum port port);
+extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
+				    struct intel_connector *intel_connector);
 void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode);
@@ -430,6 +438,11 @@ extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
 extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
 extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
 extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
+extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);
+extern void intel_dp_check_link_status(struct intel_dp *intel_dp);
+extern bool intel_dp_mode_fixup(struct drm_encoder *encoder,
+				const struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode);
 extern bool intel_dpd_is_edp(struct drm_device *dev);
 extern void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
 extern void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
@@ -615,13 +628,6 @@ 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_enable_ddi(struct intel_encoder *intel_encoder);
-extern void intel_disable_ddi(struct intel_encoder *intel_encoder);
-extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
-				   enum pipe *pipe);
-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_enable_pipe_func(struct drm_crtc *crtc);
 extern void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
@@ -630,8 +636,6 @@ extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
 extern void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
 extern void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
 extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock);
-extern void intel_ddi_pre_enable(struct intel_encoder *intel_encoder);
-extern void intel_ddi_post_disable(struct intel_encoder *intel_encoder);
 extern void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
 extern void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
 extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index ae5ee37..d8e4a8c 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -746,9 +746,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;
 }
@@ -912,12 +912,6 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
 	kfree(connector);
 }
 
-static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
-	.mode_fixup = intel_hdmi_mode_fixup,
-	.mode_set = intel_ddi_mode_set,
-	.disable = intel_encoder_noop,
-};
-
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
 	.mode_fixup = intel_hdmi_mode_fixup,
 	.mode_set = intel_hdmi_mode_set,
@@ -949,8 +943,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;
@@ -1045,22 +1039,11 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 
 	drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
 			 DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
 
-	if (IS_HASWELL(dev)) {
-		intel_encoder->pre_enable = intel_ddi_pre_enable;
-		intel_encoder->enable = intel_enable_ddi;
-		intel_encoder->disable = intel_disable_ddi;
-		intel_encoder->post_disable = intel_ddi_post_disable;
-		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
-		drm_encoder_helper_add(&intel_encoder->base,
-				       &intel_hdmi_helper_funcs_hsw);
-	} else {
-		intel_encoder->enable = intel_enable_hdmi;
-		intel_encoder->disable = intel_disable_hdmi;
-		intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
-		drm_encoder_helper_add(&intel_encoder->base,
-				       &intel_hdmi_helper_funcs);
-	}
+	intel_encoder->enable = intel_enable_hdmi;
+	intel_encoder->disable = intel_disable_hdmi;
+	intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
 
 	intel_dig_port->port = port;
 	intel_dig_port->hdmi.sdvox_reg = sdvox_reg;
-- 
1.7.10.4

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

* Re: [PATCH 01/47] drm/i915: rewrite the LCPLL code
  2012-10-02 20:51 ` [PATCH 01/47] drm/i915: rewrite the LCPLL code Paulo Zanoni
@ 2012-10-03 16:47   ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-03 16:47 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Tue, Oct 2, 2012 at 9:51 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> +       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;
> +       }

This fixup code looks weird to me, have you encountered cases where it
makes it work or is it "just in case"? it's "weird" to me for the
following reasons:
  - It tries to adapt the LCPLL freq depending on the value programmed
in CDCLOCK, but CDCLOCK derives from LCPLL, should not fixup code  try
to do the opposite then (if we want to try to do that at all)?
  - the 540MHz clock is only available is FUSE_STRAP bit 24 is not
set, I guess we'd want to test that

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

Are we sure that enabling LCPLL has ever done something? if the driver
would have to enable LCPLL, you'd have to ensure that CDCLOCK is
enabled as well for instance. My gut feeling is that this BIOS domain.

I think I'd just try to drop the initial hunk instead of rewriting it,
but what do I know :p

-- 
Damien

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

* Re: [PATCH 02/47] drm/i915: enable and disable DDI_FUNC_CTL at the right time
  2012-10-02 20:51 ` [PATCH 02/47] drm/i915: enable and disable DDI_FUNC_CTL at the right time Paulo Zanoni
@ 2012-10-03 17:44   ` Lespiau, Damien
  2012-10-04 20:15     ` Paulo Zanoni
  0 siblings, 1 reply; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-03 17:44 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Tue, Oct 2, 2012 at 9:51 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> And the right time is exactly after/before changing PIPE_CONF. See the
> documentation about the mode set sequence.
>
> This code is not inside any encoder-specific callback because
> DDI_FUNC_CTL is part of the pipe, so it is used by all encoders.

Apart from the reordering of this patch with [PATCH 07/47] drm/i915:
add haswell_crtc_mode_set,

Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

-- 
Damien

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

* Re: [PATCH 03/47] drm/i915: enable and disable PIPE_CLK_SEL at the right time
  2012-10-02 20:51 ` [PATCH 03/47] drm/i915: enable and disable PIPE_CLK_SEL " Paulo Zanoni
@ 2012-10-04 11:28   ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-04 11:28 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Tue, Oct 2, 2012 at 9:51 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> Previously we were enabling it at mode_set but never disabling. Let's
> follow the mode set sequence.

Apart from the same patch reordering mentioned in patch 2:
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

-- 
Damien

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

* Re: [PATCH 10/47] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set
  2012-10-02 20:51 ` [PATCH 10/47] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set Paulo Zanoni
@ 2012-10-04 14:14   ` Lespiau, Damien
  2012-10-05 12:53     ` Paulo Zanoni
  0 siblings, 1 reply; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-04 14:14 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Tue, Oct 2, 2012 at 9:51 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> @@ -5356,8 +5361,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
>
>         haswell_set_pipeconf(crtc, adjusted_mode, dither);
>
> -       intel_wait_for_vblank(dev, pipe);
> -

I guess this hunk could go into a separate commit.

-- 
Damien

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

* Re: [PATCH 09/47] drm/i915: add haswell_set_pipeconf
  2012-10-02 20:51 ` [PATCH 09/47] drm/i915: add haswell_set_pipeconf Paulo Zanoni
@ 2012-10-04 14:36   ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-04 14:36 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Tue, Oct 2, 2012 at 9:51 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> It's a copy of ironlake_set_pipeconf with 2 differences:
>   - There is no BPC field to set.
>   - The interlaced mask is now 2 bits instead of 3.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

--
Damien

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

* Re: [PATCH 07/47] drm/i915: add haswell_crtc_mode_set
  2012-10-02 20:51 ` [PATCH 07/47] drm/i915: add haswell_crtc_mode_set Paulo Zanoni
@ 2012-10-04 14:38   ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-04 14:38 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Tue, Oct 2, 2012 at 9:51 PM, Paulo Zanoni <przanoni@gmail.com> wrote:

> +static int haswell_crtc_mode_set(struct drm_crtc *crtc,
> +                                struct drm_display_mode *mode,
> +                                struct drm_display_mode *adjusted_mode,
> +                                int x, int y,
> +                                struct drm_framebuffer *fb)
> +{
..
> +       if (IS_HASWELL(dev))
> +               if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
> +                       return -EINVAL;

I know the patch is going to be re-ordered, but IS_HASWELL() can be
dropped when adding intel_ddi_pll_mode_set() back.

-- 
Damien

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

* Re: [PATCH 02/47] drm/i915: enable and disable DDI_FUNC_CTL at the right time
  2012-10-03 17:44   ` Lespiau, Damien
@ 2012-10-04 20:15     ` Paulo Zanoni
  0 siblings, 0 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-04 20:15 UTC (permalink / raw)
  To: Lespiau, Damien; +Cc: intel-gfx, Paulo Zanoni

2012/10/3 Lespiau, Damien <damien.lespiau@intel.com>:
> On Tue, Oct 2, 2012 at 9:51 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> And the right time is exactly after/before changing PIPE_CONF. See the
>> documentation about the mode set sequence.
>>
>> This code is not inside any encoder-specific callback because
>> DDI_FUNC_CTL is part of the pipe, so it is used by all encoders.
>
> Apart from the reordering of this patch with [PATCH 07/47] drm/i915:
> add haswell_crtc_mode_set,

This patch has nothing to do with patch 07. This patch touches
ironlake_crtc_{enable,disable}, not ironlake_crtc_mode_set. We did not
fork ironlake_crtc_{enable,disable} since the haswell-specific changes
are too small.

>
> Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

Thanks for the review :)

>
> --
> Damien



-- 
Paulo Zanoni

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

* Re: [PATCH 10/47] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set
  2012-10-04 14:14   ` Lespiau, Damien
@ 2012-10-05 12:53     ` Paulo Zanoni
  2012-10-05 13:15       ` Lespiau, Damien
  0 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 12:53 UTC (permalink / raw)
  To: Lespiau, Damien; +Cc: intel-gfx, Paulo Zanoni

2012/10/4 Lespiau, Damien <damien.lespiau@intel.com>:
> On Tue, Oct 2, 2012 at 9:51 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>> @@ -5356,8 +5361,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
>>
>>         haswell_set_pipeconf(crtc, adjusted_mode, dither);
>>
>> -       intel_wait_for_vblank(dev, pipe);
>> -
>
> I guess this hunk could go into a separate commit.

My way of thinking is that since the pipe is disabled there's no
reason to wait for vblank here.

>
> --
> Damien



-- 
Paulo Zanoni

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

* Re: [PATCH 10/47] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set
  2012-10-05 12:53     ` Paulo Zanoni
@ 2012-10-05 13:15       ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-05 13:15 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 1:53 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> 2012/10/4 Lespiau, Damien <damien.lespiau@intel.com>:
>> On Tue, Oct 2, 2012 at 9:51 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>>> @@ -5356,8 +5361,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
>>>
>>>         haswell_set_pipeconf(crtc, adjusted_mode, dither);
>>>
>>> -       intel_wait_for_vblank(dev, pipe);
>>> -
>>
>> I guess this hunk could go into a separate commit.
>
> My way of thinking is that since the pipe is disabled there's no
> reason to wait for vblank here.

Oh, sure I was just saying that it could deserve a separate commit
from the one adding the warning, but bikeshedding really.

-- 
Damien

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

* [PATCH 00/10] Haswell pipe and clocking fixes
  2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
                   ` (46 preceding siblings ...)
  2012-10-02 20:52 ` [PATCH 47/47] drm/i915: create the DDI encoder Paulo Zanoni
@ 2012-10-05 15:05 ` Paulo Zanoni
  2012-10-05 15:05   ` [PATCH 01/10] drm/i915: rewrite the LCPLL code Paulo Zanoni
                     ` (9 more replies)
  47 siblings, 10 replies; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Hi

This is a resend of the first 10 patches of the 47-patch series sent a few days
ago, with comments received on IRC and email applied.

Main changes:
  - Patch 1 rewritten. Damien pointed some things and I also had a conversation
    with an engineer and concluded that we should only check the LCPLL value and
    print errors in case it's not exactly what we expect. This register should
    be set by the BIOS and we shouldn't be changing it. Also, enabling/disabling
    LCPLL is very complicated and would require a lot of code.
  - Reordered patches. As pointed by Chris and Damien we should first fork
    haswell_crtc_mode_set and then change it, instead of changing
    ironlake_crtc_mode_set, forking a haswell version and then undoing the
    changes in ironlake_crtc.

This was the first of the 4 sub-series. So far I don't have things to change on
the second series (patches 11-24), so feel free to review them as they are.
After the changes on the first 10 patches, only patch 23 gets a very small
conflict, so I won't resend the whole series again.

I have some changes for the third series (25-38) so for now let's focus on
patches 1-10 and 11-24.

Paulo Zanoni (10):
  drm/i915: rewrite the LCPLL code
  drm/i915: enable and disable DDI_FUNC_CTL at the right time
  drm/i915: enable and disable PIPE_CLK_SEL at the right time
  drm/i915: add haswell_crtc_mode_set
  drm/i915: add proper CPU/PCH checks to crtc_mode_set functions
  drm/i915: add haswell_set_pipeconf
  drm/i915: completely rewrite the Haswell PLL handling code
  drm/i915: don't rely on previous values set on DDI_BUF_CTL
  drm/i915: disable DDI_BUF_CTL at the correct time
  drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set

 drivers/gpu/drm/i915/i915_drv.h      |   7 +
 drivers/gpu/drm/i915/i915_reg.h      |   9 +
 drivers/gpu/drm/i915/intel_ddi.c     | 441 ++++++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_display.c | 275 +++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_drv.h     |  12 +
 drivers/gpu/drm/i915/intel_hdmi.c    |   2 +
 6 files changed, 651 insertions(+), 95 deletions(-)

-- 
1.7.11.4

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

* [PATCH 01/10] drm/i915: rewrite the LCPLL code
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
@ 2012-10-05 15:05   ` Paulo Zanoni
  2012-10-10 12:47     ` Lespiau, Damien
  2012-10-05 15:05   ` [PATCH 02/10] drm/i915: enable and disable DDI_FUNC_CTL at the right time Paulo Zanoni
                     ` (8 subsequent siblings)
  9 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:05 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/enable sequence. This
register should really be set by the BIOS and we shouldn't be touching
it. Still, let's try to check its value and print some errors in case
we find something wrong. We're also adding intel_ddi_get_cdclk_freq
which will be used later in other places.

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

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f3a06b4..5107cee 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3456,6 +3456,9 @@
 #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG		0x9030
 #define  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB	(1<<11)
 
+#define HSW_FUSE_STRAP		0x42014
+#define  HSW_CDCLK_LIMIT	(1 << 24)
+
 /* PCH */
 
 /* south display engine interrupt: IBX */
@@ -4531,8 +4534,11 @@
 #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_CD_CLOCK_DISABLE		(1<<25)
 #define  LCPLL_CD2X_CLOCK_DISABLE	(1<<23)
+#define  LCPLL_CD_SOURCE_FCLK		(1<<21)
 
 /* 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 bfe3754..d912dbf 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,
@@ -817,3 +811,34 @@ void intel_disable_ddi(struct intel_encoder *encoder)
 
 	I915_WRITE(DDI_BUF_CTL(port), temp);
 }
+
+static int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
+{
+	if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT)
+		return 450;
+	else if ((I915_READ(LCPLL_CTL) & LCPLL_CLK_FREQ_MASK) ==
+		 LCPLL_CLK_FREQ_450)
+		return 450;
+	else
+		return 540;
+}
+
+void intel_ddi_pll_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t val = I915_READ(LCPLL_CTL);
+
+	/* The LCPLL register should be turned on by the BIOS. For now let's
+	 * just check its state and print errors in case something is wrong.
+	 * Don't even try to turn it on.
+	 */
+
+	DRM_DEBUG_KMS("CDCLK running at %dMHz\n",
+		      intel_ddi_get_cdclk_freq(dev_priv));
+
+	if (val & LCPLL_CD_SOURCE_FCLK)
+		DRM_ERROR("CDCLK source is not LCPLL\n");
+
+	if (val & LCPLL_PLL_DISABLE)
+		DRM_ERROR("LCPLL is disabled\n");
+}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6cf0d00..40f98d1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7477,6 +7477,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;
@@ -8085,6 +8091,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 79f8ed6..57566b7 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -580,5 +580,6 @@ extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 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.4

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

* [PATCH 02/10] drm/i915: enable and disable DDI_FUNC_CTL at the right time
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
  2012-10-05 15:05   ` [PATCH 01/10] drm/i915: rewrite the LCPLL code Paulo Zanoni
@ 2012-10-05 15:05   ` Paulo Zanoni
  2012-10-10 13:04     ` Lespiau, Damien
  2012-10-05 15:05   ` [PATCH 03/10] drm/i915: enable and disable PIPE_CLK_SEL " Paulo Zanoni
                     ` (7 subsequent siblings)
  9 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

And the right time is exactly after/before changing PIPE_CONF. See the
documentation about the mode set sequence.

This code is not inside any encoder-specific callback because
DDI_FUNC_CTL is part of the pipe, so it is used by all encoders.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      |  1 +
 drivers/gpu/drm/i915/intel_ddi.c     | 83 +++++++++++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_display.c |  6 +++
 drivers/gpu/drm/i915/intel_drv.h     |  3 ++
 4 files changed, 74 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 5107cee..d1b58d0 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4394,6 +4394,7 @@
 /* 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_SELECT_PORT(x)	((x)<<28)
+#define  PIPE_DDI_PORT_NONE		(0<<28)
 #define  PIPE_DDI_MODE_SELECT_MASK	(7<<24)
 #define  PIPE_DDI_MODE_SELECT_HDMI	(0<<24)
 #define  PIPE_DDI_MODE_SELECT_DVI	(1<<24)
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index d912dbf..4ee3038 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -203,15 +203,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 						DP_TP_CTL_ENHANCED_FRAME_ENABLE |
 						DP_TP_CTL_ENABLE);
 
-			/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in FDI mode */
-			temp = I915_READ(DDI_FUNC_CTL(pipe));
-			temp &= ~PIPE_DDI_PORT_MASK;
-			temp |= PIPE_DDI_SELECT_PORT(PORT_E) |
-					PIPE_DDI_MODE_SELECT_FDI |
-					PIPE_DDI_FUNC_ENABLE |
-					PIPE_DDI_PORT_WIDTH_X2;
-			I915_WRITE(DDI_FUNC_CTL(pipe),
-					temp);
 			break;
 		} else {
 			DRM_ERROR("Error training BUF_CTL %d\n", i);
@@ -657,7 +648,7 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	int port = intel_hdmi->ddi_port;
 	int pipe = intel_crtc->pipe;
 	int p, n2, r2;
-	u32 temp, i;
+	u32 i;
 
 	/* On Haswell, we need to enable the clocks and prepare DDI function to
 	 * work in HDMI mode for this pipe.
@@ -715,8 +706,40 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 		intel_write_eld(encoder, adjusted_mode);
 	}
 
+	intel_hdmi->set_infoframes(encoder, adjusted_mode);
+}
+
+static struct intel_encoder *
+intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder, *ret = NULL;
+	int num_encoders = 0;
+
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+		ret = intel_encoder;
+		num_encoders++;
+	}
+
+	if (num_encoders != 1)
+		WARN(1, "%d encoders on crtc for pipe %d\n", num_encoders,
+		     intel_crtc->pipe);
+
+	BUG_ON(ret == NULL);
+	return ret;
+}
+
+void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	enum pipe pipe = intel_crtc->pipe;
+	uint32_t temp;
+
 	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
-	temp = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
+	temp = PIPE_DDI_FUNC_ENABLE;
 
 	switch (intel_crtc->bpp) {
 	case 18:
@@ -736,19 +759,41 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 		     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)
+	if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
 		temp |= PIPE_DDI_PVSYNC;
-	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+	if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
 		temp |= PIPE_DDI_PHSYNC;
 
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi =
+			enc_to_intel_hdmi(&intel_encoder->base);
+
+		if (intel_hdmi->has_hdmi_sink)
+			temp |= PIPE_DDI_MODE_SELECT_HDMI;
+		else
+			temp |= PIPE_DDI_MODE_SELECT_DVI;
+
+		temp |= PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port);
+	} else if (intel_encoder->type == INTEL_OUTPUT_ANALOG) {
+		temp |= PIPE_DDI_MODE_SELECT_FDI;
+		temp |= PIPE_DDI_SELECT_PORT(PORT_E);
+	} else {
+		WARN(1, "Invalid encoder type %d for pipe %d\n",
+		     intel_encoder->type, pipe);
+	}
+
 	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+}
 
-	intel_hdmi->set_infoframes(encoder, adjusted_mode);
+void intel_ddi_disable_pipe_func(struct drm_i915_private *dev_priv,
+				 enum pipe pipe)
+{
+	uint32_t reg = DDI_FUNC_CTL(pipe);
+	uint32_t val = I915_READ(reg);
+
+	val &= ~(PIPE_DDI_FUNC_ENABLE | PIPE_DDI_PORT_MASK);
+	val |= PIPE_DDI_PORT_NONE;
+	I915_WRITE(reg, val);
 }
 
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 40f98d1..e4f07a2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3215,6 +3215,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	 */
 	intel_crtc_load_lut(crtc);
 
+	if (IS_HASWELL(dev))
+		intel_ddi_enable_pipe_func(crtc);
+
 	intel_enable_pipe(dev_priv, pipe, is_pch_port);
 	intel_enable_plane(dev_priv, plane, pipe);
 
@@ -3262,6 +3265,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
 	intel_disable_pipe(dev_priv, pipe);
 
+	if (IS_HASWELL(dev))
+		intel_ddi_disable_pipe_func(dev_priv, pipe);
+
 	/* Disable PF */
 	I915_WRITE(PF_CTL(pipe), 0);
 	I915_WRITE(PF_WIN_SZ(pipe), 0);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 57566b7..0253bb4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -581,5 +581,8 @@ 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_enable_pipe_func(struct drm_crtc *crtc);
+extern void intel_ddi_disable_pipe_func(struct drm_i915_private *dev_priv,
+					enum pipe pipe);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.11.4

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

* [PATCH 03/10] drm/i915: enable and disable PIPE_CLK_SEL at the right time
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
  2012-10-05 15:05   ` [PATCH 01/10] drm/i915: rewrite the LCPLL code Paulo Zanoni
  2012-10-05 15:05   ` [PATCH 02/10] drm/i915: enable and disable DDI_FUNC_CTL at the right time Paulo Zanoni
@ 2012-10-05 15:05   ` Paulo Zanoni
  2012-10-10 13:05     ` Lespiau, Damien
  2012-10-05 15:05   ` [PATCH 04/10] drm/i915: add haswell_crtc_mode_set Paulo Zanoni
                     ` (6 subsequent siblings)
  9 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Previously we were enabling it at mode_set but never disabling. Let's
follow the mode set sequence.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c     | 37 ++++++++++++++++++++++++++++++++----
 drivers/gpu/drm/i915/intel_display.c |  6 ++++++
 drivers/gpu/drm/i915/intel_drv.h     |  2 ++
 3 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 4ee3038..a333cfe 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -58,6 +58,22 @@ static const u32 hsw_ddi_translations_fdi[] = {
 	0x00FFFFFF, 0x00040006		/* HDMI parameters */
 };
 
+static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
+{
+	int type = intel_encoder->type;
+
+	if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi =
+			enc_to_intel_hdmi(&intel_encoder->base);
+		return intel_hdmi->ddi_port;
+	} else if (type == INTEL_OUTPUT_ANALOG) {
+		return PORT_E;
+	} else {
+		DRM_ERROR("Invalid DDI encoder type %d\n", type);
+		BUG();
+	}
+}
+
 /* On Haswell, DDI port buffers must be programmed with correct values
  * in advance. The buffer values are different for FDI and DP modes,
  * but the HDMI/DVI fields are shared among those. So we program the DDI
@@ -145,8 +161,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 	/* 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));
 
 	udelay(20);
 
@@ -689,8 +703,6 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	 */
 	I915_WRITE(PORT_CLK_SEL(port),
 			PORT_CLK_SEL_WRPLL1);
-	I915_WRITE(PIPE_CLK_SEL(pipe),
-			PIPE_CLK_SEL_PORT(port));
 
 	udelay(20);
 
@@ -825,6 +837,23 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
+{
+	struct drm_crtc *crtc = &intel_crtc->base;
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+
+	I915_WRITE(PIPE_CLK_SEL(intel_crtc->pipe), PIPE_CLK_SEL_PORT(port));
+}
+
+void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
+{
+	struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private;
+
+	I915_WRITE(PIPE_CLK_SEL(intel_crtc->pipe), PIPE_CLK_SEL_DISABLED);
+}
+
 void intel_enable_ddi(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e4f07a2..faa2013 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3197,6 +3197,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 		if (encoder->pre_enable)
 			encoder->pre_enable(encoder);
 
+	if (IS_HASWELL(dev))
+		intel_ddi_enable_pipe_clock(intel_crtc);
+
 	/* Enable panel fitting for LVDS */
 	if (dev_priv->pch_pf_size &&
 	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) {
@@ -3272,6 +3275,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	I915_WRITE(PF_CTL(pipe), 0);
 	I915_WRITE(PF_WIN_SZ(pipe), 0);
 
+	if (IS_HASWELL(dev))
+		intel_ddi_disable_pipe_clock(intel_crtc);
+
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->post_disable)
 			encoder->post_disable(encoder);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0253bb4..5de365d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -584,5 +584,7 @@ extern void intel_ddi_pll_init(struct drm_device *dev);
 extern void intel_ddi_enable_pipe_func(struct drm_crtc *crtc);
 extern void intel_ddi_disable_pipe_func(struct drm_i915_private *dev_priv,
 					enum pipe pipe);
+extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
+extern void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.11.4

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

* [PATCH 04/10] drm/i915: add haswell_crtc_mode_set
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
                     ` (2 preceding siblings ...)
  2012-10-05 15:05   ` [PATCH 03/10] drm/i915: enable and disable PIPE_CLK_SEL " Paulo Zanoni
@ 2012-10-05 15:05   ` Paulo Zanoni
  2012-10-10 13:07     ` Lespiau, Damien
  2012-10-05 15:05   ` [PATCH 05/10] drm/i915: add proper CPU/PCH checks to crtc_mode_set functions Paulo Zanoni
                     ` (5 subsequent siblings)
  9 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

It's just a copy of ironlake_crtc_mode_set.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index faa2013..ef89132 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5142,6 +5142,185 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	return ret;
 }
 
+static int haswell_crtc_mode_set(struct drm_crtc *crtc,
+				 struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode,
+				 int x, int y,
+				 struct drm_framebuffer *fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
+	int num_connectors = 0;
+	intel_clock_t clock, reduced_clock;
+	u32 dpll, fp = 0, fp2 = 0;
+	bool ok, has_reduced_clock = false;
+	bool is_lvds = false, is_dp = false, is_cpu_edp = false;
+	struct intel_encoder *encoder;
+	u32 temp;
+	int ret;
+	bool dither;
+
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		switch (encoder->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_DISPLAYPORT:
+			is_dp = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			is_dp = true;
+			if (!intel_encoder_is_pch_edp(&encoder->base))
+				is_cpu_edp = true;
+			break;
+		}
+
+		num_connectors++;
+	}
+
+	ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+				     &has_reduced_clock, &reduced_clock);
+	if (!ok) {
+		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	/* Ensure that the cursor is valid for the new mode before changing... */
+	intel_crtc_update_cursor(crtc, true);
+
+	/* determine panel color depth */
+	dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp, mode);
+	if (is_lvds && dev_priv->lvds_dither)
+		dither = true;
+
+	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+	if (has_reduced_clock)
+		fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
+			reduced_clock.m2;
+
+	dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock, fp);
+
+	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
+	drm_mode_debug_printmodeline(mode);
+
+	/* CPU eDP is the only output that doesn't need a PCH PLL of its own on
+	 * pre-Haswell/LPT generation */
+	if (HAS_PCH_LPT(dev)) {
+		DRM_DEBUG_KMS("LPT detected: no PLL for pipe %d necessary\n",
+				pipe);
+	} else if (!is_cpu_edp) {
+		struct intel_pch_pll *pll;
+
+		pll = intel_get_pch_pll(intel_crtc, dpll, fp);
+		if (pll == NULL) {
+			DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
+					 pipe);
+			return -EINVAL;
+		}
+	} else
+		intel_put_pch_pll(intel_crtc);
+
+	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
+	 * This is an exception to the general rule that mode_set doesn't turn
+	 * things on.
+	 */
+	if (is_lvds) {
+		temp = I915_READ(PCH_LVDS);
+		temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
+		if (HAS_PCH_CPT(dev)) {
+			temp &= ~PORT_TRANS_SEL_MASK;
+			temp |= PORT_TRANS_SEL_CPT(pipe);
+		} else {
+			if (pipe == 1)
+				temp |= LVDS_PIPEB_SELECT;
+			else
+				temp &= ~LVDS_PIPEB_SELECT;
+		}
+
+		/* set the corresponsding LVDS_BORDER bit */
+		temp |= dev_priv->lvds_border_bits;
+		/* Set the B0-B3 data pairs corresponding to whether we're going to
+		 * set the DPLLs for dual-channel mode or not.
+		 */
+		if (clock.p2 == 7)
+			temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+		else
+			temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
+
+		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+		 * appropriately here, but we need to look more thoroughly into how
+		 * panels behave in the two modes.
+		 */
+		temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
+		if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+			temp |= LVDS_HSYNC_POLARITY;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+			temp |= LVDS_VSYNC_POLARITY;
+		I915_WRITE(PCH_LVDS, temp);
+	}
+
+	if (is_dp && !is_cpu_edp) {
+		intel_dp_set_m_n(crtc, mode, adjusted_mode);
+	} else {
+		/* For non-DP output, clear any trans DP clock recovery setting.*/
+		I915_WRITE(TRANSDATA_M1(pipe), 0);
+		I915_WRITE(TRANSDATA_N1(pipe), 0);
+		I915_WRITE(TRANSDPLINK_M1(pipe), 0);
+		I915_WRITE(TRANSDPLINK_N1(pipe), 0);
+	}
+
+	if (intel_crtc->pch_pll) {
+		I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+
+		/* Wait for the clocks to stabilize. */
+		POSTING_READ(intel_crtc->pch_pll->pll_reg);
+		udelay(150);
+
+		/* The pixel multiplier can only be updated once the
+		 * DPLL is enabled and the clocks are stable.
+		 *
+		 * So write it again.
+		 */
+		I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+	}
+
+	intel_crtc->lowfreq_avail = false;
+	if (intel_crtc->pch_pll) {
+		if (is_lvds && has_reduced_clock && i915_powersave) {
+			I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
+			intel_crtc->lowfreq_avail = true;
+		} else {
+			I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
+		}
+	}
+
+	intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
+
+	ironlake_set_m_n(crtc, mode, adjusted_mode);
+
+	if (is_cpu_edp)
+		ironlake_set_pll_edp(crtc, adjusted_mode->clock);
+
+	ironlake_set_pipeconf(crtc, adjusted_mode, dither);
+
+	intel_wait_for_vblank(dev, pipe);
+
+	/* Set up the display plane register */
+	I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
+	POSTING_READ(DSPCNTR(plane));
+
+	ret = intel_pipe_set_base(crtc, x, y, fb);
+
+	intel_update_watermarks(dev);
+
+	intel_update_linetime_watermarks(dev, pipe, adjusted_mode);
+
+	return ret;
+}
+
 static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode,
@@ -7852,7 +8031,13 @@ static void intel_init_display(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* We always want a DPMS function */
-	if (HAS_PCH_SPLIT(dev)) {
+	if (IS_HASWELL(dev)) {
+		dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
+		dev_priv->display.crtc_enable = ironlake_crtc_enable;
+		dev_priv->display.crtc_disable = ironlake_crtc_disable;
+		dev_priv->display.off = ironlake_crtc_off;
+		dev_priv->display.update_plane = ironlake_update_plane;
+	} else if (HAS_PCH_SPLIT(dev)) {
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
 		dev_priv->display.crtc_enable = ironlake_crtc_enable;
 		dev_priv->display.crtc_disable = ironlake_crtc_disable;
-- 
1.7.11.4

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

* [PATCH 05/10] drm/i915: add proper CPU/PCH checks to crtc_mode_set functions
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
                     ` (3 preceding siblings ...)
  2012-10-05 15:05   ` [PATCH 04/10] drm/i915: add haswell_crtc_mode_set Paulo Zanoni
@ 2012-10-05 15:05   ` Paulo Zanoni
  2012-10-10 13:52     ` Lespiau, Damien
  2012-10-05 15:05   ` [PATCH 06/10] drm/i915: add haswell_set_pipeconf Paulo Zanoni
                     ` (4 subsequent siblings)
  9 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

On ironlake_crtc_mode_set, WARN if not using IBX or CPT.

On haswell_crtc_mode_set, only run IBX/CPT code on IBX/CPT. I am still
not sure whether IBX/CPT will be possible with a Haswell CPU, so leave
the code there for now and put a WARN in case we spot it.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ef89132..213831f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5002,6 +5002,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 		num_connectors++;
 	}
 
+	WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
+	     "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
+
 	ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
 				     &has_reduced_clock, &reduced_clock);
 	if (!ok) {
@@ -5027,12 +5030,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 	drm_mode_debug_printmodeline(mode);
 
-	/* CPU eDP is the only output that doesn't need a PCH PLL of its own on
-	 * pre-Haswell/LPT generation */
-	if (HAS_PCH_LPT(dev)) {
-		DRM_DEBUG_KMS("LPT detected: no PLL for pipe %d necessary\n",
-				pipe);
-	} else if (!is_cpu_edp) {
+	/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
+	if (!is_cpu_edp) {
 		struct intel_pch_pll *pll;
 
 		pll = intel_get_pch_pll(intel_crtc, dpll, fp);
@@ -5155,7 +5154,7 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	int plane = intel_crtc->plane;
 	int num_connectors = 0;
 	intel_clock_t clock, reduced_clock;
-	u32 dpll, fp = 0, fp2 = 0;
+	u32 dpll = 0, fp = 0, fp2 = 0;
 	bool ok, has_reduced_clock = false;
 	bool is_lvds = false, is_dp = false, is_cpu_edp = false;
 	struct intel_encoder *encoder;
@@ -5181,11 +5180,21 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 		num_connectors++;
 	}
 
-	ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
-				     &has_reduced_clock, &reduced_clock);
-	if (!ok) {
-		DRM_ERROR("Couldn't find PLL settings for mode!\n");
-		return -EINVAL;
+	/* We are not sure yet this won't happen. */
+	WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n",
+	     INTEL_PCH_TYPE(dev));
+
+	WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
+	     num_connectors, pipe_name(pipe));
+
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+		ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+					     &has_reduced_clock,
+					     &reduced_clock);
+		if (!ok) {
+			DRM_ERROR("Couldn't find PLL settings for mode!\n");
+			return -EINVAL;
+		}
 	}
 
 	/* Ensure that the cursor is valid for the new mode before changing... */
@@ -5196,104 +5205,112 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	if (is_lvds && dev_priv->lvds_dither)
 		dither = true;
 
-	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
-	if (has_reduced_clock)
-		fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
-			reduced_clock.m2;
-
-	dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock, fp);
-
 	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
 	drm_mode_debug_printmodeline(mode);
 
-	/* CPU eDP is the only output that doesn't need a PCH PLL of its own on
-	 * pre-Haswell/LPT generation */
-	if (HAS_PCH_LPT(dev)) {
-		DRM_DEBUG_KMS("LPT detected: no PLL for pipe %d necessary\n",
-				pipe);
-	} else if (!is_cpu_edp) {
-		struct intel_pch_pll *pll;
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+		fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+		if (has_reduced_clock)
+			fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
+			      reduced_clock.m2;
+
+		dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock,
+					     fp);
+
+		/* CPU eDP is the only output that doesn't need a PCH PLL of its
+		 * own on pre-Haswell/LPT generation */
+		if (!is_cpu_edp) {
+			struct intel_pch_pll *pll;
+
+			pll = intel_get_pch_pll(intel_crtc, dpll, fp);
+			if (pll == NULL) {
+				DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
+						 pipe);
+				return -EINVAL;
+			}
+		} else
+			intel_put_pch_pll(intel_crtc);
 
-		pll = intel_get_pch_pll(intel_crtc, dpll, fp);
-		if (pll == NULL) {
-			DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
-					 pipe);
-			return -EINVAL;
-		}
-	} else
-		intel_put_pch_pll(intel_crtc);
+		/* The LVDS pin pair needs to be on before the DPLLs are
+		 * enabled.  This is an exception to the general rule that
+		 * mode_set doesn't turn things on.
+		 */
+		if (is_lvds) {
+			temp = I915_READ(PCH_LVDS);
+			temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
+			if (HAS_PCH_CPT(dev)) {
+				temp &= ~PORT_TRANS_SEL_MASK;
+				temp |= PORT_TRANS_SEL_CPT(pipe);
+			} else {
+				if (pipe == 1)
+					temp |= LVDS_PIPEB_SELECT;
+				else
+					temp &= ~LVDS_PIPEB_SELECT;
+			}
 
-	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
-	 * This is an exception to the general rule that mode_set doesn't turn
-	 * things on.
-	 */
-	if (is_lvds) {
-		temp = I915_READ(PCH_LVDS);
-		temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-		if (HAS_PCH_CPT(dev)) {
-			temp &= ~PORT_TRANS_SEL_MASK;
-			temp |= PORT_TRANS_SEL_CPT(pipe);
-		} else {
-			if (pipe == 1)
-				temp |= LVDS_PIPEB_SELECT;
+			/* set the corresponsding LVDS_BORDER bit */
+			temp |= dev_priv->lvds_border_bits;
+			/* Set the B0-B3 data pairs corresponding to whether
+			 * we're going to set the DPLLs for dual-channel mode or
+			 * not.
+			 */
+			if (clock.p2 == 7)
+				temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
 			else
-				temp &= ~LVDS_PIPEB_SELECT;
+				temp &= ~(LVDS_B0B3_POWER_UP |
+					  LVDS_CLKB_POWER_UP);
+
+			/* It would be nice to set 24 vs 18-bit mode
+			 * (LVDS_A3_POWER_UP) appropriately here, but we need to
+			 * look more thoroughly into how panels behave in the
+			 * two modes.
+			 */
+			temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
+			if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+				temp |= LVDS_HSYNC_POLARITY;
+			if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+				temp |= LVDS_VSYNC_POLARITY;
+			I915_WRITE(PCH_LVDS, temp);
 		}
-
-		/* set the corresponsding LVDS_BORDER bit */
-		temp |= dev_priv->lvds_border_bits;
-		/* Set the B0-B3 data pairs corresponding to whether we're going to
-		 * set the DPLLs for dual-channel mode or not.
-		 */
-		if (clock.p2 == 7)
-			temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
-		else
-			temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
-
-		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
-		 * appropriately here, but we need to look more thoroughly into how
-		 * panels behave in the two modes.
-		 */
-		temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
-		if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
-			temp |= LVDS_HSYNC_POLARITY;
-		if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
-			temp |= LVDS_VSYNC_POLARITY;
-		I915_WRITE(PCH_LVDS, temp);
 	}
 
 	if (is_dp && !is_cpu_edp) {
 		intel_dp_set_m_n(crtc, mode, adjusted_mode);
 	} else {
-		/* For non-DP output, clear any trans DP clock recovery setting.*/
-		I915_WRITE(TRANSDATA_M1(pipe), 0);
-		I915_WRITE(TRANSDATA_N1(pipe), 0);
-		I915_WRITE(TRANSDPLINK_M1(pipe), 0);
-		I915_WRITE(TRANSDPLINK_N1(pipe), 0);
-	}
-
-	if (intel_crtc->pch_pll) {
-		I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
-
-		/* Wait for the clocks to stabilize. */
-		POSTING_READ(intel_crtc->pch_pll->pll_reg);
-		udelay(150);
-
-		/* The pixel multiplier can only be updated once the
-		 * DPLL is enabled and the clocks are stable.
-		 *
-		 * So write it again.
-		 */
-		I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+		if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+			/* For non-DP output, clear any trans DP clock recovery
+			 * setting.*/
+			I915_WRITE(TRANSDATA_M1(pipe), 0);
+			I915_WRITE(TRANSDATA_N1(pipe), 0);
+			I915_WRITE(TRANSDPLINK_M1(pipe), 0);
+			I915_WRITE(TRANSDPLINK_N1(pipe), 0);
+		}
 	}
 
 	intel_crtc->lowfreq_avail = false;
-	if (intel_crtc->pch_pll) {
-		if (is_lvds && has_reduced_clock && i915_powersave) {
-			I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
-			intel_crtc->lowfreq_avail = true;
-		} else {
-			I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+		if (intel_crtc->pch_pll) {
+			I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+
+			/* Wait for the clocks to stabilize. */
+			POSTING_READ(intel_crtc->pch_pll->pll_reg);
+			udelay(150);
+
+			/* The pixel multiplier can only be updated once the
+			 * DPLL is enabled and the clocks are stable.
+			 *
+			 * So write it again.
+			 */
+			I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
+		}
+
+		if (intel_crtc->pch_pll) {
+			if (is_lvds && has_reduced_clock && i915_powersave) {
+				I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
+				intel_crtc->lowfreq_avail = true;
+			} else {
+				I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
+			}
 		}
 	}
 
@@ -5301,8 +5318,9 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 
 	ironlake_set_m_n(crtc, mode, adjusted_mode);
 
-	if (is_cpu_edp)
-		ironlake_set_pll_edp(crtc, adjusted_mode->clock);
+	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+		if (is_cpu_edp)
+			ironlake_set_pll_edp(crtc, adjusted_mode->clock);
 
 	ironlake_set_pipeconf(crtc, adjusted_mode, dither);
 
-- 
1.7.11.4

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

* [PATCH 06/10] drm/i915: add haswell_set_pipeconf
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
                     ` (4 preceding siblings ...)
  2012-10-05 15:05   ` [PATCH 05/10] drm/i915: add proper CPU/PCH checks to crtc_mode_set functions Paulo Zanoni
@ 2012-10-05 15:05   ` Paulo Zanoni
  2012-10-10 13:59     ` Lespiau, Damien
  2012-10-05 15:05   ` [PATCH 07/10] drm/i915: completely rewrite the Haswell PLL handling code Paulo Zanoni
                     ` (3 subsequent siblings)
  9 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

It's a copy of ironlake_set_pipeconf with 2 differences:
  - There is no BPC field to set.
  - The interlaced mask is now 2 bits instead of 3.

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

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index d1b58d0..fd9a319 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2639,6 +2639,7 @@
 #define   PIPECONF_GAMMA		(1<<24)
 #define   PIPECONF_FORCE_BORDER	(1<<25)
 #define   PIPECONF_INTERLACE_MASK	(7 << 21)
+#define   PIPECONF_INTERLACE_MASK_HSW	(3 << 21)
 /* Note that pre-gen3 does not support interlaced display directly. Panel
  * fitting must be disabled on pre-ilk for interlaced. */
 #define   PIPECONF_PROGRESSIVE			(0 << 21)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 213831f..39d0753 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4721,6 +4721,31 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
 	POSTING_READ(PIPECONF(pipe));
 }
 
+static void haswell_set_pipeconf(struct drm_crtc *crtc,
+				 struct drm_display_mode *adjusted_mode,
+				 bool dither)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	uint32_t val;
+
+	val = I915_READ(PIPECONF(pipe));
+
+	val &= ~(PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_MASK);
+	if (dither)
+		val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
+
+	val &= ~PIPECONF_INTERLACE_MASK_HSW;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+		val |= PIPECONF_INTERLACED_ILK;
+	else
+		val |= PIPECONF_PROGRESSIVE;
+
+	I915_WRITE(PIPECONF(pipe), val);
+	POSTING_READ(PIPECONF(pipe));
+}
+
 static bool ironlake_compute_clocks(struct drm_crtc *crtc,
 				    struct drm_display_mode *adjusted_mode,
 				    intel_clock_t *clock,
@@ -5322,7 +5347,7 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 		if (is_cpu_edp)
 			ironlake_set_pll_edp(crtc, adjusted_mode->clock);
 
-	ironlake_set_pipeconf(crtc, adjusted_mode, dither);
+	haswell_set_pipeconf(crtc, adjusted_mode, dither);
 
 	intel_wait_for_vblank(dev, pipe);
 
-- 
1.7.11.4

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

* [PATCH 07/10] drm/i915: completely rewrite the Haswell PLL handling code
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
                     ` (5 preceding siblings ...)
  2012-10-05 15:05   ` [PATCH 06/10] drm/i915: add haswell_set_pipeconf Paulo Zanoni
@ 2012-10-05 15:05   ` Paulo Zanoni
  2012-10-10 14:22     ` Lespiau, Damien
  2012-10-05 15:05   ` [PATCH 08/10] drm/i915: don't rely on previous values set on DDI_BUF_CTL Paulo Zanoni
                     ` (2 subsequent siblings)
  9 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Problems with the previous code:
  - HDMI just uses WRPLL1 for everything, so dual head cases might not
    work sometimes.
  - At encoder->mode_set we just write the PLL register without doing
    any kind of check (e.g., check if the PLL is already being used).
  - There is no way to fail and return error codes at
    encoder->mode_set.
  - We write to PORT_CLK_SEL at mode_set and we never disable it.
  - Machines hang due to wrong clock enable/disable sequence.

So here we rewrite the code, making it a little more like the
pre-Haswell PLL mode set code:
  - Check PLL availability at ironlake_crtc_mode_set.
  - Try to use both WRPLLs.
  - Check if PLLs are used before actually trying to use them, and
    properly fail with error messages.
  - Enable/disable PORT_CLK_SEL at the right place.
  - Add some WARNs to check for bugs.

The next improvement will be to try to reuse PLLs if the timings
match, but this is content for another patch and it's already
documented with a TODO comment.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |   7 +
 drivers/gpu/drm/i915/i915_reg.h      |   1 +
 drivers/gpu/drm/i915/intel_ddi.c     | 263 ++++++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_display.c |  13 +-
 drivers/gpu/drm/i915/intel_drv.h     |   6 +
 drivers/gpu/drm/i915/intel_hdmi.c    |   2 +
 6 files changed, 238 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index af5ceb4..fc3761e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -93,6 +93,12 @@ struct intel_pch_pll {
 };
 #define I915_NUM_PLLS 2
 
+struct intel_ddi_plls {
+	int spll_refcount;
+	int wrpll1_refcount;
+	int wrpll2_refcount;
+};
+
 /* Interface history:
  *
  * 1.1: Original.
@@ -811,6 +817,7 @@ typedef struct drm_i915_private {
 	wait_queue_head_t pending_flip_queue;
 
 	struct intel_pch_pll pch_plls[I915_NUM_PLLS];
+	struct intel_ddi_plls ddi_plls;
 
 	/* Reclocking support */
 	bool render_reclock_avail;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index fd9a319..c8c8dd0 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4523,6 +4523,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 a333cfe..f713980 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -152,18 +152,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);
-
-	udelay(20);
-
 	/* Start the training iterating through available voltages and emphasis */
 	for (i=0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values); i++) {
 		/* Configure DP_TP_CTL with auto-training */
@@ -654,58 +642,17 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
 {
-	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;
-	int p, n2, r2;
-	u32 i;
 
 	/* 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);
-
-	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.
@@ -742,6 +689,144 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc)
 	return ret;
 }
 
+void intel_ddi_put_crtc_pll(struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	uint32_t val;
+
+	switch (intel_crtc->ddi_pll_sel) {
+	case PORT_CLK_SEL_SPLL:
+		plls->spll_refcount--;
+		if (plls->spll_refcount == 0) {
+			DRM_DEBUG_KMS("Disabling SPLL\n");
+			val = I915_READ(SPLL_CTL);
+			WARN_ON(!(val & SPLL_PLL_ENABLE));
+			I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
+			POSTING_READ(SPLL_CTL);
+		}
+		break;
+	case PORT_CLK_SEL_WRPLL1:
+		plls->wrpll1_refcount--;
+		if (plls->wrpll1_refcount == 0) {
+			DRM_DEBUG_KMS("Disabling WRPLL 1\n");
+			val = I915_READ(WRPLL_CTL1);
+			WARN_ON(!(val & WRPLL_PLL_ENABLE));
+			I915_WRITE(WRPLL_CTL1, val & ~WRPLL_PLL_ENABLE);
+			POSTING_READ(WRPLL_CTL1);
+		}
+		break;
+	case PORT_CLK_SEL_WRPLL2:
+		plls->wrpll2_refcount--;
+		if (plls->wrpll2_refcount == 0) {
+			DRM_DEBUG_KMS("Disabling WRPLL 2\n");
+			val = I915_READ(WRPLL_CTL2);
+			WARN_ON(!(val & WRPLL_PLL_ENABLE));
+			I915_WRITE(WRPLL_CTL2, val & ~WRPLL_PLL_ENABLE);
+			POSTING_READ(WRPLL_CTL2);
+		}
+		break;
+	}
+
+	WARN(plls->spll_refcount < 0, "Invalid SPLL refcount\n");
+	WARN(plls->wrpll1_refcount < 0, "Invalid WRPLL1 refcount\n");
+	WARN(plls->wrpll2_refcount < 0, "Invalid WRPLL2 refcount\n");
+
+	intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
+}
+
+static void intel_ddi_calculate_wrpll(int clock, int *p, int *n2, int *r2)
+{
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++)
+		if (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 != clock)
+		DRM_INFO("WRPLL: using settings for %dKHz on %dKHz mode\n",
+			 wrpll_tmds_clock_table[i].clock, clock);
+
+	DRM_DEBUG_KMS("WRPLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
+		      clock, *p, *n2, *r2);
+}
+
+bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_ddi_plls *plls = &dev_priv->ddi_plls;
+	int type = intel_encoder->type;
+	enum pipe pipe = intel_crtc->pipe;
+	uint32_t reg, val;
+
+	/* TODO: reuse PLLs when possible (compare values) */
+
+	intel_ddi_put_crtc_pll(crtc);
+
+	if (type == INTEL_OUTPUT_HDMI) {
+		int p, n2, r2;
+
+		if (plls->wrpll1_refcount == 0) {
+			DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n",
+				      pipe_name(pipe));
+			plls->wrpll1_refcount++;
+			reg = WRPLL_CTL1;
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
+		} else if (plls->wrpll2_refcount == 0) {
+			DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n",
+				      pipe_name(pipe));
+			plls->wrpll2_refcount++;
+			reg = WRPLL_CTL2;
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
+		} else {
+			DRM_ERROR("No WRPLLs available!\n");
+			return false;
+		}
+
+		WARN(I915_READ(reg) & WRPLL_PLL_ENABLE,
+		     "WRPLL already enabled\n");
+
+		intel_ddi_calculate_wrpll(clock, &p, &n2, &r2);
+
+		val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
+		      WRPLL_DIVIDER_POST(p);
+
+	} else if (type == INTEL_OUTPUT_ANALOG) {
+		if (plls->spll_refcount == 0) {
+			DRM_DEBUG_KMS("Using SPLL on pipe %c\n",
+				      pipe_name(pipe));
+			plls->spll_refcount++;
+			reg = SPLL_CTL;
+			intel_crtc->ddi_pll_sel = PORT_CLK_SEL_SPLL;
+		}
+
+		WARN(I915_READ(reg) & SPLL_PLL_ENABLE,
+		     "SPLL already enabled\n");
+
+		val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SCC;
+
+	} else {
+		WARN(1, "Invalid DDI encoder type %d\n", type);
+		return false;
+	}
+
+	I915_WRITE(reg, val);
+	udelay(20);
+
+	return true;
+}
+
 void intel_ddi_enable_pipe_func(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -837,6 +922,57 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 	return true;
 }
 
+static uint32_t intel_ddi_get_crtc_pll(struct drm_i915_private *dev_priv,
+				       enum pipe pipe)
+{
+	uint32_t temp, ret;
+	enum port port;
+	int i;
+
+	temp = I915_READ(DDI_FUNC_CTL(pipe));
+	temp &= PIPE_DDI_PORT_MASK;
+	for (i = PORT_A; i <= PORT_E; i++)
+		if (temp == PIPE_DDI_SELECT_PORT(i))
+			port = i;
+
+	ret = I915_READ(PORT_CLK_SEL(port));
+
+	DRM_DEBUG_KMS("Pipe %c connected to port %c using clock 0x%08x\n",
+		      pipe_name(pipe), port_name(port), ret);
+
+	return ret;
+}
+
+void intel_ddi_setup_hw_pll_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum pipe pipe;
+	struct intel_crtc *intel_crtc;
+
+	for_each_pipe(pipe) {
+		intel_crtc =
+			to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+
+		if (!intel_crtc->active)
+			continue;
+
+		intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv,
+								 pipe);
+
+		switch (intel_crtc->ddi_pll_sel) {
+		case PORT_CLK_SEL_SPLL:
+			dev_priv->ddi_plls.spll_refcount++;
+			break;
+		case PORT_CLK_SEL_WRPLL1:
+			dev_priv->ddi_plls.wrpll1_refcount++;
+			break;
+		case PORT_CLK_SEL_WRPLL2:
+			dev_priv->ddi_plls.wrpll2_refcount++;
+			break;
+		}
+	}
+}
+
 void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
 {
 	struct drm_crtc *crtc = &intel_crtc->base;
@@ -854,6 +990,27 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
 	I915_WRITE(PIPE_CLK_SEL(intel_crtc->pipe), PIPE_CLK_SEL_DISABLED);
 }
 
+void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
+{
+	struct drm_crtc *crtc = intel_encoder->base.crtc;
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+
+	WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
+
+	I915_WRITE(PORT_CLK_SEL(port), intel_crtc->ddi_pll_sel);
+}
+
+void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
+{
+	struct drm_encoder *encoder = &intel_encoder->base;
+	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
+	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+
+	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
+}
+
 void intel_enable_ddi(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 39d0753..709497d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3332,6 +3332,11 @@ static void ironlake_crtc_off(struct drm_crtc *crtc)
 	intel_put_pch_pll(intel_crtc);
 }
 
+static void haswell_crtc_off(struct drm_crtc *crtc)
+{
+	intel_ddi_put_crtc_pll(crtc);
+}
+
 static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
 {
 	if (!enable && intel_crtc->overlay) {
@@ -5212,6 +5217,9 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
 	     num_connectors, pipe_name(pipe));
 
+	if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
+		return -EINVAL;
+
 	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
 		ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
 					     &has_reduced_clock,
@@ -8078,7 +8086,7 @@ static void intel_init_display(struct drm_device *dev)
 		dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
 		dev_priv->display.crtc_enable = ironlake_crtc_enable;
 		dev_priv->display.crtc_disable = ironlake_crtc_disable;
-		dev_priv->display.off = ironlake_crtc_off;
+		dev_priv->display.off = haswell_crtc_off;
 		dev_priv->display.update_plane = ironlake_update_plane;
 	} else if (HAS_PCH_SPLIT(dev)) {
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
@@ -8533,6 +8541,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 			      crtc->active ? "enabled" : "disabled");
 	}
 
+	if (IS_HASWELL(dev))
+		intel_ddi_setup_hw_pll_state(dev);
+
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
 			    base.head) {
 		pipe = 0;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5de365d..245319a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -212,6 +212,7 @@ struct intel_crtc {
 
 	/* We can share PLLs across outputs if the timings match */
 	struct intel_pch_pll *pch_pll;
+	uint32_t ddi_pll_sel;
 };
 
 struct intel_plane {
@@ -586,5 +587,10 @@ extern void intel_ddi_disable_pipe_func(struct drm_i915_private *dev_priv,
 					enum pipe pipe);
 extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
 extern void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
+extern void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
+extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc, int clock);
+extern void intel_ddi_pre_enable(struct intel_encoder *intel_encoder);
+extern void intel_ddi_post_disable(struct intel_encoder *intel_encoder);
+extern void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index f9fb47c..a6dd00d9 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1013,8 +1013,10 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 	}
 
 	if (IS_HASWELL(dev)) {
+		intel_encoder->pre_enable = intel_ddi_pre_enable;
 		intel_encoder->enable = intel_enable_ddi;
 		intel_encoder->disable = intel_disable_ddi;
+		intel_encoder->post_disable = intel_ddi_post_disable;
 		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
 		drm_encoder_helper_add(&intel_encoder->base,
 				       &intel_hdmi_helper_funcs_hsw);
-- 
1.7.11.4

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

* [PATCH 08/10] drm/i915: don't rely on previous values set on DDI_BUF_CTL
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
                     ` (6 preceding siblings ...)
  2012-10-05 15:05   ` [PATCH 07/10] drm/i915: completely rewrite the Haswell PLL handling code Paulo Zanoni
@ 2012-10-05 15:05   ` Paulo Zanoni
  2012-10-10 14:27     ` Lespiau, Damien
  2012-10-05 15:06   ` [PATCH 09/10] drm/i915: disable DDI_BUF_CTL at the correct time Paulo Zanoni
  2012-10-05 15:06   ` [PATCH 10/10] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set Paulo Zanoni
  9 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

Just set the only bit we need, everything else is either ignored on
HDMI or should be set to zero.

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index f713980..a4e05d0 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1017,16 +1017,12 @@ void intel_enable_ddi(struct intel_encoder *encoder)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	int port = intel_hdmi->ddi_port;
-	u32 temp;
-
-	temp = I915_READ(DDI_BUF_CTL(port));
-	temp |= DDI_BUF_CTL_ENABLE;
 
 	/* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width,
 	 * and swing/emphasis values are ignored so nothing special needs
 	 * to be done besides enabling the port.
 	 */
-	I915_WRITE(DDI_BUF_CTL(port), temp);
+	I915_WRITE(DDI_BUF_CTL(port), DDI_BUF_CTL_ENABLE);
 }
 
 void intel_disable_ddi(struct intel_encoder *encoder)
-- 
1.7.11.4

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

* [PATCH 09/10] drm/i915: disable DDI_BUF_CTL at the correct time
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
                     ` (7 preceding siblings ...)
  2012-10-05 15:05   ` [PATCH 08/10] drm/i915: don't rely on previous values set on DDI_BUF_CTL Paulo Zanoni
@ 2012-10-05 15:06   ` Paulo Zanoni
  2012-10-10 22:30     ` Lespiau, Damien
  2012-10-05 15:06   ` [PATCH 10/10] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set Paulo Zanoni
  9 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

And also properly wait for its idle bit.

You may notice that DDI_BUF_CTL is enabled in .enable but disabled in
.post_disable instead of .disable. Yes, the mode set sequence is not
exactly symmetrical, but let's assume the spec is correct unless we
can prove it's wrong.

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index a4e05d0..5726acc 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1002,11 +1002,33 @@ void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 	I915_WRITE(PORT_CLK_SEL(port), intel_crtc->ddi_pll_sel);
 }
 
+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_post_disable(struct intel_encoder *intel_encoder)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
 	enum port port = intel_ddi_get_encoder_port(intel_encoder);
+	uint32_t val;
+
+	val = I915_READ(DDI_BUF_CTL(port));
+	if (val & DDI_BUF_CTL_ENABLE) {
+		val &= ~DDI_BUF_CTL_ENABLE;
+		I915_WRITE(DDI_BUF_CTL(port), val);
+		intel_wait_ddi_buf_idle(dev_priv, port);
+	}
 
 	I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
 }
@@ -1027,16 +1049,7 @@ void intel_enable_ddi(struct intel_encoder *encoder)
 
 void intel_disable_ddi(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
-	int port = intel_hdmi->ddi_port;
-	u32 temp;
-
-	temp = I915_READ(DDI_BUF_CTL(port));
-	temp &= ~DDI_BUF_CTL_ENABLE;
-
-	I915_WRITE(DDI_BUF_CTL(port), temp);
+	/* This will be needed in the future, so leave it here for now */
 }
 
 static int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
-- 
1.7.11.4

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

* [PATCH 10/10] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set
  2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
                     ` (8 preceding siblings ...)
  2012-10-05 15:06   ` [PATCH 09/10] drm/i915: disable DDI_BUF_CTL at the correct time Paulo Zanoni
@ 2012-10-05 15:06   ` Paulo Zanoni
  2012-10-10 21:57     ` Lespiau, Damien
  9 siblings, 1 reply; 83+ messages in thread
From: Paulo Zanoni @ 2012-10-05 15:06 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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

So WARN in case they're not. It also does not make any sense to
wait_for_vblank at this point.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 709497d..705ed80 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5217,6 +5217,11 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 	WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
 	     num_connectors, pipe_name(pipe));
 
+	WARN_ON(I915_READ(PIPECONF(pipe)) &
+		(PIPECONF_ENABLE | I965_PIPECONF_ACTIVE));
+
+	WARN_ON(I915_READ(DSPCNTR(plane)) & DISPLAY_PLANE_ENABLE);
+
 	if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
 		return -EINVAL;
 
@@ -5357,8 +5362,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 
 	haswell_set_pipeconf(crtc, adjusted_mode, dither);
 
-	intel_wait_for_vblank(dev, pipe);
-
 	/* Set up the display plane register */
 	I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
 	POSTING_READ(DSPCNTR(plane));
-- 
1.7.11.4

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

* Re: [PATCH 01/10] drm/i915: rewrite the LCPLL code
  2012-10-05 15:05   ` [PATCH 01/10] drm/i915: rewrite the LCPLL code Paulo Zanoni
@ 2012-10-10 12:47     ` Lespiau, Damien
  2012-10-10 12:53       ` Lespiau, Damien
  0 siblings, 1 reply; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 12:47 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:

> +static int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
> +{
> +       if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT)
> +               return 450;

I don't think reading this fused register is necessary here, it only
really matters when you try to set the LCPLL alternate frequency to
check if the hardware supports it. I'd just rely on the frequency set
bits in LCPLL (if you remove this, it means that the hunk adding the
register definition is not needed any more).

If you really want to check for consistency, then you could warn if
the LCPLL freq has been programmed with 0x1 and HSW_CDCLK_LIMIT is set
(in which case the setting will be ignored). But then, there's nothing
we can do anyway, so well...

-- 
Damien

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

* Re: [PATCH 01/10] drm/i915: rewrite the LCPLL code
  2012-10-10 12:47     ` Lespiau, Damien
@ 2012-10-10 12:53       ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 12:53 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Wed, Oct 10, 2012 at 1:47 PM, Lespiau, Damien
<damien.lespiau@intel.com> wrote:
> On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>
>> +static int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv)
>> +{
>> +       if (I915_READ(HSW_FUSE_STRAP) & HSW_CDCLK_LIMIT)
>> +               return 450;
>
> I don't think reading this fused register is necessary here, it only
> really matters when you try to set the LCPLL alternate frequency to
> check if the hardware supports it. I'd just rely on the frequency set
> bits in LCPLL (if you remove this, it means that the hunk adding the
> register definition is not needed any more).
>
> If you really want to check for consistency, then you could warn if
> the LCPLL freq has been programmed with 0x1 and HSW_CDCLK_LIMIT is set
> (in which case the setting will be ignored). But then, there's nothing
> we can do anyway, so well...

Hum, I meant to add, it's just bike-shedding really, it's totally fine
if you want to return 450 if HSW_CDCLK_LIMIT is set without checking
for the programmed value in LCPLL. So really:

Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

-- 
Damien

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

* Re: [PATCH 02/10] drm/i915: enable and disable DDI_FUNC_CTL at the right time
  2012-10-05 15:05   ` [PATCH 02/10] drm/i915: enable and disable DDI_FUNC_CTL at the right time Paulo Zanoni
@ 2012-10-10 13:04     ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 13:04 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> And the right time is exactly after/before changing PIPE_CONF. See the
> documentation about the mode set sequence.
>
> This code is not inside any encoder-specific callback because
> DDI_FUNC_CTL is part of the pipe, so it is used by all encoders.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

The r-b still holds with the resend.

-- 
Damien

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

* Re: [PATCH 03/10] drm/i915: enable and disable PIPE_CLK_SEL at the right time
  2012-10-05 15:05   ` [PATCH 03/10] drm/i915: enable and disable PIPE_CLK_SEL " Paulo Zanoni
@ 2012-10-10 13:05     ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 13:05 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> Previously we were enabling it at mode_set but never disabling. Let's
> follow the mode set sequence.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

The r-b still holds with the resend.

-- 
Damien

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

* Re: [PATCH 04/10] drm/i915: add haswell_crtc_mode_set
  2012-10-05 15:05   ` [PATCH 04/10] drm/i915: add haswell_crtc_mode_set Paulo Zanoni
@ 2012-10-10 13:07     ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 13:07 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> It's just a copy of ironlake_crtc_mode_set.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

-- 
Damien

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

* Re: [PATCH 05/10] drm/i915: add proper CPU/PCH checks to crtc_mode_set functions
  2012-10-05 15:05   ` [PATCH 05/10] drm/i915: add proper CPU/PCH checks to crtc_mode_set functions Paulo Zanoni
@ 2012-10-10 13:52     ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 13:52 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> On ironlake_crtc_mode_set, WARN if not using IBX or CPT.
>
> On haswell_crtc_mode_set, only run IBX/CPT code on IBX/CPT. I am still
> not sure whether IBX/CPT will be possible with a Haswell CPU, so leave
> the code there for now and put a WARN in case we spot it.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Hum, indeed, it'd be interesting to know if the HSW can have an
IBX/CPT PCH. Somehow I doubt it. We should definitely ask :). This
could potentially remove quite a bit of code. But for now:

Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

-- 
Damien

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

* Re: [PATCH 06/10] drm/i915: add haswell_set_pipeconf
  2012-10-05 15:05   ` [PATCH 06/10] drm/i915: add haswell_set_pipeconf Paulo Zanoni
@ 2012-10-10 13:59     ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 13:59 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> It's a copy of ironlake_set_pipeconf with 2 differences:
>   - There is no BPC field to set.
>   - The interlaced mask is now 2 bits instead of 3.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

-- 
Damien

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

* Re: [PATCH 07/10] drm/i915: completely rewrite the Haswell PLL handling code
  2012-10-05 15:05   ` [PATCH 07/10] drm/i915: completely rewrite the Haswell PLL handling code Paulo Zanoni
@ 2012-10-10 14:22     ` Lespiau, Damien
  2012-10-10 14:52       ` Daniel Vetter
  0 siblings, 1 reply; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 14:22 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> +               val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SCC;

We probably want a patch on top to fix the SCC typo (should be SSC,
Spread Spectrum Clock).

There's also some fiddly bit with CPU Vs PCH SSC sources, but this can
be a later addition.

Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

-- 
Damien

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

* Re: [PATCH 08/10] drm/i915: don't rely on previous values set on DDI_BUF_CTL
  2012-10-05 15:05   ` [PATCH 08/10] drm/i915: don't rely on previous values set on DDI_BUF_CTL Paulo Zanoni
@ 2012-10-10 14:27     ` Lespiau, Damien
  2012-10-10 14:56       ` Daniel Vetter
  0 siblings, 1 reply; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 14:27 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> Just set the only bit we need, everything else is either ignored on
> HDMI or should be set to zero.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Is the assumption that intel_enable_ddi() will only ever be used by
the HDMI encore likely to hold true for ever? looks like a general
function that could be used by others to me. Also intel_disable_ddi()
read the register back, so it'd be unfair to only touch
intel_enable_ddi() if you want to do that.

I'd just stay on the safe side and retain the programming here.

-- 
Damien

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

* Re: [PATCH 07/10] drm/i915: completely rewrite the Haswell PLL handling code
  2012-10-10 14:22     ` Lespiau, Damien
@ 2012-10-10 14:52       ` Daniel Vetter
  0 siblings, 0 replies; 83+ messages in thread
From: Daniel Vetter @ 2012-10-10 14:52 UTC (permalink / raw)
  To: Lespiau, Damien; +Cc: intel-gfx, Paulo Zanoni

On Wed, Oct 10, 2012 at 03:22:01PM +0100, Lespiau, Damien wrote:
> On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> > +               val = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SCC;
> 
> We probably want a patch on top to fix the SCC typo (should be SSC,
> Spread Spectrum Clock).
> 
> There's also some fiddly bit with CPU Vs PCH SSC sources, but this can
> be a later addition.

Hm, I don't understand what PCH SSC resources we have on hsw (which are
not just vga encoder resources, since that's the only pch encoder left).

Two more things I've noticed while reading the patch:
- the simple refcounting seems to be good enough for now, but I guess for
  pll sharing we need a real struct intel_ddi_pll, like for the pch plls.
  But that's likely best done together with the pll readout code required
  for fastboot.

- When will the wrpll table die ... ;-)

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

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

* Re: [PATCH 08/10] drm/i915: don't rely on previous values set on DDI_BUF_CTL
  2012-10-10 14:27     ` Lespiau, Damien
@ 2012-10-10 14:56       ` Daniel Vetter
  2012-10-10 18:18         ` Daniel Vetter
  0 siblings, 1 reply; 83+ messages in thread
From: Daniel Vetter @ 2012-10-10 14:56 UTC (permalink / raw)
  To: Lespiau, Damien; +Cc: intel-gfx, Paulo Zanoni

On Wed, Oct 10, 2012 at 03:27:59PM +0100, Lespiau, Damien wrote:
> On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> >
> > Just set the only bit we need, everything else is either ignored on
> > HDMI or should be set to zero.
> >
> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Is the assumption that intel_enable_ddi() will only ever be used by
> the HDMI encore likely to hold true for ever? looks like a general
> function that could be used by others to me. Also intel_disable_ddi()
> read the register back, so it'd be unfair to only touch
> intel_enable_ddi() if you want to do that.
> 
> I'd just stay on the safe side and retain the programming here.

I'd prefer to go safe and do our own programming ;-) Imo it's better to
fully program a register than to rely on random garbage left behind by the
bios - usually that allows us to bring up hw a bit quicker, but in the end
results in some nasty bug reports once hw starts shipping. For the disable
side things are usually not that important, since we need to assume that
our own code (or our own hw state readout) set things up correctly.

Wrt the general usefullness of, I guess the dp patches will changed that.
I'll just merge this one here.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 08/10] drm/i915: don't rely on previous values set on DDI_BUF_CTL
  2012-10-10 14:56       ` Daniel Vetter
@ 2012-10-10 18:18         ` Daniel Vetter
  0 siblings, 0 replies; 83+ messages in thread
From: Daniel Vetter @ 2012-10-10 18:18 UTC (permalink / raw)
  To: Lespiau, Damien; +Cc: intel-gfx, Paulo Zanoni

On Wed, Oct 10, 2012 at 04:56:07PM +0200, Daniel Vetter wrote:
> On Wed, Oct 10, 2012 at 03:27:59PM +0100, Lespiau, Damien wrote:
> > On Fri, Oct 5, 2012 at 4:05 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> > > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > >
> > > Just set the only bit we need, everything else is either ignored on
> > > HDMI or should be set to zero.
> > >
> > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > 
> > Is the assumption that intel_enable_ddi() will only ever be used by
> > the HDMI encore likely to hold true for ever? looks like a general
> > function that could be used by others to me. Also intel_disable_ddi()
> > read the register back, so it'd be unfair to only touch
> > intel_enable_ddi() if you want to do that.
> > 
> > I'd just stay on the safe side and retain the programming here.
> 
> I'd prefer to go safe and do our own programming ;-) Imo it's better to
> fully program a register than to rely on random garbage left behind by the
> bios - usually that allows us to bring up hw a bit quicker, but in the end
> results in some nasty bug reports once hw starts shipping. For the disable
> side things are usually not that important, since we need to assume that
> our own code (or our own hw state readout) set things up correctly.
> 
> Wrt the general usefullness of, I guess the dp patches will changed that.
> I'll just merge this one here.

Ok, I've merged this series up to this patch. The last two patches are
pending an r-b from a volunteer ;-)

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

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

* Re: [PATCH 10/10] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set
  2012-10-05 15:06   ` [PATCH 10/10] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set Paulo Zanoni
@ 2012-10-10 21:57     ` Lespiau, Damien
  2012-10-10 22:47       ` Daniel Vetter
  0 siblings, 1 reply; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 21:57 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 4:06 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> So WARN in case they're not. It also does not make any sense to
> wait_for_vblank at this point.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

-- 
Damien

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

* Re: [PATCH 09/10] drm/i915: disable DDI_BUF_CTL at the correct time
  2012-10-05 15:06   ` [PATCH 09/10] drm/i915: disable DDI_BUF_CTL at the correct time Paulo Zanoni
@ 2012-10-10 22:30     ` Lespiau, Damien
  0 siblings, 0 replies; 83+ messages in thread
From: Lespiau, Damien @ 2012-10-10 22:30 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Fri, Oct 5, 2012 at 4:06 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> And also properly wait for its idle bit.
>
> You may notice that DDI_BUF_CTL is enabled in .enable but disabled in
> .post_disable instead of .disable. Yes, the mode set sequence is not
> exactly symmetrical, but let's assume the spec is correct unless we
> can prove it's wrong.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

-- 
Damien

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

* Re: [PATCH 10/10] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set
  2012-10-10 21:57     ` Lespiau, Damien
@ 2012-10-10 22:47       ` Daniel Vetter
  0 siblings, 0 replies; 83+ messages in thread
From: Daniel Vetter @ 2012-10-10 22:47 UTC (permalink / raw)
  To: Lespiau, Damien; +Cc: intel-gfx, Paulo Zanoni

On Wed, Oct 10, 2012 at 10:57:05PM +0100, Lespiau, Damien wrote:
> On Fri, Oct 5, 2012 at 4:06 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> > From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> >
> > So WARN in case they're not. It also does not make any sense to
> > wait_for_vblank at this point.
> >
> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

Last two patches are now also merged, thanks.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

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

Thread overview: 83+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-02 20:51 [PATCH 00/47] Haswell clocking and HDMI fixes, DP and eDP support Paulo Zanoni
2012-10-02 20:51 ` [PATCH 01/47] drm/i915: rewrite the LCPLL code Paulo Zanoni
2012-10-03 16:47   ` Lespiau, Damien
2012-10-02 20:51 ` [PATCH 02/47] drm/i915: enable and disable DDI_FUNC_CTL at the right time Paulo Zanoni
2012-10-03 17:44   ` Lespiau, Damien
2012-10-04 20:15     ` Paulo Zanoni
2012-10-02 20:51 ` [PATCH 03/47] drm/i915: enable and disable PIPE_CLK_SEL " Paulo Zanoni
2012-10-04 11:28   ` Lespiau, Damien
2012-10-02 20:51 ` [PATCH 04/47] drm/i915: completely rewrite the Haswell PLL handling code Paulo Zanoni
2012-10-02 20:51 ` [PATCH 05/47] drm/i915: don't rely on previous values set on DDI_BUF_CTL Paulo Zanoni
2012-10-02 20:51 ` [PATCH 06/47] drm/i915: disable DDI_BUF_CTL at the correct time Paulo Zanoni
2012-10-02 20:51 ` [PATCH 07/47] drm/i915: add haswell_crtc_mode_set Paulo Zanoni
2012-10-04 14:38   ` Lespiau, Damien
2012-10-02 20:51 ` [PATCH 08/47] drm/i915: add proper CPU/PCH checks to crtc_mode_set functions Paulo Zanoni
2012-10-02 20:51 ` [PATCH 09/47] drm/i915: add haswell_set_pipeconf Paulo Zanoni
2012-10-04 14:36   ` Lespiau, Damien
2012-10-02 20:51 ` [PATCH 10/47] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set Paulo Zanoni
2012-10-04 14:14   ` Lespiau, Damien
2012-10-05 12:53     ` Paulo Zanoni
2012-10-05 13:15       ` Lespiau, Damien
2012-10-02 20:51 ` [PATCH 11/47] drm/i915: add DP support to intel_ddi_enable_pipe_func Paulo Zanoni
2012-10-02 20:51 ` [PATCH 12/47] drm/i915: add intel_ddi_set_pipe_settings Paulo Zanoni
2012-10-02 20:51 ` [PATCH 13/47] drm/i915: add DP support to intel_ddi_pll_mode_set Paulo Zanoni
2012-10-02 20:51 ` [PATCH 14/47] drm/i915: add DP support to intel_ddi_disable_port Paulo Zanoni
2012-10-02 20:51 ` [PATCH 15/47] drm/i915: add DP support to intel_ddi_mode_set Paulo Zanoni
2012-10-02 20:51 ` [PATCH 16/47] drm/i915: add basic Haswell DP link train bits Paulo Zanoni
2012-10-02 20:51 ` [PATCH 17/47] drm/i915: use TU_SIZE macro at intel_dp_set_m_n Paulo Zanoni
2012-10-02 20:51 ` [PATCH 18/47] drm/i915: fix Haswell DP M/N registers Paulo Zanoni
2012-10-02 20:51 ` [PATCH 19/47] drm/i915: fix DP AUX register definitions on Haswell Paulo Zanoni
2012-10-02 20:51 ` [PATCH 20/47] drm/i915: add DP support to intel_ddi_get_encoder_port Paulo Zanoni
2012-10-02 20:51 ` [PATCH 21/47] drm/i915: add DP support to intel_ddi_get_hw_state Paulo Zanoni
2012-10-02 20:51 ` [PATCH 22/47] drm/i915: add DP support to intel_enable_ddi Paulo Zanoni
2012-10-02 20:51 ` [PATCH 23/47] drm/i915: implement Haswell DP link train sequence Paulo Zanoni
2012-10-02 20:51 ` [PATCH 24/47] drm/i915: set the correct function pointers for Haswell DP Paulo Zanoni
2012-10-02 20:52 ` [PATCH 25/47] drm/i915: add TRANSCODER_EDP Paulo Zanoni
2012-10-02 20:52 ` [PATCH 26/47] drm/i915: convert PIPE_CLK_SEL to transcoder Paulo Zanoni
2012-10-02 20:52 ` [PATCH 27/47] drm/i915: convert DDI_FUNC_CTL " Paulo Zanoni
2012-10-02 20:52 ` [PATCH 28/47] drm/i915: check TRANSCODER_EDP on intel_modeset_setup_hw_state Paulo Zanoni
2012-10-02 20:52 ` [PATCH 29/47] drm/i915: convert PIPECONF to use transcoder instead of pipe Paulo Zanoni
2012-10-02 20:52 ` [PATCH 30/47] drm/i915: convert PIPE_MSA_MISC to transcoder Paulo Zanoni
2012-10-02 20:52 ` [PATCH 31/47] drm/i915: convert CPU M/N timings " Paulo Zanoni
2012-10-02 20:52 ` [PATCH 32/47] drm/i915: convert pipe timing definitions " Paulo Zanoni
2012-10-02 20:52 ` [PATCH 33/47] drm/i915: implement workaround for VTOTAL when using TRANSCODER_EDP Paulo Zanoni
2012-10-02 20:52 ` [PATCH 34/47] drm/i915: select the correct pipe " Paulo Zanoni
2012-10-02 20:52 ` [PATCH 35/47] drm/i915: set the correct eDP aux channel clock divider on DDI Paulo Zanoni
2012-10-02 20:52 ` [PATCH 36/47] drm/i915: set/unset the DDI eDP backlight Paulo Zanoni
2012-10-02 20:52 ` [PATCH 37/47] drm/i915: turn the eDP DDI panel on/off Paulo Zanoni
2012-10-02 20:52 ` [PATCH 38/47] drm/i915: enable DDI eDP Paulo Zanoni
2012-10-02 20:52 ` [PATCH 39/47] drm/i915: simplify assignments inside intel_dp.c Paulo Zanoni
2012-10-02 20:52 ` [PATCH 40/47] drm/i915: add intel_dp_to_dev and intel_hdmi_to_dev Paulo Zanoni
2012-10-02 20:52 ` [PATCH 41/47] drm/i915: create intel_digital_port and use it Paulo Zanoni
2012-10-02 20:52 ` [PATCH 42/47] drm/i915: remove encoder args from intel_{dp, hdmi}_add_properties Paulo Zanoni
2012-10-02 20:52 ` [PATCH 43/47] drm/i915: split intel_hdmi_init into encoder and connector pieces Paulo Zanoni
2012-10-02 20:52 ` [PATCH 44/47] drm/i915: split intel_dp_init " Paulo Zanoni
2012-10-02 20:52 ` [PATCH 45/47] drm/i915: reset intel_encoder->type when DP or HDMI is detected Paulo Zanoni
2012-10-02 20:52 ` [PATCH 46/47] drm/i915: add intel_ddi_connector_get_hw_state Paulo Zanoni
2012-10-02 20:52 ` [PATCH 47/47] drm/i915: create the DDI encoder Paulo Zanoni
2012-10-05 15:05 ` [PATCH 00/10] Haswell pipe and clocking fixes Paulo Zanoni
2012-10-05 15:05   ` [PATCH 01/10] drm/i915: rewrite the LCPLL code Paulo Zanoni
2012-10-10 12:47     ` Lespiau, Damien
2012-10-10 12:53       ` Lespiau, Damien
2012-10-05 15:05   ` [PATCH 02/10] drm/i915: enable and disable DDI_FUNC_CTL at the right time Paulo Zanoni
2012-10-10 13:04     ` Lespiau, Damien
2012-10-05 15:05   ` [PATCH 03/10] drm/i915: enable and disable PIPE_CLK_SEL " Paulo Zanoni
2012-10-10 13:05     ` Lespiau, Damien
2012-10-05 15:05   ` [PATCH 04/10] drm/i915: add haswell_crtc_mode_set Paulo Zanoni
2012-10-10 13:07     ` Lespiau, Damien
2012-10-05 15:05   ` [PATCH 05/10] drm/i915: add proper CPU/PCH checks to crtc_mode_set functions Paulo Zanoni
2012-10-10 13:52     ` Lespiau, Damien
2012-10-05 15:05   ` [PATCH 06/10] drm/i915: add haswell_set_pipeconf Paulo Zanoni
2012-10-10 13:59     ` Lespiau, Damien
2012-10-05 15:05   ` [PATCH 07/10] drm/i915: completely rewrite the Haswell PLL handling code Paulo Zanoni
2012-10-10 14:22     ` Lespiau, Damien
2012-10-10 14:52       ` Daniel Vetter
2012-10-05 15:05   ` [PATCH 08/10] drm/i915: don't rely on previous values set on DDI_BUF_CTL Paulo Zanoni
2012-10-10 14:27     ` Lespiau, Damien
2012-10-10 14:56       ` Daniel Vetter
2012-10-10 18:18         ` Daniel Vetter
2012-10-05 15:06   ` [PATCH 09/10] drm/i915: disable DDI_BUF_CTL at the correct time Paulo Zanoni
2012-10-10 22:30     ` Lespiau, Damien
2012-10-05 15:06   ` [PATCH 10/10] drm/i915: pipe and planes should be disabled on haswell_crtc_mode_set Paulo Zanoni
2012-10-10 21:57     ` Lespiau, Damien
2012-10-10 22:47       ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.