mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Damian Kos <dkos@cadence.com>
To: Archit Taneja <architt@codeaurora.org>,
	Andrzej Hajda <a.hajda@samsung.com>,
	Laurent Pinchart <Laurent.pinchart@ideasonboard.com>,
	David Airlie <airlied@linux.ie>,
	<dri-devel@lists.freedesktop.org>, <linux-kernel@vger.kernel.org>
Cc: <dkos@cadence.com>, <rafalc@cadence.com>, <piotrs@cadence.com>,
	<pgaj@cadence.com>, <quentin.schulz@bootlin.com>,
	<jbergsagel@ti.com>
Subject: [RFC PATCH] drm/bridge: add support for FEC in mhdp8546 driver
Date: Tue, 6 Nov 2018 14:47:20 +0000	[thread overview]
Message-ID: <1541515642-9603-1-git-send-email-dkos@cadence.com> (raw)

From: Przemyslaw Gaj <pgaj@cadence.com>

This patch enables FEC (Forward Error Correction) on Cadence DisplayPort
controller if it's supported by the Sink.

This patch is an addition to patch with mhdp8546 driver @
patchwork.kernel.org/cover/10632065/

Signed-off-by: Przemyslaw Gaj <pgaj@cadence.com>
Signed-off-by: Damian Kos <dkos@cadence.com>
---
 drivers/gpu/drm/bridge/cdns-mhdp.c    | 138 ++++++++++++++++++++++++++
 drivers/gpu/drm/bridge/cdns-mhdp.h    |   4 +-
 include/drm/bridge/cdns-mhdp-common.h |   2 +
 3 files changed, 143 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/cdns-mhdp.c b/drivers/gpu/drm/bridge/cdns-mhdp.c
index caaf3c17d74f..3bfe1eda1468 100644
--- a/drivers/gpu/drm/bridge/cdns-mhdp.c
+++ b/drivers/gpu/drm/bridge/cdns-mhdp.c
@@ -392,6 +392,127 @@ static void mhdp_adjust_requested_eq(struct cdns_mhdp_device *mhdp,
 	}
 }
 
