810 lines
22 KiB
Diff
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
|
|
|