From dc860cd6aa82fbdaad468f2bdacb4e75ea433ad8 Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Thu, 14 Jul 2022 21:32:42 +0100 Subject: [PATCH] drivers: gd7965: Make it possible to use multiple instances Add instance-specific data and config structs, and remove all other global variables. Signed-off-by: Andreas Sandberg --- drivers/display/gd7965.c | 140 +++++++++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 43 deletions(-) diff --git a/drivers/display/gd7965.c b/drivers/display/gd7965.c index daa814b396f..91d1b4d1281 100644 --- a/drivers/display/gd7965.c +++ b/drivers/display/gd7965.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Andreas Sandberg * Copyright (c) 2020 PHYTEC Messtechnik GmbH * * SPDX-License-Identifier: Apache-2.0 @@ -26,24 +27,34 @@ LOG_MODULE_REGISTER(gd7965, CONFIG_DISPLAY_LOG_LEVEL); * also first gate/source should be 0. */ -#define EPD_PANEL_WIDTH DT_INST_PROP(0, width) -#define EPD_PANEL_HEIGHT DT_INST_PROP(0, height) #define GD7965_PIXELS_PER_BYTE 8U +struct gd7965_dt_array { + uint8_t *data; + uint8_t len; +}; + struct gd7965_config { struct spi_dt_spec bus; struct gpio_dt_spec dc_gpio; struct gpio_dt_spec busy_gpio; struct gpio_dt_spec reset_gpio; + + uint16_t height; + uint16_t width; + + uint8_t cdi; + uint8_t tcon; + struct gd7965_dt_array softstart; + struct gd7965_dt_array pwr; }; -static uint8_t gd7965_softstart[] = DT_INST_PROP(0, softstart); -static uint8_t gd7965_pwr[] = DT_INST_PROP(0, pwr); +struct gd7965_data { + bool blanking_on; -/* Border and data polarity settings */ -static uint8_t bdd_polarity; - -static bool blanking_on = true; + /* Border and data polarity settings */ + uint8_t bdd_polarity; +}; static inline int gd7965_write_cmd(const struct device *dev, uint8_t cmd, uint8_t *data, size_t len) @@ -153,7 +164,9 @@ static int gd7965_update_display(const struct device *dev) static int gd7965_blanking_off(const struct device *dev) { - if (blanking_on) { + struct gd7965_data *data = dev->data; + + if (data->blanking_on) { /* Update EPD panel in normal mode */ gd7965_busy_wait(dev); if (gd7965_update_display(dev)) { @@ -161,14 +174,16 @@ static int gd7965_blanking_off(const struct device *dev) } } - blanking_on = false; + data->blanking_on = false; return 0; } static int gd7965_blanking_on(const struct device *dev) { - blanking_on = true; + struct gd7965_data *data = dev->data; + + data->blanking_on = true; return 0; } @@ -177,6 +192,9 @@ static int gd7965_write(const struct device *dev, const uint16_t x, const uint16 const struct display_buffer_descriptor *desc, const void *buf) { + const struct gd7965_config *config = dev->config; + struct gd7965_data *data = dev->data; + uint16_t x_end_idx = x + desc->width - 1; uint16_t y_end_idx = y + desc->height - 1; uint8_t ptl[GD7965_PTL_REG_LENGTH] = {0}; @@ -193,8 +211,8 @@ static int gd7965_write(const struct device *dev, const uint16_t x, const uint16 __ASSERT(!(desc->width % GD7965_PIXELS_PER_BYTE), "Buffer width not multiple of %d", GD7965_PIXELS_PER_BYTE); - if ((y_end_idx > (EPD_PANEL_HEIGHT - 1)) || - (x_end_idx > (EPD_PANEL_WIDTH - 1))) { + if ((y_end_idx > (config->height - 1)) || + (x_end_idx > (config->width - 1))) { LOG_ERR("Position out of bounds"); return -EINVAL; } @@ -217,9 +235,9 @@ static int gd7965_write(const struct device *dev, const uint16_t x, const uint16 } /* Disable boarder output */ - bdd_polarity |= GD7965_CDI_BDZ; + data->bdd_polarity |= GD7965_CDI_BDZ; if (gd7965_write_cmd(dev, GD7965_CMD_CDI, - &bdd_polarity, sizeof(bdd_polarity))) { + &data->bdd_polarity, sizeof(data->bdd_polarity))) { return -EIO; } @@ -228,16 +246,16 @@ static int gd7965_write(const struct device *dev, const uint16_t x, const uint16 } /* Update partial window and disable Partial Mode */ - if (blanking_on == false) { + if (data->blanking_on == false) { if (gd7965_update_display(dev)) { return -EIO; } } /* Enable boarder output */ - bdd_polarity &= ~GD7965_CDI_BDZ; + data->bdd_polarity &= ~GD7965_CDI_BDZ; if (gd7965_write_cmd(dev, GD7965_CMD_CDI, - &bdd_polarity, sizeof(bdd_polarity))) { + &data->bdd_polarity, sizeof(data->bdd_polarity))) { return -EIO; } @@ -277,9 +295,11 @@ static int gd7965_set_contrast(const struct device *dev, uint8_t contrast) static void gd7965_get_capabilities(const struct device *dev, struct display_capabilities *caps) { + const struct gd7965_config *config = dev->config; + memset(caps, 0, sizeof(struct display_capabilities)); - caps->x_resolution = EPD_PANEL_WIDTH; - caps->y_resolution = EPD_PANEL_HEIGHT; + caps->x_resolution = config->width; + caps->y_resolution = config->height; caps->supported_pixel_formats = PIXEL_FORMAT_MONO10; caps->current_pixel_format = PIXEL_FORMAT_MONO10; caps->screen_info = SCREEN_INFO_MONO_MSB_FIRST | SCREEN_INFO_EPD; @@ -307,7 +327,8 @@ static int gd7965_set_pixel_format(const struct device *dev, static int gd7965_clear_and_write_buffer(const struct device *dev, uint8_t pattern, bool update) { - const int size = EPD_PANEL_WIDTH * EPD_PANEL_HEIGHT + const struct gd7965_config *config = dev->config; + const int size = config->width * config->height / GD7965_PIXELS_PER_BYTE; if (gd7965_write_cmd_pattern(dev, GD7965_CMD_DTM1, pattern, size)) { @@ -330,8 +351,11 @@ static int gd7965_clear_and_write_buffer(const struct device *dev, static int gd7965_controller_init(const struct device *dev) { const struct gd7965_config *config = dev->config; + struct gd7965_data *data = dev->data; uint8_t tmp[GD7965_TRES_REG_LENGTH]; + data->blanking_on = true; + gpio_pin_set_dt(&config->reset_gpio, 1); k_sleep(K_MSEC(GD7965_RESET_DELAY)); gpio_pin_set_dt(&config->reset_gpio, 0); @@ -340,13 +364,13 @@ static int gd7965_controller_init(const struct device *dev) LOG_DBG("Initialize GD7965 controller"); - if (gd7965_write_cmd(dev, GD7965_CMD_PWR, gd7965_pwr, - sizeof(gd7965_pwr))) { + if (gd7965_write_cmd(dev, GD7965_CMD_PWR, config->pwr.data, + config->pwr.len)) { return -EIO; } if (gd7965_write_cmd(dev, GD7965_CMD_BTST, - gd7965_softstart, sizeof(gd7965_softstart))) { + config->softstart.data, config->softstart.len)) { return -EIO; } @@ -369,25 +393,25 @@ static int gd7965_controller_init(const struct device *dev) } /* Set panel resolution */ - sys_put_be16(EPD_PANEL_WIDTH, &tmp[GD7965_TRES_HRES_IDX]); - sys_put_be16(EPD_PANEL_HEIGHT, &tmp[GD7965_TRES_VRES_IDX]); + sys_put_be16(config->width, &tmp[GD7965_TRES_HRES_IDX]); + sys_put_be16(config->height, &tmp[GD7965_TRES_VRES_IDX]); LOG_HEXDUMP_DBG(tmp, sizeof(tmp), "TRES"); if (gd7965_write_cmd(dev, GD7965_CMD_TRES, tmp, GD7965_TRES_REG_LENGTH)) { return -EIO; } - bdd_polarity = GD7965_CDI_BDV1 | + data->bdd_polarity = GD7965_CDI_BDV1 | GD7965_CDI_N2OCP | GD7965_CDI_DDX0; - tmp[GD7965_CDI_BDZ_DDX_IDX] = bdd_polarity; - tmp[GD7965_CDI_CDI_IDX] = DT_INST_PROP(0, cdi); + tmp[GD7965_CDI_BDZ_DDX_IDX] = data->bdd_polarity; + tmp[GD7965_CDI_CDI_IDX] = config->cdi; LOG_HEXDUMP_DBG(tmp, GD7965_CDI_REG_LENGTH, "CDI"); if (gd7965_write_cmd(dev, GD7965_CMD_CDI, tmp, GD7965_CDI_REG_LENGTH)) { return -EIO; } - tmp[0] = DT_INST_PROP(0, tcon); + tmp[0] = config->tcon; if (gd7965_write_cmd(dev, GD7965_CMD_TCON, tmp, 1)) { return -EIO; } @@ -441,17 +465,6 @@ static int gd7965_init(const struct device *dev) return gd7965_controller_init(dev); } -static const struct gd7965_config gd7965_config = { - .bus = SPI_DT_SPEC_INST_GET( - 0, - SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | - SPI_LOCK_ON, - 0), - .reset_gpio = GPIO_DT_SPEC_INST_GET(0, reset_gpios), - .dc_gpio = GPIO_DT_SPEC_INST_GET(0, dc_gpios), - .busy_gpio = GPIO_DT_SPEC_INST_GET(0, busy_gpios), -}; - static struct display_driver_api gd7965_driver_api = { .blanking_on = gd7965_blanking_on, .blanking_off = gd7965_blanking_off, @@ -465,6 +478,47 @@ static struct display_driver_api gd7965_driver_api = { .set_orientation = gd7965_set_orientation, }; +#define GD7965_MAKE_INST_ARRAY_OPT(n, p) \ + static uint8_t data_ ## n ## _ ## p[] = DT_INST_PROP_OR(n, p, {}) -DEVICE_DT_INST_DEFINE(0, gd7965_init, NULL, NULL, &gd7965_config, POST_KERNEL, - CONFIG_DISPLAY_INIT_PRIORITY, &gd7965_driver_api); +#define GD7965_MAKE_INST_ARRAY(n, p) \ + static uint8_t data_ ## n ## _ ## p[] = DT_INST_PROP(n, p) + +#define GD7965_ASSIGN_ARRAY(n, p) \ + { \ + .data = data_ ## n ## _ ## p, \ + .len = sizeof(data_ ## n ## _ ## p), \ + } + +#define GD7965_DEFINE(n) \ + GD7965_MAKE_INST_ARRAY(n, softstart); \ + GD7965_MAKE_INST_ARRAY(n, pwr); \ + \ + static const struct gd7965_config gd7965_cfg_##n = { \ + .bus = SPI_DT_SPEC_INST_GET(n, \ + SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ + SPI_LOCK_ON, \ + 0), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET(n, reset_gpios), \ + .dc_gpio = GPIO_DT_SPEC_INST_GET(n, dc_gpios), \ + .busy_gpio = GPIO_DT_SPEC_INST_GET(n, busy_gpios), \ + \ + .height = DT_INST_PROP(n, height), \ + .width = DT_INST_PROP(n, width), \ + \ + .cdi = DT_INST_PROP(n, cdi), \ + .tcon = DT_INST_PROP(n, tcon), \ + .softstart = GD7965_ASSIGN_ARRAY(n, softstart), \ + .pwr = GD7965_ASSIGN_ARRAY(n, pwr), \ + }; \ + \ + static struct gd7965_data gd7965_data_##n = {}; \ + \ + DEVICE_DT_INST_DEFINE(n, gd7965_init, NULL, \ + &gd7965_data_##n, \ + &gd7965_cfg_##n, \ + POST_KERNEL, \ + CONFIG_DISPLAY_INIT_PRIORITY, \ + &gd7965_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(GD7965_DEFINE)