[PATCH] drm/rockchip: dw-mipi-dsi: Support MIPI_DSI_DCS_READ

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

 



There is sometimes a need to be able to read from the other
end for instance to identify panels.

Signed-off-by: Richard Röjfors <richard@xxxxxxxxxxxxx>
---
 drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 50 ++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
index 662b6cb5d3f0..88403954f3c4 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
@@ -719,6 +719,53 @@ static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi,
 	return dw_mipi_dsi_gen_pkt_hdr_write(dsi, hdr_val);
 }
 
+static int dw_mipi_dsi_dcs_read(struct dw_mipi_dsi *dsi,
+				const struct mipi_dsi_msg *msg)
+{
+	int ret;
+	int bytes_read = 0;
+	u32 status;
+
+	ret = dw_mipi_dsi_dcs_short_write(dsi, msg);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dsi->dev, "failed to issue read command\n");
+		return ret;
+	}
+
+	/* Loop and empty the RX FIFO */
+	do {
+		u32 val;
+
+		/* Wait for data to reach the fifo or command termination */
+		ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
+					 val, ((val & GEN_PLD_R_EMPTY)) == 0 ||
+					      ((val & GEN_RD_CMD_BUSY) == 0),
+					 1000, CMD_PKT_STATUS_TIMEOUT_US);
+		if (ret < 0) {
+			DRM_DEV_ERROR(dsi->dev,
+				      "failed to read payload from FIFO\n");
+			return ret;
+		}
+
+		status = dsi_read(dsi, DSI_CMD_PKT_STATUS);
+
+		if ((status & GEN_PLD_R_EMPTY) == 0) {
+			int i;
+			u8 *rx_buf = msg->rx_buf;
+
+			val = dsi_read(dsi, DSI_GEN_PLD_DATA);
+
+			for (i = 0; i < sizeof(u32) && bytes_read < msg->rx_len;
+			     i++) {
+				rx_buf[bytes_read++] = val & 0xff;
+				val >>= 8;
+			}
+		}
+	} while ((status & GEN_PLD_R_EMPTY) == 0);
+
+	return bytes_read;
+}
+
 static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
 					 const struct mipi_dsi_msg *msg)
 {
@@ -736,6 +783,9 @@ static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
 	case MIPI_DSI_DCS_LONG_WRITE:
 		ret = dw_mipi_dsi_dcs_long_write(dsi, msg);
 		break;
+	case MIPI_DSI_DCS_READ:
+		ret = dw_mipi_dsi_dcs_read(dsi, msg);
+		break;
 	default:
 		DRM_DEV_ERROR(dsi->dev, "unsupported message type 0x%02x\n",
 			      msg->type);
-- 
2.19.1


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/linux-rockchip




[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux