Commit 7d267f06 authored by Tomi Valkeinen's avatar Tomi Valkeinen

drm/omap: work-around for errata i886

DRA7 errata i886 (FPDLink PLL Unlocks With Certain SoC PLL M/N Values)
says that FPDLink is sensitive to jitter on the vout clock, and that low
PLL M and N values result in more jitter than high M and N values.

This patch implements a workaround for the problem by changing the PLL
setup to search for clocks starting from high M and N values, instead of
low values. This should not cause any functional change, and only
reduces the jitter.
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
parent 320d8c3d
...@@ -215,8 +215,8 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin, ...@@ -215,8 +215,8 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
dss_pll_calc_func func, void *data) dss_pll_calc_func func, void *data)
{ {
const struct dss_pll_hw *hw = pll->hw; const struct dss_pll_hw *hw = pll->hw;
int n, n_start, n_stop; int n, n_min, n_max;
int m, m_start, m_stop; int m, m_min, m_max;
unsigned long fint, clkdco; unsigned long fint, clkdco;
unsigned long pll_hw_max; unsigned long pll_hw_max;
unsigned long fint_hw_min, fint_hw_max; unsigned long fint_hw_min, fint_hw_max;
...@@ -226,21 +226,22 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin, ...@@ -226,21 +226,22 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
fint_hw_min = hw->fint_min; fint_hw_min = hw->fint_min;
fint_hw_max = hw->fint_max; fint_hw_max = hw->fint_max;
n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); n_min = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max); n_max = min((unsigned)(clkin / fint_hw_min), hw->n_max);
pll_max = pll_max ? pll_max : ULONG_MAX; pll_max = pll_max ? pll_max : ULONG_MAX;
for (n = n_start; n <= n_stop; ++n) { /* Try to find high N & M to avoid jitter (DRA7 errata i886) */
for (n = n_max; n >= n_min; --n) {
fint = clkin / n; fint = clkin / n;
m_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2), m_min = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
1ul); 1ul);
m_stop = min3((unsigned)(pll_max / fint / 2), m_max = min3((unsigned)(pll_max / fint / 2),
(unsigned)(pll_hw_max / fint / 2), (unsigned)(pll_hw_max / fint / 2),
hw->m_max); hw->m_max);
for (m = m_start; m <= m_stop; ++m) { for (m = m_max; m >= m_min; --m) {
clkdco = 2 * m * fint; clkdco = 2 * m * fint;
if (func(n, m, fint, clkdco, data)) if (func(n, m, fint, clkdco, data))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment