55 * SPDX-License-Identifier: Apache-2.0
66 */
77
8- #define DT_DRV_COMPAT solomon_ssd16xxfb
9-
108#define LOG_LEVEL CONFIG_DISPLAY_LOG_LEVEL
119#include <zephyr/logging/log.h>
1210LOG_MODULE_REGISTER (ssd16xx );
@@ -23,7 +21,7 @@ LOG_MODULE_REGISTER(ssd16xx);
2321#include "ssd16xx_regs.h"
2422
2523/**
26- * SSD1673, SSD1608, SSD1681, ILI3897 compatible EPD controller driver.
24+ * SSD16xx compatible EPD controller driver.
2725 */
2826
2927#define EPD_PANEL_NUMOF_ROWS_PER_PAGE 8
@@ -33,6 +31,17 @@ LOG_MODULE_REGISTER(ssd16xx);
3331#define SSD16XX_DEFAULT_TR_VALUE 25U
3432#define SSD16XX_TR_SCALE_FACTOR 256U
3533
34+ struct ssd16xx_quirks {
35+ /* Gates */
36+ uint16_t max_width ;
37+ /* Sources */
38+ uint16_t max_height ;
39+ /* Width (bits) of integer type representing an x coordinate */
40+ uint8_t pp_width_bits ;
41+ /* Width (bits) of integer type representing a y coordinate */
42+ uint8_t pp_height_bits ;
43+ };
44+
3645struct ssd16xx_data {
3746 bool read_supported ;
3847 uint8_t scan_mode ;
@@ -62,6 +71,8 @@ struct ssd16xx_config {
6271 struct gpio_dt_spec busy_gpio ;
6372 struct gpio_dt_spec reset_gpio ;
6473
74+ const struct ssd16xx_quirks * quirks ;
75+
6576 struct ssd16xx_dt_array softstart ;
6677
6778 struct ssd16xx_profile profile_initial ;
@@ -71,8 +82,6 @@ struct ssd16xx_config {
7182 uint16_t height ;
7283 uint16_t width ;
7384 uint8_t tssv ;
74- uint8_t pp_width_bits ;
75- uint8_t pp_height_bits ;
7685
7786 uint8_t dummy_line ;
7887 bool override_dummy_line ;
@@ -189,17 +198,18 @@ static inline size_t push_x_param(const struct device *dev,
189198{
190199 const struct ssd16xx_config * config = dev -> config ;
191200
192- if (config -> pp_width_bits == 8 ) {
201+ if (config -> quirks -> pp_width_bits == 8 ) {
193202 data [0 ] = (uint8_t )x ;
194203 return 1 ;
195204 }
196205
197- if (config -> pp_width_bits == 16 ) {
206+ if (config -> quirks -> pp_width_bits == 16 ) {
198207 sys_put_le16 (sys_cpu_to_le16 (x ), data );
199208 return 2 ;
200209 }
201210
202- LOG_ERR ("Unsupported pp_width_bits %u" , config -> pp_width_bits );
211+ LOG_ERR ("Unsupported pp_width_bits %u" ,
212+ config -> quirks -> pp_width_bits );
203213 return 0 ;
204214}
205215
@@ -208,17 +218,18 @@ static inline size_t push_y_param(const struct device *dev,
208218{
209219 const struct ssd16xx_config * config = dev -> config ;
210220
211- if (config -> pp_height_bits == 8 ) {
221+ if (config -> quirks -> pp_height_bits == 8 ) {
212222 data [0 ] = (uint8_t )y ;
213223 return 1 ;
214224 }
215225
216- if (config -> pp_height_bits == 16 ) {
226+ if (config -> quirks -> pp_height_bits == 16 ) {
217227 sys_put_le16 (sys_cpu_to_le16 (y ), data );
218228 return 2 ;
219229 }
220230
221- LOG_ERR ("Unsupported pp_height_bitsa %u" , config -> pp_height_bits );
231+ LOG_ERR ("Unsupported pp_height_bitsa %u" ,
232+ config -> quirks -> pp_height_bits );
222233 return 0 ;
223234}
224235
@@ -885,6 +896,12 @@ static int ssd16xx_init(const struct device *dev)
885896 return err ;
886897 }
887898
899+ if (config -> width > config -> quirks -> max_width ||
900+ config -> height > config -> quirks -> max_height ) {
901+ LOG_ERR ("Display size out of range." );
902+ return - EINVAL ;
903+ }
904+
888905 return ssd16xx_controller_init (dev );
889906}
890907
@@ -901,6 +918,42 @@ static struct display_driver_api ssd16xx_driver_api = {
901918 .set_orientation = ssd16xx_set_orientation ,
902919};
903920
921+ #if DT_HAS_COMPAT_STATUS_OKAY (solomon_ssd1608 )
922+ static struct ssd16xx_quirks quirks_solomon_ssd1608 = {
923+ .max_width = 320 ,
924+ .max_height = 240 ,
925+ .pp_width_bits = 16 ,
926+ .pp_height_bits = 16 ,
927+ };
928+ #endif
929+
930+ #if DT_HAS_COMPAT_STATUS_OKAY (solomon_ssd1673 )
931+ static struct ssd16xx_quirks quirks_solomon_ssd1673 = {
932+ .max_width = 250 ,
933+ .max_height = 150 ,
934+ .pp_width_bits = 8 ,
935+ .pp_height_bits = 8 ,
936+ };
937+ #endif
938+
939+ #if DT_HAS_COMPAT_STATUS_OKAY (solomon_ssd1675a )
940+ static struct ssd16xx_quirks quirks_solomon_ssd1675a = {
941+ .max_width = 296 ,
942+ .max_height = 160 ,
943+ .pp_width_bits = 8 ,
944+ .pp_height_bits = 16 ,
945+ };
946+ #endif
947+
948+ #if DT_HAS_COMPAT_STATUS_OKAY (solomon_ssd1681 )
949+ static struct ssd16xx_quirks quirks_solomon_ssd1681 = {
950+ .max_width = 200 ,
951+ .max_height = 200 ,
952+ .pp_width_bits = 8 ,
953+ .pp_height_bits = 16 ,
954+ };
955+ #endif
956+
904957#define LUT_DEFAULT_ASSIGN (n ) \
905958 .lut_default = { \
906959 .data = lut_default_##n, \
@@ -913,70 +966,75 @@ static struct display_driver_api ssd16xx_driver_api = {
913966 .len = sizeof(softstart_##n), \
914967 },
915968
916- #define SSD16XX_MAKE_INST_ARRAY_OPT (n , p ) \
917- static uint8_t data_ ## n ## _ ## p[] = DT_INST_PROP_OR(n, p, {})
969+ #define SSD16XX_MAKE_ARRAY_OPT (n , p ) \
970+ static uint8_t data_ ## n ## _ ## p[] = \
971+ DT_PROP_OR(n, p, {})
918972
919973#define SSD16XX_ASSIGN_ARRAY (n , p ) \
920974 { \
921975 .data = data_ ## n ## _ ## p, \
922- .len = sizeof(data_ ## n ## _ ## p), \
976+ .len = sizeof(data_ ## n ## _ ## p), \
923977 }
924978
925979#define SSD16XX_INITIAL_PROFILE_DEFINE (n ) \
926- SSD16XX_MAKE_INST_ARRAY_OPT (n, lut_initial); \
927- SSD16XX_MAKE_INST_ARRAY_OPT (n, gdv); \
928- SSD16XX_MAKE_INST_ARRAY_OPT (n, sdv)
980+ SSD16XX_MAKE_ARRAY_OPT (n, lut_initial); \
981+ SSD16XX_MAKE_ARRAY_OPT (n, gdv); \
982+ SSD16XX_MAKE_ARRAY_OPT (n, sdv)
929983
930984#define SSD16XX_INITIAL_PROFILE (n ) \
931985 { \
932986 .lut = SSD16XX_ASSIGN_ARRAY(n, lut_initial), \
933987 .gdv = SSD16XX_ASSIGN_ARRAY(n, gdv), \
934988 .sdv = SSD16XX_ASSIGN_ARRAY(n, sdv), \
935- .vcom = DT_INST_PROP_OR (n, vcom, 0), \
936- .override_vcom = DT_INST_NODE_HAS_PROP (n, vcom), \
937- .bwf = DT_INST_PROP_OR (n, border_waveform, 0), \
938- .override_bwf = DT_INST_NODE_HAS_PROP (n, border_waveform), \
989+ .vcom = DT_PROP_OR (n, vcom, 0), \
990+ .override_vcom = DT_NODE_HAS_PROP (n, vcom), \
991+ .bwf = DT_PROP_OR (n, border_waveform, 0), \
992+ .override_bwf = DT_NODE_HAS_PROP (n, border_waveform), \
939993 }
940994
941- #define SSD16XX_DEFINE (n ) \
942- SSD16XX_MAKE_INST_ARRAY_OPT (n, lut_default); \
943- SSD16XX_MAKE_INST_ARRAY_OPT (n, softstart); \
995+ #define SSD16XX_DEFINE (n , quirks_ptr ) \
996+ SSD16XX_MAKE_ARRAY_OPT (n, lut_default); \
997+ SSD16XX_MAKE_ARRAY_OPT (n, softstart); \
944998 SSD16XX_INITIAL_PROFILE_DEFINE(n); \
945999 \
946- static const struct ssd16xx_config ssd16xx_cfg_## n = { \
947- .bus = SPI_DT_SPEC_INST_GET (n, \
1000+ static const struct ssd16xx_config ssd16xx_cfg_ ## n = { \
1001+ .bus = SPI_DT_SPEC_GET (n, \
9481002 SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \
9491003 SPI_HOLD_ON_CS | SPI_LOCK_ON, \
9501004 0), \
951- .reset_gpio = GPIO_DT_SPEC_INST_GET(n, reset_gpios), \
952- .dc_gpio = GPIO_DT_SPEC_INST_GET(n, dc_gpios), \
953- .busy_gpio = GPIO_DT_SPEC_INST_GET(n, busy_gpios), \
954- .height = DT_INST_PROP(n, height), \
955- .width = DT_INST_PROP(n, width), \
956- .orientation = DT_INST_PROP(n, orientation_flipped), \
957- .pp_width_bits = DT_INST_PROP(n, pp_width_bits), \
958- .pp_height_bits = DT_INST_PROP(n, pp_height_bits), \
959- .tssv = DT_INST_PROP_OR(n, tssv, 0), \
1005+ .reset_gpio = GPIO_DT_SPEC_GET(n, reset_gpios), \
1006+ .dc_gpio = GPIO_DT_SPEC_GET(n, dc_gpios), \
1007+ .busy_gpio = GPIO_DT_SPEC_GET(n, busy_gpios), \
1008+ .quirks = quirks_ptr, \
1009+ .height = DT_PROP(n, height), \
1010+ .width = DT_PROP(n, width), \
1011+ .orientation = DT_PROP(n, orientation_flipped), \
1012+ .tssv = DT_PROP_OR(n, tssv, 0), \
9601013 .softstart = SSD16XX_ASSIGN_ARRAY(n, softstart), \
9611014 .lut_default = SSD16XX_ASSIGN_ARRAY(n, lut_default), \
9621015 .profile_initial = SSD16XX_INITIAL_PROFILE(n), \
963- .dummy_line = DT_INST_PROP_OR(n, dummy_line, 0), \
964- .override_dummy_line = \
965- DT_INST_NODE_HAS_PROP(n, dummy_line), \
966- .gate_line_width = \
967- DT_INST_PROP_OR(n, gate_line_width, 0), \
968- .override_gate_line_width = \
969- DT_INST_NODE_HAS_PROP(n, gate_line_width), \
1016+ .dummy_line = DT_PROP_OR(n, dummy_line, 0), \
1017+ .override_dummy_line = DT_NODE_HAS_PROP(n, dummy_line), \
1018+ .gate_line_width = DT_PROP_OR(n, gate_line_width, 0), \
1019+ .override_gate_line_width = DT_NODE_HAS_PROP( \
1020+ n, gate_line_width), \
9701021 }; \
9711022 \
972- static struct ssd16xx_data ssd16xx_data_## n; \
1023+ static struct ssd16xx_data ssd16xx_data_ ## n; \
9731024 \
974- DEVICE_DT_INST_DEFINE(n, ssd16xx_init, NULL, \
975- &ssd16xx_data_##n, \
976- &ssd16xx_cfg_##n, \
977- POST_KERNEL, \
978- CONFIG_DISPLAY_INIT_PRIORITY, \
979- &ssd16xx_driver_api); \
980-
981-
982- DT_INST_FOREACH_STATUS_OKAY (SSD16XX_DEFINE )
1025+ DEVICE_DT_DEFINE(n, \
1026+ ssd16xx_init, NULL, \
1027+ &ssd16xx_data_ ## n, \
1028+ &ssd16xx_cfg_ ## n, \
1029+ POST_KERNEL, \
1030+ CONFIG_DISPLAY_INIT_PRIORITY, \
1031+ &ssd16xx_driver_api)
1032+
1033+ DT_FOREACH_STATUS_OKAY_VARGS (solomon_ssd1608 , SSD16XX_DEFINE ,
1034+ & quirks_solomon_ssd1608 );
1035+ DT_FOREACH_STATUS_OKAY_VARGS (solomon_ssd1673 , SSD16XX_DEFINE ,
1036+ & quirks_solomon_ssd1673 );
1037+ DT_FOREACH_STATUS_OKAY_VARGS (solomon_ssd1675a , SSD16XX_DEFINE ,
1038+ & quirks_solomon_ssd1675a );
1039+ DT_FOREACH_STATUS_OKAY_VARGS (solomon_ssd1681 , SSD16XX_DEFINE ,
1040+ & quirks_solomon_ssd1681 );
0 commit comments