浏览代码

drm/i915: Add tracking for CDCLK bypass frequency

The CDCLK bypass frequency can vary on upcoming platforms, so prepare
for that now by tracking its value in the CDCLK state.

Currently on BDW+ the bypass frequency is always the reference clock and
I didn't bother with earlier platforms since it's not all that clear
what's the bypass clock on those.

I also didn't bother adding support for changing this frequency, since
atm I don't see any need for it.

Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180117172508.15993-1-imre.deak@intel.com
Imre Deak 7 年之前
父节点
当前提交
b6c51c3e28
共有 2 个文件被更改,包括 19 次插入18 次删除
  1. 1 1
      drivers/gpu/drm/i915/i915_drv.h
  2. 18 17
      drivers/gpu/drm/i915/intel_cdclk.c

+ 1 - 1
drivers/gpu/drm/i915/i915_drv.h

@@ -1791,7 +1791,7 @@ struct i915_oa_ops {
 };
 };
 
 
 struct intel_cdclk_state {
 struct intel_cdclk_state {
-	unsigned int cdclk, vco, ref;
+	unsigned int cdclk, vco, ref, bypass;
 	u8 voltage_level;
 	u8 voltage_level;
 };
 };
 
 

+ 18 - 17
drivers/gpu/drm/i915/intel_cdclk.c

