All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2
@ 2018-03-28 21:57 Paulo Zanoni
  2018-03-28 21:57 ` [PATCH 1/8] drm/i915/icl: Don't set pipe CSC/Gamma in PLANE_COLOR_CTL Paulo Zanoni
                   ` (12 more replies)
  0 siblings, 13 replies; 20+ messages in thread
From: Paulo Zanoni @ 2018-03-28 21:57 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

We already merged some patches from this series, so this new version is smaller.
Some of the patches here already have R-B tags but they depend on non-reviewed
patches.

Only patches 2, 3 and 7 need reviews. I don't think I can qualify as a reviewer
for patch 7 anymore due to how much I changed it.

Thanks,
Paulo

James Ausmus (1):
  drm/i915/icl: Don't set pipe CSC/Gamma in PLANE_COLOR_CTL

Manasi Navare (2):
  drm/i915/icl: Implement voltage swing programming sequence for Combo
    PHY DDI
  drm/i915/icl: Fix the DP Max Voltage for ICL

Paulo Zanoni (5):
  drm/i915/icl: add definitions for the ICL PLL registers
  drm/i915/icl: add basic support for the ICL clocks
  drm/i915/icl: compute the combo PHY (DPLL) HDMI registers
  drm/i915/icl: compute the combo PHY (DPLL) DP registers
  drm/i915/icl: compute the MG PLL registers

 drivers/gpu/drm/i915/i915_debugfs.c   |  22 ++
 drivers/gpu/drm/i915/i915_reg.h       | 153 +++++++-
 drivers/gpu/drm/i915/intel_ddi.c      | 297 ++++++++++++++-
 drivers/gpu/drm/i915/intel_display.c  |  24 +-
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 655 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_dpll_mgr.h |  41 +++
 drivers/gpu/drm/i915/intel_drv.h      |   6 +
 7 files changed, 1183 insertions(+), 15 deletions(-)

-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/8] drm/i915/icl: Don't set pipe CSC/Gamma in PLANE_COLOR_CTL
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
@ 2018-03-28 21:57 ` Paulo Zanoni
  2018-03-28 21:57 ` [PATCH 2/8] drm/i915/icl: add definitions for the ICL PLL registers Paulo Zanoni
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Paulo Zanoni @ 2018-03-28 21:57 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: James Ausmus <james.ausmus@intel.com>

These fields have been deprecated and moved in ICL+. Stop setting the
bits.

They have moved to GAMMA_MODE and CSC_MODE, respectively. This patch
is just to stop incorrectly setting bits in PLANE_COLOR_CTL while
we're waiting for the new replacement functionality to be done.

v2: Drop useless comment, and change !(GEN >= 11) to (GEN < 11). (Ville)

v3: No changes

v4 (from Paulo): Rebase.

Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: James Ausmus <james.ausmus@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      | 4 ++--
 drivers/gpu/drm/i915/intel_display.c | 8 ++++++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 33e52cc98d99..250ff271bcf1 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6359,9 +6359,9 @@ enum {
 #define _PLANE_COLOR_CTL_1_A			0x701CC /* GLK+ */
 #define _PLANE_COLOR_CTL_2_A			0x702CC /* GLK+ */
 #define _PLANE_COLOR_CTL_3_A			0x703CC /* GLK+ */
-#define   PLANE_COLOR_PIPE_GAMMA_ENABLE		(1 << 30)
+#define   PLANE_COLOR_PIPE_GAMMA_ENABLE		(1 << 30) /* Pre-ICL */
 #define   PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE	(1 << 28)
-#define   PLANE_COLOR_PIPE_CSC_ENABLE		(1 << 23)
+#define   PLANE_COLOR_PIPE_CSC_ENABLE		(1 << 23) /* Pre-ICL */
 #define   PLANE_COLOR_CSC_MODE_BYPASS			(0 << 17)
 #define   PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709		(1 << 17)
 #define   PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709		(2 << 17)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3acd75753a31..8b18729bc4d3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3604,11 +3604,15 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
 u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
 			const struct intel_plane_state *plane_state)
 {
+	struct drm_i915_private *dev_priv =
+		to_i915(plane_state->base.plane->dev);
 	const struct drm_framebuffer *fb = plane_state->base.fb;
 	u32 plane_color_ctl = 0;
 
-	plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
-	plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
+	if (INTEL_GEN(dev_priv) < 11) {
+		plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
+		plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
+	}
 	plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
 	plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format);
 
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 2/8] drm/i915/icl: add definitions for the ICL PLL registers
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
  2018-03-28 21:57 ` [PATCH 1/8] drm/i915/icl: Don't set pipe CSC/Gamma in PLANE_COLOR_CTL Paulo Zanoni
@ 2018-03-28 21:57 ` Paulo Zanoni
  2018-04-27 22:49   ` James Ausmus
  2018-03-28 21:57 ` [PATCH 3/8] drm/i915/icl: add basic support for the ICL clocks Paulo Zanoni
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Paulo Zanoni @ 2018-03-28 21:57 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

There's a lot of code for the PLL enabling, so let's first only
introduce the register definitions in order to make patch reviewing a
little easier.

v2: Coding style (Jani).
v3: Preparation for upstreaming.
v4: Fix MG_CLKTOP2_CORECLKCTL1 address and random typos (James).

Cc: James Ausmus <james.ausmus@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h | 149 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 149 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 250ff271bcf1..b79b2a8930da 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -8701,6 +8701,12 @@ enum skl_power_gate {
 #define  PORT_CLK_SEL_NONE		(7<<29)
 #define  PORT_CLK_SEL_MASK		(7<<29)
 
+/* On ICL+ this is the same as PORT_CLK_SEL, but all bits change. */
+#define DDI_CLK_SEL(port)		PORT_CLK_SEL(port)
+#define  DDI_CLK_SEL_NONE		(0x0 << 28)
+#define  DDI_CLK_SEL_MG			(0x8 << 28)
+#define  DDI_CLK_SEL_MASK		(0xF << 28)
+
 /* Transcoder clock selection */
 #define _TRANS_CLK_SEL_A		0x46140
 #define _TRANS_CLK_SEL_B		0x46144
@@ -8831,6 +8837,7 @@ enum skl_power_gate {
  * CNL Clocks
  */
 #define DPCLKA_CFGCR0				_MMIO(0x6C200)
+#define DPCLKA_CFGCR0_ICL			_MMIO(0x164280)
 #define  DPCLKA_CFGCR0_DDI_CLK_OFF(port)	(1 << ((port) ==  PORT_F ? 23 : \
 						      (port)+10))
 #define  DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port)	((port) == PORT_F ? 21 : \
@@ -8847,10 +8854,141 @@ enum skl_power_gate {
 #define  PLL_POWER_STATE	(1 << 26)
 #define CNL_DPLL_ENABLE(pll)	_MMIO_PLL(pll, DPLL0_ENABLE, DPLL1_ENABLE)
 
+#define _MG_PLL1_ENABLE		0x46030
+#define _MG_PLL2_ENABLE		0x46034
+#define _MG_PLL3_ENABLE		0x46038
+#define _MG_PLL4_ENABLE		0x4603C
+/* Bits are the same as DPLL0_ENABLE */
+#define MG_PLL_ENABLE(port)	_MMIO_PORT((port) - PORT_C, _MG_PLL1_ENABLE, \
+					   _MG_PLL2_ENABLE)
+
+#define _MG_REFCLKIN_CTL_PORT1				0x16892C
+#define _MG_REFCLKIN_CTL_PORT2				0x16992C
+#define _MG_REFCLKIN_CTL_PORT3				0x16A92C
+#define _MG_REFCLKIN_CTL_PORT4				0x16B92C
+#define   MG_REFCLKIN_CTL_OD_2_MUX(x)			((x) << 8)
+#define MG_REFCLKIN_CTL(port) _MMIO_PORT((port) - PORT_C, \
+					 _MG_REFCLKIN_CTL_PORT1, \
+					 _MG_REFCLKIN_CTL_PORT2)
+
+#define _MG_CLKTOP2_CORECLKCTL1_PORT1			0x1688D8
+#define _MG_CLKTOP2_CORECLKCTL1_PORT2			0x1698D8
+#define _MG_CLKTOP2_CORECLKCTL1_PORT3			0x16A8D8
+#define _MG_CLKTOP2_CORECLKCTL1_PORT4			0x16B8D8
+#define   MG_CLKTOP2_CORECLKCTL1_B_DIVRATIO(x)		((x) << 16)
+#define   MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO(x)		((x) << 8)
+#define MG_CLKTOP2_CORECLKCTL1(port) _MMIO_PORT((port) - PORT_C, \
+						_MG_CLKTOP2_CORECLKCTL1_PORT1, \
+						_MG_CLKTOP2_CORECLKCTL1_PORT2)
+
+#define _MG_CLKTOP2_HSCLKCTL_PORT1			0x1688D4
+#define _MG_CLKTOP2_HSCLKCTL_PORT2			0x1698D4
+#define _MG_CLKTOP2_HSCLKCTL_PORT3			0x16A8D4
+#define _MG_CLKTOP2_HSCLKCTL_PORT4			0x16B8D4
+#define   MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL(x)		((x) << 16)
+#define   MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL(x)	((x) << 14)
+#define   MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO(x)		((x) << 12)
+#define   MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO(x)		((x) << 8)
+#define MG_CLKTOP2_HSCLKCTL(port) _MMIO_PORT((port) - PORT_C, \
+					     _MG_CLKTOP2_HSCLKCTL_PORT1, \
+					     _MG_CLKTOP2_HSCLKCTL_PORT2)
+
+#define _MG_PLL_DIV0_PORT1				0x168A00
+#define _MG_PLL_DIV0_PORT2				0x169A00
+#define _MG_PLL_DIV0_PORT3				0x16AA00
+#define _MG_PLL_DIV0_PORT4				0x16BA00
+#define   MG_PLL_DIV0_FRACNEN_H				(1 << 30)
+#define   MG_PLL_DIV0_FBDIV_FRAC(x)			((x) << 8)
+#define   MG_PLL_DIV0_FBDIV_INT(x)			((x) << 0)
+#define MG_PLL_DIV0(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_DIV0_PORT1, \
+				     _MG_PLL_DIV0_PORT2)
+
+#define _MG_PLL_DIV1_PORT1				0x168A04
+#define _MG_PLL_DIV1_PORT2				0x169A04
+#define _MG_PLL_DIV1_PORT3				0x16AA04
+#define _MG_PLL_DIV1_PORT4				0x16BA04
+#define   MG_PLL_DIV1_IREF_NDIVRATIO(x)			((x) << 16)
+#define   MG_PLL_DIV1_DITHER_DIV_1			(0 << 12)
+#define   MG_PLL_DIV1_DITHER_DIV_2			(1 << 12)
+#define   MG_PLL_DIV1_DITHER_DIV_4			(2 << 12)
+#define   MG_PLL_DIV1_DITHER_DIV_8			(3 << 12)
+#define   MG_PLL_DIV1_NDIVRATIO(x)			((x) << 4)
+#define   MG_PLL_DIV1_FBPREDIV(x)			((x) << 0)
+#define MG_PLL_DIV1(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_DIV1_PORT1, \
+				     _MG_PLL_DIV1_PORT2)
+
+#define _MG_PLL_LF_PORT1				0x168A08
+#define _MG_PLL_LF_PORT2				0x169A08
+#define _MG_PLL_LF_PORT3				0x16AA08
+#define _MG_PLL_LF_PORT4				0x16BA08
+#define   MG_PLL_LF_TDCTARGETCNT(x)			((x) << 24)
+#define   MG_PLL_LF_AFCCNTSEL_256			(0 << 20)
+#define   MG_PLL_LF_AFCCNTSEL_512			(1 << 20)
+#define   MG_PLL_LF_GAINCTRL(x)				((x) << 16)
+#define   MG_PLL_LF_INT_COEFF(x)			((x) << 8)
+#define   MG_PLL_LF_PROP_COEFF(x)			((x) << 0)
+#define MG_PLL_LF(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_LF_PORT1, \
+				   _MG_PLL_LF_PORT2)
+
+#define _MG_PLL_FRAC_LOCK_PORT1				0x168A0C
+#define _MG_PLL_FRAC_LOCK_PORT2				0x169A0C
+#define _MG_PLL_FRAC_LOCK_PORT3				0x16AA0C
+#define _MG_PLL_FRAC_LOCK_PORT4				0x16BA0C
+#define   MG_PLL_FRAC_LOCK_TRUELOCK_CRIT_32		(1 << 18)
+#define   MG_PLL_FRAC_LOCK_EARLYLOCK_CRIT_32		(1 << 16)
+#define   MG_PLL_FRAC_LOCK_LOCKTHRESH(x)		((x) << 11)
+#define   MG_PLL_FRAC_LOCK_DCODITHEREN			(1 << 10)
+#define   MG_PLL_FRAC_LOCK_FEEDFWRDCAL_EN		(1 << 8)
+#define   MG_PLL_FRAC_LOCK_FEEDFWRDGAIN(x)		((x) << 0)
+#define MG_PLL_FRAC_LOCK(port) _MMIO_PORT((port) - PORT_C, \
+					  _MG_PLL_FRAC_LOCK_PORT1, \
+					  _MG_PLL_FRAC_LOCK_PORT2)
+
+#define _MG_PLL_SSC_PORT1				0x168A10
+#define _MG_PLL_SSC_PORT2				0x169A10
+#define _MG_PLL_SSC_PORT3				0x16AA10
+#define _MG_PLL_SSC_PORT4				0x16BA10
+#define   MG_PLL_SSC_EN					(1 << 28)
+#define   MG_PLL_SSC_TYPE(x)				((x) << 26)
+#define   MG_PLL_SSC_STEPLENGTH(x)			((x) << 16)
+#define   MG_PLL_SSC_STEPNUM(x)				((x) << 10)
+#define   MG_PLL_SSC_FLLEN				(1 << 9)
+#define   MG_PLL_SSC_STEPSIZE(x)			((x) << 0)
+#define MG_PLL_SSC(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_SSC_PORT1, \
+				    _MG_PLL_SSC_PORT2)
+
+#define _MG_PLL_BIAS_PORT1				0x168A14
+#define _MG_PLL_BIAS_PORT2				0x169A14
+#define _MG_PLL_BIAS_PORT3				0x16AA14
+#define _MG_PLL_BIAS_PORT4				0x16BA14
+#define   MG_PLL_BIAS_BIAS_GB_SEL(x)			((x) << 30)
+#define   MG_PLL_BIAS_INIT_DCOAMP(x)			((x) << 24)
+#define   MG_PLL_BIAS_BIAS_BONUS(x)			((x) << 16)
+#define   MG_PLL_BIAS_BIASCAL_EN			(1 << 15)
+#define   MG_PLL_BIAS_CTRIM(x)				((x) << 8)
+#define   MG_PLL_BIAS_VREF_RDAC(x)			((x) << 5)
+#define   MG_PLL_BIAS_IREFTRIM(x)			((x) << 0)
+#define MG_PLL_BIAS(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_BIAS_PORT1, \
+				     _MG_PLL_BIAS_PORT2)
+
+#define _MG_PLL_TDC_COLDST_BIAS_PORT1			0x168A18
+#define _MG_PLL_TDC_COLDST_BIAS_PORT2			0x169A18
+#define _MG_PLL_TDC_COLDST_BIAS_PORT3			0x16AA18
+#define _MG_PLL_TDC_COLDST_BIAS_PORT4			0x16BA18
+#define   MG_PLL_TDC_COLDST_IREFINT_EN			(1 << 27)
+#define   MG_PLL_TDC_COLDST_REFBIAS_START_PULSE_W(x)	((x) << 17)
+#define   MG_PLL_TDC_COLDST_COLDSTART			(1 << 16)
+#define   MG_PLL_TDC_TDCOVCCORR_EN			(1 << 2)
+#define   MG_PLL_TDC_TDCSEL(x)				((x) << 0)
+#define MG_PLL_TDC_COLDST_BIAS(port) _MMIO_PORT((port) - PORT_C, \
+						_MG_PLL_TDC_COLDST_BIAS_PORT1, \
+						_MG_PLL_TDC_COLDST_BIAS_PORT2)
+
 #define _CNL_DPLL0_CFGCR0		0x6C000
 #define _CNL_DPLL1_CFGCR0		0x6C080
 #define  DPLL_CFGCR0_HDMI_MODE		(1 << 30)
 #define  DPLL_CFGCR0_SSC_ENABLE		(1 << 29)
+#define  DPLL_CFGCR0_SSC_ENABLE_ICL	(1 << 25)
 #define  DPLL_CFGCR0_LINK_RATE_MASK	(0xf << 25)
 #define  DPLL_CFGCR0_LINK_RATE_2700	(0 << 25)
 #define  DPLL_CFGCR0_LINK_RATE_1350	(1 << 25)
@@ -8884,8 +9022,19 @@ enum skl_power_gate {
 #define  DPLL_CFGCR1_PDIV_5		(4 << 2)
 #define  DPLL_CFGCR1_PDIV_7		(8 << 2)
 #define  DPLL_CFGCR1_CENTRAL_FREQ	(3 << 0)
+#define  DPLL_CFGCR1_CENTRAL_FREQ_8400	(3 << 0)
 #define CNL_DPLL_CFGCR1(pll)		_MMIO_PLL(pll, _CNL_DPLL0_CFGCR1, _CNL_DPLL1_CFGCR1)
 
+#define _ICL_DPLL0_CFGCR0		0x164000
+#define _ICL_DPLL1_CFGCR0		0x164080
+#define ICL_DPLL_CFGCR0(pll)		_MMIO_PLL(pll, _ICL_DPLL0_CFGCR0, \
+						  _ICL_DPLL1_CFGCR0)
+
+#define _ICL_DPLL0_CFGCR1		0x164004
+#define _ICL_DPLL1_CFGCR1		0x164084
+#define ICL_DPLL_CFGCR1(pll)		_MMIO_PLL(pll, _ICL_DPLL0_CFGCR1, \
+						  _ICL_DPLL1_CFGCR1)
+
 /* BXT display engine PLL */
 #define BXT_DE_PLL_CTL			_MMIO(0x6d000)
 #define   BXT_DE_PLL_RATIO(x)		(x)	/* {60,65,100} * 19.2MHz */
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 3/8] drm/i915/icl: add basic support for the ICL clocks
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
  2018-03-28 21:57 ` [PATCH 1/8] drm/i915/icl: Don't set pipe CSC/Gamma in PLANE_COLOR_CTL Paulo Zanoni
  2018-03-28 21:57 ` [PATCH 2/8] drm/i915/icl: add definitions for the ICL PLL registers Paulo Zanoni
