Subject: [PATCH v4 0/5] drm/tiny: panel-mipi-dbi: Support 18 bits per color RGB666

Hi,

In this version I've fixed up a commit message that I had forgotten to
write before sending and improved a struct member name.

See version 1 of the patchset for the full cover letter.

Signed-off-by: Noralf Trønnes <[email protected]>
---
Changes in v4:
- Expand the commit message (Dmitry)
- s/emulation_format/pixel_format/ (Dmitry)
- Link to v3: https://lore.kernel.org/r/[email protected]

Changes in v3:
- Added r-b's to patch 1 and 5
- Link to v2: https://lore.kernel.org/r/[email protected]

Changes in v2:
- binding: Use 'default: r5g6b5' (Rob)
- Link to v1: https://lore.kernel.org/r/[email protected]

---
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 <[email protected]>




Subject: [PATCH v4 3/5] drm/mipi-dbi: Make bits per word configurable for pixel transfers

From: Noralf Trønnes <[email protected]>

MIPI DCS write/set commands have 8 bit parameters except for the
write_memory commands where it depends on the pixel format.
drm_mipi_dbi does currently only support RGB565 which is 16-bit and it
has to make sure that the pixels enters the SPI bus in big endian format
since the MIPI DBI spec doesn't have support for little endian.

drm_mipi_dbi is optimized for DBI interface option 3 which means that the
16-bit bytes are swapped by the upper layer if the SPI bus does not
support 16 bits per word, signified by the swap_bytes member.

In order to support both 16-bit and 24-bit pixel transfers we need a way
to tell the DBI command layer the format of the buffer. Add a
write_memory_bpw member that the upper layer can use to tell how many
bits per word to use for the SPI transfer.

v4:
- Expand the commit message (Dmitry)

Signed-off-by: Noralf Trønnes <[email protected]>
---
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.1



Subject: [PATCH v4 1/5] dt-bindings: display: panel: mipi-dbi-spi: Add a pixel format property

From: Noralf Trønnes <[email protected]>

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)

Reviewed-by: Rob Herring (Arm) <[email protected]>
Signed-off-by: Noralf Trønnes <[email protected]>
---
.../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.1



Subject: [PATCH v4 5/5] drm/tiny: panel-mipi-dbi: Support the pixel format property

From: Noralf Trønnes <[email protected]>

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.

Reviewed-by: Neil Armstrong <[email protected]>
Signed-off-by: Noralf Trønnes <[email protected]>
---
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.1



2024-06-04 13:45:10

by Dmitry Baryshkov

[permalink] [raw]
Subject: Re: [PATCH v4 3/5] drm/mipi-dbi: Make bits per word configurable for pixel transfers

On Tue, Jun 04, 2024 at 03:20:30PM +0200, Noralf Tr?nnes via B4 Relay wrote:
> From: Noralf Tr?nnes <[email protected]>
>
> MIPI DCS write/set commands have 8 bit parameters except for the
> write_memory commands where it depends on the pixel format.
> drm_mipi_dbi does currently only support RGB565 which is 16-bit and it
> has to make sure that the pixels enters the SPI bus in big endian format
> since the MIPI DBI spec doesn't have support for little endian.
>
> drm_mipi_dbi is optimized for DBI interface option 3 which means that the
> 16-bit bytes are swapped by the upper layer if the SPI bus does not
> support 16 bits per word, signified by the swap_bytes member.
>
> In order to support both 16-bit and 24-bit pixel transfers we need a way
> to tell the DBI command layer the format of the buffer. Add a
> write_memory_bpw member that the upper layer can use to tell how many
> bits per word to use for the SPI transfer.
>
> v4:
> - Expand the commit message (Dmitry)
>
> Signed-off-by: Noralf Tr?nnes <[email protected]>
> ---
> drivers/gpu/drm/drm_mipi_dbi.c | 14 ++++++++++----
> include/drm/drm_mipi_dbi.h | 5 +++++
> 2 files changed, 15 insertions(+), 4 deletions(-)
>

Reviewed-by: Dmitry Baryshkov <[email protected]>


--
With best wishes
Dmitry

Subject: [PATCH v4 4/5] drm/mipi-dbi: Add support for DRM_FORMAT_RGB888

From: Noralf Trønnes <[email protected]>

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.

v4:
- s/emulation_format/pixel_format/ (Dmitry)

Signed-off-by: Noralf Trønnes <[email protected]>
---
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..1661190c29a2 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->pixel_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->pixel_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->pixel_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..f45f9612c0bc 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;

+ /**
+ * @pixel_format: Native pixel format (DRM_FORMAT\_\*)
+ */
+ u32 pixel_format;
+
/**
* @tx_buf: Buffer used for transfer (copy clip rect area)
*/

--
2.45.1



Subject: [PATCH v4 2/5] drm/mipi-dbi: Remove mipi_dbi_machine_little_endian()

From: Noralf Trønnes <[email protected]>

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.

Reviewed-by: Dmitry Baryshkov <[email protected]>
Signed-off-by: Noralf Trønnes <[email protected]>
---
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.1



2024-06-04 14:18:16

by Dmitry Baryshkov

[permalink] [raw]
Subject: Re: [PATCH v4 4/5] drm/mipi-dbi: Add support for DRM_FORMAT_RGB888

On Tue, Jun 04, 2024 at 03:20:31PM +0200, Noralf Tr?nnes via B4 Relay wrote:
> From: Noralf Tr?nnes <[email protected]>
>
> 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.
>
> v4:
> - s/emulation_format/pixel_format/ (Dmitry)
>
> Signed-off-by: Noralf Tr?nnes <[email protected]>
> ---
> drivers/gpu/drm/drm_mipi_dbi.c | 29 +++++++++++++++++++++++++----
> include/drm/drm_mipi_dbi.h | 5 +++++
> 2 files changed, 30 insertions(+), 4 deletions(-)
>

Reviewed-by: Dmitry Baryshkov <[email protected]>


--
With best wishes
Dmitry