public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/7] drm/i915/dp: convert to new aux channel helpers
@ 2014-02-04 13:40 Jani Nikula
  2014-02-04 13:40 ` [RFC PATCH 1/7] drm/i915/dp: clean up cargo culted intel_dp_aux_native_read_retry() usage Jani Nikula
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Jani Nikula @ 2014-02-04 13:40 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula, Thierry Reding, dri-devel

These are based on drm-intel-nightly plus Thierry's aux channel
infrastructure patches [1], and supersede my dp aux fixes [2].

Patches 1-4 are prep work and fixes to our current code.

Patches 5 and 7 do the actual conversion for native aux and i2c over
aux, respectively. Patch 6 is minor cleanup in between.

I've very briefly tested this to work; I don't intend to put much more
effort into this until Thierry's series is merged (or updated if
necessary).


BR,
Jani.


[1] http://mid.gmane.org/1390332263-11974-1-git-send-email-treding@nvidia.com
[2] http://mid.gmane.org/cover.1391074436.git.jani.nikula@intel.com

Jani Nikula (7):
  drm/i915/dp: clean up cargo culted intel_dp_aux_native_read_retry()
    usage
  drm/i915/dp: fix dp aux native read return value checks
  drm/i915/dp: split edp_panel_vdd_on() for reuse
  drm/i915/dp: move edp vdd enable/disable at a lower level in
    i2c-over-aux
  drm/i915/dp: use the new drm helpers for dp aux
  drm/i915/dp: move dp aux ch register init to aux init
  drm/i915/dp: use the new drm helpers for dp i2c-over-aux

 drivers/gpu/drm/i915/intel_dp.c  |  482 ++++++++++++++------------------------
 drivers/gpu/drm/i915/intel_drv.h |    3 +-
 2 files changed, 171 insertions(+), 314 deletions(-)

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC PATCH 1/7] drm/i915/dp: clean up cargo culted intel_dp_aux_native_read_retry() usage
  2014-02-04 13:40 [RFC PATCH 0/7] drm/i915/dp: convert to new aux channel helpers Jani Nikula
@ 2014-02-04 13:40 ` Jani Nikula
  2014-02-04 14:20   ` Ville Syrjälä
  2014-02-04 13:40 ` [RFC PATCH 2/7] drm/i915/dp: fix dp aux native read return value checks Jani Nikula
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Jani Nikula @ 2014-02-04 13:40 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula, Thierry Reding, dri-devel

intel_dp_aux_native_read_retry() is only needed when the sink might be
asleep. Use the regular read without retries otherwise.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c |   33 +++++++++++++--------------------
 1 file changed, 13 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f1ef3d482c87..19ff1b161ffb 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2871,9 +2871,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	/* Check if the panel supports PSR */
 	memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
 	if (is_edp(intel_dp)) {
-		intel_dp_aux_native_read_retry(intel_dp, DP_PSR_SUPPORT,
-					       intel_dp->psr_dpcd,
-					       sizeof(intel_dp->psr_dpcd));
+		intel_dp_aux_native_read(intel_dp, DP_PSR_SUPPORT,
+					 intel_dp->psr_dpcd,
+					 sizeof(intel_dp->psr_dpcd));
 		if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) {
 			dev_priv->psr.sink_support = true;
 			DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
@@ -2895,9 +2895,10 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] == 0x10)
 		return true; /* no per-port downstream info */
 
-	if (intel_dp_aux_native_read_retry(intel_dp, DP_DOWNSTREAM_PORT_0,
-					   intel_dp->downstream_ports,
-					   DP_MAX_DOWNSTREAM_PORTS) == 0)
+	if (intel_dp_aux_native_read(intel_dp, DP_DOWNSTREAM_PORT_0,
+				     intel_dp->downstream_ports,
+				     DP_MAX_DOWNSTREAM_PORTS) !=
+	    DP_MAX_DOWNSTREAM_PORTS)
 		return false; /* downstream port status fetch failed */
 
 	return true;
@@ -2913,11 +2914,11 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
 
 	edp_panel_vdd_on(intel_dp);
 
-	if (intel_dp_aux_native_read_retry(intel_dp, DP_SINK_OUI, buf, 3))
+	if (intel_dp_aux_native_read(intel_dp, DP_SINK_OUI, buf, 3) == 3)
 		DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
 			      buf[0], buf[1], buf[2]);
 
-	if (intel_dp_aux_native_read_retry(intel_dp, DP_BRANCH_OUI, buf, 3))
+	if (intel_dp_aux_native_read(intel_dp, DP_BRANCH_OUI, buf, 3) == 3)
 		DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
 			      buf[0], buf[1], buf[2]);
 
@@ -2953,18 +2954,11 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
 	return 0;
 }
 
-static bool
+static inline bool
 intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
 {
-	int ret;
-
-	ret = intel_dp_aux_native_read_retry(intel_dp,
-					     DP_DEVICE_SERVICE_IRQ_VECTOR,
-					     sink_irq_vector, 1);
-	if (!ret)
-		return false;
-
-	return true;
+	return intel_dp_aux_native_read(intel_dp, DP_DEVICE_SERVICE_IRQ_VECTOR,
+					sink_irq_vector, 1) == 1;
 }
 
 static void
