All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ramalingam C <ramalingam.c@intel.com>
To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org,
	seanpaul@chromium.org, chris@chris-wilson.co.uk,
	tomas.winkler@intel.com, jani.nikula@linux.intel.com
Cc: rodrigo.vivi@intel.com
Subject: [PATCH v2 38/42] drm/i915: Implement gmbus burst read
Date: Thu,  8 Mar 2018 17:29:05 +0530	[thread overview]
Message-ID: <1520510349-8385-39-git-send-email-ramalingam.c@intel.com> (raw)
In-Reply-To: <1520510349-8385-1-git-send-email-ramalingam.c@intel.com>

Implements a interface for single burst read of data that is larger
than 512 Bytes through gmbus.

HDCP2.2 spec expects HDCP2.2 transmitter to read 522Bytes of HDCP
receiver certificates in single burst read. On gmbus, to read more
than 511Bytes, HW provides a workaround for burst read.

This patch passes the burst read request through gmbus read functions.
And implements the sequence of enabling and disabling the burst read.

v2:
  No Change.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h  |   2 +
 drivers/gpu/drm/i915/i915_reg.h  |   3 +
 drivers/gpu/drm/i915/intel_i2c.c | 124 +++++++++++++++++++++++++++++++++------
 3 files changed, 112 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0e35e24948a3..6991ba72b18b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3688,6 +3688,8 @@ 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 int intel_gmbus_burst_read(struct i2c_adapter *adapter,
+				  unsigned int offset, void *buf, size_t size);
 
 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 08dafd7e9278..bc5aecd1cbcc 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3114,6 +3114,7 @@ enum i915_power_well_id {
 #define   GMBUS_RATE_400KHZ	(2<<8) /* reserved on Pineview */
 #define   GMBUS_RATE_1MHZ	(3<<8) /* reserved on Pineview */
 #define   GMBUS_HOLD_EXT	(1<<7) /* 300ns hold time, rsvd on Pineview */
+#define   GMBUS_BYTE_CNT_OVERRIDE (1<<6)
 #define   GMBUS_PIN_DISABLED	0
 #define   GMBUS_PIN_SSC		1
 #define   GMBUS_PIN_VGADDC	2
@@ -3141,8 +3142,10 @@ enum i915_power_well_id {
 #define   GMBUS_CYCLE_WAIT	(1<<25)
 #define   GMBUS_CYCLE_INDEX	(2<<25)
 #define   GMBUS_CYCLE_STOP	(4<<25)
+#define   GMBUS_CYCLE_MASK	(7<<25)
 #define   GMBUS_BYTE_COUNT_SHIFT 16
 #define   GMBUS_BYTE_COUNT_MAX   256U
+#define   GMBUS_BYTE_COUNT_HW_MAX 511U
 #define   GMBUS_SLAVE_INDEX_SHIFT 8
 #define   GMBUS_SLAVE_ADDR_SHIFT 1
 #define   GMBUS_SLAVE_READ	(1<<0)
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index e6875509bcd9..dcb2be0d54ee 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -364,21 +364,30 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
 static int
 gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
 		      unsigned short addr, u8 *buf, unsigned int len,
-		      u32 gmbus1_index)
+		      u32 gmbus1_index, bool burst_read)
 {
+	unsigned int size = len;
+	int ret;
+
+	if (burst_read) {
+		/* Seq to enable Burst Read */
+		I915_WRITE_FW(GMBUS0, (I915_READ_FW(GMBUS0) |
+			      GMBUS_BYTE_CNT_OVERRIDE));
+		size = GMBUS_BYTE_COUNT_HW_MAX;
+	}
+
 	I915_WRITE_FW(GMBUS1,
 		      gmbus1_index |
 		      GMBUS_CYCLE_WAIT |
-		      (len << GMBUS_BYTE_COUNT_SHIFT) |
+		      (size << GMBUS_BYTE_COUNT_SHIFT) |
 		      (addr << GMBUS_SLAVE_ADDR_SHIFT) |
 		      GMBUS_SLAVE_READ | GMBUS_SW_RDY);
 	while (len) {
-		int ret;
 		u32 val, loop = 0;
 
 		ret = gmbus_wait(dev_priv, GMBUS_HW_RDY, GMBUS_HW_RDY_EN);
 		if (ret)
-			return ret;
+			goto exit;
 
 		val = I915_READ_FW(GMBUS3);
 		do {
@@ -387,12 +396,29 @@ gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
 		} while (--len && ++loop < 4);
 	}
 
-	return 0;
+exit:
+	if (burst_read) {
+
+		/* Seq to disable the Burst Read */
+		I915_WRITE_FW(GMBUS0, (I915_READ_FW(GMBUS0) &
+			      ~GMBUS_BYTE_CNT_OVERRIDE));
+		I915_WRITE_FW(GMBUS1, (I915_READ_FW(GMBUS1) &
+			      ~GMBUS_CYCLE_MASK) | GMBUS_CYCLE_STOP);
+
+		/*
+		 * On Burst read disable, GMBUS need more time to settle
+		 * down to Idle State.
+		 */
+		ret = intel_wait_for_register_fw(dev_priv, GMBUS2,
+						 GMBUS_ACTIVE, 0, 50);
+	}
+
+	return ret;
 }
 
 static int
 gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