+static int cdns_mhdp_wait_for_fec(struct cdns_mhdp_device *mhdp,
+				  bool expected_status)
+{
+	u32 fec_status;
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+
+	cdns_mhdp_reg_read(mhdp, CDNS_DP_FEC_STATUS, &fec_status);
+	while (((fec_status & CDNS_DP_FEC_BUSY) != expected_status) &&
+		 time_before(jiffies, timeout)) {
+		cdns_mhdp_reg_read(mhdp, CDNS_DP_FEC_STATUS, &fec_status);
+		cpu_relax();
+	}
+
+	if (time_after_eq(jiffies, timeout)) {
+		DRM_DEV_ERROR(mhdp->dev, "Timeout while waiting for FEC\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int cdns_mhdp_fec_sink_support(struct cdns_mhdp_device *mhdp)
+{
+	int ret;
+	u16 dpcd_buffer;
+
+	ret = drm_dp_dpcd_read(&mhdp->aux, DP_FEC_CAPABILITY, &dpcd_buffer, 1);
+	if (ret)
+		return ret;
+
+	if (!(dpcd_buffer & DP_FEC_CAPABLE)) {
+		ret = -ENOTSUPP;
+		DRM_DEV_ERROR(mhdp->dev, "sink does not support FEC: %d\n",
+			      ret);
+		goto err;
+	}
+
+	ret = 0;
+
+err:
+	return ret;
+}
+
+static int cdns_mhdp_fec_sink_set_ready(struct cdns_mhdp_device *mhdp,
+					bool enable)
+{
+	int ret;
+	u16 dpcd_buffer;
+
+	ret = drm_dp_dpcd_read(&mhdp->aux, DP_FEC_CONFIGURATION,
+			       &dpcd_buffer, 1);
+	if (ret)
+		goto err;
+
+	if (enable)
+		dpcd_buffer |= DP_FEC_READY;
+	else
+		dpcd_buffer &= ~DP_FEC_READY;
+
+	ret = drm_dp_dpcd_write(&mhdp->aux, DP_FEC_CONFIGURATION,
+				&dpcd_buffer, 1);
+	if (ret)
+		return 0;
+
+err:
+	DRM_DEV_ERROR(mhdp->dev, "cannot set sink FEC ready: %d\n", ret);
+	return -EIO;
+}
+
+static int cdns_mhdp_fec_set_ready(struct cdns_mhdp_device *mhdp, bool enable)
+{
+	int ret;
+
+	ret = cdns_mhdp_fec_sink_support(mhdp);
+	if (ret)
+		goto err;
+
+	ret = cdns_mhdp_fec_sink_set_ready(mhdp, enable);
+	if (ret)
+		goto err;
+
+	ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_FEC_CTRL, 1, 1, enable);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	return ret;
+}
+
+static int cdns_mhdp_fec_enable(struct cdns_mhdp_device *mhdp, bool enable)
+{
+	int ret;
+	u32 resp;
+	unsigned int dp_framer_global_config;
+
+	if (mhdp->fec_enabled == enable) {
+		ret = -EEXIST;
+		goto err;
+	}
+
+	ret = cdns_mhdp_reg_read(mhdp, DP_FRAMER_GLOBAL_CONFIG, &resp);
+	if (ret)
+		goto err;
+
+	dp_framer_global_config = be32_to_cpu(resp);
+	pr_err("0x%.8x\n", dp_framer_global_config);
+	if (!(dp_framer_global_config & CDNS_DP_NO_VIDEO_MODE)) {
+		ret = -EIO;
+		goto err;
+	}
+
+	ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_FEC_CTRL, 0, 1, enable);
+
+	return cdns_mhdp_wait_for_fec(mhdp, enable);
+err:
+	DRM_DEV_ERROR(mhdp->dev, "set fec enable failed: %d\n", ret);
+	return ret;
+}
+
+
 static bool mhdp_link_training_channel_eq(struct cdns_mhdp_device *mhdp,
 					  u8 eq_tps,
 					  unsigned int training_interval)
@@ -769,6 +890,13 @@ static int cdns_mhdp_link_up(struct cdns_mhdp_device *mhdp)
 	amp[1] = DP_SET_ANSI_8B10B;
 	drm_dp_dpcd_write(&mhdp->aux, DP_DOWNSPREAD_CTRL, amp, 2);
 
+	if (cdns_mhdp_fec_set_ready(mhdp, true)) {
+		mhdp->fec_enabled = false;
+		dev_info(mhdp->dev, "Cannot set FEC ready.\n");
+	} else {
+		mhdp->fec_enabled = true;
+	}
+
 	if (mhdp->host.fast_link & mhdp->sink.fast_link) {
 		/* FIXME: implement fastlink */
 		dev_dbg(mhdp->dev, "fastlink\n");
@@ -807,6 +935,14 @@ static int cdns_mhdp_sst_enable(struct drm_bridge *bridge)
 	pxlfmt = cdns_mhdp_get_pxlfmt(disp_info->color_formats);
 	bpp = cdns_mhdp_get_bpp(disp_info->bpc, pxlfmt);
 
+	if (mhdp->fec_enabled && cdns_mhdp_fec_enable(mhdp, true)) {
+		mhdp->fec_enabled = false;
+		dev_info(mhdp->dev, "Cannot enable FEC.\n");
+	} else {
+		mhdp->fec_enabled = true;
+	}
+
+
 	/* find optimal tu_size */
 	required_bandwidth = pxlclock * bpp / 8;
 	available_bandwidth = mhdp->link.num_lanes * rate;
@@ -814,6 +950,8 @@ static int cdns_mhdp_sst_enable(struct drm_bridge *bridge)
 		tu_size += 2;
 
 		vs_f = tu_size * required_bandwidth / available_bandwidth;
+		if (mhdp->fec_enabled)
+			vs_f = (vs_f * 1024) / 1000; // 102.4 percent
 		vs = vs_f / 1000;
 		vs_f = vs_f % 1000;
 		/*
diff --git a/drivers/gpu/drm/bridge/cdns-mhdp.h b/drivers/gpu/drm/bridge/cdns-mhdp.h
index abc1fa3f51a6..ba233adf9fe7 100644
--- a/drivers/gpu/drm/bridge/cdns-mhdp.h
+++ b/drivers/gpu/drm/bridge/cdns-mhdp.h
@@ -179,7 +179,9 @@
 #define CDNS_DP_LANE_EN				(CDNS_DPTX_GLOBAL + 0x00)
 #define CDNS_DP_LANE_EN_LANES(x)		GENMASK(x - 1, 0)
 #define CDNS_DP_ENHNCD				(CDNS_DPTX_GLOBAL + 0x04)
-
+#define CDNS_DP_FEC_CTRL			(CDNS_DPTX_GLOBAL + 0x10)
+#define CDNS_DP_FEC_STATUS			(CDNS_DPTX_GLOBAL + 0x14)
+#define CDNS_DP_FEC_BUSY			BIT(0)
 
 #define to_mhdp_connector(x) container_of(x, struct cdns_mhdp_connector, base)
 #define to_mhdp_bridge(x) container_of(x, struct cdns_mhdp_bridge, base)
diff --git a/include/drm/bridge/cdns-mhdp-common.h b/include/drm/bridge/cdns-mhdp-common.h
index 1e8a44138ce2..52feeca3a914 100644
--- a/include/drm/bridge/cdns-mhdp-common.h
+++ b/include/drm/bridge/cdns-mhdp-common.h
@@ -566,6 +566,8 @@ struct cdns_mhdp_device {
 	bool can_mst;
 	bool link_up;
 	bool plugged;
+
+	bool fec_enabled;
 };
 
 void cdns_mhdp_clock_reset(struct cdns_mhdp_device *mhdp);
-- 
2.17.1


                 reply	other threads:[~2018-11-06 14:49 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=1541515642-9603-1-git-send-email-dkos@cadence.com \
    --to=dkos@cadence.com \
    --cc=Laurent.pinchart@ideasonboard.com \
    --cc=a.hajda@samsung.com \
    --cc=airlied@linux.ie \
    --cc=architt@codeaurora.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jbergsagel@ti.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pgaj@cadence.com \
    --cc=piotrs@cadence.com \
    --cc=quentin.schulz@bootlin.com \
    --cc=rafalc@cadence.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®