Message ID | 1351101574-4386-1-git-send-email-przanoni@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Oct 24, 2012 at 6:59 PM, Paulo Zanoni <przanoni@gmail.com> wrote: > 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 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: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
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..18aa1b6 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,12 @@ 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); + + /* 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); } @@ -5361,6 +5376,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 +7917,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);