drivers: display: uc81xx: add support for uc8175
Add support for uc8175 display driver. uc8175 has a slightly different command/data length requirements for certain registers, namely TRES and PTL, compared to uc8176/uc8179 This commit refactors the driver code and such that setting TRES and PTL registers are now done by function pointers provided by config->quirks, by the same token as how it is done for setting CDI register Signed-off-by: Xiao Qin <xiaoq@google.com>
This commit is contained in:
parent
2b20c0e3e6
commit
7c46b0b898
|
@ -6,7 +6,7 @@
|
|||
config UC81XX
|
||||
bool "UltraChip UC81xx compatible display controller driver"
|
||||
default y
|
||||
depends on DT_HAS_ULTRACHIP_UC8176_ENABLED || DT_HAS_ULTRACHIP_UC8179_ENABLED
|
||||
depends on DT_HAS_ULTRACHIP_UC8175_ENABLED || DT_HAS_ULTRACHIP_UC8176_ENABLED || DT_HAS_ULTRACHIP_UC8179_ENABLED
|
||||
select SPI
|
||||
help
|
||||
Enable driver for UC81xx compatible controller.
|
||||
|
|
|
@ -66,6 +66,10 @@ struct uc81xx_quirks {
|
|||
bool auto_copy;
|
||||
|
||||
int (*set_cdi)(const struct device *dev, bool border);
|
||||
int (*set_tres)(const struct device *dev);
|
||||
int (*set_ptl)(const struct device *dev, uint16_t x, uint16_t y,
|
||||
uint16_t x_end_idx, uint16_t y_end_idx,
|
||||
const struct display_buffer_descriptor *desc);
|
||||
};
|
||||
|
||||
struct uc81xx_config {
|
||||
|
@ -224,10 +228,6 @@ static int uc81xx_set_profile(const struct device *dev,
|
|||
UC81XX_PSR_SHL |
|
||||
UC81XX_PSR_SHD |
|
||||
UC81XX_PSR_RST;
|
||||
const struct uc81xx_tres tres = {
|
||||
.hres = sys_cpu_to_be16(config->width),
|
||||
.vres = sys_cpu_to_be16(config->height),
|
||||
};
|
||||
|
||||
if (type >= UC81XX_NUM_PROFILES) {
|
||||
return -EINVAL;
|
||||
|
@ -272,9 +272,7 @@ static int uc81xx_set_profile(const struct device *dev,
|
|||
}
|
||||
|
||||
/* Set panel resolution */
|
||||
LOG_HEXDUMP_DBG(&tres, sizeof(tres), "TRES");
|
||||
if (uc81xx_write_cmd(dev, UC81XX_CMD_TRES,
|
||||
(const void *)&tres, sizeof(tres))) {
|
||||
if (config->quirks->set_tres(dev)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -403,13 +401,6 @@ static int uc81xx_write(const struct device *dev, const uint16_t x, const uint16
|
|||
|
||||
uint16_t x_end_idx = x + desc->width - 1;
|
||||
uint16_t y_end_idx = y + desc->height - 1;
|
||||
const struct uc81xx_ptl ptl = {
|
||||
.hrst = sys_cpu_to_be16(x),
|
||||
.hred = sys_cpu_to_be16(x_end_idx),
|
||||
.vrst = sys_cpu_to_be16(y),
|
||||
.vred = sys_cpu_to_be16(y_end_idx),
|
||||
.flags = UC81XX_PTL_FLAG_PT_SCAN,
|
||||
};
|
||||
size_t buf_len;
|
||||
const uint8_t back_buffer = data->blanking_on ?
|
||||
UC81XX_CMD_DTM1 : UC81XX_CMD_DTM2;
|
||||
|
@ -448,15 +439,11 @@ static int uc81xx_write(const struct device *dev, const uint16_t x, const uint16
|
|||
}
|
||||
}
|
||||
|
||||
/* Setup Partial Window and enable Partial Mode */
|
||||
LOG_HEXDUMP_DBG(&ptl, sizeof(ptl), "ptl");
|
||||
|
||||
if (uc81xx_write_cmd(dev, UC81XX_CMD_PTIN, NULL, 0)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (uc81xx_write_cmd(dev, UC81XX_CMD_PTL,
|
||||
(const void *)&ptl, sizeof(ptl))) {
|
||||
if (config->quirks->set_ptl(dev, x, y, x_end_idx, y_end_idx, desc)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -487,8 +474,7 @@ static int uc81xx_write(const struct device *dev, const uint16_t x, const uint16
|
|||
* needed.
|
||||
*/
|
||||
|
||||
if (uc81xx_write_cmd(dev, UC81XX_CMD_PTL,
|
||||
(const void *)&ptl, sizeof(ptl))) {
|
||||
if (config->quirks->set_ptl(dev, x, y, x_end_idx, y_end_idx, desc)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -654,7 +640,73 @@ static int uc81xx_init(const struct device *dev)
|
|||
return uc81xx_controller_init(dev);
|
||||
}
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(ultrachip_uc8176)
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(ultrachip_uc8175)
|
||||
static int uc81xx_set_tres_8(const struct device *dev)
|
||||
{
|
||||
const struct uc81xx_config *config = dev->config;
|
||||
const struct uc81xx_tres8 tres = {
|
||||
.hres = config->width,
|
||||
.vres = config->height,
|
||||
};
|
||||
|
||||
LOG_HEXDUMP_DBG(&tres, sizeof(tres), "TRES");
|
||||
|
||||
return uc81xx_write_cmd(dev, UC81XX_CMD_TRES, (const void *)&tres, sizeof(tres));
|
||||
}
|
||||
|
||||
static inline int uc81xx_set_ptl_8(const struct device *dev, uint16_t x, uint16_t y,
|
||||
uint16_t x_end_idx, uint16_t y_end_idx,
|
||||
const struct display_buffer_descriptor *desc)
|
||||
{
|
||||
const struct uc81xx_ptl8 ptl = {
|
||||
.hrst = x,
|
||||
.hred = x_end_idx,
|
||||
.vrst = y,
|
||||
.vred = y_end_idx,
|
||||
.flags = UC81XX_PTL_FLAG_PT_SCAN,
|
||||
};
|
||||
|
||||
/* Setup Partial Window and enable Partial Mode */
|
||||
LOG_HEXDUMP_DBG(&ptl, sizeof(ptl), "ptl");
|
||||
|
||||
return uc81xx_write_cmd(dev, UC81XX_CMD_PTL, (const void *)&ptl, sizeof(ptl));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(ultrachip_uc8176) || DT_HAS_COMPAT_STATUS_OKAY(ultrachip_uc8179)
|
||||
static int uc81xx_set_tres_16(const struct device *dev)
|
||||
{
|
||||
const struct uc81xx_config *config = dev->config;
|
||||
const struct uc81xx_tres8 tres = {
|
||||
.hres = sys_cpu_to_be16(config->width),
|
||||
.vres = sys_cpu_to_be16(config->height),
|
||||
};
|
||||
|
||||
LOG_HEXDUMP_DBG(&tres, sizeof(tres), "TRES");
|
||||
|
||||
return uc81xx_write_cmd(dev, UC81XX_CMD_TRES, (const void *)&tres, sizeof(tres));
|
||||
}
|
||||
|
||||
static inline int uc81xx_set_ptl_16(const struct device *dev, uint16_t x, uint16_t y,
|
||||
uint16_t x_end_idx, uint16_t y_end_idx,
|
||||
const struct display_buffer_descriptor *desc)
|
||||
{
|
||||
const struct uc81xx_ptl16 ptl = {
|
||||
.hrst = sys_cpu_to_be16(x),
|
||||
.hred = sys_cpu_to_be16(x_end_idx),
|
||||
.vrst = sys_cpu_to_be16(y),
|
||||
.vred = sys_cpu_to_be16(y_end_idx),
|
||||
.flags = UC81XX_PTL_FLAG_PT_SCAN,
|
||||
};
|
||||
|
||||
/* Setup Partial Window and enable Partial Mode */
|
||||
LOG_HEXDUMP_DBG(&ptl, sizeof(ptl), "ptl");
|
||||
|
||||
return uc81xx_write_cmd(dev, UC81XX_CMD_PTL, (const void *)&ptl, sizeof(ptl));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(ultrachip_uc8175) || DT_HAS_COMPAT_STATUS_OKAY(ultrachip_uc8176)
|
||||
static int uc8176_set_cdi(const struct device *dev, bool border)
|
||||
{
|
||||
const struct uc81xx_config *config = dev->config;
|
||||
|
@ -675,7 +727,22 @@ static int uc8176_set_cdi(const struct device *dev, bool border)
|
|||
LOG_DBG("CDI: %#hhx", cdi);
|
||||
return uc81xx_write_cmd_uint8(dev, UC81XX_CMD_CDI, cdi);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(ultrachip_uc8175)
|
||||
static const struct uc81xx_quirks uc8175_quirks = {
|
||||
.max_width = 80,
|
||||
.max_height = 160,
|
||||
|
||||
.auto_copy = false,
|
||||
|
||||
.set_cdi = uc8176_set_cdi,
|
||||
.set_tres = uc81xx_set_tres_8,
|
||||
.set_ptl = uc81xx_set_ptl_8,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(ultrachip_uc8176)
|
||||
static const struct uc81xx_quirks uc8176_quirks = {
|
||||
.max_width = 400,
|
||||
.max_height = 300,
|
||||
|
@ -683,6 +750,8 @@ static const struct uc81xx_quirks uc8176_quirks = {
|
|||
.auto_copy = false,
|
||||
|
||||
.set_cdi = uc8176_set_cdi,
|
||||
.set_tres = uc81xx_set_tres_16,
|
||||
.set_ptl = uc81xx_set_ptl_16,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -714,6 +783,8 @@ static const struct uc81xx_quirks uc8179_quirks = {
|
|||
.auto_copy = true,
|
||||
|
||||
.set_cdi = uc8179_set_cdi,
|
||||
.set_tres = uc81xx_set_tres_16,
|
||||
.set_ptl = uc81xx_set_ptl_16,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -814,6 +885,9 @@ static struct display_driver_api uc81xx_driver_api = {
|
|||
CONFIG_DISPLAY_INIT_PRIORITY, \
|
||||
&uc81xx_driver_api);
|
||||
|
||||
DT_FOREACH_STATUS_OKAY_VARGS(ultrachip_uc8175, UC81XX_DEFINE,
|
||||
&uc8175_quirks);
|
||||
|
||||
DT_FOREACH_STATUS_OKAY_VARGS(ultrachip_uc8176, UC81XX_DEFINE,
|
||||
&uc8176_quirks);
|
||||
|
||||
|
|
|
@ -106,14 +106,31 @@
|
|||
#define UC8179_CDI_DDX1 BIT(1)
|
||||
#define UC8179_CDI_DDX0 BIT(0)
|
||||
|
||||
struct uc81xx_tres {
|
||||
struct uc81xx_tres8 {
|
||||
uint8_t hres;
|
||||
uint8_t vres;
|
||||
} __packed;
|
||||
|
||||
BUILD_ASSERT(sizeof(struct uc81xx_tres8) == 2);
|
||||
|
||||
struct uc81xx_ptl8 {
|
||||
uint8_t hrst;
|
||||
uint8_t hred;
|
||||
uint8_t vrst;
|
||||
uint8_t vred;
|
||||
uint8_t flags;
|
||||
} __packed;
|
||||
|
||||
BUILD_ASSERT(sizeof(struct uc81xx_ptl8) == 5);
|
||||
|
||||
struct uc81xx_tres16 {
|
||||
uint16_t hres;
|
||||
uint16_t vres;
|
||||
} __packed;
|
||||
|
||||
BUILD_ASSERT(sizeof(struct uc81xx_tres) == 4);
|
||||
BUILD_ASSERT(sizeof(struct uc81xx_tres16) == 4);
|
||||
|
||||
struct uc81xx_ptl {
|
||||
struct uc81xx_ptl16 {
|
||||
uint16_t hrst;
|
||||
uint16_t hred;
|
||||
uint16_t vrst;
|
||||
|
@ -121,11 +138,10 @@ struct uc81xx_ptl {
|
|||
uint8_t flags;
|
||||
} __packed;
|
||||
|
||||
BUILD_ASSERT(sizeof(struct uc81xx_ptl) == 9);
|
||||
BUILD_ASSERT(sizeof(struct uc81xx_ptl16) == 9);
|
||||
|
||||
#define UC81XX_PTL_FLAG_PT_SCAN BIT(0)
|
||||
|
||||
|
||||
/* Time constants in ms */
|
||||
#define UC81XX_RESET_DELAY 10U
|
||||
#define UC81XX_PON_DELAY 100U
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2022 Andreas Sandberg
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: UltraChip UC8175 EPD controller
|
||||
|
||||
compatible: "ultrachip,uc8175"
|
||||
|
||||
include: ultrachip,uc81xx-common.yaml
|
Loading…
Reference in New Issue