diff mbox

[05/18] drm/i915: add TRANSCODER_EDP

Message ID 1351024208-3489-6-git-send-email-przanoni@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paulo Zanoni Oct. 23, 2012, 8:29 p.m. UTC
From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Before Haswell we used to have the CPU pipes and the PCH transcoders.
We had the same amount of pipes and transcoders, and there was a 1:1
mapping between them. After Haswell what we used to call CPU pipe was
split into CPU pipe and CPU transcoder. So now we have 3 CPU pipes (A,
B and C), 4 CPU transcoders (A, B, C and EDP) and 1 PCH transcoder
(only used for VGA).

For all the outputs except for EDP we have an 1:1 mapping on the CPU
pipes and CPU transcoders, so if you're using CPU pipe A you have to
use CPU transcoder A. When have an eDP ouput you have to use
transcoder EDP and you can attach this CPU transcoder to any of the 3
CPU pipes. When using VGA you need to select a pair of matching CPU
pipes/transcoders (A/A, B/B, C/C) and you also need to enable/use the
PCH transcoder.

For now we're just creating the cpu_transcoder definitions and setting
cpu_transcoder to TRANSCODER_EDP on DDI eDP code, but none of the
registers was ported to use transcoder instead of pipe. The goal is to
keep the code backwards-compatible since on all cases except when
using eDP we must have pipe == cpu_transcoder.

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 | 18 ++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  4 ++++
 4 files changed, 31 insertions(+)

Comments

Lespiau, Damien Oct. 24, 2012, 2:50 p.m. UTC | #1
On Tue, Oct 23, 2012 at 9:29 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>  static void haswell_crtc_off(struct drm_crtc *crtc)
>  {
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +
> +       intel_crtc->cpu_transcoder = intel_crtc->pipe;
>         intel_ddi_put_crtc_pll(crtc);
>  }
>

I can't find the reason why you would set the cpu_transcoder in the
off() function, would you mind explaining why? (or maybe the clue is
in a later patch, which might mean this hunk belongs to a later patch
as well).
Paulo Zanoni Oct. 24, 2012, 4:33 p.m. UTC | #2
Hi

2012/10/24 Lespiau, Damien <damien.lespiau@intel.com>:
> On Tue, Oct 23, 2012 at 9:29 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>>  static void haswell_crtc_off(struct drm_crtc *crtc)
>>  {
>> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>> +
>> +       intel_crtc->cpu_transcoder = intel_crtc->pipe;
>>         intel_ddi_put_crtc_pll(crtc);
>>  }
>>
>
> I can't find the reason why you would set the cpu_transcoder in the
> off() function, would you mind explaining why? (or maybe the clue is
> in a later patch, which might mean this hunk belongs to a later patch
> as well).

The very first version I wrote for this patch did not have this line
too, until I discovered I needed it. Fasten your seatbelts...

Because TRANSCODER_EDP can be used by any CRTC, so when you stop using
it you have to stop saying you're using it, otherwise you may have at
some point 2 crtcs claiming they're using TRANSCODER_EDP (a disable
crtc and an enabled one), then the HW state readout code will get
completely confused.

In other words:

Imagine the following case:
- xrandr --output eDP1 --auto --crtc 0
- xrandr --output eDP1 --off
- xrandr --output eDP1 --auto --crtc 2

After the last command you will get a nice "pipe A assertion failure
(expected off, current on)" because crtc 0 still claims it's using
transcoder_edp, so the hw state readout function will read it (through
pipeconf) and expect it to be off, when it is actually on because it's
being used by crtc 2.

So when we make "intel_crtc->cpu_transcoder = intel_crtc->pipe" we
make sure we're pointing to our own original crtc which is certainly
not used by any other CRTC.

>
> --
> Damien
Daniel Vetter Oct. 24, 2012, 4:43 p.m. UTC | #3
On Wed, Oct 24, 2012 at 6:33 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> 2012/10/24 Lespiau, Damien <damien.lespiau@intel.com>:
>> On Tue, Oct 23, 2012 at 9:29 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>>>  static void haswell_crtc_off(struct drm_crtc *crtc)
>>>  {
>>> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>>> +
>>> +       intel_crtc->cpu_transcoder = intel_crtc->pipe;
>>>         intel_ddi_put_crtc_pll(crtc);
>>>  }
>>>
>>
>> I can't find the reason why you would set the cpu_transcoder in the
>> off() function, would you mind explaining why? (or maybe the clue is
>> in a later patch, which might mean this hunk belongs to a later patch
>> as well).
>
> The very first version I wrote for this patch did not have this line
> too, until I discovered I needed it. Fasten your seatbelts...
>
> Because TRANSCODER_EDP can be used by any CRTC, so when you stop using
> it you have to stop saying you're using it, otherwise you may have at
> some point 2 crtcs claiming they're using TRANSCODER_EDP (a disable
> crtc and an enabled one), then the HW state readout code will get
> completely confused.
>
> In other words:
>
> Imagine the following case:
> - xrandr --output eDP1 --auto --crtc 0
> - xrandr --output eDP1 --off
> - xrandr --output eDP1 --auto --crtc 2
>
> After the last command you will get a nice "pipe A assertion failure
> (expected off, current on)" because crtc 0 still claims it's using
> transcoder_edp, so the hw state readout function will read it (through
> pipeconf) and expect it to be off, when it is actually on because it's
> being used by crtc 2.
>
> So when we make "intel_crtc->cpu_transcoder = intel_crtc->pipe" we
> make sure we're pointing to our own original crtc which is certainly
> not used by any other CRTC.

This needs to be in a comment somewhere. I think the long version here
in the commit message, and a short one in the code.
-Daniel
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 987af6f..2fcf284 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 c7c4b96..598f83a 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 67c9472..214ff5a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -937,6 +937,15 @@  intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
 	return true;
 }
 
+enum transcoder intel_pipe_to_cpu_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->cpu_transcoder;
+}
+
 static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3485,6 +3494,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->cpu_transcoder = intel_crtc->pipe;
 	intel_ddi_put_crtc_pll(crtc);
 }
 
@@ -5361,6 +5373,11 @@  static int haswell_crtc_mode_set(struct drm_crtc *crtc,
 		num_connectors++;
 	}
 
+	if (is_cpu_edp)
+		intel_crtc->cpu_transcoder = TRANSCODER_EDP;
+	else
+		intel_crtc->cpu_transcoder = pipe;
+
 	/* We are not sure yet this won't happen. */
 	WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n",
 	     INTEL_PCH_TYPE(dev));
@@ -7897,6 +7914,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->cpu_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 c2e439b..14484ef 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -195,6 +195,7 @@  struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
 	enum plane plane;
+	enum transcoder cpu_transcoder;
 	u8 lut_r[256], lut_g[256], lut_b[256];
 	/*
 	 * Whether the crtc and the connected output pipeline is active. Implies
@@ -506,6 +507,9 @@  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
+intel_pipe_to_cpu_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);