led_strip: ws2812: allow to configure reset delay

Some devices compatibles with the WS2812 IC have a different reset/latch
delay.

This patch introduces the "reset-delay" optional property for the WS2812
DT binding and adds support to the ws2812_spi driver. This new property
allows to configure the reset/latch delay of a WS2812 compatible LED
strip controller from its DT node.

If omitted the driver uses 8 microseconds by default (which is good for
the WS2812 IC).

Signed-off-by: Simon Guinot <simon.guinot@seagate.com>
This commit is contained in:
Simon Guinot 2021-05-18 17:36:14 +02:00 committed by Carles Cufí
parent 4ada0bbd6e
commit 17c0ddfe9c
2 changed files with 20 additions and 11 deletions

View file

@ -26,14 +26,6 @@ LOG_MODULE_REGISTER(ws2812_spi);
/* spi-one-frame and spi-zero-frame in DT are for 8-bit frames. */
#define SPI_FRAME_BITS 8
/*
* Delay time to make sure the strip has latched a signal.
*
* Despite datasheet claims, a 6 microsecond delay is enough to reset
* the strip. Delay for 8 usec just to be safe.
*/
#define RESET_DELAY_USEC 8
/*
* SPI master configuration:
*
@ -56,6 +48,7 @@ struct ws2812_spi_cfg {
uint8_t zero_frame;
uint8_t num_colors;
const uint8_t *color_mapping;
uint16_t reset_delay;
};
static struct ws2812_spi_data *dev_data(const struct device *dev)
@ -100,13 +93,13 @@ static inline bool num_pixels_ok(const struct ws2812_spi_cfg *cfg,
/*
* Latch current color values on strip and reset its state machines.
*/
static inline void ws2812_reset_delay(void)
static inline void ws2812_reset_delay(uint16_t delay)
{
/*
* TODO: swap out with k_usleep() once that can be trusted to
* work reliably.
*/
k_busy_wait(RESET_DELAY_USEC);
k_busy_wait(delay);
}
static int ws2812_strip_update_rgb(const struct device *dev,
@ -167,7 +160,7 @@ static int ws2812_strip_update_rgb(const struct device *dev,
* Display the pixel data.
*/
rc = spi_write(dev_data(dev)->spi, &cfg->spi_cfg, &tx);
ws2812_reset_delay();
ws2812_reset_delay(cfg->reset_delay);
return rc;
}
@ -212,6 +205,9 @@ static const uint8_t ws2812_spi_##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. */
#define WS2812_RESET_DELAY(idx) DT_INST_PROP(idx, reset_delay)
#define WS2812_SPI_DEVICE(idx) \
\
static struct ws2812_spi_data ws2812_spi_##idx##_data; \
@ -233,6 +229,7 @@ static const uint8_t ws2812_spi_##idx##_color_mapping[] = \
.zero_frame = WS2812_SPI_ZERO_FRAME(idx), \
.num_colors = WS2812_NUM_COLORS(idx), \
.color_mapping = ws2812_spi_##idx##_color_mapping, \
.reset_delay = WS2812_RESET_DELAY(idx), \
}; \
\
static int ws2812_spi_##idx##_init(const struct device *dev) \

View file

@ -38,3 +38,15 @@ properties:
color-mapping = <LED_COLOR_ID_GREEN
LED_COLOR_ID_RED
LED_COLOR_ID_BLUE>;
reset-delay:
type: int
required: false
default: 8
description: |
Minimum delay to wait (in microseconds) to make sure that the strip has
latched the signal. If omitted, a default value of 8 microseconds is used.
This default is good for the WS2812 controllers. Note that despite the
WS2812 datasheet states that a 50 microseconds delay is required, it seems
6 microseconds is enough. The default is set to 8 microseconds just to be
safe.