@@ -3047,8 +3041,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
 	    intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) {
 		uint8_t reg;
-		if (!intel_dp_aux_native_read_retry(intel_dp, DP_SINK_COUNT,
-						    &reg, 1))
+		if (intel_dp_aux_native_read(intel_dp, DP_SINK_COUNT, &reg, 1) != 1)
 			return connector_status_unknown;
 		return DP_GET_SINK_COUNT(reg) ? connector_status_connected
 					      : connector_status_disconnected;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 2/7] drm/i915/dp: fix dp aux native read return value checks
  2014-02-04 13:40 [RFC PATCH 0/7] drm/i915/dp: convert to new aux channel helpers Jani Nikula
  2014-02-04 13:40 ` [RFC PATCH 1/7] drm/i915/dp: clean up cargo culted intel_dp_aux_native_read_retry() usage Jani Nikula
@ 2014-02-04 13:40 ` Jani Nikula
  2014-02-04 13:40 ` [RFC PATCH 3/7] drm/i915/dp: split edp_panel_vdd_on() for reuse Jani Nikula
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jani Nikula @ 2014-02-04 13:40 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula, Thierry Reding, dri-devel

There's some confusion between ints and bools.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 19ff1b161ffb..ccc1228b7df7 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2857,8 +2857,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 
 	char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3];
 
-	if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
-					   sizeof(intel_dp->dpcd)) == 0)
+	if (!intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
+					    sizeof(intel_dp->dpcd)))
 		return false; /* aux transfer failed */
 
 	hex_dump_to_buffer(intel_dp->dpcd, sizeof(intel_dp->dpcd),
@@ -2933,21 +2933,21 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
 		to_intel_crtc(intel_dig_port->base.base.crtc);
 	u8 buf[1];
 
-	if (!intel_dp_aux_native_read(intel_dp, DP_TEST_SINK_MISC, buf, 1))
+	if (intel_dp_aux_native_read(intel_dp, DP_TEST_SINK_MISC, buf, 1) != 1)
 		return -EAGAIN;
 
 	if (!(buf[0] & DP_TEST_CRC_SUPPORTED))
 		return -ENOTTY;
 
-	if (!intel_dp_aux_native_write_1(intel_dp, DP_TEST_SINK,
-					 DP_TEST_SINK_START))
+	if (intel_dp_aux_native_write_1(intel_dp, DP_TEST_SINK,
+					DP_TEST_SINK_START) != 1)
 		return -EAGAIN;
 
 	/* Wait 2 vblanks to be sure we will have the correct CRC value */
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 
-	if (!intel_dp_aux_native_read(intel_dp, DP_TEST_CRC_R_CR, crc, 6))
+	if (intel_dp_aux_native_read(intel_dp, DP_TEST_CRC_R_CR, crc, 6) != 6)
 		return -EAGAIN;
 
 	intel_dp_aux_native_write_1(intel_dp, DP_TEST_SINK, 0);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 3/7] drm/i915/dp: split edp_panel_vdd_on() for reuse
  2014-02-04 13:40 [RFC PATCH 0/7] drm/i915/dp: convert to new aux channel helpers Jani Nikula
  2014-02-04 13:40 ` [RFC PATCH 1/7] drm/i915/dp: clean up cargo culted intel_dp_aux_native_read_retry() usage Jani Nikula
  2014-02-04 13:40 ` [RFC PATCH 2/7] drm/i915/dp: fix dp aux native read return value checks Jani Nikula
@ 2014-02-04 13:40 ` Jani Nikula
  2014-02-04 13:40 ` [RFC PATCH 4/7] drm/i915/dp: move edp vdd enable/disable at a lower level in i2c-over-aux Jani Nikula
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jani Nikula @ 2014-02-04 13:40 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula, dri-devel

Introduce _edp_panel_vdd_on() that returns true if the call enabled vdd,
and a matching disable is needed. Keep edp_panel_vdd_on() as a helper
for when it is expected the vdd is off.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c |   22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index ccc1228b7df7..5bb69964ad01 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -91,6 +91,7 @@ static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
 }
 
 static void intel_dp_link_down(struct intel_dp *intel_dp);
+static bool _edp_panel_vdd_on(struct intel_dp *intel_dp);
 static void edp_panel_vdd_on(struct intel_dp *intel_dp);
 static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
 
@@ -1135,23 +1136,21 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	return control;
 }
 
-static void edp_panel_vdd_on(struct intel_dp *intel_dp)
+static bool _edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 	u32 pp_stat_reg, pp_ctrl_reg;
+	bool need_to_disable = !intel_dp->want_panel_vdd;
 
 	if (!is_edp(intel_dp))
-		return;
-
-	WARN(intel_dp->want_panel_vdd,
-	     "eDP VDD already requested on\n");
+		return false;
 
 	intel_dp->want_panel_vdd = true;
 
 	if (edp_have_panel_vdd(intel_dp))
-		return;
+		return need_to_disable;
 
 	intel_runtime_pm_get(dev_priv);
 
@@ -1177,6 +1176,17 @@ static void edp_panel_vdd_on(struct intel_dp *intel_dp)
 		DRM_DEBUG_KMS("eDP was not running\n");
 		msleep(intel_dp->panel_power_up_delay);
 	}
+
+	return need_to_disable;
+}
+
+static void edp_panel_vdd_on(struct intel_dp *intel_dp)
+{
+	if (is_edp(intel_dp)) {
+		bool vdd = _edp_panel_vdd_on(intel_dp);
+
+		WARN(!vdd, "eDP VDD already requested on\n");
+	}
 }
 
 static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 4/7] drm/i915/dp: move edp vdd enable/disable at a lower level in i2c-over-aux
  2014-02-04 13:40 [RFC PATCH 0/7] drm/i915/dp: convert to new aux channel helpers Jani Nikula
                   ` (2 preceding siblings ...)
  2014-02-04 13:40 ` [RFC PATCH 3/7] drm/i915/dp: split edp_panel_vdd_on() for reuse Jani Nikula
@ 2014-02-04 13:40 ` Jani Nikula
  2014-02-04 13:40 ` [RFC PATCH 5/7] drm/i915/dp: use the new drm helpers for dp aux Jani Nikula
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jani Nikula @ 2014-02-04 13:40 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula, Thierry Reding, dri-devel

This is prep work for conversion to generic drm i2c-over-aux helpers
where we won't have the function to do this at.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 5bb69964ad01..2eb6715f78df 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -461,6 +461,9 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	uint32_t status;
 	int try, clock = 0;
 	bool has_aux_irq = true;
+	bool vdd;
+
+	vdd = _edp_panel_vdd_on(intel_dp);
 
 	/* dp aux is extremely sensitive to irq latency, hence request the
 	 * lowest possible wakeup latency and so prevent the cpu from going into
@@ -566,6 +569,9 @@ out:
 	pm_qos_update_request(&dev_priv->pm_qos, PM_QOS_DEFAULT_VALUE);
 	intel_aux_display_runtime_put(dev_priv);
 
+	if (vdd)
+		edp_panel_vdd_off(intel_dp, false);
+
 	return ret;
 }
 
@@ -671,8 +677,6 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 	int reply_bytes;
 	int ret;
 
-	edp_panel_vdd_on(intel_dp);
-	intel_dp_check_edp(intel_dp);
 	/* Set up the command byte */
 	if (mode & MODE_I2C_READ)
 		msg[0] = DP_AUX_I2C_READ << 4;
@@ -774,7 +778,6 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
 	ret = -EREMOTEIO;
 
 out:
-	edp_panel_vdd_off(intel_dp, false);
 	return ret;
 }
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 5/7] drm/i915/dp: use the new drm helpers for dp aux
  2014-02-04 13:40 [RFC PATCH 0/7] drm/i915/dp: convert to new aux channel helpers Jani Nikula
                   ` (3 preceding siblings ...)
  2014-02-04 13:40 ` [RFC PATCH 4/7] drm/i915/dp: move edp vdd enable/disable at a lower level in i2c-over-aux Jani Nikula
@ 2014-02-04 13:40 ` Jani Nikula
  2014-02-04 13:40 ` [RFC PATCH 6/7] drm/i915/dp: move dp aux ch register init to aux init Jani Nikula
  2014-02-04 13:40 ` [RFC PATCH 7/7] drm/i915/dp: use the new drm helpers for dp i2c-over-aux Jani Nikula
  6 siblings, 0 replies; 9+ messages in thread
