Browse Source

drivers: display: uc81xx: convert to MIPI DBI API

Convert UC81XX display to use MIPI DBI API, as this display uses a SPI
3/4 wire bus. In tree shields using this driver have also had their
devicetrees updated to use the new MIPI DBI SPI driver

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
pull/73686/head
Daniel DeGrasse 1 year ago committed by Alberto Escolar
parent
commit
9fdaf43e79
  1. 146
      boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2-p.overlay
  2. 36
      boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2.overlay
  3. 36
      boards/shields/waveshare_epaper/waveshare_epaper_gdew075t7.overlay
  4. 2
      drivers/display/Kconfig.uc81xx
  5. 114
      drivers/display/uc81xx.c
  6. 21
      dts/bindings/display/ultrachip,uc81xx-common.yaml

146
boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2-p.overlay

@ -8,87 +8,93 @@ @@ -8,87 +8,93 @@
/ {
chosen {
zephyr,display = &uc8176_waveshare_epaper_gdew042t2-p;
zephyr,display = &uc8176_waveshare_epaper_gdew042t2_p;
};
};
&arduino_spi {
/*
* GoodDisplay GDEW042T2 with fast partial refresh. Based on
* configuration from GoodDisplay's Arduino example.
*/
uc8176_waveshare_epaper_gdew042t2-p: uc8176@0 {
compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176";
spi-max-frequency = <4000000>;
reg = <0>;
width = <400>;
height = <300>;
dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */
mipi_dbi_waveshare_epaper_gdew042t2-p {
compatible = "zephyr,mipi-dbi-spi";
spi-dev = <&arduino_spi>;
dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */
reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */
busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */
write-only;
#address-cells = <1>;
#size-cells = <0>;
softstart = [ 17 17 17 ];
/*
* GoodDisplay GDEW042T2 with fast partial refresh. Based on
* configuration from GoodDisplay's Arduino example.
*/
uc8176_waveshare_epaper_gdew042t2_p: uc8176@0 {
compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176";
mipi-max-frequency = <4000000>;
reg = <0>;
width = <400>;
height = <300>;
busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */
full {
cdi = <0x07>;
};
softstart = [ 17 17 17 ];
full {
cdi = <0x07>;
};
partial {
pwr = [ 03 02 2b 2b ];
cdi = <0x07>;
pll = <0x3c>;
vdcs = <0x08>;
partial {
pwr = [ 03 02 2b 2b ];
cdi = <0x07>;
pll = <0x3c>;
vdcs = <0x08>;
lutc = [
00 01 0E 00 00 01
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00
];
lutc = [
00 01 0E 00 00 01
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00
];
lutww = [
00 01 0E 00 00 01
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
];
lutww = [
00 01 0E 00 00 01
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
];
lutkw = [
20 01 0E 00 00 01
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
];
lutkw = [
20 01 0E 00 00 01
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
];
lutwk = [
10 01 0E 00 00 01
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
];
lutwk = [
10 01 0E 00 00 01
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
];
lutkk = [
00 01 0E 00 00 01
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
];
lutkk = [
00 01 0E 00 00 01
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
];
};
};
};
};

36
boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2.overlay

@ -9,25 +9,31 @@ @@ -9,25 +9,31 @@
chosen {
zephyr,display = &uc8176_waveshare_epaper_gdew042t2;
};
};
&arduino_spi {
uc8176_waveshare_epaper_gdew042t2: uc8176@0 {
compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176";
spi-max-frequency = <4000000>;
reg = <0>;
width = <400>;
height = <300>;
dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */
mipi_dbi_waveshare_epaper_gdew042t2 {
compatible = "zephyr,mipi-dbi-spi";
spi-dev = <&arduino_spi>;
dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */
reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */
busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */
write-only;
#address-cells = <1>;
#size-cells = <0>;
uc8176_waveshare_epaper_gdew042t2: uc8176@0 {
compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176";
mipi-max-frequency = <4000000>;
reg = <0>;
width = <400>;
height = <300>;
busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */
softstart = [17 17 17];
softstart = [17 17 17];
full {
pwr = [03 00 26 26 09];
cdi = <0xd7>;
tcon = <0x22>;
full {
pwr = [03 00 26 26 09];
cdi = <0xd7>;
tcon = <0x22>;
};
};
};
};

36
boards/shields/waveshare_epaper/waveshare_epaper_gdew075t7.overlay

@ -10,25 +10,31 @@ @@ -10,25 +10,31 @@
chosen {
zephyr,display = &uc8179_waveshare_epaper_gdew075t7;
};
};
&arduino_spi {
uc8179_waveshare_epaper_gdew075t7: uc8179@0 {
compatible = "gooddisplay,gdew075t7", "ultrachip,uc8179";
spi-max-frequency = <4000000>;
reg = <0>;
width = <800>;
height = <480>;
dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */
mipi_dbi_waveshare_epaper_gdew075t7 {
compatible = "zephyr,mipi-dbi-spi";
spi-dev = <&arduino_spi>;
dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */
reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */
busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */
write-only;
#address-cells = <1>;
#size-cells = <0>;
uc8179_waveshare_epaper_gdew075t7: uc8179@0 {
compatible = "gooddisplay,gdew075t7", "ultrachip,uc8179";
mipi-max-frequency = <4000000>;
reg = <0>;
width = <800>;
height = <480>;
busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */
softstart = [17 17 17 17];
softstart = [17 17 17 17];
full {
pwr = [07 07 3f 3f];
cdi = <07>;
tcon = <0x22>;
full {
pwr = [07 07 3f 3f];
cdi = <07>;
tcon = <0x22>;
};
};
};
};

2
drivers/display/Kconfig.uc81xx

@ -7,6 +7,6 @@ config UC81XX @@ -7,6 +7,6 @@ config UC81XX
bool "UltraChip UC81xx compatible display controller driver"
default y
depends on DT_HAS_ULTRACHIP_UC8175_ENABLED || DT_HAS_ULTRACHIP_UC8176_ENABLED || DT_HAS_ULTRACHIP_UC8179_ENABLED
select SPI
select MIPI_DBI
help
Enable driver for UC81xx compatible controller.

114
drivers/display/uc81xx.c

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
/*
* Copyright (c) 2022 Andreas Sandberg
* Copyright (c) 2020 PHYTEC Messtechnik GmbH
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -10,7 +11,7 @@ @@ -10,7 +11,7 @@
#include <zephyr/init.h>
#include <zephyr/drivers/display.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/drivers/mipi_dbi.h>
#include <zephyr/sys/byteorder.h>
#include "uc81xx_regs.h"
@ -75,10 +76,9 @@ struct uc81xx_quirks { @@ -75,10 +76,9 @@ struct uc81xx_quirks {
struct uc81xx_config {
const struct uc81xx_quirks *quirks;
struct spi_dt_spec bus;
struct gpio_dt_spec dc_gpio;
const struct device *mipi_dev;
const struct mipi_dbi_config dbi_config;
struct gpio_dt_spec busy_gpio;
struct gpio_dt_spec reset_gpio;
uint16_t height;
uint16_t width;
@ -110,39 +110,13 @@ static inline int uc81xx_write_cmd(const struct device *dev, uint8_t cmd, @@ -110,39 +110,13 @@ static inline int uc81xx_write_cmd(const struct device *dev, uint8_t cmd,
const uint8_t *data, size_t len)
{
const struct uc81xx_config *config = dev->config;
struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)};
struct spi_buf_set buf_set = {.buffers = &buf, .count = 1};
int err;
uc81xx_busy_wait(dev);
err = gpio_pin_set_dt(&config->dc_gpio, 1);
if (err < 0) {
return err;
}
err = spi_write_dt(&config->bus, &buf_set);
if (err < 0) {
goto spi_out;
}
if (data != NULL) {
buf.buf = (void *)data;
buf.len = len;
err = gpio_pin_set_dt(&config->dc_gpio, 0);
if (err < 0) {
goto spi_out;
}
err = spi_write_dt(&config->bus, &buf_set);
if (err < 0) {
goto spi_out;
}
}
spi_out:
spi_release_dt(&config->bus);
err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config,
cmd, data, len);
mipi_dbi_release(config->mipi_dev, &config->dbi_config);
return err;
}
@ -151,43 +125,42 @@ static inline int uc81xx_write_cmd_pattern(const struct device *dev, @@ -151,43 +125,42 @@ static inline int uc81xx_write_cmd_pattern(const struct device *dev,
uint8_t pattern, size_t len)
{
const struct uc81xx_config *config = dev->config;
struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)};
struct spi_buf_set buf_set = {.buffers = &buf, .count = 1};
struct display_buffer_descriptor mipi_desc;
int err;
uint8_t data[64];
uc81xx_busy_wait(dev);
err = gpio_pin_set_dt(&config->dc_gpio, 1);
err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config,
cmd, NULL, 0);
if (err < 0) {
return err;
}
err = spi_write_dt(&config->bus, &buf_set);
if (err < 0) {
goto spi_out;
}
err = gpio_pin_set_dt(&config->dc_gpio, 0);
if (err < 0) {
goto spi_out;
}
/*
* MIPI display write API requires a display buffer descriptor.
* Create one that describes the buffer we are writing
*/
mipi_desc.height = 1;
memset(data, pattern, sizeof(data));
while (len) {
buf.buf = data;
buf.len = MIN(len, sizeof(data));
mipi_desc.buf_size = mipi_desc.width = mipi_desc.pitch =
MIN(len, sizeof(data));
err = spi_write_dt(&config->bus, &buf_set);
err = mipi_dbi_write_display(config->mipi_dev,
&config->dbi_config,
data, &mipi_desc,
PIXEL_FORMAT_MONO10);
if (err < 0) {
goto spi_out;
goto out;
}
len -= buf.len;
len -= mipi_desc.buf_size;
}
spi_out:
spi_release_dt(&config->bus);
out:
mipi_dbi_release(config->mipi_dev, &config->dbi_config);
return err;
}
@ -544,9 +517,7 @@ static int uc81xx_controller_init(const struct device *dev) @@ -544,9 +517,7 @@ static int uc81xx_controller_init(const struct device *dev)
const struct uc81xx_config *config = dev->config;
struct uc81xx_data *data = dev->data;
gpio_pin_set_dt(&config->reset_gpio, 1);
k_sleep(K_MSEC(UC81XX_RESET_DELAY));
gpio_pin_set_dt(&config->reset_gpio, 0);
mipi_dbi_reset(config->mipi_dev, UC81XX_RESET_DELAY);
k_sleep(K_MSEC(UC81XX_RESET_DELAY));
uc81xx_busy_wait(dev);
@ -570,26 +541,11 @@ static int uc81xx_init(const struct device *dev) @@ -570,26 +541,11 @@ static int uc81xx_init(const struct device *dev)
LOG_DBG("");
if (!spi_is_ready_dt(&config->bus)) {
LOG_ERR("SPI bus %s not ready", config->bus.bus->name);
return -ENODEV;
}
if (!gpio_is_ready_dt(&config->reset_gpio)) {
LOG_ERR("Reset GPIO device not ready");
return -ENODEV;
}
gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE);
if (!gpio_is_ready_dt(&config->dc_gpio)) {
LOG_ERR("DC GPIO device not ready");
if (!device_is_ready(config->mipi_dev)) {
LOG_ERR("MIPI device not ready");
return -ENODEV;
}
gpio_pin_configure_dt(&config->dc_gpio, GPIO_OUTPUT_INACTIVE);
if (!gpio_is_ready_dt(&config->busy_gpio)) {
LOG_ERR("Busy GPIO device not ready");
return -ENODEV;
@ -816,12 +772,14 @@ static const struct display_driver_api uc81xx_driver_api = { @@ -816,12 +772,14 @@ static const struct display_driver_api uc81xx_driver_api = {
\
static const struct uc81xx_config uc81xx_cfg_ ## n = { \
.quirks = quirks_ptr, \
.bus = SPI_DT_SPEC_GET(n, \
SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \
SPI_LOCK_ON, \
0), \
.reset_gpio = GPIO_DT_SPEC_GET(n, reset_gpios), \
.dc_gpio = GPIO_DT_SPEC_GET(n, dc_gpios), \
.mipi_dev = DEVICE_DT_GET(DT_PARENT(n)), \
.dbi_config = { \
.mode = MIPI_DBI_MODE_SPI_4WIRE, \
.config = MIPI_DBI_SPI_CONFIG_DT(n, \
SPI_OP_MODE_MASTER | \
SPI_LOCK_ON | SPI_WORD_SET(8), \
0), \
}, \
.busy_gpio = GPIO_DT_SPEC_GET(n, busy_gpios), \
\
.height = DT_PROP(n, height), \

21
dts/bindings/display/ultrachip,uc81xx-common.yaml

@ -1,30 +1,13 @@ @@ -1,30 +1,13 @@
# Copyright (c) 2022 Andreas Sandberg
# Copyright (c) 2020, Phytec Messtechnik GmbH
# Copyright 2024 NXP
# SPDX-License-Identifier: Apache-2.0
description: UltraChip UC81xx EPD display controller common properties
include: [spi-device.yaml, display-controller.yaml]
include: [mipi-dbi-spi-device.yaml, display-controller.yaml]
properties:
reset-gpios:
type: phandle-array
required: true
description: RESET pin.
The RESET pin of UC81xx is active low.
If connected directly the MCU pin should be configured
as active low.
dc-gpios:
type: phandle-array
required: true
description: DC pin.
The DC pin of UC81xx is active low (transmission command byte).
If connected directly the MCU pin should be configured
as active low.
busy-gpios:
type: phandle-array
required: true

Loading…
Cancel
Save