@@ -60,6 +60,15 @@ struct ssd16xx_quirks {
60
60
* SSD16XX_CMD_UPDATE_CTRL2 for a partial refresh.
61
61
*/
62
62
uint8_t ctrl2_partial ;
63
+
64
+ /*
65
+ * Device specific flag deciding whether to pass in the byte address or
66
+ * the bit address when setting the RAM x position window or counter in
67
+ * SSD16XX_CMD_RAM_XPOS_CTRL or SSD16XX_CMD_RAM_XPOS_CNTR. Expected to
68
+ * be `true` for the devices that expects the byte address, `false`
69
+ * otherwise.
70
+ */
71
+ bool x_addr_in_bytes ;
63
72
};
64
73
65
74
struct ssd16xx_data {
@@ -105,6 +114,8 @@ struct ssd16xx_config {
105
114
uint16_t height ;
106
115
uint16_t width ;
107
116
uint8_t tssv ;
117
+ uint8_t gdo_flags ;
118
+ bool scan_y_reverse ;
108
119
};
109
120
110
121
static int ssd16xx_set_profile (const struct device * dev ,
@@ -369,33 +380,69 @@ static int ssd16xx_set_window(const struct device *dev,
369
380
}
370
381
}
371
382
372
- switch (data -> orientation ) {
373
- case DISPLAY_ORIENTATION_NORMAL :
374
- x_start = (panel_h - 1 - y ) / SSD16XX_PIXELS_PER_BYTE ;
375
- x_end = (panel_h - 1 - (y + desc -> height - 1 )) / SSD16XX_PIXELS_PER_BYTE ;
376
- y_start = x ;
377
- y_end = (x + desc -> width - 1 );
378
- break ;
379
- case DISPLAY_ORIENTATION_ROTATED_90 :
380
- x_start = (panel_h - 1 - x ) / SSD16XX_PIXELS_PER_BYTE ;
381
- x_end = (panel_h - 1 - (x + desc -> width - 1 )) / SSD16XX_PIXELS_PER_BYTE ;
382
- y_start = (config -> width - 1 - y );
383
- y_end = (config -> width - 1 - (y + desc -> height - 1 ));
384
- break ;
385
- case DISPLAY_ORIENTATION_ROTATED_180 :
386
- x_start = y / SSD16XX_PIXELS_PER_BYTE ;
387
- x_end = (y + desc -> height - 1 ) / SSD16XX_PIXELS_PER_BYTE ;
388
- y_start = (x + desc -> width - 1 );
389
- y_end = x ;
390
- break ;
391
- case DISPLAY_ORIENTATION_ROTATED_270 :
392
- x_start = x / SSD16XX_PIXELS_PER_BYTE ;
393
- x_end = (x + desc -> width - 1 ) / SSD16XX_PIXELS_PER_BYTE ;
394
- y_start = y ;
395
- y_end = (y + desc -> height - 1 );
396
- break ;
397
- default :
398
- return - EINVAL ;
383
+ if (config -> scan_y_reverse ) {
384
+ switch (data -> orientation ) {
385
+ case DISPLAY_ORIENTATION_NORMAL :
386
+ x_start = (panel_h - 1 - y );
387
+ x_end = (panel_h - 1 - (y + desc -> height - 1 ));
388
+ y_start = (config -> width - 1 - x );
389
+ y_end = (config -> width - 1 - (x + desc -> width - 1 ));
390
+ break ;
391
+ case DISPLAY_ORIENTATION_ROTATED_90 :
392
+ x_start = x ;
393
+ x_end = (x + desc -> width - 1 );
394
+ y_start = (config -> width - 1 - y );
395
+ y_end = (config -> width - 1 - (y + desc -> height - 1 ));
396
+ break ;
397
+ case DISPLAY_ORIENTATION_ROTATED_180 :
398
+ x_start = y ;
399
+ x_end = (y + desc -> height - 1 );
400
+ y_start = x ;
401
+ y_end = (x + desc -> width - 1 );
402
+ break ;
403
+ case DISPLAY_ORIENTATION_ROTATED_270 :
404
+ x_start = (panel_h - 1 - x );
405
+ x_end = (panel_h - 1 - (x + desc -> width - 1 ));
406
+ y_start = y ;
407
+ y_end = (y + desc -> height - 1 );
408
+ break ;
409
+ default :
410
+ return - EINVAL ;
411
+ }
412
+ } else {
413
+ switch (data -> orientation ) {
414
+ case DISPLAY_ORIENTATION_NORMAL :
415
+ x_start = (panel_h - 1 - y );
416
+ x_end = (panel_h - 1 - (y + desc -> height - 1 ));
417
+ y_start = x ;
418
+ y_end = (x + desc -> width - 1 );
419
+ break ;
420
+ case DISPLAY_ORIENTATION_ROTATED_90 :
421
+ x_start = (panel_h - 1 - x );
422
+ x_end = (panel_h - 1 - (x + desc -> width - 1 ));
423
+ y_start = (config -> width - 1 - y );
424
+ y_end = (config -> width - 1 - (y + desc -> height - 1 ));
425
+ break ;
426
+ case DISPLAY_ORIENTATION_ROTATED_180 :
427
+ x_start = y ;
428
+ x_end = (y + desc -> height - 1 );
429
+ y_start = (x + desc -> width - 1 );
430
+ y_end = x ;
431
+ break ;
432
+ case DISPLAY_ORIENTATION_ROTATED_270 :
433
+ x_start = x ;
434
+ x_end = (x + desc -> width - 1 );
435
+ y_start = y ;
436
+ y_end = (y + desc -> height - 1 );
437
+ break ;
438
+ default :
439
+ return - EINVAL ;
440
+ }
441
+ }
442
+
443
+ if (config -> quirks -> x_addr_in_bytes ) {
444
+ x_start /= SSD16XX_PIXELS_PER_BYTE ;
445
+ x_end /= SSD16XX_PIXELS_PER_BYTE ;
399
446
}
400
447
401
448
err = ssd16xx_set_ram_param (dev , x_start , x_end , y_start , y_end );
@@ -588,17 +635,30 @@ static int ssd16xx_set_pixel_format(const struct device *dev,
588
635
static int ssd16xx_set_orientation (const struct device * dev ,
589
636
const enum display_orientation orientation )
590
637
{
638
+ const struct ssd16xx_config * config = dev -> config ;
591
639
struct ssd16xx_data * data = dev -> data ;
592
640
int err ;
593
641
594
- if (orientation == DISPLAY_ORIENTATION_NORMAL ) {
595
- data -> scan_mode = SSD16XX_DATA_ENTRY_XDYIY ;
596
- } else if (orientation == DISPLAY_ORIENTATION_ROTATED_90 ) {
597
- data -> scan_mode = SSD16XX_DATA_ENTRY_XDYDX ;
598
- } else if (orientation == DISPLAY_ORIENTATION_ROTATED_180 ) {
599
- data -> scan_mode = SSD16XX_DATA_ENTRY_XIYDY ;
600
- } else if (orientation == DISPLAY_ORIENTATION_ROTATED_270 ) {
601
- data -> scan_mode = SSD16XX_DATA_ENTRY_XIYIX ;
642
+ if (config -> scan_y_reverse ) {
643
+ if (orientation == DISPLAY_ORIENTATION_NORMAL ) {
644
+ data -> scan_mode = SSD16XX_DATA_ENTRY_XDYDY ;
645
+ } else if (orientation == DISPLAY_ORIENTATION_ROTATED_90 ) {
646
+ data -> scan_mode = SSD16XX_DATA_ENTRY_XIYDX ;
647
+ } else if (orientation == DISPLAY_ORIENTATION_ROTATED_180 ) {
648
+ data -> scan_mode = SSD16XX_DATA_ENTRY_XIYIY ;
649
+ } else if (orientation == DISPLAY_ORIENTATION_ROTATED_270 ) {
650
+ data -> scan_mode = SSD16XX_DATA_ENTRY_XDYIX ;
651
+ }
652
+ } else {
653
+ if (orientation == DISPLAY_ORIENTATION_NORMAL ) {
654
+ data -> scan_mode = SSD16XX_DATA_ENTRY_XDYIY ;
655
+ } else if (orientation == DISPLAY_ORIENTATION_ROTATED_90 ) {
656
+ data -> scan_mode = SSD16XX_DATA_ENTRY_XDYDX ;
657
+ } else if (orientation == DISPLAY_ORIENTATION_ROTATED_180 ) {
658
+ data -> scan_mode = SSD16XX_DATA_ENTRY_XIYDY ;
659
+ } else if (orientation == DISPLAY_ORIENTATION_ROTATED_270 ) {
660
+ data -> scan_mode = SSD16XX_DATA_ENTRY_XIYIX ;
661
+ }
602
662
}
603
663
604
664
err = ssd16xx_write_uint8 (dev , SSD16XX_CMD_ENTRY_MODE , data -> scan_mode );
@@ -614,7 +674,7 @@ static int ssd16xx_set_orientation(const struct device *dev,
614
674
static int ssd16xx_clear_cntlr_mem (const struct device * dev , uint8_t ram_cmd )
615
675
{
616
676
const struct ssd16xx_config * config = dev -> config ;
617
- uint16_t panel_h = config -> height / EPD_PANEL_NUMOF_ROWS_PER_PAGE ;
677
+ uint16_t panel_h = config -> height ;
618
678
uint16_t last_gate = config -> width - 1 ;
619
679
uint8_t clear_page [64 ];
620
680
int err ;
@@ -623,8 +683,9 @@ static int ssd16xx_clear_cntlr_mem(const struct device *dev, uint8_t ram_cmd)
623
683
* Clear unusable memory area when the resolution of the panel is not
624
684
* multiple of an octet.
625
685
*/
626
- if (config -> height % EPD_PANEL_NUMOF_ROWS_PER_PAGE ) {
627
- panel_h += 1 ;
686
+ if (config -> quirks -> x_addr_in_bytes ) {
687
+ panel_h = (config -> height + (EPD_PANEL_NUMOF_ROWS_PER_PAGE - 1 )) /
688
+ EPD_PANEL_NUMOF_ROWS_PER_PAGE ;
628
689
}
629
690
630
691
err = ssd16xx_write_uint8 (dev , SSD16XX_CMD_ENTRY_MODE ,
@@ -771,7 +832,7 @@ static int ssd16xx_set_profile(const struct device *dev,
771
832
}
772
833
773
834
gdo_len = push_y_param (dev , gdo , last_gate );
774
- gdo [gdo_len ++ ] = 0U ;
835
+ gdo [gdo_len ++ ] = config -> gdo_flags ;
775
836
err = ssd16xx_write_cmd (dev , SSD16XX_CMD_GDO_CTRL , gdo , gdo_len );
776
837
if (err < 0 ) {
777
838
return err ;
@@ -964,6 +1025,7 @@ static struct ssd16xx_quirks quirks_solomon_ssd1608 = {
964
1025
.pp_height_bits = 16 ,
965
1026
.ctrl2_full = SSD16XX_GEN1_CTRL2_TO_PATTERN ,
966
1027
.ctrl2_partial = SSD16XX_GEN1_CTRL2_TO_PATTERN ,
1028
+ .x_addr_in_bytes = true,
967
1029
};
968
1030
#endif
969
1031
@@ -975,6 +1037,7 @@ static struct ssd16xx_quirks quirks_solomon_ssd1673 = {
975
1037
.pp_height_bits = 8 ,
976
1038
.ctrl2_full = SSD16XX_GEN1_CTRL2_TO_PATTERN ,
977
1039
.ctrl2_partial = SSD16XX_GEN1_CTRL2_TO_PATTERN ,
1040
+ .x_addr_in_bytes = true,
978
1041
};
979
1042
#endif
980
1043
@@ -986,6 +1049,19 @@ static struct ssd16xx_quirks quirks_solomon_ssd1675a = {
986
1049
.pp_height_bits = 16 ,
987
1050
.ctrl2_full = SSD16XX_GEN1_CTRL2_TO_PATTERN ,
988
1051
.ctrl2_partial = SSD16XX_GEN1_CTRL2_TO_PATTERN ,
1052
+ .x_addr_in_bytes = true,
1053
+ };
1054
+ #endif
1055
+
1056
+ #if DT_HAS_COMPAT_STATUS_OKAY (solomon_ssd1677 )
1057
+ static const struct ssd16xx_quirks quirks_solomon_ssd1677 = {
1058
+ .max_width = 680 ,
1059
+ .max_height = 960 ,
1060
+ .pp_width_bits = 16 ,
1061
+ .pp_height_bits = 16 ,
1062
+ .ctrl2_full = SSD16XX_GEN2_CTRL2_DISPLAY ,
1063
+ .ctrl2_partial = SSD16XX_GEN2_CTRL2_DISPLAY | SSD16XX_GEN2_CTRL2_MODE2 ,
1064
+ .x_addr_in_bytes = false,
989
1065
};
990
1066
#endif
991
1067
@@ -997,6 +1073,7 @@ static const struct ssd16xx_quirks quirks_solomon_ssd1680 = {
997
1073
.pp_height_bits = 16 ,
998
1074
.ctrl2_full = SSD16XX_GEN2_CTRL2_DISPLAY ,
999
1075
.ctrl2_partial = SSD16XX_GEN2_CTRL2_DISPLAY | SSD16XX_GEN2_CTRL2_MODE2 ,
1076
+ .x_addr_in_bytes = true,
1000
1077
};
1001
1078
#endif
1002
1079
@@ -1008,6 +1085,7 @@ static struct ssd16xx_quirks quirks_solomon_ssd1681 = {
1008
1085
.pp_height_bits = 16 ,
1009
1086
.ctrl2_full = SSD16XX_GEN2_CTRL2_DISPLAY ,
1010
1087
.ctrl2_partial = SSD16XX_GEN2_CTRL2_DISPLAY | SSD16XX_GEN2_CTRL2_MODE2 ,
1088
+ .x_addr_in_bytes = true,
1011
1089
};
1012
1090
#endif
1013
1091
@@ -1072,7 +1150,9 @@ static struct ssd16xx_quirks quirks_solomon_ssd1681 = {
1072
1150
.height = DT_PROP(n, height), \
1073
1151
.width = DT_PROP(n, width), \
1074
1152
.rotation = DT_PROP(n, rotation), \
1153
+ .scan_y_reverse = DT_PROP(n, scan_y_reverse), \
1075
1154
.tssv = DT_PROP_OR(n, tssv, 0), \
1155
+ .gdo_flags = DT_PROP_OR(n, gdo_flags, 0), \
1076
1156
.softstart = SSD16XX_ASSIGN_ARRAY(n, softstart), \
1077
1157
.profiles = { \
1078
1158
[SSD16XX_PROFILE_FULL] = \
@@ -1098,6 +1178,8 @@ DT_FOREACH_STATUS_OKAY_VARGS(solomon_ssd1673, SSD16XX_DEFINE,
1098
1178
& quirks_solomon_ssd1673 );
1099
1179
DT_FOREACH_STATUS_OKAY_VARGS (solomon_ssd1675a , SSD16XX_DEFINE ,
1100
1180
& quirks_solomon_ssd1675a );
1181
+ DT_FOREACH_STATUS_OKAY_VARGS (solomon_ssd1677 , SSD16XX_DEFINE ,
1182
+ & quirks_solomon_ssd1677 );
1101
1183
DT_FOREACH_STATUS_OKAY_VARGS (solomon_ssd1680 , SSD16XX_DEFINE ,
1102
1184
& quirks_solomon_ssd1680 );
1103
1185
DT_FOREACH_STATUS_OKAY_VARGS (solomon_ssd1681 , SSD16XX_DEFINE ,
0 commit comments