@@ -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);
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@puffinpack.se> --- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 50 ++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)