dri-devel Archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/5] drm/tiny: panel-mipi-dbi: Support 18 bits per color RGB666
@ 2024-05-12 15:25 Noralf Trønnes via B4 Relay
  2024-05-12 15:25 ` [PATCH v2 1/5] dt-bindings: display: panel: mipi-dbi-spi: Add a pixel format property Noralf Trønnes via B4 Relay
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Noralf Trønnes via B4 Relay @ 2024-05-12 15:25 UTC (permalink / raw
  To: Neil Armstrong, Jessica Zhang, Sam Ravnborg, David Airlie,
	Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: dri-devel, devicetree, linux-kernel, Kamlesh Gurudasani,
	Tommaso Merciai, Noralf Trønnes

Hi,

To my suprise I have discovered that the MIPI DBI specification does only
list RGB111 as a pixel format for the Serial Interface (Type C).

For the parallel interface type (Type A and B) it lists: RGB332, RGB444,
RGB565, RGB666 and RGB888.

I have never read the specification closely enough to discover this always
assuming that the datasheets for the various MIPI DBI compatible
controllers I've looked at over the years did follow the specification
when they supported RGB565 and RGB666 on the serial interface.

So it is quite clear that the industry has chosen to extend the standard
and provide support for more pixel formats over the serial interface.

drm_mipi_dbi and its predecessor fbtft support only RGB565 over SPI since
RGB666 uses 3 bytes per pixel instead of 2 bytes, severly impacting the
framerate.

The reason I started to look at this is that there seem to be an increase
in cheap SPI displays that is based on the ILI9488 controller. The
datasheet for this controller states that it supports RGB565, but
experience[1] shows that this is not true and that the controller only
supports RGB666 over SPI.

I have known for some time that the ILI9486 controller does not support
RGB565 over SPI, it only supports RGB111 and RGB666. Some display
breakoutboard manufacturers have solved this by putting a shift register
in front of the parallel bus on this controller in order to support
RGB565. This requires some custom code when writing to the SPI bus as
shown in the tiny/ili9486.c driver. The downside is that these displays
are really slow due to the slow shift registers used.

This patchset documents the defacto industry standard wrt pixel formats
over SPI and adds support for RGB666 in the panel-mipi-dbi driver.

There have been two previous attempts to add a DRM driver for
ili9488[2][3]. The panel-mipi-dbi driver is a generic MIPI DBI driver
supporting controller initialization via a firmware file and with the help
of this patchset it will support ILI9488 based SPI displays.

[1] https://github.com/notro/panel-mipi-dbi/issues/2#issuecomment-2016857690
[2] https://lore.kernel.org/dri-devel/cover.1592055494.git.kamlesh.gurudasani@gmail.com/
[3] https://lore.kernel.org/dri-devel/20221018164532.1705215-1-tommaso.merciai@amarulasolutions.com/

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
Changes in v2:
- binding: Use 'default: r5g6b5' (Rob)
- Link to v1: https://lore.kernel.org/r/20240507-panel-mipi-dbi-rgb666-v1-0-6799234afa3e@tronnes.org

---
Noralf Trønnes (5):
      dt-bindings: display: panel: mipi-dbi-spi: Add a pixel format property
      drm/mipi-dbi: Remove mipi_dbi_machine_little_endian()
      drm/mipi-dbi: Make bits per word configurable for pixel transfers
      drm/mipi-dbi: Add support for DRM_FORMAT_RGB888
      drm/tiny: panel-mipi-dbi: Support the pixel format property

 .../bindings/display/panel/panel-mipi-dbi-spi.yaml | 30 +++++++++
 drivers/gpu/drm/drm_mipi_dbi.c                     | 76 +++++++++++++++-------
 drivers/gpu/drm/tiny/panel-mipi-dbi.c              | 55 +++++++++++++++-
 include/drm/drm_mipi_dbi.h                         | 10 +++
 4 files changed, 147 insertions(+), 24 deletions(-)
---
base-commit: 0209df3b4731516fe77638bfc52ba2e9629c67cd
change-id: 20240405-panel-mipi-dbi-rgb666-4e033787d6c9

Best regards,
-- 
Noralf Trønnes <noralf@tronnes.org>



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

* [PATCH v2 1/5] dt-bindings: display: panel: mipi-dbi-spi: Add a pixel format property
  2024-05-12 15:25 [PATCH v2 0/5] drm/tiny: panel-mipi-dbi: Support 18 bits per color RGB666 Noralf Trønnes via B4 Relay
@ 2024-05-12 15:25 ` Noralf Trønnes via B4 Relay
  2024-05-20 15:57   ` Rob Herring (Arm)
  2024-05-12 15:25 ` [PATCH v2 2/5] drm/mipi-dbi: Remove mipi_dbi_machine_little_endian() Noralf Trønnes via B4 Relay
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Noralf Trønnes via B4 Relay @ 2024-05-12 15:25 UTC (permalink / raw
  To: Neil Armstrong, Jessica Zhang, Sam Ravnborg, David Airlie,
	Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: dri-devel, devicetree, linux-kernel, Kamlesh Gurudasani,
	Tommaso Merciai, Noralf Trønnes

From: Noralf Trønnes <noralf@tronnes.org>

The MIPI DBI 2.0 specification (2005) lists only two pixel formats for
the Type C Interface (SPI) and that is 3-bits/pixel RGB111 with
2 options for bit layout.

For Type A and B (parallel) the following formats are listed: RGB332,
RGB444, RGB565, RGB666 and RGB888 (some have 2 options for the bit layout).

Many MIPI DBI compatible controllers support all interface types on the
same chip and often the manufacturers have chosen to provide support for
the Type A/B interface pixel formats also on the Type C interface.

Some chips provide many pixel formats with optional bit layouts over SPI,
but the most common by far are RGB565 and RGB666. So even if the
specification doesn't list these formats for the Type C interface, the
industry has chosen to include them.

The MIPI DCS specification lists the standard commands that can be sent
over the MIPI DBI interface. The set_address_mode (36h) command has one
bit in the parameter that controls RGB/BGR order:
    This bit controls the RGB data latching order transferred from the
    peripheral’s frame memory to the display device.
This means that each supported RGB format also has a BGR variant.

Based on this rationale document the following pixel formats describing
the bit layout going over the wire:
- RGB111 (option 1): x2r1g1b1r1g1b1 (2 pixels per byte)
- BGR111 (option 1): x2b1g1r1b1g1r1 (2 pixels per byte)
- RGB111 (option 2): x1r1g1b1x1r1g1b1 (2 pixels per byte)
- BGR111 (option 2): x1b1g1r1x1b1g1r1 (2 pixels per byte)
- RGB565: r5g6b5 (2 bytes)
- BGR565: b5g6r5 (2 bytes)
- RGB666: r6x2g6x2b6x2 (3 bytes)
- BGR666: b6x2g6x2r6x2 (3 bytes)
(x: don't care)

v2:
- Use 'default: r5g6b5' (Rob)

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 .../bindings/display/panel/panel-mipi-dbi-spi.yaml | 30 ++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml b/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml
index e808215cb39e..8994549b4bff 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-mipi-dbi-spi.yaml
@@ -50,6 +50,12 @@ description: |
       |        Command or data         |
       |<D7><D6><D5><D4><D3><D2><D1><D0>|
 
+  The standard defines one pixel format for type C: RGB111. The industry
+  however has decided to provide the type A/B interface pixel formats also on
+  the Type C interface and most common among these are RGB565 and RGB666.
+  The MIPI DCS command set_address_mode (36h) has one bit that controls RGB/BGR
+  order. This gives each supported RGB format a BGR variant.
+
   The panel resolution is specified using the panel-timing node properties
   hactive (width) and vactive (height). The other mandatory panel-timing
   properties should be set to zero except clock-frequency which can be
@@ -90,6 +96,28 @@ properties:
 
   spi-3wire: true
 
+  format:
+    description: >
+      Pixel format in bit order as going on the wire:
+        * `x2r1g1b1r1g1b1` - RGB111, 2 pixels per byte
+        * `x2b1g1r1b1g1r1` - BGR111, 2 pixels per byte
+        * `x1r1g1b1x1r1g1b1` - RGB111, 2 pixels per byte
+        * `x1b1g1r1x1b1g1r1` - BGR111, 2 pixels per byte
+        * `r5g6b5` - RGB565, 2 bytes
+        * `b5g6r5` - BGR565, 2 bytes
+        * `r6x2g6x2b6x2` - RGB666, 3 bytes
+        * `b6x2g6x2r6x2` - BGR666, 3 bytes
+    enum:
+      - x2r1g1b1r1g1b1
+      - x2b1g1r1b1g1r1
+      - x1r1g1b1x1r1g1b1
+      - x1b1g1r1x1b1g1r1
+      - r5g6b5
+      - b5g6r5
+      - r6x2g6x2b6x2
+      - b6x2g6x2r6x2
+    default: r5g6b5
+
 required:
   - compatible
   - reg
@@ -116,6 +144,8 @@ examples:
             reset-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
             write-only;
 
+            format = "r5g6b5";
+
             backlight = <&backlight>;
 
             width-mm = <35>;

-- 
2.45.0



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

* [PATCH v2 2/5] drm/mipi-dbi: Remove mipi_dbi_machine_little_endian()
  2024-05-12 15:25 [PATCH v2 0/5] drm/tiny: panel-mipi-dbi: Support 18 bits per color RGB666 Noralf Trønnes via B4 Relay
  2024-05-12 15:25 ` [PATCH v2 1/5] dt-bindings: display: panel: mipi-dbi-spi: Add a pixel format property Noralf Trønnes via B4 Relay
@ 2024-05-12 15:25 ` Noralf Trønnes via B4 Relay
  2024-05-12 15:25 ` [PATCH v2 3/5] drm/mipi-dbi: Make bits per word configurable for pixel transfers Noralf Trønnes via B4 Relay
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Noralf Trønnes via B4 Relay @ 2024-05-12 15:25 UTC (permalink / raw
  To: Neil Armstrong, Jessica Zhang, Sam Ravnborg, David Airlie,
	Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: dri-devel, devicetree, linux-kernel, Kamlesh Gurudasani,
	Tommaso Merciai, Noralf Trønnes

From: Noralf Trønnes <noralf@tronnes.org>

mipi_dbi_machine_little_endian() should really have been called
mipi_dbi_framebuffer_little_endian() because that's the function it
performs. When I added support for these SPI displays I thought that the
framebuffers on big endian machines were also big endian, but I have
later learned that this is not the case. There's a bit in the fourcc code
that controls this: DRM_FORMAT_BIG_ENDIAN.

Just remove the function to avoid confusion. We can add big endian support
later should the need arise and we have hardware to test on.

Instead of just amending the docs, expand it to explain the endianness
handling.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_mipi_dbi.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index daac649aabdb..fa8aba6dc81c 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -824,15 +824,6 @@ u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len)
 }
 EXPORT_SYMBOL(mipi_dbi_spi_cmd_max_speed);
 
-static bool mipi_dbi_machine_little_endian(void)
-{
-#if defined(__LITTLE_ENDIAN)
-	return true;
-#else
-	return false;
-#endif
-}
-
 /*
  * MIPI DBI Type C Option 1
  *
@@ -855,7 +846,7 @@ static int mipi_dbi_spi1e_transfer(struct mipi_dbi *dbi, int dc,
 				   const void *buf, size_t len,
 				   unsigned int bpw)
 {
-	bool swap_bytes = (bpw == 16 && mipi_dbi_machine_little_endian());
+	bool swap_bytes = (bpw == 16);
 	size_t chunk, max_chunk = dbi->tx_buf9_len;
 	struct spi_device *spi = dbi->spi;
 	struct spi_transfer tr = {
@@ -1004,7 +995,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc,
 		size_t chunk = min(len, max_chunk);
 		unsigned int i;
 
-		if (bpw == 16 && mipi_dbi_machine_little_endian()) {
+		if (bpw == 16) {
 			for (i = 0; i < (chunk * 2); i += 2) {
 				dst16[i]     = *src16 >> 8;
 				dst16[i + 1] = *src16++ & 0xFF;
@@ -1218,11 +1209,23 @@ static int mipi_dbi_typec3_command(struct mipi_dbi *dbi, u8 *cmd,
  * If @dc is set, a Type C Option 3 interface is assumed, if not
  * Type C Option 1.
  *
- * If the SPI master driver doesn't support the necessary bits per word,
- * the following transformation is used:
+ * If the command is %MIPI_DCS_WRITE_MEMORY_START and the pixel format is RGB565, endianness has
+ * to be taken into account. The MIPI DBI serial interface is big endian and framebuffers are
+ * assumed stored in memory as little endian (%DRM_FORMAT_BIG_ENDIAN is not supported).
  *
- * - 9-bit: reorder buffer as 9x 8-bit words, padded with no-op command.
- * - 16-bit: if big endian send as 8-bit, if little endian swap bytes
+ * This is how endianness is handled:
+ *
+ * Option 1 (D/C as a bit): The buffer is sent on the wire byte by byte so the 16-bit buffer is
+ *                          byteswapped before transfer.
+ *
+ * Option 3 (D/C as a gpio): If the SPI controller supports 16 bits per word the buffer can be
+ *                           sent as-is. If not the caller is responsible for swapping the bytes
+ *                           before calling mipi_dbi_command_buf() and the buffer is sent 8 bpw.
+ *
+ * This handling is optimised for %DRM_FORMAT_RGB565 framebuffers.
+ *
+ * If the interface is Option 1 and the SPI controller doesn't support 9 bits per word,
+ * the buffer is sent as 9x 8-bit words, padded with MIPI DCS no-op commands if necessary.
  *
  * Returns:
  * Zero on success, negative error code on failure.
@@ -1257,7 +1260,7 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi,
 	if (dc) {
 		dbi->command = mipi_dbi_typec3_command;
 		dbi->dc = dc;
-		if (mipi_dbi_machine_little_endian() && !spi_is_bpw_supported(spi, 16))
+		if (!spi_is_bpw_supported(spi, 16))
 			dbi->swap_bytes = true;
 	} else {
 		dbi->command = mipi_dbi_typec1_command;

-- 
2.45.0



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

* [PATCH v2 3/5] drm/mipi-dbi: Make bits per word configurable for pixel transfers
  2024-05-12 15:25 [PATCH v2 0/5] drm/tiny: panel-mipi-dbi: Support 18 bits per color RGB666 Noralf Trønnes via B4 Relay
  2024-05-12 15:25 ` [PATCH v2 1/5] dt-bindings: display: panel: mipi-dbi-spi: Add a pixel format property Noralf Trønnes via B4 Relay
  2024-05-12 15:25 ` [PATCH v2 2/5] drm/mipi-dbi: Remove mipi_dbi_machine_little_endian() Noralf Trønnes via B4 Relay
@ 2024-05-12 15:25 ` Noralf Trønnes via B4 Relay
  2024-05-12 15:25 ` [PATCH v2 4/5] drm/mipi-dbi: Add support for DRM_FORMAT_RGB888 Noralf Trønnes via B4 Relay
  2024-05-12 15:25 ` [PATCH v2 5/5] drm/tiny: panel-mipi-dbi: Support the pixel format property Noralf Trønnes via B4 Relay
  4 siblings, 0 replies; 8+ messages in thread
From: Noralf Trønnes via B4 Relay @ 2024-05-12 15:25 UTC (permalink / raw
  To: Neil Armstrong, Jessica Zhang, Sam Ravnborg, David Airlie,
	Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: dri-devel, devicetree, linux-kernel, Kamlesh Gurudasani,
	Tommaso Merciai, Noralf Trønnes

From: Noralf Trønnes <noralf@tronnes.org>

This prepares for supporting other pixel formats than RGB565.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_mipi_dbi.c | 14 ++++++++++----
 include/drm/drm_mipi_dbi.h     |  5 +++++
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index fa8aba6dc81c..77f8a828d6e0 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -1079,7 +1079,7 @@ static int mipi_dbi_typec1_command_read(struct mipi_dbi *dbi, u8 *cmd,
 static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd,
 				   u8 *parameters, size_t num)
 {
-	unsigned int bpw = (*cmd == MIPI_DCS_WRITE_MEMORY_START) ? 16 : 8;
+	unsigned int bpw = 8;
 	int ret;
 
 	if (mipi_dbi_command_is_read(dbi, *cmd))
@@ -1091,6 +1091,9 @@ static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd,
 	if (ret || !num)
 		return ret;
 
+	if (*cmd == MIPI_DCS_WRITE_MEMORY_START)
+		bpw = dbi->write_memory_bpw;
+
 	return mipi_dbi_spi1_transfer(dbi, 1, parameters, num, bpw);
 }
 
@@ -1184,8 +1187,8 @@ static int mipi_dbi_typec3_command(struct mipi_dbi *dbi, u8 *cmd,
 	if (ret || !num)
 		return ret;
 
-	if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !dbi->swap_bytes)
-		bpw = 16;
+	if (*cmd == MIPI_DCS_WRITE_MEMORY_START)
+		bpw = dbi->write_memory_bpw;
 
 	spi_bus_lock(spi->controller);
 	gpiod_set_value_cansleep(dbi->dc, 1);
@@ -1256,12 +1259,15 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi,
 
 	dbi->spi = spi;
 	dbi->read_commands = mipi_dbi_dcs_read_commands;
+	dbi->write_memory_bpw = 16;
 
 	if (dc) {
 		dbi->command = mipi_dbi_typec3_command;
 		dbi->dc = dc;
-		if (!spi_is_bpw_supported(spi, 16))
+		if (!spi_is_bpw_supported(spi, 16)) {
+			dbi->write_memory_bpw = 8;
 			dbi->swap_bytes = true;
+		}
 	} else {
 		dbi->command = mipi_dbi_typec1_command;
 		dbi->tx_buf9_len = SZ_16K;
diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h
index e8e0f8d39f3a..b36596efdcc3 100644
--- a/include/drm/drm_mipi_dbi.h
+++ b/include/drm/drm_mipi_dbi.h
@@ -56,6 +56,11 @@ struct mipi_dbi {
 	 */
 	struct spi_device *spi;
 
+	/**
+	 * @write_memory_bpw: Bits per word used on a MIPI_DCS_WRITE_MEMORY_START transfer
+	 */
+	unsigned int write_memory_bpw;
+
 	/**
 	 * @dc: Optional D/C gpio.
 	 */

-- 
2.45.0



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

* [PATCH v2 4/5] drm/mipi-dbi: Add support for DRM_FORMAT_RGB888
  2024-05-12 15:25 [PATCH v2 0/5] drm/tiny: panel-mipi-dbi: Support 18 bits per color RGB666 Noralf Trønnes via B4 Relay
                   ` (2 preceding siblings ...)
  2024-05-12 15:25 ` [PATCH v2 3/5] drm/mipi-dbi: Make bits per word configurable for pixel transfers Noralf Trønnes via B4 Relay
@ 2024-05-12 15:25 ` Noralf Trønnes via B4 Relay
  2024-05-12 15:25 ` [PATCH v2 5/5] drm/tiny: panel-mipi-dbi: Support the pixel format property Noralf Trønnes via B4 Relay
  4 siblings, 0 replies; 8+ messages in thread
From: Noralf Trønnes via B4 Relay @ 2024-05-12 15:25 UTC (permalink / raw
  To: Neil Armstrong, Jessica Zhang, Sam Ravnborg, David Airlie,
	Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: dri-devel, devicetree, linux-kernel, Kamlesh Gurudasani,
	Tommaso Merciai, Noralf Trønnes

From: Noralf Trønnes <noralf@tronnes.org>

DRM_FORMAT_RGB888 is 24 bits per pixel and it would be natural to send it
on the SPI bus using a 24 bits per word transfer. The problem with this
is that not all SPI controllers support 24 bpw.

Since DRM_FORMAT_RGB888 is stored in memory as little endian and the SPI
bus is big endian we use 8 bpw to always get the same pixel format on the
bus: b8g8r8.

The MIPI DCS specification lists the standard commands that can be sent
over the MIPI DBI interface. The set_address_mode (36h) command has one
bit in the parameter that controls RGB/BGR order. This means that the
controller can be configured to receive the pixel as BGR.

RGB888 is rarely supported on these controllers but RGB666 is very common.
All datasheets I have seen do at least support the pixel format option
where each color is sent as one byte and the 6 MSB's are used.

All this put together means that we can send each pixel as b8g8r8 and an
RGB666 capable controller sees this as b6x2g6x2r6x2.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/drm_mipi_dbi.c | 29 +++++++++++++++++++++++++----
 include/drm/drm_mipi_dbi.h     |  5 +++++
 2 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 77f8a828d6e0..eb330676857c 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -206,6 +206,7 @@ int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *
 		      struct drm_rect *clip, bool swap,
 		      struct drm_format_conv_state *fmtcnv_state)
 {
+	struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
 	struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
 	struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst);
 	int ret;
@@ -222,8 +223,18 @@ int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *
 		else
 			drm_fb_memcpy(&dst_map, NULL, src, fb, clip);
 		break;
+	case DRM_FORMAT_RGB888:
+		drm_fb_memcpy(&dst_map, NULL, src, fb, clip);
+		break;
 	case DRM_FORMAT_XRGB8888:
-		drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, fmtcnv_state, swap);
+		switch (dbidev->emulation_format) {
+		case DRM_FORMAT_RGB565:
+			drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, fmtcnv_state, swap);
+			break;
+		case DRM_FORMAT_RGB888:
+			drm_fb_xrgb8888_to_rgb888(&dst_map, NULL, src, fb, clip, fmtcnv_state);
+			break;
+		}
 		break;
 	default:
 		drm_err_once(fb->dev, "Format is not supported: %p4cc\n",
@@ -260,9 +271,11 @@ static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb,
 	struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
 	unsigned int height = rect->y2 - rect->y1;
 	unsigned int width = rect->x2 - rect->x1;
+	const struct drm_format_info *dst_format;
 	struct mipi_dbi *dbi = &dbidev->dbi;
 	bool swap = dbi->swap_bytes;
 	int ret = 0;
+	size_t len;
 	bool full;
 	void *tr;
 
@@ -283,8 +296,13 @@ static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb,
 	mipi_dbi_set_window_address(dbidev, rect->x1, rect->x2 - 1, rect->y1,
 				    rect->y2 - 1);
 
-	ret = mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START, tr,
-				   width * height * 2);
+	if (fb->format->format == DRM_FORMAT_XRGB8888)
+		dst_format = drm_format_info(dbidev->emulation_format);
+	else
+		dst_format = fb->format;
+	len = drm_format_info_min_pitch(dst_format, 0, width) * height;
+
+	ret = mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START, tr, len);
 err_msg:
 	if (ret)
 		drm_err_once(fb->dev, "Failed to update display %d\n", ret);
@@ -572,7 +590,7 @@ static const uint32_t mipi_dbi_formats[] = {
  * has one fixed &drm_display_mode which is rotated according to @rotation.
  * This mode is used to set the mode config min/max width/height properties.
  *
- * Use mipi_dbi_dev_init() if you don't need custom formats.
+ * Use mipi_dbi_dev_init() if you want native RGB565 and emulated XRGB8888 format.
  *
  * Note:
  * Some of the helper functions expects RGB565 to be the default format and the
@@ -631,6 +649,9 @@ int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev,
 	drm->mode_config.min_height = dbidev->mode.vdisplay;
 	drm->mode_config.max_height = dbidev->mode.vdisplay;
 	dbidev->rotation = rotation;
+	dbidev->emulation_format = formats[0];
+	if (formats[0] == DRM_FORMAT_RGB888)
+		dbidev->dbi.write_memory_bpw = 8;
 
 	DRM_DEBUG_KMS("rotation = %u\n", rotation);
 
diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h
index b36596efdcc3..85bf19b98cee 100644
--- a/include/drm/drm_mipi_dbi.h
+++ b/include/drm/drm_mipi_dbi.h
@@ -101,6 +101,11 @@ struct mipi_dbi_dev {
 	 */
 	struct drm_display_mode mode;
 
+	/**
+	 * @emulation_format: Pixel format to use when emulating XRGB8888
+	 */
+	u32 emulation_format;
+
 	/**
 	 * @tx_buf: Buffer used for transfer (copy clip rect area)
 	 */

-- 
2.45.0



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

* [PATCH v2 5/5] drm/tiny: panel-mipi-dbi: Support the pixel format property
  2024-05-12 15:25 [PATCH v2 0/5] drm/tiny: panel-mipi-dbi: Support 18 bits per color RGB666 Noralf Trønnes via B4 Relay
                   ` (3 preceding siblings ...)
  2024-05-12 15:25 ` [PATCH v2 4/5] drm/mipi-dbi: Add support for DRM_FORMAT_RGB888 Noralf Trønnes via B4 Relay
@ 2024-05-12 15:25 ` Noralf Trønnes via B4 Relay
  2024-05-21  8:04   ` Neil Armstrong
  4 siblings, 1 reply; 8+ messages in thread
From: Noralf Trønnes via B4 Relay @ 2024-05-12 15:25 UTC (permalink / raw
  To: Neil Armstrong, Jessica Zhang, Sam Ravnborg, David Airlie,
	Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: dri-devel, devicetree, linux-kernel, Kamlesh Gurudasani,
	Tommaso Merciai, Noralf Trønnes

From: Noralf Trønnes <noralf@tronnes.org>

Add support for these pixel format property values:
- r5g6b5, RGB565
- b6x2g6x2r6x2, BGR666

BGR666 is presented to userspace as RGB888. The 2 LSB in each color
are discarded by the controller. The pixel is sent on the wire using
8 bits per word (little endian) so the controller sees it as BGR.

RGB565 is the default if the property is not present.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/gpu/drm/tiny/panel-mipi-dbi.c | 55 ++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
index f80a141fcf36..f3aa2abce314 100644
--- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
+++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
@@ -26,6 +26,49 @@
 
 #include <video/mipi_display.h>
 
+struct panel_mipi_dbi_format {
+	const char *name;
+	u32 fourcc;
+	unsigned int bpp;
+};
+
+static const struct panel_mipi_dbi_format panel_mipi_dbi_formats[] = {
+	{ "r5g6b5", DRM_FORMAT_RGB565, 16 },
+	{ "b6x2g6x2r6x2", DRM_FORMAT_RGB888, 24 },
+};
+
+static int panel_mipi_dbi_get_format(struct device *dev, u32 *formats, unsigned int *bpp)
+{
+	const char *format_name;
+	unsigned int i;
+	int ret;
+
+	formats[1] = DRM_FORMAT_XRGB8888;
+
+	ret = device_property_read_string(dev, "format", &format_name);
+	if (ret) {
+		/* Old Device Trees don't have this property */
+		formats[0] = DRM_FORMAT_RGB565;
+		*bpp = 16;
+		return 0;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(panel_mipi_dbi_formats); i++) {
+		const struct panel_mipi_dbi_format *format = &panel_mipi_dbi_formats[i];
+
+		if (strcmp(format_name, format->name))
+			continue;
+
+		formats[0] = format->fourcc;
+		*bpp = format->bpp;
+		return 0;
+	}
+
+	dev_err(dev, "Pixel format is not supported: '%s'\n", format_name);
+
+	return -EINVAL;
+}
+
 static const u8 panel_mipi_dbi_magic[15] = { 'M', 'I', 'P', 'I', ' ', 'D', 'B', 'I',
 					     0, 0, 0, 0, 0, 0, 0 };
 
@@ -276,6 +319,9 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
 	struct drm_device *drm;
 	struct mipi_dbi *dbi;
 	struct gpio_desc *dc;
+	unsigned int bpp;
+	size_t buf_size;
+	u32 formats[2];
 	int ret;
 
 	dbidev = devm_drm_dev_alloc(dev, &panel_mipi_dbi_driver, struct mipi_dbi_dev, drm);
@@ -323,7 +369,14 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
 	if (IS_ERR(dbidev->driver_private))
 		return PTR_ERR(dbidev->driver_private);
 
-	ret = mipi_dbi_dev_init(dbidev, &panel_mipi_dbi_pipe_funcs, &mode, 0);
+	ret = panel_mipi_dbi_get_format(dev, formats, &bpp);
+	if (ret)
+		return ret;
+
+	buf_size = DIV_ROUND_UP(mode.hdisplay * mode.vdisplay * bpp, 8);
+	ret = mipi_dbi_dev_init_with_formats(dbidev, &panel_mipi_dbi_pipe_funcs,
+					     formats, ARRAY_SIZE(formats),
+					     &mode, 0, buf_size);
 	if (ret)
 		return ret;
 

-- 
2.45.0



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

* Re: [PATCH v2 1/5] dt-bindings: display: panel: mipi-dbi-spi: Add a pixel format property
  2024-05-12 15:25 ` [PATCH v2 1/5] dt-bindings: display: panel: mipi-dbi-spi: Add a pixel format property Noralf Trønnes via B4 Relay
@ 2024-05-20 15:57   ` Rob Herring (Arm)
  0 siblings, 0 replies; 8+ messages in thread
From: Rob Herring (Arm) @ 2024-05-20 15:57 UTC (permalink / raw
  To: Noralf Trønnes
  Cc: Maarten Lankhorst, Daniel Vetter, Maxime Ripard, David Airlie,
	Jessica Zhang, Sam Ravnborg, linux-kernel, Thomas Zimmermann,
	Neil Armstrong, Krzysztof Kozlowski, Conor Dooley, dri-devel,
	devicetree, Tommaso Merciai, Kamlesh Gurudasani


On Sun, 12 May 2024 17:25:38 +0200, Noralf Trønnes wrote:
> The MIPI DBI 2.0 specification (2005) lists only two pixel formats for
> the Type C Interface (SPI) and that is 3-bits/pixel RGB111 with
> 2 options for bit layout.
> 
> For Type A and B (parallel) the following formats are listed: RGB332,
> RGB444, RGB565, RGB666 and RGB888 (some have 2 options for the bit layout).
> 
> Many MIPI DBI compatible controllers support all interface types on the
> same chip and often the manufacturers have chosen to provide support for
> the Type A/B interface pixel formats also on the Type C interface.
> 
> Some chips provide many pixel formats with optional bit layouts over SPI,
> but the most common by far are RGB565 and RGB666. So even if the
> specification doesn't list these formats for the Type C interface, the
> industry has chosen to include them.
> 
> The MIPI DCS specification lists the standard commands that can be sent
> over the MIPI DBI interface. The set_address_mode (36h) command has one
> bit in the parameter that controls RGB/BGR order:
>     This bit controls the RGB data latching order transferred from the
>     peripheral’s frame memory to the display device.
> This means that each supported RGB format also has a BGR variant.
> 
> Based on this rationale document the following pixel formats describing
> the bit layout going over the wire:
> - RGB111 (option 1): x2r1g1b1r1g1b1 (2 pixels per byte)
> - BGR111 (option 1): x2b1g1r1b1g1r1 (2 pixels per byte)
> - RGB111 (option 2): x1r1g1b1x1r1g1b1 (2 pixels per byte)
> - BGR111 (option 2): x1b1g1r1x1b1g1r1 (2 pixels per byte)
> - RGB565: r5g6b5 (2 bytes)
> - BGR565: b5g6r5 (2 bytes)
> - RGB666: r6x2g6x2b6x2 (3 bytes)
> - BGR666: b6x2g6x2r6x2 (3 bytes)
> (x: don't care)
> 
> v2:
> - Use 'default: r5g6b5' (Rob)
> 
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> ---
>  .../bindings/display/panel/panel-mipi-dbi-spi.yaml | 30 ++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


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

* Re: [PATCH v2 5/5] drm/tiny: panel-mipi-dbi: Support the pixel format property
  2024-05-12 15:25 ` [PATCH v2 5/5] drm/tiny: panel-mipi-dbi: Support the pixel format property Noralf Trønnes via B4 Relay
@ 2024-05-21  8:04   ` Neil Armstrong
  0 siblings, 0 replies; 8+ messages in thread
From: Neil Armstrong @ 2024-05-21  8:04 UTC (permalink / raw
  To: noralf, Jessica Zhang, Sam Ravnborg, David Airlie, Daniel Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: dri-devel, devicetree, linux-kernel, Kamlesh Gurudasani,
	Tommaso Merciai

On 12/05/2024 17:25, Noralf Trønnes via B4 Relay wrote:
> From: Noralf Trønnes <noralf@tronnes.org>
> 
> Add support for these pixel format property values:
> - r5g6b5, RGB565
> - b6x2g6x2r6x2, BGR666
> 
> BGR666 is presented to userspace as RGB888. The 2 LSB in each color
> are discarded by the controller. The pixel is sent on the wire using
> 8 bits per word (little endian) so the controller sees it as BGR.
> 
> RGB565 is the default if the property is not present.
> 
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> ---
>   drivers/gpu/drm/tiny/panel-mipi-dbi.c | 55 ++++++++++++++++++++++++++++++++++-
>   1 file changed, 54 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
> index f80a141fcf36..f3aa2abce314 100644
> --- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
> +++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
> @@ -26,6 +26,49 @@
>   
>   #include <video/mipi_display.h>
>   
> +struct panel_mipi_dbi_format {
> +	const char *name;
> +	u32 fourcc;
> +	unsigned int bpp;
> +};
> +
> +static const struct panel_mipi_dbi_format panel_mipi_dbi_formats[] = {
> +	{ "r5g6b5", DRM_FORMAT_RGB565, 16 },
> +	{ "b6x2g6x2r6x2", DRM_FORMAT_RGB888, 24 },
> +};
> +
> +static int panel_mipi_dbi_get_format(struct device *dev, u32 *formats, unsigned int *bpp)
> +{
> +	const char *format_name;
> +	unsigned int i;
> +	int ret;
> +
> +	formats[1] = DRM_FORMAT_XRGB8888;
> +
> +	ret = device_property_read_string(dev, "format", &format_name);
> +	if (ret) {
> +		/* Old Device Trees don't have this property */
> +		formats[0] = DRM_FORMAT_RGB565;
> +		*bpp = 16;
> +		return 0;
> +	}
> +
> +	for (i = 0; i < ARRAY_SIZE(panel_mipi_dbi_formats); i++) {
> +		const struct panel_mipi_dbi_format *format = &panel_mipi_dbi_formats[i];
> +
> +		if (strcmp(format_name, format->name))
> +			continue;
> +
> +		formats[0] = format->fourcc;
> +		*bpp = format->bpp;
> +		return 0;
> +	}
> +
> +	dev_err(dev, "Pixel format is not supported: '%s'\n", format_name);
> +
> +	return -EINVAL;
> +}
> +
>   static const u8 panel_mipi_dbi_magic[15] = { 'M', 'I', 'P', 'I', ' ', 'D', 'B', 'I',
>   					     0, 0, 0, 0, 0, 0, 0 };
>   
> @@ -276,6 +319,9 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
>   	struct drm_device *drm;
>   	struct mipi_dbi *dbi;
>   	struct gpio_desc *dc;
> +	unsigned int bpp;
> +	size_t buf_size;
> +	u32 formats[2];
>   	int ret;
>   
>   	dbidev = devm_drm_dev_alloc(dev, &panel_mipi_dbi_driver, struct mipi_dbi_dev, drm);
> @@ -323,7 +369,14 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
>   	if (IS_ERR(dbidev->driver_private))
>   		return PTR_ERR(dbidev->driver_private);
>   
> -	ret = mipi_dbi_dev_init(dbidev, &panel_mipi_dbi_pipe_funcs, &mode, 0);
> +	ret = panel_mipi_dbi_get_format(dev, formats, &bpp);
> +	if (ret)
> +		return ret;
> +
> +	buf_size = DIV_ROUND_UP(mode.hdisplay * mode.vdisplay * bpp, 8);
> +	ret = mipi_dbi_dev_init_with_formats(dbidev, &panel_mipi_dbi_pipe_funcs,
> +					     formats, ARRAY_SIZE(formats),
> +					     &mode, 0, buf_size);
>   	if (ret)
>   		return ret;
>   
> 

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

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

end of thread, other threads:[~2024-05-21  8:04 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-12 15:25 [PATCH v2 0/5] drm/tiny: panel-mipi-dbi: Support 18 bits per color RGB666 Noralf Trønnes via B4 Relay
2024-05-12 15:25 ` [PATCH v2 1/5] dt-bindings: display: panel: mipi-dbi-spi: Add a pixel format property Noralf Trønnes via B4 Relay
2024-05-20 15:57   ` Rob Herring (Arm)
2024-05-12 15:25 ` [PATCH v2 2/5] drm/mipi-dbi: Remove mipi_dbi_machine_little_endian() Noralf Trønnes via B4 Relay
2024-05-12 15:25 ` [PATCH v2 3/5] drm/mipi-dbi: Make bits per word configurable for pixel transfers Noralf Trønnes via B4 Relay
2024-05-12 15:25 ` [PATCH v2 4/5] drm/mipi-dbi: Add support for DRM_FORMAT_RGB888 Noralf Trønnes via B4 Relay
2024-05-12 15:25 ` [PATCH v2 5/5] drm/tiny: panel-mipi-dbi: Support the pixel format property Noralf Trønnes via B4 Relay
2024-05-21  8:04   ` Neil Armstrong

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 read-only IMAP folder(s) and NNTP newsgroup(s).