From: Jani Nikula @ 2014-02-04 13:40 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula, Thierry Reding, dri-devel

The main differences are:

* Native aux has retry limit of 7 instead of infinite retry.

* Sleep in native reply defer increases from udelay(100) to
  usleep_range(400, 500).

* Unknown native reply results in retry instead of -EIO.

* Lower level -EBUSY results in retry instead of fail.

* Write return of 0 results in -EPROTO instead of (questionable)
  success.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c  |  249 ++++++++++++++++++--------------------
 drivers/gpu/drm/i915/intel_drv.h |    1 +
 2 files changed, 120 insertions(+), 130 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 2eb6715f78df..835f16da80af 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -575,90 +575,68 @@ out:
 	return ret;
 }
 
-/* Write data to the aux channel in native mode */
-static int
-intel_dp_aux_native_write(struct intel_dp *intel_dp,
-			  uint16_t address, uint8_t *send, int send_bytes)
+#define HEADER_SIZE	4
+static ssize_t
+intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
 {
+	struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux);
+	uint8_t txbuf[20], rxbuf[20];
+	size_t txsize, rxsize;
 	int ret;
-	uint8_t	msg[20];
-	int msg_bytes;
-	uint8_t	ack;
 
-	if (WARN_ON(send_bytes > 16))
-		return -E2BIG;
+	txbuf[0] = msg->request << 4;
+	txbuf[1] = msg->address >> 8;
+	txbuf[2] = msg->address & 0xff;
+	txbuf[3] = msg->size - 1;
 
-	intel_dp_check_edp(intel_dp);
-	msg[0] = DP_AUX_NATIVE_WRITE << 4;
-	msg[1] = address >> 8;
-	msg[2] = address & 0xff;
-	msg[3] = send_bytes - 1;
-	memcpy(&msg[4], send, send_bytes);
-	msg_bytes = send_bytes + 4;
-	for (;;) {
-		ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
-		if (ret < 0)
-			return ret;
-		ack >>= 4;
-		if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
-			break;
-		else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-			udelay(100);
-		else
-			return -EIO;
-	}
-	return send_bytes;
-}
+	switch (msg->request & ~DP_AUX_I2C_MOT) {
+	case DP_AUX_NATIVE_WRITE:
+	case DP_AUX_I2C_WRITE:
+		txsize = HEADER_SIZE + msg->size;
+		rxsize = 1;
 
-/* Write a single byte to the aux channel in native mode */
-static int
-intel_dp_aux_native_write_1(struct intel_dp *intel_dp,
-			    uint16_t address, uint8_t byte)
-{
-	return intel_dp_aux_native_write(intel_dp, address, &byte, 1);
-}
+		if (WARN_ON(txsize > 20))
+			return -E2BIG;
 
-/* read bytes from a native aux channel */
-static int
-intel_dp_aux_native_read(struct intel_dp *intel_dp,
-			 uint16_t address, uint8_t *recv, int recv_bytes)
-{
-	uint8_t msg[4];
-	int msg_bytes;
-	uint8_t reply[20];
-	int reply_bytes;
-	uint8_t ack;
-	int ret;
+		memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size);
 
-	if (WARN_ON(recv_bytes > 19))
-		return -E2BIG;
+		ret = intel_dp_aux_ch(intel_dp, txbuf, txsize, rxbuf, rxsize);
+		if (ret > 0) {
+			msg->reply = rxbuf[0] >> 4;
 
-	intel_dp_check_edp(intel_dp);
-	msg[0] = DP_AUX_NATIVE_READ << 4;
-	msg[1] = address >> 8;
-	msg[2] = address & 0xff;
-	msg[3] = recv_bytes - 1;
+			/* Return payload size. */
+			ret = msg->size;
+		}
+		break;
 
-	msg_bytes = 4;
-	reply_bytes = recv_bytes + 1;
+	case DP_AUX_NATIVE_READ:
+	case DP_AUX_I2C_READ:
+		txsize = HEADER_SIZE;
+		rxsize = msg->size + 1;
 
-	for (;;) {
-		ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes,
-				      reply, reply_bytes);
-		if (ret == 0)
-			return -EPROTO;
-		if (ret < 0)
-			return ret;
-		ack = reply[0] >> 4;
-		if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) {
-			memcpy(recv, reply + 1, ret - 1);
-			return ret - 1;
+		if (WARN_ON(rxsize > 20))
+			return -E2BIG;
+
+		ret = intel_dp_aux_ch(intel_dp, txbuf, txsize, rxbuf, rxsize);
+		if (ret > 0) {
+			msg->reply = rxbuf[0] >> 4;
+			/*
+			 * Assume happy day, and copy the data. The caller is
+			 * expected to check msg->reply before touching it.
+			 *
+			 * Return payload size.
+			 */
+			ret--;
+			memcpy(msg->buffer, rxbuf + 1, ret);
 		}
-		else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-			udelay(100);
-		else
-			return -EIO;
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
 	}
