Commit 6cf86a5e authored by Daniel Vetter's avatar Daniel Vetter

drm/i915: clear up the fdi/dp set_m_n confusion

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.

v4: Drop the addition of has_dp_encoder, it's in the wrong patch (Jesse).
Reviewed-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent ecb135a1
...@@ -5373,15 +5373,47 @@ int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp) ...@@ -5373,15 +5373,47 @@ int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp)
return bps / (link_bw * 8) + 1; 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; 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 intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_display_mode *adjusted_mode = struct drm_display_mode *adjusted_mode =
&intel_crtc->config.adjusted_mode; &intel_crtc->config.adjusted_mode;
struct drm_display_mode *mode = &intel_crtc->config.requested_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_encoder *intel_encoder, *edp_encoder = NULL;
struct intel_link_m_n m_n = {0}; struct intel_link_m_n m_n = {0};
int target_clock, lane, link_bw; int target_clock, lane, link_bw;
...@@ -5401,22 +5433,14 @@ static void ironlake_set_m_n(struct drm_crtc *crtc) ...@@ -5401,22 +5433,14 @@ static void ironlake_set_m_n(struct drm_crtc *crtc)
} }
} }
/* FDI link */ /* FDI is a binary signal running at ~2.7GHz, encoding
lane = 0; * each output octet as 10 bits. The actual frequency
/* CPU eDP doesn't require FDI link, so just set DP M/N * is stored as a divider into a 100MHz clock, and the
according to current link config */ * mode pixel clock is stored in units of 1KHz.
if (is_cpu_edp) { * Hence the bw of each lane in terms of the mode signal
intel_edp_link_config(edp_encoder, &lane, &link_bw); * is:
} else { */
/* FDI is a binary signal running at ~2.7GHz, encoding link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
* 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. */ /* [e]DP over FDI requires target mode clock instead of link clock. */
if (edp_encoder) if (edp_encoder)
...@@ -5426,9 +5450,8 @@ static void ironlake_set_m_n(struct drm_crtc *crtc) ...@@ -5426,9 +5450,8 @@ static void ironlake_set_m_n(struct drm_crtc *crtc)
else else
target_clock = adjusted_mode->clock; target_clock = adjusted_mode->clock;
if (!lane) lane = ironlake_get_lanes_required(target_clock, link_bw,
lane = ironlake_get_lanes_required(target_clock, link_bw, intel_crtc->config.pipe_bpp);
intel_crtc->config.pipe_bpp);
intel_crtc->fdi_lanes = lane; intel_crtc->fdi_lanes = lane;
...@@ -5437,10 +5460,7 @@ static void ironlake_set_m_n(struct drm_crtc *crtc) ...@@ -5437,10 +5460,7 @@ static void ironlake_set_m_n(struct drm_crtc *crtc)
intel_link_compute_m_n(intel_crtc->config.pipe_bpp, lane, target_clock, intel_link_compute_m_n(intel_crtc->config.pipe_bpp, lane, target_clock,
link_bw, &m_n); link_bw, &m_n);
I915_WRITE(PIPE_DATA_M1(cpu_transcoder), TU_SIZE(m_n.tu) | m_n.gmch_m); intel_cpu_transcoder_set_m_n(intel_crtc, &m_n);
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);
} }
static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
...@@ -5587,6 +5607,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5587,6 +5607,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)), WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
"Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev)); "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
intel_crtc->cpu_transcoder = pipe;
ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock, ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
&has_reduced_clock, &reduced_clock); &has_reduced_clock, &reduced_clock);
if (!ok) { if (!ok) {
...@@ -5625,7 +5647,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5625,7 +5647,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
} else } else
intel_put_pch_pll(intel_crtc); intel_put_pch_pll(intel_crtc);
if (is_dp && !is_cpu_edp) if (is_dp)
intel_dp_set_m_n(crtc, mode, adjusted_mode); intel_dp_set_m_n(crtc, mode, adjusted_mode);
for_each_encoder_on_crtc(dev, crtc, encoder) for_each_encoder_on_crtc(dev, crtc, encoder)
...@@ -5661,7 +5683,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5661,7 +5683,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
/* Note, this also computes intel_crtc->fdi_lanes which is used below in /* Note, this also computes intel_crtc->fdi_lanes which is used below in
* ironlake_check_fdi_lanes. */ * 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); fdi_config_ok = ironlake_check_fdi_lanes(intel_crtc);
...@@ -5773,15 +5797,15 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc, ...@@ -5773,15 +5797,15 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe); DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
drm_mode_debug_printmodeline(mode); drm_mode_debug_printmodeline(mode);
if (is_dp && !is_cpu_edp) if (is_dp)
intel_dp_set_m_n(crtc, mode, adjusted_mode); intel_dp_set_m_n(crtc, mode, adjusted_mode);
intel_crtc->lowfreq_avail = false; intel_crtc->lowfreq_avail = false;
intel_set_pipe_timings(intel_crtc, mode, adjusted_mode); intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
if (!is_dp || is_cpu_edp) if (intel_crtc->config.has_pch_encoder)
ironlake_set_m_n(crtc); ironlake_fdi_set_m_n(crtc);
haswell_set_pipeconf(crtc, adjusted_mode, dither); haswell_set_pipeconf(crtc, adjusted_mode, dither);
......
...@@ -775,12 +775,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, ...@@ -775,12 +775,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_dp *intel_dp; struct intel_dp *intel_dp;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int lane_count = 4; int lane_count = 4;
struct intel_link_m_n m_n; struct intel_link_m_n m_n;
int pipe = intel_crtc->pipe;
enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
int target_clock; int target_clock;
/* /*
...@@ -814,29 +811,10 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, ...@@ -814,29 +811,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, intel_link_compute_m_n(intel_crtc->config.pipe_bpp, lane_count,
target_clock, adjusted_mode->clock, &m_n); target_clock, adjusted_mode->clock, &m_n);
if (HAS_DDI(dev)) { if (intel_crtc->config.has_pch_encoder)
I915_WRITE(PIPE_DATA_M1(cpu_transcoder), intel_pch_transcoder_set_m_n(intel_crtc, &m_n);
TU_SIZE(m_n.tu) | m_n.gmch_m); else
I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n); intel_cpu_transcoder_set_m_n(intel_crtc, &m_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);
}
} }
void intel_dp_init_link_config(struct intel_dp *intel_dp) void intel_dp_init_link_config(struct intel_dp *intel_dp)
......
...@@ -192,6 +192,7 @@ struct intel_crtc_config { ...@@ -192,6 +192,7 @@ struct intel_crtc_config {
bool dither; bool dither;
int pipe_bpp; int pipe_bpp;
struct intel_link_m_n dp_m_n;
/* Used by SDVO (and if we ever fix it, HDMI). */ /* Used by SDVO (and if we ever fix it, HDMI). */
unsigned pixel_multiplier; unsigned pixel_multiplier;
...@@ -640,6 +641,10 @@ extern void intel_init_clock_gating(struct drm_device *dev); ...@@ -640,6 +641,10 @@ extern void intel_init_clock_gating(struct drm_device *dev);
extern void intel_write_eld(struct drm_encoder *encoder, extern void intel_write_eld(struct drm_encoder *encoder,
struct drm_display_mode *mode); struct drm_display_mode *mode);
extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe); 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 intel_prepare_ddi(struct drm_device *dev);
extern void hsw_fdi_link_train(struct drm_crtc *crtc); extern void hsw_fdi_link_train(struct drm_crtc *crtc);
extern void intel_ddi_init(struct drm_device *dev, enum port port); extern void intel_ddi_init(struct drm_device *dev, enum port port);
......
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