[PATCH v6] drm/i915/dsi: add payload receiving code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



To support Host to read data from Peripheral after
a DCS read command is sent over DSI.

v1: initial version.
v2:
- adding error message when failing to place BTA.
- returning byte number instead of 0 for the read
function dsi_read_pkt_payld().
v3: fixing coding style warning.
v4:
- correcting the data type of returning data for
the read function dsi_read_pkt_payld().
v5: adding change history as part of commit messages.
v6: according to the review comments from Jani,
- drop the commented out variable "hdr_data".
- use int insteaf of u8 as the data type of the loop
variable i.
- use intel_de_rmw() for read-modify-write.
- add new function place_bta_request() to keep
payload receive function clean.
- explicitly clear the READ_UNLOADS_DW bit of
DSI_CMD_RXCTL before reading receive payload.
- use two loops to copy received data.
- remove the unrelated change from this patch,
which is made to gen11_dsi_setup_timeouts().
- drop the comment in gen11_dsi_host_transfer().
- change the condition to call the payload
receive function in gen11_dsi_host_transfer().

Cc: Jani Nikula <jani.nikula@xxxxxxxxxxxxxxx>
Cc: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
Cc: Vandita Kulkarni <vandita.kulkarni@xxxxxxxxx>
Cc: Lee Shawn C <shawn.c.lee@xxxxxxxxx>
Signed-off-by: William Tseng <william.tseng@xxxxxxxxx>
---
 drivers/gpu/drm/i915/display/icl_dsi.c      | 76 ++++++++++++++++++++-
 drivers/gpu/drm/i915/display/icl_dsi_regs.h | 13 ++++
 2 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index 19bf717fd4cb..edf20016af91 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -201,6 +201,75 @@ static int dsi_send_pkt_hdr(struct intel_dsi_host *host,
 	return 0;
 }
 
+static bool place_bta_request(struct intel_dsi_host *host)
+{
+	struct intel_dsi *intel_dsi = host->intel_dsi;
+	struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
+	enum transcoder dsi_trans = dsi_port_to_transcoder(host->port);
+
+	/* step2a(i): specify Turn-Around timeout */
+	intel_de_rmw(dev_priv, DSI_TA_TO(dsi_trans), TA_TIMEOUT_VALUE_MASK,
+		     TA_TIMEOUT_VALUE(intel_dsi->turn_arnd_val));
+
+	 /* step2a(ii): specify maximum allowed time */
+	intel_de_rmw(dev_priv, DSI_LPRX_HOST_TO(dsi_trans), ~LPRX_TIMEOUT_VALUE_MASK,
+		     LPRX_TIMEOUT_VALUE(intel_dsi->lp_rx_timeout));
+
+	/* check if header credit available */
+	if (!wait_for_header_credits(dev_priv, dsi_trans, 1)) {
+		drm_err(&dev_priv->drm, "not ready to recive payload\n");
+		return false;
+	}
+
+	/* place BTA request */
+	intel_de_rmw(dev_priv, DSI_LP_MSG(dsi_trans), LINK_BTA, LINK_BTA);
+
+	return true;
+}
+
+static int dsi_read_pkt_payld(struct intel_dsi_host *host,
+			      u8 *rx_buf, size_t rx_len)
+{
+	struct intel_dsi *intel_dsi = host->intel_dsi;
+	struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
+	enum transcoder dsi_trans = dsi_port_to_transcoder(host->port);
+	u32 tmp, payld_data;
+	u32 payld_dw;
+	int i, j;
+
+	if (rx_len <= 0)
+		return 0;
+
+	/* do not unload receive queue */
+	tmp = intel_de_read(dev_priv, DSI_CMD_RXCTL(dsi_trans));
+	tmp &= ~READ_UNLOADS_DW;
+	intel_de_write(dev_priv, DSI_CMD_RXCTL(dsi_trans), tmp);
+
+	/* step2: place a BTA request */
+	if (!place_bta_request(host))
+		return -EBUSY;
+
+	/* step4a: wait and read payload */
+	if (wait_for_us(((intel_de_read(dev_priv, DSI_CMD_RXCTL(dsi_trans)) &
+		NUMBER_RX_PLOAD_DW_MASK) >> NUMBER_RX_PLOAD_DW_SHIFT) > 0, 100000)) {
+		drm_err(&dev_priv->drm, "DSI fails to receive payload\n");
+		return -EBUSY;
+	}
+
+	tmp = intel_de_read(dev_priv, DSI_CMD_RXCTL(dsi_trans));
+	payld_dw = (tmp & NUMBER_RX_PLOAD_DW_MASK) >> NUMBER_RX_PLOAD_DW_SHIFT;
+
+	for (i = 0; i < payld_dw; i++) {
+
+		payld_data = intel_de_read(dev_priv, DSI_CMD_RXPYLD(dsi_trans));
+
+		for (j = 0; j < min_t(u32, rx_len - (i * 4), 4); j++)
+			*(rx_buf + (i * 4 + j)) = (payld_data >> 8 * j) & 0xff;
+	}
+
+	return ((i - 1) * 4 + j);
+}
+
 void icl_dsi_frame_update(struct intel_crtc_state *crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -1837,9 +1906,10 @@ static ssize_t gen11_dsi_host_transfer(struct mipi_dsi_host *host,
 	if (ret < 0)
 		return ret;
 
-	//TODO: add payload receive code if needed
-
-	ret = sizeof(dsi_pkt.header) + dsi_pkt.payload_length;
+	if (msg->rx_buf)
+		ret = dsi_read_pkt_payld(intel_dsi_host, msg->rx_buf, msg->rx_len);
+	else
+		ret = sizeof(dsi_pkt.header) + dsi_pkt.payload_length;
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/display/icl_dsi_regs.h b/drivers/gpu/drm/i915/display/icl_dsi_regs.h
index f78f28b8dd94..a77a49b42d60 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi_regs.h
+++ b/drivers/gpu/drm/i915/display/icl_dsi_regs.h
@@ -251,6 +251,18 @@
 #define  NUMBER_RX_PLOAD_DW_MASK	(0xff << 0)
 #define  NUMBER_RX_PLOAD_DW_SHIFT	0
 
+#define _DSI_CMD_RXHDR_0		0x6b0e0
+#define _DSI_CMD_RXHDR_1		0x6b8e0
+#define DSI_CMD_RXHDR(tc)		_MMIO_DSI(tc,	\
+						  _DSI_CMD_RXHDR_0,\
+						  _DSI_CMD_RXHDR_1)
+
+#define _DSI_CMD_RXPYLD_0		0x6b0e4
+#define _DSI_CMD_RXPYLD_1		0x6b8e4
+#define DSI_CMD_RXPYLD(tc)		_MMIO_DSI(tc,	\
+						  _DSI_CMD_RXPYLD_0,\
+						  _DSI_CMD_RXPYLD_1)
+
 #define _DSI_CMD_TXCTL_0		0x6b0d0
 #define _DSI_CMD_TXCTL_1		0x6b8d0
 #define DSI_CMD_TXCTL(tc)		_MMIO_DSI(tc,	\
@@ -294,6 +306,7 @@
 #define  LPTX_IN_PROGRESS		(1 << 17)
 #define  LINK_IN_ULPS			(1 << 16)
 #define  LINK_ULPS_TYPE_LP11		(1 << 8)
+#define  LINK_BTA			(1 << 1)
 #define  LINK_ENTER_ULPS		(1 << 0)
 
 /* DSI timeout registers */
-- 
2.17.1




[Index of Archives]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux