|  | /* | 
|  | * Copyright (c) 2019 Jan Van Winkel <jan.van_winkel@dxplore.eu> | 
|  | * Copyright 2023 NXP | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <zephyr/kernel.h> | 
|  | #include <errno.h> | 
|  |  | 
|  | #include "lvgl_display.h" | 
|  |  | 
|  | #ifdef CONFIG_LV_Z_FLUSH_THREAD | 
|  |  | 
|  | K_SEM_DEFINE(flush_complete, 0, 1); | 
|  | /* Message queue will only ever need to queue one message */ | 
|  | K_MSGQ_DEFINE(flush_queue, sizeof(struct lvgl_display_flush), 1, 1); | 
|  |  | 
|  | void lvgl_flush_thread_entry(void *arg1, void *arg2, void *arg3) | 
|  | { | 
|  | struct lvgl_display_flush flush; | 
|  | struct lvgl_disp_data *data; | 
|  |  | 
|  | while (1) { | 
|  | k_msgq_get(&flush_queue, &flush, K_FOREVER); | 
|  | data = (struct lvgl_disp_data *)flush.disp_drv->user_data; | 
|  |  | 
|  | display_write(data->display_dev, flush.x, flush.y, &flush.desc, | 
|  | flush.buf); | 
|  |  | 
|  | lv_disp_flush_ready(flush.disp_drv); | 
|  | k_sem_give(&flush_complete); | 
|  | } | 
|  | } | 
|  |  | 
|  | K_THREAD_DEFINE(lvgl_flush_thread, CONFIG_LV_Z_FLUSH_THREAD_STACK_SIZE, | 
|  | lvgl_flush_thread_entry, NULL, NULL, NULL, | 
|  | K_PRIO_COOP(CONFIG_LV_Z_FLUSH_THREAD_PRIO), 0, 0); | 
|  |  | 
|  |  | 
|  | void lvgl_wait_cb(lv_disp_drv_t *disp_drv) | 
|  | { | 
|  | k_sem_take(&flush_complete, K_FOREVER); | 
|  | } | 
|  |  | 
|  | #endif /* CONFIG_LV_Z_FLUSH_THREAD */ | 
|  |  | 
|  | int set_lvgl_rendering_cb(lv_disp_drv_t *disp_drv) | 
|  | { | 
|  | int err = 0; | 
|  | struct lvgl_disp_data *data = (struct lvgl_disp_data *)disp_drv->user_data; | 
|  |  | 
|  | #ifdef CONFIG_LV_Z_FLUSH_THREAD | 
|  | disp_drv->wait_cb = lvgl_wait_cb; | 
|  | #endif | 
|  |  | 
|  | switch (data->cap.current_pixel_format) { | 
|  | case PIXEL_FORMAT_ARGB_8888: | 
|  | disp_drv->flush_cb = lvgl_flush_cb_32bit; | 
|  | disp_drv->rounder_cb = NULL; | 
|  | #ifdef CONFIG_LV_COLOR_DEPTH_32 | 
|  | disp_drv->set_px_cb = NULL; | 
|  | #else | 
|  | disp_drv->set_px_cb = lvgl_set_px_cb_32bit; | 
|  | #endif | 
|  | break; | 
|  | case PIXEL_FORMAT_RGB_888: | 
|  | disp_drv->flush_cb = lvgl_flush_cb_24bit; | 
|  | disp_drv->rounder_cb = NULL; | 
|  | disp_drv->set_px_cb = lvgl_set_px_cb_24bit; | 
|  | break; | 
|  | case PIXEL_FORMAT_RGB_565: | 
|  | case PIXEL_FORMAT_BGR_565: | 
|  | disp_drv->flush_cb = lvgl_flush_cb_16bit; | 
|  | disp_drv->rounder_cb = NULL; | 
|  | #ifdef CONFIG_LV_COLOR_DEPTH_16 | 
|  | disp_drv->set_px_cb = NULL; | 
|  | #else | 
|  | disp_drv->set_px_cb = lvgl_set_px_cb_16bit; | 
|  | #endif | 
|  | break; | 
|  | case PIXEL_FORMAT_MONO01: | 
|  | case PIXEL_FORMAT_MONO10: | 
|  | disp_drv->flush_cb = lvgl_flush_cb_mono; | 
|  | disp_drv->rounder_cb = lvgl_rounder_cb_mono; | 
|  | disp_drv->set_px_cb = lvgl_set_px_cb_mono; | 
|  | break; | 
|  | default: | 
|  | disp_drv->flush_cb = NULL; | 
|  | disp_drv->rounder_cb = NULL; | 
|  | disp_drv->set_px_cb = NULL; | 
|  | err = -ENOTSUP; | 
|  | break; | 
|  | } | 
|  |  | 
|  | return err; | 
|  | } | 
|  |  | 
|  | void lvgl_flush_display(struct lvgl_display_flush *request) | 
|  | { | 
|  | #ifdef CONFIG_LV_Z_FLUSH_THREAD | 
|  | /* | 
|  | * LVGL will only start a flush once the previous one is complete, | 
|  | * so we can reset the flush state semaphore here. | 
|  | */ | 
|  | k_sem_reset(&flush_complete); | 
|  | k_msgq_put(&flush_queue, request, K_FOREVER); | 
|  | /* Explicitly yield, in case the calling thread is a cooperative one */ | 
|  | k_yield(); | 
|  | #else | 
|  | /* Write directly to the display */ | 
|  | struct lvgl_disp_data *data = | 
|  | (struct lvgl_disp_data *)request->disp_drv->user_data; | 
|  |  | 
|  | display_write(data->display_dev, request->x, request->y, | 
|  | &request->desc, request->buf); | 
|  | lv_disp_flush_ready(request->disp_drv); | 
|  | #endif | 
|  | } |