@ 2018-03-28 21:57 ` Paulo Zanoni
  2018-04-09 23:23   ` James Ausmus
  2018-03-28 21:57 ` [PATCH 4/8] drm/i915/icl: compute the combo PHY (DPLL) HDMI registers Paulo Zanoni
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Paulo Zanoni @ 2018-03-28 21:57 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

This commit introduces the definitions for the ICL clocks and adds the
basic functions to the shared DPLL framework. It adds code for the
Enable and Disable sequences for some PLLs, but it does not have the
code to compute the actual PLL values, which are marked as TODO
comments and should be introduced as separate commits.

Special thanks to James Ausmus for investigating and fixing a bug with
the placement of icl_unmap_plls_to_ports() function.

v2:
 - Rebase around dpll_lock changes.
v3:
 - The spec now says what the timeouts should be.
 - Touch DPCLKA_CFGCR0_ICL at the appropriate time so we don't freeze
   the machine.
 - Checkpatch found a white space problem.
 - Small adjustments before upstreaming.
v4:
 - Move the ICL checks out of the *map_plls_to_ports() functions
  (James)
 - Add extra encoder check (James)
 - Call icl_unmap_plls_to_ports() later (James)
v5:
 - Rebase after the pll struct changes.

Cc: James Ausmus <james.ausmus@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c   |  22 +++
 drivers/gpu/drm/i915/intel_ddi.c      |  98 ++++++++++-
 drivers/gpu/drm/i915/intel_display.c  |  16 ++
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 312 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_dpll_mgr.h |  41 +++++
 drivers/gpu/drm/i915/intel_drv.h      |   6 +
 6 files changed, 490 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index ff90577da450..43a805c39b0a 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3296,6 +3296,28 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
 		seq_printf(m, " fp0:     0x%08x\n", pll->state.hw_state.fp0);
 		seq_printf(m, " fp1:     0x%08x\n", pll->state.hw_state.fp1);
 		seq_printf(m, " wrpll:   0x%08x\n", pll->state.hw_state.wrpll);
+		seq_printf(m, " cfgcr0:  0x%08x\n", pll->state.hw_state.cfgcr0);
+		seq_printf(m, " cfgcr1:  0x%08x\n", pll->state.hw_state.cfgcr1);
+		seq_printf(m, " mg_refclkin_ctl:        0x%08x\n",
+			   pll->state.hw_state.mg_refclkin_ctl);
+		seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n",
+			   pll->state.hw_state.mg_clktop2_coreclkctl1);
+		seq_printf(m, " mg_clktop2_hsclkctl:    0x%08x\n",
+			   pll->state.hw_state.mg_clktop2_hsclkctl);
+		seq_printf(m, " mg_pll_div0:  0x%08x\n",
+			   pll->state.hw_state.mg_pll_div0);
+		seq_printf(m, " mg_pll_div1:  0x%08x\n",
+			   pll->state.hw_state.mg_pll_div1);
+		seq_printf(m, " mg_pll_lf:    0x%08x\n",
+			   pll->state.hw_state.mg_pll_lf);
+		seq_printf(m, " mg_pll_frac_lock: 0x%08x\n",
+			   pll->state.hw_state.mg_pll_frac_lock);
+		seq_printf(m, " mg_pll_ssc:   0x%08x\n",
+			   pll->state.hw_state.mg_pll_ssc);
+		seq_printf(m, " mg_pll_bias:  0x%08x\n",
+			   pll->state.hw_state.mg_pll_bias);
+		seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n",
+			   pll->state.hw_state.mg_pll_tdc_coldst_bias);
 	}
 	drm_modeset_unlock_all(dev);
 
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index a6672a9abd85..10223ffcceab 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1013,6 +1013,25 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
 	}
 }
 
+static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
+				       const struct intel_shared_dpll *pll)
+{
+	const enum intel_dpll_id id = pll->info->id;
+
+	switch (id) {
+	default:
+		MISSING_CASE(id);
+	case DPLL_ID_ICL_DPLL0:
+	case DPLL_ID_ICL_DPLL1:
+		return DDI_CLK_SEL_NONE;
+	case DPLL_ID_ICL_MGPLL1:
+	case DPLL_ID_ICL_MGPLL2:
+	case DPLL_ID_ICL_MGPLL3:
+	case DPLL_ID_ICL_MGPLL4:
+		return DDI_CLK_SEL_MG;
+	}
+}
+
 /* Starting with Haswell, different DDI ports can work in FDI mode for
  * connection to the PCH-located connectors. For this, it is necessary to train
  * both the DDI port and PCH receiver for the desired DDI buffer settings.
@@ -2234,6 +2253,69 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
 	return DDI_BUF_TRANS_SELECT(level);
 }
 
+void icl_map_plls_to_ports(struct drm_crtc *crtc,
+			   struct intel_crtc_state *crtc_state,
+			   struct drm_atomic_state *old_state)
+{
+	struct intel_shared_dpll *pll = crtc_state->shared_dpll;
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+	struct drm_connector_state *conn_state;
+	struct drm_connector *conn;
+	int i;
+
+	for_each_new_connector_in_state(old_state, conn, conn_state, i) {
+		struct intel_encoder *encoder =
+			to_intel_encoder(conn_state->best_encoder);
+		enum port port = encoder->port;
+		uint32_t val;
+
+		if (conn_state->crtc != crtc)
+			continue;
+
+		mutex_lock(&dev_priv->dpll_lock);
+
+		val = I915_READ(DPCLKA_CFGCR0_ICL);
+		WARN_ON((val & DPCLKA_CFGCR0_DDI_CLK_OFF(port)) == 0);
+
+		if (port == PORT_A || port == PORT_B) {
+			val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
+			val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
+			I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+			POSTING_READ(DPCLKA_CFGCR0_ICL);
+		}
+
+		val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
+		I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+
+		mutex_unlock(&dev_priv->dpll_lock);
+	}
+}
+
+void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
+			     struct intel_crtc_state *crtc_state,
+			     struct drm_atomic_state *old_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+	struct drm_connector_state *conn_state;
+	struct drm_connector *conn;
+	int i;
+
+	for_each_new_connector_in_state(old_state, conn, conn_state, i) {
+		struct intel_encoder *encoder =
+			to_intel_encoder(conn_state->best_encoder);
+		enum port port = encoder->port;
+
+		if (!encoder || conn_state->crtc != crtc)
+			continue;
+
+		mutex_lock(&dev_priv->dpll_lock);
+		I915_WRITE(DPCLKA_CFGCR0_ICL,
+			   I915_READ(DPCLKA_CFGCR0_ICL) |
+			   DPCLKA_CFGCR0_DDI_CLK_OFF(port));
+		mutex_unlock(&dev_priv->dpll_lock);
+	}
+}
+
 static void intel_ddi_clk_select(struct intel_encoder *encoder,
 				 const struct intel_shared_dpll *pll)
 {
@@ -2246,7 +2328,11 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
 
 	mutex_lock(&dev_priv->dpll_lock);
 
-	if (IS_CANNONLAKE(dev_priv)) {
+	if (IS_ICELAKE(dev_priv)) {
+		if (port >= PORT_C)
+			I915_WRITE(DDI_CLK_SEL(port),
+				   icl_pll_to_ddi_pll_sel(encoder, pll));
+	} else if (IS_CANNONLAKE(dev_priv)) {
 		/* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */
 		val = I915_READ(DPCLKA_CFGCR0);
 		val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
@@ -2284,14 +2370,18 @@ static void intel_ddi_clk_disable(struct intel_encoder *encoder)
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	enum port port = encoder->port;
 
-	if (IS_CANNONLAKE(dev_priv))
+	if (IS_ICELAKE(dev_priv)) {
+		if (port >= PORT_C)
+			I915_WRITE(DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
+	} else if (IS_CANNONLAKE(dev_priv)) {
 		I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) |
 			   DPCLKA_CFGCR0_DDI_CLK_OFF(port));
-	else if (IS_GEN9_BC(dev_priv))
+	} else if (IS_GEN9_BC(dev_priv)) {
 		I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) |
 			   DPLL_CTRL2_DDI_CLK_OFF(port));
-	else if (INTEL_GEN(dev_priv) < 9)
+	} else if (INTEL_GEN(dev_priv) < 9) {
 		I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
+	}
 }
 
 static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 8b18729bc4d3..64e7943164d5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5508,6 +5508,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 	if (intel_crtc->config->shared_dpll)
 		intel_enable_shared_dpll(intel_crtc);
 
+	if (INTEL_GEN(dev_priv) >= 11)
+		icl_map_plls_to_ports(crtc, pipe_config, old_state);
+
 	if (intel_crtc_has_dp_encoder(intel_crtc->config))
 		intel_dp_set_m_n(intel_crtc, M1_N1);
 
@@ -5705,6 +5708,9 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
 		intel_ddi_disable_pipe_clock(intel_crtc->config);
 
 	intel_encoders_post_disable(crtc, old_crtc_state, old_state);
+
+	if (INTEL_GEN(dev_priv) >= 11)
+		icl_unmap_plls_to_ports(crtc, old_crtc_state, old_state);
 }
 
 static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -11324,6 +11330,16 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
 	PIPE_CONF_CHECK_X(dpll_hw_state.pll9);
 	PIPE_CONF_CHECK_X(dpll_hw_state.pll10);
 	PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias);
 
 	PIPE_CONF_CHECK_X(dsi_pll.ctrl);
 	PIPE_CONF_CHECK_X(dsi_pll.div);
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index d5e114e9660b..470de6a33ca0 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -2399,6 +2399,314 @@ static const struct intel_dpll_mgr cnl_pll_mgr = {
 	.dump_hw_state = cnl_dump_hw_state,
 };
 
+static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
+				struct intel_encoder *encoder, int clock,
+				struct intel_dpll_hw_state *pll_state)
+{
+	/* TODO */
+	return true;
+}
+
+static enum port icl_mg_pll_id_to_port(enum intel_dpll_id id)
+{
+	return id - DPLL_ID_ICL_MGPLL1 + PORT_C;
+}
+
+static enum intel_dpll_id icl_port_to_mg_pll_id(enum port port)
+{
+	return port - PORT_C + DPLL_ID_ICL_MGPLL1;
+}
+
+static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
+				  struct intel_encoder *encoder, int clock,
+				  struct intel_dpll_hw_state *pll_state)
+{
+	/* TODO */
+	return true;
+}
+
+static struct intel_shared_dpll *
+icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+	     struct intel_encoder *encoder)
+{
+	struct intel_shared_dpll *pll;
+	struct intel_dpll_hw_state pll_state = {};
+	enum port port = encoder->port;
+	enum intel_dpll_id min, max;
+	int clock = crtc_state->port_clock;
+	bool ret;
+
+	switch (port) {
+	case PORT_A:
+	case PORT_B:
+		min = DPLL_ID_ICL_DPLL0;
+		max = DPLL_ID_ICL_DPLL1;
+		ret = icl_calc_dpll_state(crtc_state, encoder, clock,
+					  &pll_state);
+		break;
+	case PORT_C:
+	case PORT_D:
+	case PORT_E:
+	case PORT_F:
+		min = max = icl_port_to_mg_pll_id(port);
+		ret = icl_calc_mg_pll_state(crtc_state, encoder, clock,
+					    &pll_state);
+		break;
+	default:
+		MISSING_CASE(port);
+		return NULL;
+	}
+
+	if (!ret) {
+		DRM_DEBUG_KMS("Could not calculate PLL state.\n");
+		return NULL;
+	}
+
+	crtc_state->dpll_hw_state = pll_state;
+
+	pll = intel_find_shared_dpll(crtc, crtc_state, min, max);
+	if (!pll) {
+		DRM_DEBUG_KMS("No PLL selected\n");
+		return NULL;
+	}
+
+	intel_reference_shared_dpll(pll, crtc_state);
+
+	return pll;
+}
+
+static i915_reg_t icl_pll_id_to_enable_reg(enum intel_dpll_id id)
+{
+	switch (id) {
+	default:
+		MISSING_CASE(id);
+	case DPLL_ID_ICL_DPLL0:
+	case DPLL_ID_ICL_DPLL1:
+		return CNL_DPLL_ENABLE(id);
+	case DPLL_ID_ICL_MGPLL1:
+	case DPLL_ID_ICL_MGPLL2:
+	case DPLL_ID_ICL_MGPLL3:
+	case DPLL_ID_ICL_MGPLL4:
+		return MG_PLL_ENABLE(icl_mg_pll_id_to_port(id));
+	}
+}
+
+static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
+				 struct intel_shared_dpll *pll,
+				 struct intel_dpll_hw_state *hw_state)
+{
+	const enum intel_dpll_id id = pll->info->id;
+	uint32_t val;
+	enum port port;
+	bool ret = false;
+
+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+		return false;
+
+	val = I915_READ(icl_pll_id_to_enable_reg(id));
+	if (!(val & PLL_ENABLE))
+		goto out;
+
+	switch (id) {
+	case DPLL_ID_ICL_DPLL0:
+	case DPLL_ID_ICL_DPLL1:
+		hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(id));
+		hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(id));
+		break;
+	case DPLL_ID_ICL_MGPLL1:
+	case DPLL_ID_ICL_MGPLL2:
+	case DPLL_ID_ICL_MGPLL3:
+	case DPLL_ID_ICL_MGPLL4:
+		port = icl_mg_pll_id_to_port(id);
+		hw_state->mg_refclkin_ctl = I915_READ(MG_REFCLKIN_CTL(port));
+		hw_state->mg_clktop2_coreclkctl1 =
+			I915_READ(MG_CLKTOP2_CORECLKCTL1(port));
+		hw_state->mg_clktop2_hsclkctl =
+			I915_READ(MG_CLKTOP2_HSCLKCTL(port));
+		hw_state->mg_pll_div0 = I915_READ(MG_PLL_DIV0(port));
+		hw_state->mg_pll_div1 = I915_READ(MG_PLL_DIV1(port));
+		hw_state->mg_pll_lf = I915_READ(MG_PLL_LF(port));
+		hw_state->mg_pll_frac_lock = I915_READ(MG_PLL_FRAC_LOCK(port));
+		hw_state->mg_pll_ssc = I915_READ(MG_PLL_SSC(port));
+		hw_state->mg_pll_bias = I915_READ(MG_PLL_BIAS(port));
+		hw_state->mg_pll_tdc_coldst_bias =
+			I915_READ(MG_PLL_TDC_COLDST_BIAS(port));
+		break;
+	default:
+		MISSING_CASE(id);
+	}
+
+	ret = true;
+out:
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	return ret;
+}
+
+static void icl_dpll_write(struct drm_i915_private *dev_priv,
+			   struct intel_shared_dpll *pll)
+{
+	struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
+	const enum intel_dpll_id id = pll->info->id;
+
+	I915_WRITE(ICL_DPLL_CFGCR0(id), hw_state->cfgcr0);
+	I915_WRITE(ICL_DPLL_CFGCR1(id), hw_state->cfgcr1);
+	POSTING_READ(ICL_DPLL_CFGCR1(id));
+}
+
+static void icl_mg_pll_write(struct drm_i915_private *dev_priv,
+			     struct intel_shared_dpll *pll)
+{
+	struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
+	enum port port = icl_mg_pll_id_to_port(pll->info->id);
+
+	I915_WRITE(MG_REFCLKIN_CTL(port), hw_state->mg_refclkin_ctl);
+	I915_WRITE(MG_CLKTOP2_CORECLKCTL1(port),
+		   hw_state->mg_clktop2_coreclkctl1);
+	I915_WRITE(MG_CLKTOP2_HSCLKCTL(port), hw_state->mg_clktop2_hsclkctl);
+	I915_WRITE(MG_PLL_DIV0(port), hw_state->mg_pll_div0);
+	I915_WRITE(MG_PLL_DIV1(port), hw_state->mg_pll_div1);
+	I915_WRITE(MG_PLL_LF(port), hw_state->mg_pll_lf);
+	I915_WRITE(MG_PLL_FRAC_LOCK(port), hw_state->mg_pll_frac_lock);
+	I915_WRITE(MG_PLL_SSC(port), hw_state->mg_pll_ssc);
+	I915_WRITE(MG_PLL_BIAS(port), hw_state->mg_pll_bias);
+	I915_WRITE(MG_PLL_TDC_COLDST_BIAS(port),
+		   hw_state->mg_pll_tdc_coldst_bias);
+	POSTING_READ(MG_PLL_TDC_COLDST_BIAS(port));
+}
+
+static void icl_pll_enable(struct drm_i915_private *dev_priv,
+			   struct intel_shared_dpll *pll)
+{
+	const enum intel_dpll_id id = pll->info->id;
+	i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
+	uint32_t val;
+
+	val = I915_READ(enable_reg);
+	val |= PLL_POWER_ENABLE;
+	I915_WRITE(enable_reg, val);
+
+	/*
+	 * The spec says we need to "wait" but it also says it should be
+	 * immediate.
+	 */
+	if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE,
+				    PLL_POWER_STATE, 1))
+		DRM_ERROR("PLL %d Power not enabled\n", id);
+
+	switch (id) {
+	case DPLL_ID_ICL_DPLL0:
+	case DPLL_ID_ICL_DPLL1:
+		icl_dpll_write(dev_priv, pll);
+		break;
+	case DPLL_ID_ICL_MGPLL1:
+	case DPLL_ID_ICL_MGPLL2:
+	case DPLL_ID_ICL_MGPLL3:
+	case DPLL_ID_ICL_MGPLL4:
+		icl_mg_pll_write(dev_priv, pll);
+		break;
+	default:
+		MISSING_CASE(id);
+	}
+
+	/*
+	 * DVFS pre sequence would be here, but in our driver the cdclk code
+	 * paths should already be setting the appropriate voltage, hence we do
+	 * nothign here.
+	 */
+
+	val = I915_READ(enable_reg);
+	val |= PLL_ENABLE;
+	I915_WRITE(enable_reg, val);
+
+	if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, PLL_LOCK,
+				    1)) /* 600us actually. */
+		DRM_ERROR("PLL %d not locked\n", id);
+
+	/* DVFS post sequence would be here. See the comment above. */
+}
+
+static void icl_pll_disable(struct drm_i915_private *dev_priv,
+			    struct intel_shared_dpll *pll)
+{
+	const enum intel_dpll_id id = pll->info->id;
+	i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
+	uint32_t val;
+
+	/* The first steps are done by intel_ddi_post_disable(). */
+
+	/*
+	 * DVFS pre sequence would be here, but in our driver the cdclk code
+	 * paths should already be setting the appropriate voltage, hence we do
+	 * nothign here.
+	 */
+
+	val = I915_READ(enable_reg);
+	val &= ~PLL_ENABLE;
+	I915_WRITE(enable_reg, val);
+
+	/* Timeout is actually 1us. */
+	if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, 0, 1))
+		DRM_ERROR("PLL %d locked\n", id);
+
+	/* DVFS post sequence would be here. See the comment above. */
+
+	val = I915_READ(enable_reg);
+	val &= ~PLL_POWER_ENABLE;
+	I915_WRITE(enable_reg, val);
+
+	/*
+	 * The spec says we need to "wait" but it also says it should be
+	 * immediate.
+	 */
+	if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE, 0,
+				    1))
+		DRM_ERROR("PLL %d Power not disabled\n", id);
+}
+
+static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
+			      struct intel_dpll_hw_state *hw_state)
+{
+	DRM_DEBUG_KMS("dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, "
+		      "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
+		      "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, "
+		      "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, "
+		      "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, "
+		      "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n",
+		      hw_state->cfgcr0, hw_state->cfgcr1,
+		      hw_state->mg_refclkin_ctl,
+		      hw_state->mg_clktop2_coreclkctl1,
+		      hw_state->mg_clktop2_hsclkctl,
+		      hw_state->mg_pll_div0,
+		      hw_state->mg_pll_div1,
+		      hw_state->mg_pll_lf,
+		      hw_state->mg_pll_frac_lock,
+		      hw_state->mg_pll_ssc,
+		      hw_state->mg_pll_bias,
+		      hw_state->mg_pll_tdc_coldst_bias);
+}
+
+static const struct intel_shared_dpll_funcs icl_pll_funcs = {
+	.enable = icl_pll_enable,
+	.disable = icl_pll_disable,
+	.get_hw_state = icl_pll_get_hw_state,
+};
+
+static const struct dpll_info icl_plls[] = {
+	{ "DPLL 0",   &icl_pll_funcs, DPLL_ID_ICL_DPLL0,  0 },
+	{ "DPLL 1",   &icl_pll_funcs, DPLL_ID_ICL_DPLL1,  0 },
+	{ "MG PLL 1", &icl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 },
+	{ "MG PLL 2", &icl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 },
+	{ "MG PLL 3", &icl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 },
+	{ "MG PLL 4", &icl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 },
+	{ },
+};
+
+static const struct intel_dpll_mgr icl_pll_mgr = {
+	.dpll_info = icl_plls,
+	.get_dpll = icl_get_dpll,
+	.dump_hw_state = icl_dump_hw_state,
+};
+
 /**
  * intel_shared_dpll_init - Initialize shared DPLLs
  * @dev: drm device
@@ -2412,7 +2720,9 @@ void intel_shared_dpll_init(struct drm_device *dev)
 	const struct dpll_info *dpll_info;
 	int i;
 
-	if (IS_CANNONLAKE(dev_priv))
+	if (IS_ICELAKE(dev_priv))
+		dpll_mgr = &icl_pll_mgr;
+	else if (IS_CANNONLAKE(dev_priv))
 		dpll_mgr = &cnl_pll_mgr;
 	else if (IS_GEN9_BC(dev_priv))
 		dpll_mgr = &skl_pll_mgr;
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
index 4febfaa90bde..7a0cd564a9ee 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h
@@ -103,6 +103,32 @@ enum intel_dpll_id {
 	 * @DPLL_ID_SKL_DPLL3: SKL and later DPLL3
 	 */
 	DPLL_ID_SKL_DPLL3 = 3,
+
+
+	/**
+	 * @DPLL_ID_ICL_DPLL0: ICL combo PHY DPLL0
+	 */
+	DPLL_ID_ICL_DPLL0 = 0,
+	/**
+	 * @DPLL_ID_ICL_DPLL1: ICL combo PHY DPLL1
+	 */
+	DPLL_ID_ICL_DPLL1 = 1,
+	/**
+	 * @DPLL_ID_ICL_MGPLL1: ICL MG PLL 1 port 1 (C)
+	 */
+	DPLL_ID_ICL_MGPLL1 = 2,
+	/**
+	 * @DPLL_ID_ICL_MGPLL2: ICL MG PLL 1 port 2 (D)
+	 */
+	DPLL_ID_ICL_MGPLL2 = 3,
+	/**
+	 * @DPLL_ID_ICL_MGPLL3: ICL MG PLL 1 port 3 (E)
+	 */
+	DPLL_ID_ICL_MGPLL3 = 4,
+	/**
+	 * @DPLL_ID_ICL_MGPLL4: ICL MG PLL 1 port 4 (F)
+	 */
+	DPLL_ID_ICL_MGPLL4 = 5,
 };
 #define I915_NUM_PLLS 6
 
@@ -135,6 +161,21 @@ struct intel_dpll_hw_state {
 	/* bxt */
 	uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
 		 pcsdw12;
+
+	/*
+	 * ICL uses the following, already defined:
+	 * uint32_t cfgcr0, cfgcr1;
+	 */
+	uint32_t mg_refclkin_ctl;
+	uint32_t mg_clktop2_coreclkctl1;
+	uint32_t mg_clktop2_hsclkctl;
+	uint32_t mg_pll_div0;
+	uint32_t mg_pll_div1;
+	uint32_t mg_pll_lf;
+	uint32_t mg_pll_frac_lock;
+	uint32_t mg_pll_ssc;
+	uint32_t mg_pll_bias;
+	uint32_t mg_pll_tdc_coldst_bias;
 };
 
 /**
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d1452fd2a58d..d77306950676 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1393,6 +1393,12 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp);
 u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
 int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
 				     bool enable);
+void icl_map_plls_to_ports(struct drm_crtc *crtc,
+			   struct intel_crtc_state *crtc_state,
+			   struct drm_atomic_state *old_state);
+void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
+			     struct intel_crtc_state *crtc_state,
+			     struct drm_atomic_state *old_state);
 
 unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
 				   int plane, unsigned int height);
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 4/8] drm/i915/icl: compute the combo PHY (DPLL) HDMI registers
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
                   ` (2 preceding siblings ...)
  2018-03-28 21:57 ` [PATCH 3/8] drm/i915/icl: add basic support for the ICL clocks Paulo Zanoni
@ 2018-03-28 21:57 ` Paulo Zanoni
  2018-03-28 21:58 ` [PATCH 5/8] drm/i915/icl: compute the combo PHY (DPLL) DP registers Paulo Zanoni
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Paulo Zanoni @ 2018-03-28 21:57 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

HDMI mode DPLL programming on ICL is the same as CNL, so just reuse
the CNL code.

v2:
 - Properly detect HDMI crtcs.
 - Rebase after changes to the cnl function (clock * 1000).
v3:
 - Add a comment to clarify why we treat 38.4 as 19.2 (James).

Reviewed-by: James Ausmus <james.ausmus@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 39 ++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index 470de6a33ca0..7fad122b45d4 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -2218,6 +2218,7 @@ cnl_ddi_calculate_wrpll(int clock,
 			struct skl_wrpll_params *wrpll_params)
 {
 	u32 afe_clock = clock * 5;
+	uint32_t ref_clock;
 	u32 dco_min = 7998000;
 	u32 dco_max = 10000000;
 	u32 dco_mid = (dco_min + dco_max) / 2;
@@ -2250,8 +2251,17 @@ cnl_ddi_calculate_wrpll(int clock,
 
 	cnl_wrpll_get_multipliers(best_div, &pdiv, &qdiv, &kdiv);
 
-	cnl_wrpll_params_populate(wrpll_params, best_dco,
-				  dev_priv->cdclk.hw.ref, pdiv, qdiv, kdiv);
+	ref_clock = dev_priv->cdclk.hw.ref;
+
+	/*
+	 * For ICL, the spec states: if reference frequency is 38.4, use 19.2
+	 * because the DPLL automatically divides that by 2.
+	 */
+	if (IS_ICELAKE(dev_priv) && ref_clock == 38400)
+		ref_clock = 19200;
+
+	cnl_wrpll_params_populate(wrpll_params, best_dco, ref_clock, pdiv, qdiv,
+				  kdiv);
 
 	return true;
 }
@@ -2403,7 +2413,30 @@ static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
 				struct intel_encoder *encoder, int clock,
 				struct intel_dpll_hw_state *pll_state)
 {
-	/* TODO */
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	uint32_t cfgcr0, cfgcr1;
+	struct skl_wrpll_params pll_params = { 0 };
+	bool ret;
+
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
+		ret = cnl_ddi_calculate_wrpll(clock, dev_priv, &pll_params);
+	else
+		ret = false; /* TODO */
+
+	if (!ret)
+		return false;
+
+	cfgcr0 = DPLL_CFGCR0_DCO_FRACTION(pll_params.dco_fraction) |
+		 pll_params.dco_integer;
+
+	cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(pll_params.qdiv_ratio) |
+		 DPLL_CFGCR1_QDIV_MODE(pll_params.qdiv_mode) |
+		 DPLL_CFGCR1_KDIV(pll_params.kdiv) |
+		 DPLL_CFGCR1_PDIV(pll_params.pdiv) |
+		 DPLL_CFGCR1_CENTRAL_FREQ_8400;
+
+	pll_state->cfgcr0 = cfgcr0;
+	pll_state->cfgcr1 = cfgcr1;
 	return true;
 }
 
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 5/8] drm/i915/icl: compute the combo PHY (DPLL) DP registers
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
                   ` (3 preceding siblings ...)
  2018-03-28 21:57 ` [PATCH 4/8] drm/i915/icl: compute the combo PHY (DPLL) HDMI registers Paulo Zanoni
@ 2018-03-28 21:58 ` Paulo Zanoni
  2018-03-28 21:58 ` [PATCH 6/8] drm/i915/icl: compute the MG PLL registers Paulo Zanoni
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Paulo Zanoni @ 2018-03-28 21:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

Just use the hardcoded tables provided by our spec.

v2: Rebase.
v3: Clarify that 38.4 uses the 19.2 table (James).

Reviewed-by: James Ausmus <james.ausmus@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 87 ++++++++++++++++++++++++++++++++++-
 1 file changed, 86 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index 7fad122b45d4..d305f20c53c9 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -2409,6 +2409,91 @@ static const struct intel_dpll_mgr cnl_pll_mgr = {
 	.dump_hw_state = cnl_dump_hw_state,
 };
 
+/*
+ * These values alrea already adjusted: they're the bits we write to the
+ * registers, not the logical values.
+ */
+static const struct skl_wrpll_params icl_dp_combo_pll_24MHz_values[] = {
+	{ .dco_integer = 0x151, .dco_fraction = 0x4000,		/* [0]: 5.4 */
+	  .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x151, .dco_fraction = 0x4000,		/* [1]: 2.7 */
+	  .pdiv = 0x2 /* 3 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x151, .dco_fraction = 0x4000,		/* [2]: 1.62 */
+	  .pdiv = 0x4 /* 5 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x151, .dco_fraction = 0x4000,		/* [3]: 3.24 */
+	  .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x168, .dco_fraction = 0x0000,		/* [4]: 2.16 */
+	  .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 1, .qdiv_ratio = 2},
+	{ .dco_integer = 0x168, .dco_fraction = 0x0000,		/* [5]: 4.32 */
+	  .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x195, .dco_fraction = 0x0000,		/* [6]: 6.48 */
+	  .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x151, .dco_fraction = 0x4000,		/* [7]: 8.1 */
+	  .pdiv = 0x1 /* 2 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0},
+};
+
+/* Also used for 38.4 MHz values. */
+static const struct skl_wrpll_params icl_dp_combo_pll_19_2MHz_values[] = {
+	{ .dco_integer = 0x1A5, .dco_fraction = 0x7000,		/* [0]: 5.4 */
+	  .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x1A5, .dco_fraction = 0x7000,		/* [1]: 2.7 */
+	  .pdiv = 0x2 /* 3 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x1A5, .dco_fraction = 0x7000,		/* [2]: 1.62 */
+	  .pdiv = 0x4 /* 5 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x1A5, .dco_fraction = 0x7000,		/* [3]: 3.24 */
+	  .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x1C2, .dco_fraction = 0x0000,		/* [4]: 2.16 */
+	  .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 1, .qdiv_ratio = 2},
+	{ .dco_integer = 0x1C2, .dco_fraction = 0x0000,		/* [5]: 4.32 */
+	  .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x1FA, .dco_fraction = 0x2000,		/* [6]: 6.48 */
+	  .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0},
+	{ .dco_integer = 0x1A5, .dco_fraction = 0x7000,		/* [7]: 8.1 */
+	  .pdiv = 0x1 /* 2 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0},
+};
+
+static bool icl_calc_dp_combo_pll(struct drm_i915_private *dev_priv, int clock,
+				  struct skl_wrpll_params *pll_params)
+{
+	const struct skl_wrpll_params *params;
+
+	params = dev_priv->cdclk.hw.ref == 24000 ?
+			icl_dp_combo_pll_24MHz_values :
+			icl_dp_combo_pll_19_2MHz_values;
+
+	switch (clock) {
+	case 540000:
+		*pll_params = params[0];
+		break;
+	case 270000:
+		*pll_params = params[1];
+		break;
+	case 162000:
+		*pll_params = params[2];
+		break;
+	case 324000:
+		*pll_params = params[3];
+		break;
+	case 216000:
+		*pll_params = params[4];
+		break;
+	case 432000:
+		*pll_params = params[5];
+		break;
+	case 648000:
+		*pll_params = params[6];
+		break;
+	case 810000:
+		*pll_params = params[7];
+		break;
+	default:
+		MISSING_CASE(clock);
+		return false;
+	}
+
+	return true;
+}
+
 static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
 				struct intel_encoder *encoder, int clock,
 				struct intel_dpll_hw_state *pll_state)
@@ -2421,7 +2506,7 @@ static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
 		ret = cnl_ddi_calculate_wrpll(clock, dev_priv, &pll_params);
 	else
-		ret = false; /* TODO */
+		ret = icl_calc_dp_combo_pll(dev_priv, clock, &pll_params);
 
 	if (!ret)
 		return false;
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 6/8] drm/i915/icl: compute the MG PLL registers
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
                   ` (4 preceding siblings ...)
  2018-03-28 21:58 ` [PATCH 5/8] drm/i915/icl: compute the combo PHY (DPLL) DP registers Paulo Zanoni
@ 2018-03-28 21:58 ` Paulo Zanoni
  2018-03-28 21:58 ` [PATCH 7/8] drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI Paulo Zanoni
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Paulo Zanoni @ 2018-03-28 21:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

This implements the "MG PLL Programming" sequence from our spec. The
biggest problem was that the spec assumes real numbers, so we had to
adjust some numbers and alculations due to the fact that the Kernel
prefers to deal with integers.

I recommend grabbing some coffee, a pen and paper before reviewing
this patch.

v2:
 - Correctly identify DP encoders after upstream change.
 - Small checkpatch issues.
 - Rebase.
v3:
 - Try to impove the comment on the tdc_targetcnt calculation based on
   Manasi's feedback (Manasi).
 - Rebase.

Reviewed-by; Manasi Navare <manasi.d.navare@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 223 +++++++++++++++++++++++++++++++++-
 1 file changed, 222 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index d305f20c53c9..1c5971b4a9b7 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -2535,11 +2535,232 @@ static enum intel_dpll_id icl_port_to_mg_pll_id(enum port port)
 	return port - PORT_C + DPLL_ID_ICL_MGPLL1;
 }
 
+static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc,
+				     uint32_t *target_dco_khz,
+				     struct intel_dpll_hw_state *state)
+{
+	uint32_t dco_min_freq, dco_max_freq;
+	int div1_vals[] = {7, 5, 3, 2};
+	unsigned int i;
+	int div2;
+
+	dco_min_freq = is_dp ? 8100000 : use_ssc ? 8000000 : 7992000;
+	dco_max_freq = is_dp ? 8100000 : 10000000;
+
+	for (i = 0; i < ARRAY_SIZE(div1_vals); i++) {
+		int div1 = div1_vals[i];
+
+		for (div2 = 10; div2 > 0; div2--) {
+			int dco = div1 * div2 * clock_khz * 5;
+			int a_divratio, tlinedrv, inputsel, hsdiv;
+
+			if (dco < dco_min_freq || dco > dco_max_freq)
+				continue;
+
+			if (div2 >= 2) {
+				a_divratio = is_dp ? 10 : 5;
+				tlinedrv = 2;
+			} else {
+				a_divratio = 5;
+				tlinedrv = 0;
+			}
+			inputsel = is_dp ? 0 : 1;
+
+			switch (div1) {
+			default:
+				MISSING_CASE(div1);
+			case 2:
+				hsdiv = 0;
+				break;
+			case 3:
+				hsdiv = 1;
+				break;
+			case 5:
+				hsdiv = 2;
+				break;
+			case 7:
+				hsdiv = 3;
+				break;
+			}
+
+			*target_dco_khz = dco;
+
+			state->mg_refclkin_ctl = MG_REFCLKIN_CTL_OD_2_MUX(1);
+
+			state->mg_clktop2_coreclkctl1 =
+				MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO(a_divratio);
+
+			state->mg_clktop2_hsclkctl =
+				MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL(tlinedrv) |
+				MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL(inputsel) |
+				MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO(hsdiv) |
+				MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO(div2);
+
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/*
+ * The specification for this function uses real numbers, so the math had to be
+ * adapted to integer-only calculation, that's why it looks so different.
+ */
 static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
 				  struct intel_encoder *encoder, int clock,
 				  struct intel_dpll_hw_state *pll_state)
 {
-	/* TODO */
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	int refclk_khz = dev_priv->cdclk.hw.ref;
+	uint32_t dco_khz, m1div, m2div_int, m2div_rem, m2div_frac;
+	uint32_t iref_ndiv, iref_trim, iref_pulse_w;
+	uint32_t prop_coeff, int_coeff;
+	uint32_t tdc_targetcnt, feedfwgain;
+	uint64_t ssc_stepsize, ssc_steplen, ssc_steplog;
+	uint64_t tmp;
+	bool use_ssc = false;
+	bool is_dp = !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI);
+
+	if (!icl_mg_pll_find_divisors(clock, is_dp, use_ssc, &dco_khz,
+				      pll_state)) {
+		DRM_DEBUG_KMS("Failed to find divisors for clock %d\n", clock);
+		return false;
+	}
+
+	m1div = 2;
+	m2div_int = dco_khz / (refclk_khz * m1div);
+	if (m2div_int > 255) {
+		m1div = 4;
+		m2div_int = dco_khz / (refclk_khz * m1div);
+		if (m2div_int > 255) {
+			DRM_DEBUG_KMS("Failed to find mdiv for clock %d\n",
+				      clock);
+			return false;
+		}
+	}
+	m2div_rem = dco_khz % (refclk_khz * m1div);
+
+	tmp = (uint64_t)m2div_rem * (1 << 22);
+	do_div(tmp, refclk_khz * m1div);
+	m2div_frac = tmp;
+
+	switch (refclk_khz) {
+	case 19200:
+		iref_ndiv = 1;
+		iref_trim = 28;
+		iref_pulse_w = 1;
+		break;
+	case 24000:
+		iref_ndiv = 1;
+		iref_trim = 25;
+		iref_pulse_w = 2;
+		break;
+	case 38400:
+		iref_ndiv = 2;
+		iref_trim = 28;
+		iref_pulse_w = 1;
+		break;
+	default:
+		MISSING_CASE(refclk_khz);
+		return false;
+	}
+
+	/*
+	 * tdc_res = 0.000003
+	 * tdc_targetcnt = int(2 / (tdc_res * 8 * 50 * 1.1) / refclk_mhz + 0.5)
+	 *
+	 * The multiplication by 1000 is due to refclk MHz to KHz conversion. It
+	 * was supposed to be a division, but we rearranged the operations of
+	 * the formula to avoid early divisions so we don't multiply the
+	 * rounding errors.
+	 *
+	 * 0.000003 * 8 * 50 * 1.1 = 0.00132, also known as 132 / 100000, which
+	 * we also rearrange to work with integers.
+	 *
+	 * The 0.5 transformed to 5 results in a multiplication by 10 and the
+	 * last division by 10.
+	 */
+	tdc_targetcnt = (2 * 1000 * 100000 * 10 / (132 * refclk_khz) + 5) / 10;
+
+	/*
+	 * Here we divide dco_khz by 10 in order to allow the dividend to fit in
+	 * 32 bits. That's not a problem since we round the division down
+	 * anyway.
+	 */
+	feedfwgain = (use_ssc || m2div_rem > 0) ?
+		m1div * 1000000 * 100 / (dco_khz * 3 / 10) : 0;
+
+	if (dco_khz >= 9000000) {
+		prop_coeff = 5;
+		int_coeff = 10;
+	} else {
+		prop_coeff = 4;
+		int_coeff = 8;
+	}
+
+	if (use_ssc) {
+		tmp = (uint64_t)dco_khz * 47 * 32;
+		do_div(tmp, refclk_khz * m1div * 10000);
+		ssc_stepsize = tmp;
+
+		tmp = (uint64_t)dco_khz * 1000;
+		ssc_steplen = DIV_ROUND_UP_ULL(tmp, 32 * 2 * 32);
+	} else {
+		ssc_stepsize = 0;
+		ssc_steplen = 0;
+	}
+	ssc_steplog = 4;
+
+	pll_state->mg_pll_div0 = (m2div_rem > 0 ? MG_PLL_DIV0_FRACNEN_H : 0) |
+				  MG_PLL_DIV0_FBDIV_FRAC(m2div_frac) |
+				  MG_PLL_DIV0_FBDIV_INT(m2div_int);
+
+	pll_state->mg_pll_div1 = MG_PLL_DIV1_IREF_NDIVRATIO(iref_ndiv) |
+				 MG_PLL_DIV1_DITHER_DIV_2 |
+				 MG_PLL_DIV1_NDIVRATIO(1) |
+				 MG_PLL_DIV1_FBPREDIV(m1div);
+
+	pll_state->mg_pll_lf = MG_PLL_LF_TDCTARGETCNT(tdc_targetcnt) |
+			       MG_PLL_LF_AFCCNTSEL_512 |
+			       MG_PLL_LF_GAINCTRL(1) |
+			       MG_PLL_LF_INT_COEFF(int_coeff) |
+			       MG_PLL_LF_PROP_COEFF(prop_coeff);
+
+	pll_state->mg_pll_frac_lock = MG_PLL_FRAC_LOCK_TRUELOCK_CRIT_32 |
+				      MG_PLL_FRAC_LOCK_EARLYLOCK_CRIT_32 |
+				      MG_PLL_FRAC_LOCK_LOCKTHRESH(10) |
+				      MG_PLL_FRAC_LOCK_DCODITHEREN |
+				      MG_PLL_FRAC_LOCK_FEEDFWRDGAIN(feedfwgain);
+	if (use_ssc || m2div_rem > 0)
+		pll_state->mg_pll_frac_lock |= MG_PLL_FRAC_LOCK_FEEDFWRDCAL_EN;
+
+	pll_state->mg_pll_ssc = (use_ssc ? MG_PLL_SSC_EN : 0) |
+				MG_PLL_SSC_TYPE(2) |
+				MG_PLL_SSC_STEPLENGTH(ssc_steplen) |
+				MG_PLL_SSC_STEPNUM(ssc_steplog) |
+				MG_PLL_SSC_FLLEN |
+				MG_PLL_SSC_STEPSIZE(ssc_stepsize);
+
+	pll_state->mg_pll_tdc_coldst_bias = MG_PLL_TDC_COLDST_COLDSTART;
+
+	if (refclk_khz != 38400) {
+		pll_state->mg_pll_tdc_coldst_bias |=
+			MG_PLL_TDC_COLDST_IREFINT_EN |
+			MG_PLL_TDC_COLDST_REFBIAS_START_PULSE_W(iref_pulse_w) |
+			MG_PLL_TDC_COLDST_COLDSTART |
+			MG_PLL_TDC_TDCOVCCORR_EN |
+			MG_PLL_TDC_TDCSEL(3);
+
+		pll_state->mg_pll_bias = MG_PLL_BIAS_BIAS_GB_SEL(3) |
+					 MG_PLL_BIAS_INIT_DCOAMP(0x3F) |
+					 MG_PLL_BIAS_BIAS_BONUS(10) |
+					 MG_PLL_BIAS_BIASCAL_EN |
+					 MG_PLL_BIAS_CTRIM(12) |
+					 MG_PLL_BIAS_VREF_RDAC(4) |
+					 MG_PLL_BIAS_IREFTRIM(iref_trim);
+	}
+
 	return true;
 }
 
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 7/8] drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
                   ` (5 preceding siblings ...)
  2018-03-28 21:58 ` [PATCH 6/8] drm/i915/icl: compute the MG PLL registers Paulo Zanoni
@ 2018-03-28 21:58 ` Paulo Zanoni
  2018-03-31  9:53   ` kbuild test robot
  2018-03-28 21:58 ` [PATCH 8/8] drm/i915/icl: Fix the DP Max Voltage for ICL Paulo Zanoni
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 20+ messages in thread
From: Paulo Zanoni @ 2018-03-28 21:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Rodrigo Vivi, Paulo Zanoni

