diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_i2c.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_i2c.c | 61 | 
1 files changed, 52 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 49fdf09f9919..ef9f91a0b0c9 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -128,22 +128,46 @@ intel_i2c_reset(struct drm_i915_private *dev_priv)  	I915_WRITE(GMBUS4, 0);  } -static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) +static void pnv_gmbus_clock_gating(struct drm_i915_private *dev_priv, +				   bool enable)  {  	u32 val;  	/* When using bit bashing for I2C, this bit needs to be set to 1 */ -	if (!IS_PINEVIEW(dev_priv)) -		return; -  	val = I915_READ(DSPCLK_GATE_D); -	if (enable) -		val |= DPCUNIT_CLOCK_GATE_DISABLE; +	if (!enable) +		val |= PNV_GMBUSUNIT_CLOCK_GATE_DISABLE;  	else -		val &= ~DPCUNIT_CLOCK_GATE_DISABLE; +		val &= ~PNV_GMBUSUNIT_CLOCK_GATE_DISABLE;  	I915_WRITE(DSPCLK_GATE_D, val);  } +static void pch_gmbus_clock_gating(struct drm_i915_private *dev_priv, +				   bool enable) +{ +	u32 val; + +	val = I915_READ(SOUTH_DSPCLK_GATE_D); +	if (!enable) +		val |= PCH_GMBUSUNIT_CLOCK_GATE_DISABLE; +	else +		val &= ~PCH_GMBUSUNIT_CLOCK_GATE_DISABLE; +	I915_WRITE(SOUTH_DSPCLK_GATE_D, val); +} + +static void bxt_gmbus_clock_gating(struct drm_i915_private *dev_priv, +				   bool enable) +{ +	u32 val; + +	val = I915_READ(GEN9_CLKGATE_DIS_4); +	if (!enable) +		val |= BXT_GMBUS_GATING_DIS; +	else +		val &= ~BXT_GMBUS_GATING_DIS; +	I915_WRITE(GEN9_CLKGATE_DIS_4, val); +} +  static u32 get_reserved(struct intel_gmbus *bus)  {  	struct drm_i915_private *dev_priv = bus->dev_priv; @@ -221,7 +245,10 @@ intel_gpio_pre_xfer(struct i2c_adapter *adapter)  	struct drm_i915_private *dev_priv = bus->dev_priv;  	intel_i2c_reset(dev_priv); -	intel_i2c_quirk_set(dev_priv, true); + +	if (IS_PINEVIEW(dev_priv)) +		pnv_gmbus_clock_gating(dev_priv, false); +  	set_data(bus, 1);  	set_clock(bus, 1);  	udelay(I2C_RISEFALL_TIME); @@ -238,7 +265,9 @@ intel_gpio_post_xfer(struct i2c_adapter *adapter)  	set_data(bus, 1);  	set_clock(bus, 1); -	intel_i2c_quirk_set(dev_priv, false); + +	if (IS_PINEVIEW(dev_priv)) +		pnv_gmbus_clock_gating(dev_priv, true);  }  static void @@ -481,6 +510,13 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)  	int i = 0, inc, try = 0;  	int ret = 0; +	/* Display WA #0868: skl,bxt,kbl,cfl,glk,cnl */ +	if (IS_GEN9_LP(dev_priv)) +		bxt_gmbus_clock_gating(dev_priv, false); +	else if (HAS_PCH_SPT(dev_priv) || +		 HAS_PCH_KBP(dev_priv) || HAS_PCH_CNP(dev_priv)) +		pch_gmbus_clock_gating(dev_priv, false); +  retry:  	I915_WRITE_FW(GMBUS0, bus->reg0); @@ -582,6 +618,13 @@ timeout:  	ret = -EAGAIN;  out: +	/* Display WA #0868: skl,bxt,kbl,cfl,glk,cnl */ +	if (IS_GEN9_LP(dev_priv)) +		bxt_gmbus_clock_gating(dev_priv, true); +	else if (HAS_PCH_SPT(dev_priv) || +		 HAS_PCH_KBP(dev_priv) || HAS_PCH_CNP(dev_priv)) +		pch_gmbus_clock_gating(dev_priv, true); +  	return ret;  }  |