Patches merged to dinq, thanks for the patches and reviews!<br><br><div class="gmail_quote"><div dir="ltr">On Fri, Jun 9, 2017 at 3:27 PM Rodrigo Vivi <<a href="mailto:rodrigo.vivi@intel.com">rodrigo.vivi@intel.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: "Kahola, Mika" <<a href="mailto:mika.kahola@intel.com" target="_blank">mika.kahola@intel.com</a>><br>
<br>
Enable wrpll computation for Cannonlake platform to support<br>
pll's required for HDMI output. The patch contains the following features<br>
<br>
- compute Cannonlake port clock programming<br>
dividers P, Q, and K.<br>
- compute PLL parameters for Cannonlake. These parameters<br>
set the values on DPLL registers.<br>
- find the register values to program wrpll for Cannonlake.<br>
The reference clock can be either 19.2MHz or 24MHz.<br>
<br>
v2: rebase<br>
v3: squash wrpll patches into one (Rodrigo)<br>
v4: switch order of getting even dividers (Paulo)<br>
update divider register values for PDiv and KDiv (Paulo)<br>
update wrpll computation algorithm (Paulo)<br>
v5: Remove ref clock division by 1000. (Rodrigo)<br>
v6: Rodrigo rebasing on top of latest code.<br>
<br>
Signed-off-by: Kahola, Mika <<a href="mailto:mika.kahola@intel.com" target="_blank">mika.kahola@intel.com</a>><br>
Signed-off-by: Rodrigo Vivi <<a href="mailto:rodrigo.vivi@intel.com" target="_blank">rodrigo.vivi@intel.com</a>><br>
Reviewed-by: Clint Taylor <<a href="mailto:Clinton.A.Taylor@intel.com" target="_blank">Clinton.A.Taylor@intel.com</a>><br>
---<br>
drivers/gpu/drm/i915/intel_dpll_mgr.c | 140 +++++++++++++++++++++++++++++++++-<br>
1 file changed, 138 insertions(+), 2 deletions(-)<br>
<br>
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c<br>
index 903c38d..8e669b6 100644<br>
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c<br>
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c<br>
@@ -2126,17 +2126,153 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,<br>
return ret;<br>
}<br>
<br>
+static void cnl_wrpll_get_multipliers(unsigned int bestdiv,<br>
+ unsigned int *pdiv,<br>
+ unsigned int *qdiv,<br>
+ unsigned int *kdiv)<br>
+{<br>
+ /* even dividers */<br>
+ if (bestdiv % 2 == 0) {<br>
+ if (bestdiv == 2) {<br>
+ *pdiv = 2;<br>
+ *qdiv = 1;<br>
+ *kdiv = 1;<br>
+ } else if (bestdiv % 4 == 0) {<br>
+ *pdiv = 2;<br>
+ *qdiv = bestdiv / 4;<br>
+ *kdiv = 2;<br>
+ } else if (bestdiv % 6 == 0) {<br>
+ *pdiv = 3;<br>
+ *qdiv = bestdiv / 6;<br>
+ *kdiv = 2;<br>
+ } else if (bestdiv % 5 == 0) {<br>
+ *pdiv = 5;<br>
+ *qdiv = bestdiv / 10;<br>
+ *kdiv = 2;<br>
+ } else if (bestdiv % 14 == 0) {<br>
+ *pdiv = 7;<br>
+ *qdiv = bestdiv / 14;<br>
+ *kdiv = 2;<br>
+ }<br>
+ } else {<br>
+ if (bestdiv == 3 || bestdiv == 5 || bestdiv == 7) {<br>
+ *pdiv = bestdiv;<br>
+ *qdiv = 1;<br>
+ *kdiv = 1;<br>
+ } else { /* 9, 15, 21 */<br>
+ *pdiv = bestdiv / 3;<br>
+ *qdiv = 1;<br>
+ *kdiv = 3;<br>
+ }<br>
+ }<br>
+}<br>
+<br>
+static void cnl_wrpll_params_populate(struct skl_wrpll_params *params, uint32_t dco_freq,<br>
+ uint32_t ref_freq, uint32_t pdiv, uint32_t qdiv,<br>
+ uint32_t kdiv)<br>
+{<br>
+ switch (kdiv) {<br>
+ case 1:<br>
+ params->kdiv = 1;<br>
+ break;<br>
+ case 2:<br>
+ params->kdiv = 2;<br>
+ break;<br>
+ case 3:<br>
+ params->kdiv = 4;<br>
+ break;<br>
+ default:<br>
+ WARN(1, "Incorrect KDiv\n");<br>
+ }<br>
+<br>
+ switch (pdiv) {<br>
+ case 2:<br>
+ params->pdiv = 1;<br>
+ break;<br>
+ case 3:<br>
+ params->pdiv = 2;<br>
+ break;<br>
+ case 5:<br>
+ params->pdiv = 4;<br>
+ break;<br>
+ case 7:<br>
+ params->pdiv = 8;<br>
+ break;<br>
+ default:<br>
+ WARN(1, "Incorrect PDiv\n");<br>
+ }<br>
+<br>
+ if (kdiv != 2)<br>
+ qdiv = 1;<br>
+<br>
+ params->qdiv_ratio = qdiv;<br>
+ params->qdiv_mode = (qdiv == 1) ? 0 : 1;<br>
+<br>
+ params->dco_integer = div_u64(dco_freq, ref_freq);<br>
+ params->dco_fraction = div_u64((div_u64((uint64_t)dco_freq<<15, (uint64_t)ref_freq) -<br>
+ ((uint64_t)params->dco_integer<<15)) * 0x8000, 0x8000);<br>
+}<br>
+<br>
+static bool<br>
+cnl_ddi_calculate_wrpll(int clock /* in Hz */,<br>
+ struct drm_i915_private *dev_priv,<br>
+ struct skl_wrpll_params *wrpll_params)<br>
+{<br>
+ uint64_t afe_clock = clock * 5 / KHz(1); /* clocks in kHz */<br>
+ unsigned int dco_min = 7998 * KHz(1);<br>
+ unsigned int dco_max = 10000 * KHz(1);<br>
+ unsigned int dco_mid = (dco_min + dco_max) / 2;<br>
+<br>
+ static const int dividers[] = { 2, 4, 6, 8, 10, 12, 14, 16,<br>
+ 18, 20, 24, 28, 30, 32, 36, 40,<br>
+ 42, 44, 48, 50, 52, 54, 56, 60,<br>
+ 64, 66, 68, 70, 72, 76, 78, 80,<br>
+ 84, 88, 90, 92, 96, 98, 100, 102,<br>
+ 3, 5, 7, 9, 15, 21 };<br>
+ unsigned int d, dco;<br>
+ unsigned int dco_centrality = 0;<br>
+ unsigned int best_dco_centrality = 999999;<br>
+ unsigned int best_div = 0;<br>
+ unsigned int best_dco = 0;<br>
+ unsigned int pdiv = 0, qdiv = 0, kdiv = 0;<br>
+<br>
+ for (d = 0; d < ARRAY_SIZE(dividers); d++) {<br>
+ dco = afe_clock * dividers[d];<br>
+<br>
+ if ((dco <= dco_max) && (dco >= dco_min)) {<br>
+ dco_centrality = abs(dco - dco_mid);<br>
+<br>
+ if (dco_centrality < best_dco_centrality) {<br>
+ best_dco_centrality = dco_centrality;<br>
+ best_div = dividers[d];<br>
+ best_dco = dco;<br>
+ }<br>
+ }<br>
+ }<br>
+<br>
+ if (best_div == 0)<br>
+ return false;<br>
+<br>
+ cnl_wrpll_get_multipliers(best_div, &pdiv, &qdiv, &kdiv);<br>
+<br>
+ cnl_wrpll_params_populate(wrpll_params, best_dco,<br>
+ dev_priv->cdclk.hw.ref, pdiv, qdiv, kdiv);<br>
+<br>
+ return true;<br>
+}<br>
+<br>
static bool cnl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,<br>
struct intel_crtc_state *crtc_state,<br>
int clock)<br>
{<br>
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);<br>
uint32_t cfgcr0, cfgcr1;<br>
struct skl_wrpll_params wrpll_params = { 0, };<br>
<br>
cfgcr0 = DPLL_CFGCR0_HDMI_MODE;<br>
<br>
- /* FIXME: Proper wrpll calculation done in a following patch */<br>
- return false;<br>
+ if (!cnl_ddi_calculate_wrpll(clock * 1000, dev_priv, &wrpll_params))<br>
+ return false;<br>
<br>
cfgcr0 |= DPLL_CFGCR0_DCO_FRACTION(wrpll_params.dco_fraction) |<br>
wrpll_params.dco_integer;<br>
--<br>
1.9.1<br>
<br>
_______________________________________________<br>
Intel-gfx mailing list<br>
<a href="mailto:Intel-gfx@lists.freedesktop.org" target="_blank">Intel-gfx@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/intel-gfx" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/intel-gfx</a><br>
</blockquote></div>