diff mbox

[PATCHv3,01/30] drm/omap: work-around for errata i886

Message ID 1490706496-4959-2-git-send-email-tomi.valkeinen@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tomi Valkeinen March 28, 2017, 1:07 p.m. UTC
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: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/dss/pll.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

Comments

Laurent Pinchart March 29, 2017, 8 a.m. UTC | #1
Hi Tomi,

Thank you for the patch.

On Tuesday 28 Mar 2017 16:07:47 Tomi Valkeinen wrote:
> 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: Tomi Valkeinen <tomi.valkeinen@ti.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/gpu/drm/omapdrm/dss/pll.c | 17 +++++++++--------
>  1 file changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/dss/pll.c
> b/drivers/gpu/drm/omapdrm/dss/pll.c index 0a76c89cdc2e..5e221302768b 100644
> --- a/drivers/gpu/drm/omapdrm/dss/pll.c
> +++ b/drivers/gpu/drm/omapdrm/dss/pll.c
> @@ -215,8 +215,8 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned
> long clkin, dss_pll_calc_func func, void *data)
>  {
>  	const struct dss_pll_hw *hw = pll->hw;
> -	int n, n_start, n_stop;
> -	int m, m_start, m_stop;
> +	int n, n_min, n_max;
> +	int m, m_min, m_max;
>  	unsigned long fint, clkdco;
>  	unsigned long pll_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, fint_hw_min = hw->fint_min;
>  	fint_hw_max = hw->fint_max;
> 
> -	n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
> -	n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max);
> +	n_min = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
> +	n_max = min((unsigned)(clkin / fint_hw_min), hw->n_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;
> 
> -		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);
> -		m_stop = min3((unsigned)(pll_max / fint / 2),
> +		m_max = min3((unsigned)(pll_max / fint / 2),
>  				(unsigned)(pll_hw_max / fint / 2),
>  				hw->m_max);
> 
> -		for (m = m_start; m <= m_stop; ++m) {
> +		for (m = m_max; m >= m_min; --m) {
>  			clkdco = 2 * m * fint;
> 
>  			if (func(n, m, fint, clkdco, data))
diff mbox

Patch

diff --git a/drivers/gpu/drm/omapdrm/dss/pll.c b/drivers/gpu/drm/omapdrm/dss/pll.c
index 0a76c89cdc2e..5e221302768b 100644
--- a/drivers/gpu/drm/omapdrm/dss/pll.c
+++ b/drivers/gpu/drm/omapdrm/dss/pll.c
@@ -215,8 +215,8 @@  bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
 		dss_pll_calc_func func, void *data)
 {
 	const struct dss_pll_hw *hw = pll->hw;
-	int n, n_start, n_stop;
-	int m, m_start, m_stop;
+	int n, n_min, n_max;
+	int m, m_min, m_max;
 	unsigned long fint, clkdco;
 	unsigned long pll_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,
 	fint_hw_min = hw->fint_min;
 	fint_hw_max = hw->fint_max;
 
-	n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
-	n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max);
+	n_min = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
+	n_max = min((unsigned)(clkin / fint_hw_min), hw->n_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;
 
-		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);
-		m_stop = min3((unsigned)(pll_max / fint / 2),
+		m_max = min3((unsigned)(pll_max / fint / 2),
 				(unsigned)(pll_hw_max / fint / 2),
 				hw->m_max);
 
-		for (m = m_start; m <= m_stop; ++m) {
+		for (m = m_max; m >= m_min; --m) {
 			clkdco = 2 * m * fint;
 
 			if (func(n, m, fint, clkdco, data))