From: Manasi Navare <manasi.d.navare@intel.com>

This is an important part of the DDI initalization as well as
for changing the voltage during DisplayPort link training.

The Voltage swing seqeuence is similar to Cannonlake.
However it has different register definitions and hence
it makes sense to create a separate vswing sequence and
program functions for ICL to leave room for more changes
in case the Bspec changes later and deviates from CNL sequence.

v2:
Use ~TAP3_DISABLE for enbaling that bit (Jani Nikula)

v3:
* Use dw4_scaling column for PORT_TX_DW4 values (Rodrigo)

v4:
* Call it combo_vswing, use switch statement (Paulo)

v5 (from Paulo):
* Fix a typo.
* s/rate < 600000/rate <= 600000/.
* Don't remove blank lines that should be there.

v6:
* Rebased by Rodrigo on top of Cannonlake changes
  where non vswing sequences are not aligned with iboost
  anymore.

v7: Another rebase after an upstream rework.

v8 (from Paulo):
* Adjust the code to the upstream output type changes.
* Squash the patch that moved some functions up.
* Merge both get_combo_buf_trans functions in order to simplify the
  code.
* Change the changelog format.

v9 (from Paulo):
* Use RTERM_SELECT instead of SCALING_MODE_SEL.
* Adjust the output type handling according to how the other platforms
  do it now.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: James Ausmus <james.ausmus@intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 191 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 188 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 10223ffcceab..bfe3e10e080d 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -870,6 +870,45 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
 	}
 }
 
+static const struct icl_combo_phy_ddi_buf_trans *
+icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port,
+			int type, int *n_entries)
+{
+	u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK;
+
+	if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
+		switch (voltage) {
+		case VOLTAGE_INFO_0_85V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V);
+			return icl_combo_phy_ddi_translations_edp_0_85V;
+		case VOLTAGE_INFO_0_95V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V);
+			return icl_combo_phy_ddi_translations_edp_0_95V;
+		case VOLTAGE_INFO_1_05V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V);
+			return icl_combo_phy_ddi_translations_edp_1_05V;
+		default:
+			MISSING_CASE(voltage);
+			return NULL;
+		}
+	} else {
+		switch (voltage) {
+		case VOLTAGE_INFO_0_85V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V);
+			return icl_combo_phy_ddi_translations_dp_hdmi_0_85V;
+		case VOLTAGE_INFO_0_95V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V);
+			return icl_combo_phy_ddi_translations_dp_hdmi_0_95V;
+		case VOLTAGE_INFO_1_05V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
+			return icl_combo_phy_ddi_translations_dp_hdmi_1_05V;
+		default:
+			MISSING_CASE(voltage);
+			return NULL;
+		}
+	}
+}
+
 static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port)
 {
 	int n_entries, level, default_entry;
@@ -2201,6 +2240,146 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,
 	I915_WRITE(CNL_PORT_TX_DW5_GRP(port), val);
 }
 
+static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
+					 u32 level, enum port port, int type)
+{
+	const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL;
+	u32 n_entries, val;
+	int ln;
+
+	ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type,
+						   &n_entries);
+	if (!ddi_translations)
+		return;
+
+	if (level >= n_entries) {
+		DRM_DEBUG_KMS("DDI translation not found for level %d. Using %d instead.", level, n_entries - 1);
+		level = n_entries - 1;
+	}
+
+	/* Set PORT_TX_DW5 Scaling Mode Sel to 110b. */
+	val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+	val &= ~RTERM_SELECT_MASK;
+	val |= RTERM_SELECT(0x6);
+	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
+
+	/* Program PORT_TX_DW5 */
+	val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+	/* Set DisableTap2 and DisableTap3 if MIPI DSI
+	 * Clear DisableTap2 and DisableTap3 for all other Ports
+	 */
+	if (type == INTEL_OUTPUT_DSI) {
+		val |= TAP2_DISABLE;
+		val |= TAP3_DISABLE;
+	} else {
+		val &= ~TAP2_DISABLE;
+		val &= ~TAP3_DISABLE;
+	}
+	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
+
+	/* Program PORT_TX_DW2 */
+	val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
+	val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
+		 RCOMP_SCALAR_MASK);
+	val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
+	val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
+	/* Program Rcomp scalar for every table entry */
+	val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
+	I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
+
+	/* Program PORT_TX_DW4 */
+	/* We cannot write to GRP. It would overwrite individual loadgen. */
+	for (ln = 0; ln <= 3; ln++) {
+		val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
+		val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
+			 CURSOR_COEFF_MASK);
+		val |= ddi_translations[level].dw4_scaling;
+		I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
+	}
+}
+
+static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
+					      u32 level,
+					      enum intel_output_type type)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum port port = encoder->port;
+	int width = 0;
+	int rate = 0;
+	u32 val;
+	int ln = 0;
+
+	if (type == INTEL_OUTPUT_HDMI) {
+		width = 4;
+		/* Rate is always < than 6GHz for HDMI */
+	} else {
+		struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+		width = intel_dp->lane_count;
+		rate = intel_dp->link_rate;
+	}
+
+	/*
+	 * 1. If port type is eDP or DP,
+	 * set PORT_PCS_DW1 cmnkeeper_enable to 1b,
+	 * else clear to 0b.
+	 */
+	val = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
+	if (type == INTEL_OUTPUT_HDMI)
+		val &= ~COMMON_KEEPER_EN;
+	else
+		val |= COMMON_KEEPER_EN;
+	I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), val);
+
+	/* 2. Program loadgen select */
+	/*
+	 * Program PORT_TX_DW4_LN depending on Bit rate and used lanes
+	 * <= 6 GHz and 4 lanes (LN0=0, LN1=1, LN2=1, LN3=1)
+	 * <= 6 GHz and 1,2 lanes (LN0=0, LN1=1, LN2=1, LN3=0)
+	 * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0)
+	 */
+	for (ln = 0; ln <= 3; ln++) {
+		val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
+		val &= ~LOADGEN_SELECT;
+
+		if ((rate <= 600000 && width == 4 && ln >= 1) ||
+		    (rate <= 600000 && width < 4 && (ln == 1 || ln == 2))) {
+			val |= LOADGEN_SELECT;
+		}
+		I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
+	}
+
+	/* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
+	val = I915_READ(ICL_PORT_CL_DW5(port));
+	val |= SUS_CLOCK_CONFIG;
+	I915_WRITE(ICL_PORT_CL_DW5(port), val);
+
+	/* 4. Clear training enable to change swing values */
+	val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+	val &= ~TX_TRAINING_EN;
+	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
+
+	/* 5. Program swing and de-emphasis */
+	icl_ddi_combo_vswing_program(dev_priv, level, port, type);
+
+	/* 6. Set training enable to trigger update */
+	val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+	val |= TX_TRAINING_EN;
+	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
+}
+
+static void icl_ddi_vswing_sequence(struct intel_encoder *encoder, u32 level,
+				    enum intel_output_type type)
+{
+	enum port port = encoder->port;
+
+	if (port == PORT_A || port == PORT_B)
+		icl_combo_phy_ddi_vswing_sequence(encoder, level, type);
+	else
+		/* Not Implemented Yet */
+		WARN_ON(1);
+}
+
 static uint32_t translate_signal_level(int signal_levels)
 {
 	int i;
@@ -2232,7 +2411,9 @@ u32 bxt_signal_levels(struct intel_dp *intel_dp)
 	struct intel_encoder *encoder = &dport->base;
 	int level = intel_ddi_dp_level(intel_dp);
 
-	if (IS_CANNONLAKE(dev_priv))
+	if (IS_ICELAKE(dev_priv))
+		icl_ddi_vswing_sequence(encoder, level, encoder->type);
+	else if (IS_CANNONLAKE(dev_priv))
 		cnl_ddi_vswing_sequence(encoder, level, encoder->type);
 	else
 		bxt_ddi_vswing_sequence(encoder, level, encoder->type);
@@ -2406,7 +2587,9 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
 
 	intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
 
-	if (IS_CANNONLAKE(dev_priv))
+	if (IS_ICELAKE(dev_priv))
+		icl_ddi_vswing_sequence(encoder, level, encoder->type);
+	else if (IS_CANNONLAKE(dev_priv))
 		cnl_ddi_vswing_sequence(encoder, level, encoder->type);
 	else if (IS_GEN9_LP(dev_priv))
 		bxt_ddi_vswing_sequence(encoder, level, encoder->type);
@@ -2436,7 +2619,9 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
 
 	intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
 
-	if (IS_CANNONLAKE(dev_priv))
+	if (IS_ICELAKE(dev_priv))
+		icl_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI);
+	else if (IS_CANNONLAKE(dev_priv))
 		cnl_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI);
 	else if (IS_GEN9_LP(dev_priv))
 		bxt_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI);
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 8/8] drm/i915/icl: Fix the DP Max Voltage for ICL
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
                   ` (6 preceding siblings ...)
  2018-03-28 21:58 ` [PATCH 7/8] drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI Paulo Zanoni
@ 2018-03-28 21:58 ` Paulo Zanoni
  2018-03-28 23:06 ` ✗ Fi.CI.CHECKPATCH: warning for ICL PLLs, DP/HDMI and misc display (rev5) Patchwork
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Paulo Zanoni @ 2018-03-28 21:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni, Rodrigo Vivi

From: Manasi Navare <manasi.d.navare@intel.com>

On clock recovery this function is called to find out
the max voltage swing level that we could go.

However gen 9 functions use the old buffer translation tables
to figure that out. ICL uses different set of tables for eDP
and DP for both Combo and MG PHY ports. This patch adds the hook
for ICL for getting this information from appropriate buf trans tables.

v5 (from Paulo):
* New rebase after changes to earlier patches.
v4:
* Rebase.
v3:
* Follow the coding conventions here
(https://cgit.freedesktop.org/drm-intel/tree/Documentation/process/codin
g-style.rst#n191) (Paulo)
v2:
* Rebase after patch that adds voltage check inside buf trans
function (Rodrigo)

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index bfe3e10e080d..ea8a07496602 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2083,7 +2083,13 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)
 	enum port port = encoder->port;
 	int n_entries;
 
-	if (IS_CANNONLAKE(dev_priv)) {
+	if (IS_ICELAKE(dev_priv)) {
+		if (port == PORT_A || port == PORT_B)
+			icl_get_combo_buf_trans(dev_priv, port, encoder->type,
+						&n_entries);
+		else
+			n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
+	} else if (IS_CANNONLAKE(dev_priv)) {
 		if (encoder->type == INTEL_OUTPUT_EDP)
 			cnl_get_buf_trans_edp(dev_priv, &n_entries);
 		else
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for ICL PLLs, DP/HDMI and misc display (rev5)
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
                   ` (7 preceding siblings ...)
  2018-03-28 21:58 ` [PATCH 8/8] drm/i915/icl: Fix the DP Max Voltage for ICL Paulo Zanoni
@ 2018-03-28 23:06 ` Patchwork
  2018-03-28 23:21 ` ✓ Fi.CI.BAT: success " Patchwork
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Patchwork @ 2018-03-28 23:06 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

== Series Details ==

Series: ICL PLLs, DP/HDMI and misc display (rev5)
URL   : https://patchwork.freedesktop.org/series/38737/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
faa292edccbc drm/i915/icl: Don't set pipe CSC/Gamma in PLANE_COLOR_CTL
890b377784c4 drm/i915/icl: add definitions for the ICL PLL registers
b138b1cf6546 drm/i915/icl: add basic support for the ICL clocks
-:300: CHECK:MULTIPLE_ASSIGNMENTS: multiple assignments should be avoided
#300: FILE: drivers/gpu/drm/i915/intel_dpll_mgr.c:2451:
+		min = max = icl_port_to_mg_pll_id(port);

-:582: CHECK:LINE_SPACING: Please don't use multiple blank lines
#582: FILE: drivers/gpu/drm/i915/intel_dpll_mgr.h:107:
+
+

total: 0 errors, 0 warnings, 2 checks, 578 lines checked
1ff01dc96c10 drm/i915/icl: compute the combo PHY (DPLL) HDMI registers
14141f89c65e drm/i915/icl: compute the combo PHY (DPLL) DP registers
ad6fa9a0548d drm/i915/icl: compute the MG PLL registers
6ae62e939c05 drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI
-:122: WARNING:LONG_LINE: line over 100 characters
#122: FILE: drivers/gpu/drm/i915/intel_ddi.c:2256:
+		DRM_DEBUG_KMS("DDI translation not found for level %d. Using %d instead.", level, n_entries - 1);

total: 0 errors, 1 warnings, 0 checks, 221 lines checked
c9f0f26ddf17 drm/i915/icl: Fix the DP Max Voltage for ICL

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* ✓ Fi.CI.BAT: success for ICL PLLs, DP/HDMI and misc display (rev5)
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
                   ` (8 preceding siblings ...)
  2018-03-28 23:06 ` ✗ Fi.CI.CHECKPATCH: warning for ICL PLLs, DP/HDMI and misc display (rev5) Patchwork
@ 2018-03-28 23:21 ` Patchwork
  2018-03-29  7:53 ` ✓ Fi.CI.IGT: " Patchwork
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 20+ messages in thread
From: Patchwork @ 2018-03-28 23:21 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

== Series Details ==

Series: ICL PLLs, DP/HDMI and misc display (rev5)
URL   : https://patchwork.freedesktop.org/series/38737/
State : success

== Summary ==

Series 38737v5 ICL PLLs, DP/HDMI and misc display
https://patchwork.freedesktop.org/api/1.0/series/38737/revisions/5/mbox/

---- Possible new issues:

Test kms_pipe_crc_basic:
        Subgroup nonblocking-crc-pipe-a-frame-sequence:
                fail       -> PASS       (fi-cfl-s3)
        Subgroup read-crc-pipe-c-frame-sequence:
                fail       -> PASS       (fi-cfl-s3)

---- Known issues:

Test gem_exec_suspend:
        Subgroup basic-s3:
                pass       -> DMESG-WARN (fi-skl-6700k2) fdo#104108
Test gem_mmap_gtt:
        Subgroup basic-small-bo-tiledx:
                fail       -> PASS       (fi-gdg-551) fdo#102575
Test kms_flip:
        Subgroup basic-flip-vs-wf_vblank:
                fail       -> PASS       (fi-cfl-s3) fdo#100368
Test kms_pipe_crc_basic:
        Subgroup suspend-read-crc-pipe-a:
                pass       -> DMESG-WARN (fi-cnl-y3) fdo#103191

fdo#104108 https://bugs.freedesktop.org/show_bug.cgi?id=104108
fdo#102575 https://bugs.freedesktop.org/show_bug.cgi?id=102575
fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#103191 https://bugs.freedesktop.org/show_bug.cgi?id=103191

fi-bdw-5557u     total:285  pass:264  dwarn:0   dfail:0   fail:0   skip:21  time:431s
fi-bdw-gvtdvm    total:285  pass:261  dwarn:0   dfail:0   fail:0   skip:24  time:442s
fi-blb-e6850     total:285  pass:220  dwarn:1   dfail:0   fail:0   skip:64  time:380s
fi-bsw-n3050     total:285  pass:239  dwarn:0   dfail:0   fail:0   skip:46  time:532s
fi-bwr-2160      total:285  pass:180  dwarn:0   dfail:0   fail:0   skip:105 time:297s
fi-bxt-dsi       total:285  pass:255  dwarn:0   dfail:0   fail:0   skip:30  time:514s
fi-bxt-j4205     total:285  pass:256  dwarn:0   dfail:0   fail:0   skip:29  time:511s
fi-byt-j1900     total:285  pass:250  dwarn:0   dfail:0   fail:0   skip:35  time:516s
fi-byt-n2820     total:285  pass:246  dwarn:0   dfail:0   fail:0   skip:39  time:511s
fi-cfl-8700k     total:285  pass:257  dwarn:0   dfail:0   fail:0   skip:28  time:412s
fi-cfl-s3        total:285  pass:259  dwarn:0   dfail:0   fail:0   skip:26  time:560s
fi-cfl-u         total:285  pass:259  dwarn:0   dfail:0   fail:0   skip:26  time:515s
fi-cnl-y3        total:285  pass:258  dwarn:1   dfail:0   fail:0   skip:26  time:588s
fi-elk-e7500     total:285  pass:225  dwarn:1   dfail:0   fail:0   skip:59  time:422s
fi-gdg-551       total:285  pass:177  dwarn:0   dfail:0   fail:0   skip:108 time:318s
fi-glk-1         total:285  pass:257  dwarn:0   dfail:0   fail:0   skip:28  time:538s
fi-hsw-4770      total:285  pass:258  dwarn:0   dfail:0   fail:0   skip:27  time:403s
fi-ilk-650       total:285  pass:225  dwarn:0   dfail:0   fail:0   skip:60  time:420s
fi-ivb-3520m     total:285  pass:256  dwarn:0   dfail:0   fail:0   skip:29  time:461s
fi-ivb-3770      total:285  pass:252  dwarn:0   dfail:0   fail:0   skip:33  time:429s
fi-kbl-7500u     total:285  pass:260  dwarn:1   dfail:0   fail:0   skip:24  time:472s
fi-kbl-7567u     total:285  pass:265  dwarn:0   dfail:0   fail:0   skip:20  time:461s
fi-kbl-r         total:285  pass:258  dwarn:0   dfail:0   fail:0   skip:27  time:507s
fi-pnv-d510      total:285  pass:219  dwarn:1   dfail:0   fail:0   skip:65  time:659s
fi-skl-6260u     total:285  pass:265  dwarn:0   dfail:0   fail:0   skip:20  time:436s
fi-skl-6600u     total:285  pass:258  dwarn:0   dfail:0   fail:0   skip:27  time:532s
fi-skl-6700k2    total:285  pass:260  dwarn:1   dfail:0   fail:0   skip:24  time:502s
fi-skl-6770hq    total:285  pass:265  dwarn:0   dfail:0   fail:0   skip:20  time:495s
fi-skl-guc       total:285  pass:257  dwarn:0   dfail:0   fail:0   skip:28  time:427s
fi-skl-gvtdvm    total:285  pass:262  dwarn:0   dfail:0   fail:0   skip:23  time:444s
fi-snb-2520m     total:285  pass:245  dwarn:0   dfail:0   fail:0   skip:40  time:584s
fi-snb-2600      total:285  pass:245  dwarn:0   dfail:0   fail:0   skip:40  time:400s
Blacklisted hosts:
fi-cnl-psr       total:285  pass:256  dwarn:3   dfail:0   fail:0   skip:26  time:519s
fi-glk-j4005     total:285  pass:256  dwarn:0   dfail:0   fail:0   skip:29  time:483s

4668e88d66074a81aae645e0db0391e7ea9afe8a drm-tip: 2018y-03m-28d-20h-45m-29s UTC integration manifest
c9f0f26ddf17 drm/i915/icl: Fix the DP Max Voltage for ICL
6ae62e939c05 drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI
ad6fa9a0548d drm/i915/icl: compute the MG PLL registers
14141f89c65e drm/i915/icl: compute the combo PHY (DPLL) DP registers
1ff01dc96c10 drm/i915/icl: compute the combo PHY (DPLL) HDMI registers
b138b1cf6546 drm/i915/icl: add basic support for the ICL clocks
890b377784c4 drm/i915/icl: add definitions for the ICL PLL registers
faa292edccbc drm/i915/icl: Don't set pipe CSC/Gamma in PLANE_COLOR_CTL

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8524/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* ✓ Fi.CI.IGT: success for ICL PLLs, DP/HDMI and misc display (rev5)
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
                   ` (9 preceding siblings ...)
  2018-03-28 23:21 ` ✓ Fi.CI.BAT: success " Patchwork
@ 2018-03-29  7:53 ` Patchwork
  2018-04-30  8:42 ` ✗ Fi.CI.CHECKPATCH: warning for ICL PLLs, DP/HDMI and misc display (rev6) Patchwork
  2018-04-30  8:57 ` ✗ Fi.CI.BAT: failure " Patchwork
  12 siblings, 0 replies; 20+ messages in thread
From: Patchwork @ 2018-03-29  7:53 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

== Series Details ==

Series: ICL PLLs, DP/HDMI and misc display (rev5)
URL   : https://patchwork.freedesktop.org/series/38737/
State : success

== Summary ==

---- Known issues:

Test kms_cursor_crc:
        Subgroup cursor-256x256-suspend:
                pass       -> INCOMPLETE (shard-hsw) fdo#103375
        Subgroup cursor-64x64-suspend:
                incomplete -> PASS       (shard-hsw) fdo#103540 +1
Test kms_flip:
        Subgroup 2x-flip-vs-expired-vblank-interruptible:
                pass       -> FAIL       (shard-hsw) fdo#102887 +1
        Subgroup 2x-plain-flip-ts-check-interruptible:
                pass       -> FAIL       (shard-hsw) fdo#100368 +3
        Subgroup dpms-vs-vblank-race:
                fail       -> PASS       (shard-hsw) fdo#103060
Test kms_setmode:
        Subgroup basic:
                fail       -> PASS       (shard-hsw) fdo#99912
Test kms_vblank:
        Subgroup pipe-a-accuracy-idle:
                fail       -> PASS       (shard-hsw) fdo#102583

fdo#103375 https://bugs.freedesktop.org/show_bug.cgi?id=103375
fdo#103540 https://bugs.freedesktop.org/show_bug.cgi?id=103540
fdo#102887 https://bugs.freedesktop.org/show_bug.cgi?id=102887
fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#103060 https://bugs.freedesktop.org/show_bug.cgi?id=103060
fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912
fdo#102583 https://bugs.freedesktop.org/show_bug.cgi?id=102583

shard-apl        total:3495 pass:1831 dwarn:1   dfail:0   fail:7   skip:1655 time:12780s
shard-hsw        total:3443 pass:1748 dwarn:1   dfail:0   fail:4   skip:1687 time:10575s
shard-snb        total:3495 pass:1375 dwarn:1   dfail:0   fail:2   skip:2117 time:6887s
Blacklisted hosts:
shard-kbl        total:3495 pass:1958 dwarn:1   dfail:0   fail:7   skip:1529 time:9290s

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8524/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 7/8] drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI
  2018-03-28 21:58 ` [PATCH 7/8] drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI Paulo Zanoni
@ 2018-03-31  9:53   ` kbuild test robot
  0 siblings, 0 replies; 20+ messages in thread
From: kbuild test robot @ 2018-03-31  9:53 UTC (permalink / raw)
  Cc: Paulo Zanoni, intel-gfx, kbuild-all, Rodrigo Vivi

[-- Attachment #1: Type: text/plain, Size: 16207 bytes --]

Hi Manasi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20180329]
[cannot apply to v4.16-rc7]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Paulo-Zanoni/ICL-PLLs-DP-HDMI-and-misc-display-v2/20180330-131619
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-randconfig-h0-03311214 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

                    ^
   In file included from include/linux/list.h:9:0,
                    from include/linux/kobject.h:19,
                    from include/linux/device.h:16,
                    from include/linux/i2c.h:30,
                    from include/drm/drm_scdc_helper.h:27,
                    from drivers/gpu//drm/i915/intel_ddi.c:28:
   drivers/gpu//drm/i915/intel_ddi.c:784:28: error: 'icl_combo_phy_ddi_translations_dp_hdmi_1_05V' undeclared (first use in this function)
       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
                               ^
   include/linux/kernel.h:71:33: note: in definition of macro 'ARRAY_SIZE'
    #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                                    ^
   In file included from include/linux/kernel.h:15:0,
                    from include/linux/list.h:9,
                    from include/linux/kobject.h:19,
                    from include/linux/device.h:16,
                    from include/linux/i2c.h:30,
                    from include/drm/drm_scdc_helper.h:27,
                    from drivers/gpu//drm/i915/intel_ddi.c:28:
   include/linux/build_bug.h:29:45: error: bit-field '<anonymous>' width not an integer constant
    #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
                                                ^
   include/linux/compiler-gcc.h:65:28: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
    #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
                               ^
   include/linux/kernel.h:71:59: note: in expansion of macro '__must_be_array'
    #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                                                              ^
   drivers/gpu//drm/i915/intel_ddi.c:784:17: note: in expansion of macro 'ARRAY_SIZE'
       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
                    ^
   drivers/gpu//drm/i915/intel_ddi.c: In function 'icl_pll_to_ddi_pll_sel':
   drivers/gpu//drm/i915/intel_ddi.c:939:35: error: 'const struct intel_shared_dpll' has no member named 'info'
     const enum intel_dpll_id id = pll->info->id;
                                      ^
   drivers/gpu//drm/i915/intel_ddi.c: In function 'icl_ddi_combo_vswing_program':
   drivers/gpu//drm/i915/intel_ddi.c:2142:2: error: implicit declaration of function 'ICL_PORT_TX_DW5_LN0' [-Werror=implicit-function-declaration]
     val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2142:8: note: in expansion of macro 'I915_READ'
     val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
           ^
   drivers/gpu//drm/i915/intel_ddi.c:2142:2: note: expected 'i915_reg_t' but argument is of type 'int'
     val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2145:2: error: implicit declaration of function 'ICL_PORT_TX_DW5_GRP' [-Werror=implicit-function-declaration]
     I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3858:30: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_writel'
    #define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2145:2: note: in expansion of macro 'I915_WRITE'
     I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2145:2: note: expected 'i915_reg_t' but argument is of type 'int'
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2148:8: note: in expansion of macro 'I915_READ'
     val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
           ^
   drivers/gpu//drm/i915/intel_ddi.c:2148:2: note: expected 'i915_reg_t' but argument is of type 'int'
     val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2153:10: error: 'TAP2_DISABLE' undeclared (first use in this function)
      val |= TAP2_DISABLE;
             ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3858:30: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_writel'
    #define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2159:2: note: in expansion of macro 'I915_WRITE'
     I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2159:2: note: expected 'i915_reg_t' but argument is of type 'int'
   drivers/gpu//drm/i915/intel_ddi.c:2162:2: error: implicit declaration of function 'ICL_PORT_TX_DW2_LN0' [-Werror=implicit-function-declaration]
     val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2162:8: note: in expansion of macro 'I915_READ'
     val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
           ^
   drivers/gpu//drm/i915/intel_ddi.c:2162:2: note: expected 'i915_reg_t' but argument is of type 'int'
     val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2165:2: error: invalid use of undefined type 'struct icl_combo_phy_ddi_buf_trans'
     val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
     ^
   In file included from drivers/gpu//drm/i915/i915_drv.h:56:0,
                    from drivers/gpu//drm/i915/intel_ddi.c:29:
>> drivers/gpu//drm/i915/intel_ddi.c:2165:41: error: dereferencing pointer to incomplete type
     val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
                                            ^
   drivers/gpu//drm/i915/i915_reg.h:1991:33: note: in definition of macro 'SWING_SEL_UPPER'
    #define   SWING_SEL_UPPER(x)  ((x >> 3) << 15)
                                    ^
   drivers/gpu//drm/i915/intel_ddi.c:2166:2: error: invalid use of undefined type 'struct icl_combo_phy_ddi_buf_trans'
     val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
     ^
   In file included from drivers/gpu//drm/i915/i915_drv.h:56:0,
                    from drivers/gpu//drm/i915/intel_ddi.c:29:
   drivers/gpu//drm/i915/intel_ddi.c:2166:41: error: dereferencing pointer to incomplete type
     val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
                                            ^
   drivers/gpu//drm/i915/i915_reg.h:1993:33: note: in definition of macro 'SWING_SEL_LOWER'
    #define   SWING_SEL_LOWER(x)  ((x & 0x7) << 11)
                                    ^
   drivers/gpu//drm/i915/intel_ddi.c:2168:2: error: invalid use of undefined type 'struct icl_combo_phy_ddi_buf_trans'
     val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
     ^
   In file included from drivers/gpu//drm/i915/i915_drv.h:56:0,
                    from drivers/gpu//drm/i915/intel_ddi.c:29:
   drivers/gpu//drm/i915/intel_ddi.c:2168:38: error: dereferencing pointer to incomplete type
     val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
                                         ^
   drivers/gpu//drm/i915/i915_reg.h:1995:30: note: in definition of macro 'RCOMP_SCALAR'
    #define   RCOMP_SCALAR(x)  ((x) << 0)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2169:2: error: implicit declaration of function 'ICL_PORT_TX_DW2_GRP' [-Werror=implicit-function-declaration]
     I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3858:30: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_writel'
    #define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2169:2: note: in expansion of macro 'I915_WRITE'
     I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2169:2: note: expected 'i915_reg_t' but argument is of type 'int'
   drivers/gpu//drm/i915/intel_ddi.c:2174:3: error: implicit declaration of function 'ICL_PORT_TX_DW4_LN' [-Werror=implicit-function-declaration]
      val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
      ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2174:9: note: in expansion of macro 'I915_READ'
      val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
            ^
   drivers/gpu//drm/i915/intel_ddi.c:2174:3: note: expected 'i915_reg_t' but argument is of type 'int'
      val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
      ^
   drivers/gpu//drm/i915/intel_ddi.c:2177:3: error: invalid use of undefined type 'struct icl_combo_phy_ddi_buf_trans'
      val |= ddi_translations[level].dw4_scaling;
      ^
   drivers/gpu//drm/i915/intel_ddi.c:2177:26: error: dereferencing pointer to incomplete type
      val |= ddi_translations[level].dw4_scaling;
                             ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3858:30: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_writel'
    #define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2178:3: note: in expansion of macro 'I915_WRITE'
      I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
      ^
   drivers/gpu//drm/i915/intel_ddi.c:2178:3: note: expected 'i915_reg_t' but argument is of type 'int'
   drivers/gpu//drm/i915/intel_ddi.c: In function 'icl_combo_phy_ddi_vswing_sequence':
   drivers/gpu//drm/i915/intel_ddi.c:2208:2: error: implicit declaration of function 'ICL_PORT_PCS_DW1_LN0' [-Werror=implicit-function-declaration]
     val = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2208:8: note: in expansion of macro 'I915_READ'
     val = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
           ^
   drivers/gpu//drm/i915/intel_ddi.c:2208:2: note: expected 'i915_reg_t' but argument is of type 'int'
     val = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2213:2: error: implicit declaration of function 'ICL_PORT_PCS_DW1_GRP' [-Werror=implicit-function-declaration]
     I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), val);
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3858:30: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_writel'
    #define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2213:2: note: in expansion of macro 'I915_WRITE'
     I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), val);
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2213:2: note: expected 'i915_reg_t' but argument is of type 'int'
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2223:9: note: in expansion of macro 'I915_READ'
      val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
            ^
   drivers/gpu//drm/i915/intel_ddi.c:2223:3: note: expected 'i915_reg_t' but argument is of type 'int'
      val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
      ^

vim +2165 drivers/gpu//drm/i915/intel_ddi.c

  2123	
  2124	static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
  2125						 u32 level, enum port port, int type)
  2126	{
  2127		const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL;
  2128		u32 n_entries, val;
  2129		int ln;
  2130	
  2131		ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type,
  2132							   &n_entries);
  2133		if (!ddi_translations)
  2134			return;
  2135	
  2136		if (level >= n_entries) {
  2137			DRM_DEBUG_KMS("DDI translation not found for level %d. Using %d instead.", level, n_entries - 1);
  2138			level = n_entries - 1;
  2139		}
  2140	
  2141		/* Set PORT_TX_DW5 Scaling Mode Sel to 110b. */
  2142		val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
  2143		val &= ~RTERM_SELECT_MASK;
  2144		val |= RTERM_SELECT(0x6);
  2145		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
  2146	
  2147		/* Program PORT_TX_DW5 */
  2148		val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
  2149		/* Set DisableTap2 and DisableTap3 if MIPI DSI
  2150		 * Clear DisableTap2 and DisableTap3 for all other Ports
  2151		 */
  2152		if (type == INTEL_OUTPUT_DSI) {
  2153			val |= TAP2_DISABLE;
  2154			val |= TAP3_DISABLE;
  2155		} else {
  2156			val &= ~TAP2_DISABLE;
  2157			val &= ~TAP3_DISABLE;
  2158		}
  2159		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
  2160	
  2161		/* Program PORT_TX_DW2 */
> 2162		val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
  2163		val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
  2164			 RCOMP_SCALAR_MASK);
> 2165		val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
  2166		val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
  2167		/* Program Rcomp scalar for every table entry */
  2168		val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
  2169		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
  2170	
  2171		/* Program PORT_TX_DW4 */
  2172		/* We cannot write to GRP. It would overwrite individual loadgen. */
  2173		for (ln = 0; ln <= 3; ln++) {
  2174			val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
  2175			val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
  2176				 CURSOR_COEFF_MASK);
  2177			val |= ddi_translations[level].dw4_scaling;
  2178			I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
  2179		}
  2180	}
  2181	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 28153 bytes --]

[-- Attachment #3: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/8] drm/i915/icl: add basic support for the ICL clocks
  2018-03-28 21:57 ` [PATCH 3/8] drm/i915/icl: add basic support for the ICL clocks Paulo Zanoni
@ 2018-04-09 23:23   ` James Ausmus
  2018-04-25  0:22     ` Paulo Zanoni
  0 siblings, 1 reply; 20+ messages in thread
From: James Ausmus @ 2018-04-09 23:23 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Wed, Mar 28, 2018 at 02:57:58PM -0700, Paulo Zanoni wrote:
> This commit introduces the definitions for the ICL clocks and adds the
> basic functions to the shared DPLL framework. It adds code for the
> Enable and Disable sequences for some PLLs, but it does not have the
> code to compute the actual PLL values, which are marked as TODO
> comments and should be introduced as separate commits.
> 
> Special thanks to James Ausmus for investigating and fixing a bug with
> the placement of icl_unmap_plls_to_ports() function.
> 
> v2:
>  - Rebase around dpll_lock changes.
> v3:
>  - The spec now says what the timeouts should be.
>  - Touch DPCLKA_CFGCR0_ICL at the appropriate time so we don't freeze
>    the machine.
>  - Checkpatch found a white space problem.
>  - Small adjustments before upstreaming.
> v4:
>  - Move the ICL checks out of the *map_plls_to_ports() functions
>   (James)
>  - Add extra encoder check (James)
>  - Call icl_unmap_plls_to_ports() later (James)
> v5:
>  - Rebase after the pll struct changes.
> 
> Cc: James Ausmus <james.ausmus@intel.com>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c   |  22 +++
>  drivers/gpu/drm/i915/intel_ddi.c      |  98 ++++++++++-
>  drivers/gpu/drm/i915/intel_display.c  |  16 ++
>  drivers/gpu/drm/i915/intel_dpll_mgr.c | 312 +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_dpll_mgr.h |  41 +++++
>  drivers/gpu/drm/i915/intel_drv.h      |   6 +
>  6 files changed, 490 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index ff90577da450..43a805c39b0a 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -3296,6 +3296,28 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
>  		seq_printf(m, " fp0:     0x%08x\n", pll->state.hw_state.fp0);
>  		seq_printf(m, " fp1:     0x%08x\n", pll->state.hw_state.fp1);
>  		seq_printf(m, " wrpll:   0x%08x\n", pll->state.hw_state.wrpll);
> +		seq_printf(m, " cfgcr0:  0x%08x\n", pll->state.hw_state.cfgcr0);
> +		seq_printf(m, " cfgcr1:  0x%08x\n", pll->state.hw_state.cfgcr1);
> +		seq_printf(m, " mg_refclkin_ctl:        0x%08x\n",
> +			   pll->state.hw_state.mg_refclkin_ctl);
> +		seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n",
> +			   pll->state.hw_state.mg_clktop2_coreclkctl1);
> +		seq_printf(m, " mg_clktop2_hsclkctl:    0x%08x\n",
> +			   pll->state.hw_state.mg_clktop2_hsclkctl);
> +		seq_printf(m, " mg_pll_div0:  0x%08x\n",
> +			   pll->state.hw_state.mg_pll_div0);
> +		seq_printf(m, " mg_pll_div1:  0x%08x\n",
> +			   pll->state.hw_state.mg_pll_div1);
> +		seq_printf(m, " mg_pll_lf:    0x%08x\n",
> +			   pll->state.hw_state.mg_pll_lf);
> +		seq_printf(m, " mg_pll_frac_lock: 0x%08x\n",
> +			   pll->state.hw_state.mg_pll_frac_lock);
> +		seq_printf(m, " mg_pll_ssc:   0x%08x\n",
> +			   pll->state.hw_state.mg_pll_ssc);
> +		seq_printf(m, " mg_pll_bias:  0x%08x\n",
> +			   pll->state.hw_state.mg_pll_bias);
> +		seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n",
> +			   pll->state.hw_state.mg_pll_tdc_coldst_bias);
>  	}
>  	drm_modeset_unlock_all(dev);
>  
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index a6672a9abd85..10223ffcceab 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1013,6 +1013,25 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
>  	}
>  }
>  
> +static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
> +				       const struct intel_shared_dpll *pll)
> +{
> +	const enum intel_dpll_id id = pll->info->id;
> +
> +	switch (id) {
> +	default:
> +		MISSING_CASE(id);
> +	case DPLL_ID_ICL_DPLL0:
> +	case DPLL_ID_ICL_DPLL1:
> +		return DDI_CLK_SEL_NONE;
> +	case DPLL_ID_ICL_MGPLL1:
> +	case DPLL_ID_ICL_MGPLL2:
> +	case DPLL_ID_ICL_MGPLL3:
> +	case DPLL_ID_ICL_MGPLL4:
> +		return DDI_CLK_SEL_MG;
> +	}
> +}
> +
>  /* Starting with Haswell, different DDI ports can work in FDI mode for
>   * connection to the PCH-located connectors. For this, it is necessary to train
>   * both the DDI port and PCH receiver for the desired DDI buffer settings.
> @@ -2234,6 +2253,69 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
>  	return DDI_BUF_TRANS_SELECT(level);
>  }
>  
> +void icl_map_plls_to_ports(struct drm_crtc *crtc,
> +			   struct intel_crtc_state *crtc_state,
> +			   struct drm_atomic_state *old_state)
> +{
> +	struct intel_shared_dpll *pll = crtc_state->shared_dpll;
> +	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> +	struct drm_connector_state *conn_state;
> +	struct drm_connector *conn;
> +	int i;
> +
> +	for_each_new_connector_in_state(old_state, conn, conn_state, i) {
> +		struct intel_encoder *encoder =
> +			to_intel_encoder(conn_state->best_encoder);
> +		enum port port = encoder->port;

Just realized that we have the same potential NULL encoder problem here
in map, too - not just unmap, which I missed previously. 

> +		uint32_t val;
> +
> +		if (conn_state->crtc != crtc)
> +			continue;
> +
> +		mutex_lock(&dev_priv->dpll_lock);
> +
> +		val = I915_READ(DPCLKA_CFGCR0_ICL);
> +		WARN_ON((val & DPCLKA_CFGCR0_DDI_CLK_OFF(port)) == 0);
> +
> +		if (port == PORT_A || port == PORT_B) {
> +			val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
> +			val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
> +			I915_WRITE(DPCLKA_CFGCR0_ICL, val);
> +			POSTING_READ(DPCLKA_CFGCR0_ICL);
> +		}
> +
> +		val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
> +		I915_WRITE(DPCLKA_CFGCR0_ICL, val);
> +
> +		mutex_unlock(&dev_priv->dpll_lock);
> +	}
> +}
> +
> +void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
> +			     struct intel_crtc_state *crtc_state,
> +			     struct drm_atomic_state *old_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> +	struct drm_connector_state *conn_state;
> +	struct drm_connector *conn;
> +	int i;
> +
> +	for_each_new_connector_in_state(old_state, conn, conn_state, i) {
> +		struct intel_encoder *encoder =
> +			to_intel_encoder(conn_state->best_encoder);
> +		enum port port = encoder->port;

Access of encoder->port needs to be after the encoder NULL check,
otherwise the NULL check is pointless :)

> +
> +		if (!encoder || conn_state->crtc != crtc)
> +			continue;
> +
> +		mutex_lock(&dev_priv->dpll_lock);
> +		I915_WRITE(DPCLKA_CFGCR0_ICL,
> +			   I915_READ(DPCLKA_CFGCR0_ICL) |
> +			   DPCLKA_CFGCR0_DDI_CLK_OFF(port));
> +		mutex_unlock(&dev_priv->dpll_lock);
> +	}
> +}
> +
>  static void intel_ddi_clk_select(struct intel_encoder *encoder,
>  				 const struct intel_shared_dpll *pll)
>  {
> @@ -2246,7 +2328,11 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
>  
>  	mutex_lock(&dev_priv->dpll_lock);
>  
> -	if (IS_CANNONLAKE(dev_priv)) {
> +	if (IS_ICELAKE(dev_priv)) {
> +		if (port >= PORT_C)
> +			I915_WRITE(DDI_CLK_SEL(port),
> +				   icl_pll_to_ddi_pll_sel(encoder, pll));
> +	} else if (IS_CANNONLAKE(dev_priv)) {
>  		/* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */
>  		val = I915_READ(DPCLKA_CFGCR0);
>  		val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
> @@ -2284,14 +2370,18 @@ static void intel_ddi_clk_disable(struct intel_encoder *encoder)
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	enum port port = encoder->port;
>  
> -	if (IS_CANNONLAKE(dev_priv))
> +	if (IS_ICELAKE(dev_priv)) {
> +		if (port >= PORT_C)
> +			I915_WRITE(DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
> +	} else if (IS_CANNONLAKE(dev_priv)) {
>  		I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) |
>  			   DPCLKA_CFGCR0_DDI_CLK_OFF(port));
> -	else if (IS_GEN9_BC(dev_priv))
> +	} else if (IS_GEN9_BC(dev_priv)) {
>  		I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) |
>  			   DPLL_CTRL2_DDI_CLK_OFF(port));
> -	else if (INTEL_GEN(dev_priv) < 9)
> +	} else if (INTEL_GEN(dev_priv) < 9) {
>  		I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
> +	}
>  }
>  
>  static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 8b18729bc4d3..64e7943164d5 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5508,6 +5508,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
>  	if (intel_crtc->config->shared_dpll)
>  		intel_enable_shared_dpll(intel_crtc);
>  
> +	if (INTEL_GEN(dev_priv) >= 11)
> +		icl_map_plls_to_ports(crtc, pipe_config, old_state);
> +
>  	if (intel_crtc_has_dp_encoder(intel_crtc->config))
>  		intel_dp_set_m_n(intel_crtc, M1_N1);
>  
> @@ -5705,6 +5708,9 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
>  		intel_ddi_disable_pipe_clock(intel_crtc->config);
>  
>  	intel_encoders_post_disable(crtc, old_crtc_state, old_state);
> +
> +	if (INTEL_GEN(dev_priv) >= 11)
> +		icl_unmap_plls_to_ports(crtc, old_crtc_state, old_state);
>  }
>  
>  static void i9xx_pfit_enable(struct intel_crtc *crtc)
> @@ -11324,6 +11330,16 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
>  	PIPE_CONF_CHECK_X(dpll_hw_state.pll9);
>  	PIPE_CONF_CHECK_X(dpll_hw_state.pll10);
>  	PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias);
>  
>  	PIPE_CONF_CHECK_X(dsi_pll.ctrl);
>  	PIPE_CONF_CHECK_X(dsi_pll.div);
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> index d5e114e9660b..470de6a33ca0 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> @@ -2399,6 +2399,314 @@ static const struct intel_dpll_mgr cnl_pll_mgr = {
>  	.dump_hw_state = cnl_dump_hw_state,
>  };
>  
> +static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
> +				struct intel_encoder *encoder, int clock,
> +				struct intel_dpll_hw_state *pll_state)
> +{
> +	/* TODO */
> +	return true;
> +}
> +
> +static enum port icl_mg_pll_id_to_port(enum intel_dpll_id id)
> +{
> +	return id - DPLL_ID_ICL_MGPLL1 + PORT_C;
> +}
> +
> +static enum intel_dpll_id icl_port_to_mg_pll_id(enum port port)
> +{
> +	return port - PORT_C + DPLL_ID_ICL_MGPLL1;
> +}
> +
> +static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
> +				  struct intel_encoder *encoder, int clock,
> +				  struct intel_dpll_hw_state *pll_state)
> +{
> +	/* TODO */
> +	return true;
> +}
> +
> +static struct intel_shared_dpll *
> +icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
> +	     struct intel_encoder *encoder)
> +{
> +	struct intel_shared_dpll *pll;
> +	struct intel_dpll_hw_state pll_state = {};
> +	enum port port = encoder->port;
> +	enum intel_dpll_id min, max;
> +	int clock = crtc_state->port_clock;
> +	bool ret;
> +
> +	switch (port) {
> +	case PORT_A:
> +	case PORT_B:
> +		min = DPLL_ID_ICL_DPLL0;
> +		max = DPLL_ID_ICL_DPLL1;
> +		ret = icl_calc_dpll_state(crtc_state, encoder, clock,
> +					  &pll_state);
> +		break;
> +	case PORT_C:
> +	case PORT_D:
> +	case PORT_E:
> +	case PORT_F:
> +		min = max = icl_port_to_mg_pll_id(port);
> +		ret = icl_calc_mg_pll_state(crtc_state, encoder, clock,
> +					    &pll_state);
> +		break;
> +	default:
> +		MISSING_CASE(port);
> +		return NULL;
> +	}
> +
> +	if (!ret) {
> +		DRM_DEBUG_KMS("Could not calculate PLL state.\n");
> +		return NULL;
> +	}
> +
> +	crtc_state->dpll_hw_state = pll_state;
> +
> +	pll = intel_find_shared_dpll(crtc, crtc_state, min, max);
> +	if (!pll) {
> +		DRM_DEBUG_KMS("No PLL selected\n");
> +		return NULL;
> +	}
> +
> +	intel_reference_shared_dpll(pll, crtc_state);
> +
> +	return pll;
> +}
> +
> +static i915_reg_t icl_pll_id_to_enable_reg(enum intel_dpll_id id)
> +{
> +	switch (id) {
> +	default:
> +		MISSING_CASE(id);
> +	case DPLL_ID_ICL_DPLL0:
> +	case DPLL_ID_ICL_DPLL1:
> +		return CNL_DPLL_ENABLE(id);
> +	case DPLL_ID_ICL_MGPLL1:
> +	case DPLL_ID_ICL_MGPLL2:
> +	case DPLL_ID_ICL_MGPLL3:
> +	case DPLL_ID_ICL_MGPLL4:
> +		return MG_PLL_ENABLE(icl_mg_pll_id_to_port(id));
> +	}
> +}
> +
> +static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
> +				 struct intel_shared_dpll *pll,
> +				 struct intel_dpll_hw_state *hw_state)
> +{
> +	const enum intel_dpll_id id = pll->info->id;
> +	uint32_t val;
> +	enum port port;
> +	bool ret = false;
> +
> +	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +		return false;
> +
> +	val = I915_READ(icl_pll_id_to_enable_reg(id));
> +	if (!(val & PLL_ENABLE))
> +		goto out;
> +
> +	switch (id) {
> +	case DPLL_ID_ICL_DPLL0:
> +	case DPLL_ID_ICL_DPLL1:
> +		hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(id));
> +		hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(id));
> +		break;
> +	case DPLL_ID_ICL_MGPLL1:
> +	case DPLL_ID_ICL_MGPLL2:
> +	case DPLL_ID_ICL_MGPLL3:
> +	case DPLL_ID_ICL_MGPLL4:
> +		port = icl_mg_pll_id_to_port(id);
> +		hw_state->mg_refclkin_ctl = I915_READ(MG_REFCLKIN_CTL(port));
> +		hw_state->mg_clktop2_coreclkctl1 =
> +			I915_READ(MG_CLKTOP2_CORECLKCTL1(port));
> +		hw_state->mg_clktop2_hsclkctl =
> +			I915_READ(MG_CLKTOP2_HSCLKCTL(port));
> +		hw_state->mg_pll_div0 = I915_READ(MG_PLL_DIV0(port));
> +		hw_state->mg_pll_div1 = I915_READ(MG_PLL_DIV1(port));
> +		hw_state->mg_pll_lf = I915_READ(MG_PLL_LF(port));
> +		hw_state->mg_pll_frac_lock = I915_READ(MG_PLL_FRAC_LOCK(port));
> +		hw_state->mg_pll_ssc = I915_READ(MG_PLL_SSC(port));
> +		hw_state->mg_pll_bias = I915_READ(MG_PLL_BIAS(port));
> +		hw_state->mg_pll_tdc_coldst_bias =
> +			I915_READ(MG_PLL_TDC_COLDST_BIAS(port));
> +		break;
> +	default:
> +		MISSING_CASE(id);
> +	}
> +
> +	ret = true;
> +out:
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +	return ret;
> +}
> +
> +static void icl_dpll_write(struct drm_i915_private *dev_priv,
> +			   struct intel_shared_dpll *pll)
> +{
> +	struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
> +	const enum intel_dpll_id id = pll->info->id;
> +
> +	I915_WRITE(ICL_DPLL_CFGCR0(id), hw_state->cfgcr0);
> +	I915_WRITE(ICL_DPLL_CFGCR1(id), hw_state->cfgcr1);
> +	POSTING_READ(ICL_DPLL_CFGCR1(id));
> +}
> +
> +static void icl_mg_pll_write(struct drm_i915_private *dev_priv,
> +			     struct intel_shared_dpll *pll)
> +{
> +	struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
> +	enum port port = icl_mg_pll_id_to_port(pll->info->id);
> +
> +	I915_WRITE(MG_REFCLKIN_CTL(port), hw_state->mg_refclkin_ctl);
> +	I915_WRITE(MG_CLKTOP2_CORECLKCTL1(port),
> +		   hw_state->mg_clktop2_coreclkctl1);
> +	I915_WRITE(MG_CLKTOP2_HSCLKCTL(port), hw_state->mg_clktop2_hsclkctl);
> +	I915_WRITE(MG_PLL_DIV0(port), hw_state->mg_pll_div0);
> +	I915_WRITE(MG_PLL_DIV1(port), hw_state->mg_pll_div1);
> +	I915_WRITE(MG_PLL_LF(port), hw_state->mg_pll_lf);
> +	I915_WRITE(MG_PLL_FRAC_LOCK(port), hw_state->mg_pll_frac_lock);
> +	I915_WRITE(MG_PLL_SSC(port), hw_state->mg_pll_ssc);
> +	I915_WRITE(MG_PLL_BIAS(port), hw_state->mg_pll_bias);
> +	I915_WRITE(MG_PLL_TDC_COLDST_BIAS(port),
> +		   hw_state->mg_pll_tdc_coldst_bias);
> +	POSTING_READ(MG_PLL_TDC_COLDST_BIAS(port));
> +}
> +
> +static void icl_pll_enable(struct drm_i915_private *dev_priv,
> +			   struct intel_shared_dpll *pll)
> +{
> +	const enum intel_dpll_id id = pll->info->id;
> +	i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
> +	uint32_t val;
> +
> +	val = I915_READ(enable_reg);
> +	val |= PLL_POWER_ENABLE;
> +	I915_WRITE(enable_reg, val);
> +
> +	/*
> +	 * The spec says we need to "wait" but it also says it should be
> +	 * immediate.
> +	 */
> +	if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE,
> +				    PLL_POWER_STATE, 1))
> +		DRM_ERROR("PLL %d Power not enabled\n", id);
> +
> +	switch (id) {
> +	case DPLL_ID_ICL_DPLL0:
> +	case DPLL_ID_ICL_DPLL1:
> +		icl_dpll_write(dev_priv, pll);
> +		break;
> +	case DPLL_ID_ICL_MGPLL1:
> +	case DPLL_ID_ICL_MGPLL2:
> +	case DPLL_ID_ICL_MGPLL3:
> +	case DPLL_ID_ICL_MGPLL4:
> +		icl_mg_pll_write(dev_priv, pll);
> +		break;
> +	default:
> +		MISSING_CASE(id);
> +	}
> +
> +	/*
> +	 * DVFS pre sequence would be here, but in our driver the cdclk code
> +	 * paths should already be setting the appropriate voltage, hence we do
> +	 * nothign here.
> +	 */
> +
> +	val = I915_READ(enable_reg);
> +	val |= PLL_ENABLE;
> +	I915_WRITE(enable_reg, val);
> +
> +	if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, PLL_LOCK,
> +				    1)) /* 600us actually. */
> +		DRM_ERROR("PLL %d not locked\n", id);
> +
> +	/* DVFS post sequence would be here. See the comment above. */
> +}
> +
> +static void icl_pll_disable(struct drm_i915_private *dev_priv,
> +			    struct intel_shared_dpll *pll)
> +{
> +	const enum intel_dpll_id id = pll->info->id;
> +	i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
> +	uint32_t val;
> +
> +	/* The first steps are done by intel_ddi_post_disable(). */
> +
> +	/*
> +	 * DVFS pre sequence would be here, but in our driver the cdclk code
> +	 * paths should already be setting the appropriate voltage, hence we do
> +	 * nothign here.
> +	 */
> +
> +	val = I915_READ(enable_reg);
> +	val &= ~PLL_ENABLE;
> +	I915_WRITE(enable_reg, val);
> +
> +	/* Timeout is actually 1us. */
> +	if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, 0, 1))
> +		DRM_ERROR("PLL %d locked\n", id);
> +
> +	/* DVFS post sequence would be here. See the comment above. */
> +
> +	val = I915_READ(enable_reg);
> +	val &= ~PLL_POWER_ENABLE;
> +	I915_WRITE(enable_reg, val);
> +
> +	/*
> +	 * The spec says we need to "wait" but it also says it should be
> +	 * immediate.
> +	 */
> +	if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE, 0,
> +				    1))
> +		DRM_ERROR("PLL %d Power not disabled\n", id);
> +}
> +
> +static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
> +			      struct intel_dpll_hw_state *hw_state)
> +{
> +	DRM_DEBUG_KMS("dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, "
> +		      "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
> +		      "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, "
> +		      "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, "
> +		      "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, "
> +		      "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n",
> +		      hw_state->cfgcr0, hw_state->cfgcr1,
> +		      hw_state->mg_refclkin_ctl,
> +		      hw_state->mg_clktop2_coreclkctl1,
> +		      hw_state->mg_clktop2_hsclkctl,
> +		      hw_state->mg_pll_div0,
> +		      hw_state->mg_pll_div1,
> +		      hw_state->mg_pll_lf,
> +		      hw_state->mg_pll_frac_lock,
> +		      hw_state->mg_pll_ssc,
> +		      hw_state->mg_pll_bias,
> +		      hw_state->mg_pll_tdc_coldst_bias);
> +}
> +
> +static const struct intel_shared_dpll_funcs icl_pll_funcs = {
> +	.enable = icl_pll_enable,
> +	.disable = icl_pll_disable,
> +	.get_hw_state = icl_pll_get_hw_state,
> +};
> +
> +static const struct dpll_info icl_plls[] = {
> +	{ "DPLL 0",   &icl_pll_funcs, DPLL_ID_ICL_DPLL0,  0 },
> +	{ "DPLL 1",   &icl_pll_funcs, DPLL_ID_ICL_DPLL1,  0 },
> +	{ "MG PLL 1", &icl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 },
> +	{ "MG PLL 2", &icl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 },
> +	{ "MG PLL 3", &icl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 },
> +	{ "MG PLL 4", &icl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 },
> +	{ },
> +};
> +
> +static const struct intel_dpll_mgr icl_pll_mgr = {
> +	.dpll_info = icl_plls,
> +	.get_dpll = icl_get_dpll,
> +	.dump_hw_state = icl_dump_hw_state,
> +};
> +
>  /**
>   * intel_shared_dpll_init - Initialize shared DPLLs
>   * @dev: drm device
> @@ -2412,7 +2720,9 @@ void intel_shared_dpll_init(struct drm_device *dev)
>  	const struct dpll_info *dpll_info;
>  	int i;
>  
> -	if (IS_CANNONLAKE(dev_priv))
> +	if (IS_ICELAKE(dev_priv))
> +		dpll_mgr = &icl_pll_mgr;
> +	else if (IS_CANNONLAKE(dev_priv))
>  		dpll_mgr = &cnl_pll_mgr;
>  	else if (IS_GEN9_BC(dev_priv))
>  		dpll_mgr = &skl_pll_mgr;
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> index 4febfaa90bde..7a0cd564a9ee 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
> +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> @@ -103,6 +103,32 @@ enum intel_dpll_id {
>  	 * @DPLL_ID_SKL_DPLL3: SKL and later DPLL3
>  	 */
>  	DPLL_ID_SKL_DPLL3 = 3,
> +
> +
> +	/**
> +	 * @DPLL_ID_ICL_DPLL0: ICL combo PHY DPLL0
> +	 */
> +	DPLL_ID_ICL_DPLL0 = 0,
> +	/**
> +	 * @DPLL_ID_ICL_DPLL1: ICL combo PHY DPLL1
> +	 */
> +	DPLL_ID_ICL_DPLL1 = 1,
> +	/**
> +	 * @DPLL_ID_ICL_MGPLL1: ICL MG PLL 1 port 1 (C)
> +	 */
> +	DPLL_ID_ICL_MGPLL1 = 2,
> +	/**
> +	 * @DPLL_ID_ICL_MGPLL2: ICL MG PLL 1 port 2 (D)
> +	 */
> +	DPLL_ID_ICL_MGPLL2 = 3,
> +	/**
> +	 * @DPLL_ID_ICL_MGPLL3: ICL MG PLL 1 port 3 (E)
> +	 */
> +	DPLL_ID_ICL_MGPLL3 = 4,
> +	/**
> +	 * @DPLL_ID_ICL_MGPLL4: ICL MG PLL 1 port 4 (F)
> +	 */
> +	DPLL_ID_ICL_MGPLL4 = 5,
>  };
>  #define I915_NUM_PLLS 6
>  
> @@ -135,6 +161,21 @@ struct intel_dpll_hw_state {
>  	/* bxt */
>  	uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
>  		 pcsdw12;
> +
> +	/*
> +	 * ICL uses the following, already defined:
> +	 * uint32_t cfgcr0, cfgcr1;
> +	 */
> +	uint32_t mg_refclkin_ctl;
> +	uint32_t mg_clktop2_coreclkctl1;
> +	uint32_t mg_clktop2_hsclkctl;
> +	uint32_t mg_pll_div0;
> +	uint32_t mg_pll_div1;
> +	uint32_t mg_pll_lf;
> +	uint32_t mg_pll_frac_lock;
> +	uint32_t mg_pll_ssc;
> +	uint32_t mg_pll_bias;
> +	uint32_t mg_pll_tdc_coldst_bias;
>  };
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d1452fd2a58d..d77306950676 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1393,6 +1393,12 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp);
>  u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
>  int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
>  				     bool enable);
> +void icl_map_plls_to_ports(struct drm_crtc *crtc,
> +			   struct intel_crtc_state *crtc_state,
> +			   struct drm_atomic_state *old_state);
> +void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
> +			     struct intel_crtc_state *crtc_state,
> +			     struct drm_atomic_state *old_state);
>  
>  unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
>  				   int plane, unsigned int height);
> -- 
> 2.14.3
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/8] drm/i915/icl: add basic support for the ICL clocks
  2018-04-09 23:23   ` James Ausmus
@ 2018-04-25  0:22     ` Paulo Zanoni
  2018-04-27 23:14       ` Paulo Zanoni
  0 siblings, 1 reply; 20+ messages in thread
From: Paulo Zanoni @ 2018-04-25  0:22 UTC (permalink / raw)
  To: James Ausmus; +Cc: intel-gfx

Em Seg, 2018-04-09 às 16:23 -0700, James Ausmus escreveu:
> On Wed, Mar 28, 2018 at 02:57:58PM -0700, Paulo Zanoni wrote:
> > This commit introduces the definitions for the ICL clocks and adds
> > the
> > basic functions to the shared DPLL framework. It adds code for the
> > Enable and Disable sequences for some PLLs, but it does not have
> > the
> > code to compute the actual PLL values, which are marked as TODO
> > comments and should be introduced as separate commits.
> > 
> > Special thanks to James Ausmus for investigating and fixing a bug
> > with
> > the placement of icl_unmap_plls_to_ports() function.
> > 
> > v2:
> >  - Rebase around dpll_lock changes.
> > v3:
> >  - The spec now says what the timeouts should be.
> >  - Touch DPCLKA_CFGCR0_ICL at the appropriate time so we don't
> > freeze
> >    the machine.
> >  - Checkpatch found a white space problem.
> >  - Small adjustments before upstreaming.
> > v4:
> >  - Move the ICL checks out of the *map_plls_to_ports() functions
> >   (James)
> >  - Add extra encoder check (James)
> >  - Call icl_unmap_plls_to_ports() later (James)
> > v5:
> >  - Rebase after the pll struct changes.
> > 
> > Cc: James Ausmus <james.ausmus@intel.com>
> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_debugfs.c   |  22 +++
> >  drivers/gpu/drm/i915/intel_ddi.c      |  98 ++++++++++-
> >  drivers/gpu/drm/i915/intel_display.c  |  16 ++
> >  drivers/gpu/drm/i915/intel_dpll_mgr.c | 312
> > +++++++++++++++++++++++++++++++++-
> >  drivers/gpu/drm/i915/intel_dpll_mgr.h |  41 +++++
> >  drivers/gpu/drm/i915/intel_drv.h      |   6 +
> >  6 files changed, 490 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> > b/drivers/gpu/drm/i915/i915_debugfs.c
> > index ff90577da450..43a805c39b0a 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -3296,6 +3296,28 @@ static int i915_shared_dplls_info(struct
> > seq_file *m, void *unused)
> >  		seq_printf(m, " fp0:     0x%08x\n", pll-
> > >state.hw_state.fp0);
> >  		seq_printf(m, " fp1:     0x%08x\n", pll-
> > >state.hw_state.fp1);
> >  		seq_printf(m, " wrpll:   0x%08x\n", pll-
> > >state.hw_state.wrpll);
> > +		seq_printf(m, " cfgcr0:  0x%08x\n", pll-
> > >state.hw_state.cfgcr0);
> > +		seq_printf(m, " cfgcr1:  0x%08x\n", pll-
> > >state.hw_state.cfgcr1);
> > +		seq_printf(m, " mg_refclkin_ctl:        0x%08x\n",
> > +			   pll->state.hw_state.mg_refclkin_ctl);
> > +		seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n",
> > +			   pll-
> > >state.hw_state.mg_clktop2_coreclkctl1);
> > +		seq_printf(m, " mg_clktop2_hsclkctl:    0x%08x\n",
> > +			   pll-
> > >state.hw_state.mg_clktop2_hsclkctl);
> > +		seq_printf(m, " mg_pll_div0:  0x%08x\n",
> > +			   pll->state.hw_state.mg_pll_div0);
> > +		seq_printf(m, " mg_pll_div1:  0x%08x\n",
> > +			   pll->state.hw_state.mg_pll_div1);
> > +		seq_printf(m, " mg_pll_lf:    0x%08x\n",
> > +			   pll->state.hw_state.mg_pll_lf);
> > +		seq_printf(m, " mg_pll_frac_lock: 0x%08x\n",
> > +			   pll->state.hw_state.mg_pll_frac_lock);
> > +		seq_printf(m, " mg_pll_ssc:   0x%08x\n",
> > +			   pll->state.hw_state.mg_pll_ssc);
> > +		seq_printf(m, " mg_pll_bias:  0x%08x\n",
> > +			   pll->state.hw_state.mg_pll_bias);
> > +		seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n",
> > +			   pll-
> > >state.hw_state.mg_pll_tdc_coldst_bias);
> >  	}
> >  	drm_modeset_unlock_all(dev);
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> > b/drivers/gpu/drm/i915/intel_ddi.c
> > index a6672a9abd85..10223ffcceab 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -1013,6 +1013,25 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const
> > struct intel_shared_dpll *pll)
> >  	}
> >  }
> >  
> > +static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder
> > *encoder,
> > +				       const struct
> > intel_shared_dpll *pll)
> > +{
> > +	const enum intel_dpll_id id = pll->info->id;
> > +
> > +	switch (id) {
> > +	default:
> > +		MISSING_CASE(id);
> > +	case DPLL_ID_ICL_DPLL0:
> > +	case DPLL_ID_ICL_DPLL1:
> > +		return DDI_CLK_SEL_NONE;
> > +	case DPLL_ID_ICL_MGPLL1:
> > +	case DPLL_ID_ICL_MGPLL2:
> > +	case DPLL_ID_ICL_MGPLL3:
> > +	case DPLL_ID_ICL_MGPLL4:
> > +		return DDI_CLK_SEL_MG;
> > +	}
> > +}
> > +
> >  /* Starting with Haswell, different DDI ports can work in FDI mode
> > for
> >   * connection to the PCH-located connectors. For this, it is
> > necessary to train
> >   * both the DDI port and PCH receiver for the desired DDI buffer
> > settings.
> > @@ -2234,6 +2253,69 @@ uint32_t ddi_signal_levels(struct intel_dp
> > *intel_dp)
> >  	return DDI_BUF_TRANS_SELECT(level);
> >  }
> >  
> > +void icl_map_plls_to_ports(struct drm_crtc *crtc,
> > +			   struct intel_crtc_state *crtc_state,
> > +			   struct drm_atomic_state *old_state)
> > +{
> > +	struct intel_shared_dpll *pll = crtc_state->shared_dpll;
> > +	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> > +	struct drm_connector_state *conn_state;
> > +	struct drm_connector *conn;
> > +	int i;
> > +
> > +	for_each_new_connector_in_state(old_state, conn,
> > conn_state, i) {
> > +		struct intel_encoder *encoder =
> > +			to_intel_encoder(conn_state-
> > >best_encoder);
> > +		enum port port = encoder->port;
> 
> Just realized that we have the same potential NULL encoder problem
> here
> in map, too - not just unmap, which I missed previously. 

Function icl_map_plls_to_ports() is based on
intel_encoders_pre_pll_enable(), which doesn't have the check. I
suppose that's because you can't enable a connector without an encoder
in a commit.


> 
> > +		uint32_t val;
> > +
> > +		if (conn_state->crtc != crtc)
> > +			continue;
> > +
> > +		mutex_lock(&dev_priv->dpll_lock);
> > +
> > +		val = I915_READ(DPCLKA_CFGCR0_ICL);
> > +		WARN_ON((val & DPCLKA_CFGCR0_DDI_CLK_OFF(port)) ==
> > 0);
> > +
> > +		if (port == PORT_A || port == PORT_B) {
> > +			val &=
> > ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
> > +			val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll-
> > >info->id, port);
> > +			I915_WRITE(DPCLKA_CFGCR0_ICL, val);
> > +			POSTING_READ(DPCLKA_CFGCR0_ICL);
> > +		}
> > +
> > +		val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
> > +		I915_WRITE(DPCLKA_CFGCR0_ICL, val);
> > +
> > +		mutex_unlock(&dev_priv->dpll_lock);
> > +	}
> > +}
> > +
> > +void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
> > +			     struct intel_crtc_state *crtc_state,
> > +			     struct drm_atomic_state *old_state)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> > +	struct drm_connector_state *conn_state;
> > +	struct drm_connector *conn;
> > +	int i;
> > +
> > +	for_each_new_connector_in_state(old_state, conn,
> > conn_state, i) {
> > +		struct intel_encoder *encoder =
> > +			to_intel_encoder(conn_state-
> > >best_encoder);
> > +		enum port port = encoder->port;
> 
> Access of encoder->port needs to be after the encoder NULL check,
> otherwise the NULL check is pointless :)

You're right in that statement, but I realized
icl_unmap_plls_to_ports() should be based on
intel_encoders_post_disable(), which doesn't have the encoder check
either. The problem is that post_disable iterates over the old
connector state (so no need for the check since the older enabled
connector had an encoder), and that is what seems to be wrong about this function here. I'll fix it.


> 
> > +
> > +		if (!encoder || conn_state->crtc != crtc)
> > +			continue;
> > +
> > +		mutex_lock(&dev_priv->dpll_lock);
> > +		I915_WRITE(DPCLKA_CFGCR0_ICL,
> > +			   I915_READ(DPCLKA_CFGCR0_ICL) |
> > +			   DPCLKA_CFGCR0_DDI_CLK_OFF(port));
> > +		mutex_unlock(&dev_priv->dpll_lock);
> > +	}
> > +}
> > +
> >  static void intel_ddi_clk_select(struct intel_encoder *encoder,
> >  				 const struct intel_shared_dpll
> > *pll)
> >  {
> > @@ -2246,7 +2328,11 @@ static void intel_ddi_clk_select(struct
> > intel_encoder *encoder,
> >  
> >  	mutex_lock(&dev_priv->dpll_lock);
> >  
> > -	if (IS_CANNONLAKE(dev_priv)) {
> > +	if (IS_ICELAKE(dev_priv)) {
> > +		if (port >= PORT_C)
> > +			I915_WRITE(DDI_CLK_SEL(port),
> > +				   icl_pll_to_ddi_pll_sel(encoder,
> > pll));
> > +	} else if (IS_CANNONLAKE(dev_priv)) {
> >  		/* Configure DPCLKA_CFGCR0 to map the DPLL to the
> > DDI. */
> >  		val = I915_READ(DPCLKA_CFGCR0);
> >  		val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
> > @@ -2284,14 +2370,18 @@ static void intel_ddi_clk_disable(struct
> > intel_encoder *encoder)
> >  	struct drm_i915_private *dev_priv = to_i915(encoder-
> > >base.dev);
> >  	enum port port = encoder->port;
> >  
> > -	if (IS_CANNONLAKE(dev_priv))
> > +	if (IS_ICELAKE(dev_priv)) {
> > +		if (port >= PORT_C)
> > +			I915_WRITE(DDI_CLK_SEL(port),
> > DDI_CLK_SEL_NONE);
> > +	} else if (IS_CANNONLAKE(dev_priv)) {
> >  		I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0)
> > |
> >  			   DPCLKA_CFGCR0_DDI_CLK_OFF(port));
> > -	else if (IS_GEN9_BC(dev_priv))
> > +	} else if (IS_GEN9_BC(dev_priv)) {
> >  		I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) |
> >  			   DPLL_CTRL2_DDI_CLK_OFF(port));
> > -	else if (INTEL_GEN(dev_priv) < 9)
> > +	} else if (INTEL_GEN(dev_priv) < 9) {
> >  		I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
> > +	}
> >  }
> >  
> >  static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
> > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > b/drivers/gpu/drm/i915/intel_display.c
> > index 8b18729bc4d3..64e7943164d5 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -5508,6 +5508,9 @@ static void haswell_crtc_enable(struct
> > intel_crtc_state *pipe_config,
> >  	if (intel_crtc->config->shared_dpll)
> >  		intel_enable_shared_dpll(intel_crtc);
> >  
> > +	if (INTEL_GEN(dev_priv) >= 11)
> > +		icl_map_plls_to_ports(crtc, pipe_config,
> > old_state);
> > +
> >  	if (intel_crtc_has_dp_encoder(intel_crtc->config))
> >  		intel_dp_set_m_n(intel_crtc, M1_N1);
> >  
> > @@ -5705,6 +5708,9 @@ static void haswell_crtc_disable(struct
> > intel_crtc_state *old_crtc_state,
> >  		intel_ddi_disable_pipe_clock(intel_crtc->config);
> >  
> >  	intel_encoders_post_disable(crtc, old_crtc_state,
> > old_state);
> > +
> > +	if (INTEL_GEN(dev_priv) >= 11)
> > +		icl_unmap_plls_to_ports(crtc, old_crtc_state,
> > old_state);
> >  }
> >  
> >  static void i9xx_pfit_enable(struct intel_crtc *crtc)
> > @@ -11324,6 +11330,16 @@ intel_pipe_config_compare(struct
> > drm_i915_private *dev_priv,
> >  	PIPE_CONF_CHECK_X(dpll_hw_state.pll9);
> >  	PIPE_CONF_CHECK_X(dpll_hw_state.pll10);
> >  	PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12);
> > +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl);
> > +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1);
> > +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl);
> > +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0);
> > +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1);
> > +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf);
> > +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock);
> > +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc);
> > +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias);
> > +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias);
> >  
> >  	PIPE_CONF_CHECK_X(dsi_pll.ctrl);
> >  	PIPE_CONF_CHECK_X(dsi_pll.div);
> > diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > index d5e114e9660b..470de6a33ca0 100644
> > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > @@ -2399,6 +2399,314 @@ static const struct intel_dpll_mgr
> > cnl_pll_mgr = {
> >  	.dump_hw_state = cnl_dump_hw_state,
> >  };
> >  
> > +static bool icl_calc_dpll_state(struct intel_crtc_state
> > *crtc_state,
> > +				struct intel_encoder *encoder, int
> > clock,
> > +				struct intel_dpll_hw_state
> > *pll_state)
> > +{
> > +	/* TODO */
> > +	return true;
> > +}
> > +
> > +static enum port icl_mg_pll_id_to_port(enum intel_dpll_id id)
> > +{
> > +	return id - DPLL_ID_ICL_MGPLL1 + PORT_C;
> > +}
> > +
> > +static enum intel_dpll_id icl_port_to_mg_pll_id(enum port port)
> > +{
> > +	return port - PORT_C + DPLL_ID_ICL_MGPLL1;
> > +}
> > +
> > +static bool icl_calc_mg_pll_state(struct intel_crtc_state
> > *crtc_state,
> > +				  struct intel_encoder *encoder,
> > int clock,
> > +				  struct intel_dpll_hw_state
> > *pll_state)
> > +{
> > +	/* TODO */
> > +	return true;
> > +}
> > +
> > +static struct intel_shared_dpll *
> > +icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state
> > *crtc_state,
> > +	     struct intel_encoder *encoder)
> > +{
> > +	struct intel_shared_dpll *pll;
> > +	struct intel_dpll_hw_state pll_state = {};
> > +	enum port port = encoder->port;
> > +	enum intel_dpll_id min, max;
> > +	int clock = crtc_state->port_clock;
> > +	bool ret;
> > +
> > +	switch (port) {
> > +	case PORT_A:
> > +	case PORT_B:
> > +		min = DPLL_ID_ICL_DPLL0;
> > +		max = DPLL_ID_ICL_DPLL1;
> > +		ret = icl_calc_dpll_state(crtc_state, encoder,
> > clock,
> > +					  &pll_state);
> > +		break;
> > +	case PORT_C:
> > +	case PORT_D:
> > +	case PORT_E:
> > +	case PORT_F:
> > +		min = max = icl_port_to_mg_pll_id(port);
> > +		ret = icl_calc_mg_pll_state(crtc_state, encoder,
> > clock,
> > +					    &pll_state);
> > +		break;
> > +	default:
> > +		MISSING_CASE(port);
> > +		return NULL;
> > +	}
> > +
> > +	if (!ret) {
> > +		DRM_DEBUG_KMS("Could not calculate PLL state.\n");
> > +		return NULL;
> > +	}
> > +
> > +	crtc_state->dpll_hw_state = pll_state;
> > +
> > +	pll = intel_find_shared_dpll(crtc, crtc_state, min, max);
> > +	if (!pll) {
> > +		DRM_DEBUG_KMS("No PLL selected\n");
> > +		return NULL;
> > +	}
> > +
> > +	intel_reference_shared_dpll(pll, crtc_state);
> > +
> > +	return pll;
> > +}
> > +
> > +static i915_reg_t icl_pll_id_to_enable_reg(enum intel_dpll_id id)
> > +{
> > +	switch (id) {
> > +	default:
> > +		MISSING_CASE(id);
> > +	case DPLL_ID_ICL_DPLL0:
> > +	case DPLL_ID_ICL_DPLL1:
> > +		return CNL_DPLL_ENABLE(id);
> > +	case DPLL_ID_ICL_MGPLL1:
> > +	case DPLL_ID_ICL_MGPLL2:
> > +	case DPLL_ID_ICL_MGPLL3:
> > +	case DPLL_ID_ICL_MGPLL4:
> > +		return MG_PLL_ENABLE(icl_mg_pll_id_to_port(id));
> > +	}
> > +}
> > +
> > +static bool icl_pll_get_hw_state(struct drm_i915_private
> > *dev_priv,
> > +				 struct intel_shared_dpll *pll,
> > +				 struct intel_dpll_hw_state
> > *hw_state)
> > +{
> > +	const enum intel_dpll_id id = pll->info->id;
> > +	uint32_t val;
> > +	enum port port;
> > +	bool ret = false;
> > +
> > +	if (!intel_display_power_get_if_enabled(dev_priv,
> > POWER_DOMAIN_PLLS))
> > +		return false;
> > +
> > +	val = I915_READ(icl_pll_id_to_enable_reg(id));
> > +	if (!(val & PLL_ENABLE))
> > +		goto out;
> > +
> > +	switch (id) {
> > +	case DPLL_ID_ICL_DPLL0:
> > +	case DPLL_ID_ICL_DPLL1:
> > +		hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(id));
> > +		hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(id));
> > +		break;
> > +	case DPLL_ID_ICL_MGPLL1:
> > +	case DPLL_ID_ICL_MGPLL2:
> > +	case DPLL_ID_ICL_MGPLL3:
> > +	case DPLL_ID_ICL_MGPLL4:
> > +		port = icl_mg_pll_id_to_port(id);
> > +		hw_state->mg_refclkin_ctl =
> > I915_READ(MG_REFCLKIN_CTL(port));
> > +		hw_state->mg_clktop2_coreclkctl1 =
> > +			I915_READ(MG_CLKTOP2_CORECLKCTL1(port));
> > +		hw_state->mg_clktop2_hsclkctl =
> > +			I915_READ(MG_CLKTOP2_HSCLKCTL(port));
> > +		hw_state->mg_pll_div0 =
> > I915_READ(MG_PLL_DIV0(port));
> > +		hw_state->mg_pll_div1 =
> > I915_READ(MG_PLL_DIV1(port));
> > +		hw_state->mg_pll_lf = I915_READ(MG_PLL_LF(port));
> > +		hw_state->mg_pll_frac_lock =
> > I915_READ(MG_PLL_FRAC_LOCK(port));
> > +		hw_state->mg_pll_ssc =
> > I915_READ(MG_PLL_SSC(port));
> > +		hw_state->mg_pll_bias =
> > I915_READ(MG_PLL_BIAS(port));
> > +		hw_state->mg_pll_tdc_coldst_bias =
> > +			I915_READ(MG_PLL_TDC_COLDST_BIAS(port));
> > +		break;
> > +	default:
> > +		MISSING_CASE(id);
> > +	}
> > +
> > +	ret = true;
> > +out:
> > +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> > +	return ret;
> > +}
> > +
> > +static void icl_dpll_write(struct drm_i915_private *dev_priv,
> > +			   struct intel_shared_dpll *pll)
> > +{
> > +	struct intel_dpll_hw_state *hw_state = &pll-
> > >state.hw_state;
> > +	const enum intel_dpll_id id = pll->info->id;
> > +
> > +	I915_WRITE(ICL_DPLL_CFGCR0(id), hw_state->cfgcr0);
> > +	I915_WRITE(ICL_DPLL_CFGCR1(id), hw_state->cfgcr1);
> > +	POSTING_READ(ICL_DPLL_CFGCR1(id));
> > +}
> > +
> > +static void icl_mg_pll_write(struct drm_i915_private *dev_priv,
> > +			     struct intel_shared_dpll *pll)
> > +{
> > +	struct intel_dpll_hw_state *hw_state = &pll-
> > >state.hw_state;
> > +	enum port port = icl_mg_pll_id_to_port(pll->info->id);
> > +
> > +	I915_WRITE(MG_REFCLKIN_CTL(port), hw_state-
> > >mg_refclkin_ctl);
> > +	I915_WRITE(MG_CLKTOP2_CORECLKCTL1(port),
> > +		   hw_state->mg_clktop2_coreclkctl1);
> > +	I915_WRITE(MG_CLKTOP2_HSCLKCTL(port), hw_state-
> > >mg_clktop2_hsclkctl);
> > +	I915_WRITE(MG_PLL_DIV0(port), hw_state->mg_pll_div0);
> > +	I915_WRITE(MG_PLL_DIV1(port), hw_state->mg_pll_div1);
> > +	I915_WRITE(MG_PLL_LF(port), hw_state->mg_pll_lf);
> > +	I915_WRITE(MG_PLL_FRAC_LOCK(port), hw_state-
> > >mg_pll_frac_lock);
> > +	I915_WRITE(MG_PLL_SSC(port), hw_state->mg_pll_ssc);
> > +	I915_WRITE(MG_PLL_BIAS(port), hw_state->mg_pll_bias);
> > +	I915_WRITE(MG_PLL_TDC_COLDST_BIAS(port),
> > +		   hw_state->mg_pll_tdc_coldst_bias);
> > +	POSTING_READ(MG_PLL_TDC_COLDST_BIAS(port));
> > +}
> > +
> > +static void icl_pll_enable(struct drm_i915_private *dev_priv,
> > +			   struct intel_shared_dpll *pll)
> > +{
> > +	const enum intel_dpll_id id = pll->info->id;
> > +	i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
> > +	uint32_t val;
> > +
> > +	val = I915_READ(enable_reg);
> > +	val |= PLL_POWER_ENABLE;
> > +	I915_WRITE(enable_reg, val);
> > +
> > +	/*
> > +	 * The spec says we need to "wait" but it also says it
> > should be
> > +	 * immediate.
> > +	 */
> > +	if (intel_wait_for_register(dev_priv, enable_reg,
> > PLL_POWER_STATE,
> > +				    PLL_POWER_STATE, 1))
> > +		DRM_ERROR("PLL %d Power not enabled\n", id);
> > +
> > +	switch (id) {
> > +	case DPLL_ID_ICL_DPLL0:
> > +	case DPLL_ID_ICL_DPLL1:
> > +		icl_dpll_write(dev_priv, pll);
> > +		break;
> > +	case DPLL_ID_ICL_MGPLL1:
> > +	case DPLL_ID_ICL_MGPLL2:
> > +	case DPLL_ID_ICL_MGPLL3:
> > +	case DPLL_ID_ICL_MGPLL4:
> > +		icl_mg_pll_write(dev_priv, pll);
> > +		break;
> > +	default:
> > +		MISSING_CASE(id);
> > +	}
> > +
> > +	/*
> > +	 * DVFS pre sequence would be here, but in our driver the
> > cdclk code
> > +	 * paths should already be setting the appropriate
> > voltage, hence we do
> > +	 * nothign here.
> > +	 */
> > +
> > +	val = I915_READ(enable_reg);
> > +	val |= PLL_ENABLE;
> > +	I915_WRITE(enable_reg, val);
> > +
> > +	if (intel_wait_for_register(dev_priv, enable_reg,
> > PLL_LOCK, PLL_LOCK,
> > +				    1)) /* 600us actually. */
> > +		DRM_ERROR("PLL %d not locked\n", id);
> > +
> > +	/* DVFS post sequence would be here. See the comment
> > above. */
> > +}
> > +
> > +static void icl_pll_disable(struct drm_i915_private *dev_priv,
> > +			    struct intel_shared_dpll *pll)
> > +{
> > +	const enum intel_dpll_id id = pll->info->id;
> > +	i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
> > +	uint32_t val;
> > +
> > +	/* The first steps are done by intel_ddi_post_disable().
> > */
> > +
> > +	/*
> > +	 * DVFS pre sequence would be here, but in our driver the
> > cdclk code
> > +	 * paths should already be setting the appropriate
> > voltage, hence we do
> > +	 * nothign here.
> > +	 */
> > +
> > +	val = I915_READ(enable_reg);
> > +	val &= ~PLL_ENABLE;
> > +	I915_WRITE(enable_reg, val);
> > +
> > +	/* Timeout is actually 1us. */
> > +	if (intel_wait_for_register(dev_priv, enable_reg,
> > PLL_LOCK, 0, 1))
> > +		DRM_ERROR("PLL %d locked\n", id);
> > +
> > +	/* DVFS post sequence would be here. See the comment
> > above. */
> > +
> > +	val = I915_READ(enable_reg);
> > +	val &= ~PLL_POWER_ENABLE;
> > +	I915_WRITE(enable_reg, val);
> > +
> > +	/*
> > +	 * The spec says we need to "wait" but it also says it
> > should be
> > +	 * immediate.
> > +	 */
> > +	if (intel_wait_for_register(dev_priv, enable_reg,
> > PLL_POWER_STATE, 0,
> > +				    1))
> > +		DRM_ERROR("PLL %d Power not disabled\n", id);
> > +}
> > +
> > +static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
> > +			      struct intel_dpll_hw_state
> > *hw_state)
> > +{
> > +	DRM_DEBUG_KMS("dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x,
> > "
> > +		      "mg_refclkin_ctl: 0x%x,
> > hg_clktop2_coreclkctl1: 0x%x, "
> > +		      "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0:
> > 0x%x, "
> > +		      "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, "
> > +		      "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, "
> > +		      "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias:
> > 0x%x\n",
> > +		      hw_state->cfgcr0, hw_state->cfgcr1,
> > +		      hw_state->mg_refclkin_ctl,
> > +		      hw_state->mg_clktop2_coreclkctl1,
> > +		      hw_state->mg_clktop2_hsclkctl,
> > +		      hw_state->mg_pll_div0,
> > +		      hw_state->mg_pll_div1,
> > +		      hw_state->mg_pll_lf,
> > +		      hw_state->mg_pll_frac_lock,
> > +		      hw_state->mg_pll_ssc,
> > +		      hw_state->mg_pll_bias,
> > +		      hw_state->mg_pll_tdc_coldst_bias);
> > +}
> > +
> > +static const struct intel_shared_dpll_funcs icl_pll_funcs = {
> > +	.enable = icl_pll_enable,
> > +	.disable = icl_pll_disable,
> > +	.get_hw_state = icl_pll_get_hw_state,
> > +};
> > +
> > +static const struct dpll_info icl_plls[] = {
> > +	{ "DPLL 0",   &icl_pll_funcs, DPLL_ID_ICL_DPLL0,  0 },
> > +	{ "DPLL 1",   &icl_pll_funcs, DPLL_ID_ICL_DPLL1,  0 },
> > +	{ "MG PLL 1", &icl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 },
> > +	{ "MG PLL 2", &icl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 },
> > +	{ "MG PLL 3", &icl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 },
> > +	{ "MG PLL 4", &icl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 },
> > +	{ },
> > +};
> > +
> > +static const struct intel_dpll_mgr icl_pll_mgr = {
> > +	.dpll_info = icl_plls,
> > +	.get_dpll = icl_get_dpll,
> > +	.dump_hw_state = icl_dump_hw_state,
> > +};
> > +
> >  /**
> >   * intel_shared_dpll_init - Initialize shared DPLLs
> >   * @dev: drm device
> > @@ -2412,7 +2720,9 @@ void intel_shared_dpll_init(struct drm_device
> > *dev)
> >  	const struct dpll_info *dpll_info;
> >  	int i;
> >  
> > -	if (IS_CANNONLAKE(dev_priv))
> > +	if (IS_ICELAKE(dev_priv))
> > +		dpll_mgr = &icl_pll_mgr;
> > +	else if (IS_CANNONLAKE(dev_priv))
> >  		dpll_mgr = &cnl_pll_mgr;
> >  	else if (IS_GEN9_BC(dev_priv))
> >  		dpll_mgr = &skl_pll_mgr;
> > diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h
> > b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> > index 4febfaa90bde..7a0cd564a9ee 100644
> > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
> > +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> > @@ -103,6 +103,32 @@ enum intel_dpll_id {
> >  	 * @DPLL_ID_SKL_DPLL3: SKL and later DPLL3
> >  	 */
> >  	DPLL_ID_SKL_DPLL3 = 3,
> > +
> > +
> > +	/**
> > +	 * @DPLL_ID_ICL_DPLL0: ICL combo PHY DPLL0
> > +	 */
> > +	DPLL_ID_ICL_DPLL0 = 0,
> > +	/**
> > +	 * @DPLL_ID_ICL_DPLL1: ICL combo PHY DPLL1
> > +	 */
> > +	DPLL_ID_ICL_DPLL1 = 1,
> > +	/**
> > +	 * @DPLL_ID_ICL_MGPLL1: ICL MG PLL 1 port 1 (C)
> > +	 */
> > +	DPLL_ID_ICL_MGPLL1 = 2,
> > +	/**
> > +	 * @DPLL_ID_ICL_MGPLL2: ICL MG PLL 1 port 2 (D)
> > +	 */
> > +	DPLL_ID_ICL_MGPLL2 = 3,
> > +	/**
> > +	 * @DPLL_ID_ICL_MGPLL3: ICL MG PLL 1 port 3 (E)
> > +	 */
> > +	DPLL_ID_ICL_MGPLL3 = 4,
> > +	/**
> > +	 * @DPLL_ID_ICL_MGPLL4: ICL MG PLL 1 port 4 (F)
> > +	 */
> > +	DPLL_ID_ICL_MGPLL4 = 5,
> >  };
> >  #define I915_NUM_PLLS 6
> >  
> > @@ -135,6 +161,21 @@ struct intel_dpll_hw_state {
> >  	/* bxt */
> >  	uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8,
> > pll9, pll10,
> >  		 pcsdw12;
> > +
> > +	/*
> > +	 * ICL uses the following, already defined:
> > +	 * uint32_t cfgcr0, cfgcr1;
> > +	 */
> > +	uint32_t mg_refclkin_ctl;
> > +	uint32_t mg_clktop2_coreclkctl1;
> > +	uint32_t mg_clktop2_hsclkctl;
> > +	uint32_t mg_pll_div0;
> > +	uint32_t mg_pll_div1;
> > +	uint32_t mg_pll_lf;
> > +	uint32_t mg_pll_frac_lock;
> > +	uint32_t mg_pll_ssc;
> > +	uint32_t mg_pll_bias;
> > +	uint32_t mg_pll_tdc_coldst_bias;
> >  };
> >  
> >  /**
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > b/drivers/gpu/drm/i915/intel_drv.h
> > index d1452fd2a58d..d77306950676 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1393,6 +1393,12 @@ uint32_t ddi_signal_levels(struct intel_dp
> > *intel_dp);
> >  u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
> >  int intel_ddi_toggle_hdcp_signalling(struct intel_encoder
> > *intel_encoder,
> >  				     bool enable);
> > +void icl_map_plls_to_ports(struct drm_crtc *crtc,
> > +			   struct intel_crtc_state *crtc_state,
> > +			   struct drm_atomic_state *old_state);
> > +void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
> > +			     struct intel_crtc_state *crtc_state,
> > +			     struct drm_atomic_state *old_state);
> >  
> >  unsigned int intel_fb_align_height(const struct drm_framebuffer
> > *fb,
> >  				   int plane, unsigned int
> > height);
> > -- 
> > 2.14.3
> > 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/8] drm/i915/icl: add definitions for the ICL PLL registers
  2018-03-28 21:57 ` [PATCH 2/8] drm/i915/icl: add definitions for the ICL PLL registers Paulo Zanoni
@ 2018-04-27 22:49   ` James Ausmus
  0 siblings, 0 replies; 20+ messages in thread
From: James Ausmus @ 2018-04-27 22:49 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Wed, Mar 28, 2018 at 02:57:57PM -0700, Paulo Zanoni wrote:
> There's a lot of code for the PLL enabling, so let's first only
> introduce the register definitions in order to make patch reviewing a
> little easier.
> 
> v2: Coding style (Jani).
> v3: Preparation for upstreaming.
> v4: Fix MG_CLKTOP2_CORECLKCTL1 address and random typos (James).
> 
> Cc: James Ausmus <james.ausmus@intel.com>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Reviewed-by: James Ausmus <james.ausmus@intel.com>

> ---
>  drivers/gpu/drm/i915/i915_reg.h | 149 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 149 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 250ff271bcf1..b79b2a8930da 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -8701,6 +8701,12 @@ enum skl_power_gate {
>  #define  PORT_CLK_SEL_NONE		(7<<29)
>  #define  PORT_CLK_SEL_MASK		(7<<29)
>  
> +/* On ICL+ this is the same as PORT_CLK_SEL, but all bits change. */
> +#define DDI_CLK_SEL(port)		PORT_CLK_SEL(port)
> +#define  DDI_CLK_SEL_NONE		(0x0 << 28)
> +#define  DDI_CLK_SEL_MG			(0x8 << 28)
> +#define  DDI_CLK_SEL_MASK		(0xF << 28)
> +
>  /* Transcoder clock selection */
>  #define _TRANS_CLK_SEL_A		0x46140
>  #define _TRANS_CLK_SEL_B		0x46144
> @@ -8831,6 +8837,7 @@ enum skl_power_gate {
>   * CNL Clocks
>   */
>  #define DPCLKA_CFGCR0				_MMIO(0x6C200)
> +#define DPCLKA_CFGCR0_ICL			_MMIO(0x164280)
>  #define  DPCLKA_CFGCR0_DDI_CLK_OFF(port)	(1 << ((port) ==  PORT_F ? 23 : \
>  						      (port)+10))
>  #define  DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port)	((port) == PORT_F ? 21 : \
> @@ -8847,10 +8854,141 @@ enum skl_power_gate {
>  #define  PLL_POWER_STATE	(1 << 26)
>  #define CNL_DPLL_ENABLE(pll)	_MMIO_PLL(pll, DPLL0_ENABLE, DPLL1_ENABLE)
>  
> +#define _MG_PLL1_ENABLE		0x46030
> +#define _MG_PLL2_ENABLE		0x46034
> +#define _MG_PLL3_ENABLE		0x46038
> +#define _MG_PLL4_ENABLE		0x4603C
> +/* Bits are the same as DPLL0_ENABLE */
> +#define MG_PLL_ENABLE(port)	_MMIO_PORT((port) - PORT_C, _MG_PLL1_ENABLE, \
> +					   _MG_PLL2_ENABLE)
> +
> +#define _MG_REFCLKIN_CTL_PORT1				0x16892C
> +#define _MG_REFCLKIN_CTL_PORT2				0x16992C
> +#define _MG_REFCLKIN_CTL_PORT3				0x16A92C
> +#define _MG_REFCLKIN_CTL_PORT4				0x16B92C
> +#define   MG_REFCLKIN_CTL_OD_2_MUX(x)			((x) << 8)
> +#define MG_REFCLKIN_CTL(port) _MMIO_PORT((port) - PORT_C, \
> +					 _MG_REFCLKIN_CTL_PORT1, \
> +					 _MG_REFCLKIN_CTL_PORT2)
> +
> +#define _MG_CLKTOP2_CORECLKCTL1_PORT1			0x1688D8
> +#define _MG_CLKTOP2_CORECLKCTL1_PORT2			0x1698D8
> +#define _MG_CLKTOP2_CORECLKCTL1_PORT3			0x16A8D8
> +#define _MG_CLKTOP2_CORECLKCTL1_PORT4			0x16B8D8
> +#define   MG_CLKTOP2_CORECLKCTL1_B_DIVRATIO(x)		((x) << 16)
> +#define   MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO(x)		((x) << 8)
> +#define MG_CLKTOP2_CORECLKCTL1(port) _MMIO_PORT((port) - PORT_C, \
> +						_MG_CLKTOP2_CORECLKCTL1_PORT1, \
> +						_MG_CLKTOP2_CORECLKCTL1_PORT2)
> +
> +#define _MG_CLKTOP2_HSCLKCTL_PORT1			0x1688D4
> +#define _MG_CLKTOP2_HSCLKCTL_PORT2			0x1698D4
> +#define _MG_CLKTOP2_HSCLKCTL_PORT3			0x16A8D4
> +#define _MG_CLKTOP2_HSCLKCTL_PORT4			0x16B8D4
> +#define   MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL(x)		((x) << 16)
> +#define   MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL(x)	((x) << 14)
> +#define   MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO(x)		((x) << 12)
> +#define   MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO(x)		((x) << 8)
> +#define MG_CLKTOP2_HSCLKCTL(port) _MMIO_PORT((port) - PORT_C, \
> +					     _MG_CLKTOP2_HSCLKCTL_PORT1, \
> +					     _MG_CLKTOP2_HSCLKCTL_PORT2)
> +
> +#define _MG_PLL_DIV0_PORT1				0x168A00
> +#define _MG_PLL_DIV0_PORT2				0x169A00
> +#define _MG_PLL_DIV0_PORT3				0x16AA00
> +#define _MG_PLL_DIV0_PORT4				0x16BA00
> +#define   MG_PLL_DIV0_FRACNEN_H				(1 << 30)
> +#define   MG_PLL_DIV0_FBDIV_FRAC(x)			((x) << 8)
> +#define   MG_PLL_DIV0_FBDIV_INT(x)			((x) << 0)
> +#define MG_PLL_DIV0(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_DIV0_PORT1, \
> +				     _MG_PLL_DIV0_PORT2)
> +
> +#define _MG_PLL_DIV1_PORT1				0x168A04
> +#define _MG_PLL_DIV1_PORT2				0x169A04
> +#define _MG_PLL_DIV1_PORT3				0x16AA04
> +#define _MG_PLL_DIV1_PORT4				0x16BA04
> +#define   MG_PLL_DIV1_IREF_NDIVRATIO(x)			((x) << 16)
> +#define   MG_PLL_DIV1_DITHER_DIV_1			(0 << 12)
> +#define   MG_PLL_DIV1_DITHER_DIV_2			(1 << 12)
> +#define   MG_PLL_DIV1_DITHER_DIV_4			(2 << 12)
> +#define   MG_PLL_DIV1_DITHER_DIV_8			(3 << 12)
> +#define   MG_PLL_DIV1_NDIVRATIO(x)			((x) << 4)
> +#define   MG_PLL_DIV1_FBPREDIV(x)			((x) << 0)
> +#define MG_PLL_DIV1(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_DIV1_PORT1, \
> +				     _MG_PLL_DIV1_PORT2)
> +
> +#define _MG_PLL_LF_PORT1				0x168A08
> +#define _MG_PLL_LF_PORT2				0x169A08
> +#define _MG_PLL_LF_PORT3				0x16AA08
> +#define _MG_PLL_LF_PORT4				0x16BA08
> +#define   MG_PLL_LF_TDCTARGETCNT(x)			((x) << 24)
> +#define   MG_PLL_LF_AFCCNTSEL_256			(0 << 20)
> +#define   MG_PLL_LF_AFCCNTSEL_512			(1 << 20)
> +#define   MG_PLL_LF_GAINCTRL(x)				((x) << 16)
> +#define   MG_PLL_LF_INT_COEFF(x)			((x) << 8)
> +#define   MG_PLL_LF_PROP_COEFF(x)			((x) << 0)
> +#define MG_PLL_LF(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_LF_PORT1, \
> +				   _MG_PLL_LF_PORT2)
> +
> +#define _MG_PLL_FRAC_LOCK_PORT1				0x168A0C
> +#define _MG_PLL_FRAC_LOCK_PORT2				0x169A0C
> +#define _MG_PLL_FRAC_LOCK_PORT3				0x16AA0C
> +#define _MG_PLL_FRAC_LOCK_PORT4				0x16BA0C
> +#define   MG_PLL_FRAC_LOCK_TRUELOCK_CRIT_32		(1 << 18)
> +#define   MG_PLL_FRAC_LOCK_EARLYLOCK_CRIT_32		(1 << 16)
> +#define   MG_PLL_FRAC_LOCK_LOCKTHRESH(x)		((x) << 11)
> +#define   MG_PLL_FRAC_LOCK_DCODITHEREN			(1 << 10)
> +#define   MG_PLL_FRAC_LOCK_FEEDFWRDCAL_EN		(1 << 8)
> +#define   MG_PLL_FRAC_LOCK_FEEDFWRDGAIN(x)		((x) << 0)
> +#define MG_PLL_FRAC_LOCK(port) _MMIO_PORT((port) - PORT_C, \
> +					  _MG_PLL_FRAC_LOCK_PORT1, \
> +					  _MG_PLL_FRAC_LOCK_PORT2)
> +
> +#define _MG_PLL_SSC_PORT1				0x168A10
> +#define _MG_PLL_SSC_PORT2				0x169A10
> +#define _MG_PLL_SSC_PORT3				0x16AA10
> +#define _MG_PLL_SSC_PORT4				0x16BA10
> +#define   MG_PLL_SSC_EN					(1 << 28)
> +#define   MG_PLL_SSC_TYPE(x)				((x) << 26)
> +#define   MG_PLL_SSC_STEPLENGTH(x)			((x) << 16)
> +#define   MG_PLL_SSC_STEPNUM(x)				((x) << 10)
> +#define   MG_PLL_SSC_FLLEN				(1 << 9)
> +#define   MG_PLL_SSC_STEPSIZE(x)			((x) << 0)
> +#define MG_PLL_SSC(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_SSC_PORT1, \
> +				    _MG_PLL_SSC_PORT2)
> +
> +#define _MG_PLL_BIAS_PORT1				0x168A14
> +#define _MG_PLL_BIAS_PORT2				0x169A14
> +#define _MG_PLL_BIAS_PORT3				0x16AA14
> +#define _MG_PLL_BIAS_PORT4				0x16BA14
> +#define   MG_PLL_BIAS_BIAS_GB_SEL(x)			((x) << 30)
> +#define   MG_PLL_BIAS_INIT_DCOAMP(x)			((x) << 24)
> +#define   MG_PLL_BIAS_BIAS_BONUS(x)			((x) << 16)
> +#define   MG_PLL_BIAS_BIASCAL_EN			(1 << 15)
> +#define   MG_PLL_BIAS_CTRIM(x)				((x) << 8)
> +#define   MG_PLL_BIAS_VREF_RDAC(x)			((x) << 5)
> +#define   MG_PLL_BIAS_IREFTRIM(x)			((x) << 0)
> +#define MG_PLL_BIAS(port) _MMIO_PORT((port) - PORT_C, _MG_PLL_BIAS_PORT1, \
> +				     _MG_PLL_BIAS_PORT2)
> +
> +#define _MG_PLL_TDC_COLDST_BIAS_PORT1			0x168A18
> +#define _MG_PLL_TDC_COLDST_BIAS_PORT2			0x169A18
> +#define _MG_PLL_TDC_COLDST_BIAS_PORT3			0x16AA18
> +#define _MG_PLL_TDC_COLDST_BIAS_PORT4			0x16BA18
> +#define   MG_PLL_TDC_COLDST_IREFINT_EN			(1 << 27)
> +#define   MG_PLL_TDC_COLDST_REFBIAS_START_PULSE_W(x)	((x) << 17)
> +#define   MG_PLL_TDC_COLDST_COLDSTART			(1 << 16)
> +#define   MG_PLL_TDC_TDCOVCCORR_EN			(1 << 2)
> +#define   MG_PLL_TDC_TDCSEL(x)				((x) << 0)
> +#define MG_PLL_TDC_COLDST_BIAS(port) _MMIO_PORT((port) - PORT_C, \
> +						_MG_PLL_TDC_COLDST_BIAS_PORT1, \
> +						_MG_PLL_TDC_COLDST_BIAS_PORT2)
> +
>  #define _CNL_DPLL0_CFGCR0		0x6C000
>  #define _CNL_DPLL1_CFGCR0		0x6C080
>  #define  DPLL_CFGCR0_HDMI_MODE		(1 << 30)
>  #define  DPLL_CFGCR0_SSC_ENABLE		(1 << 29)
> +#define  DPLL_CFGCR0_SSC_ENABLE_ICL	(1 << 25)
>  #define  DPLL_CFGCR0_LINK_RATE_MASK	(0xf << 25)
>  #define  DPLL_CFGCR0_LINK_RATE_2700	(0 << 25)
>  #define  DPLL_CFGCR0_LINK_RATE_1350	(1 << 25)
> @@ -8884,8 +9022,19 @@ enum skl_power_gate {
>  #define  DPLL_CFGCR1_PDIV_5		(4 << 2)
>  #define  DPLL_CFGCR1_PDIV_7		(8 << 2)
>  #define  DPLL_CFGCR1_CENTRAL_FREQ	(3 << 0)
> +#define  DPLL_CFGCR1_CENTRAL_FREQ_8400	(3 << 0)
>  #define CNL_DPLL_CFGCR1(pll)		_MMIO_PLL(pll, _CNL_DPLL0_CFGCR1, _CNL_DPLL1_CFGCR1)
>  
> +#define _ICL_DPLL0_CFGCR0		0x164000
> +#define _ICL_DPLL1_CFGCR0		0x164080
> +#define ICL_DPLL_CFGCR0(pll)		_MMIO_PLL(pll, _ICL_DPLL0_CFGCR0, \
> +						  _ICL_DPLL1_CFGCR0)
> +
> +#define _ICL_DPLL0_CFGCR1		0x164004
> +#define _ICL_DPLL1_CFGCR1		0x164084
> +#define ICL_DPLL_CFGCR1(pll)		_MMIO_PLL(pll, _ICL_DPLL0_CFGCR1, \
> +						  _ICL_DPLL1_CFGCR1)
> +
>  /* BXT display engine PLL */
>  #define BXT_DE_PLL_CTL			_MMIO(0x6d000)
>  #define   BXT_DE_PLL_RATIO(x)		(x)	/* {60,65,100} * 19.2MHz */
> -- 
> 2.14.3
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 3/8] drm/i915/icl: add basic support for the ICL clocks
  2018-04-25  0:22     ` Paulo Zanoni
@ 2018-04-27 23:14       ` Paulo Zanoni
  2018-05-07 18:52         ` James Ausmus
  0 siblings, 1 reply; 20+ messages in thread
From: Paulo Zanoni @ 2018-04-27 23:14 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

This commit introduces the definitions for the ICL clocks and adds the
basic functions to the shared DPLL framework. It adds code for the
Enable and Disable sequences for some PLLs, but it does not have the
code to compute the actual PLL values, which are marked as TODO
comments and should be introduced as separate commits.

Special thanks to James Ausmus for investigating and fixing a bug with
the placement of icl_unmap_plls_to_ports() function.

v2:
 - Rebase around dpll_lock changes.
v3:
 - The spec now says what the timeouts should be.
 - Touch DPCLKA_CFGCR0_ICL at the appropriate time so we don't freeze
   the machine.
 - Checkpatch found a white space problem.
 - Small adjustments before upstreaming.
v4:
 - Move the ICL checks out of the *map_plls_to_ports() functions
  (James)
 - Add extra encoder check (James)
 - Call icl_unmap_plls_to_ports() later (James)
v5:
 - Rebase after the pll struct changes.
v6:
 - Properly make the unmap function based on encoders_post_disable()
   with regarding to checks and iterators.
 - Address checkpatch comment on "min = max = x()".

Cc: James Ausmus <james.ausmus@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c   |  22 +++
 drivers/gpu/drm/i915/intel_ddi.c      |  98 ++++++++++-
 drivers/gpu/drm/i915/intel_display.c  |  16 ++
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 313 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_dpll_mgr.h |  41 +++++
 drivers/gpu/drm/i915/intel_drv.h      |   6 +
 6 files changed, 491 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index cb1a804bf72e..ba8927cb1dcc 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3365,6 +3365,28 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
 		seq_printf(m, " fp0:     0x%08x\n", pll->state.hw_state.fp0);
 		seq_printf(m, " fp1:     0x%08x\n", pll->state.hw_state.fp1);
 		seq_printf(m, " wrpll:   0x%08x\n", pll->state.hw_state.wrpll);
+		seq_printf(m, " cfgcr0:  0x%08x\n", pll->state.hw_state.cfgcr0);
+		seq_printf(m, " cfgcr1:  0x%08x\n", pll->state.hw_state.cfgcr1);
+		seq_printf(m, " mg_refclkin_ctl:        0x%08x\n",
+			   pll->state.hw_state.mg_refclkin_ctl);
+		seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n",
+			   pll->state.hw_state.mg_clktop2_coreclkctl1);
+		seq_printf(m, " mg_clktop2_hsclkctl:    0x%08x\n",
+			   pll->state.hw_state.mg_clktop2_hsclkctl);
+		seq_printf(m, " mg_pll_div0:  0x%08x\n",
+			   pll->state.hw_state.mg_pll_div0);
+		seq_printf(m, " mg_pll_div1:  0x%08x\n",
+			   pll->state.hw_state.mg_pll_div1);
+		seq_printf(m, " mg_pll_lf:    0x%08x\n",
+			   pll->state.hw_state.mg_pll_lf);
+		seq_printf(m, " mg_pll_frac_lock: 0x%08x\n",
+			   pll->state.hw_state.mg_pll_frac_lock);
+		seq_printf(m, " mg_pll_ssc:   0x%08x\n",
+			   pll->state.hw_state.mg_pll_ssc);
+		seq_printf(m, " mg_pll_bias:  0x%08x\n",
+			   pll->state.hw_state.mg_pll_bias);
+		seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n",
+			   pll->state.hw_state.mg_pll_tdc_coldst_bias);
 	}
 	drm_modeset_unlock_all(dev);
 
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 92cb26b18a9b..178a7b0d0149 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1013,6 +1013,25 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
 	}
 }
 
+static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
+				       const struct intel_shared_dpll *pll)
+{
+	const enum intel_dpll_id id = pll->info->id;
+
+	switch (id) {
+	default:
+		MISSING_CASE(id);
+	case DPLL_ID_ICL_DPLL0:
+	case DPLL_ID_ICL_DPLL1:
+		return DDI_CLK_SEL_NONE;
+	case DPLL_ID_ICL_MGPLL1:
+	case DPLL_ID_ICL_MGPLL2:
+	case DPLL_ID_ICL_MGPLL3:
+	case DPLL_ID_ICL_MGPLL4:
+		return DDI_CLK_SEL_MG;
+	}
+}
+
 /* Starting with Haswell, different DDI ports can work in FDI mode for
  * connection to the PCH-located connectors. For this, it is necessary to train
  * both the DDI port and PCH receiver for the desired DDI buffer settings.
@@ -2234,6 +2253,69 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
 	return DDI_BUF_TRANS_SELECT(level);
 }
 
+void icl_map_plls_to_ports(struct drm_crtc *crtc,
+			   struct intel_crtc_state *crtc_state,
+			   struct drm_atomic_state *old_state)
+{
+	struct intel_shared_dpll *pll = crtc_state->shared_dpll;
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+	struct drm_connector_state *conn_state;
+	struct drm_connector *conn;
+	int i;
+
+	for_each_new_connector_in_state(old_state, conn, conn_state, i) {
+		struct intel_encoder *encoder =
+			to_intel_encoder(conn_state->best_encoder);
+		enum port port = encoder->port;
+		uint32_t val;
+
+		if (conn_state->crtc != crtc)
+			continue;
+
+		mutex_lock(&dev_priv->dpll_lock);
+
+		val = I915_READ(DPCLKA_CFGCR0_ICL);
+		WARN_ON((val & DPCLKA_CFGCR0_DDI_CLK_OFF(port)) == 0);
+
+		if (port == PORT_A || port == PORT_B) {
+			val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
+			val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
+			I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+			POSTING_READ(DPCLKA_CFGCR0_ICL);
+		}
+
+		val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
+		I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+
+		mutex_unlock(&dev_priv->dpll_lock);
+	}
+}
+
+void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
+			     struct intel_crtc_state *crtc_state,
+			     struct drm_atomic_state *old_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+	struct drm_connector_state *old_conn_state;
+	struct drm_connector *conn;
+	int i;
+
+	for_each_old_connector_in_state(old_state, conn, old_conn_state, i) {
+		struct intel_encoder *encoder =
+			to_intel_encoder(old_conn_state->best_encoder);
+		enum port port = encoder->port;
+
+		if (old_conn_state->crtc != crtc)
+			continue;
+
+		mutex_lock(&dev_priv->dpll_lock);
+		I915_WRITE(DPCLKA_CFGCR0_ICL,
+			   I915_READ(DPCLKA_CFGCR0_ICL) |
+			   DPCLKA_CFGCR0_DDI_CLK_OFF(port));
+		mutex_unlock(&dev_priv->dpll_lock);
+	}
+}
+
 static void intel_ddi_clk_select(struct intel_encoder *encoder,
 				 const struct intel_shared_dpll *pll)
 {
@@ -2246,7 +2328,11 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
 
 	mutex_lock(&dev_priv->dpll_lock);
 
-	if (IS_CANNONLAKE(dev_priv)) {
+	if (IS_ICELAKE(dev_priv)) {
+		if (port >= PORT_C)
+			I915_WRITE(DDI_CLK_SEL(port),
+				   icl_pll_to_ddi_pll_sel(encoder, pll));
+	} else if (IS_CANNONLAKE(dev_priv)) {
 		/* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */
 		val = I915_READ(DPCLKA_CFGCR0);
 		val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
@@ -2284,14 +2370,18 @@ static void intel_ddi_clk_disable(struct intel_encoder *encoder)
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	enum port port = encoder->port;
 
-	if (IS_CANNONLAKE(dev_priv))
+	if (IS_ICELAKE(dev_priv)) {
+		if (port >= PORT_C)
+			I915_WRITE(DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
+	} else if (IS_CANNONLAKE(dev_priv)) {
 		I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) |
 			   DPCLKA_CFGCR0_DDI_CLK_OFF(port));
-	else if (IS_GEN9_BC(dev_priv))
+	} else if (IS_GEN9_BC(dev_priv)) {
 		I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) |
 			   DPLL_CTRL2_DDI_CLK_OFF(port));
-	else if (INTEL_GEN(dev_priv) < 9)
+	} else if (INTEL_GEN(dev_priv) < 9) {
 		I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
+	}
 }
 
 static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 48576ea2d36c..1d3da5b7d33c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5559,6 +5559,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 	if (intel_crtc->config->shared_dpll)
 		intel_enable_shared_dpll(intel_crtc);
 
+	if (INTEL_GEN(dev_priv) >= 11)
+		icl_map_plls_to_ports(crtc, pipe_config, old_state);
+
 	if (intel_crtc_has_dp_encoder(intel_crtc->config))
 		intel_dp_set_m_n(intel_crtc, M1_N1);
 
@@ -5756,6 +5759,9 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
 		intel_ddi_disable_pipe_clock(intel_crtc->config);
 
 	intel_encoders_post_disable(crtc, old_crtc_state, old_state);
+
+	if (INTEL_GEN(dev_priv) >= 11)
+		icl_unmap_plls_to_ports(crtc, old_crtc_state, old_state);
 }
 
 static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -11386,6 +11392,16 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
 	PIPE_CONF_CHECK_X(dpll_hw_state.pll9);
 	PIPE_CONF_CHECK_X(dpll_hw_state.pll10);
 	PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias);
+	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias);
 
 	PIPE_CONF_CHECK_X(dsi_pll.ctrl);
 	PIPE_CONF_CHECK_X(dsi_pll.div);
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index d5e114e9660b..14f5414ceab2 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -2399,6 +2399,315 @@ static const struct intel_dpll_mgr cnl_pll_mgr = {
 	.dump_hw_state = cnl_dump_hw_state,
 };
 
+static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
+				struct intel_encoder *encoder, int clock,
+				struct intel_dpll_hw_state *pll_state)
+{
+	/* TODO */
+	return true;
+}
+
+static enum port icl_mg_pll_id_to_port(enum intel_dpll_id id)
+{
+	return id - DPLL_ID_ICL_MGPLL1 + PORT_C;
+}
+
+static enum intel_dpll_id icl_port_to_mg_pll_id(enum port port)
+{
+	return port - PORT_C + DPLL_ID_ICL_MGPLL1;
+}
+
+static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
+				  struct intel_encoder *encoder, int clock,
+				  struct intel_dpll_hw_state *pll_state)
+{
+	/* TODO */
+	return true;
+}
+
+static struct intel_shared_dpll *
+icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+	     struct intel_encoder *encoder)
+{
+	struct intel_shared_dpll *pll;
+	struct intel_dpll_hw_state pll_state = {};
+	enum port port = encoder->port;
+	enum intel_dpll_id min, max;
+	int clock = crtc_state->port_clock;
+	bool ret;
+
+	switch (port) {
+	case PORT_A:
+	case PORT_B:
+		min = DPLL_ID_ICL_DPLL0;
+		max = DPLL_ID_ICL_DPLL1;
+		ret = icl_calc_dpll_state(crtc_state, encoder, clock,
+					  &pll_state);
+		break;
+	case PORT_C:
+	case PORT_D:
+	case PORT_E:
+	case PORT_F:
+		min = icl_port_to_mg_pll_id(port);
+		max = min;
+		ret = icl_calc_mg_pll_state(crtc_state, encoder, clock,
+					    &pll_state);
+		break;
+	default:
+		MISSING_CASE(port);
+		return NULL;
+	}
+
+	if (!ret) {
+		DRM_DEBUG_KMS("Could not calculate PLL state.\n");
+		return NULL;
+	}
+
+	crtc_state->dpll_hw_state = pll_state;
+
+	pll = intel_find_shared_dpll(crtc, crtc_state, min, max);
+	if (!pll) {
+		DRM_DEBUG_KMS("No PLL selected\n");
+		return NULL;
+	}
+
+	intel_reference_shared_dpll(pll, crtc_state);
+
+	return pll;
+}
+
+static i915_reg_t icl_pll_id_to_enable_reg(enum intel_dpll_id id)
+{
+	switch (id) {
+	default:
+		MISSING_CASE(id);
+	case DPLL_ID_ICL_DPLL0:
+	case DPLL_ID_ICL_DPLL1:
+		return CNL_DPLL_ENABLE(id);
+	case DPLL_ID_ICL_MGPLL1:
+	case DPLL_ID_ICL_MGPLL2:
+	case DPLL_ID_ICL_MGPLL3:
+	case DPLL_ID_ICL_MGPLL4:
+		return MG_PLL_ENABLE(icl_mg_pll_id_to_port(id));
+	}
+}
+
+static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
+				 struct intel_shared_dpll *pll,
+				 struct intel_dpll_hw_state *hw_state)
+{
+	const enum intel_dpll_id id = pll->info->id;
+	uint32_t val;
+	enum port port;
+	bool ret = false;
+
+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+		return false;
+
+	val = I915_READ(icl_pll_id_to_enable_reg(id));
+	if (!(val & PLL_ENABLE))
+		goto out;
+
+	switch (id) {
+	case DPLL_ID_ICL_DPLL0:
+	case DPLL_ID_ICL_DPLL1:
+		hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(id));
+		hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(id));
+		break;
+	case DPLL_ID_ICL_MGPLL1:
+	case DPLL_ID_ICL_MGPLL2:
+	case DPLL_ID_ICL_MGPLL3:
+	case DPLL_ID_ICL_MGPLL4:
+		port = icl_mg_pll_id_to_port(id);
+		hw_state->mg_refclkin_ctl = I915_READ(MG_REFCLKIN_CTL(port));
+		hw_state->mg_clktop2_coreclkctl1 =
+			I915_READ(MG_CLKTOP2_CORECLKCTL1(port));
+		hw_state->mg_clktop2_hsclkctl =
+			I915_READ(MG_CLKTOP2_HSCLKCTL(port));
+		hw_state->mg_pll_div0 = I915_READ(MG_PLL_DIV0(port));
+		hw_state->mg_pll_div1 = I915_READ(MG_PLL_DIV1(port));
+		hw_state->mg_pll_lf = I915_READ(MG_PLL_LF(port));
+		hw_state->mg_pll_frac_lock = I915_READ(MG_PLL_FRAC_LOCK(port));
+		hw_state->mg_pll_ssc = I915_READ(MG_PLL_SSC(port));
+		hw_state->mg_pll_bias = I915_READ(MG_PLL_BIAS(port));
+		hw_state->mg_pll_tdc_coldst_bias =
+			I915_READ(MG_PLL_TDC_COLDST_BIAS(port));
+		break;
+	default:
+		MISSING_CASE(id);
+	}
+
+	ret = true;
+out:
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	return ret;
+}
+
+static void icl_dpll_write(struct drm_i915_private *dev_priv,
+			   struct intel_shared_dpll *pll)
+{
+	struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
+	const enum intel_dpll_id id = pll->info->id;
+
+	I915_WRITE(ICL_DPLL_CFGCR0(id), hw_state->cfgcr0);
+	I915_WRITE(ICL_DPLL_CFGCR1(id), hw_state->cfgcr1);
+	POSTING_READ(ICL_DPLL_CFGCR1(id));
+}
+
+static void icl_mg_pll_write(struct drm_i915_private *dev_priv,
+			     struct intel_shared_dpll *pll)
+{
+	struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
+	enum port port = icl_mg_pll_id_to_port(pll->info->id);
+
+	I915_WRITE(MG_REFCLKIN_CTL(port), hw_state->mg_refclkin_ctl);
+	I915_WRITE(MG_CLKTOP2_CORECLKCTL1(port),
+		   hw_state->mg_clktop2_coreclkctl1);
+	I915_WRITE(MG_CLKTOP2_HSCLKCTL(port), hw_state->mg_clktop2_hsclkctl);
+	I915_WRITE(MG_PLL_DIV0(port), hw_state->mg_pll_div0);
+	I915_WRITE(MG_PLL_DIV1(port), hw_state->mg_pll_div1);
+	I915_WRITE(MG_PLL_LF(port), hw_state->mg_pll_lf);
+	I915_WRITE(MG_PLL_FRAC_LOCK(port), hw_state->mg_pll_frac_lock);
+	I915_WRITE(MG_PLL_SSC(port), hw_state->mg_pll_ssc);
+	I915_WRITE(MG_PLL_BIAS(port), hw_state->mg_pll_bias);
+	I915_WRITE(MG_PLL_TDC_COLDST_BIAS(port),
+		   hw_state->mg_pll_tdc_coldst_bias);
+	POSTING_READ(MG_PLL_TDC_COLDST_BIAS(port));
+}
+
+static void icl_pll_enable(struct drm_i915_private *dev_priv,
+			   struct intel_shared_dpll *pll)
+{
+	const enum intel_dpll_id id = pll->info->id;
+	i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
+	uint32_t val;
+
+	val = I915_READ(enable_reg);
+	val |= PLL_POWER_ENABLE;
+	I915_WRITE(enable_reg, val);
+
+	/*
+	 * The spec says we need to "wait" but it also says it should be
+	 * immediate.
+	 */
+	if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE,
+				    PLL_POWER_STATE, 1))
+		DRM_ERROR("PLL %d Power not enabled\n", id);
+
+	switch (id) {
+	case DPLL_ID_ICL_DPLL0:
+	case DPLL_ID_ICL_DPLL1:
+		icl_dpll_write(dev_priv, pll);
+		break;
+	case DPLL_ID_ICL_MGPLL1:
+	case DPLL_ID_ICL_MGPLL2:
+	case DPLL_ID_ICL_MGPLL3:
+	case DPLL_ID_ICL_MGPLL4:
+		icl_mg_pll_write(dev_priv, pll);
+		break;
+	default:
+		MISSING_CASE(id);
+	}
+
+	/*
+	 * DVFS pre sequence would be here, but in our driver the cdclk code
+	 * paths should already be setting the appropriate voltage, hence we do
+	 * nothign here.
+	 */
+
+	val = I915_READ(enable_reg);
+	val |= PLL_ENABLE;
+	I915_WRITE(enable_reg, val);
+
+	if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, PLL_LOCK,
+				    1)) /* 600us actually. */
+		DRM_ERROR("PLL %d not locked\n", id);
+
+	/* DVFS post sequence would be here. See the comment above. */
+}
+
+static void icl_pll_disable(struct drm_i915_private *dev_priv,
+			    struct intel_shared_dpll *pll)
+{
+	const enum intel_dpll_id id = pll->info->id;
+	i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
+	uint32_t val;
+
+	/* The first steps are done by intel_ddi_post_disable(). */
+
+	/*
+	 * DVFS pre sequence would be here, but in our driver the cdclk code
+	 * paths should already be setting the appropriate voltage, hence we do
+	 * nothign here.
+	 */
+
+	val = I915_READ(enable_reg);
+	val &= ~PLL_ENABLE;
+	I915_WRITE(enable_reg, val);
+
+	/* Timeout is actually 1us. */
+	if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, 0, 1))
+		DRM_ERROR("PLL %d locked\n", id);
+
+	/* DVFS post sequence would be here. See the comment above. */
+
+	val = I915_READ(enable_reg);
+	val &= ~PLL_POWER_ENABLE;
+	I915_WRITE(enable_reg, val);
+
+	/*
+	 * The spec says we need to "wait" but it also says it should be
+	 * immediate.
+	 */
+	if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE, 0,
+				    1))
+		DRM_ERROR("PLL %d Power not disabled\n", id);
+}
+
+static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
+			      struct intel_dpll_hw_state *hw_state)
+{
+	DRM_DEBUG_KMS("dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, "
+		      "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
+		      "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, "
+		      "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, "
+		      "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, "
+		      "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n",
+		      hw_state->cfgcr0, hw_state->cfgcr1,
+		      hw_state->mg_refclkin_ctl,
+		      hw_state->mg_clktop2_coreclkctl1,
+		      hw_state->mg_clktop2_hsclkctl,
+		      hw_state->mg_pll_div0,
+		      hw_state->mg_pll_div1,
+		      hw_state->mg_pll_lf,
+		      hw_state->mg_pll_frac_lock,
+		      hw_state->mg_pll_ssc,
+		      hw_state->mg_pll_bias,
+		      hw_state->mg_pll_tdc_coldst_bias);
+}
+
+static const struct intel_shared_dpll_funcs icl_pll_funcs = {
+	.enable = icl_pll_enable,
+	.disable = icl_pll_disable,
+	.get_hw_state = icl_pll_get_hw_state,
+};
+
+static const struct dpll_info icl_plls[] = {
+	{ "DPLL 0",   &icl_pll_funcs, DPLL_ID_ICL_DPLL0,  0 },
+	{ "DPLL 1",   &icl_pll_funcs, DPLL_ID_ICL_DPLL1,  0 },
+	{ "MG PLL 1", &icl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 },
+	{ "MG PLL 2", &icl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 },
+	{ "MG PLL 3", &icl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 },
+	{ "MG PLL 4", &icl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 },
+	{ },
+};
+
+static const struct intel_dpll_mgr icl_pll_mgr = {
+	.dpll_info = icl_plls,
+	.get_dpll = icl_get_dpll,
+	.dump_hw_state = icl_dump_hw_state,
+};
+
 /**
  * intel_shared_dpll_init - Initialize shared DPLLs
  * @dev: drm device
@@ -2412,7 +2721,9 @@ void intel_shared_dpll_init(struct drm_device *dev)
 	const struct dpll_info *dpll_info;
 	int i;
 
-	if (IS_CANNONLAKE(dev_priv))
+	if (IS_ICELAKE(dev_priv))
+		dpll_mgr = &icl_pll_mgr;
+	else if (IS_CANNONLAKE(dev_priv))
 		dpll_mgr = &cnl_pll_mgr;
 	else if (IS_GEN9_BC(dev_priv))
 		dpll_mgr = &skl_pll_mgr;
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
index 4febfaa90bde..7a0cd564a9ee 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h
@@ -103,6 +103,32 @@ enum intel_dpll_id {
 	 * @DPLL_ID_SKL_DPLL3: SKL and later DPLL3
 	 */
 	DPLL_ID_SKL_DPLL3 = 3,
+
+
+	/**
+	 * @DPLL_ID_ICL_DPLL0: ICL combo PHY DPLL0
+	 */
+	DPLL_ID_ICL_DPLL0 = 0,
+	/**
+	 * @DPLL_ID_ICL_DPLL1: ICL combo PHY DPLL1
+	 */
+	DPLL_ID_ICL_DPLL1 = 1,
+	/**
+	 * @DPLL_ID_ICL_MGPLL1: ICL MG PLL 1 port 1 (C)
+	 */
+	DPLL_ID_ICL_MGPLL1 = 2,
+	/**
+	 * @DPLL_ID_ICL_MGPLL2: ICL MG PLL 1 port 2 (D)
+	 */
+	DPLL_ID_ICL_MGPLL2 = 3,
+	/**
+	 * @DPLL_ID_ICL_MGPLL3: ICL MG PLL 1 port 3 (E)
+	 */
+	DPLL_ID_ICL_MGPLL3 = 4,
+	/**
+	 * @DPLL_ID_ICL_MGPLL4: ICL MG PLL 1 port 4 (F)
+	 */
+	DPLL_ID_ICL_MGPLL4 = 5,
 };
 #define I915_NUM_PLLS 6
 
@@ -135,6 +161,21 @@ struct intel_dpll_hw_state {
 	/* bxt */
 	uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
 		 pcsdw12;
+
+	/*
+	 * ICL uses the following, already defined:
+	 * uint32_t cfgcr0, cfgcr1;
+	 */
+	uint32_t mg_refclkin_ctl;
+	uint32_t mg_clktop2_coreclkctl1;
+	uint32_t mg_clktop2_hsclkctl;
+	uint32_t mg_pll_div0;
+	uint32_t mg_pll_div1;
+	uint32_t mg_pll_lf;
+	uint32_t mg_pll_frac_lock;
+	uint32_t mg_pll_ssc;
+	uint32_t mg_pll_bias;
+	uint32_t mg_pll_tdc_coldst_bias;
 };
 
 /**
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9bba0354ccd3..49053150e192 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1405,6 +1405,12 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp);
 u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
 int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
 				     bool enable);
+void icl_map_plls_to_ports(struct drm_crtc *crtc,
+			   struct intel_crtc_state *crtc_state,
+			   struct drm_atomic_state *old_state);
+void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
+			     struct intel_crtc_state *crtc_state,
+			     struct drm_atomic_state *old_state);
 
 unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
 				   int plane, unsigned int height);
-- 
2.14.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for ICL PLLs, DP/HDMI and misc display (rev6)
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
                   ` (10 preceding siblings ...)
  2018-03-29  7:53 ` ✓ Fi.CI.IGT: " Patchwork
@ 2018-04-30  8:42 ` Patchwork
  2018-04-30  8:57 ` ✗ Fi.CI.BAT: failure " Patchwork
  12 siblings, 0 replies; 20+ messages in thread
From: Patchwork @ 2018-04-30  8:42 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

== Series Details ==

Series: ICL PLLs, DP/HDMI and misc display (rev6)
URL   : https://patchwork.freedesktop.org/series/38737/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
c11f69a4c228 drm/i915/icl: add basic support for the ICL clocks
-:587: CHECK:LINE_SPACING: Please don't use multiple blank lines
#587: FILE: drivers/gpu/drm/i915/intel_dpll_mgr.h:107:
+
+

total: 0 errors, 0 warnings, 1 checks, 579 lines checked
64b1ec9a7080 drm/i915/icl: compute the combo PHY (DPLL) HDMI registers
2d87d80fed62 drm/i915/icl: compute the combo PHY (DPLL) DP registers
a5d6e3cf1a9f drm/i915/icl: compute the MG PLL registers
6b07af6901ab drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI
-:122: WARNING:LONG_LINE: line over 100 characters
#122: FILE: drivers/gpu/drm/i915/intel_ddi.c:2256:
+		DRM_DEBUG_KMS("DDI translation not found for level %d. Using %d instead.", level, n_entries - 1);

total: 0 errors, 1 warnings, 0 checks, 221 lines checked
d5fa048c69f2 drm/i915/icl: Fix the DP Max Voltage for ICL

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* ✗ Fi.CI.BAT: failure for ICL PLLs, DP/HDMI and misc display (rev6)
  2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
                   ` (11 preceding siblings ...)
  2018-04-30  8:42 ` ✗ Fi.CI.CHECKPATCH: warning for ICL PLLs, DP/HDMI and misc display (rev6) Patchwork
@ 2018-04-30  8:57 ` Patchwork
  12 siblings, 0 replies; 20+ messages in thread
From: Patchwork @ 2018-04-30  8:57 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

== Series Details ==

Series: ICL PLLs, DP/HDMI and misc display (rev6)
URL   : https://patchwork.freedesktop.org/series/38737/
State : failure

== Summary ==

= CI Bug Log - changes from CI_DRM_4111 -> Patchwork_8833 =

== Summary - FAILURE ==

  Serious unknown changes coming with Patchwork_8833 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_8833, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/38737/revisions/6/mbox/

== Possible new issues ==

  Here are the unknown changes that may have been introduced in Patchwork_8833:

  === IGT changes ===

    ==== Possible regressions ====

    igt@kms_flip@basic-flip-vs-wf_vblank:
      fi-skl-6770hq:      PASS -> FAIL

    
== Known issues ==

  Here are the changes found in Patchwork_8833 that come from known issues:

  === IGT changes ===

    ==== Issues hit ====

    igt@gem_exec_suspend@basic-s4-devices:
      fi-kbl-7500u:       PASS -> DMESG-WARN (fdo#105128)

    igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a:
      fi-cnl-psr:         PASS -> DMESG-WARN (fdo#104951)

    igt@kms_pipe_crc_basic@suspend-read-crc-pipe-c:
      fi-ivb-3520m:       PASS -> DMESG-WARN (fdo#106084)

    
    ==== Possible fixes ====

    igt@kms_pipe_crc_basic@suspend-read-crc-pipe-b:
      fi-ivb-3520m:       DMESG-WARN (fdo#106084) -> PASS

    
  fdo#104951 https://bugs.freedesktop.org/show_bug.cgi?id=104951
  fdo#105128 https://bugs.freedesktop.org/show_bug.cgi?id=105128
  fdo#106084 https://bugs.freedesktop.org/show_bug.cgi?id=106084


== Participating hosts (37 -> 34) ==

  Additional (1): fi-kbl-7560u 
  Missing    (4): fi-byt-j1900 fi-ilk-m540 fi-glk-j4005 fi-skl-6700hq 


== Build changes ==

    * Linux: CI_DRM_4111 -> Patchwork_8833

  CI_DRM_4111: 741ab57af83cdcc5b7faf6780c1e1c6398093f44 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_4452: 29ae12bd764e3b1876356e7628a32192b4ec9066 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_8833: d5fa048c69f23061c665d3b6c32e52d8543c5637 @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4452: 04a2952c5b3782eb03cb136bb16d89daaf243f14 @ git://anongit.freedesktop.org/piglit


== Linux commits ==

d5fa048c69f2 drm/i915/icl: Fix the DP Max Voltage for ICL
6b07af6901ab drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI
a5d6e3cf1a9f drm/i915/icl: compute the MG PLL registers
2d87d80fed62 drm/i915/icl: compute the combo PHY (DPLL) DP registers
64b1ec9a7080 drm/i915/icl: compute the combo PHY (DPLL) HDMI registers
c11f69a4c228 drm/i915/icl: add basic support for the ICL clocks

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8833/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/8] drm/i915/icl: add basic support for the ICL clocks
  2018-04-27 23:14       ` Paulo Zanoni
@ 2018-05-07 18:52         ` James Ausmus
  0 siblings, 0 replies; 20+ messages in thread
From: James Ausmus @ 2018-05-07 18:52 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx

On Fri, Apr 27, 2018 at 04:14:36PM -0700, Paulo Zanoni wrote:
> This commit introduces the definitions for the ICL clocks and adds the
> basic functions to the shared DPLL framework. It adds code for the
> Enable and Disable sequences for some PLLs, but it does not have the
> code to compute the actual PLL values, which are marked as TODO
> comments and should be introduced as separate commits.
> 
> Special thanks to James Ausmus for investigating and fixing a bug with
> the placement of icl_unmap_plls_to_ports() function.
> 
> v2:
>  - Rebase around dpll_lock changes.
> v3:
>  - The spec now says what the timeouts should be.
>  - Touch DPCLKA_CFGCR0_ICL at the appropriate time so we don't freeze
>    the machine.
>  - Checkpatch found a white space problem.
>  - Small adjustments before upstreaming.
> v4:
>  - Move the ICL checks out of the *map_plls_to_ports() functions
>   (James)
>  - Add extra encoder check (James)
>  - Call icl_unmap_plls_to_ports() later (James)
> v5:
>  - Rebase after the pll struct changes.
> v6:
>  - Properly make the unmap function based on encoders_post_disable()
>    with regarding to checks and iterators.
>  - Address checkpatch comment on "min = max = x()".
> 
> Cc: James Ausmus <james.ausmus@intel.com>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Reviewed-by: James Ausmus <james.ausmus@intel.com>


> ---
>  drivers/gpu/drm/i915/i915_debugfs.c   |  22 +++
>  drivers/gpu/drm/i915/intel_ddi.c      |  98 ++++++++++-
>  drivers/gpu/drm/i915/intel_display.c  |  16 ++
>  drivers/gpu/drm/i915/intel_dpll_mgr.c | 313 +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_dpll_mgr.h |  41 +++++
>  drivers/gpu/drm/i915/intel_drv.h      |   6 +
>  6 files changed, 491 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index cb1a804bf72e..ba8927cb1dcc 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -3365,6 +3365,28 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
>  		seq_printf(m, " fp0:     0x%08x\n", pll->state.hw_state.fp0);
>  		seq_printf(m, " fp1:     0x%08x\n", pll->state.hw_state.fp1);
>  		seq_printf(m, " wrpll:   0x%08x\n", pll->state.hw_state.wrpll);
> +		seq_printf(m, " cfgcr0:  0x%08x\n", pll->state.hw_state.cfgcr0);
> +		seq_printf(m, " cfgcr1:  0x%08x\n", pll->state.hw_state.cfgcr1);
> +		seq_printf(m, " mg_refclkin_ctl:        0x%08x\n",
> +			   pll->state.hw_state.mg_refclkin_ctl);
> +		seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n",
> +			   pll->state.hw_state.mg_clktop2_coreclkctl1);
> +		seq_printf(m, " mg_clktop2_hsclkctl:    0x%08x\n",
> +			   pll->state.hw_state.mg_clktop2_hsclkctl);
> +		seq_printf(m, " mg_pll_div0:  0x%08x\n",
> +			   pll->state.hw_state.mg_pll_div0);
> +		seq_printf(m, " mg_pll_div1:  0x%08x\n",
> +			   pll->state.hw_state.mg_pll_div1);
> +		seq_printf(m, " mg_pll_lf:    0x%08x\n",
> +			   pll->state.hw_state.mg_pll_lf);
> +		seq_printf(m, " mg_pll_frac_lock: 0x%08x\n",
> +			   pll->state.hw_state.mg_pll_frac_lock);
> +		seq_printf(m, " mg_pll_ssc:   0x%08x\n",
> +			   pll->state.hw_state.mg_pll_ssc);
> +		seq_printf(m, " mg_pll_bias:  0x%08x\n",
> +			   pll->state.hw_state.mg_pll_bias);
> +		seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n",
> +			   pll->state.hw_state.mg_pll_tdc_coldst_bias);
>  	}
>  	drm_modeset_unlock_all(dev);
>  
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 92cb26b18a9b..178a7b0d0149 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1013,6 +1013,25 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
>  	}
>  }
>  
> +static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
> +				       const struct intel_shared_dpll *pll)
> +{
> +	const enum intel_dpll_id id = pll->info->id;
> +
> +	switch (id) {
> +	default:
> +		MISSING_CASE(id);
> +	case DPLL_ID_ICL_DPLL0:
> +	case DPLL_ID_ICL_DPLL1:
> +		return DDI_CLK_SEL_NONE;
> +	case DPLL_ID_ICL_MGPLL1:
> +	case DPLL_ID_ICL_MGPLL2:
> +	case DPLL_ID_ICL_MGPLL3:
> +	case DPLL_ID_ICL_MGPLL4:
> +		return DDI_CLK_SEL_MG;
> +	}
> +}
> +
>  /* Starting with Haswell, different DDI ports can work in FDI mode for
>   * connection to the PCH-located connectors. For this, it is necessary to train
>   * both the DDI port and PCH receiver for the desired DDI buffer settings.
> @@ -2234,6 +2253,69 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
>  	return DDI_BUF_TRANS_SELECT(level);
>  }
>  
> +void icl_map_plls_to_ports(struct drm_crtc *crtc,
> +			   struct intel_crtc_state *crtc_state,
> +			   struct drm_atomic_state *old_state)
> +{
> +	struct intel_shared_dpll *pll = crtc_state->shared_dpll;
> +	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> +	struct drm_connector_state *conn_state;
> +	struct drm_connector *conn;
> +	int i;
> +
> +	for_each_new_connector_in_state(old_state, conn, conn_state, i) {
> +		struct intel_encoder *encoder =
> +			to_intel_encoder(conn_state->best_encoder);
> +		enum port port = encoder->port;
> +		uint32_t val;
> +
> +		if (conn_state->crtc != crtc)
> +			continue;
> +
> +		mutex_lock(&dev_priv->dpll_lock);
> +
> +		val = I915_READ(DPCLKA_CFGCR0_ICL);
> +		WARN_ON((val & DPCLKA_CFGCR0_DDI_CLK_OFF(port)) == 0);
> +
> +		if (port == PORT_A || port == PORT_B) {
> +			val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
> +			val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
> +			I915_WRITE(DPCLKA_CFGCR0_ICL, val);
> +			POSTING_READ(DPCLKA_CFGCR0_ICL);
> +		}
> +
> +		val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
> +		I915_WRITE(DPCLKA_CFGCR0_ICL, val);
> +
> +		mutex_unlock(&dev_priv->dpll_lock);
> +	}
> +}
> +
> +void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
> +			     struct intel_crtc_state *crtc_state,
> +			     struct drm_atomic_state *old_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> +	struct drm_connector_state *old_conn_state;
> +	struct drm_connector *conn;
> +	int i;
> +
> +	for_each_old_connector_in_state(old_state, conn, old_conn_state, i) {
> +		struct intel_encoder *encoder =
> +			to_intel_encoder(old_conn_state->best_encoder);
> +		enum port port = encoder->port;
> +
> +		if (old_conn_state->crtc != crtc)
> +			continue;
> +
> +		mutex_lock(&dev_priv->dpll_lock);
> +		I915_WRITE(DPCLKA_CFGCR0_ICL,
> +			   I915_READ(DPCLKA_CFGCR0_ICL) |
> +			   DPCLKA_CFGCR0_DDI_CLK_OFF(port));
> +		mutex_unlock(&dev_priv->dpll_lock);
> +	}
> +}
> +
>  static void intel_ddi_clk_select(struct intel_encoder *encoder,
>  				 const struct intel_shared_dpll *pll)
>  {
> @@ -2246,7 +2328,11 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
>  
>  	mutex_lock(&dev_priv->dpll_lock);
>  
> -	if (IS_CANNONLAKE(dev_priv)) {
> +	if (IS_ICELAKE(dev_priv)) {
> +		if (port >= PORT_C)
> +			I915_WRITE(DDI_CLK_SEL(port),
> +				   icl_pll_to_ddi_pll_sel(encoder, pll));
> +	} else if (IS_CANNONLAKE(dev_priv)) {
>  		/* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */
>  		val = I915_READ(DPCLKA_CFGCR0);
>  		val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
> @@ -2284,14 +2370,18 @@ static void intel_ddi_clk_disable(struct intel_encoder *encoder)
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	enum port port = encoder->port;
>  
> -	if (IS_CANNONLAKE(dev_priv))
> +	if (IS_ICELAKE(dev_priv)) {
> +		if (port >= PORT_C)
> +			I915_WRITE(DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
> +	} else if (IS_CANNONLAKE(dev_priv)) {
>  		I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) |
>  			   DPCLKA_CFGCR0_DDI_CLK_OFF(port));
> -	else if (IS_GEN9_BC(dev_priv))
> +	} else if (IS_GEN9_BC(dev_priv)) {
>  		I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) |
>  			   DPLL_CTRL2_DDI_CLK_OFF(port));
> -	else if (INTEL_GEN(dev_priv) < 9)
> +	} else if (INTEL_GEN(dev_priv) < 9) {
>  		I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
> +	}
>  }
>  
>  static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 48576ea2d36c..1d3da5b7d33c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5559,6 +5559,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
>  	if (intel_crtc->config->shared_dpll)
>  		intel_enable_shared_dpll(intel_crtc);
>  
> +	if (INTEL_GEN(dev_priv) >= 11)
> +		icl_map_plls_to_ports(crtc, pipe_config, old_state);
> +
>  	if (intel_crtc_has_dp_encoder(intel_crtc->config))
>  		intel_dp_set_m_n(intel_crtc, M1_N1);
>  
> @@ -5756,6 +5759,9 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
>  		intel_ddi_disable_pipe_clock(intel_crtc->config);
>  
>  	intel_encoders_post_disable(crtc, old_crtc_state, old_state);
> +
> +	if (INTEL_GEN(dev_priv) >= 11)
> +		icl_unmap_plls_to_ports(crtc, old_crtc_state, old_state);
>  }
>  
>  static void i9xx_pfit_enable(struct intel_crtc *crtc)
> @@ -11386,6 +11392,16 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
>  	PIPE_CONF_CHECK_X(dpll_hw_state.pll9);
>  	PIPE_CONF_CHECK_X(dpll_hw_state.pll10);
>  	PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias);
> +	PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias);
>  
>  	PIPE_CONF_CHECK_X(dsi_pll.ctrl);
>  	PIPE_CONF_CHECK_X(dsi_pll.div);
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> index d5e114e9660b..14f5414ceab2 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> @@ -2399,6 +2399,315 @@ static const struct intel_dpll_mgr cnl_pll_mgr = {
>  	.dump_hw_state = cnl_dump_hw_state,
>  };
>  
> +static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
> +				struct intel_encoder *encoder, int clock,
> +				struct intel_dpll_hw_state *pll_state)
> +{
> +	/* TODO */
> +	return true;
> +}
> +
> +static enum port icl_mg_pll_id_to_port(enum intel_dpll_id id)
> +{
> +	return id - DPLL_ID_ICL_MGPLL1 + PORT_C;
> +}
> +
> +static enum intel_dpll_id icl_port_to_mg_pll_id(enum port port)
> +{
> +	return port - PORT_C + DPLL_ID_ICL_MGPLL1;
> +}
> +
> +static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
> +				  struct intel_encoder *encoder, int clock,
> +				  struct intel_dpll_hw_state *pll_state)
> +{
> +	/* TODO */
> +	return true;
> +}
> +
> +static struct intel_shared_dpll *
> +icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
> +	     struct intel_encoder *encoder)
> +{
> +	struct intel_shared_dpll *pll;
> +	struct intel_dpll_hw_state pll_state = {};
> +	enum port port = encoder->port;
> +	enum intel_dpll_id min, max;
> +	int clock = crtc_state->port_clock;
> +	bool ret;
> +
> +	switch (port) {
> +	case PORT_A:
> +	case PORT_B:
> +		min = DPLL_ID_ICL_DPLL0;
> +		max = DPLL_ID_ICL_DPLL1;
> +		ret = icl_calc_dpll_state(crtc_state, encoder, clock,
> +					  &pll_state);
> +		break;
> +	case PORT_C:
> +	case PORT_D:
> +	case PORT_E:
> +	case PORT_F:
> +		min = icl_port_to_mg_pll_id(port);
> +		max = min;
> +		ret = icl_calc_mg_pll_state(crtc_state, encoder, clock,
> +					    &pll_state);
> +		break;
> +	default:
> +		MISSING_CASE(port);
> +		return NULL;
> +	}
> +
> +	if (!ret) {
> +		DRM_DEBUG_KMS("Could not calculate PLL state.\n");
> +		return NULL;
> +	}
> +
> +	crtc_state->dpll_hw_state = pll_state;
> +
> +	pll = intel_find_shared_dpll(crtc, crtc_state, min, max);
> +	if (!pll) {
> +		DRM_DEBUG_KMS("No PLL selected\n");
> +		return NULL;
> +	}
> +
> +	intel_reference_shared_dpll(pll, crtc_state);
> +
> +	return pll;
> +}
> +
> +static i915_reg_t icl_pll_id_to_enable_reg(enum intel_dpll_id id)
> +{
> +	switch (id) {
> +	default:
> +		MISSING_CASE(id);
> +	case DPLL_ID_ICL_DPLL0:
> +	case DPLL_ID_ICL_DPLL1:
> +		return CNL_DPLL_ENABLE(id);
> +	case DPLL_ID_ICL_MGPLL1:
> +	case DPLL_ID_ICL_MGPLL2:
> +	case DPLL_ID_ICL_MGPLL3:
> +	case DPLL_ID_ICL_MGPLL4:
> +		return MG_PLL_ENABLE(icl_mg_pll_id_to_port(id));
> +	}
> +}
> +
> +static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
> +				 struct intel_shared_dpll *pll,
> +				 struct intel_dpll_hw_state *hw_state)
> +{
> +	const enum intel_dpll_id id = pll->info->id;
> +	uint32_t val;
> +	enum port port;
> +	bool ret = false;
> +
> +	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +		return false;
> +
> +	val = I915_READ(icl_pll_id_to_enable_reg(id));
> +	if (!(val & PLL_ENABLE))
> +		goto out;
> +
> +	switch (id) {
> +	case DPLL_ID_ICL_DPLL0:
> +	case DPLL_ID_ICL_DPLL1:
> +		hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(id));
> +		hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(id));
> +		break;
> +	case DPLL_ID_ICL_MGPLL1:
> +	case DPLL_ID_ICL_MGPLL2:
> +	case DPLL_ID_ICL_MGPLL3:
> +	case DPLL_ID_ICL_MGPLL4:
> +		port = icl_mg_pll_id_to_port(id);
> +		hw_state->mg_refclkin_ctl = I915_READ(MG_REFCLKIN_CTL(port));
> +		hw_state->mg_clktop2_coreclkctl1 =
> +			I915_READ(MG_CLKTOP2_CORECLKCTL1(port));
> +		hw_state->mg_clktop2_hsclkctl =
> +			I915_READ(MG_CLKTOP2_HSCLKCTL(port));
> +		hw_state->mg_pll_div0 = I915_READ(MG_PLL_DIV0(port));
> +		hw_state->mg_pll_div1 = I915_READ(MG_PLL_DIV1(port));
> +		hw_state->mg_pll_lf = I915_READ(MG_PLL_LF(port));
> +		hw_state->mg_pll_frac_lock = I915_READ(MG_PLL_FRAC_LOCK(port));
> +		hw_state->mg_pll_ssc = I915_READ(MG_PLL_SSC(port));
> +		hw_state->mg_pll_bias = I915_READ(MG_PLL_BIAS(port));
> +		hw_state->mg_pll_tdc_coldst_bias =
> +			I915_READ(MG_PLL_TDC_COLDST_BIAS(port));
> +		break;
> +	default:
> +		MISSING_CASE(id);
> +	}
> +
> +	ret = true;
> +out:
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +	return ret;
> +}
> +
> +static void icl_dpll_write(struct drm_i915_private *dev_priv,
> +			   struct intel_shared_dpll *pll)
> +{
> +	struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
> +	const enum intel_dpll_id id = pll->info->id;
> +
> +	I915_WRITE(ICL_DPLL_CFGCR0(id), hw_state->cfgcr0);
> +	I915_WRITE(ICL_DPLL_CFGCR1(id), hw_state->cfgcr1);
> +	POSTING_READ(ICL_DPLL_CFGCR1(id));
> +}
> +
> +static void icl_mg_pll_write(struct drm_i915_private *dev_priv,
> +			     struct intel_shared_dpll *pll)
> +{
> +	struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
> +	enum port port = icl_mg_pll_id_to_port(pll->info->id);
> +
> +	I915_WRITE(MG_REFCLKIN_CTL(port), hw_state->mg_refclkin_ctl);
> +	I915_WRITE(MG_CLKTOP2_CORECLKCTL1(port),
> +		   hw_state->mg_clktop2_coreclkctl1);
> +	I915_WRITE(MG_CLKTOP2_HSCLKCTL(port), hw_state->mg_clktop2_hsclkctl);
> +	I915_WRITE(MG_PLL_DIV0(port), hw_state->mg_pll_div0);
> +	I915_WRITE(MG_PLL_DIV1(port), hw_state->mg_pll_div1);
> +	I915_WRITE(MG_PLL_LF(port), hw_state->mg_pll_lf);
> +	I915_WRITE(MG_PLL_FRAC_LOCK(port), hw_state->mg_pll_frac_lock);
> +	I915_WRITE(MG_PLL_SSC(port), hw_state->mg_pll_ssc);
> +	I915_WRITE(MG_PLL_BIAS(port), hw_state->mg_pll_bias);
> +	I915_WRITE(MG_PLL_TDC_COLDST_BIAS(port),
> +		   hw_state->mg_pll_tdc_coldst_bias);
> +	POSTING_READ(MG_PLL_TDC_COLDST_BIAS(port));
> +}
> +
> +static void icl_pll_enable(struct drm_i915_private *dev_priv,
> +			   struct intel_shared_dpll *pll)
> +{
> +	const enum intel_dpll_id id = pll->info->id;
> +	i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
> +	uint32_t val;
> +
> +	val = I915_READ(enable_reg);
> +	val |= PLL_POWER_ENABLE;
> +	I915_WRITE(enable_reg, val);
> +
> +	/*
> +	 * The spec says we need to "wait" but it also says it should be
> +	 * immediate.
> +	 */
> +	if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE,
> +				    PLL_POWER_STATE, 1))
> +		DRM_ERROR("PLL %d Power not enabled\n", id);
> +
> +	switch (id) {
> +	case DPLL_ID_ICL_DPLL0:
> +	case DPLL_ID_ICL_DPLL1:
> +		icl_dpll_write(dev_priv, pll);
> +		break;
> +	case DPLL_ID_ICL_MGPLL1:
> +	case DPLL_ID_ICL_MGPLL2:
> +	case DPLL_ID_ICL_MGPLL3:
> +	case DPLL_ID_ICL_MGPLL4:
> +		icl_mg_pll_write(dev_priv, pll);
> +		break;
> +	default:
> +		MISSING_CASE(id);
> +	}
> +
> +	/*
> +	 * DVFS pre sequence would be here, but in our driver the cdclk code
> +	 * paths should already be setting the appropriate voltage, hence we do
> +	 * nothign here.
> +	 */
> +
> +	val = I915_READ(enable_reg);
> +	val |= PLL_ENABLE;
> +	I915_WRITE(enable_reg, val);
> +
> +	if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, PLL_LOCK,
> +				    1)) /* 600us actually. */
> +		DRM_ERROR("PLL %d not locked\n", id);
> +
> +	/* DVFS post sequence would be here. See the comment above. */
> +}
> +
> +static void icl_pll_disable(struct drm_i915_private *dev_priv,
> +			    struct intel_shared_dpll *pll)
> +{
> +	const enum intel_dpll_id id = pll->info->id;
> +	i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
> +	uint32_t val;
> +
> +	/* The first steps are done by intel_ddi_post_disable(). */
> +
> +	/*
> +	 * DVFS pre sequence would be here, but in our driver the cdclk code
> +	 * paths should already be setting the appropriate voltage, hence we do
> +	 * nothign here.
> +	 */
> +
> +	val = I915_READ(enable_reg);
> +	val &= ~PLL_ENABLE;
> +	I915_WRITE(enable_reg, val);
> +
> +	/* Timeout is actually 1us. */
> +	if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, 0, 1))
> +		DRM_ERROR("PLL %d locked\n", id);
> +
> +	/* DVFS post sequence would be here. See the comment above. */
> +
> +	val = I915_READ(enable_reg);
> +	val &= ~PLL_POWER_ENABLE;
> +	I915_WRITE(enable_reg, val);
> +
> +	/*
> +	 * The spec says we need to "wait" but it also says it should be
> +	 * immediate.
> +	 */
> +	if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE, 0,
> +				    1))
> +		DRM_ERROR("PLL %d Power not disabled\n", id);
> +}
> +
> +static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
> +			      struct intel_dpll_hw_state *hw_state)
> +{
> +	DRM_DEBUG_KMS("dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, "
> +		      "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
> +		      "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, "
> +		      "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, "
> +		      "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, "
> +		      "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n",
> +		      hw_state->cfgcr0, hw_state->cfgcr1,
> +		      hw_state->mg_refclkin_ctl,
> +		      hw_state->mg_clktop2_coreclkctl1,
> +		      hw_state->mg_clktop2_hsclkctl,
> +		      hw_state->mg_pll_div0,
> +		      hw_state->mg_pll_div1,
> +		      hw_state->mg_pll_lf,
> +		      hw_state->mg_pll_frac_lock,
> +		      hw_state->mg_pll_ssc,
> +		      hw_state->mg_pll_bias,
> +		      hw_state->mg_pll_tdc_coldst_bias);
> +}
> +
> +static const struct intel_shared_dpll_funcs icl_pll_funcs = {
> +	.enable = icl_pll_enable,
> +	.disable = icl_pll_disable,
> +	.get_hw_state = icl_pll_get_hw_state,
> +};
> +
> +static const struct dpll_info icl_plls[] = {
> +	{ "DPLL 0",   &icl_pll_funcs, DPLL_ID_ICL_DPLL0,  0 },
> +	{ "DPLL 1",   &icl_pll_funcs, DPLL_ID_ICL_DPLL1,  0 },
> +	{ "MG PLL 1", &icl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 },
> +	{ "MG PLL 2", &icl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 },
> +	{ "MG PLL 3", &icl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 },
> +	{ "MG PLL 4", &icl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 },
> +	{ },
> +};
> +
> +static const struct intel_dpll_mgr icl_pll_mgr = {
> +	.dpll_info = icl_plls,
> +	.get_dpll = icl_get_dpll,
> +	.dump_hw_state = icl_dump_hw_state,
> +};
> +
>  /**
>   * intel_shared_dpll_init - Initialize shared DPLLs
>   * @dev: drm device
> @@ -2412,7 +2721,9 @@ void intel_shared_dpll_init(struct drm_device *dev)
>  	const struct dpll_info *dpll_info;
>  	int i;
>  
> -	if (IS_CANNONLAKE(dev_priv))
> +	if (IS_ICELAKE(dev_priv))
> +		dpll_mgr = &icl_pll_mgr;
> +	else if (IS_CANNONLAKE(dev_priv))
>  		dpll_mgr = &cnl_pll_mgr;
>  	else if (IS_GEN9_BC(dev_priv))
>  		dpll_mgr = &skl_pll_mgr;
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> index 4febfaa90bde..7a0cd564a9ee 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
> +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> @@ -103,6 +103,32 @@ enum intel_dpll_id {
>  	 * @DPLL_ID_SKL_DPLL3: SKL and later DPLL3
>  	 */
>  	DPLL_ID_SKL_DPLL3 = 3,
> +
> +
> +	/**
> +	 * @DPLL_ID_ICL_DPLL0: ICL combo PHY DPLL0
> +	 */
> +	DPLL_ID_ICL_DPLL0 = 0,
> +	/**
> +	 * @DPLL_ID_ICL_DPLL1: ICL combo PHY DPLL1
> +	 */
> +	DPLL_ID_ICL_DPLL1 = 1,
> +	/**
> +	 * @DPLL_ID_ICL_MGPLL1: ICL MG PLL 1 port 1 (C)
> +	 */
> +	DPLL_ID_ICL_MGPLL1 = 2,
> +	/**
> +	 * @DPLL_ID_ICL_MGPLL2: ICL MG PLL 1 port 2 (D)
> +	 */
> +	DPLL_ID_ICL_MGPLL2 = 3,
> +	/**
> +	 * @DPLL_ID_ICL_MGPLL3: ICL MG PLL 1 port 3 (E)
> +	 */
> +	DPLL_ID_ICL_MGPLL3 = 4,
> +	/**
> +	 * @DPLL_ID_ICL_MGPLL4: ICL MG PLL 1 port 4 (F)
> +	 */
> +	DPLL_ID_ICL_MGPLL4 = 5,
>  };
>  #define I915_NUM_PLLS 6
>  
> @@ -135,6 +161,21 @@ struct intel_dpll_hw_state {
>  	/* bxt */
>  	uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
>  		 pcsdw12;
> +
> +	/*
> +	 * ICL uses the following, already defined:
> +	 * uint32_t cfgcr0, cfgcr1;
> +	 */
> +	uint32_t mg_refclkin_ctl;
> +	uint32_t mg_clktop2_coreclkctl1;
> +	uint32_t mg_clktop2_hsclkctl;
> +	uint32_t mg_pll_div0;
> +	uint32_t mg_pll_div1;
> +	uint32_t mg_pll_lf;
> +	uint32_t mg_pll_frac_lock;
> +	uint32_t mg_pll_ssc;
> +	uint32_t mg_pll_bias;
> +	uint32_t mg_pll_tdc_coldst_bias;
>  };
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 9bba0354ccd3..49053150e192 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1405,6 +1405,12 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp);
>  u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
>  int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
>  				     bool enable);
> +void icl_map_plls_to_ports(struct drm_crtc *crtc,
> +			   struct intel_crtc_state *crtc_state,
> +			   struct drm_atomic_state *old_state);
> +void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
> +			     struct intel_crtc_state *crtc_state,
> +			     struct drm_atomic_state *old_state);
>  
>  unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
>  				   int plane, unsigned int height);
> -- 
> 2.14.3
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2018-05-07 18:53 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-28 21:57 [PATCH 0/8] ICL PLLs, DP/HDMI and misc display, v2 Paulo Zanoni
2018-03-28 21:57 ` [PATCH 1/8] drm/i915/icl: Don't set pipe CSC/Gamma in PLANE_COLOR_CTL Paulo Zanoni
2018-03-28 21:57 ` [PATCH 2/8] drm/i915/icl: add definitions for the ICL PLL registers Paulo Zanoni
2018-04-27 22:49   ` James Ausmus
2018-03-28 21:57 ` [PATCH 3/8] drm/i915/icl: add basic support for the ICL clocks Paulo Zanoni
2018-04-09 23:23   ` James Ausmus
2018-04-25  0:22     ` Paulo Zanoni
2018-04-27 23:14       ` Paulo Zanoni
2018-05-07 18:52         ` James Ausmus
2018-03-28 21:57 ` [PATCH 4/8] drm/i915/icl: compute the combo PHY (DPLL) HDMI registers Paulo Zanoni
2018-03-28 21:58 ` [PATCH 5/8] drm/i915/icl: compute the combo PHY (DPLL) DP registers Paulo Zanoni
2018-03-28 21:58 ` [PATCH 6/8] drm/i915/icl: compute the MG PLL registers Paulo Zanoni
2018-03-28 21:58 ` [PATCH 7/8] drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI Paulo Zanoni
2018-03-31  9:53   ` kbuild test robot
2018-03-28 21:58 ` [PATCH 8/8] drm/i915/icl: Fix the DP Max Voltage for ICL Paulo Zanoni
2018-03-28 23:06 ` ✗ Fi.CI.CHECKPATCH: warning for ICL PLLs, DP/HDMI and misc display (rev5) Patchwork
2018-03-28 23:21 ` ✓ Fi.CI.BAT: success " Patchwork
2018-03-29  7:53 ` ✓ Fi.CI.IGT: " Patchwork
2018-04-30  8:42 ` ✗ Fi.CI.CHECKPATCH: warning for ICL PLLs, DP/HDMI and misc display (rev6) Patchwork
2018-04-30  8:57 ` ✗ Fi.CI.BAT: failure " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.