drivers: display: st7735r: convert to MIPI DBI API
Convert the ST7735R display to use the MIPI DBI API. Boards and overlays using this display are also updated. Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
parent
b8049b41ae
commit
13ae32e1c2
5 changed files with 124 additions and 158 deletions
|
@ -4,22 +4,26 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/mipi_dbi/mipi_dbi.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,display = &st7735r_st7735r_ada_160x128;
|
||||
};
|
||||
};
|
||||
|
||||
&arduino_spi {
|
||||
status = "okay";
|
||||
cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */
|
||||
mipi_dbi_st7735r_ada_160x128 {
|
||||
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 */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
st7735r_st7735r_ada_160x128: st7735r@0 {
|
||||
compatible = "sitronix,st7735r";
|
||||
spi-max-frequency = <20000000>;
|
||||
mipi-max-frequency = <20000000>;
|
||||
mipi-mode = <MIPI_DBI_MODE_SPI_4WIRE>;
|
||||
reg = <0>;
|
||||
cmd-data-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */
|
||||
reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */
|
||||
width = <160>;
|
||||
height = <128>;
|
||||
x-offset = <0>;
|
||||
|
@ -38,4 +42,10 @@
|
|||
gamctrp1 = [02 1c 07 12 37 32 29 2d 29 25 2b 39 00 01 03 10];
|
||||
gamctrn1 = [03 1d 07 06 2e 2c 29 2d 2e 2e 37 3f 00 00 02 10];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&arduino_spi {
|
||||
status = "okay";
|
||||
cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
#include <zephyr/dt-bindings/mipi_dbi/mipi_dbi.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
|
@ -65,6 +66,50 @@
|
|||
sw0 = &button_boot0;
|
||||
watchdog0 = &fwdgt;
|
||||
};
|
||||
|
||||
mipi_dbi {
|
||||
compatible = "zephyr,mipi-dbi-spi";
|
||||
reset-gpios = <&gpiob 1 GPIO_ACTIVE_LOW>;
|
||||
dc-gpios = <&gpiob 0 GPIO_ACTIVE_HIGH>;
|
||||
spi-dev = <&spi0>;
|
||||
write-only;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* longan nano has LCD with st7735s controller.
|
||||
* It can use with st7735r driver.
|
||||
*/
|
||||
lcd0: lcd@0 {
|
||||
compatible = "sitronix,st7735r";
|
||||
reg = <0>;
|
||||
status = "okay";
|
||||
width = <160>;
|
||||
height = <80>;
|
||||
inversion-on;
|
||||
rgb-is-inverted;
|
||||
x-offset = <1>;
|
||||
y-offset = <26>;
|
||||
pwctr1 = [62 02 04];
|
||||
pwctr2 = [C0];
|
||||
pwctr3 = [0D 00];
|
||||
pwctr4 = [8D 6A];
|
||||
pwctr5 = [8D EE];
|
||||
invctr = <3>;
|
||||
frmctr1 = [05 3A 3A];
|
||||
frmctr2 = [05 3A 3A];
|
||||
frmctr3 = [05 3A 3A 05 3A 3A];
|
||||
vmctr1 = <14>;
|
||||
gamctrp1 = [10 0E 02 03 0E 07 02 07 0A 12 27 37 00 0D 0E 10];
|
||||
gamctrn1 = [10 0E 03 03 0F 06 02 08 0A 13 26 36 00 0D 0E 10];
|
||||
colmod = <5>;
|
||||
madctl = <120>;
|
||||
caset = [00 01 00 a0];
|
||||
raset = [00 1a 00 69];
|
||||
|
||||
mipi-mode = <MIPI_DBI_MODE_SPI_4WIRE>;
|
||||
mipi-max-frequency = <4000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&gpioa {
|
||||
|
@ -109,41 +154,6 @@
|
|||
pinctrl-names = "default";
|
||||
|
||||
cs-gpios = <&gpiob 2 GPIO_ACTIVE_LOW>;
|
||||
|
||||
/* longan nano has LCD with st7735s controller.
|
||||
* It can use with st7735r driver.
|
||||
*/
|
||||
lcd0: lcd@0 {
|
||||
compatible = "sitronix,st7735r";
|
||||
reg = <0>;
|
||||
status = "okay";
|
||||
reset-gpios = <&gpiob 1 GPIO_ACTIVE_LOW>;
|
||||
cmd-data-gpios = <&gpiob 0 GPIO_ACTIVE_LOW>;
|
||||
width = <160>;
|
||||
height = <80>;
|
||||
inversion-on;
|
||||
rgb-is-inverted;
|
||||
x-offset = <1>;
|
||||
y-offset = <26>;
|
||||
pwctr1 = [62 02 04];
|
||||
pwctr2 = [C0];
|
||||
pwctr3 = [0D 00];
|
||||
pwctr4 = [8D 6A];
|
||||
pwctr5 = [8D EE];
|
||||
invctr = <3>;
|
||||
frmctr1 = [05 3A 3A];
|
||||
frmctr2 = [05 3A 3A];
|
||||
frmctr3 = [05 3A 3A 05 3A 3A];
|
||||
vmctr1 = <14>;
|
||||
gamctrp1 = [10 0E 02 03 0E 07 02 07 0A 12 27 37 00 0D 0E 10];
|
||||
gamctrn1 = [10 0E 03 03 0F 06 02 08 0A 13 26 36 00 0D 0E 10];
|
||||
colmod = <5>;
|
||||
madctl = <120>;
|
||||
caset = [00 01 00 a0];
|
||||
raset = [00 1a 00 69];
|
||||
|
||||
spi-max-frequency = <4000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
|
|
|
@ -7,6 +7,6 @@ config ST7735R
|
|||
bool "ST7735R/ST7735S display driver"
|
||||
default y
|
||||
depends on DT_HAS_SITRONIX_ST7735R_ENABLED
|
||||
select SPI
|
||||
select MIPI_DBI
|
||||
help
|
||||
Enable driver for ST7735R/ST7735S display driver.
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright (c) 2019 PHYTEC Messtechnik GmbH
|
||||
* Copyright (c) 2020 Endian Technologies AB
|
||||
* Copyright (c) 2020 Kim Bøndergaard <kim@fam-boendergaard.dk>
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -14,7 +15,7 @@
|
|||
#include "display_st7735r.h"
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#include <zephyr/drivers/mipi_dbi.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
@ -23,15 +24,14 @@
|
|||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(display_st7735r, CONFIG_DISPLAY_LOG_LEVEL);
|
||||
|
||||
#define ST7735R_RESET_TIME K_MSEC(1)
|
||||
#define ST7735R_RESET_TIME 1
|
||||
#define ST7735R_EXIT_SLEEP_TIME K_MSEC(120)
|
||||
|
||||
#define ST7735R_PIXEL_SIZE 2u
|
||||
|
||||
struct st7735r_config {
|
||||
struct spi_dt_spec bus;
|
||||
struct gpio_dt_spec cmd_data;
|
||||
struct gpio_dt_spec reset;
|
||||
const struct device *mipi_dev;
|
||||
const struct mipi_dbi_config dbi_config;
|
||||
uint16_t height;
|
||||
uint16_t width;
|
||||
uint8_t madctl;
|
||||
|
@ -68,38 +68,13 @@ static void st7735r_set_lcd_margins(const struct device *dev,
|
|||
data->y_offset = y_offset;
|
||||
}
|
||||
|
||||
static void st7735r_set_cmd(const struct device *dev, int is_cmd)
|
||||
{
|
||||
const struct st7735r_config *config = dev->config;
|
||||
|
||||
gpio_pin_set_dt(&config->cmd_data, is_cmd);
|
||||
}
|
||||
|
||||
static int st7735r_transmit_hold(const struct device *dev, uint8_t cmd,
|
||||
const uint8_t *tx_data, size_t tx_count)
|
||||
{
|
||||
const struct st7735r_config *config = dev->config;
|
||||
struct spi_buf tx_buf = { .buf = &cmd, .len = 1 };
|
||||
struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 };
|
||||
int ret;
|
||||
|
||||
st7735r_set_cmd(dev, 1);
|
||||
ret = spi_write_dt(&config->bus, &tx_bufs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (tx_data != NULL) {
|
||||
tx_buf.buf = (void *)tx_data;
|
||||
tx_buf.len = tx_count;
|
||||
st7735r_set_cmd(dev, 0);
|
||||
ret = spi_write_dt(&config->bus, &tx_bufs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return mipi_dbi_command_write(config->mipi_dev, &config->dbi_config,
|
||||
cmd, tx_data, tx_count);
|
||||
}
|
||||
|
||||
static int st7735r_transmit(const struct device *dev, uint8_t cmd,
|
||||
|
@ -109,7 +84,7 @@ static int st7735r_transmit(const struct device *dev, uint8_t cmd,
|
|||
int ret;
|
||||
|
||||
ret = st7735r_transmit_hold(dev, cmd, tx_data, tx_count);
|
||||
spi_release_dt(&config->bus);
|
||||
mipi_dbi_release(config->mipi_dev, &config->dbi_config);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -133,11 +108,8 @@ static int st7735r_reset_display(const struct device *dev)
|
|||
int ret;
|
||||
|
||||
LOG_DBG("Resetting display");
|
||||
if (config->reset.port != NULL) {
|
||||
gpio_pin_set_dt(&config->reset, 1);
|
||||
k_sleep(ST7735R_RESET_TIME);
|
||||
gpio_pin_set_dt(&config->reset, 0);
|
||||
} else {
|
||||
ret = mipi_dbi_reset(config->mipi_dev, ST7735R_RESET_TIME);
|
||||
if (ret != 0) {
|
||||
ret = st7735r_transmit(dev, ST7735R_CMD_SW_RESET, NULL, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
@ -204,12 +176,12 @@ static int st7735r_write(const struct device *dev,
|
|||
{
|
||||
const struct st7735r_config *config = dev->config;
|
||||
const uint8_t *write_data_start = (uint8_t *) buf;
|
||||
struct spi_buf tx_buf;
|
||||
struct spi_buf_set tx_bufs;
|
||||
uint16_t write_cnt;
|
||||
uint16_t nbr_of_writes;
|
||||
uint16_t write_h;
|
||||
int ret;
|
||||
enum display_pixel_format fmt;
|
||||
struct display_buffer_descriptor mipi_desc;
|
||||
|
||||
__ASSERT(desc->width <= desc->pitch, "Pitch is smaller than width");
|
||||
__ASSERT((desc->pitch * ST7735R_PIXEL_SIZE * desc->height)
|
||||
|
@ -225,9 +197,24 @@ static int st7735r_write(const struct device *dev,
|
|||
if (desc->pitch > desc->width) {
|
||||
write_h = 1U;
|
||||
nbr_of_writes = desc->height;
|
||||
mipi_desc.height = 1;
|
||||
mipi_desc.buf_size = desc->pitch * ST7735R_PIXEL_SIZE;
|
||||
} else {
|
||||
write_h = desc->height;
|
||||
nbr_of_writes = 1U;
|
||||
mipi_desc.height = desc->height;
|
||||
mipi_desc.buf_size = desc->width * ST7735R_PIXEL_SIZE * write_h;
|
||||
}
|
||||
|
||||
mipi_desc.width = desc->width;
|
||||
/* Per MIPI API, pitch must always match width */
|
||||
mipi_desc.pitch = desc->width;
|
||||
|
||||
|
||||
if (!(config->madctl & ST7735R_MADCTL_BGR) != !config->rgb_is_inverted) {
|
||||
fmt = PIXEL_FORMAT_BGR_565;
|
||||
} else {
|
||||
fmt = PIXEL_FORMAT_RGB_565;
|
||||
}
|
||||
|
||||
ret = st7735r_transmit_hold(dev, ST7735R_CMD_RAMWR,
|
||||
|
@ -237,14 +224,13 @@ static int st7735r_write(const struct device *dev,
|
|||
goto out;
|
||||
}
|
||||
|
||||
tx_bufs.buffers = &tx_buf;
|
||||
tx_bufs.count = 1;
|
||||
|
||||
write_data_start += (desc->pitch * ST7735R_PIXEL_SIZE);
|
||||
for (write_cnt = 1U; write_cnt < nbr_of_writes; ++write_cnt) {
|
||||
tx_buf.buf = (void *)write_data_start;
|
||||
tx_buf.len = desc->width * ST7735R_PIXEL_SIZE * write_h;
|
||||
ret = spi_write_dt(&config->bus, &tx_bufs);
|
||||
ret = mipi_dbi_write_display(config->mipi_dev,
|
||||
&config->dbi_config,
|
||||
write_data_start,
|
||||
&mipi_desc,
|
||||
fmt);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
@ -254,7 +240,7 @@ static int st7735r_write(const struct device *dev,
|
|||
|
||||
ret = 0;
|
||||
out:
|
||||
spi_release_dt(&config->bus);
|
||||
mipi_dbi_release(config->mipi_dev, &config->dbi_config);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -445,36 +431,11 @@ static int st7735r_init(const struct device *dev)
|
|||
const struct st7735r_config *config = dev->config;
|
||||
int ret;
|
||||
|
||||
if (!spi_is_ready_dt(&config->bus)) {
|
||||
LOG_ERR("SPI bus %s not ready", config->bus.bus->name);
|
||||
if (!device_is_ready(config->mipi_dev)) {
|
||||
LOG_ERR("MIPI bus %s not ready", config->mipi_dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (config->reset.port != NULL) {
|
||||
if (!gpio_is_ready_dt(&config->reset)) {
|
||||
LOG_ERR("Reset GPIO port for display not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = gpio_pin_configure_dt(&config->reset,
|
||||
GPIO_OUTPUT_INACTIVE);
|
||||
if (ret) {
|
||||
LOG_ERR("Couldn't configure reset pin");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gpio_is_ready_dt(&config->cmd_data)) {
|
||||
LOG_ERR("cmd/DATA GPIO port not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = gpio_pin_configure_dt(&config->cmd_data, GPIO_OUTPUT);
|
||||
if (ret) {
|
||||
LOG_ERR("Couldn't configure cmd/DATA pin");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = st7735r_reset_display(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Couldn't reset display");
|
||||
|
@ -530,11 +491,13 @@ static const struct display_driver_api st7735r_api = {
|
|||
|
||||
#define ST7735R_INIT(inst) \
|
||||
const static struct st7735r_config st7735r_config_ ## inst = { \
|
||||
.bus = SPI_DT_SPEC_INST_GET( \
|
||||
inst, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \
|
||||
.mipi_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
|
||||
.dbi_config = MIPI_DBI_CONFIG_DT_INST(inst, \
|
||||
SPI_OP_MODE_MASTER | \
|
||||
((DT_INST_PROP(inst, mipi_mode) == \
|
||||
MIPI_DBI_MODE_SPI_4WIRE) ? SPI_WORD_SET(8) : \
|
||||
SPI_WORD_SET(9)) | \
|
||||
SPI_HOLD_ON_CS | SPI_LOCK_ON, 0), \
|
||||
.cmd_data = GPIO_DT_SPEC_INST_GET(inst, cmd_data_gpios), \
|
||||
.reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}), \
|
||||
.width = DT_INST_PROP(inst, width), \
|
||||
.height = DT_INST_PROP(inst, height), \
|
||||
.madctl = DT_INST_PROP(inst, madctl), \
|
||||
|
|
|
@ -5,26 +5,9 @@ description: ST7735R/ST7735S 160x128 (max) display controller
|
|||
|
||||
compatible: "sitronix,st7735r"
|
||||
|
||||
include: [spi-device.yaml, display-controller.yaml]
|
||||
include: [mipi-dbi-spi-device.yaml, display-controller.yaml]
|
||||
|
||||
properties:
|
||||
reset-gpios:
|
||||
type: phandle-array
|
||||
description: RESET pin.
|
||||
|
||||
The RESET pin of ST7735R is active low.
|
||||
If connected directly the MCU pin should be configured
|
||||
as active low.
|
||||
|
||||
cmd-data-gpios:
|
||||
type: phandle-array
|
||||
required: true
|
||||
description: D/CX pin.
|
||||
|
||||
The D/CX pin of ST7735R is active low (transmission command byte).
|
||||
If connected directly the MCU pin should be configured
|
||||
as active low.
|
||||
|
||||
x-offset:
|
||||
type: int
|
||||
required: true
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue