feat(disp): update nuttx disp framebuffer (#4591)
Signed-off-by: rongyichang <rongyichang@xiaomi.com>
This commit is contained in:
8
Kconfig
8
Kconfig
@@ -1190,10 +1190,6 @@ menu "LVGL configuration"
|
||||
bool "Use BSD flavored framebuffer device"
|
||||
depends on LV_USE_LINUX_FBDEV
|
||||
default n
|
||||
config LV_LINUX_FBDEV_NUTTX
|
||||
bool "Use NuttX flavored framebuffer device"
|
||||
depends on LV_USE_LINUX_FBDEV
|
||||
default n
|
||||
|
||||
choice
|
||||
prompt "Framebuffer device render mode"
|
||||
@@ -1247,6 +1243,10 @@ menu "LVGL configuration"
|
||||
depends on LV_USE_LINUX_FBDEV && LV_LINUX_FBDEV_CUSTOM_BUFFER
|
||||
default 60
|
||||
|
||||
config LV_USE_NUTTX_FBDEV
|
||||
bool "Use Nuttx framebuffer device"
|
||||
default n
|
||||
|
||||
config LV_USE_NUTTX_LCD
|
||||
bool "Use NuttX LCD device"
|
||||
default n
|
||||
|
||||
@@ -168,6 +168,8 @@ Make sure `LV_MEM_SIZE` is no less than `(64*1024U)`.
|
||||
|
||||
- LV_USE_LINUX_FBDEV
|
||||
|
||||
- LV_USE_NUTTX_FBDEV
|
||||
|
||||
- LV_USE_LINUX_DRM
|
||||
|
||||
- LV_USE_TFT_ESPI
|
||||
|
||||
@@ -745,12 +745,13 @@
|
||||
#define LV_USE_LINUX_FBDEV 0
|
||||
#if LV_USE_LINUX_FBDEV
|
||||
#define LV_LINUX_FBDEV_BSD 0
|
||||
#define LV_LINUX_FBDEV_NUTTX 0
|
||||
#define LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL
|
||||
#define LV_LINUX_FBDEV_BUFFER_COUNT 0
|
||||
#define LV_LINUX_FBDEV_BUFFER_SIZE 60
|
||||
#endif
|
||||
|
||||
#define LV_USE_NUTTX_FBDEV 0
|
||||
|
||||
/*Driver for /dev/lcd*/
|
||||
#define LV_USE_NUTTX_LCD 0
|
||||
#if LV_USE_NUTTX_LCD
|
||||
|
||||
1
lvgl.h
1
lvgl.h
@@ -118,6 +118,7 @@ extern "C" {
|
||||
|
||||
#include "src/dev/display/drm/lv_linux_drm.h"
|
||||
#include "src/dev/display/fb/lv_linux_fbdev.h"
|
||||
#include "src/dev/display/fb/lv_nuttx_fbdev.h"
|
||||
#include "src/dev/display/lcd/lv_nuttx_lcd.h"
|
||||
|
||||
#include "src/dev/input/touchscreen/lv_nuttx_touchscreen.h"
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/consio.h>
|
||||
#include <sys/fbio.h>
|
||||
#elif LV_LINUX_FBDEV_NUTTX
|
||||
#include <nuttx/video/fb.h>
|
||||
#else
|
||||
#include <linux/fb.h>
|
||||
#endif /* LV_LINUX_FBDEV_BSD */
|
||||
@@ -130,13 +128,11 @@ void lv_linux_fbdev_set_file(lv_display_t * disp, const char * file)
|
||||
}
|
||||
LV_LOG_INFO("The framebuffer device was opened successfully");
|
||||
|
||||
#if !LV_LINUX_FBDEV_NUTTX
|
||||
/* Make sure that the display is on.*/
|
||||
if(ioctl(dsc->fbfd, FBIOBLANK, FB_BLANK_UNBLANK) != 0) {
|
||||
perror("ioctl(FBIOBLANK)");
|
||||
/* Don't return. Some framebuffer drivers like efifb or simplefb don't implement FBIOBLANK.*/
|
||||
}
|
||||
#endif /* !LV_LINUX_FBDEV_NUTTX */
|
||||
|
||||
#if LV_LINUX_FBDEV_BSD
|
||||
struct fbtype fb;
|
||||
@@ -256,16 +252,6 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * colo
|
||||
}
|
||||
}
|
||||
|
||||
#if LV_LINUX_FBDEV_NUTTX && defined(CONFIG_FB_UPDATE)
|
||||
/*May be some direct update command is required*/
|
||||
struct fb_area_s fb_area;
|
||||
fb_area.x = area->x1;
|
||||
fb_area.y = area->y1;
|
||||
fb_area.w = lv_area_get_width(area);
|
||||
fb_area.h = lv_area_get_height(area);
|
||||
ioctl(dsc->fbfd, FBIO_UPDATE, (unsigned long)((uintptr_t)&fb_area));
|
||||
#endif
|
||||
|
||||
lv_display_flush_ready(disp);
|
||||
}
|
||||
|
||||
|
||||
281
src/dev/display/fb/lv_nuttx_fbdev.c
Normal file
281
src/dev/display/fb/lv_nuttx_fbdev.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/**
|
||||
* @file lv_nuttx_fbdev.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_nuttx_fbdev.h"
|
||||
#if LV_USE_NUTTX_FBDEV
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <nuttx/video/fb.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
#include "../../../lvgl_private.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
struct fb_videoinfo_s vinfo;
|
||||
struct fb_planeinfo_s pinfo;
|
||||
|
||||
void * mem;
|
||||
void * mem2;
|
||||
uint32_t mem2_yoffset;
|
||||
int fd;
|
||||
} lv_nuttx_fb_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p);
|
||||
static int fbdev_get_pinfo(int fd, struct fb_planeinfo_s * pinfo);
|
||||
static int fbdev_init_mem2(lv_nuttx_fb_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lv_nuttx_fbdev_create
|
||||
****************************************************************************/
|
||||
|
||||
lv_display_t * lv_nuttx_fbdev_create(void)
|
||||
{
|
||||
lv_nuttx_fb_t * dsc = lv_malloc(sizeof(lv_nuttx_fb_t));
|
||||
LV_ASSERT_MALLOC(dsc);
|
||||
if(dsc == NULL) return NULL;
|
||||
lv_memzero(dsc, sizeof(lv_nuttx_fb_t));
|
||||
|
||||
lv_display_t * disp = lv_display_create(800, 480);
|
||||
if(disp == NULL) {
|
||||
lv_free(dsc);
|
||||
return NULL;
|
||||
}
|
||||
dsc->fd = -1;
|
||||
lv_display_set_driver_data(disp, dsc);
|
||||
lv_display_set_flush_cb(disp, flush_cb);
|
||||
return disp;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lv_nuttx_fbdev_set_file
|
||||
****************************************************************************/
|
||||
|
||||
int lv_nuttx_fbdev_set_file(lv_display_t * disp, const char * file)
|
||||
{
|
||||
int ret;
|
||||
LV_ASSERT(disp && file);
|
||||
lv_nuttx_fb_t * dsc = lv_display_get_driver_data(disp);
|
||||
|
||||
if(dsc->fd >= 0) close(dsc->fd);
|
||||
|
||||
/* Open the file for reading and writing*/
|
||||
dsc->fd = open(file, O_RDWR);
|
||||
if(dsc->fd < 0) {
|
||||
LV_LOG_ERROR("Error: cannot open framebuffer device");
|
||||
return -errno;
|
||||
}
|
||||
LV_LOG_INFO("The framebuffer device was opened successfully");
|
||||
|
||||
if(ioctl(dsc->fd, FBIOGET_VIDEOINFO, (unsigned long)((uintptr_t)&dsc->vinfo)) < 0) {
|
||||
LV_LOG_ERROR("ioctl(FBIOGET_VIDEOINFO) failed: %d", errno);
|
||||
ret = -errno;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
LV_LOG_INFO("VideoInfo:");
|
||||
LV_LOG_INFO(" fmt: %u", dsc->vinfo.fmt);
|
||||
LV_LOG_INFO(" xres: %u", dsc->vinfo.xres);
|
||||
LV_LOG_INFO(" yres: %u", dsc->vinfo.yres);
|
||||
LV_LOG_INFO(" nplanes: %u", dsc->vinfo.nplanes);
|
||||
|
||||
if((ret = fbdev_get_pinfo(dsc->fd, &dsc->pinfo)) < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
dsc->mem = mmap(NULL, dsc->pinfo.fblen, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_FILE, dsc->fd, 0);
|
||||
if(dsc->mem == MAP_FAILED) {
|
||||
LV_LOG_ERROR("ioctl(FBIOGET_PLANEINFO) failed: %d", errno);
|
||||
ret = -errno;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* double buffer mode */
|
||||
if(dsc->pinfo.yres_virtual == (dsc->vinfo.yres * 2)) {
|
||||
if((ret = fbdev_init_mem2(dsc)) < 0) {
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
lv_display_set_draw_buffers(disp, dsc->mem, dsc->mem2,
|
||||
(dsc->pinfo.stride * dsc->vinfo.yres), LV_DISP_RENDER_MODE_DIRECT);
|
||||
lv_display_set_resolution(disp, dsc->vinfo.xres, dsc->vinfo.yres);
|
||||
|
||||
LV_LOG_INFO("Resolution is set to %dx%d at %ddpi", dsc->vinfo.xres, dsc->vinfo.yres, lv_display_get_dpi(disp));
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
close(dsc->fd);
|
||||
dsc->fd = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p)
|
||||
{
|
||||
lv_nuttx_fb_t * dsc = lv_display_get_driver_data(disp);
|
||||
|
||||
if(dsc->mem == NULL ||
|
||||
area->x2 < 0 || area->y2 < 0 ||
|
||||
area->x1 > (int32_t)dsc->vinfo.xres - 1 || area->y1 > (int32_t)dsc->vinfo.yres - 1) {
|
||||
lv_display_flush_ready(disp);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FB_UPDATE)
|
||||
/*May be some direct update command is required*/
|
||||
struct fb_area_s fb_area;
|
||||
fb_area.x = area->x1;
|
||||
fb_area.y = area->y1;
|
||||
fb_area.w = lv_area_get_width(area);
|
||||
fb_area.h = lv_area_get_height(area);
|
||||
if(ioctl(dsc->fd, FBIO_UPDATE, (unsigned long)((uintptr_t)&fb_area)) < 0) {
|
||||
LV_LOG_ERROR("ioctl(FBIO_UPDATE) failed: %d", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* double framebuffer */
|
||||
if(dsc->mem2 != NULL) {
|
||||
if(disp->buf_act == disp->buf_1) {
|
||||
dsc->pinfo.yoffset = 0;
|
||||
}
|
||||
else {
|
||||
dsc->pinfo.yoffset = dsc->mem2_yoffset;
|
||||
}
|
||||
|
||||
if(ioctl(dsc->fd, FBIOPAN_DISPLAY, (unsigned long)((uintptr_t) & (dsc->pinfo))) < 0) {
|
||||
LV_LOG_ERROR("ioctl(FBIOPAN_DISPLAY) failed: %d", errno);
|
||||
}
|
||||
}
|
||||
lv_display_flush_ready(disp);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fbdev_get_pinfo
|
||||
****************************************************************************/
|
||||
|
||||
static int fbdev_get_pinfo(int fd, FAR struct fb_planeinfo_s * pinfo)
|
||||
{
|
||||
if(ioctl(fd, FBIOGET_PLANEINFO, (unsigned long)((uintptr_t)pinfo)) < 0) {
|
||||
LV_LOG_ERROR("ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d", errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
LV_LOG_INFO("PlaneInfo (plane %d):", pinfo->display);
|
||||
LV_LOG_INFO(" mem: %p", pinfo->mem);
|
||||
LV_LOG_INFO(" fblen: %zu", pinfo->fblen);
|
||||
LV_LOG_INFO(" stride: %u", pinfo->stride);
|
||||
LV_LOG_INFO(" display: %u", pinfo->display);
|
||||
LV_LOG_INFO(" bpp: %u", pinfo->bpp);
|
||||
|
||||
/* Only these pixel depths are supported. viinfo.fmt is ignored, only
|
||||
* certain color formats are supported.
|
||||
*/
|
||||
|
||||
if(pinfo->bpp != 32 && pinfo->bpp != 16 &&
|
||||
pinfo->bpp != 8 && pinfo->bpp != 1) {
|
||||
LV_LOG_ERROR("bpp = %u not supported", pinfo->bpp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fbdev_init_mem2
|
||||
****************************************************************************/
|
||||
|
||||
static int fbdev_init_mem2(lv_nuttx_fb_t * dsc)
|
||||
{
|
||||
uintptr_t buf_offset;
|
||||
struct fb_planeinfo_s pinfo;
|
||||
int ret;
|
||||
|
||||
memset(&pinfo, 0, sizeof(pinfo));
|
||||
|
||||
/* Get display[1] planeinfo */
|
||||
|
||||
pinfo.display = dsc->pinfo.display + 1;
|
||||
|
||||
if((ret = fbdev_get_pinfo(dsc->fd, &pinfo)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check bpp */
|
||||
|
||||
if(pinfo.bpp != dsc->pinfo.bpp) {
|
||||
LV_LOG_WARN("mem2 is incorrect");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check the buffer address offset,
|
||||
* It needs to be divisible by pinfo.stride
|
||||
*/
|
||||
|
||||
buf_offset = pinfo.fbmem - dsc->mem;
|
||||
|
||||
if((buf_offset % dsc->pinfo.stride) != 0) {
|
||||
LV_LOG_WARN("It is detected that buf_offset(%" PRIuPTR ") "
|
||||
"and stride(%d) are not divisible, please ensure "
|
||||
"that the driver handles the address offset by itself.",
|
||||
buf_offset, dsc->pinfo.stride);
|
||||
}
|
||||
|
||||
/* Calculate the address and yoffset of mem2 */
|
||||
|
||||
if(buf_offset == 0) {
|
||||
dsc->mem2_yoffset = dsc->vinfo.yres;
|
||||
dsc->mem2 = pinfo.fbmem + dsc->mem2_yoffset * pinfo.stride;
|
||||
LV_LOG_INFO("Use consecutive mem2 = %p, yoffset = %" PRIu32,
|
||||
dsc->mem2, dsc->mem2_yoffset);
|
||||
}
|
||||
else {
|
||||
dsc->mem2_yoffset = buf_offset / dsc->pinfo.stride;
|
||||
dsc->mem2 = pinfo.fbmem;
|
||||
LV_LOG_INFO("Use non-consecutive mem2 = %p, yoffset = %" PRIu32,
|
||||
dsc->mem2, dsc->mem2_yoffset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_NUTTX_FBDEV*/
|
||||
46
src/dev/display/fb/lv_nuttx_fbdev.h
Normal file
46
src/dev/display/fb/lv_nuttx_fbdev.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file lv_nuttx_fbdev_h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_NUTTX_FBDEV_H
|
||||
#define LV_NUTTX_FBDEV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../../display/lv_display.h"
|
||||
|
||||
#if LV_USE_NUTTX_FBDEV
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
lv_display_t * lv_nuttx_fbdev_create(void);
|
||||
|
||||
int lv_nuttx_fbdev_set_file(lv_display_t * disp, const char * file);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_NUTTX_FBDEV */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* LV_NUTTX_FBDEV_H */
|
||||
@@ -40,7 +40,7 @@ lv_indev_t * lv_nuttx_touchscreen_create(const char * dev_path);
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_LINUX_FBDEV */
|
||||
#endif /* LV_USE_NUTTX_TOUCHSCREEN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -2435,13 +2435,6 @@
|
||||
#define LV_LINUX_FBDEV_BSD 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef LV_LINUX_FBDEV_NUTTX
|
||||
#ifdef CONFIG_LV_LINUX_FBDEV_NUTTX
|
||||
#define LV_LINUX_FBDEV_NUTTX CONFIG_LV_LINUX_FBDEV_NUTTX
|
||||
#else
|
||||
#define LV_LINUX_FBDEV_NUTTX 0
|
||||
#endif
|
||||
#endif
|
||||
#ifndef LV_LINUX_FBDEV_RENDER_MODE
|
||||
#ifdef CONFIG_LV_LINUX_FBDEV_RENDER_MODE
|
||||
#define LV_LINUX_FBDEV_RENDER_MODE CONFIG_LV_LINUX_FBDEV_RENDER_MODE
|
||||
@@ -2465,6 +2458,14 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LV_USE_NUTTX_FBDEV
|
||||
#ifdef CONFIG_LV_USE_NUTTX_FBDEV
|
||||
#define LV_USE_NUTTX_FBDEV CONFIG_LV_USE_NUTTX_FBDEV
|
||||
#else
|
||||
#define LV_USE_NUTTX_FBDEV 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Driver for /dev/lcd*/
|
||||
#ifndef LV_USE_NUTTX_LCD
|
||||
#ifdef CONFIG_LV_USE_NUTTX_LCD
|
||||
|
||||
Reference in New Issue
Block a user