@@ -858,7 +858,7 @@ static void skl_get_cdclk(struct drm_i915_private *dev_priv,
 
 
 	skl_dpll0_update(dev_priv, cdclk_state);
 	skl_dpll0_update(dev_priv, cdclk_state);
 
 
-	cdclk_state->cdclk = cdclk_state->ref;
+	cdclk_state->cdclk = cdclk_state->bypass = cdclk_state->ref;
 
 
 	if (cdclk_state->vco == 0)
 	if (cdclk_state->vco == 0)
 		goto out;
 		goto out;
@@ -1006,7 +1006,7 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
 	/* Choose frequency for this cdclk */
 	/* Choose frequency for this cdclk */
 	switch (cdclk) {
 	switch (cdclk) {
 	default:
 	default:
-		WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
+		WARN_ON(cdclk != dev_priv->cdclk.hw.bypass);
 		WARN_ON(vco != 0);
 		WARN_ON(vco != 0);
 		/* fall through */
 		/* fall through */
 	case 308571:
 	case 308571:
@@ -1085,7 +1085,7 @@ static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
 
 
 	/* Is PLL enabled and locked ? */
 	/* Is PLL enabled and locked ? */
 	if (dev_priv->cdclk.hw.vco == 0 ||
 	if (dev_priv->cdclk.hw.vco == 0 ||
-	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
+	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.bypass)
 		goto sanitize;
 		goto sanitize;
 
 
 	/* DPLL okay; verify the cdclock
 	/* DPLL okay; verify the cdclock
@@ -1159,7 +1159,7 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
 {
 	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
 	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
 
 
-	cdclk_state.cdclk = cdclk_state.ref;
+	cdclk_state.cdclk = cdclk_state.bypass;
 	cdclk_state.vco = 0;
 	cdclk_state.vco = 0;
 	cdclk_state.voltage_level = skl_calc_voltage_level(cdclk_state.cdclk);
 	cdclk_state.voltage_level = skl_calc_voltage_level(cdclk_state.cdclk);
 
 
@@ -1199,7 +1199,7 @@ static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 {
 {
 	int ratio;
 	int ratio;
 
 
-	if (cdclk == dev_priv->cdclk.hw.ref)
+	if (cdclk == dev_priv->cdclk.hw.bypass)
 		return 0;
 		return 0;
 
 
 	switch (cdclk) {
 	switch (cdclk) {
@@ -1224,7 +1224,7 @@ static int glk_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 {
 {
 	int ratio;
 	int ratio;
 
 
-	if (cdclk == dev_priv->cdclk.hw.ref)
+	if (cdclk == dev_priv->cdclk.hw.bypass)
 		return 0;
 		return 0;
 
 
 	switch (cdclk) {
 	switch (cdclk) {
@@ -1268,7 +1268,7 @@ static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
 
 
 	bxt_de_pll_update(dev_priv, cdclk_state);
 	bxt_de_pll_update(dev_priv, cdclk_state);
 
 
-	cdclk_state->cdclk = cdclk_state->ref;
+	cdclk_state->cdclk = cdclk_state->bypass = cdclk_state->ref;
 
 
 	if (cdclk_state->vco == 0)
 	if (cdclk_state->vco == 0)
 		goto out;
 		goto out;
@@ -1352,7 +1352,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
 	/* cdclk = vco / 2 / div{1,1.5,2,4} */
 	/* cdclk = vco / 2 / div{1,1.5,2,4} */
 	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
 	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
 	default:
 	default:
-		WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
+		WARN_ON(cdclk != dev_priv->cdclk.hw.bypass);
 		WARN_ON(vco != 0);
 		WARN_ON(vco != 0);
 		/* fall through */
 		/* fall through */
 	case 2:
 	case 2:
@@ -1425,7 +1425,7 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
 	intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK");
 	intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK");
 
 
 	if (dev_priv->cdclk.hw.vco == 0 ||
 	if (dev_priv->cdclk.hw.vco == 0 ||
-	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
+	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.bypass)
 		goto sanitize;
 		goto sanitize;
 
 
 	/* DPLL okay; verify the cdclock
 	/* DPLL okay; verify the cdclock
@@ -1514,7 +1514,7 @@ void bxt_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
 {
 	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
 	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
 
 
-	cdclk_state.cdclk = cdclk_state.ref;
+	cdclk_state.cdclk = cdclk_state.bypass;
 	cdclk_state.vco = 0;
 	cdclk_state.vco = 0;
 	cdclk_state.voltage_level = bxt_calc_voltage_level(cdclk_state.cdclk);
 	cdclk_state.voltage_level = bxt_calc_voltage_level(cdclk_state.cdclk);
 
 
@@ -1574,7 +1574,7 @@ static void cnl_get_cdclk(struct drm_i915_private *dev_priv,
 
 
 	cnl_cdclk_pll_update(dev_priv, cdclk_state);
 	cnl_cdclk_pll_update(dev_priv, cdclk_state);
 
 
-	cdclk_state->cdclk = cdclk_state->ref;
+	cdclk_state->cdclk = cdclk_state->bypass = cdclk_state->ref;
 
 
 	if (cdclk_state->vco == 0)
 	if (cdclk_state->vco == 0)
 		goto out;
 		goto out;
@@ -1660,7 +1660,7 @@ static void cnl_set_cdclk(struct drm_i915_private *dev_priv,
 	/* cdclk = vco / 2 / div{1,2} */
 	/* cdclk = vco / 2 / div{1,2} */
 	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
 	switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
 	default:
 	default:
-		WARN_ON(cdclk != dev_priv->cdclk.hw.ref);
+		WARN_ON(cdclk != dev_priv->cdclk.hw.bypass);
 		WARN_ON(vco != 0);
 		WARN_ON(vco != 0);
 		/* fall through */
 		/* fall through */
 	case 2:
 	case 2:
@@ -1705,7 +1705,7 @@ static int cnl_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 {
 {
 	int ratio;
 	int ratio;
 
 
-	if (cdclk == dev_priv->cdclk.hw.ref)
+	if (cdclk == dev_priv->cdclk.hw.bypass)
 		return 0;
 		return 0;
 
 
 	switch (cdclk) {
 	switch (cdclk) {
@@ -1732,7 +1732,7 @@ static void cnl_sanitize_cdclk(struct drm_i915_private *dev_priv)
 	intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK");
 	intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK");
 
 
 	if (dev_priv->cdclk.hw.vco == 0 ||
 	if (dev_priv->cdclk.hw.vco == 0 ||
-	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.ref)
+	    dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.bypass)
 		goto sanitize;
 		goto sanitize;
 
 
 	/* DPLL okay; verify the cdclock
 	/* DPLL okay; verify the cdclock
@@ -1805,7 +1805,7 @@ void cnl_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
 {
 	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
 	struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw;
 
 
-	cdclk_state.cdclk = cdclk_state.ref;
+	cdclk_state.cdclk = cdclk_state.bypass;
 	cdclk_state.vco = 0;
 	cdclk_state.vco = 0;
 	cdclk_state.voltage_level = cnl_calc_voltage_level(cdclk_state.cdclk);
 	cdclk_state.voltage_level = cnl_calc_voltage_level(cdclk_state.cdclk);
 
 
@@ -1846,9 +1846,10 @@ bool intel_cdclk_changed(const struct intel_cdclk_state *a,
 void intel_dump_cdclk_state(const struct intel_cdclk_state *cdclk_state,
 void intel_dump_cdclk_state(const struct intel_cdclk_state *cdclk_state,
 			    const char *context)
 			    const char *context)
 {
 {
-	DRM_DEBUG_DRIVER("%s %d kHz, VCO %d kHz, ref %d kHz, voltage level %d\n",
+	DRM_DEBUG_DRIVER("%s %d kHz, VCO %d kHz, ref %d kHz, bypass %d kHz, voltage level %d\n",
 			 context, cdclk_state->cdclk, cdclk_state->vco,
 			 context, cdclk_state->cdclk, cdclk_state->vco,
-			 cdclk_state->ref, cdclk_state->voltage_level);
+			 cdclk_state->ref, cdclk_state->bypass,
+			 cdclk_state->voltage_level);
 }
 }
 
 
 /**
 /**