drivers: add SSD1673 EPD controller driver
Add SSD1673 electrophoretic display controller driver. Signed-off-by: Johann Fischer <j.fischer@phytec.de>
This commit is contained in:
parent
419f4b7801
commit
3a66b86544
6 changed files with 705 additions and 0 deletions
|
@ -7,3 +7,4 @@ zephyr_sources_ifdef(CONFIG_ILI9340_LCD_ADAFRUIT_1480
|
|||
display_ili9340_adafruit_1480.c
|
||||
)
|
||||
zephyr_sources_ifdef(CONFIG_SSD1306 ssd1306.c)
|
||||
zephyr_sources_ifdef(CONFIG_SSD1673 ssd1673.c)
|
||||
|
|
|
@ -23,4 +23,6 @@ source "drivers/display/Kconfig.ili9340"
|
|||
|
||||
source "drivers/display/Kconfig.ssd1306"
|
||||
|
||||
source "drivers/display/Kconfig.ssd1673"
|
||||
|
||||
endif # DISPLAY
|
||||
|
|
29
drivers/display/Kconfig.ssd1673
Normal file
29
drivers/display/Kconfig.ssd1673
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Kconfig - SSD1673 display controller configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2018 Phytec Messtechnik GmbH
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menuconfig SSD1673
|
||||
bool "SSD1673 display driver"
|
||||
depends on SPI
|
||||
help
|
||||
Enable driver for SSD1673 display driver.
|
||||
|
||||
if SSD1673
|
||||
|
||||
choice
|
||||
prompt "EPD display"
|
||||
default SSD1673_EPD_GDE0213B1
|
||||
help
|
||||
Specify the type of EPD connected to the SSD1673 controller.
|
||||
|
||||
config SSD1673_EPD_GDE0213B1
|
||||
bool
|
||||
prompt "GDE0213B1 2.13\""
|
||||
|
||||
endchoice
|
||||
|
||||
endif #SSD1673
|
532
drivers/display/ssd1673.c
Normal file
532
drivers/display/ssd1673.c
Normal file
|
@ -0,0 +1,532 @@
|
|||
/*
|
||||
* Copyright (c) 2018 PHYTEC Messtechnik GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_LEVEL CONFIG_DISPLAY_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(ssd1673);
|
||||
|
||||
#include <string.h>
|
||||
#include <device.h>
|
||||
#include <display.h>
|
||||
#include <init.h>
|
||||
#include <gpio.h>
|
||||
#include <spi.h>
|
||||
|
||||
#include "ssd1673_regs.h"
|
||||
#include <display/cfb.h>
|
||||
|
||||
#define EPD_PANEL_WIDTH 250
|
||||
#define EPD_PANEL_HEIGHT 120
|
||||
#define EPD_PANEL_NUMOF_COLUMS 250
|
||||
#define EPD_PANEL_NUMOF_ROWS_PER_PAGE 8
|
||||
#define EPD_PANEL_NUMOF_PAGES (EPD_PANEL_HEIGHT / \
|
||||
EPD_PANEL_NUMOF_ROWS_PER_PAGE)
|
||||
|
||||
#define SSD1673_PANEL_FIRST_PAGE 0
|
||||
#define SSD1673_PANEL_LAST_PAGE (EPD_PANEL_NUMOF_PAGES - 1)
|
||||
#define SSD1673_PANEL_FIRST_GATE 0
|
||||
#define SSD1673_PANEL_LAST_GATE 249
|
||||
|
||||
struct ssd1673_data {
|
||||
struct device *reset;
|
||||
struct device *dc;
|
||||
struct device *busy;
|
||||
struct device *spi_dev;
|
||||
struct spi_config spi_config;
|
||||
#if defined(CONFIG_SSD1673_SPI_GPIO_CS)
|
||||
struct spi_cs_control cs_ctrl;
|
||||
#endif
|
||||
u8_t contrast;
|
||||
u8_t scan_mode;
|
||||
u8_t last_lut;
|
||||
u8_t numof_part_cycles;
|
||||
};
|
||||
|
||||
#define SSD1673_LAST_LUT_INITIAL 0
|
||||
#define SSD1673_LAST_LUT_DEFAULT 255
|
||||
#define SSD1673_LUT_SIZE 29
|
||||
|
||||
static u8_t ssd1673_lut_initial[SSD1673_LUT_SIZE] = {
|
||||
0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static u8_t ssd1673_lut_default[SSD1673_LUT_SIZE] = {
|
||||
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static inline int ssd1673_write_cmd(struct ssd1673_data *driver,
|
||||
u8_t cmd, u8_t *data, size_t len)
|
||||
{
|
||||
struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)};
|
||||
struct spi_buf_set buf_set = {.buffers = &buf, .count = 1};
|
||||
|
||||
gpio_pin_write(driver->dc, CONFIG_SSD1673_DC_PIN, 0);
|
||||
if (spi_write(driver->spi_dev, &driver->spi_config, &buf_set)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data != NULL) {
|
||||
buf.buf = data;
|
||||
buf.len = len;
|
||||
gpio_pin_write(driver->dc, CONFIG_SSD1673_DC_PIN, 1);
|
||||
if (spi_write(driver->spi_dev, &driver->spi_config, &buf_set)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ssd1673_busy_wait(struct ssd1673_data *driver)
|
||||
{
|
||||
u32_t val = 0;
|
||||
|
||||
gpio_pin_read(driver->busy, CONFIG_SSD1673_BUSY_PIN, &val);
|
||||
while (val) {
|
||||
k_busy_wait(SSD1673_BUSY_DELAY);
|
||||
gpio_pin_read(driver->busy, CONFIG_SSD1673_BUSY_PIN, &val);
|
||||
};
|
||||
}
|
||||
|
||||
static inline int ssd1673_set_ram_param(struct ssd1673_data *driver,
|
||||
u8_t sx, u8_t ex, u8_t sy, u8_t ey)
|
||||
{
|
||||
u8_t tmp[2];
|
||||
|
||||
tmp[0] = sx; tmp[1] = ex;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_RAM_XPOS_CTRL,
|
||||
tmp, sizeof(tmp))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp[0] = sy; tmp[1] = ey;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_RAM_YPOS_CTRL,
|
||||
tmp, sizeof(tmp))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ssd1673_set_ram_ptr(struct ssd1673_data *driver,
|
||||
u8_t x, u8_t y)
|
||||
{
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_RAM_XPOS_CNTR,
|
||||
&x, sizeof(x))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_RAM_YPOS_CNTR,
|
||||
&y, sizeof(y))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ssd1673_set_orientation(struct ssd1673_data *driver)
|
||||
|
||||
{
|
||||
#if defined(CONFIG_SSD1673_ORIENTATION_FLIPPED)
|
||||
driver->scan_mode = SSD1673_DATA_ENTRY_XIYDY;
|
||||
#else
|
||||
driver->scan_mode = SSD1673_DATA_ENTRY_XDYIY;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ssd1673_resume(const struct device *dev)
|
||||
{
|
||||
struct ssd1673_data *driver = dev->driver_data;
|
||||
u8_t tmp;
|
||||
|
||||
/*
|
||||
* Uncomment for voltage measurement
|
||||
* tmp = SSD1673_CTRL2_ENABLE_CLK;
|
||||
* ssd1673_write_cmd(SSD1673_CMD_UPDATE_CTRL2, &tmp, sizeof(tmp));
|
||||
* ssd1673_write_cmd(SSD1673_CMD_MASTER_ACTIVATION, NULL, 0);
|
||||
*/
|
||||
|
||||
tmp = SSD1673_SLEEP_MODE_PON;
|
||||
return ssd1673_write_cmd(driver, SSD1673_CMD_SLEEP_MODE,
|
||||
&tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static int ssd1673_suspend(const struct device *dev)
|
||||
{
|
||||
struct ssd1673_data *driver = dev->driver_data;
|
||||
u8_t tmp = SSD1673_SLEEP_MODE_DSM;
|
||||
|
||||
return ssd1673_write_cmd(driver, SSD1673_CMD_SLEEP_MODE,
|
||||
&tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static int ssd1673_update_display(const struct device *dev, bool initial)
|
||||
{
|
||||
struct ssd1673_data *driver = dev->driver_data;
|
||||
u8_t tmp;
|
||||
|
||||
tmp = SSD1673_CTRL1_INITIAL_UPDATE_LH;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_UPDATE_CTRL1,
|
||||
&tmp, sizeof(tmp))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (initial) {
|
||||
driver->numof_part_cycles = 0;
|
||||
driver->last_lut = SSD1673_LAST_LUT_INITIAL;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_UPDATE_LUT,
|
||||
ssd1673_lut_initial,
|
||||
sizeof(ssd1673_lut_initial))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
driver->numof_part_cycles++;
|
||||
if (driver->last_lut != SSD1673_LAST_LUT_DEFAULT) {
|
||||
driver->last_lut = SSD1673_LAST_LUT_DEFAULT;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_UPDATE_LUT,
|
||||
ssd1673_lut_default,
|
||||
sizeof(ssd1673_lut_default))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmp = (SSD1673_CTRL2_ENABLE_CLK |
|
||||
SSD1673_CTRL2_ENABLE_ANALOG |
|
||||
SSD1673_CTRL2_TO_PATTERN |
|
||||
SSD1673_CTRL2_DISABLE_ANALOG |
|
||||
SSD1673_CTRL2_DISABLE_CLK);
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_UPDATE_CTRL2,
|
||||
&tmp, sizeof(tmp))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_MASTER_ACTIVATION,
|
||||
NULL, 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1673_write(const struct device *dev, const u16_t x,
|
||||
const u16_t y,
|
||||
const struct display_buffer_descriptor *desc,
|
||||
const void *buf)
|
||||
{
|
||||
struct ssd1673_data *driver = dev->driver_data;
|
||||
u8_t cmd = SSD1673_CMD_WRITE_RAM;
|
||||
u8_t dummy_page[SSD1673_RAM_YRES];
|
||||
struct spi_buf sbuf = {.buf = &cmd, .len = 1};
|
||||
struct spi_buf_set buf_set = {.buffers = &sbuf, .count = 1};
|
||||
bool update = true;
|
||||
|
||||
if (desc->pitch < desc->width) {
|
||||
LOG_ERR("Pitch is smaller then width");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buf == NULL || desc->buf_size == 0) {
|
||||
LOG_ERR("Display buffer is not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (desc->pitch > desc->width) {
|
||||
LOG_ERR("Unsupported mode");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x != 0 && y != 0) {
|
||||
LOG_ERR("Unsupported origin");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ssd1673_busy_wait(driver);
|
||||
memset(dummy_page, 0xff, sizeof(dummy_page));
|
||||
|
||||
switch (driver->scan_mode) {
|
||||
case SSD1673_DATA_ENTRY_XIYDY:
|
||||
if (ssd1673_set_ram_param(driver,
|
||||
SSD1673_PANEL_FIRST_PAGE,
|
||||
SSD1673_PANEL_LAST_PAGE + 1,
|
||||
SSD1673_PANEL_LAST_GATE,
|
||||
SSD1673_PANEL_FIRST_GATE)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssd1673_set_ram_ptr(driver,
|
||||
SSD1673_PANEL_FIRST_PAGE,
|
||||
SSD1673_PANEL_LAST_GATE)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SSD1673_DATA_ENTRY_XDYIY:
|
||||
if (ssd1673_set_ram_param(driver,
|
||||
SSD1673_PANEL_LAST_PAGE + 1,
|
||||
SSD1673_PANEL_FIRST_PAGE,
|
||||
SSD1673_PANEL_FIRST_GATE,
|
||||
SSD1673_PANEL_LAST_GATE)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssd1673_set_ram_ptr(driver,
|
||||
SSD1673_PANEL_LAST_PAGE + 1,
|
||||
SSD1673_PANEL_FIRST_GATE)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_ENTRY_MODE,
|
||||
&driver->scan_mode, sizeof(driver->scan_mode))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpio_pin_write(driver->dc, CONFIG_SSD1673_DC_PIN, 0);
|
||||
if (spi_write(driver->spi_dev, &driver->spi_config, &buf_set)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
gpio_pin_write(driver->dc, CONFIG_SSD1673_DC_PIN, 1);
|
||||
/* clear unusable page */
|
||||
if (driver->scan_mode == SSD1673_DATA_ENTRY_XDYIY) {
|
||||
sbuf.buf = dummy_page;
|
||||
sbuf.len = sizeof(dummy_page);
|
||||
if (spi_write(driver->spi_dev, &driver->spi_config, &buf_set)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
sbuf.buf = (u8_t *)buf;
|
||||
sbuf.len = desc->buf_size;
|
||||
if (spi_write(driver->spi_dev, &driver->spi_config, &buf_set)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* clear unusable page */
|
||||
if (driver->scan_mode == SSD1673_DATA_ENTRY_XIYDY) {
|
||||
sbuf.buf = dummy_page;
|
||||
sbuf.len = sizeof(dummy_page);
|
||||
if (spi_write(driver->spi_dev, &driver->spi_config, &buf_set)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (update) {
|
||||
if (driver->contrast) {
|
||||
return ssd1673_update_display(dev, true);
|
||||
}
|
||||
return ssd1673_update_display(dev, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1673_read(const struct device *dev, const u16_t x,
|
||||
const u16_t y,
|
||||
const struct display_buffer_descriptor *desc,
|
||||
void *buf)
|
||||
{
|
||||
LOG_ERR("not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static void *ssd1673_get_framebuffer(const struct device *dev)
|
||||
{
|
||||
LOG_ERR("not supported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ssd1673_set_brightness(const struct device *dev,
|
||||
const u8_t brightness)
|
||||
{
|
||||
LOG_WRN("not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int ssd1673_set_contrast(const struct device *dev, u8_t contrast)
|
||||
{
|
||||
struct ssd1673_data *driver = dev->driver_data;
|
||||
|
||||
driver->contrast = contrast;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ssd1673_get_capabilities(const struct device *dev,
|
||||
struct display_capabilities *caps)
|
||||
{
|
||||
memset(caps, 0, sizeof(struct display_capabilities));
|
||||
caps->x_resolution = EPD_PANEL_WIDTH;
|
||||
caps->y_resolution = EPD_PANEL_HEIGHT;
|
||||
caps->supported_pixel_formats = PIXEL_FORMAT_MONO10;
|
||||
caps->current_pixel_format = PIXEL_FORMAT_MONO10;
|
||||
caps->screen_info = SCREEN_INFO_MONO_VTILED |
|
||||
SCREEN_INFO_MONO_MSB_FIRST |
|
||||
SCREEN_INFO_EPD;
|
||||
}
|
||||
|
||||
static int ssd1673_set_pixel_format(const struct device *dev,
|
||||
const enum display_pixel_format pf)
|
||||
{
|
||||
LOG_ERR("not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int ssd1673_controller_init(struct device *dev)
|
||||
{
|
||||
struct ssd1673_data *driver = dev->driver_data;
|
||||
u8_t tmp[3];
|
||||
|
||||
LOG_DBG("");
|
||||
|
||||
gpio_pin_write(driver->reset, CONFIG_SSD1673_RESET_PIN, 0);
|
||||
k_sleep(SSD1673_RESET_DELAY);
|
||||
gpio_pin_write(driver->reset, CONFIG_SSD1673_RESET_PIN, 1);
|
||||
k_sleep(SSD1673_RESET_DELAY);
|
||||
ssd1673_busy_wait(driver);
|
||||
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_SW_RESET, NULL, 0)) {
|
||||
return -1;
|
||||
}
|
||||
ssd1673_busy_wait(driver);
|
||||
|
||||
tmp[0] = (SSD1673_RAM_YRES - 1);
|
||||
tmp[1] = 0;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_GDO_CTRL, tmp, 2)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp[0] = SSD1673_VAL_GDV_CTRL_A;
|
||||
tmp[1] = SSD1673_VAL_GDV_CTRL_B;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_GDV_CTRL, tmp, 2)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp[0] = SSD1673_VAL_SDV_CTRL;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_SDV_CTRL, tmp, 1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp[0] = SSD1673_VAL_VCOM_VOLTAGE;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_VCOM_VOLTAGE, tmp, 1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp[0] = SSD1673_VAL_DUMMY_LINE;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_DUMMY_LINE, tmp, 1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp[0] = SSD1673_VAL_GATE_LWIDTH;
|
||||
if (ssd1673_write_cmd(driver, SSD1673_CMD_GATE_LINE_WIDTH, tmp, 1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssd1673_set_orientation(driver);
|
||||
driver->numof_part_cycles = 0;
|
||||
driver->last_lut = SSD1673_LAST_LUT_INITIAL;
|
||||
driver->contrast = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1673_init(struct device *dev)
|
||||
{
|
||||
struct ssd1673_data *driver = dev->driver_data;
|
||||
|
||||
LOG_DBG("");
|
||||
|
||||
driver->spi_dev = device_get_binding(CONFIG_SSD1673_SPI_DEV_NAME);
|
||||
if (driver->spi_dev == NULL) {
|
||||
LOG_ERR("Could not get SPI device for SSD1673");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
driver->spi_config.frequency = CONFIG_SSD1673_SPI_FREQ;
|
||||
driver->spi_config.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8);
|
||||
driver->spi_config.slave = CONFIG_SSD1673_SPI_SLAVE_NUMBER;
|
||||
driver->spi_config.cs = NULL;
|
||||
|
||||
driver->reset = device_get_binding(CONFIG_SSD1673_RESET_GPIO_PORT_NAME);
|
||||
if (driver->reset == NULL) {
|
||||
LOG_ERR("Could not get GPIO port for SSD1673 reset");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
gpio_pin_configure(driver->reset, CONFIG_SSD1673_RESET_PIN,
|
||||
GPIO_DIR_OUT);
|
||||
|
||||
driver->dc = device_get_binding(CONFIG_SSD1673_DC_GPIO_PORT_NAME);
|
||||
if (driver->dc == NULL) {
|
||||
LOG_ERR("Could not get GPIO port for SSD1673 DC signal");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
gpio_pin_configure(driver->dc, CONFIG_SSD1673_DC_PIN,
|
||||
GPIO_DIR_OUT);
|
||||
|
||||
driver->busy = device_get_binding(CONFIG_SSD1673_BUSY_GPIO_PORT_NAME);
|
||||
if (driver->busy == NULL) {
|
||||
LOG_ERR("Could not get GPIO port for SSD1673 busy signal");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
gpio_pin_configure(driver->busy, CONFIG_SSD1673_BUSY_PIN,
|
||||
GPIO_DIR_IN);
|
||||
|
||||
#if defined(CONFIG_SSD1673_SPI_GPIO_CS)
|
||||
driver->cs_ctrl.gpio_dev = device_get_binding(
|
||||
CONFIG_SSD1673_SPI_GPIO_CS_DRV_NAME);
|
||||
if (!driver->cs_ctrl.gpio_dev) {
|
||||
LOG_ERR("Unable to get SPI GPIO CS device");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
driver->cs_ctrl.gpio_pin = CONFIG_SSD1673_SPI_GPIO_CS_PIN;
|
||||
driver->cs_ctrl.delay = 0;
|
||||
driver->spi_config.cs = &driver->cs_ctrl;
|
||||
#endif
|
||||
|
||||
ssd1673_controller_init(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ssd1673_data ssd1673_driver;
|
||||
|
||||
static struct display_driver_api ssd1673_driver_api = {
|
||||
.blanking_on = ssd1673_resume,
|
||||
.blanking_off = ssd1673_suspend,
|
||||
.write = ssd1673_write,
|
||||
.read = ssd1673_read,
|
||||
.get_framebuffer = ssd1673_get_framebuffer,
|
||||
.set_brightness = ssd1673_set_brightness,
|
||||
.set_contrast = ssd1673_set_contrast,
|
||||
.get_capabilities = ssd1673_get_capabilities,
|
||||
.set_pixel_format = ssd1673_set_pixel_format,
|
||||
.set_orientation = NULL,
|
||||
};
|
||||
|
||||
|
||||
DEVICE_AND_API_INIT(ssd1673, CONFIG_SSD1673_DEV_NAME, ssd1673_init,
|
||||
&ssd1673_driver, NULL,
|
||||
POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY,
|
||||
&ssd1673_driver_api);
|
88
drivers/display/ssd1673_regs.h
Normal file
88
drivers/display/ssd1673_regs.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/* ssd1673_regs.h - Registers definition for SSD1673 controller */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 PHYTEC Messtechnik GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __SSD1673_REGS_H__
|
||||
#define __SSD1673_REGS_H__
|
||||
|
||||
#define SSD1673_CMD_GDO_CTRL 0x01
|
||||
#define SSD1673_CMD_GDV_CTRL 0x03
|
||||
#define SSD1673_CMD_SDV_CTRL 0x04
|
||||
#define SSD1673_CMD_GSCAN_START 0x0f
|
||||
#define SSD1673_CMD_SLEEP_MODE 0x10
|
||||
#define SSD1673_CMD_ENTRY_MODE 0x11
|
||||
#define SSD1673_CMD_SW_RESET 0x12
|
||||
#define SSD1673_CMD_TSENS_CTRL 0x1a
|
||||
#define SSD1673_CMD_MASTER_ACTIVATION 0x20
|
||||
#define SSD1673_CMD_UPDATE_CTRL1 0x21
|
||||
#define SSD1673_CMD_UPDATE_CTRL2 0x22
|
||||
#define SSD1673_CMD_WRITE_RAM 0x24
|
||||
#define SSD1673_CMD_VCOM_SENSE 0x28
|
||||
#define SSD1673_CMD_VCOM_SENSE_DURATON 0x29
|
||||
#define SSD1673_CMD_PRGM_VCOM_OTP 0x2a
|
||||
#define SSD1673_CMD_VCOM_VOLTAGE 0x2c
|
||||
#define SSD1673_CMD_PRGM_WS_OTP 0x30
|
||||
#define SSD1673_CMD_UPDATE_LUT 0x32
|
||||
#define SSD1673_CMD_PRGM_OTP_SELECTION 0x36
|
||||
#define SSD1673_CMD_OTP_SELECTION_CTRL 0x37
|
||||
#define SSD1673_CMD_DUMMY_LINE 0x3a
|
||||
#define SSD1673_CMD_GATE_LINE_WIDTH 0x3b
|
||||
#define SSD1673_CMD_BWF_CTRL 0x3c
|
||||
#define SSD1673_CMD_RAM_XPOS_CTRL 0x44
|
||||
#define SSD1673_CMD_RAM_YPOS_CTRL 0x45
|
||||
#define SSD1673_CMD_RAM_XPOS_CNTR 0x4e
|
||||
#define SSD1673_CMD_RAM_YPOS_CNTR 0x4f
|
||||
|
||||
/* Data entry sequence modes */
|
||||
#define SSD1673_DATA_ENTRY_MASK 0x07
|
||||
#define SSD1673_DATA_ENTRY_XDYDX 0x00
|
||||
#define SSD1673_DATA_ENTRY_XIYDX 0x01
|
||||
#define SSD1673_DATA_ENTRY_XDYIX 0x02
|
||||
#define SSD1673_DATA_ENTRY_XIYIX 0x03
|
||||
#define SSD1673_DATA_ENTRY_XDYDY 0x04
|
||||
#define SSD1673_DATA_ENTRY_XIYDY 0x05
|
||||
#define SSD1673_DATA_ENTRY_XDYIY 0x06
|
||||
#define SSD1673_DATA_ENTRY_XIYIY 0x07
|
||||
|
||||
/* Options for display update */
|
||||
#define SSD1673_CTRL1_INITIAL_UPDATE_LL 0x00
|
||||
#define SSD1673_CTRL1_INITIAL_UPDATE_LH 0x01
|
||||
#define SSD1673_CTRL1_INITIAL_UPDATE_HL 0x02
|
||||
#define SSD1673_CTRL1_INITIAL_UPDATE_HH 0x03
|
||||
|
||||
/* Options for display update sequence */
|
||||
#define SSD1673_CTRL2_ENABLE_CLK 0x80
|
||||
#define SSD1673_CTRL2_ENABLE_ANALOG 0x40
|
||||
#define SSD1673_CTRL2_TO_INITIAL 0x08
|
||||
#define SSD1673_CTRL2_TO_PATTERN 0x04
|
||||
#define SSD1673_CTRL2_DISABLE_ANALOG 0x02
|
||||
#define SSD1673_CTRL2_DISABLE_CLK 0x01
|
||||
|
||||
#define SSD1673_SLEEP_MODE_DSM 0x01
|
||||
#define SSD1673_SLEEP_MODE_PON 0x00
|
||||
|
||||
/* Default values */
|
||||
#define SSD1673_VAL_GDV_CTRL_A 16
|
||||
#define SSD1673_VAL_GDV_CTRL_B 10
|
||||
#define SSD1673_VAL_SDV_CTRL 0x19
|
||||
#define SSD1673_VAL_VCOM_VOLTAGE 0xa8
|
||||
#define SSD1673_VAL_DUMMY_LINE 0x1a
|
||||
#define SSD1673_VAL_GATE_LWIDTH 0x08
|
||||
|
||||
/** Maximum resolution in the X direction */
|
||||
#define SSD1673_RAM_XRES 152
|
||||
/** Maximum resolution in the Y direction */
|
||||
#define SSD1673_RAM_YRES 250
|
||||
|
||||
/* time constants in ms */
|
||||
#define SSD1673_RESET_DELAY 1
|
||||
#define SSD1673_BUSY_DELAY 1
|
||||
|
||||
/** Size of each RAM in octets */
|
||||
#define SSD1673_RAM_SIZE (SSD1673_RAM_XRES * SSD1673_RAM_YRES / 8)
|
||||
|
||||
#endif /* __SSD1673_REGS_H__ */
|
53
dts/bindings/display/solomon,ssd1673fb.yaml
Normal file
53
dts/bindings/display/solomon,ssd1673fb.yaml
Normal file
|
@ -0,0 +1,53 @@
|
|||
#
|
||||
# Copyright (c) 2018, Phytec Messtechnik GmbH
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
---
|
||||
title: SSD1673 250x150 EPD Display Controller
|
||||
id: solomon,ssd1673fb-spi
|
||||
version: 0.1
|
||||
|
||||
description: >
|
||||
This is a representation of the SSD1673 250x150 EPD Display Controller
|
||||
|
||||
inherits:
|
||||
!include spi-device.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
constraint: "solomon,ssd1673fb-spi"
|
||||
|
||||
height:
|
||||
type: int
|
||||
category: required
|
||||
generation: Height in pixel of the panel driven by the controller
|
||||
|
||||
width:
|
||||
type: int
|
||||
category: required
|
||||
generation: Width in pixel of the panel driven by the controller
|
||||
|
||||
orientation-flipped:
|
||||
type: string
|
||||
category: optional
|
||||
generation: Last column address is mapped to first segment
|
||||
|
||||
reset-gpios:
|
||||
type: compound
|
||||
category: required
|
||||
generation: define, use-prop-name
|
||||
|
||||
dc-gpios:
|
||||
type: compound
|
||||
category: required
|
||||
generation: define, use-prop-name
|
||||
|
||||
busy-gpios:
|
||||
type: compound
|
||||
category: required
|
||||
generation: define, use-prop-name
|
||||
|
||||
base_label: SSD1673
|
||||
|
||||
...
|
Loading…
Add table
Add a link
Reference in a new issue