drivers: display: ili9xxx: add support for ILI9341 controller

Add support for the ILI9341 display controller.

Signed-off-by: Krivorot Oleg <krivorot.oleg@gmail.com>
This commit is contained in:
Krivorot Oleg 2021-06-23 12:34:41 +03:00 committed by Anas Nashif
commit 1d55d929db
7 changed files with 439 additions and 1 deletions

View file

@ -16,6 +16,7 @@ if (CONFIG_ILI9XXX)
zephyr_sources(display_ili9xxx.c) zephyr_sources(display_ili9xxx.c)
endif() endif()
zephyr_sources_ifdef(CONFIG_ILI9340 display_ili9340.c) zephyr_sources_ifdef(CONFIG_ILI9340 display_ili9340.c)
zephyr_sources_ifdef(CONFIG_ILI9341 display_ili9341.c)
zephyr_sources_ifdef(CONFIG_ILI9488 display_ili9488.c) zephyr_sources_ifdef(CONFIG_ILI9488 display_ili9488.c)
zephyr_sources_ifdef(CONFIG_MICROBIT_DISPLAY zephyr_sources_ifdef(CONFIG_MICROBIT_DISPLAY

View file

@ -2,6 +2,7 @@
# Copyright (c) 2017 Jan Van Winkel <jan.van_winkel@dxplore.eu> # Copyright (c) 2017 Jan Van Winkel <jan.van_winkel@dxplore.eu>
# Copyright (c) 2020 Teslabs Engineering S.L. # Copyright (c) 2020 Teslabs Engineering S.L.
# Copyright (c) 2021 Krivorot Oleg <krivorot.oleg@gmail.com>
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
config ILI9XXX config ILI9XXX
@ -16,6 +17,13 @@ config ILI9340
help help
Enable driver for ILI9340 display driver. Enable driver for ILI9340 display driver.
config ILI9341
bool "ILI9341 display driver"
depends on SPI
select ILI9XXX
help
Enable driver for ILI9341 display driver.
config ILI9488 config ILI9488
bool "ILI9488 display driver" bool "ILI9488 display driver"
depends on SPI depends on SPI

View file

@ -0,0 +1,125 @@
/*
* Copyright (c) 2020 Teslabs Engineering S.L.
* Copyright (c) 2021 Krivorot Oleg <krivorot.oleg@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "display_ili9341.h"
#include "display_ili9xxx.h"
#include <logging/log.h>
LOG_MODULE_REGISTER(display_ili9341, CONFIG_DISPLAY_LOG_LEVEL);
int ili9341_regs_init(const struct device *dev)
{
const struct ili9xxx_config *config = dev->config;
const struct ili9341_regs *regs = config->regs;
int r;
LOG_HEXDUMP_DBG(regs->pwseqctrl, ILI9341_PWSEQCTRL_LEN, "PWSEQCTRL");
r = ili9xxx_transmit(dev, ILI9341_PWSEQCTRL, regs->pwseqctrl, ILI9341_PWSEQCTRL_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->timctrla, ILI9341_TIMCTRLA_LEN, "TIMCTRLA");
r = ili9xxx_transmit(dev, ILI9341_TIMCTRLA, regs->timctrla, ILI9341_TIMCTRLA_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->timctrlb, ILI9341_TIMCTRLB_LEN, "TIMCTRLB");
r = ili9xxx_transmit(dev, ILI9341_TIMCTRLB, regs->timctrlb, ILI9341_TIMCTRLB_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->pumpratioctrl, ILI9341_PUMPRATIOCTRL_LEN, "PUMPRATIOCTRL");
r = ili9xxx_transmit(dev, ILI9341_PUMPRATIOCTRL, regs->pumpratioctrl,
ILI9341_PUMPRATIOCTRL_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->pwctrla, ILI9341_PWCTRLA_LEN, "PWCTRLA");
r = ili9xxx_transmit(dev, ILI9341_PWCTRLA, regs->pwctrla, ILI9341_PWCTRLA_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->pwctrlb, ILI9341_PWCTRLB_LEN, "PWCTRLB");
r = ili9xxx_transmit(dev, ILI9341_PWCTRLB, regs->pwctrlb, ILI9341_PWCTRLB_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->gamset, ILI9341_GAMSET_LEN, "GAMSET");
r = ili9xxx_transmit(dev, ILI9341_GAMSET, regs->gamset, ILI9341_GAMSET_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->frmctr1, ILI9341_FRMCTR1_LEN, "FRMCTR1");
r = ili9xxx_transmit(dev, ILI9341_FRMCTR1, regs->frmctr1, ILI9341_FRMCTR1_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->disctrl, ILI9341_DISCTRL_LEN, "DISCTRL");
r = ili9xxx_transmit(dev, ILI9341_DISCTRL, regs->disctrl, ILI9341_DISCTRL_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->pwctrl1, ILI9341_PWCTRL1_LEN, "PWCTRL1");
r = ili9xxx_transmit(dev, ILI9341_PWCTRL1, regs->pwctrl1, ILI9341_PWCTRL1_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->pwctrl2, ILI9341_PWCTRL2_LEN, "PWCTRL2");
r = ili9xxx_transmit(dev, ILI9341_PWCTRL2, regs->pwctrl2, ILI9341_PWCTRL2_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->vmctrl1, ILI9341_VMCTRL1_LEN, "VMCTRL1");
r = ili9xxx_transmit(dev, ILI9341_VMCTRL1, regs->vmctrl1, ILI9341_VMCTRL1_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->vmctrl2, ILI9341_VMCTRL2_LEN, "VMCTRL2");
r = ili9xxx_transmit(dev, ILI9341_VMCTRL2, regs->vmctrl2, ILI9341_VMCTRL2_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->pgamctrl, ILI9341_PGAMCTRL_LEN, "PGAMCTRL");
r = ili9xxx_transmit(dev, ILI9341_PGAMCTRL, regs->pgamctrl, ILI9341_PGAMCTRL_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->ngamctrl, ILI9341_NGAMCTRL_LEN, "NGAMCTRL");
r = ili9xxx_transmit(dev, ILI9341_NGAMCTRL, regs->ngamctrl, ILI9341_NGAMCTRL_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->enable3g, ILI9341_ENABLE3G_LEN, "ENABLE3G");
r = ili9xxx_transmit(dev, ILI9341_ENABLE3G, regs->enable3g, ILI9341_ENABLE3G_LEN);
if (r < 0) {
return r;
}
LOG_HEXDUMP_DBG(regs->etmod, ILI9341_ETMOD_LEN, "ETMOD");
r = ili9xxx_transmit(dev, ILI9341_ETMOD, regs->etmod, ILI9341_ETMOD_LEN);
if (r < 0) {
return r;
}
return 0;
}

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2020 Teslabs Engineering S.L.
* Copyright (c) 2021 Krivorot Oleg <krivorot.oleg@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_DRIVERS_DISPLAY_DISPLAY_ILI9341_H_
#define ZEPHYR_DRIVERS_DISPLAY_DISPLAY_ILI9341_H_
#include <device.h>
/* Commands/registers. */
#define ILI9341_GAMSET 0x26
#define ILI9341_FRMCTR1 0xB1
#define ILI9341_DISCTRL 0xB6
#define ILI9341_ETMOD 0xB7
#define ILI9341_PWCTRL1 0xC0
#define ILI9341_PWCTRL2 0xC1
#define ILI9341_VMCTRL1 0xC5
#define ILI9341_VMCTRL2 0xC7
#define ILI9341_PWCTRLA 0xCB
#define ILI9341_PWCTRLB 0xCF
#define ILI9341_PGAMCTRL 0xE0
#define ILI9341_NGAMCTRL 0xE1
#define ILI9341_TIMCTRLA 0xE8
#define ILI9341_TIMCTRLB 0xEA
#define ILI9341_PWSEQCTRL 0xED
#define ILI9341_ENABLE3G 0xF2
#define ILI9341_PUMPRATIOCTRL 0xF7
/* Commands/registers length. */
#define ILI9341_GAMSET_LEN 1U
#define ILI9341_FRMCTR1_LEN 2U
#define ILI9341_DISCTRL_LEN 3U
#define ILI9341_PWCTRL1_LEN 1U
#define ILI9341_PWCTRL2_LEN 1U
#define ILI9341_VMCTRL1_LEN 2U
#define ILI9341_VMCTRL2_LEN 1U
#define ILI9341_PGAMCTRL_LEN 15U
#define ILI9341_NGAMCTRL_LEN 15U
#define ILI9341_PWCTRLA_LEN 5U
#define ILI9341_PWCTRLB_LEN 3U
#define ILI9341_PWSEQCTRL_LEN 4U
#define ILI9341_TIMCTRLA_LEN 3U
#define ILI9341_TIMCTRLB_LEN 2U
#define ILI9341_PUMPRATIOCTRL_LEN 1U
#define ILI9341_ENABLE3G_LEN 1U
#define ILI9341_ETMOD_LEN 1U
/** X resolution (pixels). */
#define ILI9341_X_RES 240U
/** Y resolution (pixels). */
#define ILI9341_Y_RES 320U
/** ILI9341 registers to be initialized. */
struct ili9341_regs {
uint8_t gamset[ILI9341_GAMSET_LEN];
uint8_t frmctr1[ILI9341_FRMCTR1_LEN];
uint8_t disctrl[ILI9341_DISCTRL_LEN];
uint8_t pwctrl1[ILI9341_PWCTRL1_LEN];
uint8_t pwctrl2[ILI9341_PWCTRL2_LEN];
uint8_t vmctrl1[ILI9341_VMCTRL1_LEN];
uint8_t vmctrl2[ILI9341_VMCTRL2_LEN];
uint8_t pgamctrl[ILI9341_PGAMCTRL_LEN];
uint8_t ngamctrl[ILI9341_NGAMCTRL_LEN];
uint8_t pwctrla[ILI9341_PWCTRLA_LEN];
uint8_t pwctrlb[ILI9341_PWCTRLB_LEN];
uint8_t pwseqctrl[ILI9341_PWSEQCTRL_LEN];
uint8_t timctrla[ILI9341_TIMCTRLA_LEN];
uint8_t timctrlb[ILI9341_TIMCTRLB_LEN];
uint8_t pumpratioctrl[ILI9341_PUMPRATIOCTRL_LEN];
uint8_t enable3g[ILI9341_ENABLE3G_LEN];
uint8_t etmod[ILI9341_ETMOD_LEN];
};
/* Initializer macro for ILI9341 registers. */
#define ILI9341_REGS_INIT(n) \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), gamset) == ILI9341_GAMSET_LEN, \
"ili9341: Error length gamma set (GAMSET) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), frmctr1) == ILI9341_FRMCTR1_LEN, \
"ili9341: Error length frame rate control (FRMCTR1) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), disctrl) == ILI9341_DISCTRL_LEN, \
"ili9341: Error length display function control (DISCTRL) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), pwctrl1) == ILI9341_PWCTRL1_LEN, \
"ili9341: Error length power control 1 (PWCTRL1) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), pwctrl2) == ILI9341_PWCTRL2_LEN, \
"ili9341: Error length power control 2 (PWCTRL2) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), vmctrl1) == ILI9341_VMCTRL1_LEN, \
"ili9341: Error length VCOM control 1 (VMCTRL1) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), vmctrl2) == ILI9341_VMCTRL2_LEN, \
"ili9341: Error length VCOM control 2 (VMCTRL2) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), pgamctrl) == ILI9341_PGAMCTRL_LEN, \
"ili9341: Error length positive gamma correction (PGAMCTRL) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), ngamctrl) == ILI9341_NGAMCTRL_LEN, \
"ili9341: Error length negative gamma correction (NGAMCTRL) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), pwctrla) == ILI9341_PWCTRLA_LEN, \
"ili9341: Error length power control A (PWCTRLA) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), pwctrlb) == ILI9341_PWCTRLB_LEN, \
"ili9341: Error length power control B (PWCTRLB) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), pwseqctrl) == ILI9341_PWSEQCTRL_LEN, \
"ili9341: Error length power on sequence control (PWSEQCTRL) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), timctrla) == ILI9341_TIMCTRLA_LEN, \
"ili9341: Error length driver timing control A (TIMCTRLA) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), timctrlb) == ILI9341_TIMCTRLB_LEN, \
"ili9341: Error length driver timing control B (TIMCTRLB) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), pumpratioctrl) == \
ILI9341_PUMPRATIOCTRL_LEN, \
"ili9341: Error length Pump ratio control (PUMPRATIOCTRL) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), enable3g) == ILI9341_ENABLE3G_LEN, \
"ili9341: Error length enable 3G (ENABLE3G) register"); \
BUILD_ASSERT(DT_PROP_LEN(DT_INST(n, ilitek_ili9341), etmod) == ILI9341_ETMOD_LEN, \
"ili9341: Error length entry Mode Set (ETMOD) register"); \
static const struct ili9341_regs ili9xxx_regs_##n = { \
.gamset = DT_PROP(DT_INST(n, ilitek_ili9341), gamset), \
.frmctr1 = DT_PROP(DT_INST(n, ilitek_ili9341), frmctr1), \
.disctrl = DT_PROP(DT_INST(n, ilitek_ili9341), disctrl), \
.pwctrl1 = DT_PROP(DT_INST(n, ilitek_ili9341), pwctrl1), \
.pwctrl2 = DT_PROP(DT_INST(n, ilitek_ili9341), pwctrl2), \
.vmctrl1 = DT_PROP(DT_INST(n, ilitek_ili9341), vmctrl1), \
.vmctrl2 = DT_PROP(DT_INST(n, ilitek_ili9341), vmctrl2), \
.pgamctrl = DT_PROP(DT_INST(n, ilitek_ili9341), pgamctrl), \
.ngamctrl = DT_PROP(DT_INST(n, ilitek_ili9341), ngamctrl), \
.pwctrla = DT_PROP(DT_INST(n, ilitek_ili9341), pwctrla), \
.pwctrlb = DT_PROP(DT_INST(n, ilitek_ili9341), pwctrlb), \
.pwseqctrl = DT_PROP(DT_INST(n, ilitek_ili9341), pwseqctrl), \
.timctrla = DT_PROP(DT_INST(n, ilitek_ili9341), timctrla), \
.timctrlb = DT_PROP(DT_INST(n, ilitek_ili9341), timctrlb), \
.pumpratioctrl = DT_PROP(DT_INST(n, ilitek_ili9341), pumpratioctrl), \
.enable3g = DT_PROP(DT_INST(n, ilitek_ili9341), enable3g), \
.etmod = DT_PROP(DT_INST(n, ilitek_ili9341), etmod), \
}
/**
* @brief Initialize ILI9341 registers with DT values.
*
* @param dev ILI9341 device instance
* @return 0 on success, errno otherwise.
*/
int ili9341_regs_init(const struct device *dev);
#endif /* ZEPHYR_DRIVERS_DISPLAY_DISPLAY_ILI9341_H_ */

View file

@ -2,7 +2,7 @@
* Copyright (c) 2017 Jan Van Winkel <jan.van_winkel@dxplore.eu> * Copyright (c) 2017 Jan Van Winkel <jan.van_winkel@dxplore.eu>
* Copyright (c) 2019 Nordic Semiconductor ASA * Copyright (c) 2019 Nordic Semiconductor ASA
* Copyright (c) 2020 Teslabs Engineering S.L. * Copyright (c) 2020 Teslabs Engineering S.L.
* * Copyright (c) 2021 Krivorot Oleg <krivorot.oleg@gmail.com>
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -411,6 +411,16 @@ static int ili9xxx_init(const struct device *dev)
ili9xxx_hw_reset(dev); ili9xxx_hw_reset(dev);
r = ili9xxx_transmit(dev, ILI9XXX_SWRESET, NULL, 0);
if (r < 0) {
LOG_ERR("Error transmit command Software Reset (%d)", r);
return r;
}
k_sleep(K_MSEC(ILI9XXX_RESET_WAIT_TIME));
ili9xxx_display_blanking_on(dev);
r = ili9xxx_configure(dev); r = ili9xxx_configure(dev);
if (r < 0) { if (r < 0) {
LOG_ERR("Could not configure display (%d)", r); LOG_ERR("Could not configure display (%d)", r);
@ -498,6 +508,11 @@ static const struct display_driver_api ili9xxx_api = {
DT_INST_FOREACH_ILI9XXX_STATUS_OKAY(9340); DT_INST_FOREACH_ILI9XXX_STATUS_OKAY(9340);
#endif #endif
#ifdef CONFIG_ILI9341
#include "display_ili9341.h"
DT_INST_FOREACH_ILI9XXX_STATUS_OKAY(9341);
#endif
#ifdef CONFIG_ILI9488 #ifdef CONFIG_ILI9488
#include "display_ili9488.h" #include "display_ili9488.h"
DT_INST_FOREACH_ILI9XXX_STATUS_OKAY(9488); DT_INST_FOREACH_ILI9XXX_STATUS_OKAY(9488);

View file

@ -2,6 +2,7 @@
* Copyright (c) 2017 Jan Van Winkel <jan.van_winkel@dxplore.eu> * Copyright (c) 2017 Jan Van Winkel <jan.van_winkel@dxplore.eu>
* Copyright (c) 2019 Nordic Semiconductor ASA * Copyright (c) 2019 Nordic Semiconductor ASA
* Copyright (c) 2020 Teslabs Engineering S.L. * Copyright (c) 2020 Teslabs Engineering S.L.
* Copyright (c) 2021 Krivorot Oleg <krivorot.oleg@gmail.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -12,6 +13,7 @@
#include <sys/util.h> #include <sys/util.h>
/* Commands/registers. */ /* Commands/registers. */
#define ILI9XXX_SWRESET 0x01
#define ILI9XXX_SLPOUT 0x11 #define ILI9XXX_SLPOUT 0x11
#define ILI9XXX_DINVON 0x21 #define ILI9XXX_DINVON 0x21
#define ILI9XXX_GAMSET 0x26 #define ILI9XXX_GAMSET 0x26

View file

@ -0,0 +1,146 @@
# Copyright (c) 2018, Jan Van Winkel <jan.van_winkel@dxplore.eu>
# Copyright (c) 2020, Teslabs Engineering S.L.
# Copyright (c) 2021, Krivorot Oleg <krivorot.oleg@gmail.com>
# SPDX-License-Identifier: Apache-2.0
description: ILI9341 320x240 display controller
compatible: "ilitek,ili9341"
include: ilitek,ili9xxx-common.yaml
properties:
pwctrla:
type: uint8-array
default: [0x39, 0x2c, 0x00, 0x34, 0x02]
description:
Power control A (PWCTRLA) register value.
pwctrlb:
type: uint8-array
default: [0x00, 0x8b, 0x30]
description:
Power control B (PWCTRLB) register value.
pwseqctrl:
type: uint8-array
default: [0x55, 0x01, 0x23, 0x01]
description:
Power on sequence control (PWSEQCTRL) register value.
timctrla:
type: uint8-array
default: [0x84, 0x11, 0x7a]
description:
Driver timing control A (TIMCTRLA) register value.
timctrlb:
type: uint8-array
default: [0x00, 0x00]
description:
Driver timing control B (TIMCTRLB) register value.
pumpratioctrl:
type: uint8-array
default: [0x10]
description:
Pump ratio control (PUMPRATIOCTRL) register value.
enable3g:
type: uint8-array
default: [0x02]
description:
Enable 3G (ENABLE3G) register value.
etmod:
type: uint8-array
default: [ 0x06 ]
description:
Entry Mode Set (ETMOD) register value.
gamset:
type: uint8-array
default: [0x01]
description:
Gamma set (GAMSET) register value.
frmctr1:
type: uint8-array
default: [0x00, 0x1b]
description:
Frame rate control (in normal mode / full colors) (FRMCTR1) register value.
disctrl:
type: uint8-array
default: [0x0a, 0x82, 0x27]
description:
Display function control (DISCTRL) register value. Note that changing
default SS bit value (0) may interfere with display rotation.
pwctrl1:
type: uint8-array
default: [0x21]
description:
Power control 1 (PWCTRL1) register values.
pwctrl2:
type: uint8-array
default: [0x10]
description:
Power control 2 (PWCTRL2) register values.
vmctrl1:
type: uint8-array
default: [0x31, 0x3c]
description:
VCOM control 1 (VMCTRL1) register values.
vmctrl2:
type: uint8-array
default: [0xc0]
description:
VCOM control 2 (VMCTRL2) register values.
pgamctrl:
type: uint8-array
default: [
0x0f,
0x22,
0x1f,
0x0a,
0x0e,
0x06,
0x4d,
0x76,
0x3b,
0x03,
0x0e,
0x04,
0x13,
0x0e,
0x0c
]
description:
Positive gamma correction (PGAMCTRL) register values.
ngamctrl:
type: uint8-array
default: [
0x0c,
0x23,
0x26,
0x04,
0x10,
0x04,
0x39,
0x24,
0x4b,
0x03,
0x0b,
0x0b,
0x33,
0x37,
0x0f
]
description:
Negative gamma correction (NGAMCTRL) register values.