Re: [Intel-gfx] [PATCH 2/8] drm/i915: Use literal representation of cdclk tables

2019-09-10 Thread Ville Syrjälä
On Sat, Sep 07, 2019 at 09:05:00PM -0700, Matt Roper wrote:
> The bspec lays out legal cdclk frequencies, PLL ratios, and CD2X
> dividers in an easy-to-read table for most recent platforms.  We've been
> translating the data from that table into platform-specific code logic,
> but it's easy to overlook an area we need to update when adding new
> cdclk values or enabling new platforms.  Let's just add a form of the
> bspec table to the code and then adjust our functions to pull what they
> need directly out of the table.
> 
> v2: Fix comparison when finding best cdclk.
> 
> v3: Another logic fix for calc_cdclk.
> 
> Cc: Ville Syrjälä 
> Signed-off-by: Matt Roper 
> ---
>  drivers/gpu/drm/i915/display/intel_cdclk.c | 318 -
>  drivers/gpu/drm/i915/display/intel_cdclk.h |   8 +
>  drivers/gpu/drm/i915/i915_drv.h|   4 +
>  3 files changed, 125 insertions(+), 205 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c 
> b/drivers/gpu/drm/i915/display/intel_cdclk.c
> index e07de3b84cec..ca64143b6d7e 100644
> --- a/drivers/gpu/drm/i915/display/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
> @@ -1161,28 +1161,96 @@ static void skl_uninit_cdclk(struct drm_i915_private 
> *dev_priv)
>   skl_set_cdclk(dev_priv, &cdclk_state, INVALID_PIPE);
>  }
>  
> -static int bxt_calc_cdclk(int min_cdclk)
> -{
> - if (min_cdclk > 576000)
> - return 624000;
> - else if (min_cdclk > 384000)
> - return 576000;
> - else if (min_cdclk > 288000)
> - return 384000;
> - else if (min_cdclk > 144000)
> - return 288000;
> - else
> - return 144000;
> +static const struct intel_cdclk_vals bxt_cdclk_table[] = {
> + { 144000, 8, 60 },
> + { 288000, 4, 60 },
> + { 384000, 3, 60 },
> + { 576000, 2, 60 },
> + { 624000, 2, 65 },

Named initializers might make this number soup digestible.

> +};
> +
> +static const struct intel_cdclk_vals glk_cdclk_table[] = {
> + {  79200, 8, 33 },
> + { 158400, 4, 33 },
> + { 316800, 2, 33 },
> +};
> +
> +static const struct intel_cdclk_vals cnl_cdclk_table[] = {
> + { 168000, 4, 35, 28 },
> + { 336000, 2, 35, 28 },
> + { 528000, 2, 55, 44 },
> +};
> +
> +static const struct intel_cdclk_vals icl_cdclk_table[] = {
> + { 172800, 2, 18,  0,  9 },
> + { 18, 2,  0, 15,  0 },
> + { 192000, 2, 20, 16, 10 },
> + { 307200, 2, 32,  0, 16 },
> + { 312000, 2,  0, 26,  0 },
> + { 324000, 4,  0, 54,  0 },
> + { 326400, 4, 68,  0, 34 },
> + { 552000, 2,  0, 46,  0 },
> + { 556800, 2, 58,  0, 29 },
> + { 648000, 2,  0, 54,  0 },
> + { 652800, 2, 68,  0, 34 },
> +};
> +
> +static int calc_cdclk(struct drm_i915_private *dev_priv,
> +   int min_cdclk)
> +{
> + const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
> + unsigned int ref = dev_priv->cdclk.hw.ref;
> + int best_cdclk = 0;
> + int i;
> +
> + if (WARN_ON(ref != 19200 && ref != 24000 && ref != 38400))
> + ref = 19200;

Feels a bit like dead code.

> +
> + for (i = 0; i < dev_priv->cdclk.table_size; i++) {
> + if ((ref == 19200 && table[i].ratio_19 == 0) ||
> + (ref == 24000 && table[i].ratio_24 == 0) ||
> + (ref == 38400 && table[i].ratio_38 == 0))
> + continue;
> +
> + best_cdclk = table[i].cdclk;
> + if (table[i].cdclk >= min_cdclk)
> + return best_cdclk;
> + }
> +
> + WARN(1, "Cannot satisfy minimum cdclk %d\n", min_cdclk);
> + return best_cdclk;

Same for the best_cdclk thing. I'd probably just MISSING_CASE() 
and return 0, or something.

>  }
>  
> -static int glk_calc_cdclk(int min_cdclk)
> +static int calc_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk)

