On Wed, Mar 27, 2013 at 12:45:02AM +0100, Daniel Vetter wrote:
> There's a rather decent confusion going on around transcoder m_n
> values. So let's clarify:
> - All dp encoders need this, either on the pch transcoder if it's a
>   pch port, or on the cpu transcoder/pipe if it's a cpu port.
> - fdi links need to have the right m_n values for the fdi link set in
>   the cpu transcoder.
> 
> To handle the pch vs transcoder stuff a bit better, extract transcoder
> set_m_n helpers. To make them simpler, set intel_crtc->cpu_transcoder
> als in ironlake_crtc_mode_set, so that gen5+ (where the cpu m_n
> registers are all at the same offset) can use it.
> 
> Haswell modeset is decently confused about dp vs. edp vs. fdi. dp vs.
> edp works exactly the same as dp (since there's no pch dp any more),
> so use that as a check. And only set up the fdi m_n values if we
> really have a pch encoder present (which means we have a VGA encoder).
> 
> On ilk+ we've called ironlake_set_m_n both for cpu_edp and for pch
> encoders. Now that dp_set_m_n handles all dp links (thanks to the
> pch encoder check), we can ditch the cpu_edp stuff from the
> fdi_set_m_n function.
> 
> Since the dp_m_n values are not readily available, we need to
> carefully coax the edp values out of the encoder. Hence we can't (yet)
> kill this superflous complexity.
> 
> v2: Rebase on top of the ivb fdi B/C check patch - we need to properly
> clear intel_crtc->fdi_lane, otherwise those checks will misfire.
> 
> v3: Rebased on top of a s/IS_HASWELL/HAS_DDI/ patch from Paulo Zanoni.
> 
> Signed-off-by: Daniel Vetter <[email protected]>

Oops, that patch is already part of the next pile of pipe_config stuff.
Please disregard (for now ...).
-Daniel
> ---
>  drivers/gpu/drm/i915/intel_display.c | 86 
> +++++++++++++++++++++++-------------
>  drivers/gpu/drm/i915/intel_dp.c      | 30 ++-----------
>  drivers/gpu/drm/i915/intel_drv.h     |  8 ++++
>  3 files changed, 67 insertions(+), 57 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c 
> b/drivers/gpu/drm/i915/intel_display.c
> index 8ab7520..b076665 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5297,15 +5297,47 @@ int ironlake_get_lanes_required(int target_clock, int 
> link_bw, int bpp)
>       return bps / (link_bw * 8) + 1;
>  }
>  
> -static void ironlake_set_m_n(struct drm_crtc *crtc)
> +void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
> +                               struct intel_link_m_n *m_n)
>  {
> -     struct drm_device *dev = crtc->dev;
> +     struct drm_device *dev = crtc->base.dev;
> +     struct drm_i915_private *dev_priv = dev->dev_private;
> +     int pipe = crtc->pipe;
> +
> +     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);
> +}
> +
> +void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
> +                               struct intel_link_m_n *m_n)
> +{
> +     struct drm_device *dev = crtc->base.dev;
>       struct drm_i915_private *dev_priv = dev->dev_private;
> +     int pipe = crtc->pipe;
> +     enum transcoder transcoder = crtc->cpu_transcoder;
> +
> +     if (INTEL_INFO(dev)->gen >= 5) {
> +             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 {
> +             I915_WRITE(PIPE_GMCH_DATA_M(pipe), 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);
> +     }
> +}
> +
> +static void ironlake_fdi_set_m_n(struct drm_crtc *crtc)
> +{
> +     struct drm_device *dev = crtc->dev;
>       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>       struct drm_display_mode *adjusted_mode =
>               &intel_crtc->config.adjusted_mode;
>       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
> -     enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
>       struct intel_encoder *intel_encoder, *edp_encoder = NULL;
>       struct intel_link_m_n m_n = {0};
>       int target_clock, lane, link_bw;
> @@ -5325,22 +5357,14 @@ static void ironlake_set_m_n(struct drm_crtc *crtc)
>               }
>       }
>  
> -     /* FDI link */
> -     lane = 0;
> -     /* CPU eDP doesn't require FDI link, so just set DP M/N
> -        according to current link config */
> -     if (is_cpu_edp) {
> -             intel_edp_link_config(edp_encoder, &lane, &link_bw);
> -     } else {
> -             /* FDI is a binary signal running at ~2.7GHz, encoding
> -              * each output octet as 10 bits. The actual frequency
> -              * is stored as a divider into a 100MHz clock, and the
> -              * mode pixel clock is stored in units of 1KHz.
> -              * Hence the bw of each lane in terms of the mode signal
> -              * is:
> -              */
> -             link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
> -     }
> +     /* FDI is a binary signal running at ~2.7GHz, encoding
> +      * each output octet as 10 bits. The actual frequency
> +      * is stored as a divider into a 100MHz clock, and the
> +      * mode pixel clock is stored in units of 1KHz.
> +      * Hence the bw of each lane in terms of the mode signal
> +      * is:
> +      */
> +     link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
>  
>       /* [e]DP over FDI requires target mode clock instead of link clock. */
>       if (edp_encoder)
> @@ -5350,9 +5374,8 @@ static void ironlake_set_m_n(struct drm_crtc *crtc)
>       else
>               target_clock = adjusted_mode->clock;
>  
> -     if (!lane)
> -             lane = ironlake_get_lanes_required(target_clock, link_bw,
> -                                                intel_crtc->config.pipe_bpp);
> +     lane = ironlake_get_lanes_required(target_clock, link_bw,
> +                                        intel_crtc->config.pipe_bpp);
>  
>       intel_crtc->fdi_lanes = lane;
>  
> @@ -5361,10 +5384,7 @@ static void ironlake_set_m_n(struct drm_crtc *crtc)
>       intel_link_compute_m_n(intel_crtc->config.pipe_bpp, lane, target_clock,
>                              link_bw, &m_n);
>  
> -     I915_WRITE(PIPE_DATA_M1(cpu_transcoder), TU_SIZE(m_n.tu) | m_n.gmch_m);
> -     I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n);
> -     I915_WRITE(PIPE_LINK_M1(cpu_transcoder), m_n.link_m);
> -     I915_WRITE(PIPE_LINK_N1(cpu_transcoder), m_n.link_n);
> +     intel_cpu_transcoder_set_m_n(intel_crtc, &m_n);
>  }
>  
>  static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
> @@ -5511,6 +5531,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
>       WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
>            "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
>  
> +     intel_crtc->cpu_transcoder = pipe;
> +
>       ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
>                                    &has_reduced_clock, &reduced_clock);
>       if (!ok) {
> @@ -5549,7 +5571,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
>       } else
>               intel_put_pch_pll(intel_crtc);
>  
> -     if (is_dp && !is_cpu_edp)
> +     if (is_dp)
>               intel_dp_set_m_n(crtc, mode, adjusted_mode);
>  
>       for_each_encoder_on_crtc(dev, crtc, encoder)
> @@ -5585,7 +5607,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
>  
>       /* Note, this also computes intel_crtc->fdi_lanes which is used below in
>        * ironlake_check_fdi_lanes. */
> -     ironlake_set_m_n(crtc);
> +     intel_crtc->fdi_lanes = 0;
> +     if (intel_crtc->config.has_pch_encoder)
> +             ironlake_fdi_set_m_n(crtc);
>  
>       fdi_config_ok = ironlake_check_fdi_lanes(intel_crtc);
>  
> @@ -5697,15 +5721,15 @@ static int haswell_crtc_mode_set(struct drm_crtc 
> *crtc,
>       DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
>       drm_mode_debug_printmodeline(mode);
>  
> -     if (is_dp && !is_cpu_edp)
> +     if (is_dp)
>               intel_dp_set_m_n(crtc, mode, adjusted_mode);
>  
>       intel_crtc->lowfreq_avail = false;
>  
>       intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
>  
> -     if (!is_dp || is_cpu_edp)
> -             ironlake_set_m_n(crtc);
> +     if (intel_crtc->config.has_pch_encoder)
> +             ironlake_fdi_set_m_n(crtc);
>  
>       haswell_set_pipeconf(crtc, adjusted_mode, dither);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 251aa6b..6b8a279 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -766,12 +766,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct 
> drm_display_mode *mode,
>       struct drm_device *dev = crtc->dev;
>       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;
>       struct intel_link_m_n m_n;
> -     int pipe = intel_crtc->pipe;
> -     enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
>       int target_clock;
>  
>       /*
> @@ -805,29 +802,10 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct 
> drm_display_mode *mode,
>       intel_link_compute_m_n(intel_crtc->config.pipe_bpp, lane_count,
>                              target_clock, adjusted_mode->clock, &m_n);
>  
> -     if (HAS_DDI(dev)) {
> -             I915_WRITE(PIPE_DATA_M1(cpu_transcoder),
> -                        TU_SIZE(m_n.tu) | m_n.gmch_m);
> -             I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n);
> -             I915_WRITE(PIPE_LINK_M1(cpu_transcoder), m_n.link_m);
> -             I915_WRITE(PIPE_LINK_N1(cpu_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);
> -             I915_WRITE(TRANSDPLINK_M1(pipe), m_n.link_m);
> -             I915_WRITE(TRANSDPLINK_N1(pipe), m_n.link_n);
> -     } else if (IS_VALLEYVIEW(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 {
> -             I915_WRITE(PIPE_GMCH_DATA_M(pipe),
> -                        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);
> -     }
> +     if (intel_crtc->config.has_pch_encoder)
> +             intel_pch_transcoder_set_m_n(intel_crtc, &m_n);
> +     else
> +             intel_cpu_transcoder_set_m_n(intel_crtc, &m_n);
>  }
>  
>  void intel_dp_init_link_config(struct intel_dp *intel_dp)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> b/drivers/gpu/drm/i915/intel_drv.h
> index 5c7b04b..3a9b7be 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -192,8 +192,12 @@ struct intel_crtc_config {
>        */
>       bool limited_color_range;
>  
> +     /* DP has a bunch of special case unfortunately, so mark the pipe
> +      * accordingly. */
> +     bool has_dp_encoder;
>       bool dither;
>       int pipe_bpp;
> +     struct intel_link_m_n dp_m_n;
>  
>       /* Used by SDVO (and if we ever fix it, HDMI). */
>       unsigned pixel_multiplier;
> @@ -641,6 +645,10 @@ extern void intel_init_clock_gating(struct drm_device 
> *dev);
>  extern void intel_write_eld(struct drm_encoder *encoder,
>                           struct drm_display_mode *mode);
>  extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
> +extern void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
> +                                      struct intel_link_m_n *m_n);
> +extern void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
> +                                      struct intel_link_m_n *m_n);
>  extern void intel_prepare_ddi(struct drm_device *dev);
>  extern void hsw_fdi_link_train(struct drm_crtc *crtc);
>  extern void intel_ddi_init(struct drm_device *dev, enum port port);
> -- 
> 1.7.11.7
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to