-		u32 gmbus1_index)
+		u32 gmbus1_index, bool burst_read)
 {
 	u8 *buf = msg->buf;
 	unsigned int rx_size = msg->len;
@@ -400,10 +426,13 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
 	int ret;
 
 	do {
-		len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
+		if (burst_read)
+			len = rx_size;
+		else
+			len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
 
-		ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
-					    buf, len, gmbus1_index);
+		ret = gmbus_xfer_read_chunk(dev_priv, msg->addr, buf, len,
+					    gmbus1_index, burst_read);
 		if (ret)
 			return ret;
 
@@ -491,7 +520,8 @@ gmbus_is_index_xfer(struct i2c_msg *msgs, int i, int num)
 }
 
 static int
-gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
+gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs,
+		 bool burst_read)
 {
 	u32 gmbus1_index = 0;
 	u32 gmbus5 = 0;
@@ -509,7 +539,8 @@ gmbus_index_xfer(struct drm_i915_private *dev_priv, struct i2c_msg *msgs)
 		I915_WRITE_FW(GMBUS5, gmbus5);
 
 	if (msgs[1].flags & I2C_M_RD)
-		ret = gmbus_xfer_read(dev_priv, &msgs[1], gmbus1_index);
+		ret = gmbus_xfer_read(dev_priv, &msgs[1],
+				      gmbus1_index, burst_read);
 	else
 		ret = gmbus_xfer_write(dev_priv, &msgs[1], gmbus1_index);
 
@@ -522,7 +553,7 @@ gmbus_index_xfer(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,
-	      u32 gmbus0_source)
+	      u32 gmbus0_source, bool burst_read)
 {
 	struct intel_gmbus *bus = container_of(adapter,
 					       struct intel_gmbus,
@@ -544,15 +575,20 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
 	for (; i < num; i += inc) {
 		inc = 1;
 		if (gmbus_is_index_xfer(msgs, i, num)) {
-			ret = gmbus_index_xfer(dev_priv, &msgs[i]);
+			ret = gmbus_index_xfer(dev_priv, &msgs[i], burst_read);
 			inc = 2; /* an index transmission is two msgs */
 		} else if (msgs[i].flags & I2C_M_RD) {
-			ret = gmbus_xfer_read(dev_priv, &msgs[i], 0);
+			ret = gmbus_xfer_read(dev_priv, &msgs[i],
+					      0, burst_read);
 		} else {
 			ret = gmbus_xfer_write(dev_priv, &msgs[i], 0);
 		}
 
-		if (!ret)
+		/*
+		 * Burst read Sequence ends with STOP. So Dont expect
+		 * HW wait phase.
+		 */
+		if (!ret && !burst_read)
 			ret = gmbus_wait(dev_priv,
 					 GMBUS_HW_WAIT_PHASE, GMBUS_HW_WAIT_EN);
 		if (ret == -ETIMEDOUT)
@@ -664,7 +700,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, 0);
+		ret = do_gmbus_xfer(adapter, msgs, num, 0, false);
 		if (ret == -EAGAIN)
 			bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
 	}
@@ -705,7 +741,8 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
 	 * 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);
+	ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs),
+			    GMBUS_AKSV_SELECT, false);
 
 	mutex_unlock(&dev_priv->gmbus_mutex);
 	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
@@ -713,6 +750,59 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
 	return ret;
 }
 
