linuxOS_AP06/buildroot/package/lvgl/lv_drivers/0016-lv_drivers-Add-support-rkadk.patch
2025-06-03 12:28:32 +08:00

810 lines
22 KiB
Diff

From 2fcee0df544242e6df568e53c0ec6bd406020d86 Mon Sep 17 00:00:00 2001
From: ZiHan Huang <zack.huang@rock-chips.com>
Date: Fri, 28 Jun 2024 16:19:15 +0800
Subject: [PATCH] lv_drivers: Add support rkadk
Signed-off-by: ZiHan Huang <zack.huang@rock-chips.com>
---
CMakeLists.txt | 3 +
rkadk/rkadk.c | 734 +++++++++++++++++++++++++++++++++++++++++++++++++
rkadk/rkadk.h | 32 +++
3 files changed, 769 insertions(+)
create mode 100644 rkadk/rkadk.c
create mode 100644 rkadk/rkadk.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1491218..2210c87 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,6 +34,9 @@ if (LV_DRV_USE_RGA)
add_definitions(-DUSE_RGA=1)
include_directories(${CMAKE_SYSROOT}/usr/include/rga/)
endif()
+if (LV_DRV_USE_RKADK)
+ add_definitions(-DUSE_RKADK=1)
+endif()
add_definitions(-g -DLV_CONF_INCLUDE_SIMPLE)
include_directories(${CMAKE_SYSROOT}/usr/include/libdrm/)
diff --git a/rkadk/rkadk.c b/rkadk/rkadk.c
new file mode 100644
index 0000000..3f47da2
--- /dev/null
+++ b/rkadk/rkadk.c
@@ -0,0 +1,734 @@
+/*
+ * Copyright (c) 2023 Rockchip, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if USE_RKADK
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <lvgl/lvgl.h>
+
+#include <rkadk/rkadk_media_comm.h>
+#include <rkadk/rkadk_ui.h>
+
+#include <rga/rga.h>
+#include <rga/RgaApi.h>
+
+/**********************
+ * MACROS
+ **********************/
+//#define USE_DOUBLE_BUF
+
+#define DRM_CARD "/dev/dri/card0"
+#define DRM_CONNECTOR_ID -1 /* -1 for the first connected one */
+
+#define DBG_TAG "drm"
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#define print(msg, ...) fprintf(stderr, msg, ##__VA_ARGS__);
+#define err(msg, ...) print("error: " msg "\n", ##__VA_ARGS__)
+#define info(msg, ...) print(msg "\n", ##__VA_ARGS__)
+#define dbg(msg, ...) {} //print(DBG_TAG ": " msg "\n", ##__VA_ARGS__)
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+
+/**********************
+ * GLOBAL VARIABLES
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+static void *pMblk;
+
+struct disp_buffer
+{
+ RKADK_UI_FRAME_INFO frame_info;
+ unsigned long int size;
+ int32_t fd;
+ void *map;
+};
+
+struct disp_dev
+{
+ RKADK_MW_PTR ui_ptr;
+ lv_disp_rot_t rot;
+#ifdef USE_DOUBLE_BUF
+ struct disp_buffer *cur_bufs[2]; /* double buffering handling */
+ struct disp_buffer bufs[2];
+#else
+ struct disp_buffer bufs[1];
+#endif
+ uint32_t width, height;
+ uint32_t mm_width, mm_height;
+} disp_dev;
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+static int32_t drm_open(const char *path)
+{
+ int32_t fd, flags;
+ uint64_t has_dumb;
+ int32_t ret;
+
+ fd = open(path, O_RDWR);
+ if (fd < 0)
+ {
+ err("cannot open \"%s\"", path);
+ return -1;
+ }
+
+ /* set FD_CLOEXEC flag */
+ if ((flags = fcntl(fd, F_GETFD)) < 0 ||
+ fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
+ {
+ err("fcntl FD_CLOEXEC failed");
+ goto err;
+ }
+
+ /* check capability */
+ ret = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb);
+ if (ret < 0 || has_dumb == 0)
+ {
+ err("drmGetCap DRM_CAP_DUMB_BUFFER failed or \"%s\" doesn't have dumb "
+ "buffer", path);
+ goto err;
+ }
+
+ return fd;
+err:
+ close(fd);
+ return -1;
+}
+
+static int drm_find_connector(int32_t dev_fd)
+{
+ drmModeConnector *conn = NULL;
+ drmModeRes *res = NULL;
+ int32_t i;
+
+ if ((res = drmModeGetResources(dev_fd)) == NULL)
+ {
+ err("drmModeGetResources() failed");
+ return -1;
+ }
+
+ if (res->count_crtcs <= 0)
+ {
+ err("no Crtcs");
+ goto free_res;
+ }
+
+ /* find all available connectors */
+ for (i = 0; i < res->count_connectors; i++)
+ {
+ conn = drmModeGetConnector(dev_fd, res->connectors[i]);
+ if (!conn)
+ continue;
+
+#if DRM_CONNECTOR_ID >= 0
+ if (conn->connector_id != DRM_CONNECTOR_ID)
+ {
+ drmModeFreeConnector(conn);
+ continue;
+ }
+#endif
+
+ if (conn->connection == DRM_MODE_CONNECTED)
+ {
+ dbg("drm: connector %d: connected", conn->connector_id);
+ }
+ else if (conn->connection == DRM_MODE_DISCONNECTED)
+ {
+ dbg("drm: connector %d: disconnected", conn->connector_id);
+ }
+ else if (conn->connection == DRM_MODE_UNKNOWNCONNECTION)
+ {
+ dbg("drm: connector %d: unknownconnection", conn->connector_id);
+ }
+ else
+ {
+ dbg("drm: connector %d: unknown", conn->connector_id);
+ }
+
+ if (conn->connection == DRM_MODE_CONNECTED && conn->count_modes > 0)
+ break;
+
+ drmModeFreeConnector(conn);
+ conn = NULL;
+ };
+
+ if (!conn)
+ {
+ err("suitable connector not found");
+ goto free_res;
+ }
+
+ disp_dev.width = conn->modes[0].hdisplay;
+ if (disp_dev.width % 16 != 0)
+ {
+ disp_dev.width = (disp_dev.width + 16) & (~15);
+ }
+ disp_dev.height = conn->modes[0].vdisplay;
+ disp_dev.mm_width = conn->mmWidth;
+ disp_dev.mm_height = conn->mmHeight;
+
+ return 0;
+
+free_res:
+ drmModeFreeResources(res);
+
+ return -1;
+}
+
+static int32_t get_disp_info(void)
+{
+ int32_t dev_fd, ret;
+ const char *device_path = NULL;
+
+ device_path = getenv("DRM_CARD");
+ if (!device_path)
+ device_path = DRM_CARD;
+
+ dev_fd = drm_open(device_path);
+ if (dev_fd < 0)
+ return -1;
+
+ ret = drm_find_connector(dev_fd);
+ if (ret)
+ {
+ err("available drm devices not found");
+ close(dev_fd);
+ return -1;
+ }
+
+ close(dev_fd);
+
+ info("rk_disp: %dx%d (%dmm X% dmm)",
+ disp_dev.width, disp_dev.height, disp_dev.mm_width, disp_dev.mm_height);
+
+ return 0;
+}
+
+static int32_t rk_disp_setup(void)
+{
+ int32_t ret;
+
+ RKADK_MPI_SYS_Init();
+
+ RKADK_UI_ATTR_S ui_attr;
+
+ memset(&ui_attr, 0, sizeof(ui_attr));
+
+ ui_attr.u32VoChn = 2;
+ ui_attr.u32VoDev = -1;
+ ui_attr.u32VoLay = -1;
+ ui_attr.u32DispFrmRt = 30;
+ ui_attr.u32DispWidth = disp_dev.width;
+ ui_attr.u32DispHeight = disp_dev.height;
+ ui_attr.u32ImgWidth = disp_dev.width;
+ ui_attr.u32ImgHeight = disp_dev.height;
+ ui_attr.enUiVoFormat = VO_FORMAT_RGB888;
+ ui_attr.enVoSpliceMode = SPLICE_MODE_RGA;
+
+#ifdef PLATFORM_RV1106
+ ui_attr.enUiVoIntfTye = DISPLAY_TYPE_DEFAULT;
+#else
+ ui_attr.enUiVoIntfTye = DISPLAY_TYPE_MIPI;
+#endif
+
+ ret = RKADK_UI_Create(&ui_attr, &disp_dev.ui_ptr);
+ if (0 != ret)
+ {
+ err("RKADK_DISP_Init failed(%d)", ret);
+ return -1;
+ }
+
+ info("rk_disp: ui created successfullyl.");
+
+ return 0;
+}
+
+static void rk_disp_teardown(void)
+{
+ if (NULL == disp_dev.ui_ptr)
+ return;
+
+ int32_t ret = RKADK_UI_Destroy(disp_dev.ui_ptr);
+ if (0 != ret)
+ err("RKADK_DISP_Init failed(%d)", ret);
+
+ info("rk_disp: ui destroyed successfully.");
+}
+
+static int32_t rk_disp_setup_buffers(void)
+{
+ int32_t ret;
+ uint32_t i, size;
+ void *blk = NULL;
+ RKADK_FORMAT_E format;
+
+ if (LV_COLOR_DEPTH == 32)
+ {
+ format = RKADK_FMT_BGRA8888;
+ }
+ else
+ {
+ format = -1;
+ err("drm_flush rga not supported format\n");
+ return -1;
+ }
+
+ size = disp_dev.width * disp_dev.height * (LV_COLOR_SIZE / 8);
+ //size = 1088 * disp_dev.height * (LV_COLOR_SIZE / 8);
+ for (i = 0; i < sizeof(disp_dev.bufs) / sizeof(disp_dev.bufs[0]); i++)
+ {
+ ret = RK_MPI_MMZ_Alloc(&blk, size, RK_MMZ_ALLOC_CACHEABLE);
+ if (0 != ret)
+ {
+ err("alloc failed!");
+ break;
+ }
+
+ disp_dev.bufs[i].frame_info.Format = format;
+ disp_dev.bufs[i].frame_info.pMblk = blk;
+ disp_dev.bufs[i].frame_info.u32Width = disp_dev.width;
+ //disp_dev.bufs[i].frame_info.u32Width = 1088;
+ disp_dev.bufs[i].frame_info.u32Height = disp_dev.height;
+ disp_dev.bufs[i].size = size;
+ disp_dev.bufs[i].map = RK_MPI_MMZ_Handle2VirAddr(blk);
+ disp_dev.bufs[i].fd = RK_MPI_MMZ_Handle2Fd(blk);
+
+ memset(disp_dev.bufs[i].map, 0xff, size);
+
+ info("rk_disp: ui bufs[%u] application is successful.", i);
+ }
+
+#ifdef USE_DOUBLE_BUF
+ /* Set buffering handling */
+ disp_dev.cur_bufs[0] = NULL;
+ disp_dev.cur_bufs[1] = &disp_dev.bufs[0];
+#endif
+
+ return 0;
+}
+
+static void rk_disp_teardown_buffers(void)
+{
+ for (uint32_t i = 0; i < sizeof(disp_dev.bufs) / sizeof(disp_dev.bufs[0]); i++)
+ {
+ if (NULL != disp_dev.bufs[i].frame_info.pMblk)
+ {
+ RK_MPI_MMZ_Free(disp_dev.bufs[i].frame_info.pMblk);
+ memset(&disp_dev.bufs[i], 0, sizeof(disp_dev.bufs[i]));
+ info("rk_disp: ui bufs[%d] released successfully.", i);
+ }
+ }
+}
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+int32_t rk_disp_init(lv_disp_rot_t rotate_disp)
+{
+ int32_t ret;
+
+ ret = get_disp_info();
+ if (0 != ret)
+ {
+ err("get display info failed");
+ return -1;
+ }
+
+ ret = rk_disp_setup();
+ if (0 != ret)
+ {
+ err("rk_disp_setup failed");
+ return -1;
+ }
+
+ ret = rk_disp_setup_buffers();
+ if (0 != ret)
+ {
+ err("Allocating display buffer failed");
+ goto err;
+ }
+
+ disp_dev.rot = rotate_disp;
+
+ return 0;
+err:
+ rk_disp_teardown();
+
+ return -1;
+}
+
+void rk_disp_exit(void)
+{
+ rk_disp_teardown_buffers();
+ rk_disp_teardown();
+ RKADK_MPI_SYS_Exit();
+}
+
+static void draw_buf_rotate_90(lv_color_t *color_p, const lv_area_t *area,
+ lv_color_t *dst_buf, lv_coord_t canvas_w, lv_coord_t canvas_h)
+{
+ lv_coord_t area_w = (area->x2 - area->x1 + 1);
+ lv_coord_t area_h = (area->y2 - area->y1 + 1);
+ uint32_t initial_i = area->x1 * canvas_w + (canvas_w - area->y1 - 1);
+ for (lv_coord_t y = 0; y < area_h; y++)
+ {
+ uint32_t i = initial_i - y;
+ for (lv_coord_t x = 0; x < area_w; x++)
+ {
+ dst_buf[i] = *(color_p++);
+ i += canvas_w;
+ }
+ }
+}
+
+#ifdef USE_DOUBLE_BUF
+void rk_disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) {
+ int32_t format = 0;
+ bool partial_update = false;
+ struct disp_buffer *fbuf = disp_dev.cur_bufs[1];
+ lv_coord_t w = (area->x2 - area->x1 + 1);
+ lv_coord_t h = (area->y2 - area->y1 + 1);
+
+ dbg("x %d:%d y %d:%d w %d h %d", area->x1, area->x2, area->y1, area->y2, w, h);
+
+ if (LV_COLOR_DEPTH == 16) {
+ format = RK_FORMAT_RGB_565;
+ }else if (LV_COLOR_DEPTH == 32) {
+ format = RK_FORMAT_ARGB_8888;
+ }else {
+ format = -1;
+ printf("drm_flush rga not supported format\n");
+ return;
+ }
+
+ rga_info_t src;
+ rga_info_t dst;
+
+ /* Partial update */
+ if (disp_dev.rot == LV_DISP_ROT_90 || disp_dev.rot == LV_DISP_ROT_270) {
+ if ((w != disp_dev.height || h != disp_dev.width) && disp_dev.cur_bufs[0])
+ partial_update = true;
+ } else {
+ if ((w != disp_dev.width || h != disp_dev.height) && disp_dev.cur_bufs[0])
+ partial_update = true;
+ }
+
+ if (true == partial_update) {
+ memset(&src, 0, sizeof(rga_info_t));
+ memset(&dst, 0, sizeof(rga_info_t));
+
+ src.fd = disp_dev.cur_bufs[0]->fd;
+ src.mmuFlag = 1;
+ dst.fd = fbuf->fd;
+ dst.mmuFlag = 1;
+ rga_set_rect(&src.rect, 0, 0, disp_dev.width, disp_dev.height,
+ disp_dev.width, disp_dev.height, format);
+ rga_set_rect(&dst.rect, 0, 0, disp_dev.width, disp_dev.height,
+ disp_dev.width, disp_dev.height, format);
+ if (c_RkRgaBlit(&src, &dst, NULL))
+ printf("c_RkRgaBlit2 error : %s\n", strerror(errno));
+ }
+
+ memset(&src, 0, sizeof(rga_info_t));
+ memset(&dst, 0, sizeof(rga_info_t));
+
+ if (disp_dev.rot == LV_DISP_ROT_90 || disp_dev.rot == LV_DISP_ROT_270) {
+ if (w < 2 || h < 2) {
+ draw_buf_rotate_90(color_p, area, fbuf->map, disp_dev.width, disp_dev.height);
+ } else {
+ src.virAddr = color_p;
+ src.mmuFlag = 1;
+ src.rotation = HAL_TRANSFORM_ROT_90;
+ dst.fd = fbuf->fd;
+ dst.mmuFlag = 1;
+ rga_set_rect(&src.rect, 0, 0, w, h, w, h, format);
+ rga_set_rect(&dst.rect, (disp_dev.width - (area->y1 + h)), area->x1, h, w,
+ disp_dev.width, disp_dev.height, format);
+ if (c_RkRgaBlit(&src, &dst, NULL))
+ printf("c_RkRgaBlit2 error : %s\n", strerror(errno));
+ }
+ } else {
+ if (w < 2 || h < 2) {
+ for (uint32_t y = 0, i = area->y1 ; i <= area->y2 ; ++i, ++y) {
+ memcpy((uint8_t *)fbuf->map + (area->x1 + disp_dev.width * i) * (LV_COLOR_SIZE/8),
+ (uint8_t *)color_p + (w * (LV_COLOR_SIZE/8) * y),
+ w * (LV_COLOR_SIZE/8));
+ }
+ } else {
+ src.virAddr = color_p;
+ src.mmuFlag = 1;
+ dst.fd = fbuf->fd;
+ dst.mmuFlag = 1;
+ rga_set_rect(&src.rect, 0, 0, w, h, w, h, format);
+ rga_set_rect(&dst.rect, area->x1, area->y1, w, h,
+ disp_dev.width, disp_dev.height, format);
+ if (c_RkRgaBlit(&src, &dst, NULL))
+ printf("c_RkRgaBlit2 error : %s\n", strerror(errno));
+ }
+ }
+ /* show fbuf plane */
+ RK_MPI_SYS_MmzFlushCache(fbuf->frame_info.pMblk, RK_FALSE);
+ RKADK_UI_Update(disp_dev.ui_ptr, &(fbuf->frame_info));
+
+ if (!disp_dev.cur_bufs[0])
+ disp_dev.cur_bufs[1] = &disp_dev.bufs[1];
+ else
+ disp_dev.cur_bufs[1] = disp_dev.cur_bufs[0];
+
+ disp_dev.cur_bufs[0] = fbuf;
+
+ lv_disp_flush_ready(disp_drv);
+}
+#else
+void rk_disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area,
+ lv_color_t *color_p)
+{
+ int32_t format = 0;
+ struct disp_buffer *fbuf = &disp_dev.bufs[0];
+ lv_coord_t w = (area->x2 - area->x1 + 1);
+ lv_coord_t h = (area->y2 - area->y1 + 1);
+
+ dbg("x %d:%d y %d:%d w %d h %d", area->x1, area->x2, area->y1, area->y2, w, h);
+
+ if (LV_COLOR_DEPTH == 16)
+ {
+ format = RK_FORMAT_RGB_565;
+ }
+ else if (LV_COLOR_DEPTH == 32)
+ {
+ format = RK_FORMAT_ARGB_8888;
+ }
+ else
+ {
+ format = -1;
+ printf("drm_flush rga not supported format\n");
+ return;
+ }
+
+ rga_info_t src;
+ rga_info_t dst;
+
+ memset(&src, 0, sizeof(rga_info_t));
+ memset(&dst, 0, sizeof(rga_info_t));
+
+ /* Partial update */
+ if (disp_dev.rot == LV_DISP_ROT_90 || disp_dev.rot == LV_DISP_ROT_270)
+ {
+ if (w < 2 || h < 2)
+ {
+ draw_buf_rotate_90(color_p, area, fbuf->map, disp_dev.width, disp_dev.height);
+ }
+ else
+ {
+ src.virAddr = color_p;
+ src.mmuFlag = 1;
+ src.rotation = HAL_TRANSFORM_ROT_90;
+ dst.fd = fbuf->fd;
+ dst.mmuFlag = 1;
+ rga_set_rect(&src.rect, 0, 0, w, h, w, h, format);
+ rga_set_rect(&dst.rect, (disp_dev.width - (area->y1 + h)), area->x1, h, w,
+ disp_dev.width, disp_dev.height, format);
+ if (c_RkRgaBlit(&src, &dst, NULL))
+ printf("c_RkRgaBlit2 error : %s\n", strerror(errno));
+ }
+ }
+ else
+ {
+ if (w < 2 || h < 2)
+ {
+ for (uint32_t y = 0, i = area->y1 ; i <= area->y2 ; ++i, ++y)
+ {
+ memcpy((uint8_t *)fbuf->map + (area->x1 + disp_dev.width * i) *
+ (LV_COLOR_SIZE / 8),
+ (uint8_t *)color_p + (w * (LV_COLOR_SIZE / 8) * y),
+ w * (LV_COLOR_SIZE / 8));
+ }
+ }
+ else
+ {
+ src.virAddr = color_p;
+ src.mmuFlag = 1;
+ dst.fd = fbuf->fd;
+ dst.mmuFlag = 1;
+ rga_set_rect(&src.rect, 0, 0, w, h, w, h, format);
+ rga_set_rect(&dst.rect, area->x1, area->y1, w, h,
+ disp_dev.width, disp_dev.height, format);
+ if (c_RkRgaBlit(&src, &dst, NULL))
+ printf("c_RkRgaBlit2 error : %s\n", strerror(errno));
+ }
+
+ // force cpu
+ // for (uint32_t y = 0, i = area->y1 ; i <= area->y2 ; ++i, ++y) {
+ // memcpy((uint8_t *)fbuf->map + (area->x1 + disp_dev.width * i) * (LV_COLOR_SIZE/8),
+ // (uint8_t *)color_p + (w * (LV_COLOR_SIZE/8) * y),
+ // w * (LV_COLOR_SIZE/8));
+ // }
+
+ //force cpu
+ // for (uint32_t y = 0, i = area->y1 ; i <= area->y2 ; ++i, ++y) {
+ // memcpy((uint8_t *)fbuf->map + (area->x1 + 1088 * i) * (LV_COLOR_SIZE/8),
+ // (uint8_t *)color_p + (w * (LV_COLOR_SIZE/8) * y),
+ // w * (LV_COLOR_SIZE/8));
+ // }
+ }
+
+ /* show fbuf plane */
+
+ RKADK_UI_Update(disp_dev.ui_ptr, &(disp_dev.bufs[0].frame_info));
+ RK_MPI_SYS_MmzFlushCache(disp_dev.bufs[0].frame_info.pMblk, RK_FALSE);
+ lv_disp_flush_ready(disp_drv);
+
+}
+#endif
+
+void rk_disp_get_sizes(lv_coord_t *width, lv_coord_t *height, uint32_t *dpi)
+{
+ if (width)
+ *width = disp_dev.width;
+
+ if (height)
+ *height = disp_dev.height;
+
+ if (dpi && disp_dev.mm_width)
+ *dpi = DIV_ROUND_UP(disp_dev.width * 25400, disp_dev.mm_width * 1000);
+
+ return;
+}
+
+void rkadk_disp_drv_init(lv_disp_rot_t rotate_disp)
+{
+ lv_coord_t lcd_w, lcd_h;
+ /*-------------------------
+ * Initialize your display
+ * -----------------------*/
+ rk_disp_init(rotate_disp);
+ rk_disp_get_sizes(&lcd_w, &lcd_h, NULL);
+ /*-----------------------------
+ * Create a buffer for drawing
+ *----------------------------*/
+
+ /**
+ * LVGL requires a buffer where it internally draws the widgets.
+ * Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display.
+ * The buffer has to be greater than 1 display row
+ *
+ * There are 3 buffering configurations:
+ * 1. Create ONE buffer:
+ * LVGL will draw the display's content here and writes it to your display
+ *
+ * 2. Create TWO buffer:
+ * LVGL will draw the display's content to a buffer and writes it your display.
+ * You should use DMA to write the buffer's content to the display.
+ * It will enable LVGL to draw the next part of the screen to the other buffer while
+ * the data is being sent form the first buffer. It makes rendering and flushing parallel.
+ *
+ * 3. Double buffering
+ * Set 2 screens sized buffers and set disp_drv.full_refresh = 1.
+ * This way LVGL will always provide the whole rendered screen in `flush_cb`
+ * and you only need to change the frame buffer's address.
+ */
+
+ /* Example for 1) */
+ static lv_disp_draw_buf_t draw_buf_dsc;
+ lv_color_t *draw_buf = NULL;
+ uint32_t size_in_px_cnt = lcd_w * lcd_h;
+ if (0 != RK_MPI_MMZ_Alloc(&pMblk, (size_in_px_cnt * (LV_COLOR_SIZE / 8)),
+ RK_MMZ_ALLOC_CACHEABLE))
+ {
+ return ;
+ }
+ draw_buf = RK_MPI_MMZ_Handle2VirAddr(pMblk);
+ lv_disp_draw_buf_init(&draw_buf_dsc, draw_buf, NULL,
+ size_in_px_cnt); /*Initialize the display buffer*/
+
+ /*-----------------------------------
+ * Register the display in LVGL
+ *----------------------------------*/
+
+ static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
+ lv_disp_drv_init(&disp_drv); /*Basic initialization*/
+
+ /*Set up the functions to access to your display*/
+
+ /*Set the resolution of the display*/
+ if (rotate_disp == LV_DISP_ROT_NONE)
+ {
+ disp_drv.hor_res = lcd_w;
+ disp_drv.ver_res = lcd_h;
+ disp_drv.sw_rotate = 0;
+ disp_drv.rotated = LV_DISP_ROT_NONE;
+ }
+ else if (rotate_disp == LV_DISP_ROT_180)
+ {
+ disp_drv.hor_res = lcd_w;
+ disp_drv.ver_res = lcd_h;
+ disp_drv.sw_rotate = 1;
+ disp_drv.rotated = LV_DISP_ROT_180;
+ }
+ else if (rotate_disp == LV_DISP_ROT_90)
+ {
+ disp_drv.hor_res = lcd_h;
+ disp_drv.ver_res = lcd_w;
+ disp_drv.sw_rotate = 0;
+ disp_drv.rotated = LV_DISP_ROT_NONE;
+ }
+ else if (rotate_disp == LV_DISP_ROT_270)
+ {
+ disp_drv.hor_res = lcd_h;
+ disp_drv.ver_res = lcd_w;
+ disp_drv.sw_rotate = 1;
+ disp_drv.rotated = LV_DISP_ROT_270;
+ }
+
+ /*Used to copy the buffer's content to the display*/
+ disp_drv.flush_cb = rk_disp_flush;
+
+ /*Set a display buffer*/
+ disp_drv.draw_buf = &draw_buf_dsc;
+
+ /*Finally register the driver*/
+ lv_disp_drv_register(&disp_drv);
+}
+
+void lv_port_disp_deinit(void)
+{
+ if (NULL != pMblk)
+ {
+ RK_MPI_MMZ_Free(pMblk);
+ pMblk = NULL;
+ }
+
+ rk_disp_exit();
+}
+#endif
diff --git a/rkadk/rkadk.h b/rkadk/rkadk.h
new file mode 100644
index 0000000..3fabb0a
--- /dev/null
+++ b/rkadk/rkadk.h
@@ -0,0 +1,32 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************
+ * INCLUDES
+ *********************/
+#ifndef LV_DRV_NO_CONF
+#ifdef LV_CONF_INCLUDE_SIMPLE
+#include "lv_drv_conf.h"
+#else
+#include "../../lv_drv_conf.h"
+#endif
+#endif
+
+#if USE_RKADK
+#include <rkadk_media_comm.h>
+#include <rkadk_ui.h>
+
+// Concrete realization
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+void rkadk_disp_drv_init(int rot);
+void lv_port_disp_deinit(void);
+
+#endif /*USE_RKADK*/
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
--
2.34.1