intel-gfx.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: Shashank Sharma <shashank.sharma@intel.com>
To: intel-gfx@lists.freedesktop.org, daniel.vetter@intel.com
Cc: akashdeep.sharma@inte.com
Subject: [PATCH 6/7] drm/i915: Add lspcon core functions
Date: Tue, 22 Mar 2016 19:55:07 +0530	[thread overview]
Message-ID: <1458656708-31228-7-git-send-email-shashank.sharma@intel.com> (raw)
In-Reply-To: <1458656708-31228-1-git-send-email-shashank.sharma@intel.com>

This patch adds lspcon's internal functions, which work
on the probe layer, and indicate the working status of
lspcon, which are mostly:

probe: A lspcon device is probed only once, during boot
time, as its always present with the device, next to port.
So the i2c_over_aux channel is alwyas read/writeable if DC is
powered on. If VBT says that this port contains lspcon, we
check and probe the HW to verify and initialize it.

get_mode: This function indicates the current mode of operation
of lspcon (ls or pcon mode)

change_mode: This function can change the lspcon's mode of
operation to desired mode.

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
Signed-off-by: Akashdeep Sharma <Akashdeep.sharma@intel.com>
---
 drivers/gpu/drm/i915/intel_lspcon.c | 165 ++++++++++++++++++++++++++++++++++++
 1 file changed, 165 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
index e64abd3..6ef320b 100644
--- a/drivers/gpu/drm/i915/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/intel_lspcon.c
@@ -120,6 +120,164 @@ int lspcon_ioa_write(struct i2c_adapter *adapter, u8 *buffer,
 	return err;
 }
 
+enum lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon)
+{
+	u8 data;
+	int err = 0;
+	struct intel_digital_port *dig_port = lspcon_to_dig_port(lspcon);
+	struct i2c_adapter *adapter = &dig_port->dp.aux.ddc;
+
+	/* Read Status: i2c over aux */
+	err = lspcon_ioa_read(adapter, &data, LSPCON_I2C_ADDRESS,
+			LSPCON_MODE_CHECK_OFFSET, 1);
+	if (err < 0) {
+		DRM_ERROR("LSPCON read mode ioa (0x80, 0x41) failed\n");
+		return lspcon_mode_invalid;
+	}
+
+	DRM_DEBUG_DRIVER("LSPCON mode (0x80, 0x41) = %x\n", (unsigned int)data);
+	return data & LSPCON_MODE_MASK ? lspcon_mode_pcon : lspcon_mode_ls;
+}
+
+int lspcon_change_mode(struct intel_lspcon *lspcon,
+	enum lspcon_mode mode, bool force)
+{
+	u8 data;
+	int err;
+	int time_out = 200;
+	enum lspcon_mode current_mode;
+	struct intel_digital_port *dig_port = lspcon_to_dig_port(lspcon);
+
+	current_mode = lspcon_get_current_mode(lspcon);
+	if (current_mode == lspcon_mode_invalid) {
+		DRM_ERROR("Failed to get current LSPCON mode\n");
+		return -EFAULT;
+	}
+
+	if (current_mode == mode && !force) {
+		DRM_DEBUG_DRIVER("Current mode = desired LSPCON mode\n");
+		return 0;
+	}
+
+	if (mode == lspcon_mode_ls)
+		data = ~LSPCON_MODE_MASK;
+	else
+		data = LSPCON_MODE_MASK;
+
+	/* Change mode */
+	err = lspcon_ioa_write(&dig_port->dp.aux.ddc, &data, LSPCON_I2C_ADDRESS,
+			LSPCON_MODE_CHANGE_OFFSET, 1);
+	if (err < 0) {
+		DRM_ERROR("LSPCON mode change failed\n");
+		return err;
+	}
+
+	/*
+	* Confirm mode change by reading the status bit.
+	* Sometimes, it takes a while to change the mode,
+	* so wait and retry until time out or done.
+	*/
+	while (time_out) {
+		current_mode = lspcon_get_current_mode(lspcon);
+		if (current_mode != mode) {
+			mdelay(10);
+			time_out -= 10;
+		} else {
+			lspcon->mode_of_op = mode;
+			DRM_DEBUG_DRIVER("LSPCON mode changed to %s\n",
+				mode == lspcon_mode_ls ? "LS" : "PCON");
+			return 0;
+		}
+	}
+
+	DRM_ERROR("LSPCON mode change timed out\n");
+	return -EFAULT;
+}
+
+bool lspcon_detect_identifier(struct intel_lspcon *lspcon)
+{
+	int err = 0;
+	u8 sign[LSPCON_IDENTIFIER_LENGTH + 1] = {'\0', };
+	struct intel_digital_port *dig_port = lspcon_to_dig_port(lspcon);
+	struct i2c_adapter *adapter = &dig_port->dp.aux.ddc;
+
+	/*
+	 * Identifier: First 15 bytes are ascii for "DP-HDMI ADAPTOR". The 16th
+	 * byte defines if thats a LSPCON or any other dongle. If byte 16 =0xa8
+	 * its LSPCON
+	 */
+
+	/* Read 16 bytes from I2C reg 0x80, offset 0x0 I2C-over-aux */
+	err = lspcon_ioa_read(adapter, sign, LSPCON_I2C_ADDRESS,
+			LSPCON_ADAPTER_SIGN_OFFSET, LSPCON_IDENTIFIER_LENGTH);
+	if (err < 0) {
+		DRM_ERROR("Error reading lspcon sign (0x80, 0x0)\n");
+		return false;
+	}
+
+	/* Check sign */
+	if (strncmp((void *)sign, "DP-HDMI ADAPTOR",
+		LSPCON_IDENTIFIER_LENGTH - 1)) {
+		DRM_ERROR("Cant detect adaptor sign, its %s\n", sign);
+		return false;
+	}
+
+	/* Identify LSPCON */
+	if (sign[LSPCON_IDENTIFIER_OFFSET] != LSPCON_ADAPTER) {
+		DRM_ERROR("Found non LSPCON adaptor\n");
+		return false;
+	}
+
+	/* yay ... found a LSPCON */
+	DRM_DEBUG_DRIVER("LSPCON adaptor detected\n");
+	return true;
+}
+
+enum lspcon_mode lspcon_probe(struct intel_lspcon *lspcon)
+{
+	enum lspcon_mode current_mode;
+
+	/* Detect a valid lspcon */
+	if (!lspcon_detect_identifier(lspcon)) {
+		DRM_DEBUG_DRIVER("Failed to find LSPCON identifier\n");
+		return false;
+	}
+
+	/* LSPCON's mode of operation */
+	current_mode = lspcon_get_current_mode(lspcon);
+	if (current_mode == lspcon_mode_invalid) {
+		DRM_ERROR("Failed to read LSPCON mode\n");
+		return false;
+	}
+
+	/* All is well */
+	lspcon->mode_of_op = current_mode;
+	lspcon->active = true;
+	return current_mode;
+}
+
+bool lspcon_device_init(struct intel_lspcon *lspcon)
+{
+
+	/* Lets check LSPCON now, probe the HW status */
+	lspcon->active = false;
+	lspcon->mode_of_op = lspcon_mode_invalid;
+	if (!lspcon_probe(lspcon)) {
+		DRM_ERROR("Failed to probe lspcon");
+		return false;
+	}
+
+	/* We wish to keep LSPCON in LS mode */
+	if (lspcon->active && lspcon->mode_of_op != lspcon_mode_ls) {
+		if (lspcon_change_mode(lspcon, lspcon_mode_ls, true) < 0) {
+			DRM_ERROR("LSPCON mode change to LS failed\n");
+			return false;
+		}
+	}
+	DRM_DEBUG_DRIVER("LSPCON init success\n");
+	return true;
+}
+
 static int lspcon_get_edid_over_aux(void *data,
 	u8 *buf, unsigned int block, size_t len)
 {
@@ -333,6 +491,7 @@ void intel_lspcon_init_connector(struct intel_digital_port *intel_dig_port)
 	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_lspcon *lspcon = &intel_dig_port->lspcon;
 	struct intel_connector *intel_connector;
 	struct drm_connector *connector;
 	enum port port = intel_dig_port->port;
@@ -411,6 +570,12 @@ void intel_lspcon_init_connector(struct intel_digital_port *intel_dig_port)
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
 
+	/* Now initialize the LSPCON device */
+	if (!lspcon_device_init(lspcon)) {
+		DRM_ERROR("LSPCON device init failed\n");
+		goto fail;
+	}
+
 	DRM_DEBUG_DRIVER("LSPCON connector init done\n");
 	return;
 
-- 
1.9.1

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

  parent reply	other threads:[~2016-03-22 14:20 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-22 14:25 [PATCH 0/7] Add lspcon support Shashank Sharma
2016-03-22 14:25 ` [PATCH 1/7] drm/i915: add lspcon vbt bit parsing Shashank Sharma
2016-03-22 15:54   ` Jani Nikula
2016-03-22 16:50     ` Sharma, Shashank
2016-03-22 17:05       ` Ville Syrjälä
2016-03-22 17:10         ` Sharma, Shashank
2016-03-22 14:25 ` [PATCH 2/7] drm/i915: Add lspcon data structures Shashank Sharma
2016-03-22 14:25 ` [PATCH 3/7] drm/i915: Add new lspcon file Shashank Sharma
2016-03-22 14:25 ` [PATCH 4/7] drm/i915: Add and initialize lspcon connector Shashank Sharma
2016-03-22 14:25 ` [PATCH 5/7] drm/i915: Add and register lspcon connector functions Shashank Sharma
2016-03-22 14:25 ` Shashank Sharma [this message]
2016-03-22 14:25 ` [PATCH 7/7] drm/i915: Add lspcon hpd handler Shashank Sharma
2016-03-22 16:20 ` [PATCH 0/7] Add lspcon support Ville Syrjälä
2016-03-22 16:47   ` Sharma, Shashank
2016-03-23  9:03     ` Daniel Vetter
2016-03-23  9:12       ` Sharma, Shashank
2016-03-25 16:02       ` Sharma, Shashank
2016-03-22 16:32 ` ✗ Fi.CI.BAT: warning for " Patchwork

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=1458656708-31228-7-git-send-email-shashank.sharma@intel.com \
    --to=shashank.sharma@intel.com \
    --cc=akashdeep.sharma@inte.com \
    --cc=daniel.vetter@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).