* [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers
@ 2025-05-20 17:10 Hugo Villeneuve
2025-05-21 7:43 ` Biju Das
2025-05-22 4:25 ` kernel test robot
0 siblings, 2 replies; 4+ messages in thread
From: Hugo Villeneuve @ 2025-05-20 17:10 UTC (permalink / raw)
To: biju.das.jz, maarten.lankhorst, mripard, tzimmermann, airlied, simona
Cc: dri-devel, linux-renesas-soc, linux-kernel, hugo,
Hugo Villeneuve, Chris Brandt
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Add support for sending MIPI DSI command packets from the host to a
peripheral. This is required for panels that need configuration before
they accept video data.
Based on Renesas Linux kernel v5.10 repos [1].
Link: https://github.com/renesas-rz/rz_linux-cip.git
Cc: Biju Das <biju.das.jz@bp.renesas.com>
Cc: Chris Brandt <chris.brandt@renesas.com>
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
.../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 174 ++++++++++++++++++
.../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h | 56 ++++++
2 files changed, 230 insertions(+)
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
index dc6ab012cdb69..77d3a31ff8e35 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -6,6 +6,7 @@
*/
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
@@ -23,9 +24,12 @@
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include <drm/drm_probe_helper.h>
+#include <video/mipi_display.h>
#include "rzg2l_mipi_dsi_regs.h"
+#define RZG2L_DCS_BUF_SIZE 128 /* Maximum DCS buffer size in external memory. */
+
struct rzg2l_mipi_dsi {
struct device *dev;
void __iomem *mmio;
@@ -44,6 +48,10 @@ struct rzg2l_mipi_dsi {
unsigned int num_data_lanes;
unsigned int lanes;
unsigned long mode_flags;
+
+ /* DCS buffer pointers when using external memory. */
+ dma_addr_t dcs_buf_phys;
+ u8 *dcs_buf_virt;
};
static inline struct rzg2l_mipi_dsi *
@@ -651,9 +659,168 @@ static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,
return 0;
}
+static ssize_t rzg2l_mipi_dsi_read_response(struct rzg2l_mipi_dsi *dsi,
+ const struct mipi_dsi_msg *msg)
+{
+ u8 *msg_rx = msg->rx_buf;
+ u16 size;
+ u8 datatype;
+ u32 result;
+
+ result = rzg2l_mipi_dsi_link_read(dsi, RXRSS0R);
+ if (result & RXRSS0R_RXPKTDFAIL) {
+ dev_err(dsi->dev, "packet rx data did not save correctly\n");
+ return -EPROTO;
+ }
+
+ if (result & RXRSS0R_RXFAIL) {
+ dev_err(dsi->dev, "packet rx failure\n");
+ return -EPROTO;
+ }
+
+ if (!(result & RXRSS0R_RXSUC))
+ return -EPROTO;
+
+ datatype = FIELD_GET(RXRSS0R_DT, result);
+
+ switch (datatype) {
+ case 0:
+ dev_dbg(dsi->dev, "ACK\n");
+ return 0;
+ case MIPI_DSI_RX_END_OF_TRANSMISSION:
+ dev_dbg(dsi->dev, "EoTp\n");
+ return 0;
+ case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
+ dev_dbg(dsi->dev, "Acknowledge and error report: $%02x%02x\n",
+ (u8)FIELD_GET(RXRSS0R_DATA1, result),
+ (u8)FIELD_GET(RXRSS0R_DATA0, result));
+ return 0;
+ case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
+ case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
+ msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
+ return 1;
+ case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
+ case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
+ msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
+ msg_rx[1] = FIELD_GET(RXRSS0R_DATA1, result);
+ return 2;
+ case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
+ case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
+ size = FIELD_GET(RXRSS0R_WC, result);
+
+ if (size > msg->rx_len) {
+ dev_err(dsi->dev, "rx buffer too small");
+ return -ENOSPC;
+ }
+
+ memcpy(msg_rx, dsi->dcs_buf_virt, size);
+ return size;
+ default:
+ dev_err(dsi->dev, "unhandled response type: %02x\n", datatype);
+ return -EPROTO;
+ }
+}
+
+static ssize_t rzg2l_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
+ const struct mipi_dsi_msg *msg)
+{
+ struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
+ struct mipi_dsi_packet packet;
+ bool need_bta;
+ u32 value;
+ int ret;
+
+ ret = mipi_dsi_create_packet(&packet, msg);
+ if (ret < 0)
+ return ret;
+
+ /* Terminate operation after this descriptor is finished */
+ value = SQCH0DSC0AR_NXACT_TERM;
+
+ if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
+ need_bta = true; /* Message with explicitly requested ACK */
+ value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NON_READ);
+ } else if (msg->rx_buf && msg->rx_len > 0) {
+ need_bta = true; /* Read request */
+ value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_READ);
+ } else {
+ need_bta = false;
+ value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NONE);
+ }
+
+ /* Set transmission speed */
+ if (msg->flags & MIPI_DSI_MSG_USE_LPM)
+ value |= SQCH0DSC0AR_SPD_LOW;
+ else
+ value |= SQCH0DSC0AR_SPD_HIGH;
+
+ /* Write TX packet header */
+ value |= FIELD_PREP(SQCH0DSC0AR_DT, packet.header[0]) |
+ FIELD_PREP(SQCH0DSC0AR_DATA0, packet.header[1]) |
+ FIELD_PREP(SQCH0DSC0AR_DATA1, packet.header[2]);
+
+ if (mipi_dsi_packet_format_is_long(msg->type)) {
+ value |= SQCH0DSC0AR_FMT_LONG;
+
+ if (packet.payload_length > RZG2L_DCS_BUF_SIZE) {
+ dev_err(dsi->dev, "Packet Tx payload size (%d) too large",
+ (unsigned int)packet.payload_length);
+ return -ENOSPC;
+ }
+
+ /* Copy TX packet payload data to memory space */
+ memcpy(dsi->dcs_buf_virt, packet.payload, packet.payload_length);
+ } else {
+ value |= SQCH0DSC0AR_FMT_SHORT;
+ }
+
+ rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0AR, value);
+
+ /*
+ * Write: specify payload data source location, only used for
+ * long packet.
+ * Read: specify payload data storage location of response
+ * packet. Note: a read packet is always a short packet.
+ * If the response packet is a short packet or a long packet
+ * with WC = 0 (no payload), DTSEL is meaningless.
+ */
+ rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0BR, SQCH0DSC0BR_DTSEL_MEM_SPACE);
+
+ /*
+ * Set SQCHxSR.AACTFIN bit when descriptor actions are finished.
+ * Read: set Rx result save slot number to 0 (ACTCODE).
+ */
+ rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0CR, SQCH0DSC0CR_FINACT);
+
+ /* Set rx/tx payload data address, only relevant for long packet. */
+ rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0DR, (u32)dsi->dcs_buf_phys);
+
+ /* Start sequence 0 operation */
+ value = rzg2l_mipi_dsi_link_read(dsi, SQCH0SET0R);
+ value |= SQCH0SET0R_START;
+ rzg2l_mipi_dsi_link_write(dsi, SQCH0SET0R, value);
+
+ /* Wait for operation to finish */
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read,
+ value, value & SQCH0SR_ADESFIN,
+ 2000, 20000, false, dsi, SQCH0SR);
+ if (ret == 0) {
+ /* Success: clear status bit */
+ rzg2l_mipi_dsi_link_write(dsi, SQCH0SCR, SQCH0SCR_ADESFIN);
+
+ if (need_bta)
+ ret = rzg2l_mipi_dsi_read_response(dsi, msg);
+ else
+ ret = packet.payload_length;
+ }
+
+ return ret;
+}
+
static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {
.attach = rzg2l_mipi_dsi_host_attach,
.detach = rzg2l_mipi_dsi_host_detach,
+ .transfer = rzg2l_mipi_dsi_host_transfer,
};
/* -----------------------------------------------------------------------------
@@ -771,6 +938,11 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
if (ret < 0)
goto err_pm_disable;
+ dsi->dcs_buf_virt = dma_alloc_coherent(dsi->host.dev, RZG2L_DCS_BUF_SIZE,
+ &dsi->dcs_buf_phys, GFP_KERNEL);
+ if (!dsi->dcs_buf_virt)
+ return -ENOMEM;
+
return 0;
err_phy:
@@ -785,6 +957,8 @@ static void rzg2l_mipi_dsi_remove(struct platform_device *pdev)
{
struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);
+ dma_free_coherent(dsi->host.dev, RZG2L_DCS_BUF_SIZE, dsi->dcs_buf_virt,
+ dsi->dcs_buf_phys);
mipi_dsi_host_unregister(&dsi->host);
pm_runtime_disable(&pdev->dev);
}
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
index 1dbc16ec64a4b..33cd669bc74b1 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
@@ -81,6 +81,16 @@
#define RSTSR_SWRSTLP (1 << 1)
#define RSTSR_SWRSTHS (1 << 0)
+/* Rx Result Save Slot 0 Register */
+#define RXRSS0R 0x240
+#define RXRSS0R_RXPKTDFAIL BIT(28)
+#define RXRSS0R_RXFAIL BIT(27)
+#define RXRSS0R_RXSUC BIT(25)
+#define RXRSS0R_DT GENMASK(21, 16)
+#define RXRSS0R_DATA1 GENMASK(15, 8)
+#define RXRSS0R_DATA0 GENMASK(7, 0)
+#define RXRSS0R_WC GENMASK(15, 0) /* Word count for long packet. */
+
/* Clock Lane Stop Time Set Register */
#define CLSTPTSETR 0x314
#define CLSTPTSETR_CLKKPT(x) ((x) << 24)
@@ -148,4 +158,50 @@
#define VICH1HPSETR_HFP(x) (((x) & 0x1fff) << 16)
#define VICH1HPSETR_HBP(x) (((x) & 0x1fff) << 0)
+/* Sequence Channel 0 Set 0 Register */
+#define SQCH0SET0R 0x5c0
+#define SQCH0SET0R_START BIT(0)
+
+/* Sequence Channel 0 Set 1 Register */
+#define SQCH0SET1R 0x5c4
+
+/* Sequence Channel 0 Status Register */
+#define SQCH0SR 0x5d0
+#define SQCH0SR_RUNNING BIT(2)
+#define SQCH0SR_ADESFIN BIT(8)
+
+/* Sequence Channel 0 Status Clear Register */
+#define SQCH0SCR 0x5d4
+#define SQCH0SCR_ADESFIN BIT(8)
+
+/* Sequence Channel 0 Descriptor 0-A Register */
+#define SQCH0DSC0AR 0x780
+#define SQCH0DSC0AR_NXACT_TERM 0
+#define SQCH0DSC0AR_NXACT_OPER BIT(28)
+#define SQCH0DSC0AR_BTA GENMASK(27, 26)
+#define SQCH0DSC0AR_BTA_NONE 0
+#define SQCH0DSC0AR_BTA_NON_READ 1
+#define SQCH0DSC0AR_BTA_READ 2
+#define SQCH0DSC0AR_BTA_ONLY 3
+#define SQCH0DSC0AR_SPD_HIGH 0
+#define SQCH0DSC0AR_SPD_LOW BIT(25)
+#define SQCH0DSC0AR_FMT_SHORT 0
+#define SQCH0DSC0AR_FMT_LONG BIT(24)
+#define SQCH0DSC0AR_DT GENMASK(21, 16)
+#define SQCH0DSC0AR_DATA1 GENMASK(15, 8)
+#define SQCH0DSC0AR_DATA0 GENMASK(7, 0)
+
+/* Sequence Channel 0 Descriptor 0-B Register */
+#define SQCH0DSC0BR 0x784
+#define SQCH0DSC0BR_DTSEL_PAYLOAD_DR 0 /* Use packet payload data register */
+#define SQCH0DSC0BR_DTSEL_MEM_SPACE BIT(24) /* Use external memory */
+
+/* Sequence Channel 0 Descriptor 0-C Register */
+#define SQCH0DSC0CR 0x788
+#define SQCH0DSC0CR_FINACT BIT(0)
+#define SQCH0DSC0CR_AUXOP BIT(22)
+
+/* Sequence Channel 0 Descriptor 0-D Register */
+#define SQCH0DSC0DR 0x78c
+
#endif /* __RZG2L_MIPI_DSI_REGS_H__ */
--
2.39.5
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers
2025-05-20 17:10 [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers Hugo Villeneuve
@ 2025-05-21 7:43 ` Biju Das
2025-05-21 18:51 ` Hugo Villeneuve
2025-05-22 4:25 ` kernel test robot
1 sibling, 1 reply; 4+ messages in thread
From: Biju Das @ 2025-05-21 7:43 UTC (permalink / raw)
To: Hugo Villeneuve, maarten.lankhorst, mripard, tzimmermann,
airlied, simona
Cc: dri-devel, linux-renesas-soc, linux-kernel, Hugo Villeneuve,
Chris Brandt
Hi Hugo,
Thanks for the patch.
For some reason, your cover letter is not showing link to this patch
[1] https://lore.kernel.org/all/20250520164034.3453315-1-hugo@hugovil.com/
> -----Original Message-----
> From: Hugo Villeneuve <hugo@hugovil.com>
> Sent: 20 May 2025 18:11
> Subject: [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers
rcar-du->rz-du
>
> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
>
> Add support for sending MIPI DSI command packets from the host to a peripheral. This is required for
> panels that need configuration before they accept video data.
>
> Based on Renesas Linux kernel v5.10 repos [1].
>
> Link: https://github.com/renesas-rz/rz_linux-cip.git
> Cc: Biju Das <biju.das.jz@bp.renesas.com>
> Cc: Chris Brandt <chris.brandt@renesas.com>
> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> ---
> .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 174 ++++++++++++++++++
> .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h | 56 ++++++
> 2 files changed, 230 insertions(+)
>
> diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-
> du/rzg2l_mipi_dsi.c
> index dc6ab012cdb69..77d3a31ff8e35 100644
> --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> @@ -6,6 +6,7 @@
> */
> #include <linux/clk.h>
> #include <linux/delay.h>
> +#include <linux/dma-mapping.h>
> #include <linux/io.h>
> #include <linux/iopoll.h>
> #include <linux/module.h>
> @@ -23,9 +24,12 @@
> #include <drm/drm_of.h>
> #include <drm/drm_panel.h>
> #include <drm/drm_probe_helper.h>
> +#include <video/mipi_display.h>
>
> #include "rzg2l_mipi_dsi_regs.h"
>
> +#define RZG2L_DCS_BUF_SIZE 128 /* Maximum DCS buffer size in external memory. */
> +
> struct rzg2l_mipi_dsi {
> struct device *dev;
> void __iomem *mmio;
> @@ -44,6 +48,10 @@ struct rzg2l_mipi_dsi {
> unsigned int num_data_lanes;
> unsigned int lanes;
> unsigned long mode_flags;
> +
> + /* DCS buffer pointers when using external memory. */
> + dma_addr_t dcs_buf_phys;
> + u8 *dcs_buf_virt;
> };
>
> static inline struct rzg2l_mipi_dsi *
> @@ -651,9 +659,168 @@ static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,
> return 0;
> }
>
> +static ssize_t rzg2l_mipi_dsi_read_response(struct rzg2l_mipi_dsi *dsi,
> + const struct mipi_dsi_msg *msg) {
> + u8 *msg_rx = msg->rx_buf;
> + u16 size;
> + u8 datatype;
> + u32 result;
Please arrange the variables in reverse xmas tree fashion.
> +
> + result = rzg2l_mipi_dsi_link_read(dsi, RXRSS0R);
> + if (result & RXRSS0R_RXPKTDFAIL) {
> + dev_err(dsi->dev, "packet rx data did not save correctly\n");
> + return -EPROTO;
> + }
> +
> + if (result & RXRSS0R_RXFAIL) {
> + dev_err(dsi->dev, "packet rx failure\n");
> + return -EPROTO;
> + }
> +
> + if (!(result & RXRSS0R_RXSUC))
> + return -EPROTO;
> +
> + datatype = FIELD_GET(RXRSS0R_DT, result);
> +
> + switch (datatype) {
> + case 0:
> + dev_dbg(dsi->dev, "ACK\n");
> + return 0;
> + case MIPI_DSI_RX_END_OF_TRANSMISSION:
> + dev_dbg(dsi->dev, "EoTp\n");
> + return 0;
> + case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
> + dev_dbg(dsi->dev, "Acknowledge and error report: $%02x%02x\n",
> + (u8)FIELD_GET(RXRSS0R_DATA1, result),
> + (u8)FIELD_GET(RXRSS0R_DATA0, result));
> + return 0;
> + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
> + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
> + msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
> + return 1;
> + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
> + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
> + msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
> + msg_rx[1] = FIELD_GET(RXRSS0R_DATA1, result);
> + return 2;
> + case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
> + case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
> + size = FIELD_GET(RXRSS0R_WC, result);
> +
> + if (size > msg->rx_len) {
> + dev_err(dsi->dev, "rx buffer too small");
> + return -ENOSPC;
> + }
> +
> + memcpy(msg_rx, dsi->dcs_buf_virt, size);
> + return size;
> + default:
> + dev_err(dsi->dev, "unhandled response type: %02x\n", datatype);
> + return -EPROTO;
> + }
> +}
> +
> +static ssize_t rzg2l_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
> + const struct mipi_dsi_msg *msg) {
> + struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
> + struct mipi_dsi_packet packet;
> + bool need_bta;
> + u32 value;
> + int ret;
> +
> + ret = mipi_dsi_create_packet(&packet, msg);
> + if (ret < 0)
> + return ret;
> +
> + /* Terminate operation after this descriptor is finished */
> + value = SQCH0DSC0AR_NXACT_TERM;
> +
> + if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
> + need_bta = true; /* Message with explicitly requested ACK */
> + value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NON_READ);
> + } else if (msg->rx_buf && msg->rx_len > 0) {
> + need_bta = true; /* Read request */
> + value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_READ);
> + } else {
> + need_bta = false;
> + value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NONE);
> + }
> +
> + /* Set transmission speed */
> + if (msg->flags & MIPI_DSI_MSG_USE_LPM)
> + value |= SQCH0DSC0AR_SPD_LOW;
> + else
> + value |= SQCH0DSC0AR_SPD_HIGH;
> +
> + /* Write TX packet header */
> + value |= FIELD_PREP(SQCH0DSC0AR_DT, packet.header[0]) |
> + FIELD_PREP(SQCH0DSC0AR_DATA0, packet.header[1]) |
> + FIELD_PREP(SQCH0DSC0AR_DATA1, packet.header[2]);
> +
> + if (mipi_dsi_packet_format_is_long(msg->type)) {
> + value |= SQCH0DSC0AR_FMT_LONG;
> +
> + if (packet.payload_length > RZG2L_DCS_BUF_SIZE) {
> + dev_err(dsi->dev, "Packet Tx payload size (%d) too large",
> + (unsigned int)packet.payload_length);
> + return -ENOSPC;
> + }
> +
> + /* Copy TX packet payload data to memory space */
> + memcpy(dsi->dcs_buf_virt, packet.payload, packet.payload_length);
> + } else {
> + value |= SQCH0DSC0AR_FMT_SHORT;
> + }
> +
> + rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0AR, value);
> +
> + /*
> + * Write: specify payload data source location, only used for
> + * long packet.
> + * Read: specify payload data storage location of response
> + * packet. Note: a read packet is always a short packet.
> + * If the response packet is a short packet or a long packet
> + * with WC = 0 (no payload), DTSEL is meaningless.
> + */
> + rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0BR,
> +SQCH0DSC0BR_DTSEL_MEM_SPACE);
> +
> + /*
> + * Set SQCHxSR.AACTFIN bit when descriptor actions are finished.
> + * Read: set Rx result save slot number to 0 (ACTCODE).
> + */
> + rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0CR, SQCH0DSC0CR_FINACT);
> +
> + /* Set rx/tx payload data address, only relevant for long packet. */
> + rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0DR, (u32)dsi->dcs_buf_phys);
> +
> + /* Start sequence 0 operation */
> + value = rzg2l_mipi_dsi_link_read(dsi, SQCH0SET0R);
> + value |= SQCH0SET0R_START;
> + rzg2l_mipi_dsi_link_write(dsi, SQCH0SET0R, value);
> +
> + /* Wait for operation to finish */
> + ret = read_poll_timeout(rzg2l_mipi_dsi_link_read,
> + value, value & SQCH0SR_ADESFIN,
> + 2000, 20000, false, dsi, SQCH0SR);
> + if (ret == 0) {
> + /* Success: clear status bit */
> + rzg2l_mipi_dsi_link_write(dsi, SQCH0SCR, SQCH0SCR_ADESFIN);
> +
> + if (need_bta)
> + ret = rzg2l_mipi_dsi_read_response(dsi, msg);
> + else
> + ret = packet.payload_length;
> + }
> +
> + return ret;
> +}
> +
> static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {
> .attach = rzg2l_mipi_dsi_host_attach,
> .detach = rzg2l_mipi_dsi_host_detach,
> + .transfer = rzg2l_mipi_dsi_host_transfer,
> };
>
> /* -----------------------------------------------------------------------------
> @@ -771,6 +938,11 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
> if (ret < 0)
> goto err_pm_disable;
>
> + dsi->dcs_buf_virt = dma_alloc_coherent(dsi->host.dev, RZG2L_DCS_BUF_SIZE,
> + &dsi->dcs_buf_phys, GFP_KERNEL);
> + if (!dsi->dcs_buf_virt)
> + return -ENOMEM;
> +
> return 0;
>
> err_phy:
> @@ -785,6 +957,8 @@ static void rzg2l_mipi_dsi_remove(struct platform_device *pdev) {
> struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);
>
> + dma_free_coherent(dsi->host.dev, RZG2L_DCS_BUF_SIZE, dsi->dcs_buf_virt,
> + dsi->dcs_buf_phys);
> mipi_dsi_host_unregister(&dsi->host);
> pm_runtime_disable(&pdev->dev);
> }
> diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/renesas/rz-
> du/rzg2l_mipi_dsi_regs.h
> index 1dbc16ec64a4b..33cd669bc74b1 100644
> --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
> +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
> @@ -81,6 +81,16 @@
> #define RSTSR_SWRSTLP (1 << 1)
> #define RSTSR_SWRSTHS (1 << 0)
>
> +/* Rx Result Save Slot 0 Register */
> +#define RXRSS0R 0x240
> +#define RXRSS0R_RXPKTDFAIL BIT(28)
> +#define RXRSS0R_RXFAIL BIT(27)
> +#define RXRSS0R_RXSUC BIT(25)
> +#define RXRSS0R_DT GENMASK(21, 16)
> +#define RXRSS0R_DATA1 GENMASK(15, 8)
> +#define RXRSS0R_DATA0 GENMASK(7, 0)
> +#define RXRSS0R_WC GENMASK(15, 0) /* Word count for long packet. */
> +
> /* Clock Lane Stop Time Set Register */
> #define CLSTPTSETR 0x314
> #define CLSTPTSETR_CLKKPT(x) ((x) << 24)
> @@ -148,4 +158,50 @@
> #define VICH1HPSETR_HFP(x) (((x) & 0x1fff) << 16)
> #define VICH1HPSETR_HBP(x) (((x) & 0x1fff) << 0)
>
> +/* Sequence Channel 0 Set 0 Register */
> +#define SQCH0SET0R 0x5c0
> +#define SQCH0SET0R_START BIT(0)
> +
> +/* Sequence Channel 0 Set 1 Register */
> +#define SQCH0SET1R 0x5c4
Unused. Drop it.
> +
> +/* Sequence Channel 0 Status Register */
> +#define SQCH0SR 0x5d0
> +#define SQCH0SR_RUNNING BIT(2)
Unused
> +#define SQCH0SR_ADESFIN BIT(8)
> +
> +/* Sequence Channel 0 Status Clear Register */
> +#define SQCH0SCR 0x5d4
> +#define SQCH0SCR_ADESFIN BIT(8)
> +
> +/* Sequence Channel 0 Descriptor 0-A Register */
> +#define SQCH0DSC0AR 0x780
> +#define SQCH0DSC0AR_NXACT_TERM 0
> +#define SQCH0DSC0AR_NXACT_OPER BIT(28)
Unused
> +#define SQCH0DSC0AR_BTA GENMASK(27, 26)
> +#define SQCH0DSC0AR_BTA_NONE 0
> +#define SQCH0DSC0AR_BTA_NON_READ 1
> +#define SQCH0DSC0AR_BTA_READ 2
> +#define SQCH0DSC0AR_BTA_ONLY 3
> +#define SQCH0DSC0AR_SPD_HIGH 0
> +#define SQCH0DSC0AR_SPD_LOW BIT(25)
> +#define SQCH0DSC0AR_FMT_SHORT 0
> +#define SQCH0DSC0AR_FMT_LONG BIT(24)
> +#define SQCH0DSC0AR_DT GENMASK(21, 16)
> +#define SQCH0DSC0AR_DATA1 GENMASK(15, 8)
> +#define SQCH0DSC0AR_DATA0 GENMASK(7, 0)
> +
> +/* Sequence Channel 0 Descriptor 0-B Register */
> +#define SQCH0DSC0BR 0x784
> +#define SQCH0DSC0BR_DTSEL_PAYLOAD_DR 0 /* Use packet payload data register */
Unused
> +#define SQCH0DSC0BR_DTSEL_MEM_SPACE BIT(24) /* Use external memory */
> +
> +/* Sequence Channel 0 Descriptor 0-C Register */
> +#define SQCH0DSC0CR 0x788
> +#define SQCH0DSC0CR_FINACT BIT(0)
> +#define SQCH0DSC0CR_AUXOP BIT(22)
Unused
> +
> +/* Sequence Channel 0 Descriptor 0-D Register */
> +#define SQCH0DSC0DR 0x78c
> +
Cheers,
Biju
> #endif /* __RZG2L_MIPI_DSI_REGS_H__ */
> --
> 2.39.5
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers
2025-05-21 7:43 ` Biju Das
@ 2025-05-21 18:51 ` Hugo Villeneuve
0 siblings, 0 replies; 4+ messages in thread
From: Hugo Villeneuve @ 2025-05-21 18:51 UTC (permalink / raw)
To: Biju Das
Cc: maarten.lankhorst, mripard, tzimmermann, airlied, simona,
dri-devel, linux-renesas-soc, linux-kernel, Hugo Villeneuve,
Chris Brandt
Hi Biju,
On Wed, 21 May 2025 07:43:08 +0000
Biju Das <biju.das.jz@bp.renesas.com> wrote:
> Hi Hugo,
>
> Thanks for the patch.
>
> For some reason, your cover letter is not showing link to this patch
> [1] https://lore.kernel.org/all/20250520164034.3453315-1-hugo@hugovil.com/
My server had problems, and only sent the cover letter, forcing me to
manually send the two remaining patches thinking it would be ok :)
>
> > -----Original Message-----
> > From: Hugo Villeneuve <hugo@hugovil.com>
> > Sent: 20 May 2025 18:11
> > Subject: [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers
>
> rcar-du->rz-du
Yes, and other commits use "drm: renesas: rz-du:", so I will change it
to this prefix.
> > From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> >
> > Add support for sending MIPI DSI command packets from the host to a peripheral. This is required for
> > panels that need configuration before they accept video data.
> >
> > Based on Renesas Linux kernel v5.10 repos [1].
>
> >
> > Link: https://github.com/renesas-rz/rz_linux-cip.git
> > Cc: Biju Das <biju.das.jz@bp.renesas.com>
> > Cc: Chris Brandt <chris.brandt@renesas.com>
> > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > ---
> > .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 174 ++++++++++++++++++
> > .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h | 56 ++++++
> > 2 files changed, 230 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-
> > du/rzg2l_mipi_dsi.c
> > index dc6ab012cdb69..77d3a31ff8e35 100644
> > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> > @@ -6,6 +6,7 @@
> > */
> > #include <linux/clk.h>
> > #include <linux/delay.h>
> > +#include <linux/dma-mapping.h>
> > #include <linux/io.h>
> > #include <linux/iopoll.h>
> > #include <linux/module.h>
> > @@ -23,9 +24,12 @@
> > #include <drm/drm_of.h>
> > #include <drm/drm_panel.h>
> > #include <drm/drm_probe_helper.h>
> > +#include <video/mipi_display.h>
> >
> > #include "rzg2l_mipi_dsi_regs.h"
> >
> > +#define RZG2L_DCS_BUF_SIZE 128 /* Maximum DCS buffer size in external memory. */
> > +
> > struct rzg2l_mipi_dsi {
> > struct device *dev;
> > void __iomem *mmio;
> > @@ -44,6 +48,10 @@ struct rzg2l_mipi_dsi {
> > unsigned int num_data_lanes;
> > unsigned int lanes;
> > unsigned long mode_flags;
> > +
> > + /* DCS buffer pointers when using external memory. */
> > + dma_addr_t dcs_buf_phys;
> > + u8 *dcs_buf_virt;
> > };
> >
> > static inline struct rzg2l_mipi_dsi *
> > @@ -651,9 +659,168 @@ static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,
> > return 0;
> > }
> >
> > +static ssize_t rzg2l_mipi_dsi_read_response(struct rzg2l_mipi_dsi *dsi,
> > + const struct mipi_dsi_msg *msg) {
> > + u8 *msg_rx = msg->rx_buf;
> > + u16 size;
> > + u8 datatype;
> > + u32 result;
>
> Please arrange the variables in reverse xmas tree fashion.
Ok.
> > +
> > + result = rzg2l_mipi_dsi_link_read(dsi, RXRSS0R);
> > + if (result & RXRSS0R_RXPKTDFAIL) {
> > + dev_err(dsi->dev, "packet rx data did not save correctly\n");
> > + return -EPROTO;
> > + }
> > +
> > + if (result & RXRSS0R_RXFAIL) {
> > + dev_err(dsi->dev, "packet rx failure\n");
> > + return -EPROTO;
> > + }
> > +
> > + if (!(result & RXRSS0R_RXSUC))
> > + return -EPROTO;
> > +
> > + datatype = FIELD_GET(RXRSS0R_DT, result);
> > +
> > + switch (datatype) {
> > + case 0:
> > + dev_dbg(dsi->dev, "ACK\n");
> > + return 0;
> > + case MIPI_DSI_RX_END_OF_TRANSMISSION:
> > + dev_dbg(dsi->dev, "EoTp\n");
> > + return 0;
> > + case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
> > + dev_dbg(dsi->dev, "Acknowledge and error report: $%02x%02x\n",
> > + (u8)FIELD_GET(RXRSS0R_DATA1, result),
> > + (u8)FIELD_GET(RXRSS0R_DATA0, result));
> > + return 0;
> > + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
> > + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
> > + msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
> > + return 1;
> > + case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
> > + case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
> > + msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
> > + msg_rx[1] = FIELD_GET(RXRSS0R_DATA1, result);
> > + return 2;
> > + case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
> > + case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
> > + size = FIELD_GET(RXRSS0R_WC, result);
> > +
> > + if (size > msg->rx_len) {
> > + dev_err(dsi->dev, "rx buffer too small");
> > + return -ENOSPC;
> > + }
> > +
> > + memcpy(msg_rx, dsi->dcs_buf_virt, size);
> > + return size;
> > + default:
> > + dev_err(dsi->dev, "unhandled response type: %02x\n", datatype);
> > + return -EPROTO;
> > + }
> > +}
> > +
> > +static ssize_t rzg2l_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
> > + const struct mipi_dsi_msg *msg) {
> > + struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
> > + struct mipi_dsi_packet packet;
> > + bool need_bta;
> > + u32 value;
> > + int ret;
> > +
> > + ret = mipi_dsi_create_packet(&packet, msg);
> > + if (ret < 0)
> > + return ret;
> > +
> > + /* Terminate operation after this descriptor is finished */
> > + value = SQCH0DSC0AR_NXACT_TERM;
> > +
> > + if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
> > + need_bta = true; /* Message with explicitly requested ACK */
> > + value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NON_READ);
> > + } else if (msg->rx_buf && msg->rx_len > 0) {
> > + need_bta = true; /* Read request */
> > + value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_READ);
> > + } else {
> > + need_bta = false;
> > + value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NONE);
> > + }
> > +
> > + /* Set transmission speed */
> > + if (msg->flags & MIPI_DSI_MSG_USE_LPM)
> > + value |= SQCH0DSC0AR_SPD_LOW;
> > + else
> > + value |= SQCH0DSC0AR_SPD_HIGH;
> > +
> > + /* Write TX packet header */
> > + value |= FIELD_PREP(SQCH0DSC0AR_DT, packet.header[0]) |
> > + FIELD_PREP(SQCH0DSC0AR_DATA0, packet.header[1]) |
> > + FIELD_PREP(SQCH0DSC0AR_DATA1, packet.header[2]);
> > +
> > + if (mipi_dsi_packet_format_is_long(msg->type)) {
> > + value |= SQCH0DSC0AR_FMT_LONG;
> > +
> > + if (packet.payload_length > RZG2L_DCS_BUF_SIZE) {
> > + dev_err(dsi->dev, "Packet Tx payload size (%d) too large",
> > + (unsigned int)packet.payload_length);
> > + return -ENOSPC;
> > + }
> > +
> > + /* Copy TX packet payload data to memory space */
> > + memcpy(dsi->dcs_buf_virt, packet.payload, packet.payload_length);
> > + } else {
> > + value |= SQCH0DSC0AR_FMT_SHORT;
> > + }
> > +
> > + rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0AR, value);
> > +
> > + /*
> > + * Write: specify payload data source location, only used for
> > + * long packet.
> > + * Read: specify payload data storage location of response
> > + * packet. Note: a read packet is always a short packet.
> > + * If the response packet is a short packet or a long packet
> > + * with WC = 0 (no payload), DTSEL is meaningless.
> > + */
> > + rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0BR,
> > +SQCH0DSC0BR_DTSEL_MEM_SPACE);
> > +
> > + /*
> > + * Set SQCHxSR.AACTFIN bit when descriptor actions are finished.
> > + * Read: set Rx result save slot number to 0 (ACTCODE).
> > + */
> > + rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0CR, SQCH0DSC0CR_FINACT);
> > +
> > + /* Set rx/tx payload data address, only relevant for long packet. */
> > + rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0DR, (u32)dsi->dcs_buf_phys);
> > +
> > + /* Start sequence 0 operation */
> > + value = rzg2l_mipi_dsi_link_read(dsi, SQCH0SET0R);
> > + value |= SQCH0SET0R_START;
> > + rzg2l_mipi_dsi_link_write(dsi, SQCH0SET0R, value);
> > +
> > + /* Wait for operation to finish */
> > + ret = read_poll_timeout(rzg2l_mipi_dsi_link_read,
> > + value, value & SQCH0SR_ADESFIN,
> > + 2000, 20000, false, dsi, SQCH0SR);
> > + if (ret == 0) {
> > + /* Success: clear status bit */
> > + rzg2l_mipi_dsi_link_write(dsi, SQCH0SCR, SQCH0SCR_ADESFIN);
> > +
> > + if (need_bta)
> > + ret = rzg2l_mipi_dsi_read_response(dsi, msg);
> > + else
> > + ret = packet.payload_length;
> > + }
> > +
> > + return ret;
> > +}
> > +
> > static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {
> > .attach = rzg2l_mipi_dsi_host_attach,
> > .detach = rzg2l_mipi_dsi_host_detach,
> > + .transfer = rzg2l_mipi_dsi_host_transfer,
> > };
> >
> > /* -----------------------------------------------------------------------------
> > @@ -771,6 +938,11 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
> > if (ret < 0)
> > goto err_pm_disable;
> >
> > + dsi->dcs_buf_virt = dma_alloc_coherent(dsi->host.dev, RZG2L_DCS_BUF_SIZE,
> > + &dsi->dcs_buf_phys, GFP_KERNEL);
> > + if (!dsi->dcs_buf_virt)
> > + return -ENOMEM;
> > +
> > return 0;
> >
> > err_phy:
> > @@ -785,6 +957,8 @@ static void rzg2l_mipi_dsi_remove(struct platform_device *pdev) {
> > struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);
> >
> > + dma_free_coherent(dsi->host.dev, RZG2L_DCS_BUF_SIZE, dsi->dcs_buf_virt,
> > + dsi->dcs_buf_phys);
> > mipi_dsi_host_unregister(&dsi->host);
> > pm_runtime_disable(&pdev->dev);
> > }
> > diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/renesas/rz-
> > du/rzg2l_mipi_dsi_regs.h
> > index 1dbc16ec64a4b..33cd669bc74b1 100644
> > --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
> > +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
> > @@ -81,6 +81,16 @@
> > #define RSTSR_SWRSTLP (1 << 1)
> > #define RSTSR_SWRSTHS (1 << 0)
> >
> > +/* Rx Result Save Slot 0 Register */
> > +#define RXRSS0R 0x240
> > +#define RXRSS0R_RXPKTDFAIL BIT(28)
> > +#define RXRSS0R_RXFAIL BIT(27)
> > +#define RXRSS0R_RXSUC BIT(25)
> > +#define RXRSS0R_DT GENMASK(21, 16)
> > +#define RXRSS0R_DATA1 GENMASK(15, 8)
> > +#define RXRSS0R_DATA0 GENMASK(7, 0)
> > +#define RXRSS0R_WC GENMASK(15, 0) /* Word count for long packet. */
> > +
> > /* Clock Lane Stop Time Set Register */
> > #define CLSTPTSETR 0x314
> > #define CLSTPTSETR_CLKKPT(x) ((x) << 24)
> > @@ -148,4 +158,50 @@
> > #define VICH1HPSETR_HFP(x) (((x) & 0x1fff) << 16)
> > #define VICH1HPSETR_HBP(x) (((x) & 0x1fff) << 0)
> >
> > +/* Sequence Channel 0 Set 0 Register */
> > +#define SQCH0SET0R 0x5c0
> > +#define SQCH0SET0R_START BIT(0)
> > +
> > +/* Sequence Channel 0 Set 1 Register */
> > +#define SQCH0SET1R 0x5c4
>
> Unused. Drop it.
Ok, will remove all unused macros.
>
> > +
> > +/* Sequence Channel 0 Status Register */
> > +#define SQCH0SR 0x5d0
> > +#define SQCH0SR_RUNNING BIT(2)
> Unused
>
> > +#define SQCH0SR_ADESFIN BIT(8)
> > +
> > +/* Sequence Channel 0 Status Clear Register */
> > +#define SQCH0SCR 0x5d4
> > +#define SQCH0SCR_ADESFIN BIT(8)
> > +
> > +/* Sequence Channel 0 Descriptor 0-A Register */
> > +#define SQCH0DSC0AR 0x780
> > +#define SQCH0DSC0AR_NXACT_TERM 0
> > +#define SQCH0DSC0AR_NXACT_OPER BIT(28)
> Unused
>
> > +#define SQCH0DSC0AR_BTA GENMASK(27, 26)
> > +#define SQCH0DSC0AR_BTA_NONE 0
> > +#define SQCH0DSC0AR_BTA_NON_READ 1
> > +#define SQCH0DSC0AR_BTA_READ 2
> > +#define SQCH0DSC0AR_BTA_ONLY 3
> > +#define SQCH0DSC0AR_SPD_HIGH 0
> > +#define SQCH0DSC0AR_SPD_LOW BIT(25)
> > +#define SQCH0DSC0AR_FMT_SHORT 0
> > +#define SQCH0DSC0AR_FMT_LONG BIT(24)
> > +#define SQCH0DSC0AR_DT GENMASK(21, 16)
> > +#define SQCH0DSC0AR_DATA1 GENMASK(15, 8)
> > +#define SQCH0DSC0AR_DATA0 GENMASK(7, 0)
> > +
> > +/* Sequence Channel 0 Descriptor 0-B Register */
> > +#define SQCH0DSC0BR 0x784
> > +#define SQCH0DSC0BR_DTSEL_PAYLOAD_DR 0 /* Use packet payload data register */
> Unused
>
> > +#define SQCH0DSC0BR_DTSEL_MEM_SPACE BIT(24) /* Use external memory */
> > +
> > +/* Sequence Channel 0 Descriptor 0-C Register */
> > +#define SQCH0DSC0CR 0x788
> > +#define SQCH0DSC0CR_FINACT BIT(0)
> > +#define SQCH0DSC0CR_AUXOP BIT(22)
> Unused
>
> > +
> > +/* Sequence Channel 0 Descriptor 0-D Register */
> > +#define SQCH0DSC0DR 0x78c
> > +
>
> Cheers,
> Biju
>
> > #endif /* __RZG2L_MIPI_DSI_REGS_H__ */
> > --
> > 2.39.5
>
>
--
Hugo Villeneuve
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers
2025-05-20 17:10 [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers Hugo Villeneuve
2025-05-21 7:43 ` Biju Das
@ 2025-05-22 4:25 ` kernel test robot
1 sibling, 0 replies; 4+ messages in thread
From: kernel test robot @ 2025-05-22 4:25 UTC (permalink / raw)
To: Hugo Villeneuve, biju.das.jz, maarten.lankhorst, mripard,
tzimmermann, airlied, simona
Cc: oe-kbuild-all, dri-devel, linux-renesas-soc, linux-kernel, hugo,
Hugo Villeneuve, Chris Brandt
Hi Hugo,
kernel test robot noticed the following build errors:
[auto build test ERROR on 7c1a9408ce5f34ded5a85db81cf80e0975901685]
url: https://github.com/intel-lab-lkp/linux/commits/Hugo-Villeneuve/drm-rcar-du-rzg2l_mipi_dsi-Implement-host-transfers/20250521-011613
base: 7c1a9408ce5f34ded5a85db81cf80e0975901685
patch link: https://lore.kernel.org/r/20250520171034.3488482-2-hugo%40hugovil.com
patch subject: [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers
config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20250522/202505221231.A6G8HqGd-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250522/202505221231.A6G8HqGd-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505221231.A6G8HqGd-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c: In function 'rzg2l_mipi_dsi_read_response':
>> drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c:684:20: error: implicit declaration of function 'FIELD_GET' [-Wimplicit-function-declaration]
684 | datatype = FIELD_GET(RXRSS0R_DT, result);
| ^~~~~~~~~
drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c: In function 'rzg2l_mipi_dsi_host_transfer':
>> drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c:742:26: error: implicit declaration of function 'FIELD_PREP' [-Wimplicit-function-declaration]
742 | value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NON_READ);
| ^~~~~~~~~~
vim +/FIELD_GET +684 drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
661
662 static ssize_t rzg2l_mipi_dsi_read_response(struct rzg2l_mipi_dsi *dsi,
663 const struct mipi_dsi_msg *msg)
664 {
665 u8 *msg_rx = msg->rx_buf;
666 u16 size;
667 u8 datatype;
668 u32 result;
669
670 result = rzg2l_mipi_dsi_link_read(dsi, RXRSS0R);
671 if (result & RXRSS0R_RXPKTDFAIL) {
672 dev_err(dsi->dev, "packet rx data did not save correctly\n");
673 return -EPROTO;
674 }
675
676 if (result & RXRSS0R_RXFAIL) {
677 dev_err(dsi->dev, "packet rx failure\n");
678 return -EPROTO;
679 }
680
681 if (!(result & RXRSS0R_RXSUC))
682 return -EPROTO;
683
> 684 datatype = FIELD_GET(RXRSS0R_DT, result);
685
686 switch (datatype) {
687 case 0:
688 dev_dbg(dsi->dev, "ACK\n");
689 return 0;
690 case MIPI_DSI_RX_END_OF_TRANSMISSION:
691 dev_dbg(dsi->dev, "EoTp\n");
692 return 0;
693 case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
694 dev_dbg(dsi->dev, "Acknowledge and error report: $%02x%02x\n",
695 (u8)FIELD_GET(RXRSS0R_DATA1, result),
696 (u8)FIELD_GET(RXRSS0R_DATA0, result));
697 return 0;
698 case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
699 case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
700 msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
701 return 1;
702 case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
703 case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
704 msg_rx[0] = FIELD_GET(RXRSS0R_DATA0, result);
705 msg_rx[1] = FIELD_GET(RXRSS0R_DATA1, result);
706 return 2;
707 case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
708 case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
709 size = FIELD_GET(RXRSS0R_WC, result);
710
711 if (size > msg->rx_len) {
712 dev_err(dsi->dev, "rx buffer too small");
713 return -ENOSPC;
714 }
715
716 memcpy(msg_rx, dsi->dcs_buf_virt, size);
717 return size;
718 default:
719 dev_err(dsi->dev, "unhandled response type: %02x\n", datatype);
720 return -EPROTO;
721 }
722 }
723
724 static ssize_t rzg2l_mipi_dsi_host_transfer(struct mipi_dsi_host *host,
725 const struct mipi_dsi_msg *msg)
726 {
727 struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
728 struct mipi_dsi_packet packet;
729 bool need_bta;
730 u32 value;
731 int ret;
732
733 ret = mipi_dsi_create_packet(&packet, msg);
734 if (ret < 0)
735 return ret;
736
737 /* Terminate operation after this descriptor is finished */
738 value = SQCH0DSC0AR_NXACT_TERM;
739
740 if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
741 need_bta = true; /* Message with explicitly requested ACK */
> 742 value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NON_READ);
743 } else if (msg->rx_buf && msg->rx_len > 0) {
744 need_bta = true; /* Read request */
745 value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_READ);
746 } else {
747 need_bta = false;
748 value |= FIELD_PREP(SQCH0DSC0AR_BTA, SQCH0DSC0AR_BTA_NONE);
749 }
750
751 /* Set transmission speed */
752 if (msg->flags & MIPI_DSI_MSG_USE_LPM)
753 value |= SQCH0DSC0AR_SPD_LOW;
754 else
755 value |= SQCH0DSC0AR_SPD_HIGH;
756
757 /* Write TX packet header */
758 value |= FIELD_PREP(SQCH0DSC0AR_DT, packet.header[0]) |
759 FIELD_PREP(SQCH0DSC0AR_DATA0, packet.header[1]) |
760 FIELD_PREP(SQCH0DSC0AR_DATA1, packet.header[2]);
761
762 if (mipi_dsi_packet_format_is_long(msg->type)) {
763 value |= SQCH0DSC0AR_FMT_LONG;
764
765 if (packet.payload_length > RZG2L_DCS_BUF_SIZE) {
766 dev_err(dsi->dev, "Packet Tx payload size (%d) too large",
767 (unsigned int)packet.payload_length);
768 return -ENOSPC;
769 }
770
771 /* Copy TX packet payload data to memory space */
772 memcpy(dsi->dcs_buf_virt, packet.payload, packet.payload_length);
773 } else {
774 value |= SQCH0DSC0AR_FMT_SHORT;
775 }
776
777 rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0AR, value);
778
779 /*
780 * Write: specify payload data source location, only used for
781 * long packet.
782 * Read: specify payload data storage location of response
783 * packet. Note: a read packet is always a short packet.
784 * If the response packet is a short packet or a long packet
785 * with WC = 0 (no payload), DTSEL is meaningless.
786 */
787 rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0BR, SQCH0DSC0BR_DTSEL_MEM_SPACE);
788
789 /*
790 * Set SQCHxSR.AACTFIN bit when descriptor actions are finished.
791 * Read: set Rx result save slot number to 0 (ACTCODE).
792 */
793 rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0CR, SQCH0DSC0CR_FINACT);
794
795 /* Set rx/tx payload data address, only relevant for long packet. */
796 rzg2l_mipi_dsi_link_write(dsi, SQCH0DSC0DR, (u32)dsi->dcs_buf_phys);
797
798 /* Start sequence 0 operation */
799 value = rzg2l_mipi_dsi_link_read(dsi, SQCH0SET0R);
800 value |= SQCH0SET0R_START;
801 rzg2l_mipi_dsi_link_write(dsi, SQCH0SET0R, value);
802
803 /* Wait for operation to finish */
804 ret = read_poll_timeout(rzg2l_mipi_dsi_link_read,
805 value, value & SQCH0SR_ADESFIN,
806 2000, 20000, false, dsi, SQCH0SR);
807 if (ret == 0) {
808 /* Success: clear status bit */
809 rzg2l_mipi_dsi_link_write(dsi, SQCH0SCR, SQCH0SCR_ADESFIN);
810
811 if (need_bta)
812 ret = rzg2l_mipi_dsi_read_response(dsi, msg);
813 else
814 ret = packet.payload_length;
815 }
816
817 return ret;
818 }
819
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-05-22 4:27 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-05-20 17:10 [PATCH 1/2] drm: rcar-du: rzg2l_mipi_dsi: Implement host transfers Hugo Villeneuve
2025-05-21 7:43 ` Biju Das
2025-05-21 18:51 ` Hugo Villeneuve
2025-05-22 4:25 ` kernel test robot
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®