[Intel-gfx] [PATCH v3 7/9] drm/i915: Add function to output Aksv over GMBUS

Daniel Vetter daniel at ffwll.ch
Tue Dec 5 17:02:03 UTC 2017


On Tue, Dec 05, 2017 at 12:15:06AM -0500, Sean Paul wrote:
> Once the Aksv is available in the PCH, we need to get it on the wire to
> the receiver via DDC. The hardware doesn't allow us to read the value
> directly, so we need to tell GMBUS to source the Aksv internally and
> send it to the right offset on the receiver.
> 
> The way we do this is to initiate an indexed write where the index is
> the Aksv register offset. We write dummy values to GMBUS3 as if we were
> sending the key, and the hardware slips in the "real" values when it
> goes out.
> 
> Changes in v2:
> - None
> Changes in v3:
> - Uses new index write feature (Ville)
> 
> Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Signed-off-by: Sean Paul <seanpaul at chromium.org>

Reviewed-by: Daniel Vetter <daniel.vetter at ffwll.ch>

> ---
>  drivers/gpu/drm/i915/i915_drv.h  |  1 +
>  drivers/gpu/drm/i915/i915_reg.h  |  1 +
>  drivers/gpu/drm/i915/intel_i2c.c | 47 +++++++++++++++++++++++++++++++++++++---
>  3 files changed, 46 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index bddd65839f60..6b39081c5e53 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -4049,6 +4049,7 @@ extern int intel_setup_gmbus(struct drm_i915_private *dev_priv);
>  extern void intel_teardown_gmbus(struct drm_i915_private *dev_priv);
>  extern bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
>  				     unsigned int pin);
> +extern int intel_gmbus_output_aksv(struct i2c_adapter *adapter);
>  
>  extern struct i2c_adapter *
>  intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin);
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 2bd2cc8441d4..107e16392710 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3043,6 +3043,7 @@ enum i915_power_well_id {
>  # define GPIO_DATA_PULLUP_DISABLE	(1 << 13)
>  
>  #define GMBUS0			_MMIO(dev_priv->gpio_mmio_base + 0x5100) /* clock/port select */
> +#define   GMBUS_AKSV_SELECT	(1<<11)
>  #define   GMBUS_RATE_100KHZ	(0<<8)
>  #define   GMBUS_RATE_50KHZ	(1<<8)
>  #define   GMBUS_RATE_400KHZ	(2<<8) /* reserved on Pineview */
> diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
> index 7399009aee0a..0a4c7486fc7b 100644
> --- a/drivers/gpu/drm/i915/intel_i2c.c
> +++ b/drivers/gpu/drm/i915/intel_i2c.c
> @@ -30,6 +30,7 @@
>  #include <linux/i2c-algo-bit.h>
>  #include <linux/export.h>
>  #include <drm/drmP.h>
> +#include <drm/drm_hdcp.h>
>  #include "intel_drv.h"
>  #include <drm/i915_drm.h>
>  #include "i915_drv.h"
> @@ -497,7 +498,8 @@ gmbus_xfer_index_read(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
>  }
>  
>  static int
> -do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
> +do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
> +	      u32 gmbus0_source)
>  {
>  	struct intel_gmbus *bus = container_of(adapter,
>  					       struct intel_gmbus,
> @@ -507,7 +509,7 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
>  	int ret = 0;
>  
>  retry:
> -	I915_WRITE_FW(GMBUS0, bus->reg0);
> +	I915_WRITE_FW(GMBUS0, gmbus0_source | bus->reg0);
>  
>  	for (; i < num; i += inc) {
>  		inc = 1;
> @@ -629,7 +631,7 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
>  		if (ret < 0)
>  			bus->force_bit &= ~GMBUS_FORCE_BIT_RETRY;
>  	} else {
> -		ret = do_gmbus_xfer(adapter, msgs, num);
> +		ret = do_gmbus_xfer(adapter, msgs, num, 0);
>  		if (ret == -EAGAIN)
>  			bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
>  	}
> @@ -639,6 +641,45 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
>  	return ret;
>  }
>  
> +int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
> +{
> +	struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
> +					       adapter);
> +	struct drm_i915_private *dev_priv = bus->dev_priv;
> +	int ret;
> +	u8 cmd = DRM_HDCP_DDC_AKSV ;
> +	u8 buf[DRM_HDCP_KSV_LEN] = { 0 };
> +	struct i2c_msg msgs[] = {
> +		{
> +			.addr = DRM_HDCP_DDC_ADDR,
> +			.flags = 0,
> +			.len = sizeof(cmd),
> +			.buf = &cmd,
> +		},
> +		{
> +			.addr = DRM_HDCP_DDC_ADDR,
> +			.flags = 0,
> +			.len = sizeof(buf),
> +			.buf = buf,
> +		}
> +	};
> +
> +	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
> +	mutex_lock(&dev_priv->gmbus_mutex);
> +
> +	/*
> +	 * In order to output Aksv to the receiver, use an indexed write to
> +	 * pass the i2c command, and tell GMBUS to use the HW-provided value
> +	 * instead of sourcing GMBUS3 for the data.
> +	 */
> +	ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
> +
> +	mutex_unlock(&dev_priv->gmbus_mutex);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> +
> +	return ret;
> +}
> +
>  static u32 gmbus_func(struct i2c_adapter *adapter)
>  {
>  	return i2c_bit_algo.functionality(adapter) &
> -- 
> 2.15.0.531.g2ccb3012c9-goog
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the dri-devel mailing list