+static inline
+bool intel_gmbus_burst_read_supported(struct drm_i915_private *dev_priv)
+{
+	if (INTEL_GEN(dev_priv) > 10 || IS_GEMINILAKE(dev_priv) ||
+	    IS_KABYLAKE(dev_priv))
+		return true;
+	return false;
+}
+
+int intel_gmbus_burst_read(struct i2c_adapter *adapter, unsigned int offset,
+			   void *buf, size_t size)
+{
+	struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
+					       adapter);
+	struct drm_i915_private *dev_priv = bus->dev_priv;
+	int ret;
+	u8 start = offset & 0xff;
+	struct i2c_msg msgs[] = {
+		{
+			.addr = DRM_HDCP_DDC_ADDR,
+			.flags = 0,
+			.len = 1,
+			.buf = &start,
+		},
+		{
+			.addr = DRM_HDCP_DDC_ADDR,
+			.flags = I2C_M_RD,
+			.len = size,
+			.buf = buf,
+		}
+	};
+
+	if (!intel_gmbus_burst_read_supported(dev_priv))
+		return -EINVAL;
+
+	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+	mutex_lock(&dev_priv->gmbus_mutex);
+
+	/*
+	 * In order to read the complete length(More than GMBus Limit) of data,
+	 * in burst mode, implement the Workaround supported in HW.
+	 */
+	ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), 0, true);
+
+	mutex_unlock(&dev_priv->gmbus_mutex);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+
+	if (ret == ARRAY_SIZE(msgs))
+		return 0;
+
+	return ret >= 0 ? -EIO : ret;
+}
+
 static u32 gmbus_func(struct i2c_adapter *adapter)
 {
 	return i2c_bit_algo.functionality(adapter) &
-- 
2.7.4

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

  parent reply	other threads:[~2018-03-08 11:59 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-08 11:58 [PATCH v2 00/42] drm/i915: Implement HDCP2.2 Ramalingam C
2018-03-08 11:58 ` [PATCH v2 01/42] drm: hdcp2.2 authentication msg definitions Ramalingam C
2018-03-08 11:58 ` [PATCH v2 02/42] drm: HDMI and DP specific HDCP2.2 defines Ramalingam C
2018-03-08 11:58 ` [PATCH v2 03/42] mei: bus: whitelist hdcp client Ramalingam C
2018-03-08 11:58 ` [PATCH v2 04/42] misc/mei/hdcp: Client driver for HDCP application Ramalingam C
2018-03-08 13:07   ` Winkler, Tomas
2018-03-12 10:58     ` Ramalingam C
2018-03-12 11:22       ` Winkler, Tomas
2018-03-12 11:20         ` Ramalingam C
2018-03-08 11:58 ` [PATCH v2 05/42] misc/mei/hdcp: Add KBuild for mei hdcp driver Ramalingam C
2018-03-08 11:58 ` [PATCH v2 06/42] misc/mei/hdcp: Verify mei client device status Ramalingam C
2018-03-08 13:08   ` Winkler, Tomas
2018-03-12 11:02     ` Ramalingam C
2018-03-08 11:58 ` [PATCH v2 07/42] misc/mei/hdcp: Get & Put for mei cl_device Ramalingam C
2018-03-08 13:10   ` Winkler, Tomas
2018-03-12 11:35     ` Ramalingam C
2018-03-08 11:58 ` [PATCH v2 08/42] misc/mei/hdcp: Define ME FW interface for HDCP2.2 Ramalingam C
2018-03-08 11:58 ` [PATCH v2 09/42] linux/mei: Header for mei_hdcp driver interface Ramalingam C
2018-03-08 13:13   ` Winkler, Tomas
2018-03-12 11:15     ` Ramalingam C
2018-03-08 11:58 ` [PATCH v2 10/42] misc/mei/hdcp: Initiate Wired HDCP2.2 Tx Session Ramalingam C
2018-03-08 13:17   ` Winkler, Tomas
2018-03-12 11:19     ` Ramalingam C
2018-03-12 11:32       ` Winkler, Tomas
2018-03-12 11:38         ` Ramalingam C
2018-03-08 11:58 ` [PATCH v2 11/42] misc/mei/hdcp: Verify Receiver Cert and prepare km Ramalingam C
2018-03-08 11:58 ` [PATCH v2 12/42] misc/mei/hdcp: Verify H_prime Ramalingam C
2018-03-08 11:58 ` [PATCH v2 13/42] misc/mei/hdcp: Store the HDCP Pairing info Ramalingam C
2018-03-08 11:58 ` [PATCH v2 14/42] misc/mei/hdcp: Initiate Locality check Ramalingam C
2018-03-08 11:58 ` [PATCH v2 15/42] misc/mei/hdcp: Verify L_prime Ramalingam C
2018-03-08 11:58 ` [PATCH v2 16/42] misc/mei/hdcp: Prepare Session Key Ramalingam C
2018-03-08 11:58 ` [PATCH v2 17/42] misc/mei/hdcp: Repeater topology verifcation and ack Ramalingam C
2018-03-08 11:58 ` [PATCH v2 18/42] misc/mei/hdcp: Verify M_prime Ramalingam C
2018-03-08 11:58 ` [PATCH v2 19/42] misc/mei/hdcp: Enabling the HDCP authentication Ramalingam C
2018-03-08 11:58 ` [PATCH v2 20/42] misc/mei/hdcp: Closing wired HDCP2.2 Tx Session Ramalingam C
2018-03-08 11:58 ` [PATCH v2 21/42] drm/i915: wrapping all hdcp var into intel_hdcp Ramalingam C
2018-03-08 11:58 ` [PATCH v2 22/42] drm/i915: Define HDCP2.2 related variables Ramalingam C
2018-03-08 11:58 ` [PATCH v2 23/42] drm/i915: Define Intel HDCP2.2 registers Ramalingam C
2018-03-08 11:58 ` [PATCH v2 24/42] drm/i915: Wrappers for mei HDCP2.2 services Ramalingam C
2018-03-08 11:58 ` [PATCH v2 25/42] drm/i915: Implement HDCP2.2 receiver authentication Ramalingam C
2018-03-08 11:58 ` [PATCH v2 26/42] drm/i915: Implement HDCP2.2 repeater authentication Ramalingam C
2018-03-08 11:58 ` [PATCH v2 27/42] drm/i915: Enable and Disable HDCP2.2 port encryption Ramalingam C
2018-03-08 11:58 ` [PATCH v2 28/42] drm/i915: Implement HDCP2.2 En/Dis-able Ramalingam C
2018-03-08 11:58 ` [PATCH v2 29/42] drm/i915: Implement HDCP2.2 link integrity check Ramalingam C
2018-03-08 11:58 ` [PATCH v2 30/42] drm/i915: Handle HDCP2.2 downstream topology change Ramalingam C
2018-03-08 11:58 ` [PATCH v2 31/42] drm/i915: Pullout the bksv read and validation Ramalingam C
2018-03-08 11:58 ` [PATCH v2 32/42] drm/i915: Initialize HDCP2.2 and its MEI interface Ramalingam C
2018-03-08 11:59 ` [PATCH v2 33/42] drm/i915: Schedule hdcp_check_link in _intel_hdcp_enable Ramalingam C
2018-03-08 11:59 ` [PATCH v2 34/42] drm/i915: Enable superior HDCP ver that is capable Ramalingam C
2018-03-08 11:59 ` [PATCH v2 35/42] drm/i915: Enable HDCP1.4 incase of HDCP2.2 failure Ramalingam C
2018-03-08 11:59 ` [PATCH v2 36/42] drm/i915: hdcp_check_link only on CP_IRQ Ramalingam C
2018-03-08 11:59 ` [PATCH v2 37/42] drm/i915: Check HDCP 1.4 and 2.2 link " Ramalingam C
2018-03-08 11:59 ` Ramalingam C [this message]
2018-03-08 11:59 ` [PATCH v2 39/42] drm/i915: Implement the HDCP2.2 support for DP Ramalingam C
2018-03-08 11:59 ` [PATCH v2 40/42] drm/i915: Implement the HDCP2.2 support for HDMI Ramalingam C
2018-03-08 11:59 ` [PATCH v2 41/42] drm/i915: Add HDCP2.2 support for DP connectors Ramalingam C
2018-03-08 11:59 ` [PATCH v2 42/42] drm/i915: Add HDCP2.2 support for HDMI connectors Ramalingam C
2018-03-08 12:30 ` [PATCH v2 00/42] drm/i915: Implement HDCP2.2 Winkler, Tomas
2018-03-08 12:33   ` Ramalingam C
2018-03-09  9:26     ` Daniel Vetter
2018-03-08 12:49 ` ✗ Fi.CI.BAT: failure for drm/i915: Implement HDCP2.2 (rev2) Patchwork
2018-03-12 11:46 ` [PATCH v2 00/42] drm/i915: Implement HDCP2.2 Ramalingam C

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1520510349-8385-39-git-send-email-ramalingam.c@intel.com \
    --to=ramalingam.c@intel.com \
    --cc=chris@chris-wilson.co.uk \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jani.nikula@linux.intel.com \
    --cc=rodrigo.vivi@intel.com \
    --cc=seanpaul@chromium.org \
    --cc=tomas.winkler@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.