We still use these things for bxt+ only, so would be nice if
the names kept reflecting that fact.

Though I suppose we should be able to extend this more
declarative approach backwards to older platforms as well.

>  {
> - if (min_cdclk > 158400)
> - return 316800;
> - else if (min_cdclk > 79200)
> - return 158400;
> - else
> - return 79200;
> + const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
> + int ratio, best_ratio, i;
> +
> + if (cdclk == dev_priv->cdclk.hw.bypass)
> + return 0;
> +
> + for (i = 0; i < dev_priv->cdclk.table_size; i++) {
> + if (dev_priv->cdclk.hw.ref == 19200)
> + ratio = table[i].ratio_19;
> + else if (dev_priv->cdclk.hw.ref == 24000)
> + ratio = table[i].ratio_24;
> + else
> + ratio = table[i].ratio_38;
> +
> + if (ratio == 0)
> + continue;
> + else
> + best_ratio = ratio;
> +
> + if (table[i].cdclk == cdclk ||

[Intel-gfx] [PATCH 2/8] drm/i915: Use literal representation of cdclk tables

2019-09-07 Thread Matt Roper
The bspec lays out legal cdclk frequencies, PLL ratios, and CD2X
dividers in an easy-to-read table for most recent platforms.  We've been
translating the data from that table into platform-specific code logic,
but it's easy to overlook an area we need to update when adding new
cdclk values or enabling new platforms.  Let's just add a form of the
bspec table to the code and then adjust our functions to pull what they
need directly out of the table.

v2: Fix comparison when finding best cdclk.

v3: Another logic fix for calc_cdclk.

Cc: Ville Syrjälä 
Signed-off-by: Matt Roper 
---
 drivers/gpu/drm/i915/display/intel_cdclk.c | 318 -
 drivers/gpu/drm/i915/display/intel_cdclk.h |   8 +
 drivers/gpu/drm/i915/i915_drv.h|   4 +
 3 files changed, 125 insertions(+), 205 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c 
b/drivers/gpu/drm/i915/display/intel_cdclk.c
index e07de3b84cec..ca64143b6d7e 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -1161,28 +1161,96 @@ static void skl_uninit_cdclk(struct drm_i915_private 
*dev_priv)
skl_set_cdclk(dev_priv, &cdclk_state, INVALID_PIPE);
 }
 
-static int bxt_calc_cdclk(int min_cdclk)
-{
-   if (min_cdclk > 576000)
-   return 624000;
-   else if (min_cdclk > 384000)
-   return 576000;
-   else if (min_cdclk > 288000)
-   return 384000;
-   else if (min_cdclk > 144000)
-   return 288000;
-   else
-   return 144000;
+static const struct intel_cdclk_vals bxt_cdclk_table[] = {
+   { 144000, 8, 60 },
+   { 288000, 4, 60 },
+   { 384000, 3, 60 },
+   { 576000, 2, 60 },
+   { 624000, 2, 65 },
+};
+
+static const struct intel_cdclk_vals glk_cdclk_table[] = {
+   {  79200, 8, 33 },
+   { 158400, 4, 33 },
+   { 316800, 2, 33 },
+};
+
+static const struct intel_cdclk_vals cnl_cdclk_table[] = {
+   { 168000, 4, 35, 28 },
+   { 336000, 2, 35, 28 },
+   { 528000, 2, 55, 44 },
+};
+
+static const struct intel_cdclk_vals icl_cdclk_table[] = {
+   { 172800, 2, 18,  0,  9 },
+   { 18, 2,  0, 15,  0 },
+   { 192000, 2, 20, 16, 10 },
+   { 307200, 2, 32,  0, 16 },
+   { 312000, 2,  0, 26,  0 },
+   { 324000, 4,  0, 54,  0 },
+   { 326400, 4, 68,  0, 34 },
+   { 552000, 2,  0, 46,  0 },
+   { 556800, 2, 58,  0, 29 },
+   { 648000, 2,  0, 54,  0 },
+   { 652800, 2, 68,  0, 34 },
+};
+
+static int calc_cdclk(struct drm_i915_private *dev_priv,
+ int min_cdclk)
+{
+   const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
+   unsigned int ref = dev_priv->cdclk.hw.ref;
+   int best_cdclk = 0;
+   int i;
+
+   if (WARN_ON(ref != 19200 && ref != 24000 && ref != 38400))
+   ref = 19200;
+
+   for (i = 0; i < dev_priv->cdclk.table_size; i++) {
+   if ((ref == 19200 && table[i].ratio_19 == 0) ||
+   (ref == 24000 && table[i].ratio_24 == 0) ||
+   (ref == 38400 && table[i].ratio_38 == 0))
+   continue;
+
+   best_cdclk = table[i].cdclk;
+   if (table[i].cdclk >= min_cdclk)
+   return best_cdclk;
+   }
+
+   WARN(1, "Cannot satisfy minimum cdclk %d\n", min_cdclk);
+   return best_cdclk;
 }
 
-static int glk_calc_cdclk(int min_cdclk)
+static int calc_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 {
-   if (min_cdclk > 158400)
-   return 316800;
-   else if (min_cdclk > 79200)
-   return 158400;
-   else
-   return 79200;
+   const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
+   int ratio, best_ratio, i;
+
+   if (cdclk == dev_priv->cdclk.hw.bypass)
+   return 0;
+
+   for (i = 0; i < dev_priv->cdclk.table_size; i++) {
+   if (dev_priv->cdclk.hw.ref == 19200)
+   ratio = table[i].ratio_19;
+   else if (dev_priv->cdclk.hw.ref == 24000)
+   ratio = table[i].ratio_24;
+   else
+   ratio = table[i].ratio_38;
+
+   if (ratio == 0)
+   continue;
+   else
+   best_ratio = ratio;
+
+   if (table[i].cdclk == cdclk ||
+   WARN_ON(table[i].cdclk > cdclk))
+   return dev_priv->cdclk.hw.ref * ratio;
+   }
+
+   WARN(1, "cdclk %d not valid for refclk %d\n",
+cdclk, dev_priv->cdclk.hw.ref);
+
+   return dev_priv->cdclk.hw.ref * best_ratio;
 }
 
 static u8 bxt_calc_voltage_level(int cdclk)
@@ -1220,52 +1288,6 @@ static u8 ehl_calc_voltage_level(int cdclk)
return 0;
 }
 
-static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
-{
-   int ratio;
-
-   if (cdclk == dev_priv->cdclk.hw.bypass)
- 

[Intel-gfx] [PATCH 2/8] drm/i915: Use literal representation of cdclk tables

2019-09-07 Thread Matt Roper
The bspec lays out legal cdclk frequencies, PLL ratios, and CD2X
dividers in an easy-to-read table for most recent platforms.  We've been
translating the data from that table into platform-specific code logic,
but it's easy to overlook an area we need to update when adding new
cdclk values or enabling new platforms.  Let's just add a form of the
bspec table to the code and then adjust our functions to pull what they
need directly out of the table.

v2: Fix comparison when finding best cdclk.

Cc: Ville Syrjälä 
Signed-off-by: Matt Roper 
---
 drivers/gpu/drm/i915/display/intel_cdclk.c | 318 -
 drivers/gpu/drm/i915/display/intel_cdclk.h |   8 +
 drivers/gpu/drm/i915/i915_drv.h|   4 +
 3 files changed, 125 insertions(+), 205 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c 
b/drivers/gpu/drm/i915/display/intel_cdclk.c
index e07de3b84cec..90efc82b8a94 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -1161,28 +1161,96 @@ static void skl_uninit_cdclk(struct drm_i915_private 
*dev_priv)
skl_set_cdclk(dev_priv, &cdclk_state, INVALID_PIPE);
 }
 
-static int bxt_calc_cdclk(int min_cdclk)
-{
-   if (min_cdclk > 576000)
-   return 624000;
-   else if (min_cdclk > 384000)
-   return 576000;
-   else if (min_cdclk > 288000)
-   return 384000;
-   else if (min_cdclk > 144000)
-   return 288000;
-   else
-   return 144000;
+static const struct intel_cdclk_vals bxt_cdclk_table[] = {
+   { 144000, 8, 60 },
+   { 288000, 4, 60 },
+   { 384000, 3, 60 },
+   { 576000, 2, 60 },
+   { 624000, 2, 65 },
+};
+
+static const struct intel_cdclk_vals glk_cdclk_table[] = {
+   {  79200, 8, 33 },
+   { 158400, 4, 33 },
+   { 316800, 2, 33 },
+};
+
+static const struct intel_cdclk_vals cnl_cdclk_table[] = {
+   { 168000, 4, 35, 28 },
+   { 336000, 2, 35, 28 },
+   { 528000, 2, 55, 44 },
+};
+
+static const struct intel_cdclk_vals icl_cdclk_table[] = {
+   { 172800, 2, 18,  0,  9 },
+   { 18, 2,  0, 15,  0 },
+   { 192000, 2, 20, 16, 10 },
+   { 307200, 2, 32,  0, 16 },
+   { 312000, 2,  0, 26,  0 },
+   { 324000, 4,  0, 54,  0 },
+   { 326400, 4, 68,  0, 34 },
+   { 552000, 2,  0, 46,  0 },
+   { 556800, 2, 58,  0, 29 },
+   { 648000, 2,  0, 54,  0 },
+   { 652800, 2, 68,  0, 34 },
+};
+
+static int calc_cdclk(struct drm_i915_private *dev_priv,
+ int min_cdclk)
+{
+   const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
+   unsigned int ref = dev_priv->cdclk.hw.ref;
+   int best_cdclk = 0;
+   int i;
+
+   if (WARN_ON(ref != 19200 && ref != 24000 && ref != 38400))
+   ref = 19200;
+
+   for (i = 0; i < dev_priv->cdclk.table_size; i++) {
+   if (ref == 19200 && table[i].ratio_19 == 0 ||
+   ref == 24000 && table[i].ratio_24 == 0 ||
+   ref == 38400 && table[i].ratio_38 == 0)
+   continue;
+
+   best_cdclk = table[i].cdclk;
+   if (table[i].cdclk >= min_cdclk)
+   return best_cdclk;
+   }
+
+   WARN(1, "Cannot satisfy minimum cdclk %d\n", min_cdclk);
+   return best_cdclk;
 }
 
-static int glk_calc_cdclk(int min_cdclk)
+static int calc_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 {
-   if (min_cdclk > 158400)
-   return 316800;
-   else if (min_cdclk > 79200)
-   return 158400;
-   else
-   return 79200;
+   const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
+   int ratio, best_ratio, i;
+
+   if (cdclk == dev_priv->cdclk.hw.bypass)
+   return 0;
+
+   for (i = 0; i < dev_priv->cdclk.table_size; i++) {
+   if (dev_priv->cdclk.hw.ref == 19200)
+   ratio = table[i].ratio_19;
+   else if (dev_priv->cdclk.hw.ref == 24000)
+   ratio = table[i].ratio_24;
+   else
+   ratio = table[i].ratio_38;
+
+   if (ratio == 0)
+   continue;
+   else
+   best_ratio = ratio;
+
+   if (table[i].cdclk == cdclk ||
+   WARN_ON(table[i].cdclk > cdclk))
+   return dev_priv->cdclk.hw.ref * ratio;
+   }
+
+   WARN(1, "cdclk %d not valid for refclk %d\n",
+cdclk, dev_priv->cdclk.hw.ref);
+
+   return dev_priv->cdclk.hw.ref * best_ratio;
 }
 
 static u8 bxt_calc_voltage_level(int cdclk)
@@ -1220,52 +1288,6 @@ static u8 ehl_calc_voltage_level(int cdclk)
return 0;
 }
 
-static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
-{
-   int ratio;
-
-   if (cdclk == dev_priv->cdclk.hw.bypass)
-   return 0;
-
-   switch (cdc

[Intel-gfx] [PATCH 2/8] drm/i915: Use literal representation of cdclk tables

2019-09-06 Thread Matt Roper
The bspec lays out legal cdclk frequencies, PLL ratios, and CD2X
dividers in an easy-to-read table for most recent platforms.  We've been
translating the data from that table into platform-specific code logic,
but it's easy to overlook an area we need to update when adding new
cdclk values or enabling new platforms.  Let's just add a form of the
bspec table to the code and then adjust our functions to pull what they
need directly out of the table.

Cc: Ville Syrjälä 
Signed-off-by: Matt Roper 
---
 drivers/gpu/drm/i915/display/intel_cdclk.c | 319 -
 drivers/gpu/drm/i915/display/intel_cdclk.h |   8 +
 drivers/gpu/drm/i915/i915_drv.h|   4 +
 3 files changed, 126 insertions(+), 205 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c 
b/drivers/gpu/drm/i915/display/intel_cdclk.c
index e07de3b84cec..8ac31f8775f0 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -1161,28 +1161,97 @@ static void skl_uninit_cdclk(struct drm_i915_private 
*dev_priv)
skl_set_cdclk(dev_priv, &cdclk_state, INVALID_PIPE);
 }
 
-static int bxt_calc_cdclk(int min_cdclk)
-{
-   if (min_cdclk > 576000)
-   return 624000;
-   else if (min_cdclk > 384000)
-   return 576000;
-   else if (min_cdclk > 288000)
-   return 384000;
-   else if (min_cdclk > 144000)
-   return 288000;
-   else
-   return 144000;
+static const struct intel_cdclk_vals bxt_cdclk_table[] = {
+   { 144000, 8, 60 },
+   { 288000, 4, 60 },
+   { 384000, 3, 60 },
+   { 576000, 2, 60 },
+   { 624000, 2, 65 },
+};
+
+static const struct intel_cdclk_vals glk_cdclk_table[] = {
+   {  79200, 8, 33 },
+   { 158400, 4, 33 },
+   { 316800, 2, 33 },
+};
+
+static const struct intel_cdclk_vals cnl_cdclk_table[] = {
+   { 168000, 4, 35, 28 },
+   { 336000, 2, 35, 28 },
+   { 528000, 2, 55, 44 },
+};
+
+static const struct intel_cdclk_vals icl_cdclk_table[] = {
+   { 172800, 2, 18,  0,  9 },
+   { 18, 2,  0, 15,  0 },
+   { 192000, 2, 20, 16, 10 },
+   { 307200, 2, 32,  0, 16 },
+   { 312000, 2,  0, 26,  0 },
+   { 324000, 4,  0, 54,  0 },
+   { 326400, 4, 68,  0, 34 },
+   { 552000, 2,  0, 46,  0 },
+   { 556800, 2, 58,  0, 29 },
+   { 648000, 2,  0, 54,  0 },
+   { 652800, 2, 68,  0, 34 },
+};
+
+static int calc_cdclk(struct drm_i915_private *dev_priv,
+ int min_cdclk)
+{
+   const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
+   unsigned int ref = dev_priv->cdclk.hw.ref;
+   int best_cdclk = 0;
+   int i;
+
+   if (WARN_ON(ref != 19200 && ref != 24000 && ref != 38400))
+   ref = 19200;
+
+   for (i = 0; i < dev_priv->cdclk.table_size; i++) {
+   if (ref == 19200 && table[i].ratio_19 != 0)
+   best_cdclk = table[i].cdclk;
+   else if (ref == 24000 && table[i].ratio_24 != 0)
+   best_cdclk = table[i].cdclk;
+   else if (ref == 38400 && table[i].ratio_38 != 0)
+   best_cdclk = table[i].cdclk;
+
+   if (table[i].cdclk < min_cdclk)
+   return best_cdclk;
+   }
+
+   WARN(1, "Cannot satisfy minimum cdclk %d\n", min_cdclk);
+   return best_cdclk;
 }
 
-static int glk_calc_cdclk(int min_cdclk)
+static int calc_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 {
-   if (min_cdclk > 158400)
-   return 316800;
-   else if (min_cdclk > 79200)
-   return 158400;
-   else
-   return 79200;
+   const struct intel_cdclk_vals *table = dev_priv->cdclk.table;
+   int ratio, best_ratio, i;
+
+   if (cdclk == dev_priv->cdclk.hw.bypass)
+   return 0;
+
+   for (i = 0; i < dev_priv->cdclk.table_size; i++) {
+   if (dev_priv->cdclk.hw.ref == 19200)
+   ratio = table[i].ratio_19;
+   else if (dev_priv->cdclk.hw.ref == 24000)
+   ratio = table[i].ratio_24;
+   else
+   ratio = table[i].ratio_38;
+
+   if (ratio == 0)
+   continue;
+   else
+   best_ratio = ratio;
+
+   if (table[i].cdclk == cdclk ||
+   WARN_ON(table[i].cdclk > cdclk))
+   return dev_priv->cdclk.hw.ref * ratio;
+   }
+
+   WARN(1, "cdclk %d not valid for refclk %d\n",
+cdclk, dev_priv->cdclk.hw.ref);
+
+   return dev_priv->cdclk.hw.ref * best_ratio;
 }
 
 static u8 bxt_calc_voltage_level(int cdclk)
@@ -1220,52 +1289,6 @@ static u8 ehl_calc_voltage_level(int cdclk)
return 0;
 }
 
-static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
-{
-   int ratio;
-
-   if (cdclk == dev_priv->cdclk.hw.bypass)
-