led_strip: ws2812: convert to spi_dt_spec

Convert ws2812 LED strip driver to `spi_dt_spec`. Also moves the init
function implementation outside the declaration macro.

Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
This commit is contained in:
Jordan Yates 2021-08-07 13:10:03 +10:00 committed by Christopher Friedt
parent 8d84626cab
commit 7065aec5e2

View file

@ -36,12 +36,8 @@ LOG_MODULE_REGISTER(ws2812_spi);
#define SPI_OPER (SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | \ #define SPI_OPER (SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | \
SPI_WORD_SET(SPI_FRAME_BITS) | SPI_LINES_SINGLE) SPI_WORD_SET(SPI_FRAME_BITS) | SPI_LINES_SINGLE)
struct ws2812_spi_data {
const struct device *spi;
};
struct ws2812_spi_cfg { struct ws2812_spi_cfg {
struct spi_config spi_cfg; struct spi_dt_spec bus;
uint8_t *px_buf; uint8_t *px_buf;
size_t px_buf_size; size_t px_buf_size;
uint8_t one_frame; uint8_t one_frame;
@ -51,11 +47,6 @@ struct ws2812_spi_cfg {
uint16_t reset_delay; uint16_t reset_delay;
}; };
static struct ws2812_spi_data *dev_data(const struct device *dev)
{
return dev->data;
}
static const struct ws2812_spi_cfg *dev_cfg(const struct device *dev) static const struct ws2812_spi_cfg *dev_cfg(const struct device *dev)
{ {
return dev->config; return dev->config;
@ -155,7 +146,7 @@ static int ws2812_strip_update_rgb(const struct device *dev,
/* /*
* Display the pixel data. * Display the pixel data.
*/ */
rc = spi_write(dev_data(dev)->spi, &cfg->spi_cfg, &tx); rc = spi_write_dt(&cfg->bus, &tx);
ws2812_reset_delay(cfg->reset_delay); ws2812_reset_delay(cfg->reset_delay);
return rc; return rc;
@ -169,6 +160,34 @@ static int ws2812_strip_update_channels(const struct device *dev,
return -ENOTSUP; return -ENOTSUP;
} }
static int ws2812_spi_init(const struct device *dev)
{
const struct ws2812_spi_cfg *cfg = dev_cfg(dev);
uint8_t i;
if (!spi_is_ready(&cfg->bus)) {
LOG_ERR("SPI device %s not ready", cfg->bus.bus->name);
return -ENODEV;
}
for (i = 0; i < cfg->num_colors; i++) {
switch (cfg->color_mapping[i]) {
case LED_COLOR_ID_WHITE:
case LED_COLOR_ID_RED:
case LED_COLOR_ID_GREEN:
case LED_COLOR_ID_BLUE:
break;
default:
LOG_ERR("%s: invalid channel to color mapping."
"Check the color-mapping DT property",
dev->name);
return -EINVAL;
}
}
return 0;
}
static const struct led_strip_driver_api ws2812_spi_api = { static const struct led_strip_driver_api ws2812_spi_api = {
.update_rgb = ws2812_strip_update_rgb, .update_rgb = ws2812_strip_update_rgb,
.update_channels = ws2812_strip_update_channels, .update_channels = ws2812_strip_update_channels,
@ -178,15 +197,9 @@ static const struct led_strip_driver_api ws2812_spi_api = {
(DT_INST_PROP(idx, chain_length)) (DT_INST_PROP(idx, chain_length))
#define WS2812_SPI_HAS_WHITE(idx) \ #define WS2812_SPI_HAS_WHITE(idx) \
(DT_INST_PROP(idx, has_white_channel) == 1) (DT_INST_PROP(idx, has_white_channel) == 1)
#define WS2812_SPI_BUS(idx) \
(DT_INST_BUS_LABEL(idx))
#define WS2812_SPI_SLAVE(idx) \
(DT_INST_REG_ADDR(idx))
#define WS2812_SPI_FREQ(idx) \
(DT_INST_PROP(idx, spi_max_frequency))
#define WS2812_SPI_ONE_FRAME(idx) \ #define WS2812_SPI_ONE_FRAME(idx) \
(DT_INST_PROP(idx, spi_one_frame)) (DT_INST_PROP(idx, spi_one_frame))
#define WS2812_SPI_ZERO_FRAME(idx)\ #define WS2812_SPI_ZERO_FRAME(idx) \
(DT_INST_PROP(idx, spi_zero_frame)) (DT_INST_PROP(idx, spi_zero_frame))
#define WS2812_SPI_BUFSZ(idx) \ #define WS2812_SPI_BUFSZ(idx) \
(WS2812_NUM_COLORS(idx) * 8 * WS2812_SPI_NUM_PIXELS(idx)) (WS2812_NUM_COLORS(idx) * 8 * WS2812_SPI_NUM_PIXELS(idx))
@ -195,77 +208,39 @@ static const struct led_strip_driver_api ws2812_spi_api = {
* Retrieve the channel to color mapping (e.g. RGB, BGR, GRB, ...) from the * Retrieve the channel to color mapping (e.g. RGB, BGR, GRB, ...) from the
* "color-mapping" DT property. * "color-mapping" DT property.
*/ */
#define WS2812_COLOR_MAPPING(idx) \ #define WS2812_COLOR_MAPPING(idx) \
static const uint8_t ws2812_spi_##idx##_color_mapping[] = \ static const uint8_t ws2812_spi_##idx##_color_mapping[] = \
DT_INST_PROP(idx, color_mapping) DT_INST_PROP(idx, color_mapping)
#define WS2812_NUM_COLORS(idx) (DT_INST_PROP_LEN(idx, color_mapping)) #define WS2812_NUM_COLORS(idx) (DT_INST_PROP_LEN(idx, color_mapping))
/* Get the latch/reset delay from the "reset-delay" DT property. */ /* Get the latch/reset delay from the "reset-delay" DT property. */
#define WS2812_RESET_DELAY(idx) DT_INST_PROP(idx, reset_delay) #define WS2812_RESET_DELAY(idx) DT_INST_PROP(idx, reset_delay)
#define WS2812_SPI_DEVICE(idx) \ #define WS2812_SPI_DEVICE(idx) \
\ \
static struct ws2812_spi_data ws2812_spi_##idx##_data; \ static uint8_t ws2812_spi_##idx##_px_buf[WS2812_SPI_BUFSZ(idx)]; \
\ \
static uint8_t ws2812_spi_##idx##_px_buf[WS2812_SPI_BUFSZ(idx)]; \ WS2812_COLOR_MAPPING(idx); \
\ \
WS2812_COLOR_MAPPING(idx); \ static const struct ws2812_spi_cfg ws2812_spi_##idx##_cfg = { \
\ .bus = SPI_DT_SPEC_INST_GET(idx, SPI_OPER, 0), \
static const struct ws2812_spi_cfg ws2812_spi_##idx##_cfg = { \ .px_buf = ws2812_spi_##idx##_px_buf, \
.spi_cfg = { \ .px_buf_size = WS2812_SPI_BUFSZ(idx), \
.frequency = WS2812_SPI_FREQ(idx), \ .one_frame = WS2812_SPI_ONE_FRAME(idx), \
.operation = SPI_OPER, \ .zero_frame = WS2812_SPI_ZERO_FRAME(idx), \
.slave = WS2812_SPI_SLAVE(idx), \ .num_colors = WS2812_NUM_COLORS(idx), \
.cs = NULL, \ .color_mapping = ws2812_spi_##idx##_color_mapping, \
}, \ .reset_delay = WS2812_RESET_DELAY(idx), \
.px_buf = ws2812_spi_##idx##_px_buf, \ }; \
.px_buf_size = WS2812_SPI_BUFSZ(idx), \ \
.one_frame = WS2812_SPI_ONE_FRAME(idx), \ DEVICE_DT_INST_DEFINE(idx, \
.zero_frame = WS2812_SPI_ZERO_FRAME(idx), \ ws2812_spi_init, \
.num_colors = WS2812_NUM_COLORS(idx), \ NULL, \
.color_mapping = ws2812_spi_##idx##_color_mapping, \ NULL, \
.reset_delay = WS2812_RESET_DELAY(idx), \ &ws2812_spi_##idx##_cfg, \
}; \ POST_KERNEL, \
\ CONFIG_LED_STRIP_INIT_PRIORITY, \
static int ws2812_spi_##idx##_init(const struct device *dev) \ &ws2812_spi_api);
{ \
struct ws2812_spi_data *data = dev_data(dev); \
const struct ws2812_spi_cfg *cfg = dev_cfg(dev); \
uint8_t i; \
\
data->spi = device_get_binding(WS2812_SPI_BUS(idx)); \
if (!data->spi) { \
LOG_ERR("SPI device %s not found", \
WS2812_SPI_BUS(idx)); \
return -ENODEV; \
} \
\
for (i = 0; i < cfg->num_colors; i++) { \
switch (cfg->color_mapping[i]) { \
case LED_COLOR_ID_WHITE: \
case LED_COLOR_ID_RED: \
case LED_COLOR_ID_GREEN: \
case LED_COLOR_ID_BLUE: \
break; \
default: \
LOG_ERR("%s: invalid channel to color mapping." \
"Check the color-mapping DT property", \
dev->name); \
return -EINVAL; \
} \
} \
\
return 0; \
} \
\
DEVICE_DT_INST_DEFINE(idx, \
ws2812_spi_##idx##_init, \
NULL, \
&ws2812_spi_##idx##_data, \
&ws2812_spi_##idx##_cfg, \
POST_KERNEL, \
CONFIG_LED_STRIP_INIT_PRIORITY, \
&ws2812_spi_api);
DT_INST_FOREACH_STATUS_OKAY(WS2812_SPI_DEVICE) DT_INST_FOREACH_STATUS_OKAY(WS2812_SPI_DEVICE)