From 9a86cda07af2c63649932f0a4fc757701ef54c42 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 27 Mar 2017 14:33:25 +0300 Subject: [PATCH] drm/i915/dp: reduce link M/N parameters MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Several major vendor USB-C->HDMI converters, in particular the DA200, fail to recover a 5.4 GHz 1 lane signal if the link N is greater than 0x80000. The link M and N depend on the pixel clock and link clock ratio. With current code link N exceeds 0x80000 only when link clock >= 540000 kHz. Except for the eDP intermediate link clocks, at least the four least significant bits are always zero. Just one bit shift right would be enough to bring even the DP 1.4 810000 kHz link clock under 0x80000 link N. The pixel clock for modes that require a link clock >= 540000 kHz would also have several least significant bits zero. Unless the user provides a mode with an odd pixel clock value, we can reduce the numbers to reach the goal, with no loss in precision. The DP spec even mentions sources making choices that "allow for static and relatively small Mvid and Nvid values", thus reducing the link M/N regardless of the sink in question seems justified. Everything here is based on the work and information gathered by Clint Taylor . This is just an iteration to reduce the parameters regardless of lane count, link rate, or sink. Reference: http://patchwork.freedesktop.org/patch/msgid/1490225256-11667-1-git-send-email-clinton.a.taylor@intel.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93578 Tested-by: Mads Tested-by: PJ Tested-by: François Guerraz Tested-by: Lev Popov Tested-by: Igor Krivenko Tested-by: Clint Taylor Reviewed-by: Clint Taylor Reviewed-by: Dhinakaran Pandiyan Acked-by: Daniel Vetter Cc: Clint Taylor Cc: Anusha Srivatsa Cc: Ville Syrjälä Cc: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1490614405-23337-1-git-send-email-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_display.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 20fb8dd13184..654b8a0c28ee 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6290,6 +6290,17 @@ intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den) static void compute_m_n(unsigned int m, unsigned int n, uint32_t *ret_m, uint32_t *ret_n) { + /* + * Reduce M/N as much as possible without loss in precision. Several DP + * dongles in particular seem to be fussy about too large *link* M/N + * values. The passed in values are more likely to have the least + * significant bits zero than M after rounding below, so do this first. + */ + while ((m & 1) == 0 && (n & 1) == 0) { + m >>= 1; + n >>= 1; + } + *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX); *ret_m = div_u64((uint64_t) m * *ret_n, n); intel_reduce_m_n_ratio(ret_m, ret_n); -- 2.39.2