Commit a5c961d1 authored by Paulo Zanoni's avatar Paulo Zanoni Committed by Daniel Vetter

drm/i915: add TRANSCODER_EDP

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 output 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.

V2: Comment the haswell_crtc_off chunk, suggested by Damien Lespiau
and Daniel Vetter.

We currently need the haswell_crtc_off chunk 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 disabled 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 could get a "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's 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.
Signed-off-by: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: default avatarDamien Lespiau <damien.lespiau@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 83616634
...@@ -58,6 +58,14 @@ enum pipe { ...@@ -58,6 +58,14 @@ enum pipe {
}; };
#define pipe_name(p) ((p) + 'A') #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 { enum plane {
PLANE_A = 0, PLANE_A = 0,
PLANE_B, PLANE_B,
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#define _I915_REG_H_ #define _I915_REG_H_
#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) #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))) #define _PORT(port, a, b) ((a) + (port)*((b)-(a)))
......
...@@ -937,6 +937,15 @@ intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc, ...@@ -937,6 +937,15 @@ intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
return true; 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) static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -3482,6 +3491,12 @@ static void ironlake_crtc_off(struct drm_crtc *crtc) ...@@ -3482,6 +3491,12 @@ static void ironlake_crtc_off(struct drm_crtc *crtc)
static void haswell_crtc_off(struct drm_crtc *crtc) static void haswell_crtc_off(struct drm_crtc *crtc)
{ {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
/* Stop saying we're using TRANSCODER_EDP because some other CRTC might
* start using it. */
intel_crtc->cpu_transcoder = intel_crtc->pipe;
intel_ddi_put_crtc_pll(crtc); intel_ddi_put_crtc_pll(crtc);
} }
...@@ -5358,6 +5373,11 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5358,6 +5373,11 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
num_connectors++; 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. */ /* We are not sure yet this won't happen. */
WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n", WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n",
INTEL_PCH_TYPE(dev)); INTEL_PCH_TYPE(dev));
...@@ -7894,6 +7914,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) ...@@ -7894,6 +7914,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
/* Swap pipes & planes for FBC on pre-965 */ /* Swap pipes & planes for FBC on pre-965 */
intel_crtc->pipe = pipe; intel_crtc->pipe = pipe;
intel_crtc->plane = pipe; intel_crtc->plane = pipe;
intel_crtc->cpu_transcoder = pipe;
if (IS_MOBILE(dev) && IS_GEN3(dev)) { if (IS_MOBILE(dev) && IS_GEN3(dev)) {
DRM_DEBUG_KMS("swapping pipes & planes for FBC\n"); DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
intel_crtc->plane = !pipe; intel_crtc->plane = !pipe;
......
...@@ -195,6 +195,7 @@ struct intel_crtc { ...@@ -195,6 +195,7 @@ struct intel_crtc {
struct drm_crtc base; struct drm_crtc base;
enum pipe pipe; enum pipe pipe;
enum plane plane; enum plane plane;
enum transcoder cpu_transcoder;
u8 lut_r[256], lut_g[256], lut_b[256]; u8 lut_r[256], lut_g[256], lut_b[256];
/* /*
* Whether the crtc and the connected output pipeline is active. Implies * Whether the crtc and the connected output pipeline is active. Implies
...@@ -505,6 +506,9 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, ...@@ -505,6 +506,9 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
struct drm_crtc *crtc); struct drm_crtc *crtc);
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
struct drm_file *file_priv); 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_vblank(struct drm_device *dev, int pipe);
extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe); extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment