From 5fcece80ecdac932a0acb71e3a239c39dd4af20f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 27 May 2015 15:03:42 +0300 Subject: drm/i915: group all hotplug related fields into a new struct in dev_priv There are plenty of hotplug related fields in struct drm_i915_private scattered all around. Group them under one hotplug struct. Clean up naming while at it. No functional changes. Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index cacb07b7a8f1..62a7c7f2b5d4 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2832,7 +2832,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) goto err; intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; - dev_priv->hpd_irq_port[port] = intel_dig_port; + dev_priv->hotplug.irq_port[port] = intel_dig_port; } /* In theory we don't need the encoder->type check, but leave it just in -- cgit v1.2.3-70-g09d2 From d66716200a8e8362599ce939df40821bb960e866 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 27 May 2015 15:03:44 +0300 Subject: drm/i915: remove useless DP and DDI encoder ->hot_plug hooks The hotplug callbacks for DP and DDI effectively did nothing. Remove them. Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 15 --------------- drivers/gpu/drm/i915/intel_dp.c | 7 ------- 2 files changed, 22 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 62a7c7f2b5d4..54b60a97ef2d 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2618,20 +2618,6 @@ void intel_ddi_fdi_disable(struct drm_crtc *crtc) I915_WRITE(_FDI_RXA_CTL, val); } -static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) -{ - struct intel_digital_port *intel_dig_port = enc_to_dig_port(&intel_encoder->base); - int type = intel_dig_port->base.type; - - if (type != INTEL_OUTPUT_DISPLAYPORT && - type != INTEL_OUTPUT_EDP && - type != INTEL_OUTPUT_UNKNOWN) { - return; - } - - intel_dp_hot_plug(intel_encoder); -} - void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { @@ -2825,7 +2811,6 @@ void intel_ddi_init(struct drm_device *dev, enum port port) intel_encoder->type = INTEL_OUTPUT_UNKNOWN; intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = 0; - intel_encoder->hot_plug = intel_ddi_hot_plug; if (init_dp) { if (!intel_ddi_init_dp_connector(intel_dig_port)) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 61c8d28deabe..823a1b31177c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4920,12 +4920,6 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = { .destroy = intel_dp_encoder_destroy, }; -void -intel_dp_hot_plug(struct intel_encoder *intel_encoder) -{ - return; -} - enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) { @@ -5937,7 +5931,6 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); } intel_encoder->cloneable = 0; - intel_encoder->hot_plug = intel_dp_hot_plug; intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; dev_priv->hotplug.irq_port[port] = intel_dig_port; -- cgit v1.2.3-70-g09d2 From 6cf75178deacd87af12a657d914e6bbca806b5ba Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 7 May 2015 18:38:38 +0100 Subject: drm/i915/skl: Make sure to break when not finding suitable PLL dividers Right now, when finishing the cycle with odd dividers without finding a suitable candidate, we end up in an infinite loop. Make sure to break in that case. Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 54b60a97ef2d..233467f40a4a 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1184,6 +1184,10 @@ found: } if (min_dco_index > 2 && dco_count == 2) { + /* oh well, we tried... */ + if (retry_with_odd) + break; + retry_with_odd = true; dco_count = 0; } -- cgit v1.2.3-70-g09d2 From 19cdc0e6cdfc29e3ddee1fe56c3bcdfe25f6a916 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 7 May 2015 18:38:39 +0100 Subject: drm/i915/skl: Display the WRPLL frequency we couldn't accomodate when failing This helps debugging. Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 233467f40a4a..c1abe6efff9d 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1194,7 +1194,8 @@ found: } if (min_dco_index > 2) { - WARN(1, "No valid values found for the given pixel clock\n"); + WARN(1, "No valid parameters found for pixel clock: %dHz\n", + clock); } else { wrpll_params->central_freq = dco_central_freq[min_dco_index]; -- cgit v1.2.3-70-g09d2 From 318bd821d65d37fb12c5673607e2b013f7a86a01 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 7 May 2015 18:38:40 +0100 Subject: drm/i915/skl: Propagate the error if we fail to find a suitable DPLL divider At the moment, even if we fail to find a suitable divider, we'll still try to set the mode with bogus parameters. Just fail the modeset if we can't generate the frequency. Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index c1abe6efff9d..f10f55690749 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1115,7 +1115,7 @@ struct skl_wrpll_params { uint32_t central_freq; }; -static void +static bool skl_ddi_calculate_wrpll(int clock /* in Hz */, struct skl_wrpll_params *wrpll_params) { @@ -1196,6 +1196,7 @@ found: if (min_dco_index > 2) { WARN(1, "No valid parameters found for pixel clock: %dHz\n", clock); + return false; } else { wrpll_params->central_freq = dco_central_freq[min_dco_index]; @@ -1262,6 +1263,8 @@ found: wrpll_params->dco_integer * MHz(1)) * 0x8000), MHz(1)); } + + return true; } @@ -1286,7 +1289,8 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); - skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params); + if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params)) + return false; cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE | DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) | -- cgit v1.2.3-70-g09d2 From 9c2367538de381435503425c22c4f192c72e282e Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 7 May 2015 18:38:41 +0100 Subject: drm/i915/skl: Use a more idomatic early return We can coalesce the WARN() condition with the WARN() itself and, as we are returning early, we can de-intent the rest of the function. Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 121 +++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 62 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index f10f55690749..c547f03904bc 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1193,76 +1193,73 @@ found: } } - if (min_dco_index > 2) { - WARN(1, "No valid parameters found for pixel clock: %dHz\n", - clock); + if (WARN(min_dco_index > 2, + "No valid parameters found for pixel clock: %dHz\n", clock)) return false; - } else { - wrpll_params->central_freq = dco_central_freq[min_dco_index]; - switch (dco_central_freq[min_dco_index]) { - case 9600000000ULL: - wrpll_params->central_freq = 0; - break; - case 9000000000ULL: - wrpll_params->central_freq = 1; - break; - case 8400000000ULL: - wrpll_params->central_freq = 3; - } + wrpll_params->central_freq = dco_central_freq[min_dco_index]; - switch (candidate_p0[min_dco_index]) { - case 1: - wrpll_params->pdiv = 0; - break; - case 2: - wrpll_params->pdiv = 1; - break; - case 3: - wrpll_params->pdiv = 2; - break; - case 7: - wrpll_params->pdiv = 4; - break; - default: - WARN(1, "Incorrect PDiv\n"); - } + switch (dco_central_freq[min_dco_index]) { + case 9600000000ULL: + wrpll_params->central_freq = 0; + break; + case 9000000000ULL: + wrpll_params->central_freq = 1; + break; + case 8400000000ULL: + wrpll_params->central_freq = 3; + } - switch (candidate_p2[min_dco_index]) { - case 5: - wrpll_params->kdiv = 0; - break; - case 2: - wrpll_params->kdiv = 1; - break; - case 3: - wrpll_params->kdiv = 2; - break; - case 1: - wrpll_params->kdiv = 3; - break; - default: - WARN(1, "Incorrect KDiv\n"); - } + switch (candidate_p0[min_dco_index]) { + case 1: + wrpll_params->pdiv = 0; + break; + case 2: + wrpll_params->pdiv = 1; + break; + case 3: + wrpll_params->pdiv = 2; + break; + case 7: + wrpll_params->pdiv = 4; + break; + default: + WARN(1, "Incorrect PDiv\n"); + } - wrpll_params->qdiv_ratio = candidate_p1[min_dco_index]; - wrpll_params->qdiv_mode = - (wrpll_params->qdiv_ratio == 1) ? 0 : 1; + switch (candidate_p2[min_dco_index]) { + case 5: + wrpll_params->kdiv = 0; + break; + case 2: + wrpll_params->kdiv = 1; + break; + case 3: + wrpll_params->kdiv = 2; + break; + case 1: + wrpll_params->kdiv = 3; + break; + default: + WARN(1, "Incorrect KDiv\n"); + } - dco_freq = candidate_p0[min_dco_index] * - candidate_p1[min_dco_index] * - candidate_p2[min_dco_index] * afe_clock; + wrpll_params->qdiv_ratio = candidate_p1[min_dco_index]; + wrpll_params->qdiv_mode = + (wrpll_params->qdiv_ratio == 1) ? 0 : 1; - /* - * Intermediate values are in Hz. - * Divide by MHz to match bsepc - */ - wrpll_params->dco_integer = div_u64(dco_freq, (24 * MHz(1))); - wrpll_params->dco_fraction = - div_u64(((div_u64(dco_freq, 24) - - wrpll_params->dco_integer * MHz(1)) * 0x8000), MHz(1)); + dco_freq = candidate_p0[min_dco_index] * + candidate_p1[min_dco_index] * + candidate_p2[min_dco_index] * afe_clock; - } + /* + * Intermediate values are in Hz. + * Divide by MHz to match bsepc + */ + wrpll_params->dco_integer = div_u64(dco_freq, (24 * MHz(1))); + wrpll_params->dco_fraction = + div_u64(((div_u64(dco_freq, 24) - + wrpll_params->dco_integer * MHz(1)) * 0x8000), MHz(1)); return true; } -- cgit v1.2.3-70-g09d2 From 76516fbc294d60481f2427d6a42125364a629386 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 7 May 2015 18:38:42 +0100 Subject: drm/i915/skl: Factor out computing the DPLL paramaters from the dividers This part doesn't depend on how we compute the DPLL dividers (p and p0/p1/p2) and can be reused even if we change the algorithm to do so. (something that is planned for a followup patch) Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 139 +++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 64 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index c547f03904bc..a8d3976f7c5f 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1115,6 +1115,75 @@ struct skl_wrpll_params { uint32_t central_freq; }; +static void skl_wrpll_params_populate(struct skl_wrpll_params *params, + uint64_t afe_clock, + uint64_t central_freq, + uint32_t p0, uint32_t p1, uint32_t p2) +{ + uint64_t dco_freq; + + params->central_freq = central_freq; + + switch (central_freq) { + case 9600000000ULL: + params->central_freq = 0; + break; + case 9000000000ULL: + params->central_freq = 1; + break; + case 8400000000ULL: + params->central_freq = 3; + } + + switch (p0) { + case 1: + params->pdiv = 0; + break; + case 2: + params->pdiv = 1; + break; + case 3: + params->pdiv = 2; + break; + case 7: + params->pdiv = 4; + break; + default: + WARN(1, "Incorrect PDiv\n"); + } + + switch (p2) { + case 5: + params->kdiv = 0; + break; + case 2: + params->kdiv = 1; + break; + case 3: + params->kdiv = 2; + break; + case 1: + params->kdiv = 3; + break; + default: + WARN(1, "Incorrect KDiv\n"); + } + + params->qdiv_ratio = p1; + params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1; + + dco_freq = p0 * p1 * p2 * afe_clock; + + /* + * Intermediate values are in Hz. + * Divide by MHz to match bsepc + */ + params->dco_integer = div_u64(dco_freq, (24 * MHz(1))); + params->dco_fraction = + div_u64(((div_u64(dco_freq, 24) - + params->dco_integer * MHz(1)) * 0x8000), MHz(1)); +} + static bool skl_ddi_calculate_wrpll(int clock /* in Hz */, struct skl_wrpll_params *wrpll_params) @@ -1134,7 +1203,6 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */, uint32_t dco_central_freq_deviation[3]; uint32_t i, P1, k, dco_count; bool retry_with_odd = false; - uint64_t dco_freq; /* Determine P0, P1 or P2 */ for (dco_count = 0; dco_count < 3; dco_count++) { @@ -1197,69 +1265,12 @@ found: "No valid parameters found for pixel clock: %dHz\n", clock)) return false; - wrpll_params->central_freq = dco_central_freq[min_dco_index]; - - switch (dco_central_freq[min_dco_index]) { - case 9600000000ULL: - wrpll_params->central_freq = 0; - break; - case 9000000000ULL: - wrpll_params->central_freq = 1; - break; - case 8400000000ULL: - wrpll_params->central_freq = 3; - } - - switch (candidate_p0[min_dco_index]) { - case 1: - wrpll_params->pdiv = 0; - break; - case 2: - wrpll_params->pdiv = 1; - break; - case 3: - wrpll_params->pdiv = 2; - break; - case 7: - wrpll_params->pdiv = 4; - break; - default: - WARN(1, "Incorrect PDiv\n"); - } - - switch (candidate_p2[min_dco_index]) { - case 5: - wrpll_params->kdiv = 0; - break; - case 2: - wrpll_params->kdiv = 1; - break; - case 3: - wrpll_params->kdiv = 2; - break; - case 1: - wrpll_params->kdiv = 3; - break; - default: - WARN(1, "Incorrect KDiv\n"); - } - - wrpll_params->qdiv_ratio = candidate_p1[min_dco_index]; - wrpll_params->qdiv_mode = - (wrpll_params->qdiv_ratio == 1) ? 0 : 1; - - dco_freq = candidate_p0[min_dco_index] * - candidate_p1[min_dco_index] * - candidate_p2[min_dco_index] * afe_clock; - - /* - * Intermediate values are in Hz. - * Divide by MHz to match bsepc - */ - wrpll_params->dco_integer = div_u64(dco_freq, (24 * MHz(1))); - wrpll_params->dco_fraction = - div_u64(((div_u64(dco_freq, 24) - - wrpll_params->dco_integer * MHz(1)) * 0x8000), MHz(1)); + skl_wrpll_params_populate(wrpll_params, + afe_clock, + dco_central_freq[min_dco_index], + candidate_p0[min_dco_index], + candidate_p1[min_dco_index], + candidate_p2[min_dco_index]); return true; } -- cgit v1.2.3-70-g09d2 From 30a7862de84e69abc3018c57184f485048eed9d8 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 7 May 2015 18:38:43 +0100 Subject: drm/i915/skl: Remove unnecessary () used with div_u64() div_u64() can be either a inline function or a define, but in either case it's safe to provide expressions as parameters without outer () around them. Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index a8d3976f7c5f..416f8fbea34e 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1178,10 +1178,10 @@ static void skl_wrpll_params_populate(struct skl_wrpll_params *params, * Intermediate values are in Hz. * Divide by MHz to match bsepc */ - params->dco_integer = div_u64(dco_freq, (24 * MHz(1))); + params->dco_integer = div_u64(dco_freq, 24 * MHz(1)); params->dco_fraction = - div_u64(((div_u64(dco_freq, 24) - - params->dco_integer * MHz(1)) * 0x8000), MHz(1)); + div_u64((div_u64(dco_freq, 24) - + params->dco_integer * MHz(1)) * 0x8000, MHz(1)); } static bool -- cgit v1.2.3-70-g09d2 From 64311571a91fdd6d2ddc9055e9ba477f118067ad Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 7 May 2015 18:38:44 +0100 Subject: drm/i915/skl: Remove unnecessary () used with abs_diff() abs_diff() properly protects its parameters, so no need for the outer () here. Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 416f8fbea34e..0f931740149b 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1239,7 +1239,7 @@ found: if (found) { dco_central_freq_deviation[dco_count] = div64_u64(10000 * - abs_diff((candidate_p * afe_clock), + abs_diff(candidate_p * afe_clock, dco_central_freq[dco_count]), dco_central_freq[dco_count]); -- cgit v1.2.3-70-g09d2 From 6358298337abfabcf1e2b211c433f2093e5e9b28 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 7 May 2015 18:38:46 +0100 Subject: drm/i915: Correctly prefix HSW/BDW HDMI clock functions Those functions were the only one in existence when they were introduced. We now know they are only valid for HSW/BDW. Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 0f931740149b..8bb5291ca4da 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -625,11 +625,11 @@ intel_ddi_get_crtc_new_encoder(struct intel_crtc_state *crtc_state) (void) (&__a == &__b); \ __a > __b ? (__a - __b) : (__b - __a); }) -struct wrpll_rnp { +struct hsw_wrpll_rnp { unsigned p, n2, r2; }; -static unsigned wrpll_get_budget_for_freq(int clock) +static unsigned hsw_wrpll_get_budget_for_freq(int clock) { unsigned budget; @@ -703,9 +703,9 @@ static unsigned wrpll_get_budget_for_freq(int clock) return budget; } -static void wrpll_update_rnp(uint64_t freq2k, unsigned budget, - unsigned r2, unsigned n2, unsigned p, - struct wrpll_rnp *best) +static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget, + unsigned r2, unsigned n2, unsigned p, + struct hsw_wrpll_rnp *best) { uint64_t a, b, c, d, diff, diff_best; @@ -762,8 +762,7 @@ static void wrpll_update_rnp(uint64_t freq2k, unsigned budget, /* Otherwise a < c && b >= d, do nothing */ } -static int intel_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, - int reg) +static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, int reg) { int refclk = LC_FREQ; int n, p, r; @@ -929,10 +928,10 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder, link_clock = 270000; break; case PORT_CLK_SEL_WRPLL1: - link_clock = intel_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL1); + link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL1); break; case PORT_CLK_SEL_WRPLL2: - link_clock = intel_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL2); + link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL2); break; case PORT_CLK_SEL_SPLL: pll = I915_READ(SPLL_CTL) & SPLL_PLL_FREQ_MASK; @@ -1011,12 +1010,12 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */, { uint64_t freq2k; unsigned p, n2, r2; - struct wrpll_rnp best = { 0, 0, 0 }; + struct hsw_wrpll_rnp best = { 0, 0, 0 }; unsigned budget; freq2k = clock / 100; - budget = wrpll_get_budget_for_freq(clock); + budget = hsw_wrpll_get_budget_for_freq(clock); /* Special case handling for 540 pixel clock: bypass WR PLL entirely * and directly pass the LC PLL to it. */ @@ -1060,8 +1059,8 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */, n2++) { for (p = P_MIN; p <= P_MAX; p += P_INC) - wrpll_update_rnp(freq2k, budget, - r2, n2, p, &best); + hsw_wrpll_update_rnp(freq2k, budget, + r2, n2, p, &best); } } -- cgit v1.2.3-70-g09d2 From 877f61d947b6666205fee4ea7a04faf187a4ede5 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 7 May 2015 18:38:47 +0100 Subject: drm/i915/skl: Don't try to store the wrong central frequency The orignal code started by storing the actual central frequency (in Hz, using a uint64_t) in a uint32_t which codes for the register value. That can't be right. Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 8bb5291ca4da..832e4e141b3d 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1121,8 +1121,6 @@ static void skl_wrpll_params_populate(struct skl_wrpll_params *params, { uint64_t dco_freq; - params->central_freq = central_freq; - switch (central_freq) { case 9600000000ULL: params->central_freq = 0; -- cgit v1.2.3-70-g09d2 From 64987fc59d90738715703362292f743b7dbbe76b Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Tue, 26 May 2015 17:50:13 +0530 Subject: drm/i915/bxt: edp1.4 Intermediate Freq support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BXT supports following intermediate link rates for edp: 2.16GHz, 2.43GHz, 3.24GHz, 4.32GHz. Adding support for programming the intermediate rates. v2: Adding clock in bxt_clk_div struct and then look for the entry with required rate (Ville) v3: 'clock' has the selected value, no need to use link_bw or rate_select for selecting pll(Ville) v4: Make bxt_dp_clk_val const and remove size (Ville) v5: Rebased v6: Removed setting of vco while rebasing in v5, adding it back Signed-off-by: Sonika Jindal Reviewed-by: Ville Syrjälä (v4) Reviewed-by: Vandana Kannan Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_ddi.c | 39 ++++++++++++++++----------------------- drivers/gpu/drm/i915/intel_dp.c | 7 ++++++- 2 files changed, 22 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 832e4e141b3d..3eaf5c050573 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1348,6 +1348,7 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, /* bxt clock parameters */ struct bxt_clk_div { + int clock; uint32_t p1; uint32_t p2; uint32_t m2_int; @@ -1357,14 +1358,14 @@ struct bxt_clk_div { }; /* pre-calculated values for DP linkrates */ -static struct bxt_clk_div bxt_dp_clk_val[7] = { - /* 162 */ {4, 2, 32, 1677722, 1, 1}, - /* 270 */ {4, 1, 27, 0, 0, 1}, - /* 540 */ {2, 1, 27, 0, 0, 1}, - /* 216 */ {3, 2, 32, 1677722, 1, 1}, - /* 243 */ {4, 1, 24, 1258291, 1, 1}, - /* 324 */ {4, 1, 32, 1677722, 1, 1}, - /* 432 */ {3, 1, 32, 1677722, 1, 1} +static const struct bxt_clk_div bxt_dp_clk_val[] = { + {162000, 4, 2, 32, 1677722, 1, 1}, + {270000, 4, 1, 27, 0, 0, 1}, + {540000, 2, 1, 27, 0, 0, 1}, + {216000, 3, 2, 32, 1677722, 1, 1}, + {243000, 4, 1, 24, 1258291, 1, 1}, + {324000, 4, 1, 32, 1677722, 1, 1}, + {432000, 3, 1, 32, 1677722, 1, 1} }; static bool @@ -1404,22 +1405,14 @@ bxt_ddi_pll_select(struct intel_crtc *intel_crtc, vco = best_clock.vco; } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT || intel_encoder->type == INTEL_OUTPUT_EDP) { - struct drm_encoder *encoder = &intel_encoder->base; - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + int i; - switch (intel_dp->link_bw) { - case DP_LINK_BW_1_62: - clk_div = bxt_dp_clk_val[0]; - break; - case DP_LINK_BW_2_7: - clk_div = bxt_dp_clk_val[1]; - break; - case DP_LINK_BW_5_4: - clk_div = bxt_dp_clk_val[2]; - break; - default: - clk_div = bxt_dp_clk_val[0]; - DRM_ERROR("Unknown link rate\n"); + clk_div = bxt_dp_clk_val[0]; + for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) { + if (bxt_dp_clk_val[i].clock == clock) { + clk_div = bxt_dp_clk_val[i]; + break; + } } vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2; } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 823a1b31177c..fb5c01e46f4b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -91,6 +91,8 @@ static const struct dp_link_dpll chv_dpll[] = { { .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } } }; +static const int bxt_rates[] = { 162000, 216000, 243000, 270000, + 324000, 432000, 540000 }; static const int skl_rates[] = { 162000, 216000, 270000, 324000, 432000, 540000 }; static const int chv_rates[] = { 162000, 202500, 210000, 216000, @@ -1170,7 +1172,10 @@ intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates) static int intel_dp_source_rates(struct drm_device *dev, const int **source_rates) { - if (IS_SKYLAKE(dev)) { + if (IS_BROXTON(dev)) { + *source_rates = bxt_rates; + return ARRAY_SIZE(bxt_rates); + } else if (IS_SKYLAKE(dev)) { *source_rates = skl_rates; return ARRAY_SIZE(skl_rates); } else if (IS_CHERRYVIEW(dev)) { -- cgit v1.2.3-70-g09d2 From d9062ae59de1025bdd15988a4030d6e667c389d0 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 4 Jun 2015 18:21:32 +0100 Subject: drm/i915: Don't display the boot CDCLK twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_update_cdclk() will already display the boot CDCLK for DDI platforms, no need to repeat there. Signed-off-by: Damien Lespiau Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_ddi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 3eaf5c050573..fff494412fe6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2517,7 +2517,6 @@ void intel_ddi_pll_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t val = I915_READ(LCPLL_CTL); - int cdclk_freq; if (IS_SKYLAKE(dev)) skl_shared_dplls_init(dev_priv); @@ -2526,10 +2525,10 @@ void intel_ddi_pll_init(struct drm_device *dev) else hsw_shared_dplls_init(dev_priv); - cdclk_freq = dev_priv->display.get_display_clock_speed(dev); - DRM_DEBUG_KMS("CDCLK running at %dKHz\n", cdclk_freq); - if (IS_SKYLAKE(dev)) { + int cdclk_freq; + + cdclk_freq = dev_priv->display.get_display_clock_speed(dev); dev_priv->skl_boot_cdclk = cdclk_freq; if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) DRM_ERROR("LCPLL1 is disabled\n"); -- cgit v1.2.3-70-g09d2 From fe4c63c8cbd22251f8ce8bcb7853e46385f7af82 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 4 Jun 2015 18:01:35 +0300 Subject: drm/i915/bxt: fix DDI PHY vswing scale value setting According to bspec the DDI PHY vswing scale value is "don't care" in case the scale enable bit [27] is clear. But this doesn't seem to be correct. The scale value seems to also matter if the scale mode bit [26] is set. So both bit 26 and 27 depend on the value. Setting the scale value to 0 while either bit is set results in a failed modeset on HDMI (sink reports no signal). After reset the scale value is 0x98, but according to the spec we have to program it to 0x9a. So for consistency program it always to 0x9a regardless of the scale enable bit. Signed-off-by: Imre Deak Tested-by: Matt Roper Acked-by: Damien Lespiau Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_ddi.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index fff494412fe6..31b29e8781ac 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -181,15 +181,15 @@ struct bxt_ddi_buf_trans { */ static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = { /* Idx NT mV diff db */ - { 52, 0, 0, 128, true }, /* 0: 400 0 */ - { 78, 0, 0, 85, false }, /* 1: 400 3.5 */ - { 104, 0, 0, 64, false }, /* 2: 400 6 */ - { 154, 0, 0, 43, false }, /* 3: 400 9.5 */ - { 77, 0, 0, 128, false }, /* 4: 600 0 */ - { 116, 0, 0, 85, false }, /* 5: 600 3.5 */ - { 154, 0, 0, 64, false }, /* 6: 600 6 */ - { 102, 0, 0, 128, false }, /* 7: 800 0 */ - { 154, 0, 0, 85, false }, /* 8: 800 3.5 */ + { 52, 0x9A, 0, 128, true }, /* 0: 400 0 */ + { 78, 0x9A, 0, 85, false }, /* 1: 400 3.5 */ + { 104, 0x9A, 0, 64, false }, /* 2: 400 6 */ + { 154, 0x9A, 0, 43, false }, /* 3: 400 9.5 */ + { 77, 0x9A, 0, 128, false }, /* 4: 600 0 */ + { 116, 0x9A, 0, 85, false }, /* 5: 600 3.5 */ + { 154, 0x9A, 0, 64, false }, /* 6: 600 6 */ + { 102, 0x9A, 0, 128, false }, /* 7: 800 0 */ + { 154, 0x9A, 0, 85, false }, /* 8: 800 3.5 */ { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ }; @@ -198,15 +198,15 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = { */ static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { /* Idx NT mV diff db */ - { 52, 0, 0, 128, false }, /* 0: 400 0 */ - { 52, 0, 0, 85, false }, /* 1: 400 3.5 */ - { 52, 0, 0, 64, false }, /* 2: 400 6 */ - { 42, 0, 0, 43, false }, /* 3: 400 9.5 */ - { 77, 0, 0, 128, false }, /* 4: 600 0 */ - { 77, 0, 0, 85, false }, /* 5: 600 3.5 */ - { 77, 0, 0, 64, false }, /* 6: 600 6 */ - { 102, 0, 0, 128, false }, /* 7: 800 0 */ - { 102, 0, 0, 85, false }, /* 8: 800 3.5 */ + { 52, 0x9A, 0, 128, false }, /* 0: 400 0 */ + { 52, 0x9A, 0, 85, false }, /* 1: 400 3.5 */ + { 52, 0x9A, 0, 64, false }, /* 2: 400 6 */ + { 42, 0x9A, 0, 43, false }, /* 3: 400 9.5 */ + { 77, 0x9A, 0, 128, false }, /* 4: 600 0 */ + { 77, 0x9A, 0, 85, false }, /* 5: 600 3.5 */ + { 77, 0x9A, 0, 64, false }, /* 6: 600 6 */ + { 102, 0x9A, 0, 128, false }, /* 7: 800 0 */ + { 102, 0x9A, 0, 85, false }, /* 8: 800 3.5 */ { 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */ }; -- cgit v1.2.3-70-g09d2 From dc2538139277089e218b1b1d0d01454ecf39e944 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 25 Jun 2015 16:15:06 +0100 Subject: drm/i915/skl: Replace the HDMI DPLL divider computation algorithm The HW validation team came back from further testing with a slightly changed constraint on the deviation between the DCO frequency and the central frequency. Instead of +-4%, it's now +1%/-6%. Unfortunately, the previous algorithm didn't quite cope with these new constraints, the reason being that it wasn't thorough enough looking at the possible divider candidates. The new algorithm looks at all dividers, which is definitely a hammer approach (we could reduce further the set of dividers to good ones as a follow up, at the cost of a bit more complicated code). But, at least, we can now satisfy the +1%/+6% rule for all the "Well known" HDMI frequencies of my test set (373 entries). On that subject, the new code is quite extensively tested in intel-gpu-tools (tools/skl_compute_wrpll). v2: Fix cycling between central frequencies and dividers (Paulo) Properly choose the minimal deviation between postive and negative candidates (Paulo). On the 373 test frequencies, v2 computes better dividers than v1 (ie more even dividers and lower deviation on average): v1: average deviation: 206.52 v2: average deviation: 194.47 Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 211 +++++++++++++++++++++++++-------------- 1 file changed, 137 insertions(+), 74 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 31b29e8781ac..6e964ef7dfda 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1104,6 +1104,103 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc, return true; } +struct skl_wrpll_context { + uint64_t min_deviation; /* current minimal deviation */ + uint64_t central_freq; /* chosen central freq */ + uint64_t dco_freq; /* chosen dco freq */ + unsigned int p; /* chosen divider */ +}; + +static void skl_wrpll_context_init(struct skl_wrpll_context *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->min_deviation = U64_MAX; +} + +/* DCO freq must be within +1%/-6% of the DCO central freq */ +#define SKL_DCO_MAX_PDEVIATION 100 +#define SKL_DCO_MAX_NDEVIATION 600 + +static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx, + uint64_t central_freq, + uint64_t dco_freq, + unsigned int divider) +{ + uint64_t deviation; + + deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq), + central_freq); + + /* positive deviation */ + if (dco_freq >= central_freq) { + if (deviation < SKL_DCO_MAX_PDEVIATION && + deviation < ctx->min_deviation) { + ctx->min_deviation = deviation; + ctx->central_freq = central_freq; + ctx->dco_freq = dco_freq; + ctx->p = divider; + } + /* negative deviation */ + } else if (deviation < SKL_DCO_MAX_NDEVIATION && + deviation < ctx->min_deviation) { + ctx->min_deviation = deviation; + ctx->central_freq = central_freq; + ctx->dco_freq = dco_freq; + ctx->p = divider; + } + +} + +static void skl_wrpll_get_multipliers(unsigned int p, + unsigned int *p0 /* out */, + unsigned int *p1 /* out */, + unsigned int *p2 /* out */) +{ + /* even dividers */ + if (p % 2 == 0) { + unsigned int half = p / 2; + + if (half == 1 || half == 2 || half == 3 || half == 5) { + *p0 = 2; + *p1 = 1; + *p2 = half; + } else if (half % 2 == 0) { + *p0 = 2; + *p1 = half / 2; + *p2 = 2; + } else if (half % 3 == 0) { + *p0 = 3; + *p1 = half / 3; + *p2 = 2; + } else if (half % 7 == 0) { + *p0 = 7; + *p1 = half / 7; + *p2 = 2; + } + } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */ + *p0 = 3; + *p1 = 1; + *p2 = p / 3; + } else if (p == 5 || p == 7) { + *p0 = p; + *p1 = 1; + *p2 = 1; + } else if (p == 15) { + *p0 = 3; + *p1 = 1; + *p2 = 5; + } else if (p == 21) { + *p0 = 7; + *p1 = 1; + *p2 = 3; + } else if (p == 35) { + *p0 = 7; + *p1 = 1; + *p2 = 5; + } +} + struct skl_wrpll_params { uint32_t dco_fraction; uint32_t dco_integer; @@ -1189,90 +1286,56 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */, uint64_t dco_central_freq[3] = {8400000000ULL, 9000000000ULL, 9600000000ULL}; - uint32_t min_dco_deviation = 400; - uint32_t min_dco_index = 3; - uint32_t P0[4] = {1, 2, 3, 7}; - uint32_t P2[4] = {1, 2, 3, 5}; - bool found = false; - uint32_t candidate_p = 0; - uint32_t candidate_p0[3] = {0}, candidate_p1[3] = {0}; - uint32_t candidate_p2[3] = {0}; - uint32_t dco_central_freq_deviation[3]; - uint32_t i, P1, k, dco_count; - bool retry_with_odd = false; - - /* Determine P0, P1 or P2 */ - for (dco_count = 0; dco_count < 3; dco_count++) { - found = false; - candidate_p = - div64_u64(dco_central_freq[dco_count], afe_clock); - if (retry_with_odd == false) - candidate_p = (candidate_p % 2 == 0 ? - candidate_p : candidate_p + 1); - - for (P1 = 1; P1 < candidate_p; P1++) { - for (i = 0; i < 4; i++) { - if (!(P0[i] != 1 || P1 == 1)) - continue; - - for (k = 0; k < 4; k++) { - if (P1 != 1 && P2[k] != 2) - continue; - - if (candidate_p == P0[i] * P1 * P2[k]) { - /* Found possible P0, P1, P2 */ - found = true; - candidate_p0[dco_count] = P0[i]; - candidate_p1[dco_count] = P1; - candidate_p2[dco_count] = P2[k]; - goto found; - } - - } - } - } - -found: - if (found) { - dco_central_freq_deviation[dco_count] = - div64_u64(10000 * - abs_diff(candidate_p * afe_clock, - dco_central_freq[dco_count]), - dco_central_freq[dco_count]); - - if (dco_central_freq_deviation[dco_count] < - min_dco_deviation) { - min_dco_deviation = - dco_central_freq_deviation[dco_count]; - min_dco_index = dco_count; + static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20, + 24, 28, 30, 32, 36, 40, 42, 44, + 48, 52, 54, 56, 60, 64, 66, 68, + 70, 72, 76, 78, 80, 84, 88, 90, + 92, 96, 98 }; + static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 }; + static const struct { + const int *list; + int n_dividers; + } dividers[] = { + { even_dividers, ARRAY_SIZE(even_dividers) }, + { odd_dividers, ARRAY_SIZE(odd_dividers) }, + }; + struct skl_wrpll_context ctx; + unsigned int dco, d, i; + unsigned int p0, p1, p2; + + skl_wrpll_context_init(&ctx); + + for (d = 0; d < ARRAY_SIZE(dividers); d++) { + for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) { + for (i = 0; i < dividers[d].n_dividers; i++) { + unsigned int p = dividers[d].list[i]; + uint64_t dco_freq = p * afe_clock; + + skl_wrpll_try_divider(&ctx, + dco_central_freq[dco], + dco_freq, + p); } } - - if (min_dco_index > 2 && dco_count == 2) { - /* oh well, we tried... */ - if (retry_with_odd) - break; - - retry_with_odd = true; - dco_count = 0; - } } - if (WARN(min_dco_index > 2, - "No valid parameters found for pixel clock: %dHz\n", clock)) + if (!ctx.p) { + DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock); return false; + } - skl_wrpll_params_populate(wrpll_params, - afe_clock, - dco_central_freq[min_dco_index], - candidate_p0[min_dco_index], - candidate_p1[min_dco_index], - candidate_p2[min_dco_index]); + /* + * gcc incorrectly analyses that these can be used without being + * initialized. To be fair, it's hard to guess. + */ + p0 = p1 = p2 = 0; + skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2); + skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq, + p0, p1, p2); return true; } - static bool skl_ddi_pll_select(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state, -- cgit v1.2.3-70-g09d2 From 267db663458a8077a087674fb85ea95f540d8671 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 25 Jun 2015 16:19:24 +0100 Subject: drm/i915/skl: Prefer even dividers for SKL DPLLs Currently, if an odd divider improves the deviation (minimizes it), we take that divider. The recommendation is to prefer even dividers. v2: Move the check at the right place after having inverted the two for loops in the previous patch. Signed-off-by: Damien Lespiau Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 6e964ef7dfda..f6b3ccc4ab66 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1317,6 +1317,13 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */, p); } } + + /* + * If a solution is found with an even divider, prefer + * this one. + */ + if (d == 0 && ctx.p) + break; } if (!ctx.p) { -- cgit v1.2.3-70-g09d2 From e7ad987832637701fc723ac2c1580c30c191bca6 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Fri, 26 Jun 2015 18:34:29 +0100 Subject: drm/i915/skl: Skip remaining dividers when deviation is 0 We can't improve a 0 deviation, so when we find such a divider, skip the remaining ones they won't be better. This short-circuit the search for 34 of the 373 test frequencies in the corresponding i-g-t test (tools/skl_compute_wrpll) v2: Place the short-circuiting code in skl_compute_wrpll() (Paulo) (I'm sure nobody will notice the spurious removal of a blank line) Reviewed-by: Paulo Zanoni Suggested-by: Paulo Zanoni Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index f6b3ccc4ab66..42c14870ef43 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1149,7 +1149,6 @@ static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx, ctx->dco_freq = dco_freq; ctx->p = divider; } - } static void skl_wrpll_get_multipliers(unsigned int p, @@ -1315,9 +1314,17 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */, dco_central_freq[dco], dco_freq, p); + /* + * Skip the remaining dividers if we're sure to + * have found the definitive divider, we can't + * improve a 0 deviation. + */ + if (ctx.min_deviation == 0) + goto skip_remaining_dividers; } } +skip_remaining_dividers: /* * If a solution is found with an even divider, prefer * this one. -- cgit v1.2.3-70-g09d2 From f8896f5d58e64bfd3c2b5f7c5ba5c3f3967e93c7 Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Thu, 25 Jun 2015 11:11:03 +0300 Subject: drm/i915/skl: Buffer translation improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for 0.85V VccIO on Skylake Y, separate buffer translation tables for Skylake U, and support for I_boost for the entries that needs this. Changes in v2: * Refactored the code a bit to move all DDI signal level setup to intel_ddi.c Issue: VIZ-5677 Signed-off-by: David Weinehall Reviewed-by: Antti Koskipää [danvet: Apply style polish checkpatch suggested.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 8 + drivers/gpu/drm/i915/i915_reg.h | 12 + drivers/gpu/drm/i915/intel_ddi.c | 509 ++++++++++++++++++++++++++++++--------- drivers/gpu/drm/i915/intel_dp.c | 104 +------- drivers/gpu/drm/i915/intel_drv.h | 3 +- 5 files changed, 423 insertions(+), 213 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6acc6504863b..64041e788a1c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2436,6 +2436,14 @@ struct drm_i915_cmd_table { /* ULX machines are also considered ULT. */ #define IS_HSW_ULX(dev) (INTEL_DEVID(dev) == 0x0A0E || \ INTEL_DEVID(dev) == 0x0A1E) +#define IS_SKL_ULT(dev) (INTEL_DEVID(dev) == 0x1906 || \ + INTEL_DEVID(dev) == 0x1913 || \ + INTEL_DEVID(dev) == 0x1916 || \ + INTEL_DEVID(dev) == 0x1921 || \ + INTEL_DEVID(dev) == 0x1926) +#define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \ + INTEL_DEVID(dev) == 0x1915 || \ + INTEL_DEVID(dev) == 0x191E) #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) #define SKL_REVID_A0 (0x0) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 50e6279d7d56..bdef9f7b629e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1384,6 +1384,18 @@ enum skl_disp_power_wells { _PORT_TX_DW14_LN0_C) + \ _BXT_LANE_OFFSET(lane)) +/* UAIMI scratch pad register 1 */ +#define UAIMI_SPR1 0x4F074 +/* SKL VccIO mask */ +#define SKL_VCCIO_MASK 0x1 +/* SKL balance leg register */ +#define DISPIO_CR_TX_BMU_CR0 0x6C00C +/* I_boost values */ +#define BALANCE_LEG_SHIFT(port) (8+3*(port)) +#define BALANCE_LEG_MASK(port) (7<<(8+3*(port))) +/* Balance leg disable bits */ +#define BALANCE_LEG_DISABLE_SHIFT 23 + /* * Fence registers */ diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 42c14870ef43..b29d103bd706 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -31,6 +31,7 @@ struct ddi_buf_trans { u32 trans1; /* balance leg enable, de-emph level */ u32 trans2; /* vref sel, vswing */ + u8 i_boost; /* SKL: I_boost; valid: 0x0, 0x1, 0x3, 0x7 */ }; /* HDMI/DVI modes ignore everything but the last 2 items. So we share @@ -38,134 +39,213 @@ struct ddi_buf_trans { * automatically adapt to HDMI connections as well */ static const struct ddi_buf_trans hsw_ddi_translations_dp[] = { - { 0x00FFFFFF, 0x0006000E }, - { 0x00D75FFF, 0x0005000A }, - { 0x00C30FFF, 0x00040006 }, - { 0x80AAAFFF, 0x000B0000 }, - { 0x00FFFFFF, 0x0005000A }, - { 0x00D75FFF, 0x000C0004 }, - { 0x80C30FFF, 0x000B0000 }, - { 0x00FFFFFF, 0x00040006 }, - { 0x80D75FFF, 0x000B0000 }, + { 0x00FFFFFF, 0x0006000E, 0x0 }, + { 0x00D75FFF, 0x0005000A, 0x0 }, + { 0x00C30FFF, 0x00040006, 0x0 }, + { 0x80AAAFFF, 0x000B0000, 0x0 }, + { 0x00FFFFFF, 0x0005000A, 0x0 }, + { 0x00D75FFF, 0x000C0004, 0x0 }, + { 0x80C30FFF, 0x000B0000, 0x0 }, + { 0x00FFFFFF, 0x00040006, 0x0 }, + { 0x80D75FFF, 0x000B0000, 0x0 }, }; static const struct ddi_buf_trans hsw_ddi_translations_fdi[] = { - { 0x00FFFFFF, 0x0007000E }, - { 0x00D75FFF, 0x000F000A }, - { 0x00C30FFF, 0x00060006 }, - { 0x00AAAFFF, 0x001E0000 }, - { 0x00FFFFFF, 0x000F000A }, - { 0x00D75FFF, 0x00160004 }, - { 0x00C30FFF, 0x001E0000 }, - { 0x00FFFFFF, 0x00060006 }, - { 0x00D75FFF, 0x001E0000 }, + { 0x00FFFFFF, 0x0007000E, 0x0 }, + { 0x00D75FFF, 0x000F000A, 0x0 }, + { 0x00C30FFF, 0x00060006, 0x0 }, + { 0x00AAAFFF, 0x001E0000, 0x0 }, + { 0x00FFFFFF, 0x000F000A, 0x0 }, + { 0x00D75FFF, 0x00160004, 0x0 }, + { 0x00C30FFF, 0x001E0000, 0x0 }, + { 0x00FFFFFF, 0x00060006, 0x0 }, + { 0x00D75FFF, 0x001E0000, 0x0 }, }; static const struct ddi_buf_trans hsw_ddi_translations_hdmi[] = { /* Idx NT mV d T mV d db */ - { 0x00FFFFFF, 0x0006000E }, /* 0: 400 400 0 */ - { 0x00E79FFF, 0x000E000C }, /* 1: 400 500 2 */ - { 0x00D75FFF, 0x0005000A }, /* 2: 400 600 3.5 */ - { 0x00FFFFFF, 0x0005000A }, /* 3: 600 600 0 */ - { 0x00E79FFF, 0x001D0007 }, /* 4: 600 750 2 */ - { 0x00D75FFF, 0x000C0004 }, /* 5: 600 900 3.5 */ - { 0x00FFFFFF, 0x00040006 }, /* 6: 800 800 0 */ - { 0x80E79FFF, 0x00030002 }, /* 7: 800 1000 2 */ - { 0x00FFFFFF, 0x00140005 }, /* 8: 850 850 0 */ - { 0x00FFFFFF, 0x000C0004 }, /* 9: 900 900 0 */ - { 0x00FFFFFF, 0x001C0003 }, /* 10: 950 950 0 */ - { 0x80FFFFFF, 0x00030002 }, /* 11: 1000 1000 0 */ + { 0x00FFFFFF, 0x0006000E, 0x0 },/* 0: 400 400 0 */ + { 0x00E79FFF, 0x000E000C, 0x0 },/* 1: 400 500 2 */ + { 0x00D75FFF, 0x0005000A, 0x0 },/* 2: 400 600 3.5 */ + { 0x00FFFFFF, 0x0005000A, 0x0 },/* 3: 600 600 0 */ + { 0x00E79FFF, 0x001D0007, 0x0 },/* 4: 600 750 2 */ + { 0x00D75FFF, 0x000C0004, 0x0 },/* 5: 600 900 3.5 */ + { 0x00FFFFFF, 0x00040006, 0x0 },/* 6: 800 800 0 */ + { 0x80E79FFF, 0x00030002, 0x0 },/* 7: 800 1000 2 */ + { 0x00FFFFFF, 0x00140005, 0x0 },/* 8: 850 850 0 */ + { 0x00FFFFFF, 0x000C0004, 0x0 },/* 9: 900 900 0 */ + { 0x00FFFFFF, 0x001C0003, 0x0 },/* 10: 950 950 0 */ + { 0x80FFFFFF, 0x00030002, 0x0 },/* 11: 1000 1000 0 */ }; static const struct ddi_buf_trans bdw_ddi_translations_edp[] = { - { 0x00FFFFFF, 0x00000012 }, - { 0x00EBAFFF, 0x00020011 }, - { 0x00C71FFF, 0x0006000F }, - { 0x00AAAFFF, 0x000E000A }, - { 0x00FFFFFF, 0x00020011 }, - { 0x00DB6FFF, 0x0005000F }, - { 0x00BEEFFF, 0x000A000C }, - { 0x00FFFFFF, 0x0005000F }, - { 0x00DB6FFF, 0x000A000C }, + { 0x00FFFFFF, 0x00000012, 0x0 }, + { 0x00EBAFFF, 0x00020011, 0x0 }, + { 0x00C71FFF, 0x0006000F, 0x0 }, + { 0x00AAAFFF, 0x000E000A, 0x0 }, + { 0x00FFFFFF, 0x00020011, 0x0 }, + { 0x00DB6FFF, 0x0005000F, 0x0 }, + { 0x00BEEFFF, 0x000A000C, 0x0 }, + { 0x00FFFFFF, 0x0005000F, 0x0 }, + { 0x00DB6FFF, 0x000A000C, 0x0 }, }; static const struct ddi_buf_trans bdw_ddi_translations_dp[] = { - { 0x00FFFFFF, 0x0007000E }, - { 0x00D75FFF, 0x000E000A }, - { 0x00BEFFFF, 0x00140006 }, - { 0x80B2CFFF, 0x001B0002 }, - { 0x00FFFFFF, 0x000E000A }, - { 0x00DB6FFF, 0x00160005 }, - { 0x80C71FFF, 0x001A0002 }, - { 0x00F7DFFF, 0x00180004 }, - { 0x80D75FFF, 0x001B0002 }, + { 0x00FFFFFF, 0x0007000E, 0x0 }, + { 0x00D75FFF, 0x000E000A, 0x0 }, + { 0x00BEFFFF, 0x00140006, 0x0 }, + { 0x80B2CFFF, 0x001B0002, 0x0 }, + { 0x00FFFFFF, 0x000E000A, 0x0 }, + { 0x00DB6FFF, 0x00160005, 0x0 }, + { 0x80C71FFF, 0x001A0002, 0x0 }, + { 0x00F7DFFF, 0x00180004, 0x0 }, + { 0x80D75FFF, 0x001B0002, 0x0 }, }; static const struct ddi_buf_trans bdw_ddi_translations_fdi[] = { - { 0x00FFFFFF, 0x0001000E }, - { 0x00D75FFF, 0x0004000A }, - { 0x00C30FFF, 0x00070006 }, - { 0x00AAAFFF, 0x000C0000 }, - { 0x00FFFFFF, 0x0004000A }, - { 0x00D75FFF, 0x00090004 }, - { 0x00C30FFF, 0x000C0000 }, - { 0x00FFFFFF, 0x00070006 }, - { 0x00D75FFF, 0x000C0000 }, + { 0x00FFFFFF, 0x0001000E, 0x0 }, + { 0x00D75FFF, 0x0004000A, 0x0 }, + { 0x00C30FFF, 0x00070006, 0x0 }, + { 0x00AAAFFF, 0x000C0000, 0x0 }, + { 0x00FFFFFF, 0x0004000A, 0x0 }, + { 0x00D75FFF, 0x00090004, 0x0 }, + { 0x00C30FFF, 0x000C0000, 0x0 }, + { 0x00FFFFFF, 0x00070006, 0x0 }, + { 0x00D75FFF, 0x000C0000, 0x0 }, }; static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = { /* Idx NT mV d T mV df db */ - { 0x00FFFFFF, 0x0007000E }, /* 0: 400 400 0 */ - { 0x00D75FFF, 0x000E000A }, /* 1: 400 600 3.5 */ - { 0x00BEFFFF, 0x00140006 }, /* 2: 400 800 6 */ - { 0x00FFFFFF, 0x0009000D }, /* 3: 450 450 0 */ - { 0x00FFFFFF, 0x000E000A }, /* 4: 600 600 0 */ - { 0x00D7FFFF, 0x00140006 }, /* 5: 600 800 2.5 */ - { 0x80CB2FFF, 0x001B0002 }, /* 6: 600 1000 4.5 */ - { 0x00FFFFFF, 0x00140006 }, /* 7: 800 800 0 */ - { 0x80E79FFF, 0x001B0002 }, /* 8: 800 1000 2 */ - { 0x80FFFFFF, 0x001B0002 }, /* 9: 1000 1000 0 */ + { 0x00FFFFFF, 0x0007000E, 0x0 },/* 0: 400 400 0 */ + { 0x00D75FFF, 0x000E000A, 0x0 },/* 1: 400 600 3.5 */ + { 0x00BEFFFF, 0x00140006, 0x0 },/* 2: 400 800 6 */ + { 0x00FFFFFF, 0x0009000D, 0x0 },/* 3: 450 450 0 */ + { 0x00FFFFFF, 0x000E000A, 0x0 },/* 4: 600 600 0 */ + { 0x00D7FFFF, 0x00140006, 0x0 },/* 5: 600 800 2.5 */ + { 0x80CB2FFF, 0x001B0002, 0x0 },/* 6: 600 1000 4.5 */ + { 0x00FFFFFF, 0x00140006, 0x0 },/* 7: 800 800 0 */ + { 0x80E79FFF, 0x001B0002, 0x0 },/* 8: 800 1000 2 */ + { 0x80FFFFFF, 0x001B0002, 0x0 },/* 9: 1000 1000 0 */ }; +/* Skylake H, S, and Skylake Y with 0.95V VccIO */ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { - { 0x00000018, 0x000000a2 }, - { 0x00004014, 0x0000009B }, - { 0x00006012, 0x00000088 }, - { 0x00008010, 0x00000087 }, - { 0x00000018, 0x0000009B }, - { 0x00004014, 0x00000088 }, - { 0x00006012, 0x00000087 }, - { 0x00000018, 0x00000088 }, - { 0x00004014, 0x00000087 }, + { 0x00002016, 0x000000A0, 0x0 }, + { 0x00005012, 0x0000009B, 0x0 }, + { 0x00007011, 0x00000088, 0x0 }, + { 0x00009010, 0x000000C7, 0x0 }, + { 0x00002016, 0x0000009B, 0x0 }, + { 0x00005012, 0x00000088, 0x0 }, + { 0x00007011, 0x000000C7, 0x0 }, + { 0x00002016, 0x000000DF, 0x0 }, + { 0x00005012, 0x000000C7, 0x0 }, }; -/* eDP 1.4 low vswing translation parameters */ +/* Skylake U */ +static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { + { 0x00002016, 0x000000A2, 0x0 }, + { 0x00005012, 0x00000088, 0x0 }, + { 0x00007011, 0x00000087, 0x0 }, + { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ + { 0x00002016, 0x0000009D, 0x0 }, + { 0x00005012, 0x000000C7, 0x0 }, + { 0x00007011, 0x000000C7, 0x0 }, + { 0x00002016, 0x00000088, 0x0 }, + { 0x00005012, 0x000000C7, 0x0 }, +}; + +/* Skylake Y with 0.85V VccIO */ +static const struct ddi_buf_trans skl_y_085v_ddi_translations_dp[] = { + { 0x00000018, 0x000000A2, 0x0 }, + { 0x00005012, 0x00000088, 0x0 }, + { 0x00007011, 0x00000087, 0x0 }, + { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ + { 0x00000018, 0x0000009D, 0x0 }, + { 0x00005012, 0x000000C7, 0x0 }, + { 0x00007011, 0x000000C7, 0x0 }, + { 0x00000018, 0x00000088, 0x0 }, + { 0x00005012, 0x000000C7, 0x0 }, +}; + +/* + * Skylake H and S, and Skylake Y with 0.95V VccIO + * eDP 1.4 low vswing translation parameters + */ static const struct ddi_buf_trans skl_ddi_translations_edp[] = { - { 0x00000018, 0x000000a8 }, - { 0x00002016, 0x000000ab }, - { 0x00006012, 0x000000a2 }, - { 0x00008010, 0x00000088 }, - { 0x00000018, 0x000000ab }, - { 0x00004014, 0x000000a2 }, - { 0x00006012, 0x000000a6 }, - { 0x00000018, 0x000000a2 }, - { 0x00005013, 0x0000009c }, - { 0x00000018, 0x00000088 }, + { 0x00000018, 0x000000A8, 0x0 }, + { 0x00004013, 0x000000A9, 0x0 }, + { 0x00007011, 0x000000A2, 0x0 }, + { 0x00009010, 0x0000009C, 0x0 }, + { 0x00000018, 0x000000A9, 0x0 }, + { 0x00006013, 0x000000A2, 0x0 }, + { 0x00007011, 0x000000A6, 0x0 }, + { 0x00000018, 0x000000AB, 0x0 }, + { 0x00007013, 0x0000009F, 0x0 }, + { 0x00000018, 0x000000DF, 0x0 }, }; +/* + * Skylake U + * eDP 1.4 low vswing translation parameters + */ +static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { + { 0x00000018, 0x000000A8, 0x0 }, + { 0x00004013, 0x000000A9, 0x0 }, + { 0x00007011, 0x000000A2, 0x0 }, + { 0x00009010, 0x0000009C, 0x0 }, + { 0x00000018, 0x000000A9, 0x0 }, + { 0x00006013, 0x000000A2, 0x0 }, + { 0x00007011, 0x000000A6, 0x0 }, + { 0x00002016, 0x000000AB, 0x0 }, + { 0x00005013, 0x0000009F, 0x0 }, + { 0x00000018, 0x000000DF, 0x0 }, +}; +/* + * Skylake Y with 0.95V VccIO + * eDP 1.4 low vswing translation parameters + */ +static const struct ddi_buf_trans skl_y_085v_ddi_translations_edp[] = { + { 0x00000018, 0x000000A8, 0x0 }, + { 0x00004013, 0x000000AB, 0x0 }, + { 0x00007011, 0x000000A4, 0x0 }, + { 0x00009010, 0x000000DF, 0x0 }, + { 0x00000018, 0x000000AA, 0x0 }, + { 0x00006013, 0x000000A4, 0x0 }, + { 0x00007011, 0x0000009D, 0x0 }, + { 0x00000018, 0x000000A0, 0x0 }, + { 0x00006012, 0x000000DF, 0x0 }, + { 0x00000018, 0x0000008A, 0x0 }, +}; + +/* Skylake H, S and U, and Skylake Y with 0.95V VccIO */ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { - { 0x00000018, 0x000000ac }, - { 0x00005012, 0x0000009d }, - { 0x00007011, 0x00000088 }, - { 0x00000018, 0x000000a1 }, - { 0x00000018, 0x00000098 }, - { 0x00004013, 0x00000088 }, - { 0x00006012, 0x00000087 }, - { 0x00000018, 0x000000df }, - { 0x00003015, 0x00000087 }, - { 0x00003015, 0x000000c7 }, - { 0x00000018, 0x000000c7 }, + { 0x00000018, 0x000000AC, 0x0 }, + { 0x00005012, 0x0000009D, 0x0 }, + { 0x00007011, 0x00000088, 0x0 }, + { 0x00000018, 0x000000A1, 0x0 }, + { 0x00000018, 0x00000098, 0x0 }, + { 0x00004013, 0x00000088, 0x0 }, + { 0x00006012, 0x00000087, 0x0 }, + { 0x00000018, 0x000000DF, 0x0 }, + { 0x00003015, 0x00000087, 0x0 }, /* Default */ + { 0x00003015, 0x000000C7, 0x0 }, + { 0x00000018, 0x000000C7, 0x0 }, +}; + +/* Skylake Y with 0.85V VccIO */ +static const struct ddi_buf_trans skl_y_085v_ddi_translations_hdmi[] = { + { 0x00000018, 0x000000A1, 0x0 }, + { 0x00005012, 0x000000DF, 0x0 }, + { 0x00007011, 0x00000084, 0x0 }, + { 0x00000018, 0x000000A4, 0x0 }, + { 0x00000018, 0x0000009D, 0x0 }, + { 0x00004013, 0x00000080, 0x0 }, + { 0x00006013, 0x000000C7, 0x0 }, + { 0x00000018, 0x0000008A, 0x0 }, + { 0x00003015, 0x000000C7, 0x0 }, /* Default */ + { 0x80003015, 0x000000C7, 0x7 }, /* Uses I_boost */ + { 0x00000018, 0x000000C7, 0x0 }, }; struct bxt_ddi_buf_trans { @@ -190,7 +270,7 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = { { 154, 0x9A, 0, 64, false }, /* 6: 600 6 */ { 102, 0x9A, 0, 128, false }, /* 7: 800 0 */ { 154, 0x9A, 0, 85, false }, /* 8: 800 3.5 */ - { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ + { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ }; /* BSpec has 2 recommended values - entries 0 and 8. @@ -210,6 +290,9 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { { 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */ }; +static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, + enum port port, int type); + static void ddi_get_encoder_port(struct intel_encoder *intel_encoder, struct intel_digital_port **dig_port, enum port *port) @@ -249,6 +332,102 @@ intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) return intel_dig_port->hdmi.hdmi_reg; } +static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev, + int *n_entries) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const struct ddi_buf_trans *ddi_translations; + static int is_095v = -1; + + if (is_095v == -1) { + u32 spr1 = I915_READ(UAIMI_SPR1); + + is_095v = spr1 & SKL_VCCIO_MASK; + } + + if (IS_SKL_ULX(dev) && !is_095v) { + ddi_translations = skl_y_085v_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_dp); + } else if (IS_SKL_ULT(dev)) { + ddi_translations = skl_u_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); + } else { + ddi_translations = skl_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); + } + + return ddi_translations; +} + +static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev, + int *n_entries) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const struct ddi_buf_trans *ddi_translations; + static int is_095v = -1; + + if (is_095v == -1) { + u32 spr1 = I915_READ(UAIMI_SPR1); + + is_095v = spr1 & SKL_VCCIO_MASK; + } + + if (IS_SKL_ULX(dev) && !is_095v) { + if (dev_priv->edp_low_vswing) { + ddi_translations = skl_y_085v_ddi_translations_edp; + *n_entries = + ARRAY_SIZE(skl_y_085v_ddi_translations_edp); + } else { + ddi_translations = skl_y_085v_ddi_translations_dp; + *n_entries = + ARRAY_SIZE(skl_y_085v_ddi_translations_dp); + } + } else if (IS_SKL_ULT(dev)) { + if (dev_priv->edp_low_vswing) { + ddi_translations = skl_u_ddi_translations_edp; + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_edp); + } else { + ddi_translations = skl_u_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); + } + } else { + if (dev_priv->edp_low_vswing) { + ddi_translations = skl_ddi_translations_edp; + *n_entries = ARRAY_SIZE(skl_ddi_translations_edp); + } else { + ddi_translations = skl_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_ddi_translations_dp); + } + } + + return ddi_translations; +} + +static const struct ddi_buf_trans * +skl_get_buf_trans_hdmi(struct drm_device *dev, + int *n_entries) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const struct ddi_buf_trans *ddi_translations; + static int is_095v = -1; + + if (is_095v == -1) { + u32 spr1 = I915_READ(UAIMI_SPR1); + + is_095v = spr1 & SKL_VCCIO_MASK; + } + + if (IS_SKL_ULX(dev) && !is_095v) { + ddi_translations = skl_y_085v_ddi_translations_hdmi; + *n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_hdmi); + } else { + ddi_translations = skl_ddi_translations_hdmi; + *n_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); + } + + return ddi_translations; +} + /* * Starting with Haswell, DDI port buffers must be programmed with correct * values in advance. The buffer values are different for FDI and DP modes, @@ -279,20 +458,13 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, INTEL_OUTPUT_HDMI); return; } else if (IS_SKYLAKE(dev)) { - ddi_translations_fdi = NULL; - ddi_translations_dp = skl_ddi_translations_dp; - n_dp_entries = ARRAY_SIZE(skl_ddi_translations_dp); - if (dev_priv->edp_low_vswing) { - ddi_translations_edp = skl_ddi_translations_edp; - n_edp_entries = ARRAY_SIZE(skl_ddi_translations_edp); - } else { - ddi_translations_edp = skl_ddi_translations_dp; - n_edp_entries = ARRAY_SIZE(skl_ddi_translations_dp); - } - - ddi_translations_hdmi = skl_ddi_translations_hdmi; - n_hdmi_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); - hdmi_default_entry = 7; + ddi_translations_dp = + skl_get_buf_trans_dp(dev, &n_dp_entries); + ddi_translations_edp = + skl_get_buf_trans_edp(dev, &n_edp_entries); + ddi_translations_hdmi = + skl_get_buf_trans_hdmi(dev, &n_hdmi_entries); + hdmi_default_entry = 8; } else if (IS_BROADWELL(dev)) { ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_dp = bdw_ddi_translations_dp; @@ -1883,8 +2055,48 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc) TRANS_CLK_SEL_DISABLED); } -void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, - enum port port, int type) +static void skl_ddi_set_iboost(struct drm_device *dev, u32 level, + enum port port, int type) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + const struct ddi_buf_trans *ddi_translations; + uint8_t iboost; + int n_entries; + u32 reg; + + if (type == INTEL_OUTPUT_DISPLAYPORT) { + ddi_translations = skl_get_buf_trans_dp(dev, &n_entries); + iboost = ddi_translations[port].i_boost; + } else if (type == INTEL_OUTPUT_EDP) { + ddi_translations = skl_get_buf_trans_edp(dev, &n_entries); + iboost = ddi_translations[port].i_boost; + } else if (type == INTEL_OUTPUT_HDMI) { + ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries); + iboost = ddi_translations[port].i_boost; + } else { + return; + } + + /* Make sure that the requested I_boost is valid */ + if (iboost && iboost != 0x1 && iboost != 0x3 && iboost != 0x7) { + DRM_ERROR("Invalid I_boost value %u\n", iboost); + return; + } + + reg = I915_READ(DISPIO_CR_TX_BMU_CR0); + reg &= ~BALANCE_LEG_MASK(port); + reg &= ~(1 << (BALANCE_LEG_DISABLE_SHIFT + port)); + + if (iboost) + reg |= iboost << BALANCE_LEG_SHIFT(port); + else + reg |= 1 << (BALANCE_LEG_DISABLE_SHIFT + port); + + I915_WRITE(DISPIO_CR_TX_BMU_CR0, reg); +} + +static void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, + enum port port, int type) { struct drm_i915_private *dev_priv = dev->dev_private; const struct bxt_ddi_buf_trans *ddi_translations; @@ -1944,6 +2156,73 @@ void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val); } +static uint32_t translate_signal_level(int signal_levels) +{ + uint32_t level; + + switch (signal_levels) { + default: + DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level: 0x%x\n", + signal_levels); + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 0; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: + level = 1; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: + level = 2; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: + level = 3; + break; + + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 4; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: + level = 5; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: + level = 6; + break; + + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 7; + break; + case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: + level = 8; + break; + + case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: + level = 9; + break; + } + + return level; +} + +uint32_t ddi_signal_levels(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dport = dp_to_dig_port(intel_dp); + struct drm_device *dev = dport->base.base.dev; + struct intel_encoder *encoder = &dport->base; + uint8_t train_set = intel_dp->train_set[0]; + int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | + DP_TRAIN_PRE_EMPHASIS_MASK); + enum port port = dport->port; + uint32_t level; + + level = translate_signal_level(signal_levels); + + if (IS_SKYLAKE(dev)) + skl_ddi_set_iboost(dev, level, port, encoder->type); + else if (IS_BROXTON(dev)) + bxt_ddi_vswing_sequence(dev, level, port, encoder->type); + + return DDI_BUF_TRANS_SELECT(level); +} + static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c43bff90c47a..367f71224c96 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3424,92 +3424,6 @@ gen7_edp_signal_levels(uint8_t train_set) } } -/* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */ -static uint32_t -hsw_signal_levels(uint8_t train_set) -{ - int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | - DP_TRAIN_PRE_EMPHASIS_MASK); - switch (signal_levels) { - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return DDI_BUF_TRANS_SELECT(0); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return DDI_BUF_TRANS_SELECT(1); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: - return DDI_BUF_TRANS_SELECT(2); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: - return DDI_BUF_TRANS_SELECT(3); - - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return DDI_BUF_TRANS_SELECT(4); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return DDI_BUF_TRANS_SELECT(5); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: - return DDI_BUF_TRANS_SELECT(6); - - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return DDI_BUF_TRANS_SELECT(7); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: - return DDI_BUF_TRANS_SELECT(8); - - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: - return DDI_BUF_TRANS_SELECT(9); - default: - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" - "0x%x\n", signal_levels); - return DDI_BUF_TRANS_SELECT(0); - } -} - -static void bxt_signal_levels(struct intel_dp *intel_dp) -{ - struct intel_digital_port *dport = dp_to_dig_port(intel_dp); - enum port port = dport->port; - struct drm_device *dev = dport->base.base.dev; - struct intel_encoder *encoder = &dport->base; - uint8_t train_set = intel_dp->train_set[0]; - uint32_t level = 0; - - int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | - DP_TRAIN_PRE_EMPHASIS_MASK); - switch (signal_levels) { - default: - DRM_DEBUG_KMS("Unsupported voltage swing/pre-emph level\n"); - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: - level = 0; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1: - level = 1; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2: - level = 2; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3: - level = 3; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0: - level = 4; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1: - level = 5; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2: - level = 6; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0: - level = 7; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: - level = 8; - break; - case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0: - level = 9; - break; - } - - bxt_ddi_vswing_sequence(dev, level, port, encoder->type); -} - /* Properly updates "DP" with the correct signal levels. */ static void intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) @@ -3517,22 +3431,20 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); enum port port = intel_dig_port->port; struct drm_device *dev = intel_dig_port->base.base.dev; - uint32_t signal_levels, mask; + uint32_t signal_levels, mask = 0; uint8_t train_set = intel_dp->train_set[0]; - if (IS_BROXTON(dev)) { - signal_levels = 0; - bxt_signal_levels(intel_dp); - mask = 0; - } else if (HAS_DDI(dev)) { - signal_levels = hsw_signal_levels(train_set); - mask = DDI_BUF_EMP_MASK; + if (HAS_DDI(dev)) { + signal_levels = ddi_signal_levels(intel_dp); + + if (IS_BROXTON(dev)) + signal_levels = 0; + else + mask = DDI_BUF_EMP_MASK; } else if (IS_CHERRYVIEW(dev)) { signal_levels = chv_signal_levels(intel_dp); - mask = 0; } else if (IS_VALLEYVIEW(dev)) { signal_levels = vlv_signal_levels(intel_dp); - mask = 0; } else if (IS_GEN7(dev) && port == PORT_A) { signal_levels = gen7_edp_signal_levels(train_set); mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7f2e204b9fb5..bb52620a3ce8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -968,8 +968,7 @@ void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder); void intel_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state); -void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level, - enum port port, int type); +uint32_t ddi_signal_levels(struct intel_dp *intel_dp); /* intel_frontbuffer.c */ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, -- cgit v1.2.3-70-g09d2 From 05712c1561041d102d3cac7d7e79548b1446caa4 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 18 Jun 2015 17:25:54 +0300 Subject: drm/i915/bxt: add missing DDI PLL registers to the state checking Although we have a fixed setting for the PLL9 and EBB4 registers, it still makes sense to check them together with the rest of PLL registers. While at it also remove a redundant comment about 10 bit clock enabling. Signed-off-by: Imre Deak Reviewed-by: Sonika Jindal Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_reg.h | 3 ++- drivers/gpu/drm/i915/intel_ddi.c | 16 +++++++++++++--- drivers/gpu/drm/i915/intel_display.c | 6 ++++-- 4 files changed, 21 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 64041e788a1c..1dbd95710bf4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -372,7 +372,8 @@ struct intel_dpll_hw_state { uint32_t cfgcr1, cfgcr2; /* bxt */ - uint32_t ebb0, pll0, pll1, pll2, pll3, pll6, pll8, pll10, pcsdw12; + uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, + pcsdw12; }; struct intel_shared_dpll_config { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bdef9f7b629e..4d8ef2de4374 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1208,7 +1208,8 @@ enum skl_disp_power_wells { /* PORT_PLL_8_A */ #define PORT_PLL_TARGET_CNT_MASK 0x3FF /* PORT_PLL_9_A */ -#define PORT_PLL_LOCK_THRESHOLD_MASK 0xe +#define PORT_PLL_LOCK_THRESHOLD_SHIFT 1 +#define PORT_PLL_LOCK_THRESHOLD_MASK (0x7 << PORT_PLL_LOCK_THRESHOLD_SHIFT) /* PORT_PLL_10_A */ #define PORT_PLL_DCO_AMP_OVR_EN_H (1<<27) #define PORT_PLL_DCO_AMP_MASK 0x3c00 diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index b29d103bd706..cf2896da8ad8 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1722,11 +1722,15 @@ bxt_ddi_pll_select(struct intel_crtc *intel_crtc, crtc_state->dpll_hw_state.pll8 = targ_cnt; + crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT; + if (dcoampovr_en_h) crtc_state->dpll_hw_state.pll10 = PORT_PLL_DCO_AMP_OVR_EN_H; crtc_state->dpll_hw_state.pll10 |= PORT_PLL_DCO_AMP(dco_amp); + crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE; + crtc_state->dpll_hw_state.pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger; @@ -2767,7 +2771,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, temp = I915_READ(BXT_PORT_PLL(port, 9)); temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK; - temp |= (5 << 1); + temp |= pll->config.hw_state.pll9; I915_WRITE(BXT_PORT_PLL(port, 9), temp); temp = I915_READ(BXT_PORT_PLL(port, 10)); @@ -2780,8 +2784,8 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); temp |= PORT_PLL_RECALIBRATE; I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); - /* Enable 10 bit clock */ - temp |= PORT_PLL_10BIT_CLK_ENABLE; + temp &= ~PORT_PLL_10BIT_CLK_ENABLE; + temp |= pll->config.hw_state.ebb4; I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); /* Enable PLL */ @@ -2832,12 +2836,18 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, return false; hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port)); + hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port)); + hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE; + hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0)); hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1)); hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2)); hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3)); hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6)); hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8)); + hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9)); + hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK; + hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10)); /* * While we write to the group register to program all lanes at once we diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b7d42e6aac10..6be876845931 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12012,17 +12012,19 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide); if (IS_BROXTON(dev)) { - DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: ebb0: 0x%x, " + DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x," "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, " - "pll6: 0x%x, pll8: 0x%x, pcsdw12: 0x%x\n", + "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pcsdw12: 0x%x\n", pipe_config->ddi_pll_sel, pipe_config->dpll_hw_state.ebb0, + pipe_config->dpll_hw_state.ebb4, pipe_config->dpll_hw_state.pll0, pipe_config->dpll_hw_state.pll1, pipe_config->dpll_hw_state.pll2, pipe_config->dpll_hw_state.pll3, pipe_config->dpll_hw_state.pll6, pipe_config->dpll_hw_state.pll8, + pipe_config->dpll_hw_state.pll9, pipe_config->dpll_hw_state.pcsdw12); } else if (IS_SKYLAKE(dev)) { DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: " -- cgit v1.2.3-70-g09d2 From aa610dcb7c1999fe3353562340a72196d9a54ae0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 22 Jun 2015 23:35:52 +0300 Subject: drm/i915/bxt: add DDI port HW readout support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for reading out the HW state for DDI ports. Since the actual programming is very similar to the CHV/VLV DPIO PLL programming we can reuse much of the logic from there. This fixes the state checker failures I saw on my BXT with HDMI output. v2: - rebased on v2 of patch 4/5 Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 15 +++++++++------ drivers/gpu/drm/i915/intel_ddi.c | 22 ++++++++++++++++++++-- 2 files changed, 29 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4d8ef2de4374..42ba1ef641d8 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1170,10 +1170,12 @@ enum skl_disp_power_wells { #define _PORT_PLL_EBB_0_A 0x162034 #define _PORT_PLL_EBB_0_B 0x6C034 #define _PORT_PLL_EBB_0_C 0x6C340 -#define PORT_PLL_P1_MASK (0x07 << 13) -#define PORT_PLL_P1(x) ((x) << 13) -#define PORT_PLL_P2_MASK (0x1f << 8) -#define PORT_PLL_P2(x) ((x) << 8) +#define PORT_PLL_P1_SHIFT 13 +#define PORT_PLL_P1_MASK (0x07 << PORT_PLL_P1_SHIFT) +#define PORT_PLL_P1(x) ((x) << PORT_PLL_P1_SHIFT) +#define PORT_PLL_P2_SHIFT 8 +#define PORT_PLL_P2_MASK (0x1f << PORT_PLL_P2_SHIFT) +#define PORT_PLL_P2(x) ((x) << PORT_PLL_P2_SHIFT) #define BXT_PORT_PLL_EBB_0(port) _PORT3(port, _PORT_PLL_EBB_0_A, \ _PORT_PLL_EBB_0_B, \ _PORT_PLL_EBB_0_C) @@ -1193,8 +1195,9 @@ enum skl_disp_power_wells { /* PORT_PLL_0_A */ #define PORT_PLL_M2_MASK 0xFF /* PORT_PLL_1_A */ -#define PORT_PLL_N_MASK (0x0F << 8) -#define PORT_PLL_N(x) ((x) << 8) +#define PORT_PLL_N_SHIFT 8 +#define PORT_PLL_N_MASK (0x0F << PORT_PLL_N_SHIFT) +#define PORT_PLL_N(x) ((x) << PORT_PLL_N_SHIFT) /* PORT_PLL_2_A */ #define PORT_PLL_M2_FRAC_MASK 0x3FFFFF /* PORT_PLL_3_A */ diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index cf2896da8ad8..cef9709fa2ba 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1140,8 +1140,26 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder, static int bxt_calc_pll_link(struct drm_i915_private *dev_priv, enum intel_dpll_id dpll) { - /* FIXME formula not available in bspec */ - return 0; + struct intel_shared_dpll *pll; + struct intel_dpll_hw_state *state; + intel_clock_t clock; + + /* For DDI ports we always use a shared PLL. */ + if (WARN_ON(dpll == DPLL_ID_PRIVATE)) + return 0; + + pll = &dev_priv->shared_dplls[dpll]; + state = &pll->config.hw_state; + + clock.m1 = 2; + clock.m2 = (state->pll0 & PORT_PLL_M2_MASK) << 22; + if (state->pll3 & PORT_PLL_M2_FRAC_ENABLE) + clock.m2 |= state->pll2 & PORT_PLL_M2_FRAC_MASK; + clock.n = (state->pll1 & PORT_PLL_N_MASK) >> PORT_PLL_N_SHIFT; + clock.p1 = (state->ebb0 & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT; + clock.p2 = (state->ebb0 & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT; + + return chv_calc_dpll_params(100000, &clock); } static void bxt_ddi_clock_get(struct intel_encoder *encoder, -- cgit v1.2.3-70-g09d2 From 793dfa59bcfde9d642295480674926827e9adcfc Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 18 Jun 2015 17:25:53 +0300 Subject: drm/i915/bxt: mask off the DPLL state checker bits we don't program For the purpose of state checking we only care about the DPLL HW flags that we actually program, so mask off the ones that we don't. This fixes one set of DPLL state check failures. Signed-off-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index cef9709fa2ba..15fc66a8da78 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2854,19 +2854,38 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, return false; hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port)); + hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK; + hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port)); hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE; hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0)); + hw_state->pll0 &= PORT_PLL_M2_MASK; + hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1)); + hw_state->pll1 &= PORT_PLL_N_MASK; + hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2)); + hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK; + hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3)); + hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE; + hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6)); + hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK | + PORT_PLL_INT_COEFF_MASK | + PORT_PLL_GAIN_CTL_MASK; + hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8)); + hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK; + hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9)); hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK; hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10)); + hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H | + PORT_PLL_DCO_AMP_MASK; + /* * While we write to the group register to program all lanes at once we * can read only lane registers. We configure all lanes the same way, so @@ -2877,6 +2896,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n", hw_state->pcsdw12, I915_READ(BXT_PORT_PCS_DW12_LN23(port))); + hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD; return true; } -- cgit v1.2.3-70-g09d2 From 398a017e91d1518e303886398b15b1851c3d902c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 30 Jun 2015 15:33:51 +0300 Subject: drm/i915: Fix HDMI 12bpc and pixel repeat clock readout for DDI platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Take the HDMI 12bpc mode and pixel repeat into account when extracting the dotclock from the hardware on DDI platforms. Tested on HSW only. Signed-off-by: Ville Syrjälä Reviewed-and-tested-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 49 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 25 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 15fc66a8da78..e7f0379453e8 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1027,6 +1027,26 @@ static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv, return dco_freq / (p0 * p1 * p2 * 5); } +static void ddi_dotclock_get(struct intel_crtc_state *pipe_config) +{ + int dotclock; + + if (pipe_config->has_pch_encoder) + dotclock = intel_dotclock_calculate(pipe_config->port_clock, + &pipe_config->fdi_m_n); + else if (pipe_config->has_dp_encoder) + dotclock = intel_dotclock_calculate(pipe_config->port_clock, + &pipe_config->dp_m_n); + else if (pipe_config->has_hdmi_sink && pipe_config->pipe_bpp == 36) + dotclock = pipe_config->port_clock * 2 / 3; + else + dotclock = pipe_config->port_clock; + + if (pipe_config->pixel_multiplier) + dotclock /= pipe_config->pixel_multiplier; + + pipe_config->base.adjusted_mode.crtc_clock = dotclock; +} static void skl_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) @@ -1073,12 +1093,7 @@ static void skl_ddi_clock_get(struct intel_encoder *encoder, pipe_config->port_clock = link_clock; - if (pipe_config->has_dp_encoder) - pipe_config->base.adjusted_mode.crtc_clock = - intel_dotclock_calculate(pipe_config->port_clock, - &pipe_config->dp_m_n); - else - pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; + ddi_dotclock_get(pipe_config); } static void hsw_ddi_clock_get(struct intel_encoder *encoder, @@ -1125,16 +1140,7 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder, pipe_config->port_clock = link_clock * 2; - if (pipe_config->has_pch_encoder) - pipe_config->base.adjusted_mode.crtc_clock = - intel_dotclock_calculate(pipe_config->port_clock, - &pipe_config->fdi_m_n); - else if (pipe_config->has_dp_encoder) - pipe_config->base.adjusted_mode.crtc_clock = - intel_dotclock_calculate(pipe_config->port_clock, - &pipe_config->dp_m_n); - else - pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; + ddi_dotclock_get(pipe_config); } static int bxt_calc_pll_link(struct drm_i915_private *dev_priv, @@ -1169,16 +1175,9 @@ static void bxt_ddi_clock_get(struct intel_encoder *encoder, enum port port = intel_ddi_get_encoder_port(encoder); uint32_t dpll = port; - pipe_config->port_clock = - bxt_calc_pll_link(dev_priv, dpll); + pipe_config->port_clock = bxt_calc_pll_link(dev_priv, dpll); - if (pipe_config->has_dp_encoder) - pipe_config->base.adjusted_mode.crtc_clock = - intel_dotclock_calculate(pipe_config->port_clock, - &pipe_config->dp_m_n); - else - pipe_config->base.adjusted_mode.crtc_clock = - pipe_config->port_clock; + ddi_dotclock_get(pipe_config); } void intel_ddi_clock_get(struct intel_encoder *encoder, -- cgit v1.2.3-70-g09d2 From e62925567c7926e78bc8ca976cde5c28ea265a49 Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Wed, 1 Jul 2015 17:02:57 +0530 Subject: drm/i915/bxt: BUNs related to port PLL This patch contains changes based on 2 updates to the spec: Port PLL VCO restriction raised up to 6700. Port PLL now needs DCO amp override enable for all VCO frequencies. v2: Sonika's review comment addressed - dcoampovr_en_h variable not required Based on a discussion with Siva, the following changes have been made. - replace dco_amp var with #define BXT_DCO_AMPLITUDE - set pll10 in a single assignment v3: Move DCO amplitude default value to i915_reg.h. Suggested by Siva. Signed-off-by: Vandana Kannan Reviewed-by: Sonika Jindal [v2] [danvet: Spell out BUN since not everyone knows what this means.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_ddi.c | 15 +++++---------- drivers/gpu/drm/i915/intel_display.c | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 42ba1ef641d8..ac8436fc6ced 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1215,6 +1215,7 @@ enum skl_disp_power_wells { #define PORT_PLL_LOCK_THRESHOLD_MASK (0x7 << PORT_PLL_LOCK_THRESHOLD_SHIFT) /* PORT_PLL_10_A */ #define PORT_PLL_DCO_AMP_OVR_EN_H (1<<27) +#define PORT_PLL_DCO_AMP_DEFAULT 15 #define PORT_PLL_DCO_AMP_MASK 0x3c00 #define PORT_PLL_DCO_AMP(x) (x<<10) #define _PORT_PLL_BASE(port) _PORT3(port, _PORT_PLL_0_A, \ diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index e7f0379453e8..db22f0173027 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1644,7 +1644,7 @@ bxt_ddi_pll_select(struct intel_crtc *intel_crtc, struct bxt_clk_div clk_div = {0}; int vco = 0; uint32_t prop_coef, int_coef, gain_ctl, targ_cnt; - uint32_t dcoampovr_en_h, dco_amp, lanestagger; + uint32_t lanestagger; if (intel_encoder->type == INTEL_OUTPUT_HDMI) { intel_clock_t best_clock; @@ -1683,9 +1683,7 @@ bxt_ddi_pll_select(struct intel_crtc *intel_crtc, vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2; } - dco_amp = 15; - dcoampovr_en_h = 0; - if (vco >= 6200000 && vco <= 6480000) { + if (vco >= 6200000 && vco <= 6700000) { prop_coef = 4; int_coef = 9; gain_ctl = 3; @@ -1696,8 +1694,6 @@ bxt_ddi_pll_select(struct intel_crtc *intel_crtc, int_coef = 11; gain_ctl = 3; targ_cnt = 9; - if (vco >= 4800000 && vco < 5400000) - dcoampovr_en_h = 1; } else if (vco == 5400000) { prop_coef = 3; int_coef = 8; @@ -1741,10 +1737,9 @@ bxt_ddi_pll_select(struct intel_crtc *intel_crtc, crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT; - if (dcoampovr_en_h) - crtc_state->dpll_hw_state.pll10 = PORT_PLL_DCO_AMP_OVR_EN_H; - - crtc_state->dpll_hw_state.pll10 |= PORT_PLL_DCO_AMP(dco_amp); + crtc_state->dpll_hw_state.pll10 = + PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT) + | PORT_PLL_DCO_AMP_OVR_EN_H; crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 724b0e3a5d37..5ba35bb8e1a5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -409,7 +409,7 @@ static const intel_limit_t intel_limits_chv = { static const intel_limit_t intel_limits_bxt = { /* FIXME: find real dot limits */ .dot = { .min = 0, .max = INT_MAX }, - .vco = { .min = 4800000, .max = 6480000 }, + .vco = { .min = 4800000, .max = 6700000 }, .n = { .min = 1, .max = 1 }, .m1 = { .min = 2, .max = 2 }, /* FIXME: find real m2 limits */ -- cgit v1.2.3-70-g09d2 From c30400fcffb70d17bbf33eaff5020b83111bd66c Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 3 Jul 2015 12:31:30 -0300 Subject: drm/i915: set FDI translations to NULL on SKL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/intel_ddi.c: In function ‘intel_prepare_ddi’: drivers/gpu/drm/i915/intel_ddi.c:517:6: warning: ‘ddi_translations_fdi’ may be used uninitialized in this function [-Wmaybe-uninitialized] if (ddi_translations_fdi) ^ drivers/gpu/drm/i915/intel_ddi.c:446:30: note: ‘ddi_translations_fdi’ was declared here const struct ddi_buf_trans *ddi_translations_fdi; ^ This line used to be there, but was removed by: commit f8896f5d58e64bfd3c2b5f7c5ba5c3f3967e93c7 Author: David Weinehall Date: Thu Jun 25 11:11:03 2015 +030 drm/i915/skl: Buffer translation improvements Cc: David Weinehall Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index db22f0173027..9a40bfb20e0c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -458,6 +458,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, INTEL_OUTPUT_HDMI); return; } else if (IS_SKYLAKE(dev)) { + ddi_translations_fdi = NULL; ddi_translations_dp = skl_get_buf_trans_dp(dev, &n_dp_entries); ddi_translations_edp = -- cgit v1.2.3-70-g09d2 From 500ea70d503ed9ba448611049a4a718c2761a5f2 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 7 Aug 2015 17:01:16 -0700 Subject: drm/i915: Set alternate aux for DDI-E There is no correspondent Aux channel for DDI-E. So we need to rely on VBT to let us know witch one is being used instead. v2: Removing some trailing spaces and giving proper credit to Xiong that added a nice way to avoid port conflicts by setting supports_dp = 0 when using equivalent aux for DDI-E. Credits-to: Xiong Zhang Signed-off-by: Rodrigo Vivi Reviewed-by: Xiong Zhang Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 7 +++++++ drivers/gpu/drm/i915/intel_bios.c | 23 +++++++++++++++++++---- drivers/gpu/drm/i915/intel_ddi.c | 5 ++--- drivers/gpu/drm/i915/intel_dp.c | 29 ++++++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4e9f7b16a729..a8ac36dbf24b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1409,6 +1409,11 @@ enum modeset_restore { MODESET_SUSPENDED, }; +#define DP_AUX_A 0x40 +#define DP_AUX_B 0x10 +#define DP_AUX_C 0x20 +#define DP_AUX_D 0x30 + struct ddi_vbt_port_info { /* * This is an index in the HDMI/DVI DDI buffer translation table. @@ -1421,6 +1426,8 @@ struct ddi_vbt_port_info { uint8_t supports_dvi:1; uint8_t supports_hdmi:1; uint8_t supports_dp:1; + + uint8_t alternate_aux_channel; }; enum psr_lines_to_wait { diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 2ff9eb00fdec..630d997c05a0 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -968,13 +968,28 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, } if (is_dp) { - if (aux_channel == 0x40 && port != PORT_A) + if (port == PORT_E) { + info->alternate_aux_channel = aux_channel; + /* if DDIE share aux channel with other port, then + * DP couldn't exist on the shared port. Otherwise + * they share the same aux channel and system + * couldn't communicate with them seperately. */ + if (aux_channel == DP_AUX_A) + dev_priv->vbt.ddi_port_info[PORT_A].supports_dp = 0; + else if (aux_channel == DP_AUX_B) + dev_priv->vbt.ddi_port_info[PORT_B].supports_dp = 0; + else if (aux_channel == DP_AUX_C) + dev_priv->vbt.ddi_port_info[PORT_C].supports_dp = 0; + else if (aux_channel == DP_AUX_D) + dev_priv->vbt.ddi_port_info[PORT_D].supports_dp = 0; + } + else if (aux_channel == DP_AUX_A && port != PORT_A) DRM_DEBUG_KMS("Unexpected AUX channel for port A\n"); - if (aux_channel == 0x10 && port != PORT_B) + else if (aux_channel == DP_AUX_B && port != PORT_B) DRM_DEBUG_KMS("Unexpected AUX channel for port B\n"); - if (aux_channel == 0x20 && port != PORT_C) + else if (aux_channel == DP_AUX_C && port != PORT_C) DRM_DEBUG_KMS("Unexpected AUX channel for port C\n"); - if (aux_channel == 0x30 && port != PORT_D) + else if (aux_channel == DP_AUX_D && port != PORT_D) DRM_DEBUG_KMS("Unexpected AUX channel for port D\n"); } diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 9a40bfb20e0c..110d5469c86c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3184,10 +3184,9 @@ void intel_ddi_init(struct drm_device *dev, enum port port) dev_priv->vbt.ddi_port_info[port].supports_hdmi); init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp; if (!init_dp && !init_hdmi) { - DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, assuming it is\n", + DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, respect it\n", port_name(port)); - init_hdmi = true; - init_dp = true; + return; } intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7eabd1175a07..f3133d81fb9d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1033,11 +1033,34 @@ static void intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) { struct drm_device *dev = intel_dp_to_dev(intel_dp); + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); enum port port = intel_dig_port->port; + struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; const char *name = NULL; + uint32_t porte_aux_ctl_reg = DPA_AUX_CH_CTL; int ret; + /* On SKL we don't have Aux for port E so we rely on VBT to set + * a proper alternate aux channel. + */ + if (IS_SKYLAKE(dev) && port == PORT_E) { + switch (info->alternate_aux_channel) { + case DP_AUX_B: + porte_aux_ctl_reg = DPB_AUX_CH_CTL; + break; + case DP_AUX_C: + porte_aux_ctl_reg = DPC_AUX_CH_CTL; + break; + case DP_AUX_D: + porte_aux_ctl_reg = DPD_AUX_CH_CTL; + break; + case DP_AUX_A: + default: + porte_aux_ctl_reg = DPA_AUX_CH_CTL; + } + } + switch (port) { case PORT_A: intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL; @@ -1055,6 +1078,10 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL; name = "DPDDC-D"; break; + case PORT_E: + intel_dp->aux_ch_ctl_reg = porte_aux_ctl_reg; + name = "DPDDC-E"; + break; default: BUG(); } @@ -1068,7 +1095,7 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) * * Skylake moves AUX_CTL back next to DDI_BUF_CTL, on the CPU. */ - if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) + if (!IS_HASWELL(dev) && !IS_BROADWELL(dev) && port != PORT_E) intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10; intel_dp->aux.name = name; -- cgit v1.2.3-70-g09d2 From 75067ddecf21271631bc018d2fb23ddd09b66aae Mon Sep 17 00:00:00 2001 From: Antti Koskipaa Date: Fri, 10 Jul 2015 14:10:55 +0300 Subject: drm/i915: Per-DDI I_boost override An OEM may request increased I_boost beyond the recommended values by specifying an I_boost value to be applied to all swing entries for a port. These override values are specified in VBT. v2: rebase and remove unused iboost_bit variable Issue: VIZ-5676 Signed-off-by: Antti Koskipaa Reviewed-by: David Weinehall Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/intel_bios.c | 21 +++++++++++++++++++++ drivers/gpu/drm/i915/intel_bios.h | 9 +++++++++ drivers/gpu/drm/i915/intel_ddi.c | 38 ++++++++++++++++++++++++++++++-------- 4 files changed, 63 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 01abe13e98e0..4273c281ce77 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1429,6 +1429,9 @@ struct ddi_vbt_port_info { uint8_t supports_dp:1; uint8_t alternate_aux_channel; + + uint8_t dp_boost_level; + uint8_t hdmi_boost_level; }; enum psr_lines_to_wait { diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 990acc20771a..8e46149bafdd 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -886,6 +886,17 @@ err: memset(dev_priv->vbt.dsi.sequence, 0, sizeof(dev_priv->vbt.dsi.sequence)); } +static u8 translate_iboost(u8 val) +{ + static const u8 mapping[] = { 1, 3, 7 }; /* See VBT spec */ + + if (val >= ARRAY_SIZE(mapping)) { + DRM_DEBUG_KMS("Unsupported I_boost value found in VBT (%d), display may not work properly\n", val); + return 0; + } + return mapping[val]; +} + static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, const struct bdb_header *bdb) { @@ -1001,6 +1012,16 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, hdmi_level_shift); info->hdmi_level_shift = hdmi_level_shift; } + + /* Parse the I_boost config for SKL and above */ + if (bdb->version >= 196 && (child->common.flags_1 & IBOOST_ENABLE)) { + info->dp_boost_level = translate_iboost(child->common.iboost_level & 0xF); + DRM_DEBUG_KMS("VBT (e)DP boost level for port %c: %d\n", + port_name(port), info->dp_boost_level); + info->hdmi_boost_level = translate_iboost(child->common.iboost_level >> 4); + DRM_DEBUG_KMS("VBT HDMI boost level for port %c: %d\n", + port_name(port), info->hdmi_boost_level); + } } static void parse_ddi_ports(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index f7ad6a585129..6d909efbf43f 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -231,6 +231,10 @@ struct old_child_dev_config { /* This one contains field offsets that are known to be common for all BDB * versions. Notice that the meaning of the contents contents may still change, * but at least the offsets are consistent. */ + +/* Definitions for flags_1 */ +#define IBOOST_ENABLE (1<<3) + struct common_child_dev_config { u16 handle; u16 device_type; @@ -239,8 +243,13 @@ struct common_child_dev_config { u8 not_common2[2]; u8 ddc_pin; u16 edid_ptr; + u8 obsolete; + u8 flags_1; + u8 not_common3[13]; + u8 iboost_level; } __packed; + /* This field changes depending on the BDB version, so the most reliable way to * read it is by checking the BDB version and reading the raw pointer. */ union child_device_config { diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 110d5469c86c..6cfe65d6a8cf 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -440,6 +440,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, { struct drm_i915_private *dev_priv = dev->dev_private; u32 reg; + u32 iboost_bit = 0; int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry, size; int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; @@ -466,6 +467,10 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, ddi_translations_hdmi = skl_get_buf_trans_hdmi(dev, &n_hdmi_entries); hdmi_default_entry = 8; + /* If we're boosting the current, set bit 31 of trans1 */ + if (dev_priv->vbt.ddi_port_info[port].hdmi_boost_level || + dev_priv->vbt.ddi_port_info[port].dp_boost_level) + iboost_bit = 1<<31; } else if (IS_BROADWELL(dev)) { ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_dp = bdw_ddi_translations_dp; @@ -526,7 +531,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, } for (i = 0, reg = DDI_BUF_TRANS(port); i < size; i++) { - I915_WRITE(reg, ddi_translations[i].trans1); + I915_WRITE(reg, ddi_translations[i].trans1 | iboost_bit); reg += 4; I915_WRITE(reg, ddi_translations[i].trans2); reg += 4; @@ -541,7 +546,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, hdmi_level = hdmi_default_entry; /* Entry 9 is for HDMI: */ - I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans1); + I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit); reg += 4; I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans2); reg += 4; @@ -2078,18 +2083,35 @@ static void skl_ddi_set_iboost(struct drm_device *dev, u32 level, struct drm_i915_private *dev_priv = dev->dev_private; const struct ddi_buf_trans *ddi_translations; uint8_t iboost; + uint8_t dp_iboost, hdmi_iboost; int n_entries; u32 reg; + /* VBT may override standard boost values */ + dp_iboost = dev_priv->vbt.ddi_port_info[port].dp_boost_level; + hdmi_iboost = dev_priv->vbt.ddi_port_info[port].hdmi_boost_level; + if (type == INTEL_OUTPUT_DISPLAYPORT) { - ddi_translations = skl_get_buf_trans_dp(dev, &n_entries); - iboost = ddi_translations[port].i_boost; + if (dp_iboost) { + iboost = dp_iboost; + } else { + ddi_translations = skl_get_buf_trans_dp(dev, &n_entries); + iboost = ddi_translations[port].i_boost; + } } else if (type == INTEL_OUTPUT_EDP) { - ddi_translations = skl_get_buf_trans_edp(dev, &n_entries); - iboost = ddi_translations[port].i_boost; + if (dp_iboost) { + iboost = dp_iboost; + } else { + ddi_translations = skl_get_buf_trans_edp(dev, &n_entries); + iboost = ddi_translations[port].i_boost; + } } else if (type == INTEL_OUTPUT_HDMI) { - ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries); - iboost = ddi_translations[port].i_boost; + if (hdmi_iboost) { + iboost = hdmi_iboost; + } else { + ddi_translations = skl_get_buf_trans_hdmi(dev, &n_entries); + iboost = ddi_translations[port].i_boost; + } } else { return; } -- cgit v1.2.3-70-g09d2 From 5f8b253147c27b8244451ee28aeb3429c5aa2e52 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 24 Aug 2015 16:48:44 -0700 Subject: drm/i915/skl: Update DDI buffer translation programming. SKL-Y can now use the same programming for all VccIO values after an adjustment to I_boost. SKL-U DP table adjustments. 1. Remove SKL Y 0.95V from "SKL H and S" columns in all tables. The other SKL Y column removes the "0.85V VccIO" so it now applies to all voltages. 2. DP table changes SKL U 400mV+0db dword 0 value from 2016h to 201Bh. 3. DP table changes SKL U 600mv+0db dword 0 value from 2016h to 201Bh. 4. DP table increases I_boost to level 3 for SKL Y 400mv+9.5db. v2: Fix compilation warnings as pointed by Paulo. Reference: Graphics Spec Change r97962 Cc: Arthur Runyan Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni [Jani: reformatted commit message for shorter lines.] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_ddi.c | 75 ++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 50 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 6cfe65d6a8cf..19004557c868 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -128,7 +128,7 @@ static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = { { 0x80FFFFFF, 0x001B0002, 0x0 },/* 9: 1000 1000 0 */ }; -/* Skylake H, S, and Skylake Y with 0.95V VccIO */ +/* Skylake H and S */ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { { 0x00002016, 0x000000A0, 0x0 }, { 0x00005012, 0x0000009B, 0x0 }, @@ -143,23 +143,23 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { /* Skylake U */ static const struct ddi_buf_trans skl_u_ddi_translations_dp[] = { - { 0x00002016, 0x000000A2, 0x0 }, + { 0x0000201B, 0x000000A2, 0x0 }, { 0x00005012, 0x00000088, 0x0 }, { 0x00007011, 0x00000087, 0x0 }, - { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ - { 0x00002016, 0x0000009D, 0x0 }, + { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost level 0x1 */ + { 0x0000201B, 0x0000009D, 0x0 }, { 0x00005012, 0x000000C7, 0x0 }, { 0x00007011, 0x000000C7, 0x0 }, { 0x00002016, 0x00000088, 0x0 }, { 0x00005012, 0x000000C7, 0x0 }, }; -/* Skylake Y with 0.85V VccIO */ -static const struct ddi_buf_trans skl_y_085v_ddi_translations_dp[] = { +/* Skylake Y */ +static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = { { 0x00000018, 0x000000A2, 0x0 }, { 0x00005012, 0x00000088, 0x0 }, { 0x00007011, 0x00000087, 0x0 }, - { 0x80009010, 0x000000C7, 0x1 }, /* Uses I_boost */ + { 0x80009010, 0x000000C7, 0x3 }, /* Uses I_boost level 0x3 */ { 0x00000018, 0x0000009D, 0x0 }, { 0x00005012, 0x000000C7, 0x0 }, { 0x00007011, 0x000000C7, 0x0 }, @@ -168,7 +168,7 @@ static const struct ddi_buf_trans skl_y_085v_ddi_translations_dp[] = { }; /* - * Skylake H and S, and Skylake Y with 0.95V VccIO + * Skylake H and S * eDP 1.4 low vswing translation parameters */ static const struct ddi_buf_trans skl_ddi_translations_edp[] = { @@ -202,10 +202,10 @@ static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { }; /* - * Skylake Y with 0.95V VccIO + * Skylake Y * eDP 1.4 low vswing translation parameters */ -static const struct ddi_buf_trans skl_y_085v_ddi_translations_edp[] = { +static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = { { 0x00000018, 0x000000A8, 0x0 }, { 0x00004013, 0x000000AB, 0x0 }, { 0x00007011, 0x000000A4, 0x0 }, @@ -218,7 +218,7 @@ static const struct ddi_buf_trans skl_y_085v_ddi_translations_edp[] = { { 0x00000018, 0x0000008A, 0x0 }, }; -/* Skylake H, S and U, and Skylake Y with 0.95V VccIO */ +/* Skylake U, H and S */ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { { 0x00000018, 0x000000AC, 0x0 }, { 0x00005012, 0x0000009D, 0x0 }, @@ -233,8 +233,8 @@ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { { 0x00000018, 0x000000C7, 0x0 }, }; -/* Skylake Y with 0.85V VccIO */ -static const struct ddi_buf_trans skl_y_085v_ddi_translations_hdmi[] = { +/* Skylake Y */ +static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = { { 0x00000018, 0x000000A1, 0x0 }, { 0x00005012, 0x000000DF, 0x0 }, { 0x00007011, 0x00000084, 0x0 }, @@ -244,7 +244,7 @@ static const struct ddi_buf_trans skl_y_085v_ddi_translations_hdmi[] = { { 0x00006013, 0x000000C7, 0x0 }, { 0x00000018, 0x0000008A, 0x0 }, { 0x00003015, 0x000000C7, 0x0 }, /* Default */ - { 0x80003015, 0x000000C7, 0x7 }, /* Uses I_boost */ + { 0x80003015, 0x000000C7, 0x7 }, /* Uses I_boost level 0x7 */ { 0x00000018, 0x000000C7, 0x0 }, }; @@ -335,19 +335,11 @@ intel_dig_port_supports_hdmi(const struct intel_digital_port *intel_dig_port) static const struct ddi_buf_trans *skl_get_buf_trans_dp(struct drm_device *dev, int *n_entries) { - struct drm_i915_private *dev_priv = dev->dev_private; const struct ddi_buf_trans *ddi_translations; - static int is_095v = -1; - - if (is_095v == -1) { - u32 spr1 = I915_READ(UAIMI_SPR1); - - is_095v = spr1 & SKL_VCCIO_MASK; - } - if (IS_SKL_ULX(dev) && !is_095v) { - ddi_translations = skl_y_085v_ddi_translations_dp; - *n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_dp); + if (IS_SKL_ULX(dev)) { + ddi_translations = skl_y_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); } else if (IS_SKL_ULT(dev)) { ddi_translations = skl_u_ddi_translations_dp; *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); @@ -364,23 +356,14 @@ static const struct ddi_buf_trans *skl_get_buf_trans_edp(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; const struct ddi_buf_trans *ddi_translations; - static int is_095v = -1; - - if (is_095v == -1) { - u32 spr1 = I915_READ(UAIMI_SPR1); - is_095v = spr1 & SKL_VCCIO_MASK; - } - - if (IS_SKL_ULX(dev) && !is_095v) { + if (IS_SKL_ULX(dev)) { if (dev_priv->edp_low_vswing) { - ddi_translations = skl_y_085v_ddi_translations_edp; - *n_entries = - ARRAY_SIZE(skl_y_085v_ddi_translations_edp); + ddi_translations = skl_y_ddi_translations_edp; + *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp); } else { - ddi_translations = skl_y_085v_ddi_translations_dp; - *n_entries = - ARRAY_SIZE(skl_y_085v_ddi_translations_dp); + ddi_translations = skl_y_ddi_translations_dp; + *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); } } else if (IS_SKL_ULT(dev)) { if (dev_priv->edp_low_vswing) { @@ -407,19 +390,11 @@ static const struct ddi_buf_trans * skl_get_buf_trans_hdmi(struct drm_device *dev, int *n_entries) { - struct drm_i915_private *dev_priv = dev->dev_private; const struct ddi_buf_trans *ddi_translations; - static int is_095v = -1; - - if (is_095v == -1) { - u32 spr1 = I915_READ(UAIMI_SPR1); - - is_095v = spr1 & SKL_VCCIO_MASK; - } - if (IS_SKL_ULX(dev) && !is_095v) { - ddi_translations = skl_y_085v_ddi_translations_hdmi; - *n_entries = ARRAY_SIZE(skl_y_085v_ddi_translations_hdmi); + if (IS_SKL_ULX(dev)) { + ddi_translations = skl_y_ddi_translations_hdmi; + *n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi); } else { ddi_translations = skl_ddi_translations_hdmi; *n_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); -- cgit v1.2.3-70-g09d2 From 7e6313a2516dbcd168f4ae36f0abe1a9227106b5 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 11 Aug 2015 20:21:46 +0300 Subject: drm/i915: Don't use link_bw for PLL setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use port_clock instead of link_bw when picking the PLL parameters for DP. link_bw may be zero with an eDP 1.4 sink that supports DP_LINK_RATE_SET so we shouldn't use it for anything other than feed it to the sink appropriately. v2: Fix typo in commit message (Sivakumar) Reviewed-by: Sivakumar Thulasimani Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter [Jani: cherry-picked from future.] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_ddi.c | 11 ++++------ drivers/gpu/drm/i915/intel_dp.c | 44 ++++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 29 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ddi.c') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 19004557c868..61575f67a626 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1554,17 +1554,14 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | wrpll_params.central_freq; } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) { - struct drm_encoder *encoder = &intel_encoder->base; - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - - switch (intel_dp->link_bw) { - case DP_LINK_BW_1_62: + switch (crtc_state->port_clock / 2) { + case 81000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0); break; - case DP_LINK_BW_2_7: + case 135000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0); break; - case DP_LINK_BW_5_4: + case 270000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0); break; } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 32663b1933f1..ef345d56f5cd 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -48,28 +48,28 @@ #define INTEL_DP_RESOLUTION_FAILSAFE (3 << INTEL_DP_RESOLUTION_SHIFT_MASK) struct dp_link_dpll { - int link_bw; + int clock; struct dpll dpll; }; static const struct dp_link_dpll gen4_dpll[] = { - { DP_LINK_BW_1_62, + { 162000, { .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } }, - { DP_LINK_BW_2_7, + { 270000, { .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } } }; static const struct dp_link_dpll pch_dpll[] = { - { DP_LINK_BW_1_62, + { 162000, { .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } }, - { DP_LINK_BW_2_7, + { 270000, { .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } } }; static const struct dp_link_dpll vlv_dpll[] = { - { DP_LINK_BW_1_62, + { 162000, { .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } }, - { DP_LINK_BW_2_7, + { 270000, { .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } } }; @@ -83,11 +83,11 @@ static const struct dp_link_dpll chv_dpll[] = { * m2 is stored in fixed point format using formula below * (m2_int << 22) | m2_fraction */ - { DP_LINK_BW_1_62, /* m2_int = 32, m2_fraction = 1677722 */ + { 162000, /* m2_int = 32, m2_fraction = 1677722 */ { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } }, - { DP_LINK_BW_2_7, /* m2_int = 27, m2_fraction = 0 */ + { 270000, /* m2_int = 27, m2_fraction = 0 */ { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }, - { DP_LINK_BW_5_4, /* m2_int = 27, m2_fraction = 0 */ + { 540000, /* m2_int = 27, m2_fraction = 0 */ { .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } } }; @@ -1130,7 +1130,7 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector) } static void -skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock) +skl_edp_set_pll_config(struct intel_crtc_state *pipe_config) { u32 ctrl1; @@ -1142,7 +1142,7 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock) pipe_config->dpll_hw_state.cfgcr2 = 0; ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0); - switch (link_clock / 2) { + switch (pipe_config->port_clock / 2) { case 81000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0); @@ -1176,19 +1176,19 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config, int link_clock) } static void -hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config, int link_bw) +hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config) { memset(&pipe_config->dpll_hw_state, 0, sizeof(pipe_config->dpll_hw_state)); - switch (link_bw) { - case DP_LINK_BW_1_62: + switch (pipe_config->port_clock / 2) { + case 81000: pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810; break; - case DP_LINK_BW_2_7: + case 135000: pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350; break; - case DP_LINK_BW_5_4: + case 270000: pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700; break; } @@ -1245,7 +1245,7 @@ intel_dp_source_rates(struct drm_device *dev, const int **source_rates) static void intel_dp_set_clock(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, int link_bw) + struct intel_crtc_state *pipe_config) { struct drm_device *dev = encoder->base.dev; const struct dp_link_dpll *divisor = NULL; @@ -1267,7 +1267,7 @@ intel_dp_set_clock(struct intel_encoder *encoder, if (divisor && count) { for (i = 0; i < count; i++) { - if (link_bw == divisor[i].link_bw) { + if (pipe_config->port_clock == divisor[i].clock) { pipe_config->dpll = divisor[i].dpll; pipe_config->clock_set = true; break; @@ -1544,13 +1544,13 @@ found: } if (IS_SKYLAKE(dev) && is_edp(intel_dp)) - skl_edp_set_pll_config(pipe_config, common_rates[clock]); + skl_edp_set_pll_config(pipe_config); else if (IS_BROXTON(dev)) /* handled in ddi */; else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) - hsw_dp_set_ddi_pll_sel(pipe_config, intel_dp->link_bw); + hsw_dp_set_ddi_pll_sel(pipe_config); else - intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); + intel_dp_set_clock(encoder, pipe_config); return true; } -- cgit v1.2.3-70-g09d2