1
1
/*
2
2
* Copyright (c) 2018-2019 Jan Van Winkel <jan.van_winkel@dxplore.eu>
3
+ * Copyright (c) 2025 Abderrahmane JARMOUNI
3
4
*
4
5
* SPDX-License-Identifier: Apache-2.0
5
6
*/
21
22
#include <zephyr/logging/log.h>
22
23
LOG_MODULE_REGISTER (lvgl , CONFIG_LV_Z_LOG_LEVEL );
23
24
24
- static lv_display_t * display ;
25
- struct lvgl_disp_data disp_data = {
25
+ static lv_display_t * lv_displays [ DT_ZEPHYR_DISPLAYS_COUNT ] ;
26
+ struct lvgl_disp_data disp_data [ DT_ZEPHYR_DISPLAYS_COUNT ] = { {
26
27
.blanking_on = false,
27
- };
28
+ }};
29
+
30
+ #if DT_HAS_COMPAT_STATUS_OKAY (zephyr_displays )
31
+ #define DISPLAY_NODE (n ) DT_ZEPHYR_DISPLAY(n)
32
+ #elif DT_HAS_CHOSEN (zephyr_display )
33
+ #define DISPLAY_NODE (n ) DT_CHOSEN(zephyr_display)
34
+ #else
35
+ #error Could not find "zephyr,display" chosen property, or a "zephyr,displays" compatible node in DT
36
+ #define DISPLAY_NODE (n ) DT_INVALID_NODE
37
+ #endif
38
+
39
+ #define IS_MONOCHROME_DISPLAY \
40
+ UTIL_OR(IS_EQ(CONFIG_LV_Z_BITS_PER_PIXEL, 1), IS_EQ(CONFIG_LV_COLOR_DEPTH_1, 1))
28
41
29
- #define DISPLAY_NODE DT_CHOSEN(zephyr_display)
30
- #define IS_MONOCHROME_DISPLAY ((CONFIG_LV_Z_BITS_PER_PIXEL == 1) || (CONFIG_LV_COLOR_DEPTH_1 == 1))
31
42
#define ALLOC_MONOCHROME_CONV_BUFFER \
32
- ((IS_MONOCHROME_DISPLAY == 1) && (CONFIG_LV_Z_MONOCHROME_CONVERSION_BUFFER == 1))
43
+ UTIL_AND(IS_EQ(IS_MONOCHROME_DISPLAY, 1), \
44
+ IS_EQ(CONFIG_LV_Z_MONOCHROME_CONVERSION_BUFFER, 1))
33
45
34
46
#ifdef CONFIG_LV_Z_BUFFER_ALLOC_STATIC
35
47
36
- #define DISPLAY_WIDTH DT_PROP(DISPLAY_NODE, width)
37
- #define DISPLAY_HEIGHT DT_PROP(DISPLAY_NODE, height)
48
+ #define DISPLAY_WIDTH ( n ) DT_PROP(DISPLAY_NODE(n) , width)
49
+ #define DISPLAY_HEIGHT ( n ) DT_PROP(DISPLAY_NODE(n) , height)
38
50
39
51
#if IS_MONOCHROME_DISPLAY
40
52
/* monochrome buffers are expected to have 8 preceding bytes for the color palette */
41
- #define BUFFER_SIZE \
42
- (((CONFIG_LV_Z_VDB_SIZE * ROUND_UP(DISPLAY_WIDTH, 8) * ROUND_UP(DISPLAY_HEIGHT, 8)) / \
53
+ #define BUFFER_SIZE (n ) \
54
+ (((CONFIG_LV_Z_VDB_SIZE * ROUND_UP(DISPLAY_WIDTH(n), 8) * \
55
+ ROUND_UP(DISPLAY_HEIGHT(n), 8)) / \
43
56
100) / 8 + \
44
57
8)
45
58
#else
46
- #define BUFFER_SIZE \
59
+ #define BUFFER_SIZE ( n ) \
47
60
(CONFIG_LV_Z_BITS_PER_PIXEL * \
48
- ((CONFIG_LV_Z_VDB_SIZE * DISPLAY_WIDTH * DISPLAY_HEIGHT) / 100) / 8)
61
+ ((CONFIG_LV_Z_VDB_SIZE * DISPLAY_WIDTH(n) * DISPLAY_HEIGHT(n) ) / 100) / 8)
49
62
#endif /* IS_MONOCHROME_DISPLAY */
50
63
51
- /* NOTE: depending on chosen color depth buffer may be accessed using uint8_t *,
52
- * uint16_t * or uint32_t *, therefore buffer needs to be aligned accordingly to
53
- * prevent unaligned memory accesses.
54
- */
55
- static uint8_t buf0 [BUFFER_SIZE ]
56
- #ifdef CONFIG_LV_Z_VDB_CUSTOM_SECTION
57
- Z_GENERIC_SECTION (.lvgl_buf )
58
- #endif
59
- __aligned (CONFIG_LV_Z_VDB_ALIGN );
64
+ static uint32_t disp_buf_size [DT_ZEPHYR_DISPLAYS_COUNT ] = {0 };
65
+ static uint8_t * buf0_p [DT_ZEPHYR_DISPLAYS_COUNT ] = {NULL };
60
66
61
67
#ifdef CONFIG_LV_Z_DOUBLE_VDB
62
- static uint8_t buf1 [BUFFER_SIZE ]
63
- #ifdef CONFIG_LV_Z_VDB_CUSTOM_SECTION
64
- Z_GENERIC_SECTION (.lvgl_buf )
68
+ static uint8_t * buf1_p [DT_ZEPHYR_DISPLAYS_COUNT ] = {NULL };
65
69
#endif
66
- __aligned (CONFIG_LV_Z_VDB_ALIGN );
67
- #endif /* CONFIG_LV_Z_DOUBLE_VDB */
68
70
69
71
#if ALLOC_MONOCHROME_CONV_BUFFER
70
- static uint8_t mono_vtile_buf [BUFFER_SIZE ]
71
- #ifdef CONFIG_LV_Z_VDB_CUSTOM_SECTION
72
- Z_GENERIC_SECTION (.lvgl_buf )
72
+ static uint8_t * mono_vtile_buf_p [DT_ZEPHYR_DISPLAYS_COUNT ] = {NULL };
73
73
#endif
74
- __aligned (CONFIG_LV_Z_VDB_ALIGN );
75
- #endif /* ALLOC_MONOCHROME_CONV_BUFFER */
74
+
75
+ /* NOTE: depending on chosen color depth, buffers may be accessed using uint8_t *,*/
76
+ /* uint16_t * or uint32_t *, therefore buffer needs to be aligned accordingly to */
77
+ /* prevent unaligned memory accesses. */
78
+
79
+ /* clang-format off */
80
+ #define LV_BUFFERS_DEFINE (n ) \
81
+ static uint8_t buf0_##n[BUFFER_SIZE(n)] \
82
+ IF_ENABLED(CONFIG_LV_Z_VDB_CUSTOM_SECTION, (Z_GENERIC_SECTION(.lvgl_buf))) \
83
+ __aligned(CONFIG_LV_Z_VDB_ALIGN); \
84
+ \
85
+ IF_ENABLED(CONFIG_LV_Z_DOUBLE_VDB, ( \
86
+ static uint8_t buf1_##n[BUFFER_SIZE(n)] \
87
+ IF_ENABLED(CONFIG_LV_Z_VDB_CUSTOM_SECTION, (Z_GENERIC_SECTION(.lvgl_buf))) \
88
+ __aligned(CONFIG_LV_Z_VDB_ALIGN); \
89
+ )) \
90
+ \
91
+ IF_ENABLED(ALLOC_MONOCHROME_CONV_BUFFER, ( \
92
+ static uint8_t mono_vtile_buf_##n[BUFFER_SIZE(n)] \
93
+ IF_ENABLED(CONFIG_LV_Z_VDB_CUSTOM_SECTION, (Z_GENERIC_SECTION(.lvgl_buf))) \
94
+ __aligned(CONFIG_LV_Z_VDB_ALIGN); \
95
+ ))
96
+
97
+ FOR_EACH (LV_BUFFERS_DEFINE , ( ), LV_DISPLAYS_IDX_LIST );
98
+
99
+ #define LV_BUFFERS_REFERENCES (n ) \
100
+ disp_buf_size[n] = (uint32_t)BUFFER_SIZE(n); \
101
+ buf0_p[n] = buf0_##n; \
102
+ IF_ENABLED(CONFIG_LV_Z_DOUBLE_VDB, (buf1_p[n] = buf1_##n;)) \
103
+ IF_ENABLED(ALLOC_MONOCHROME_CONV_BUFFER, (mono_vtile_buf_p[n] = mono_vtile_buf_##n;))
104
+ /* clang-format on */
76
105
77
106
#endif /* CONFIG_LV_Z_BUFFER_ALLOC_STATIC */
78
107
@@ -101,21 +130,19 @@ static void lvgl_log(lv_log_level_t level, const char *buf)
101
130
102
131
#ifdef CONFIG_LV_Z_BUFFER_ALLOC_STATIC
103
132
104
- static int lvgl_allocate_rendering_buffers (lv_display_t * display )
133
+ static void lvgl_allocate_rendering_buffers_static (lv_display_t * display , int disp_idx )
105
134
{
106
- int err = 0 ;
107
-
108
135
#ifdef CONFIG_LV_Z_DOUBLE_VDB
109
- lv_display_set_buffers (display , & buf0 , & buf1 , BUFFER_SIZE , LV_DISPLAY_RENDER_MODE_PARTIAL );
136
+ lv_display_set_buffers (display , buf0_p [disp_idx ], buf1_p [disp_idx ], disp_buf_size [disp_idx ],
137
+ LV_DISPLAY_RENDER_MODE_PARTIAL );
110
138
#else
111
- lv_display_set_buffers (display , & buf0 , NULL , BUFFER_SIZE , LV_DISPLAY_RENDER_MODE_PARTIAL );
112
- #endif /* CONFIG_LV_Z_DOUBLE_VDB */
139
+ lv_display_set_buffers (display , buf0_p [disp_idx ], NULL , disp_buf_size [disp_idx ],
140
+ LV_DISPLAY_RENDER_MODE_PARTIAL );
141
+ #endif /* CONFIG_LV_Z_DOUBLE_VDB */
113
142
114
143
#if ALLOC_MONOCHROME_CONV_BUFFER
115
- lvgl_set_mono_conversion_buffer (mono_vtile_buf , BUFFER_SIZE );
116
- #endif /* ALLOC_MONOCHROME_CONV_BUFFER */
117
-
118
- return err ;
144
+ lvgl_set_mono_conversion_buffer (mono_vtile_buf_p [disp_idx ], disp_buf_size [disp_idx ]);
145
+ #endif
119
146
}
120
147
121
148
#else
@@ -224,15 +251,22 @@ lv_result_t lv_mem_test_core(void)
224
251
return LV_RESULT_OK ;
225
252
}
226
253
254
+ #define ENUMERATE_DISPLAY_DEVS (n ) display_dev[n] = DEVICE_DT_GET(DISPLAY_NODE(n));
255
+
227
256
int lvgl_init (void )
228
257
{
229
- const struct device * display_dev = DEVICE_DT_GET (DISPLAY_NODE );
230
-
231
- int err = 0 ;
232
-
233
- if (!device_is_ready (display_dev )) {
234
- LOG_ERR ("Display device not ready." );
235
- return - ENODEV ;
258
+ const struct device * display_dev [DT_ZEPHYR_DISPLAYS_COUNT ];
259
+ struct lvgl_disp_data * p_disp_data ;
260
+ int err ;
261
+
262
+ /* clang-format off */
263
+ FOR_EACH (ENUMERATE_DISPLAY_DEVS , ( ), LV_DISPLAYS_IDX_LIST );
264
+ /* clang-format on */
265
+ for (int i = 0 ; i < DT_ZEPHYR_DISPLAYS_COUNT ; i ++ ) {
266
+ if (!device_is_ready (display_dev [i ])) {
267
+ LOG_ERR ("Display device %d is not ready" , i );
268
+ return - ENODEV ;
269
+ }
236
270
}
237
271
238
272
#if CONFIG_LV_Z_LOG_LEVEL != 0
@@ -246,28 +280,43 @@ int lvgl_init(void)
246
280
lvgl_fs_init ();
247
281
#endif
248
282
249
- disp_data .display_dev = display_dev ;
250
- display_get_capabilities (display_dev , & disp_data .cap );
283
+ #ifdef CONFIG_LV_Z_BUFFER_ALLOC_STATIC
284
+ /* clang-format off */
285
+ FOR_EACH (LV_BUFFERS_REFERENCES , ( ), LV_DISPLAYS_IDX_LIST );
286
+ /* clang-format on */
287
+ #endif
251
288
252
- display = lv_display_create (disp_data .cap .x_resolution , disp_data .cap .y_resolution );
253
- if (!display ) {
254
- return - ENOMEM ;
255
- }
256
- lv_display_set_user_data (display , & disp_data );
289
+ for (int i = 0 ; i < DT_ZEPHYR_DISPLAYS_COUNT ; i ++ ) {
290
+ p_disp_data = & disp_data [i ];
291
+ p_disp_data -> display_dev = display_dev [i ];
292
+ display_get_capabilities (display_dev [i ], & p_disp_data -> cap );
257
293
258
- if (set_lvgl_rendering_cb (display ) != 0 ) {
259
- LOG_ERR ("Display not supported." );
260
- return - ENOTSUP ;
261
- }
294
+ lv_displays [i ] = lv_display_create (p_disp_data -> cap .x_resolution ,
295
+ p_disp_data -> cap .y_resolution );
296
+ if (!lv_displays [i ]) {
297
+ LOG_ERR ("Failed to create display %d LV object." , i );
298
+ return - ENOMEM ;
299
+ }
262
300
263
- err = lvgl_allocate_rendering_buffers (display );
264
- if (err != 0 ) {
265
- return err ;
266
- }
301
+ lv_display_set_user_data (lv_displays [i ], p_disp_data );
302
+ if (set_lvgl_rendering_cb (lv_displays [i ]) != 0 ) {
303
+ LOG_ERR ("Display %d not supported." , i );
304
+ return - ENOTSUP ;
305
+ }
306
+
307
+ #ifdef CONFIG_LV_Z_BUFFER_ALLOC_STATIC
308
+ lvgl_allocate_rendering_buffers_static (lv_displays [i ], i );
309
+ #else
310
+ err = lvgl_allocate_rendering_buffers (lv_displays [i ]);
311
+ if (err < 0 ) {
312
+ return err ;
313
+ }
314
+ #endif
267
315
268
316
#ifdef CONFIG_LV_Z_FULL_REFRESH
269
- lv_display_set_render_mode (display , LV_DISPLAY_RENDER_MODE_FULL );
317
+ lv_display_set_render_mode (lv_displays [ i ] , LV_DISPLAY_RENDER_MODE_FULL );
270
318
#endif
319
+ }
271
320
272
321
err = lvgl_init_input_devices ();
273
322
if (err < 0 ) {
0 commit comments