[Intel-gfx] [PATCH 13/13] drm/i915: clear up the fdi/dp set_m_n confusion

Daniel Vetter daniel at ffwll.ch
Wed Mar 27 01:14:55 CET 2013


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 <daniel.vetter at ffwll.ch>

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



More information about the Intel-gfx mailing list