dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/1] drm: rcar-du: rzg2l_mipi_dsi: add MIPI DSI command support
@ 2025-06-04 14:53 Hugo Villeneuve
  2025-06-04 14:53 ` [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers Hugo Villeneuve
  2025-06-09  6:08 ` [PATCH v4 0/1] drm: rcar-du: rzg2l_mipi_dsi: add MIPI DSI command support Biju Das
  0 siblings, 2 replies; 7+ messages in thread
From: Hugo Villeneuve @ 2025-06-04 14:53 UTC (permalink / raw)
  To: biju.das.jz, maarten.lankhorst, mripard, tzimmermann, airlied,
	simona
  Cc: dri-devel, linux-renesas-soc, linux-kernel, hugo, chris.brandt,
	Hugo Villeneuve

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

Hello,
this patch series add support for sending MIPI DSI command packets to the
Renesas RZ/G2L MIPI DSI driver.

Tested on a custom board with a SolidRun RZ/G2L SOM, with two different LCD
panels using the jd9365da and st7703 drivers.

Tested short and long writes.

Tested read of 1 byte, 2 bytes and long reads. Note that to test long reads,
most LCD panels need to be sent a DCS configuration command to increase the
maximum packet size, which is set to 1 byte by default (at least on the two
panels that I tested).

Thank you.

Link: [v1] https://lore.kernel.org/all/20250520164034.3453315-1-hugo@hugovil.com
Link: [v3] https://lore.kernel.org/all/20250522143911.138077-1-hugo@hugovil.com
Link: [dep1] https://lore.kernel.org/all/20250521210335.3149065-1-chris.brandt@renesas.com/raw

Changes for V4:
- Rebased on drm-misc-next, since this series depends on [dep1]
- Move init of DCS maximum return packet size to rzg2l_mipi_dsi_startup()
- Reworded comment for DCS maximum return packet size
- Merged patches 1 and 2

Changes for V3:
- No code change, resending after fixing mail server config resulting in
  only cover letter being sent

Changes for V2:
- Change commit message prefix to "drm: renesas: rz-du: "
- Reorder variables in rzg2l_mipi_dsi_read_response()
- Remove unused macros
- Add missing bitfield include (kernel test robot)

Hugo Villeneuve (1):
  drm: renesas: rz-du: Implement MIPI DSI host transfers

 .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 186 ++++++++++++++++++
 .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  54 +++++
 2 files changed, 240 insertions(+)


base-commit: 685c407f168cb49a12cc703230d1e2d62767bfd2
-- 
2.39.5


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers
  2025-06-04 14:53 [PATCH v4 0/1] drm: rcar-du: rzg2l_mipi_dsi: add MIPI DSI command support Hugo Villeneuve
@ 2025-06-04 14:53 ` Hugo Villeneuve
  2025-06-04 16:22   ` Chris Brandt
  2025-06-05  8:18   ` Biju Das
  2025-06-09  6:08 ` [PATCH v4 0/1] drm: rcar-du: rzg2l_mipi_dsi: add MIPI DSI command support Biju Das
  1 sibling, 2 replies; 7+ messages in thread
From: Hugo Villeneuve @ 2025-06-04 14:53 UTC (permalink / raw)
  To: biju.das.jz, maarten.lankhorst, mripard, tzimmermann, airlied,
	simona
  Cc: dri-devel, linux-renesas-soc, linux-kernel, hugo, chris.brandt,
	Hugo Villeneuve

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.

Also for long reads to work properly, set DCS maximum return packet size
to the value of the DMA buffer size.

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>
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 186 ++++++++++++++++++
 .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  54 +++++
 2 files changed, 240 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 91e1a9adad7d6..50ec109aa6ed3 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -4,8 +4,11 @@
  *
  * Copyright (C) 2022 Renesas Electronics Corporation
  */
+
+#include <linux/bitfield.h>
 #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 +26,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 +50,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 *
@@ -267,6 +277,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
 	u32 clkbfht;
 	u32 clkstpt;
 	u32 golpbkt;
+	u32 dsisetr;
 	int ret;
 
 	/*
@@ -328,6 +339,15 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
 	lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
 	rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);
 
+	/*
+	 * Increase MRPSZ as the default value of 1 will result in long read
+	 * commands payload not being saved to memory.
+	 */
+	dsisetr = rzg2l_mipi_dsi_link_read(dsi, DSISETR);
+	dsisetr &= ~DSISETR_MRPSZ;
+	dsisetr |= FIELD_PREP(DSISETR_MRPSZ, RZG2L_DCS_BUF_SIZE);
+	rzg2l_mipi_dsi_link_write(dsi, DSISETR, dsisetr);
+
 	return 0;
 
 err_phy:
@@ -659,9 +679,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;
+	u8 datatype;
+	u32 result;
+	u16 size;
+
+	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,
 };
 
 /* -----------------------------------------------------------------------------
@@ -779,6 +958,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:
@@ -793,6 +977,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..26d8a37ee6351 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,20 @@
 #define RSTSR_SWRSTLP			(1 << 1)
 #define RSTSR_SWRSTHS			(1 << 0)
 
+/* DSI Set Register */
+#define DSISETR				0x120
+#define DSISETR_MRPSZ			GENMASK(15, 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 +162,44 @@
 #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 Status Register */
+#define SQCH0SR				0x5d0
+#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	/* 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_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 related	[flat|nested] 7+ messages in thread

* RE: [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers
  2025-06-04 14:53 ` [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers Hugo Villeneuve
@ 2025-06-04 16:22   ` Chris Brandt
  2025-06-05  8:18   ` Biju Das
  1 sibling, 0 replies; 7+ messages in thread
From: Chris Brandt @ 2025-06-04 16:22 UTC (permalink / raw)
  To: Hugo Villeneuve, Biju Das, maarten.lankhorst@linux.intel.com,
	mripard@kernel.org, tzimmermann@suse.de, airlied@gmail.com,
	simona@ffwll.ch
  Cc: dri-devel@lists.freedesktop.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Hugo Villeneuve

Tested on 2 different panels, with an RZ/G2L and RZ/V2L.

Thanks Hugo!


Tested-by: Chris Brandt <Chris.Brandt@renesas.com>





-----Original Message-----
From: Hugo Villeneuve <hugo@hugovil.com> 
Sent: Wednesday, June 4, 2025 10:53 AM
To: Biju Das <biju.das.jz@bp.renesas.com>; maarten.lankhorst@linux.intel.com; mripard@kernel.org; tzimmermann@suse.de; airlied@gmail.com; simona@ffwll.ch
Cc: dri-devel@lists.freedesktop.org; linux-renesas-soc@vger.kernel.org; linux-kernel@vger.kernel.org; hugo@hugovil.com; Chris Brandt <Chris.Brandt@renesas.com>; Hugo Villeneuve <hvilleneuve@dimonoff.com>
Subject: [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers

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.

Also for long reads to work properly, set DCS maximum return packet size to the value of the DMA buffer size.

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>
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 186 ++++++++++++++++++
 .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  54 +++++
 2 files changed, 240 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 91e1a9adad7d6..50ec109aa6ed3 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -4,8 +4,11 @@
  *
  * Copyright (C) 2022 Renesas Electronics Corporation
  */
+
+#include <linux/bitfield.h>
 #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 +26,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 +50,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 *
@@ -267,6 +277,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
 	u32 clkbfht;
 	u32 clkstpt;
 	u32 golpbkt;
+	u32 dsisetr;
 	int ret;
 
 	/*
@@ -328,6 +339,15 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
 	lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
 	rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);
 
+	/*
+	 * Increase MRPSZ as the default value of 1 will result in long read
+	 * commands payload not being saved to memory.
+	 */
+	dsisetr = rzg2l_mipi_dsi_link_read(dsi, DSISETR);
+	dsisetr &= ~DSISETR_MRPSZ;
+	dsisetr |= FIELD_PREP(DSISETR_MRPSZ, RZG2L_DCS_BUF_SIZE);
+	rzg2l_mipi_dsi_link_write(dsi, DSISETR, dsisetr);
+
 	return 0;
 
 err_phy:
@@ -659,9 +679,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;
+	u8 datatype;
+	u32 result;
+	u16 size;
+
+	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,
 };
 
 /* -----------------------------------------------------------------------------
@@ -779,6 +958,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:
@@ -793,6 +977,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..26d8a37ee6351 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,20 @@
 #define RSTSR_SWRSTLP			(1 << 1)
 #define RSTSR_SWRSTHS			(1 << 0)
 
+/* DSI Set Register */
+#define DSISETR				0x120
+#define DSISETR_MRPSZ			GENMASK(15, 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 +162,44 @@
 #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 Status Register */
+#define SQCH0SR				0x5d0
+#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	/* 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_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 related	[flat|nested] 7+ messages in thread

* RE: [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers
  2025-06-04 14:53 ` [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers Hugo Villeneuve
  2025-06-04 16:22   ` Chris Brandt
@ 2025-06-05  8:18   ` Biju Das
  2025-06-05 13:38     ` Hugo Villeneuve
  1 sibling, 1 reply; 7+ messages in thread
From: Biju Das @ 2025-06-05  8:18 UTC (permalink / raw)
  To: Hugo Villeneuve, maarten.lankhorst@linux.intel.com,
	mripard@kernel.org, tzimmermann@suse.de, airlied@gmail.com,
	simona@ffwll.ch
  Cc: dri-devel@lists.freedesktop.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Chris Brandt, Hugo Villeneuve

Hi Hugo,

Thanks for the patch.

> -----Original Message-----
> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of Hugo Villeneuve
> Sent: 04 June 2025 15:53
> Subject: [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers
> 
> 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.
> 
> Also for long reads to work properly, set DCS maximum return packet size to the value of the DMA
> buffer size.
> 
> 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>
> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>

Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>

FYI, Checkpatch is complaining about duplicate signature.
I can fix this while applying,if there are no more comments for this patch.

I am seeing below duplicate tags with your patch now.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>                        
Tested-by: Chris Brandt <Chris.Brandt@renesas.com>                               
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>  

$ scripts/checkpatch.pl --strict 0001-drm-renesas-rz-du-Implement-MIPI-DSI-host-transfers.patch 
WARNING: Duplicate signature
#19: 
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>

total: 0 errors, 1 warnings, 0 checks, 306 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

0001-drm-renesas-rz-du-Implement-MIPI-DSI-host-transfers.patch has style problems, please review.

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


> ---
>  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 186 ++++++++++++++++++
>  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  54 +++++
>  2 files changed, 240 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 91e1a9adad7d6..50ec109aa6ed3 100644
> --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> @@ -4,8 +4,11 @@
>   *
>   * Copyright (C) 2022 Renesas Electronics Corporation
>   */
> +

Normally, changes like this should reflect in commit message.

Cheers,
Biju

> +#include <linux/bitfield.h>
>  #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 +26,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 +50,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 *
> @@ -267,6 +277,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
>  	u32 clkbfht;
>  	u32 clkstpt;
>  	u32 golpbkt;
> +	u32 dsisetr;
>  	int ret;
> 
>  	/*
> @@ -328,6 +339,15 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
>  	lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
>  	rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);
> 
> +	/*
> +	 * Increase MRPSZ as the default value of 1 will result in long read
> +	 * commands payload not being saved to memory.
> +	 */
> +	dsisetr = rzg2l_mipi_dsi_link_read(dsi, DSISETR);
> +	dsisetr &= ~DSISETR_MRPSZ;
> +	dsisetr |= FIELD_PREP(DSISETR_MRPSZ, RZG2L_DCS_BUF_SIZE);
> +	rzg2l_mipi_dsi_link_write(dsi, DSISETR, dsisetr);
> +
>  	return 0;
> 
>  err_phy:
> @@ -659,9 +679,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;
> +	u8 datatype;
> +	u32 result;
> +	u16 size;
> +
> +	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,
>  };
> 
>  /* -----------------------------------------------------------------------------
> @@ -779,6 +958,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:
> @@ -793,6 +977,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..26d8a37ee6351 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,20 @@
>  #define RSTSR_SWRSTLP			(1 << 1)
>  #define RSTSR_SWRSTHS			(1 << 0)
> 
> +/* DSI Set Register */
> +#define DSISETR				0x120
> +#define DSISETR_MRPSZ			GENMASK(15, 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 +162,44 @@
>  #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 Status Register */
> +#define SQCH0SR				0x5d0
> +#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	/* 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_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] 7+ messages in thread

* Re: [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers
  2025-06-05  8:18   ` Biju Das
@ 2025-06-05 13:38     ` Hugo Villeneuve
  2025-06-05 13:43       ` Biju Das
  0 siblings, 1 reply; 7+ messages in thread
From: Hugo Villeneuve @ 2025-06-05 13:38 UTC (permalink / raw)
  To: Biju Das, Hugo Villeneuve, maarten.lankhorst@linux.intel.com,
	mripard@kernel.org, tzimmermann@suse.de, airlied@gmail.com,
	simona@ffwll.ch
  Cc: dri-devel@lists.freedesktop.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Chris Brandt

On 6/5/25 04:18, Biju Das wrote:
> Hi Hugo,
> 
> Thanks for the patch.
> 
>> -----Original Message-----
>> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf Of Hugo Villeneuve
>> Sent: 04 June 2025 15:53
>> Subject: [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers
>>
>> 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.
>>
>> Also for long reads to work properly, set DCS maximum return packet size to the value of the DMA
>> buffer size.
>>
>> 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>
>> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> 
> Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
> 
> FYI, Checkpatch is complaining about duplicate signature.
> I can fix this while applying,if there are no more comments for this patch.
> 
> I am seeing below duplicate tags with your patch now.
> 
> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> Tested-by: Chris Brandt <Chris.Brandt@renesas.com>
> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> 
> $ scripts/checkpatch.pl --strict 0001-drm-renesas-rz-du-Implement-MIPI-DSI-host-transfers.patch
> WARNING: Duplicate signature
> #19:
> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>

Hi Biju,
I don't know how this is possible, considering that the patch I sent 
(https://lore.kernel.org/all/20250604145306.1170676-2-hugo@hugovil.com/) 
  has only this:

---------------
Link: https://github.com/renesas-rz/rz_linux-cip.git
Cc: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---------------


> total: 0 errors, 1 warnings, 0 checks, 306 lines checked
> 
> NOTE: For some of the reported defects, checkpatch may be able to
>        mechanically convert to the typical style using --fix or --fix-inplace.
> 
> 0001-drm-renesas-rz-du-Implement-MIPI-DSI-host-transfers.patch has style problems, please review.
> 
> NOTE: If any of the errors are false positives, please report
>        them to the maintainer, see CHECKPATCH in MAINTAINERS.
> 
> 
>> ---
>>   .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 186 ++++++++++++++++++
>>   .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  54 +++++
>>   2 files changed, 240 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 91e1a9adad7d6..50ec109aa6ed3 100644
>> --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
>> +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
>> @@ -4,8 +4,11 @@
>>    *
>>    * Copyright (C) 2022 Renesas Electronics Corporation
>>    */
>> +
> 
> Normally, changes like this should reflect in commit message.

This is linked to the new #include, so this is why I didn't add a 
separate changelog entry...

Hugo.


> 
> Cheers,
> Biju
> 
>> +#include <linux/bitfield.h>
>>   #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 +26,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 +50,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 *
>> @@ -267,6 +277,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
>>   	u32 clkbfht;
>>   	u32 clkstpt;
>>   	u32 golpbkt;
>> +	u32 dsisetr;
>>   	int ret;
>>
>>   	/*
>> @@ -328,6 +339,15 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
>>   	lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
>>   	rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);
>>
>> +	/*
>> +	 * Increase MRPSZ as the default value of 1 will result in long read
>> +	 * commands payload not being saved to memory.
>> +	 */
>> +	dsisetr = rzg2l_mipi_dsi_link_read(dsi, DSISETR);
>> +	dsisetr &= ~DSISETR_MRPSZ;
>> +	dsisetr |= FIELD_PREP(DSISETR_MRPSZ, RZG2L_DCS_BUF_SIZE);
>> +	rzg2l_mipi_dsi_link_write(dsi, DSISETR, dsisetr);
>> +
>>   	return 0;
>>
>>   err_phy:
>> @@ -659,9 +679,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;
>> +	u8 datatype;
>> +	u32 result;
>> +	u16 size;
>> +
>> +	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,
>>   };
>>
>>   /* -----------------------------------------------------------------------------
>> @@ -779,6 +958,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:
>> @@ -793,6 +977,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..26d8a37ee6351 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,20 @@
>>   #define RSTSR_SWRSTLP			(1 << 1)
>>   #define RSTSR_SWRSTHS			(1 << 0)
>>
>> +/* DSI Set Register */
>> +#define DSISETR				0x120
>> +#define DSISETR_MRPSZ			GENMASK(15, 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 +162,44 @@
>>   #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 Status Register */
>> +#define SQCH0SR				0x5d0
>> +#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	/* 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_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] 7+ messages in thread

* RE: [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers
  2025-06-05 13:38     ` Hugo Villeneuve
@ 2025-06-05 13:43       ` Biju Das
  0 siblings, 0 replies; 7+ messages in thread
From: Biju Das @ 2025-06-05 13:43 UTC (permalink / raw)
  To: Hugo Villeneuve, Hugo Villeneuve,
	maarten.lankhorst@linux.intel.com, mripard@kernel.org,
	tzimmermann@suse.de, airlied@gmail.com, simona@ffwll.ch
  Cc: dri-devel@lists.freedesktop.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Chris Brandt



> -----Original Message-----
> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> Sent: 05 June 2025 14:38
> To: Biju Das <biju.das.jz@bp.renesas.com>; Hugo Villeneuve <hugo@hugovil.com>;
> maarten.lankhorst@linux.intel.com; mripard@kernel.org; tzimmermann@suse.de; airlied@gmail.com;
> simona@ffwll.ch
> Cc: dri-devel@lists.freedesktop.org; linux-renesas-soc@vger.kernel.org; linux-kernel@vger.kernel.org;
> Chris Brandt <Chris.Brandt@renesas.com>
> Subject: Re: [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers
> 
> On 6/5/25 04:18, Biju Das wrote:
> > Hi Hugo,
> >
> > Thanks for the patch.
> >
> >> -----Original Message-----
> >> From: dri-devel <dri-devel-bounces@lists.freedesktop.org> On Behalf
> >> Of Hugo Villeneuve
> >> Sent: 04 June 2025 15:53
> >> Subject: [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host
> >> transfers
> >>
> >> 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.
> >>
> >> Also for long reads to work properly, set DCS maximum return packet
> >> size to the value of the DMA buffer size.
> >>
> >> 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>
> >> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> >
> > Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
> >
> > FYI, Checkpatch is complaining about duplicate signature.
> > I can fix this while applying,if there are no more comments for this patch.
> >
> > I am seeing below duplicate tags with your patch now.
> >
> > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> > Tested-by: Chris Brandt <Chris.Brandt@renesas.com>
> > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> >
> > $ scripts/checkpatch.pl --strict
> > 0001-drm-renesas-rz-du-Implement-MIPI-DSI-host-transfers.patch
> > WARNING: Duplicate signature
> > #19:
> > Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> 
> Hi Biju,
> I don't know how this is possible, considering that the patch I sent
> (https://lore.kernel.org/all/20250604145306.1170676-2-hugo@hugovil.com/)
>   has only this:
> 
> ---------------
> Link: https://github.com/renesas-rz/rz_linux-cip.git
> Cc: Biju Das <biju.das.jz@bp.renesas.com>
> Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> ---------------
> 
> 
> > total: 0 errors, 1 warnings, 0 checks, 306 lines checked
> >
> > NOTE: For some of the reported defects, checkpatch may be able to
> >        mechanically convert to the typical style using --fix or --fix-inplace.
> >
> > 0001-drm-renesas-rz-du-Implement-MIPI-DSI-host-transfers.patch has style problems, please review.
> >
> > NOTE: If any of the errors are false positives, please report
> >        them to the maintainer, see CHECKPATCH in MAINTAINERS.
> >
> >
> >> ---
> >>   .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 186 ++++++++++++++++++
> >>   .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  54 +++++
> >>   2 files changed, 240 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
> >> 91e1a9adad7d6..50ec109aa6ed3 100644
> >> --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> >> +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
> >> @@ -4,8 +4,11 @@
> >>    *
> >>    * Copyright (C) 2022 Renesas Electronics Corporation
> >>    */
> >> +
> >
> > Normally, changes like this should reflect in commit message.
> 
> This is linked to the new #include, so this is why I didn't add a separate changelog entry...

My Bad. I overlooked this.

Cheers,
Biju

> 
> 
> >
> > Cheers,
> > Biju
> >
> >> +#include <linux/bitfield.h>
> >>   #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 +26,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 +50,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 * @@ -267,6 +277,7 @@ static
> >> int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
> >>   	u32 clkbfht;
> >>   	u32 clkstpt;
> >>   	u32 golpbkt;
> >> +	u32 dsisetr;
> >>   	int ret;
> >>
> >>   	/*
> >> @@ -328,6 +339,15 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
> >>   	lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
> >>   	rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);
> >>
> >> +	/*
> >> +	 * Increase MRPSZ as the default value of 1 will result in long read
> >> +	 * commands payload not being saved to memory.
> >> +	 */
> >> +	dsisetr = rzg2l_mipi_dsi_link_read(dsi, DSISETR);
> >> +	dsisetr &= ~DSISETR_MRPSZ;
> >> +	dsisetr |= FIELD_PREP(DSISETR_MRPSZ, RZG2L_DCS_BUF_SIZE);
> >> +	rzg2l_mipi_dsi_link_write(dsi, DSISETR, dsisetr);
> >> +
> >>   	return 0;
> >>
> >>   err_phy:
> >> @@ -659,9 +679,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;
> >> +	u8 datatype;
> >> +	u32 result;
> >> +	u16 size;
> >> +
> >> +	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,
> >>   };
> >>
> >>   /*
> >> ---------------------------------------------------------------------
> >> -------- @@ -779,6 +958,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:
> >> @@ -793,6 +977,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..26d8a37ee6351 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,20 @@
> >>   #define RSTSR_SWRSTLP			(1 << 1)
> >>   #define RSTSR_SWRSTHS			(1 << 0)
> >>
> >> +/* DSI Set Register */
> >> +#define DSISETR				0x120
> >> +#define DSISETR_MRPSZ			GENMASK(15, 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 +162,44 @@
> >>   #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 Status Register */
> >> +#define SQCH0SR				0x5d0
> >> +#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	/* 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_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] 7+ messages in thread

* RE: [PATCH v4 0/1] drm: rcar-du: rzg2l_mipi_dsi: add MIPI DSI command support
  2025-06-04 14:53 [PATCH v4 0/1] drm: rcar-du: rzg2l_mipi_dsi: add MIPI DSI command support Hugo Villeneuve
  2025-06-04 14:53 ` [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers Hugo Villeneuve
@ 2025-06-09  6:08 ` Biju Das
  1 sibling, 0 replies; 7+ messages in thread
From: Biju Das @ 2025-06-09  6:08 UTC (permalink / raw)
  To: Hugo Villeneuve, maarten.lankhorst@linux.intel.com,
	mripard@kernel.org, tzimmermann@suse.de, airlied@gmail.com,
	simona@ffwll.ch
  Cc: dri-devel@lists.freedesktop.org,
	linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Chris Brandt, Hugo Villeneuve, Prabhakar Mahadev Lad,
	Tommaso Merciai

> Subject: [PATCH v4 0/1] drm: rcar-du: rzg2l_mipi_dsi: add MIPI DSI command support
> 
> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> 
> Hello,
> this patch series add support for sending MIPI DSI command packets to the Renesas RZ/G2L MIPI DSI
> driver.
> 
> Tested on a custom board with a SolidRun RZ/G2L SOM, with two different LCD panels using the jd9365da
> and st7703 drivers.
> 
> Tested short and long writes.
> 
> Tested read of 1 byte, 2 bytes and long reads. Note that to test long reads, most LCD panels need to
> be sent a DCS configuration command to increase the maximum packet size, which is set to 1 byte by
> default (at least on the two panels that I tested).
> 
> Thank you.
> 
> Link: [v1] https://lore.kernel.org/all/20250520164034.3453315-1-hugo@hugovil.com
> Link: [v3] https://lore.kernel.org/all/20250522143911.138077-1-hugo@hugovil.com
> Link: [dep1] https://lore.kernel.org/all/20250521210335.3149065-1-chris.brandt@renesas.com/raw
> 
> Changes for V4:
> - Rebased on drm-misc-next, since this series depends on [dep1]
> - Move init of DCS maximum return packet size to rzg2l_mipi_dsi_startup()
> - Reworded comment for DCS maximum return packet size
> - Merged patches 1 and 2
> 
> Changes for V3:
> - No code change, resending after fixing mail server config resulting in
>   only cover letter being sent
> 
> Changes for V2:
> - Change commit message prefix to "drm: renesas: rz-du: "
> - Reorder variables in rzg2l_mipi_dsi_read_response()
> - Remove unused macros
> - Add missing bitfield include (kernel test robot)
> 
> Hugo Villeneuve (1):
>   drm: renesas: rz-du: Implement MIPI DSI host transfers
> 
>  .../gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c    | 186 ++++++++++++++++++
>  .../drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h   |  54 +++++
>  2 files changed, 240 insertions(+)
> 
> 
> base-commit: 685c407f168cb49a12cc703230d1e2d62767bfd2
> --
> 2.39.5

Applied to drm-misc-next

Thanks,
Biju


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-06-09  6:09 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-04 14:53 [PATCH v4 0/1] drm: rcar-du: rzg2l_mipi_dsi: add MIPI DSI command support Hugo Villeneuve
2025-06-04 14:53 ` [PATCH v4 1/1] drm: renesas: rz-du: Implement MIPI DSI host transfers Hugo Villeneuve
2025-06-04 16:22   ` Chris Brandt
2025-06-05  8:18   ` Biju Das
2025-06-05 13:38     ` Hugo Villeneuve
2025-06-05 13:43       ` Biju Das
2025-06-09  6:08 ` [PATCH v4 0/1] drm: rcar-du: rzg2l_mipi_dsi: add MIPI DSI command support Biju Das

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).