Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 945f2672 authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Rodrigo Vivi
Browse files

drm/i915/cnl: Implement .get_display_clock_speed() for CNL



Add support for reading out the cdclk frequency from the hardware on
CNL. Very similar to BXT, with a few new twists and turns:
* the PLL is now called CDCLK PLL, not DE PLL
* reference clock can be 24 MHz in addition to the 19.2 MHz BXT had
* the ratio now lives in the PLL enable register
* Only 1x and 2x CD2X dividers are supported

v2: Deal with PLL lock bit the same way as BXT/SKL do now
v3: DSSM refclk indicator is bit 31 not 24 (Ander)
v4: Rebased by Rodrigo after Ville's cdclk rework.
v5: Set cdclk to the ref clock as previous platforms. (Imre)

Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: default avatarImre Deak <imre.deak@intel.com>
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1497047175-27250-1-git-send-email-rodrigo.vivi@intel.com
parent 7d025e08
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -6550,6 +6550,9 @@ enum {
#define SKL_DFSM_PIPE_B_DISABLE		(1 << 21)
#define SKL_DFSM_PIPE_C_DISABLE		(1 << 28)

#define SKL_DSSM			_MMIO(0x51004)
#define CNL_DSSM_CDCLK_PLL_REFCLK_24MHz	(1 << 31)

#define GEN7_FF_SLICE_CS_CHICKEN1	_MMIO(0x20e0)
#define   GEN9_FFSC_PERCTX_PREEMPT_CTRL	(1<<14)

@@ -8116,6 +8119,8 @@ enum {
#define BXT_DE_PLL_ENABLE		_MMIO(0x46070)
#define   BXT_DE_PLL_PLL_ENABLE		(1 << 31)
#define   BXT_DE_PLL_LOCK		(1 << 30)
#define   CNL_CDCLK_PLL_RATIO(x)	(x)
#define   CNL_CDCLK_PLL_RATIO_MASK	0xff

/* GEN9 DC */
#define DC_STATE_EN			_MMIO(0x45504)
+55 −1
Original line number Diff line number Diff line
@@ -1400,6 +1400,58 @@ void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
	bxt_set_cdclk(dev_priv, &cdclk_state);
}

static void cnl_cdclk_pll_update(struct drm_i915_private *dev_priv,
				 struct intel_cdclk_state *cdclk_state)
{
	u32 val;

	if (I915_READ(SKL_DSSM) & CNL_DSSM_CDCLK_PLL_REFCLK_24MHz)
		cdclk_state->ref = 24000;
	else
		cdclk_state->ref = 19200;

	cdclk_state->vco = 0;

	val = I915_READ(BXT_DE_PLL_ENABLE);
	if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
		return;

	if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
		return;

	cdclk_state->vco = (val & CNL_CDCLK_PLL_RATIO_MASK) * cdclk_state->ref;
}

static void cnl_get_cdclk(struct drm_i915_private *dev_priv,
			 struct intel_cdclk_state *cdclk_state)
{
	u32 divider;
	int div;

	cnl_cdclk_pll_update(dev_priv, cdclk_state);

	cdclk_state->cdclk = cdclk_state->ref;

	if (cdclk_state->vco == 0)
		return;

	divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;

	switch (divider) {
	case BXT_CDCLK_CD2X_DIV_SEL_1:
		div = 2;
		break;
	case BXT_CDCLK_CD2X_DIV_SEL_2:
		div = 4;
		break;
	default:
		MISSING_CASE(divider);
		return;
	}

	cdclk_state->cdclk = DIV_ROUND_CLOSEST(cdclk_state->vco, div);
}

/**
 * intel_cdclk_state_compare - Determine if two CDCLK states differ
 * @a: first CDCLK state
@@ -1895,7 +1947,9 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
			skl_modeset_calc_cdclk;
	}

	if (IS_GEN9_BC(dev_priv))
	if (IS_CANNONLAKE(dev_priv))
		dev_priv->display.get_cdclk = cnl_get_cdclk;
	else if (IS_GEN9_BC(dev_priv))
		dev_priv->display.get_cdclk = skl_get_cdclk;
	else if (IS_GEN9_LP(dev_priv))
		dev_priv->display.get_cdclk = bxt_get_cdclk;