From 6a2bfa422c56e12449498a142ca79d0df14f5d2a Mon Sep 17 00:00:00 2001 From: Mohamed ElShahawi Date: Mon, 6 Mar 2023 20:58:54 +0000 Subject: [PATCH] drivers: display: ili9342c display driver This driver implement basic functions of ili9342c controller which comes mostly with IPS displays. Signed-off-by: Mohamed ElShahawi --- CODEOWNERS | 1 + drivers/display/CMakeLists.txt | 1 + drivers/display/Kconfig.ili9xxx | 9 ++ drivers/display/display_ili9342c.c | 122 +++++++++++++++++++++ drivers/display/display_ili9342c.h | 95 +++++++++++++++++ drivers/display/display_ili9xxx.c | 62 +++++++++-- drivers/display/display_ili9xxx.h | 11 ++ dts/bindings/display/ilitek,ili9342c.yaml | 124 ++++++++++++++++++++++ 8 files changed, 415 insertions(+), 10 deletions(-) create mode 100644 drivers/display/display_ili9342c.c create mode 100644 drivers/display/display_ili9342c.h create mode 100644 dts/bindings/display/ilitek,ili9342c.yaml diff --git a/CODEOWNERS b/CODEOWNERS index ab587e7113d..edda4456f4e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -256,6 +256,7 @@ /drivers/counter/*esp32* @sylvioalves /drivers/crypto/*nrf_ecb* @maciekfabia @anangl /drivers/display/*rm68200* @mmahadevan108 +/drivers/display/display_ili9342c.* @extremegtx /drivers/dac/ @martinjaeger /drivers/dai/ @juimonen @marcinszkudlinski @abonislawski /drivers/dai/intel/ @juimonen @marcinszkudlinski @abonislawski diff --git a/drivers/display/CMakeLists.txt b/drivers/display/CMakeLists.txt index 82b51b55ef4..4e7bcd024da 100644 --- a/drivers/display/CMakeLists.txt +++ b/drivers/display/CMakeLists.txt @@ -10,6 +10,7 @@ zephyr_library_sources_ifdef(CONFIG_UC81XX uc81xx.c) zephyr_library_sources_ifdef(CONFIG_ILI9XXX display_ili9xxx.c) zephyr_library_sources_ifdef(CONFIG_ILI9340 display_ili9340.c) zephyr_library_sources_ifdef(CONFIG_ILI9341 display_ili9341.c) +zephyr_library_sources_ifdef(CONFIG_ILI9342C display_ili9342c.c) zephyr_library_sources_ifdef(CONFIG_ILI9488 display_ili9488.c) zephyr_library_sources_ifdef(CONFIG_LS0XX ls0xx.c) zephyr_library_sources_ifdef(CONFIG_MAX7219 display_max7219.c) diff --git a/drivers/display/Kconfig.ili9xxx b/drivers/display/Kconfig.ili9xxx index ec3f6ab9ae8..0ae849260cf 100644 --- a/drivers/display/Kconfig.ili9xxx +++ b/drivers/display/Kconfig.ili9xxx @@ -28,6 +28,15 @@ config ILI9341 help Enable driver for ILI9341 display driver. +config ILI9342C + bool "ILI9342C display driver" + default y + depends on DT_HAS_ILITEK_ILI9342C_ENABLED + select SPI + select ILI9XXX + help + Enable driver for ILI9342C display driver. + config ILI9488 bool "ILI9488 display driver" default y diff --git a/drivers/display/display_ili9342c.c b/drivers/display/display_ili9342c.c new file mode 100644 index 00000000000..c394b301e47 --- /dev/null +++ b/drivers/display/display_ili9342c.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2020 Teslabs Engineering S.L. + * Copyright (c) 2021 Krivorot Oleg + * Copyright (c) 2022 Konstantinos Papadopoulos + * Copyright (c) 2022 Mohamed ElShahawi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "display_ili9342c.h" +#include "display_ili9xxx.h" + +#include +LOG_MODULE_REGISTER(display_ili9342c, CONFIG_DISPLAY_LOG_LEVEL); + +int ili9342c_regs_init(const struct device *dev) +{ + const struct ili9xxx_config *config = dev->config; + const struct ili9342c_regs *regs = config->regs; + int r; + + /* some commands require that SETEXTC be set first before it becomes enabled. */ + LOG_HEXDUMP_DBG(regs->setextc, ILI9342C_SETEXTC_LEN, "SETEXTC"); + r = ili9xxx_transmit(dev, ILI9342C_SETEXTC, regs->setextc, + ILI9342C_SETEXTC_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->gamset, ILI9342C_GAMSET_LEN, "GAMSET"); + r = ili9xxx_transmit(dev, ILI9342C_GAMSET, regs->gamset, + ILI9342C_GAMSET_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->ifmode, ILI9342C_IFMODE_LEN, "IFMODE"); + r = ili9xxx_transmit(dev, ILI9342C_IFMODE, regs->ifmode, + ILI9342C_IFMODE_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->frmctr1, ILI9342C_FRMCTR1_LEN, "FRMCTR1"); + r = ili9xxx_transmit(dev, ILI9342C_FRMCTR1, regs->frmctr1, + ILI9342C_FRMCTR1_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->invtr, ILI9342C_INVTR_LEN, "INVTR"); + r = ili9xxx_transmit(dev, ILI9342C_INVTR, regs->invtr, + ILI9342C_INVTR_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->disctrl, ILI9342C_DISCTRL_LEN, "DISCTRL"); + r = ili9xxx_transmit(dev, ILI9342C_DISCTRL, regs->disctrl, + ILI9342C_DISCTRL_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->etmod, ILI9342C_ETMOD_LEN, "ETMOD"); + r = ili9xxx_transmit(dev, ILI9342C_ETMOD, regs->etmod, + ILI9342C_ETMOD_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->pwctrl1, ILI9342C_PWCTRL1_LEN, "PWCTRL1"); + r = ili9xxx_transmit(dev, ILI9342C_PWCTRL1, regs->pwctrl1, + ILI9342C_PWCTRL1_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->pwctrl2, ILI9342C_PWCTRL2_LEN, "PWCTRL2"); + r = ili9xxx_transmit(dev, ILI9342C_PWCTRL2, regs->pwctrl2, + ILI9342C_PWCTRL2_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->pwctrl3, ILI9342C_PWCTRL3_LEN, "PWCTRL3"); + r = ili9xxx_transmit(dev, ILI9342C_PWCTRL3, regs->pwctrl3, + ILI9342C_PWCTRL3_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->vmctrl1, ILI9342C_VMCTRL1_LEN, "VMCTRL1"); + r = ili9xxx_transmit(dev, ILI9342C_VMCTRL1, regs->vmctrl1, + ILI9342C_VMCTRL1_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->pgamctrl, ILI9342C_PGAMCTRL_LEN, "PGAMCTRL"); + r = ili9xxx_transmit(dev, ILI9342C_PGAMCTRL, regs->pgamctrl, + ILI9342C_PGAMCTRL_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->ngamctrl, ILI9342C_NGAMCTRL_LEN, "NGAMCTRL"); + r = ili9xxx_transmit(dev, ILI9342C_NGAMCTRL, regs->ngamctrl, + ILI9342C_NGAMCTRL_LEN); + if (r < 0) { + return r; + } + + LOG_HEXDUMP_DBG(regs->ifctl, ILI9342C_IFCTL_LEN, "IFCTL"); + r = ili9xxx_transmit(dev, ILI9342C_IFCTL, regs->ifctl, + ILI9342C_IFCTL_LEN); + if (r < 0) { + return r; + } + + return 0; +} diff --git a/drivers/display/display_ili9342c.h b/drivers/display/display_ili9342c.h new file mode 100644 index 00000000000..c5cc8fb5b9f --- /dev/null +++ b/drivers/display/display_ili9342c.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 Teslabs Engineering S.L. + * Copyright (c) 2021 Krivorot Oleg + * Copyright (c) 2022 Konstantinos Papadopoulos + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_DRIVERS_DISPLAY_DISPLAY_ILI9342C_H_ +#define ZEPHYR_DRIVERS_DISPLAY_DISPLAY_ILI9342C_H_ + +#include + +/* Commands/registers. */ +#define ILI9342C_GAMSET 0x26 +#define ILI9342C_IFMODE 0xB0 +#define ILI9342C_FRMCTR1 0xB1 +#define ILI9342C_INVTR 0xB4 +#define ILI9342C_DISCTRL 0xB6 +#define ILI9342C_ETMOD 0xB7 +#define ILI9342C_PWCTRL1 0xC0 +#define ILI9342C_PWCTRL2 0xC1 +#define ILI9342C_PWCTRL3 0xC2 +#define ILI9342C_VMCTRL1 0xC5 +#define ILI9342C_SETEXTC 0xC8 +#define ILI9342C_PGAMCTRL 0xE0 +#define ILI9342C_NGAMCTRL 0xE1 +#define ILI9342C_IFCTL 0xF6 + +/* Commands/registers length. */ +#define ILI9342C_GAMSET_LEN 1U +#define ILI9342C_IFMODE_LEN 1U +#define ILI9342C_FRMCTR1_LEN 2U +#define ILI9342C_INVTR_LEN 1U +#define ILI9342C_DISCTRL_LEN 4U +#define ILI9342C_ETMOD_LEN 1U +#define ILI9342C_PWCTRL1_LEN 2U +#define ILI9342C_PWCTRL2_LEN 1U +#define ILI9342C_PWCTRL3_LEN 1U +#define ILI9342C_VMCTRL1_LEN 1U +#define ILI9342C_SETEXTC_LEN 3U +#define ILI9342C_PGAMCTRL_LEN 15U +#define ILI9342C_NGAMCTRL_LEN 15U +#define ILI9342C_IFCTL_LEN 3U + +/** X resolution (pixels). */ +#define ILI9342c_X_RES 320U +/** Y resolution (pixels). */ +#define ILI9342c_Y_RES 240U + +/** ILI9342C registers to be initialized. */ +struct ili9342c_regs { + uint8_t gamset[ILI9342C_GAMSET_LEN]; + uint8_t ifmode[ILI9342C_IFMODE_LEN]; + uint8_t frmctr1[ILI9342C_FRMCTR1_LEN]; + uint8_t invtr[ILI9342C_INVTR_LEN]; + uint8_t disctrl[ILI9342C_DISCTRL_LEN]; + uint8_t etmod[ILI9342C_ETMOD_LEN]; + uint8_t pwctrl1[ILI9342C_PWCTRL1_LEN]; + uint8_t pwctrl2[ILI9342C_PWCTRL2_LEN]; + uint8_t pwctrl3[ILI9342C_PWCTRL3_LEN]; + uint8_t vmctrl1[ILI9342C_VMCTRL1_LEN]; + uint8_t setextc[ILI9342C_SETEXTC_LEN]; + uint8_t pgamctrl[ILI9342C_PGAMCTRL_LEN]; + uint8_t ngamctrl[ILI9342C_NGAMCTRL_LEN]; + uint8_t ifctl[ILI9342C_IFCTL_LEN]; +}; + +/* Initializer macro for ILI9342C registers. */ +#define ILI9342c_REGS_INIT(n) \ + static const struct ili9342c_regs ili9xxx_regs_##n = { \ + .gamset = DT_PROP(DT_INST(n, ilitek_ili9342c), gamset), \ + .ifmode = DT_PROP(DT_INST(n, ilitek_ili9342c), ifmode), \ + .frmctr1 = DT_PROP(DT_INST(n, ilitek_ili9342c), frmctr1), \ + .invtr = DT_PROP(DT_INST(n, ilitek_ili9342c), invtr), \ + .disctrl = DT_PROP(DT_INST(n, ilitek_ili9342c), disctrl), \ + .etmod = DT_PROP(DT_INST(n, ilitek_ili9342c), etmod), \ + .pwctrl1 = DT_PROP(DT_INST(n, ilitek_ili9342c), pwctrl1), \ + .pwctrl2 = DT_PROP(DT_INST(n, ilitek_ili9342c), pwctrl2), \ + .pwctrl3 = DT_PROP(DT_INST(n, ilitek_ili9342c), pwctrl3), \ + .vmctrl1 = DT_PROP(DT_INST(n, ilitek_ili9342c), vmctrl1), \ + .setextc = {0xFF, 0x93, 0x42}, \ + .pgamctrl = DT_PROP(DT_INST(n, ilitek_ili9342c), pgamctrl), \ + .ngamctrl = DT_PROP(DT_INST(n, ilitek_ili9342c), ngamctrl), \ + .ifctl = DT_PROP(DT_INST(n, ilitek_ili9342c), ifctl), \ + }; + +/** + * @brief Initialize ILI9342C registers with DT values. + * + * @param dev ILI9342C device instance + * @return 0 on success, errno otherwise. + */ +int ili9342c_regs_init(const struct device *dev); + +#endif /* ZEPHYR_DRIVERS_DISPLAY_DISPLAY_ILI9342C_H_ */ diff --git a/drivers/display/display_ili9xxx.c b/drivers/display/display_ili9xxx.c index abfaa27ffa8..c66ea9829a5 100644 --- a/drivers/display/display_ili9xxx.c +++ b/drivers/display/display_ili9xxx.c @@ -244,20 +244,32 @@ ili9xxx_set_pixel_format(const struct device *dev, static int ili9xxx_set_orientation(const struct device *dev, const enum display_orientation orientation) { + const struct ili9xxx_config *config = dev->config; struct ili9xxx_data *data = dev->data; int r; uint8_t tx_data = ILI9XXX_MADCTL_BGR; - - if (orientation == DISPLAY_ORIENTATION_NORMAL) { - tx_data |= ILI9XXX_MADCTL_MX; - } else if (orientation == DISPLAY_ORIENTATION_ROTATED_90) { - tx_data |= ILI9XXX_MADCTL_MV; - } else if (orientation == DISPLAY_ORIENTATION_ROTATED_180) { - tx_data |= ILI9XXX_MADCTL_MY; - } else if (orientation == DISPLAY_ORIENTATION_ROTATED_270) { - tx_data |= ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MX | - ILI9XXX_MADCTL_MY; + if (config->quirks->cmd_set == CMD_SET_1) { + if (orientation == DISPLAY_ORIENTATION_NORMAL) { + tx_data |= ILI9XXX_MADCTL_MX; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_90) { + tx_data |= ILI9XXX_MADCTL_MV; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_180) { + tx_data |= ILI9XXX_MADCTL_MY; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_270) { + tx_data |= ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MX | + ILI9XXX_MADCTL_MY; + } + } else if (config->quirks->cmd_set == CMD_SET_2) { + if (orientation == DISPLAY_ORIENTATION_NORMAL) { + /* Do nothing */ + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_90) { + tx_data |= ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MY; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_180) { + tx_data |= ILI9XXX_MADCTL_MY | ILI9XXX_MADCTL_MX; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_270) { + tx_data |= ILI9XXX_MADCTL_MV | ILI9XXX_MADCTL_MX; + } } r = ili9xxx_transmit(dev, ILI9XXX_MADCTL, &tx_data, 1U); @@ -420,12 +432,37 @@ static const struct display_driver_api ili9xxx_api = { .set_orientation = ili9xxx_set_orientation, }; +#ifdef CONFIG_ILI9340 +static const struct ili9xxx_quirks ili9340_quirks = { + .cmd_set = CMD_SET_1, +}; +#endif + +#ifdef CONFIG_ILI9341 +static const struct ili9xxx_quirks ili9341_quirks = { + .cmd_set = CMD_SET_1, +}; +#endif + +#ifdef CONFIG_ILI9342C +static const struct ili9xxx_quirks ili9342c_quirks = { + .cmd_set = CMD_SET_2, +}; +#endif + +#ifdef CONFIG_ILI9488 +static const struct ili9xxx_quirks ili9488_quirks = { + .cmd_set = CMD_SET_1, +}; +#endif + #define INST_DT_ILI9XXX(n, t) DT_INST(n, ilitek_ili##t) #define ILI9XXX_INIT(n, t) \ ILI##t##_REGS_INIT(n); \ \ static const struct ili9xxx_config ili9xxx_config_##n = { \ + .quirks = &ili##t##_quirks, \ .spi = SPI_DT_SPEC_GET(INST_DT_ILI9XXX(n, t), \ SPI_OP_MODE_MASTER | SPI_WORD_SET(8), \ 0), \ @@ -462,6 +499,11 @@ DT_INST_FOREACH_ILI9XXX_STATUS_OKAY(9340); DT_INST_FOREACH_ILI9XXX_STATUS_OKAY(9341); #endif +#ifdef CONFIG_ILI9342C +#include "display_ili9342c.h" +DT_INST_FOREACH_ILI9XXX_STATUS_OKAY(9342c); +#endif + #ifdef CONFIG_ILI9488 #include "display_ili9488.h" DT_INST_FOREACH_ILI9XXX_STATUS_OKAY(9488); diff --git a/drivers/display/display_ili9xxx.h b/drivers/display/display_ili9xxx.h index 3f3fe867c8c..2cd6da98088 100644 --- a/drivers/display/display_ili9xxx.h +++ b/drivers/display/display_ili9xxx.h @@ -54,7 +54,18 @@ /** Reset wait time (ms), ref 15.4 of ILI9XXX manual. */ #define ILI9XXX_RESET_WAIT_TIME 5 +enum madctl_cmd_set { + CMD_SET_1, /* Default for most of ILI9xxx display controllers */ + CMD_SET_2, /* Used by ILI9342c */ +}; + +struct ili9xxx_quirks { + enum madctl_cmd_set cmd_set; +}; + struct ili9xxx_config { + const struct ili9xxx_quirks *quirks; + struct spi_dt_spec spi; struct gpio_dt_spec cmd_data; struct gpio_dt_spec reset; diff --git a/dts/bindings/display/ilitek,ili9342c.yaml b/dts/bindings/display/ilitek,ili9342c.yaml new file mode 100644 index 00000000000..37cf5999cd9 --- /dev/null +++ b/dts/bindings/display/ilitek,ili9342c.yaml @@ -0,0 +1,124 @@ +# Copyright (c) 2018, Jan Van Winkel +# Copyright (c) 2020, Teslabs Engineering S.L. +# Copyright (c) 2021, Krivorot Oleg +# Copyright (c) 2022, Konstantinos Papadopulos +# SPDX-License-Identifier: Apache-2.0 + +description: ILI9342C 320x240 display controller + +compatible: "ilitek,ili9342c" + +include: ilitek,ili9xxx-common.yaml + +properties: + gamset: + type: uint8-array + default: [0x01] + description: + select the desired Gamma curve for the current display. + A maximum of 4 fixed gamma curves canbe selected. + + ifmode: + type: uint8-array + default: [0x40] + description: + RGB interface signal control (IFMOD) register value. + + invtr: + type: uint8-array + default: [0x00] + description: + Display Inversion Control (INVTR) register value. + + frmctr1: + type: uint8-array + default: [0x00, 0x1c] + description: + Frame rate control (in normal mode / full colors) (FRMCTR1) register value. + + disctrl: + type: uint8-array + default: [0x0a, 0x80, 0x1d, 0x04] + description: + Display function control (DISCTRL) register value. Note that changing + default SS bit value (0) may interfere with display rotation. + + etmod: + type: uint8-array + default: [0x07] + description: + Entry Mode set (ETMOD) + + pwctrl1: + type: uint8-array + default: [0x9, 0x9] + description: + Power control 1 (PWCTRL1) register values. + + pwctrl2: + type: uint8-array + default: [0x00] + description: + Power control 2 (PWCTRL2) register values. + + pwctrl3: + type: uint8-array + default: [0xB2] + description: + Power control 3 (PWCTRL3) register values. + + vmctrl1: + type: uint8-array + default: [0xf2] + description: + VCOM control 1 (VMCTRL1) register values. + + pgamctrl: + type: uint8-array + default: [ + 0x00, + 0x05, + 0x08, + 0x04, + 0x13, + 0x0A, + 0x34, + 0x8A, + 0x46, + 0x07, + 0x0E, + 0x0A, + 0x1B, + 0x1D, + 0x0F + ] + description: + Positive gamma correction (PGAMCTRL) register values. + + ngamctrl: + type: uint8-array + default: [ + 0x00, + 0x22, + 0x25, + 0x04, + 0x0F, + 0x06, + 0x38, + 0x56, + 0x4B, + 0x05, + 0x0C, + 0x0A, + 0x37, + 0x3A, + 0x0F + ] + description: + Negative gamma correction (NGAMCTRL) register values. + + ifctl: + type: uint8-array + default: [0x01, 0x00, 0x00] + description: + Interface control (IFCTL) register value.