+
+	return ret;
 }
 
 static int
@@ -805,6 +783,13 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
 }
 
 static void
+intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
+{
+	intel_dp->aux.dev = connector->base.kdev;
+	intel_dp->aux.transfer = intel_dp_aux_transfer;
+}
+
+static void
 intel_dp_set_clock(struct intel_encoder *encoder,
 		   struct intel_crtc_config *pipe_config, int link_bw)
 {
@@ -1444,8 +1429,8 @@ void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
 		return;
 
 	if (mode != DRM_MODE_DPMS_ON) {
-		ret = intel_dp_aux_native_write_1(intel_dp, DP_SET_POWER,
-						  DP_SET_POWER_D3);
+		ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER,
+					 DP_SET_POWER_D3);
 		if (ret != 1)
 			DRM_DEBUG_DRIVER("failed to write sink power state\n");
 	} else {
@@ -1454,9 +1439,8 @@ void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
 		 * time to wake up.
 		 */
 		for (i = 0; i < 3; i++) {
-			ret = intel_dp_aux_native_write_1(intel_dp,
-							  DP_SET_POWER,
-							  DP_SET_POWER_D0);
+			ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER,
+						 DP_SET_POWER_D0);
 			if (ret == 1)
 				break;
 			msleep(1);
@@ -1673,13 +1657,11 @@ static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
 
 	/* Enable PSR in sink */
 	if (intel_dp->psr_dpcd[1] & DP_PSR_NO_TRAIN_ON_EXIT)
-		intel_dp_aux_native_write_1(intel_dp, DP_PSR_EN_CFG,
-					    DP_PSR_ENABLE &
-					    ~DP_PSR_MAIN_LINK_ACTIVE);
+		drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
+				   DP_PSR_ENABLE & ~DP_PSR_MAIN_LINK_ACTIVE);
 	else
-		intel_dp_aux_native_write_1(intel_dp, DP_PSR_EN_CFG,
-					    DP_PSR_ENABLE |
-					    DP_PSR_MAIN_LINK_ACTIVE);
+		drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG,
+				   DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE);
 
 	/* Setup AUX registers */
 	I915_WRITE(EDP_PSR_AUX_DATA1(dev), EDP_PSR_DPCD_COMMAND);
@@ -1989,26 +1971,25 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
 /*
  * Native read with retry for link status and receiver capability reads for
  * cases where the sink may still be asleep.
+ *
+ * Sinks are *supposed* to come up within 1ms from an off state, but we're also
+ * supposed to retry 3 times per the spec.
  */
-static bool
-intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address,
-			       uint8_t *recv, int recv_bytes)
+static ssize_t
+intel_dp_dpcd_read_wake(struct drm_dp_aux *aux, unsigned int offset,
+			void *buffer, size_t size)
 {
-	int ret, i;
+	ssize_t ret;
+	int i;
 
-	/*
-	 * Sinks are *supposed* to come up within 1ms from an off state,
-	 * but we're also supposed to retry 3 times per the spec.
-	 */
 	for (i = 0; i < 3; i++) {
-		ret = intel_dp_aux_native_read(intel_dp, address, recv,
-					       recv_bytes);
-		if (ret == recv_bytes)
-			return true;
+		ret = drm_dp_dpcd_read(aux, offset, buffer, size);
+		if (ret == size)
+			return ret;
 		msleep(1);
 	}
 
-	return false;
+	return ret;
 }
 
 /*
@@ -2018,10 +1999,10 @@ intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address,
 static bool
 intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
-	return intel_dp_aux_native_read_retry(intel_dp,
-					      DP_LANE0_1_STATUS,
-					      link_status,
-					      DP_LINK_STATUS_SIZE);
+	return intel_dp_dpcd_read_wake(&intel_dp->aux,
+				       DP_LANE0_1_STATUS,
+				       link_status,
+				       DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;
 }
 
 /*
@@ -2535,8 +2516,8 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 		len = intel_dp->lane_count + 1;
 	}
 
-	ret = intel_dp_aux_native_write(intel_dp, DP_TRAINING_PATTERN_SET,
-					buf, len);
+	ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET,
+				buf, len);
 
 	return ret == len;
 }
@@ -2565,9 +2546,8 @@ intel_dp_update_link_train(struct intel_dp *intel_dp, uint32_t *DP,
 	I915_WRITE(intel_dp->output_reg, *DP);
 	POSTING_READ(intel_dp->output_reg);
 
-	ret = intel_dp_aux_native_write(intel_dp, DP_TRAINING_LANE0_SET,
-					intel_dp->train_set,
-					intel_dp->lane_count);
+	ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
+				intel_dp->train_set, intel_dp->lane_count);
 
 	return ret == intel_dp->lane_count;
 }
@@ -2623,11 +2603,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 	link_config[1] = intel_dp->lane_count;
 	if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
 		link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
-	intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, link_config, 2);
+	drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
 
 	link_config[0] = 0;
 	link_config[1] = DP_SET_ANSI_8B10B;
-	intel_dp_aux_native_write(intel_dp, DP_DOWNSPREAD_CTRL, link_config, 2);
+	drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2);
 
 	DP |= DP_PORT_EN;
 
@@ -2867,11 +2847,12 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
 
 	char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3];
 
-	if (!intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,
-					    sizeof(intel_dp->dpcd)))
+	if (intel_dp_dpcd_read_wake(&intel_dp->aux, 0x000, intel_dp->dpcd,
+				    sizeof(intel_dp->dpcd)) < 0)
 		return false; /* aux transfer failed */
 
 	hex_dump_to_buffer(intel_dp->dpcd, sizeof(intel_dp->dpcd),
@@ -2884,9 +2865,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	/* Check if the panel supports PSR */
 	memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
 	if (is_edp(intel_dp)) {
-		intel_dp_aux_native_read(intel_dp, DP_PSR_SUPPORT,
-					 intel_dp->psr_dpcd,
-					 sizeof(intel_dp->psr_dpcd));
+		drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT,
+				 intel_dp->psr_dpcd,
+				 sizeof(intel_dp->psr_dpcd));
 		if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) {
 			dev_priv->psr.sink_support = true;
 			DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
@@ -2908,10 +2889,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] == 0x10)
 		return true; /* no per-port downstream info */
 
-	if (intel_dp_aux_native_read(intel_dp, DP_DOWNSTREAM_PORT_0,
-				     intel_dp->downstream_ports,
-				     DP_MAX_DOWNSTREAM_PORTS) !=
-	    DP_MAX_DOWNSTREAM_PORTS)
+	ret = drm_dp_dpcd_read(&intel_dp->aux, DP_DOWNSTREAM_PORT_0,
+			       intel_dp->downstream_ports, DP_MAX_DOWNSTREAM_PORTS);
+	if (ret != DP_MAX_DOWNSTREAM_PORTS)
 		return false; /* downstream port status fetch failed */
 
 	return true;
@@ -2927,11 +2907,11 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
 
 	edp_panel_vdd_on(intel_dp);
 
-	if (intel_dp_aux_native_read(intel_dp, DP_SINK_OUI, buf, 3) == 3)
+	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_OUI, buf, 3) == 3)
 		DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
 			      buf[0], buf[1], buf[2]);
 
-	if (intel_dp_aux_native_read(intel_dp, DP_BRANCH_OUI, buf, 3) == 3)
+	if (drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_OUI, buf, 3) == 3)
 		DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
 			      buf[0], buf[1], buf[2]);
 
@@ -2945,40 +2925,43 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
 	struct intel_crtc *intel_crtc =
 		to_intel_crtc(intel_dig_port->base.base.crtc);
 	u8 buf[1];
+	int ret;
 
-	if (intel_dp_aux_native_read(intel_dp, DP_TEST_SINK_MISC, buf, 1) != 1)
+	ret = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_SINK_MISC, buf);
+	if (ret != 1)
 		return -EAGAIN;
 
 	if (!(buf[0] & DP_TEST_CRC_SUPPORTED))
 		return -ENOTTY;
 
-	if (intel_dp_aux_native_write_1(intel_dp, DP_TEST_SINK,
-					DP_TEST_SINK_START) != 1)
+	ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, DP_TEST_SINK_START);
+	if (ret != 1)
 		return -EAGAIN;
 
 	/* Wait 2 vblanks to be sure we will have the correct CRC value */
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 
-	if (intel_dp_aux_native_read(intel_dp, DP_TEST_CRC_R_CR, crc, 6) != 6)
+	ret = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_CRC_R_CR, crc, 6);
+	if (ret != 6)
 		return -EAGAIN;
 
-	intel_dp_aux_native_write_1(intel_dp, DP_TEST_SINK, 0);
+	drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_SINK, 0);
 	return 0;
 }
 
 static inline bool
 intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
 {
-	return intel_dp_aux_native_read(intel_dp, DP_DEVICE_SERVICE_IRQ_VECTOR,
-					sink_irq_vector, 1) == 1;
+	return drm_dp_dpcd_readb(&intel_dp->aux, DP_DEVICE_SERVICE_IRQ_VECTOR,
+				 sink_irq_vector) == 1;
 }
 
 static void
 intel_dp_handle_test_request(struct intel_dp *intel_dp)
 {
 	/* NAK by default */
-	intel_dp_aux_native_write_1(intel_dp, DP_TEST_RESPONSE, DP_TEST_NAK);
+	drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, DP_TEST_NAK);
 }
 
 /*
@@ -3017,9 +3000,9 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
 	    intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) {
 		/* Clear interrupt source */
-		intel_dp_aux_native_write_1(intel_dp,
-					    DP_DEVICE_SERVICE_IRQ_VECTOR,
-					    sink_irq_vector);
+		drm_dp_dpcd_writeb(&intel_dp->aux,
+				   DP_DEVICE_SERVICE_IRQ_VECTOR,
+				   sink_irq_vector);
 
 		if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST)
 			intel_dp_handle_test_request(intel_dp);
@@ -3042,6 +3025,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 {
 	uint8_t *dpcd = intel_dp->dpcd;
 	uint8_t type;
+	int ret;
 
 	if (!intel_dp_get_dpcd(intel_dp))
 		return connector_status_disconnected;
@@ -3054,8 +3038,11 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
 	    intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) {
 		uint8_t reg;
-		if (intel_dp_aux_native_read(intel_dp, DP_SINK_COUNT, &reg, 1) != 1)
+
+		ret = drm_dp_dpcd_readb(&intel_dp->aux, DP_SINK_COUNT, &reg);
+		if (ret != 1)
 			return connector_status_unknown;
+
 		return DP_GET_SINK_COUNT(reg) ? connector_status_connected
 					      : connector_status_disconnected;
 	}
@@ -3855,6 +3842,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 	}
 
+	intel_dp_aux_init(intel_dp, intel_connector);
+
 	error = intel_dp_i2c_init(intel_dp, intel_connector, name);
 	WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
 	     error, port_name(port));
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 44067bce5e04..75a1329297d9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -479,6 +479,7 @@ struct intel_dp {
 	uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
 	struct i2c_adapter adapter;
 	struct i2c_algo_dp_aux_data algo;
+	struct drm_dp_aux aux;
 	uint8_t train_set[4];
 	int panel_power_up_delay;
 	int panel_power_down_delay;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 6/7] drm/i915/dp: move dp aux ch register init to aux init
  2014-02-04 13:40 [RFC PATCH 0/7] drm/i915/dp: convert to new aux channel helpers Jani Nikula
                   ` (4 preceding siblings ...)
  2014-02-04 13:40 ` [RFC PATCH 5/7] drm/i915/dp: use the new drm helpers for dp aux Jani Nikula
@ 2014-02-04 13:40 ` Jani Nikula
  2014-02-04 13:40 ` [RFC PATCH 7/7] drm/i915/dp: use the new drm helpers for dp i2c-over-aux Jani Nikula
  6 siblings, 0 replies; 9+ messages in thread
From: Jani Nikula @ 2014-02-04 13:40 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula, Thierry Reding, dri-devel

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c |   45 ++++++++++++++++++++++-----------------
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 835f16da80af..0a8a2b189ed0 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -785,6 +785,31 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
 static void
 intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
 {
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	enum port port = intel_dig_port->port;
+
+	if (HAS_DDI(dev)) {
+		switch (port) {
+		case PORT_A:
+			intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL;
+			break;
+		case PORT_B:
+			intel_dp->aux_ch_ctl_reg = PCH_DPB_AUX_CH_CTL;
+			break;
+		case PORT_C:
+			intel_dp->aux_ch_ctl_reg = PCH_DPC_AUX_CH_CTL;
+			break;
+		case PORT_D:
+			intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL;
+			break;
+		default:
+			BUG();
+		}
+	} else {
+		intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
+	}
+
 	intel_dp->aux.dev = connector->base.kdev;
 	intel_dp->aux.transfer = intel_dp_aux_transfer;
 }
@@ -3795,26 +3820,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
 
-	intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
-	if (HAS_DDI(dev)) {
-		switch (intel_dig_port->port) {
-		case PORT_A:
-			intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL;
-			break;
-		case PORT_B:
-			intel_dp->aux_ch_ctl_reg = PCH_DPB_AUX_CH_CTL;
-			break;
-		case PORT_C:
-			intel_dp->aux_ch_ctl_reg = PCH_DPC_AUX_CH_CTL;
-			break;
-		case PORT_D:
-			intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL;
-			break;
-		default:
-			BUG();
-		}
-	}
-
 	/* Set up the DDC bus. */
 	switch (port) {
 	case PORT_A:
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 7/7] drm/i915/dp: use the new drm helpers for dp i2c-over-aux
  2014-02-04 13:40 [RFC PATCH 0/7] drm/i915/dp: convert to new aux channel helpers Jani Nikula
                   ` (5 preceding siblings ...)
  2014-02-04 13:40 ` [RFC PATCH 6/7] drm/i915/dp: move dp aux ch register init to aux init Jani Nikula
@ 2014-02-04 13:40 ` Jani Nikula
  6 siblings, 0 replies; 9+ messages in thread
From: Jani Nikula @ 2014-02-04 13:40 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula, dri-devel

The main differences are:

* Many of the native aux differences mentioned in the relevant commit
  apply.

* Native aux and i2c-over-aux defer timeouts are increased to be safe
  for all use cases instead of depending on DP device type and
  properties.

* i2c start/stop/reset are not done.

* i2c device name changes from port based to connector kernel device
  name based, for example DPDDC-A -> card0-DP-1.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c  |  180 ++++----------------------------------
 drivers/gpu/drm/i915/intel_drv.h |    2 -
 2 files changed, 19 insertions(+), 163 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0a8a2b189ed0..9edfa3ec2dee 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -639,155 +639,13 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
 	return ret;
 }
 
-static int
-intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
-		    uint8_t write_byte, uint8_t *read_byte)
-{
-	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
-	struct intel_dp *intel_dp = container_of(adapter,
-						struct intel_dp,
-						adapter);
-	uint16_t address = algo_data->address;
-	uint8_t msg[5];
-	uint8_t reply[2];
-	unsigned retry;
-	int msg_bytes;
-	int reply_bytes;
-	int ret;
-
-	/* Set up the command byte */
-	if (mode & MODE_I2C_READ)
-		msg[0] = DP_AUX_I2C_READ << 4;
-	else
-		msg[0] = DP_AUX_I2C_WRITE << 4;
-
-	if (!(mode & MODE_I2C_STOP))
-		msg[0] |= DP_AUX_I2C_MOT << 4;
-
-	msg[1] = address >> 8;
-	msg[2] = address;
-
-	switch (mode) {
-	case MODE_I2C_WRITE:
-		msg[3] = 0;
-		msg[4] = write_byte;
-		msg_bytes = 5;
-		reply_bytes = 1;
-		break;
-	case MODE_I2C_READ:
-		msg[3] = 0;
-		msg_bytes = 4;
-		reply_bytes = 2;
-		break;
-	default:
-		msg_bytes = 3;
-		reply_bytes = 1;
-		break;
-	}
-
-	/*
-	 * DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device is
-	 * required to retry at least seven times upon receiving AUX_DEFER
-	 * before giving up the AUX transaction.
-	 */
-	for (retry = 0; retry < 7; retry++) {
-		ret = intel_dp_aux_ch(intel_dp,
-				      msg, msg_bytes,
-				      reply, reply_bytes);
-		if (ret < 0) {
-			DRM_DEBUG_KMS("aux_ch failed %d\n", ret);
-			goto out;
-		}
-
-		switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) {
-		case DP_AUX_NATIVE_REPLY_ACK:
-			/* I2C-over-AUX Reply field is only valid
-			 * when paired with AUX ACK.
-			 */
-			break;
-		case DP_AUX_NATIVE_REPLY_NACK:
-			DRM_DEBUG_KMS("aux_ch native nack\n");
-			ret = -EREMOTEIO;
-			goto out;
-		case DP_AUX_NATIVE_REPLY_DEFER:
-			/*
-			 * For now, just give more slack to branch devices. We
-			 * could check the DPCD for I2C bit rate capabilities,
-			 * and if available, adjust the interval. We could also
-			 * be more careful with DP-to-Legacy adapters where a
-			 * long legacy cable may force very low I2C bit rates.
-			 */
-			if (intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
-			    DP_DWN_STRM_PORT_PRESENT)
-				usleep_range(500, 600);
-			else
-				usleep_range(300, 400);
-			continue;
-		default:
-			DRM_ERROR("aux_ch invalid native reply 0x%02x\n",
-				  reply[0]);
-			ret = -EREMOTEIO;
-			goto out;
-		}
-
-		switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) {
-		case DP_AUX_I2C_REPLY_ACK:
-			if (mode == MODE_I2C_READ) {
-				*read_byte = reply[1];
-			}
-			ret = reply_bytes - 1;
-			goto out;
-		case DP_AUX_I2C_REPLY_NACK:
-			DRM_DEBUG_KMS("aux_i2c nack\n");
-			ret = -EREMOTEIO;
-			goto out;
-		case DP_AUX_I2C_REPLY_DEFER:
-			DRM_DEBUG_KMS("aux_i2c defer\n");
-			udelay(100);
-			break;
-		default:
-			DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]);
-			ret = -EREMOTEIO;
-			goto out;
-		}
-	}
-
-	DRM_ERROR("too many retries, giving up\n");
-	ret = -EREMOTEIO;
-
-out:
-	return ret;
-}
-
-static int
-intel_dp_i2c_init(struct intel_dp *intel_dp,
-		  struct intel_connector *intel_connector, const char *name)
-{
-	int	ret;
-
-	DRM_DEBUG_KMS("i2c_init %s\n", name);
-	intel_dp->algo.running = false;
-	intel_dp->algo.address = 0;
-	intel_dp->algo.aux_ch = intel_dp_i2c_aux_ch;
-
-	memset(&intel_dp->adapter, '\0', sizeof(intel_dp->adapter));
-	intel_dp->adapter.owner = THIS_MODULE;
-	intel_dp->adapter.class = I2C_CLASS_DDC;
-	strncpy(intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
-	intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
-	intel_dp->adapter.algo_data = &intel_dp->algo;
-	intel_dp->adapter.dev.parent = intel_connector->base.kdev;
-
-	ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
-	return ret;
-}
-
 static void
 intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	enum port port = intel_dig_port->port;
+	int ret;
 
 	if (HAS_DDI(dev)) {
 		switch (port) {
@@ -812,6 +670,15 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
 
 	intel_dp->aux.dev = connector->base.kdev;
 	intel_dp->aux.transfer = intel_dp_aux_transfer;
+
+	/* drm_dp_aux_register_i2c_bus() uses dev_name(), log the connection */
+	DRM_DEBUG_KMS("registering DPDDC-%c bus for %s\n",
+		      port_name(port), dev_name(intel_dp->aux.dev));
+
+	ret = drm_dp_aux_register_i2c_bus(&intel_dp->aux);
+
+	WARN(ret, "drm_dp_aux_register_i2c_bus() failed with error %d for port %c\n",
+	     ret, port_name(port));
 }
 
 static void
@@ -3073,7 +2940,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
 	}
 
 	/* If no HPD, poke DDC gently */
-	if (drm_probe_ddc(&intel_dp->adapter))
+	if (drm_probe_ddc(&intel_dp->aux.ddc))
 		return connector_status_connected;
 
 	/* Well we tried, say unknown for unreliable port types */
@@ -3237,7 +3104,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 	if (intel_dp->force_audio != HDMI_AUDIO_AUTO) {
 		intel_dp->has_audio = (intel_dp->force_audio == HDMI_AUDIO_ON);
 	} else {
-		edid = intel_dp_get_edid(connector, &intel_dp->adapter);
+		edid = intel_dp_get_edid(connector, &intel_dp->aux.ddc);
 		if (edid) {
 			intel_dp->has_audio = drm_detect_monitor_audio(edid);
 			kfree(edid);
@@ -3263,7 +3130,7 @@ static int intel_dp_get_modes(struct drm_connector *connector)
 	/* We should parse the EDID data and find out if it has an audio sink
 	 */
 
-	ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
+	ret = intel_dp_get_edid_modes(connector, &intel_dp->aux.ddc);
 	if (ret)
 		return ret;
 
@@ -3287,7 +3154,7 @@ intel_dp_detect_audio(struct drm_connector *connector)
 	struct edid *edid;
 	bool has_audio = false;
 
-	edid = intel_dp_get_edid(connector, &intel_dp->adapter);
+	edid = intel_dp_get_edid(connector, &intel_dp->aux.ddc);
 	if (edid) {
 		has_audio = drm_detect_monitor_audio(edid);
 		kfree(edid);
@@ -3407,7 +3274,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
-	i2c_del_adapter(&intel_dp->adapter);
+	drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
@@ -3719,7 +3586,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	/* We now know it's not a ghost, init power sequence regs. */
 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
 
-	edid = drm_get_edid(connector, &intel_dp->adapter);
+	edid = drm_get_edid(connector, &intel_dp->aux.ddc);
 	if (edid) {
 		if (drm_add_edid_modes(connector, edid)) {
 			drm_mode_connector_update_edid_property(connector,
@@ -3767,8 +3634,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum port port = intel_dig_port->port;
 	struct edp_power_seq power_seq = { 0 };
-	const char *name = NULL;
-	int type, error;
+	int type;
 
 	/* intel_dp vfuncs */
 	if (IS_VALLEYVIEW(dev))
@@ -3820,23 +3686,19 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
 
-	/* Set up the DDC bus. */
+	/* Set up the hotplug pin. */
 	switch (port) {
 	case PORT_A:
 		intel_encoder->hpd_pin = HPD_PORT_A;
-		name = "DPDDC-A";
 		break;
 	case PORT_B:
 		intel_encoder->hpd_pin = HPD_PORT_B;
-		name = "DPDDC-B";
 		break;
 	case PORT_C:
 		intel_encoder->hpd_pin = HPD_PORT_C;
-		name = "DPDDC-C";
 		break;
 	case PORT_D:
 		intel_encoder->hpd_pin = HPD_PORT_D;
-		name = "DPDDC-D";
 		break;
 	default:
 		BUG();
@@ -3849,14 +3711,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 
 	intel_dp_aux_init(intel_dp, intel_connector);
 
-	error = intel_dp_i2c_init(intel_dp, intel_connector, name);
-	WARN(error, "intel_dp_i2c_init failed with error %d for port %c\n",
-	     error, port_name(port));
-
 	intel_dp->psr_setup_done = false;
 
 	if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) {
-		i2c_del_adapter(&intel_dp->adapter);
+		drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
 		if (is_edp(intel_dp)) {
 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
 			mutex_lock(&dev->mode_config.mutex);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 75a1329297d9..dedf1e8c937c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -477,8 +477,6 @@ struct intel_dp {
 	uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
 	uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
 	uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
-	struct i2c_adapter adapter;
-	struct i2c_algo_dp_aux_data algo;
 	struct drm_dp_aux aux;
 	uint8_t train_set[4];
 	int panel_power_up_delay;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [RFC PATCH 1/7] drm/i915/dp: clean up cargo culted intel_dp_aux_native_read_retry() usage
  2014-02-04 13:40 ` [RFC PATCH 1/7] drm/i915/dp: clean up cargo culted intel_dp_aux_native_read_retry() usage Jani Nikula
@ 2014-02-04 14:20   ` Ville Syrjälä
  0 siblings, 0 replies; 9+ messages in thread
From: Ville Syrjälä @ 2014-02-04 14:20 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx, Thierry Reding, dri-devel

On Tue, Feb 04, 2014 at 03:40:44PM +0200, Jani Nikula wrote:
> intel_dp_aux_native_read_retry() is only needed when the sink might be
> asleep. Use the regular read without retries otherwise.

I guess I should repeat here what I mentioned to Jani:

The DP spec seems to indicate that AUX transactions should be performed
only when the sink is in on/standby states. When it's in the sleep state,
it may only monitor the AUX channel enough to detect something's happening.
When it detects the AUX activity, it may take up to 1ms (20ms for
"embedded connections") to respond. The state machine diagram shows
that the only valid AUX transaction here is a write of 1h to the 600h
register to wake the sink up to standby state. After that further AUX
transfers can be peformed normally. And once the source is done with
the AUX transfers, it can either proceed w/ link training and move the
sink to the on state, or it may put it back to sleep.

Currently we're doing all kinds of AUX transfers while the sink is still
in the sleep state. This doesn't appear valid according to the spec, and
even if it were, I think we'd need to use the _retry variant pretty much
always since there would no guarantee that the sink wouldn't put the AUX
channel back into the monitor-only mode between transfers.

So it seems we'd need to keep better track of the sink power state while
doing AUX transfers.

> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c |   33 +++++++++++++--------------------
>  1 file changed, 13 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index f1ef3d482c87..19ff1b161ffb 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2871,9 +2871,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
>  	/* Check if the panel supports PSR */
>  	memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
>  	if (is_edp(intel_dp)) {
> -		intel_dp_aux_native_read_retry(intel_dp, DP_PSR_SUPPORT,
> -					       intel_dp->psr_dpcd,
> -					       sizeof(intel_dp->psr_dpcd));
> +		intel_dp_aux_native_read(intel_dp, DP_PSR_SUPPORT,
> +					 intel_dp->psr_dpcd,
> +					 sizeof(intel_dp->psr_dpcd));
>  		if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) {
>  			dev_priv->psr.sink_support = true;
>  			DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
> @@ -2895,9 +2895,10 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
>  	if (intel_dp->dpcd[DP_DPCD_REV] == 0x10)
>  		return true; /* no per-port downstream info */
>  
> -	if (intel_dp_aux_native_read_retry(intel_dp, DP_DOWNSTREAM_PORT_0,
> -					   intel_dp->downstream_ports,
> -					   DP_MAX_DOWNSTREAM_PORTS) == 0)
> +	if (intel_dp_aux_native_read(intel_dp, DP_DOWNSTREAM_PORT_0,
> +				     intel_dp->downstream_ports,
> +				     DP_MAX_DOWNSTREAM_PORTS) !=
> +	    DP_MAX_DOWNSTREAM_PORTS)
>  		return false; /* downstream port status fetch failed */
>  
>  	return true;
> @@ -2913,11 +2914,11 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
>  
>  	edp_panel_vdd_on(intel_dp);
>  
> -	if (intel_dp_aux_native_read_retry(intel_dp, DP_SINK_OUI, buf, 3))
> +	if (intel_dp_aux_native_read(intel_dp, DP_SINK_OUI, buf, 3) == 3)
>  		DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
>  			      buf[0], buf[1], buf[2]);
>  
> -	if (intel_dp_aux_native_read_retry(intel_dp, DP_BRANCH_OUI, buf, 3))
> +	if (intel_dp_aux_native_read(intel_dp, DP_BRANCH_OUI, buf, 3) == 3)
>  		DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
>  			      buf[0], buf[1], buf[2]);
>  
> @@ -2953,18 +2954,11 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
>  	return 0;
>  }
>  
> -static bool
> +static inline bool
>  intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
>  {
> -	int ret;
> -
> -	ret = intel_dp_aux_native_read_retry(intel_dp,
> -					     DP_DEVICE_SERVICE_IRQ_VECTOR,
> -					     sink_irq_vector, 1);
> -	if (!ret)
> -		return false;
> -
> -	return true;
> +	return intel_dp_aux_native_read(intel_dp, DP_DEVICE_SERVICE_IRQ_VECTOR,
> +					sink_irq_vector, 1) == 1;
>  }
>  
>  static void
> @@ -3047,8 +3041,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
>  	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
>  	    intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) {
>  		uint8_t reg;
> -		if (!intel_dp_aux_native_read_retry(intel_dp, DP_SINK_COUNT,
> -						    &reg, 1))
> +		if (intel_dp_aux_native_read(intel_dp, DP_SINK_COUNT, &reg, 1) != 1)
>  			return connector_status_unknown;
>  		return DP_GET_SINK_COUNT(reg) ? connector_status_connected
>  					      : connector_status_disconnected;
> -- 
> 1.7.9.5

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2014-02-04 14:20 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-04 13:40 [RFC PATCH 0/7] drm/i915/dp: convert to new aux channel helpers Jani Nikula
2014-02-04 13:40 ` [RFC PATCH 1/7] drm/i915/dp: clean up cargo culted intel_dp_aux_native_read_retry() usage Jani Nikula
2014-02-04 14:20   ` Ville Syrjälä
2014-02-04 13:40 ` [RFC PATCH 2/7] drm/i915/dp: fix dp aux native read return value checks Jani Nikula
2014-02-04 13:40 ` [RFC PATCH 3/7] drm/i915/dp: split edp_panel_vdd_on() for reuse Jani Nikula
2014-02-04 13:40 ` [RFC PATCH 4/7] drm/i915/dp: move edp vdd enable/disable at a lower level in i2c-over-aux Jani Nikula
2014-02-04 13:40 ` [RFC PATCH 5/7] drm/i915/dp: use the new drm helpers for dp aux Jani Nikula
2014-02-04 13:40 ` [RFC PATCH 6/7] drm/i915/dp: move dp aux ch register init to aux init Jani Nikula
2014-02-04 13:40 ` [RFC PATCH 7/7] drm/i915/dp: use the new drm helpers for dp i2c-over-aux Jani Nikula

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox