From 4a75a930b91c62b5575458d3961ea53f264f26dc Mon Sep 17 00:00:00 2001 From: Abderrahmane JARMOUNI Date: Sun, 16 Mar 2025 21:40:12 +0100 Subject: [PATCH] modules: lvgl: add multi-display input support Add support for binding LV input devs to multiple displays Signed-off-by: Abderrahmane JARMOUNI --- .../input/zephyr,lvgl-common-input.yaml | 6 +++ modules/lvgl/include/lvgl_common_input.h | 1 + modules/lvgl/input/lvgl_common_input.c | 42 +++++++++++++++++-- modules/lvgl/input/lvgl_encoder_input.c | 2 + modules/lvgl/input/lvgl_keypad_input.c | 2 + modules/lvgl/input/lvgl_pointer_input.c | 5 ++- 6 files changed, 53 insertions(+), 5 deletions(-) diff --git a/dts/bindings/input/zephyr,lvgl-common-input.yaml b/dts/bindings/input/zephyr,lvgl-common-input.yaml index c4934c030f7..f6af204c316 100644 --- a/dts/bindings/input/zephyr,lvgl-common-input.yaml +++ b/dts/bindings/input/zephyr,lvgl-common-input.yaml @@ -1,4 +1,5 @@ # Copyright 2023 Fabian Blatz +# Copyright 2025 Abderrahmane JARMOUNI # SPDX-License-Identifier: Apache-2.0 # Common fields for input lvgl pseudo devices @@ -8,3 +9,8 @@ properties: type: phandle description: | Input device phandle. + display: + type: phandle + description: | + Phandle of the display device to pass input commands to. + Used in multi-display setup. diff --git a/modules/lvgl/include/lvgl_common_input.h b/modules/lvgl/include/lvgl_common_input.h index 72a931a9921..7cb0b0284d3 100644 --- a/modules/lvgl/include/lvgl_common_input.h +++ b/modules/lvgl/include/lvgl_common_input.h @@ -17,6 +17,7 @@ extern "C" { struct lvgl_common_input_config { struct k_msgq *event_msgq; + const struct device *display_dev; }; struct lvgl_common_input_data { diff --git a/modules/lvgl/input/lvgl_common_input.c b/modules/lvgl/input/lvgl_common_input.c index 487c606d7ad..c5895e20349 100644 --- a/modules/lvgl/input/lvgl_common_input.c +++ b/modules/lvgl/input/lvgl_common_input.c @@ -1,5 +1,6 @@ /* * Copyright 2023 Fabian Blatz + * Copyright 2025 Abderrahmane JARMOUNI * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,8 +8,9 @@ #include #include -#include #include +#include +#include #include "lvgl_pointer_input.h" #include "lvgl_button_input.h" #include "lvgl_encoder_input.h" @@ -42,13 +44,42 @@ static void lvgl_input_read_cb(lv_indev_t *indev, lv_indev_data_t *data) data->continue_reading = k_msgq_num_used_get(cfg->event_msgq) > 0; } +static lv_display_t *lvgl_input_get_display(const struct device *dev) +{ + const struct lvgl_common_input_config *cfg = dev->config; + const struct device *disp_dev = cfg->display_dev; + struct lvgl_disp_data *lv_disp_data; + lv_display_t *lv_disp = NULL; + + if (disp_dev == NULL) { + return NULL; + } + + for (int i = 0; i < DT_ZEPHYR_DISPLAYS_COUNT; i++) { + lv_disp = lv_display_get_next(lv_disp); + if (lv_disp == NULL) { + LOG_ERR("Could not find LV display objects of all Zephyr displays"); + break; + } + lv_disp_data = (struct lvgl_disp_data *)lv_display_get_user_data(lv_disp); + if (disp_dev == lv_disp_data->display_dev) { + return lv_disp; + } + } + + LOG_ERR("LV display corresponding to display device %s not found", disp_dev->name); + __ASSERT_NO_MSG(false); + + return NULL; +} + int lvgl_input_register_driver(lv_indev_type_t indev_type, const struct device *dev) { - /* Currently no indev binding has its dedicated data - * if that ever changes ensure that `lvgl_common_input_data` - * remains the first member + /* Ensure that `lvgl_common_input_data` remains the first member + * of indev dedicated data */ struct lvgl_common_input_data *common_data = dev->data; + lv_display_t *disp; if (common_data == NULL) { return -EINVAL; @@ -64,6 +95,9 @@ int lvgl_input_register_driver(lv_indev_type_t indev_type, const struct device * lv_indev_set_read_cb(common_data->indev, lvgl_input_read_cb); lv_indev_set_user_data(common_data->indev, (void *)dev); + disp = lvgl_input_get_display(dev); + lv_indev_set_display(common_data->indev, disp); + return 0; } diff --git a/modules/lvgl/input/lvgl_encoder_input.c b/modules/lvgl/input/lvgl_encoder_input.c index 7d63e2d4e07..e8b56e2a905 100644 --- a/modules/lvgl/input/lvgl_encoder_input.c +++ b/modules/lvgl/input/lvgl_encoder_input.c @@ -65,6 +65,8 @@ int lvgl_encoder_input_init(const struct device *dev) lvgl_encoder_process_event); \ static const struct lvgl_encoder_input_config lvgl_encoder_input_config_##inst = { \ .common_config.event_msgq = &LVGL_INPUT_EVENT_MSGQ(inst, encoder), \ + .common_config.display_dev = \ + DEVICE_DT_GET_OR_NULL(DT_INST_PHANDLE(inst, display)), \ .rotation_input_code = ROTATION_CODE(inst), \ .button_input_code = BUTTON_CODE(inst), \ }; \ diff --git a/modules/lvgl/input/lvgl_keypad_input.c b/modules/lvgl/input/lvgl_keypad_input.c index 77f9eb20922..989530e0067 100644 --- a/modules/lvgl/input/lvgl_keypad_input.c +++ b/modules/lvgl/input/lvgl_keypad_input.c @@ -63,6 +63,8 @@ int lvgl_keypad_input_init(const struct device *dev) static const uint16_t lvgl_keypad_lvgl_codes_##inst[] = DT_INST_PROP(inst, lvgl_codes); \ static const struct lvgl_keypad_input_config lvgl_keypad_input_config_##inst = { \ .common_config.event_msgq = &LVGL_INPUT_EVENT_MSGQ(inst, keypad), \ + .common_config.display_dev = \ + DEVICE_DT_GET_OR_NULL(DT_INST_PHANDLE(inst, display)), \ .input_codes = lvgl_keypad_input_codes_##inst, \ .lvgl_codes = lvgl_keypad_lvgl_codes_##inst, \ .num_codes = DT_INST_PROP_LEN(inst, input_codes), \ diff --git a/modules/lvgl/input/lvgl_pointer_input.c b/modules/lvgl/input/lvgl_pointer_input.c index 0777ec2bac5..927c994499b 100644 --- a/modules/lvgl/input/lvgl_pointer_input.c +++ b/modules/lvgl/input/lvgl_pointer_input.c @@ -1,5 +1,6 @@ /* * Copyright 2023 Fabian Blatz + * Copyright 2025 Abderrahmane JARMOUNI * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,7 +33,7 @@ static void lvgl_pointer_process_event(struct input_event *evt, void *user_data) const struct device *dev = user_data; const struct lvgl_pointer_input_config *cfg = dev->config; struct lvgl_pointer_input_data *data = dev->data; - lv_display_t *disp = lv_display_get_default(); + lv_display_t *disp = lv_indev_get_display(data->common_data.indev); struct lvgl_disp_data *disp_data = (struct lvgl_disp_data *)lv_display_get_user_data(disp); struct display_capabilities *cap = &disp_data->cap; lv_point_t *point = &data->common_data.pending_event.point; @@ -137,6 +138,8 @@ int lvgl_pointer_input_init(const struct device *dev) lvgl_pointer_process_event); \ static const struct lvgl_pointer_input_config lvgl_pointer_input_config_##inst = { \ .common_config.event_msgq = &LVGL_INPUT_EVENT_MSGQ(inst, pointer), \ + .common_config.display_dev = \ + DEVICE_DT_GET_OR_NULL(DT_INST_PHANDLE(inst, display)), \ .swap_xy = DT_INST_PROP(inst, swap_xy), \ .invert_x = DT_INST_PROP(inst, invert_x), \ .invert_y = DT_INST_PROP(inst, invert_y), \