drivers/video/fb: adapt to fbmem dynamic update.

Considering that the future fb needs to achieve dynamic resolution, the address and size of fbmem will be redistributed on the bottom driver side, so remove fbmem, fblen, and bpp cached in fb_chardev_s, and change it to call getplaneinfo every time to re-acquire panel info from the bottom driver. Avoid cache coherency problems.

Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
Signed-off-by: jianglianfang <jianglianfang@xiaomi.com>
This commit is contained in:
pengyiqiang 2023-03-30 15:07:42 +08:00 committed by Xiang Xiao
parent f132edbf35
commit 26e99ed042

View File

@ -42,6 +42,12 @@
#include <nuttx/clock.h>
#include <nuttx/wdog.h>
/****************************************************************************
* Pre-processor definitions
****************************************************************************/
#define FB_NO_OVERLAY -1
/****************************************************************************
* Private Types
****************************************************************************/
@ -55,14 +61,21 @@
struct fb_chardev_s
{
FAR struct fb_vtable_s *vtable; /* Framebuffer interface */
FAR void *fbmem; /* Start of frame buffer memory */
FAR struct pollfd *fds; /* Polling structure of waiting thread */
size_t fblen; /* Size of the framebuffer */
uint8_t plane; /* Video plan number */
uint8_t bpp; /* Bits per pixel */
volatile bool pollready; /* Poll ready flag */
clock_t vsyncoffset; /* VSync offset ticks */
struct wdog_s wdog; /* VSync offset timer */
#ifdef CONFIG_FB_OVERLAY
int overlay; /* Overlay number */
#endif
};
struct fb_panelinfo_s
{
FAR void *fbmem; /* Start of frame buffer memory */
size_t fblen; /* Size of the framebuffer */
uint8_t bpp; /* Bits per pixel */
};
/****************************************************************************
@ -79,6 +92,8 @@ static int fb_mmap(FAR struct file *filep,
FAR struct mm_map_entry_s *map);
static int fb_poll(FAR struct file *filep, FAR struct pollfd *fds,
bool setup);
static int fb_get_panelinfo(FAR struct fb_chardev_s *fb,
FAR struct fb_panelinfo_s *panelinfo);
/****************************************************************************
* Private Data
@ -109,9 +124,11 @@ static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len)
{
FAR struct inode *inode;
FAR struct fb_chardev_s *fb;
struct fb_panelinfo_s panelinfo;
size_t start;
size_t end;
size_t size;
int ret;
ginfo("len: %u\n", (unsigned int)len);
@ -121,25 +138,34 @@ static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t len)
inode = filep->f_inode;
fb = (FAR struct fb_chardev_s *)inode->i_private;
/* Get panel info */
ret = fb_get_panelinfo(fb, &panelinfo);
if (ret < 0)
{
return ret;
}
/* Get the start and size of the transfer */
start = filep->f_pos;
if (start >= fb->fblen)
if (start >= panelinfo.fblen)
{
return 0; /* Return end-of-file */
}
end = start + len;
if (end >= fb->fblen)
if (end >= panelinfo.fblen)
{
end = fb->fblen;
end = panelinfo.fblen;
}
size = end - start;
/* And transfer the data from the frame buffer */
memcpy(buffer, fb->fbmem + start, size);
memcpy(buffer, panelinfo.fbmem + start, size);
filep->f_pos += size;
return size;
}
@ -153,9 +179,11 @@ static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer,
{
FAR struct inode *inode;
FAR struct fb_chardev_s *fb;
struct fb_panelinfo_s panelinfo;
size_t start;
size_t end;
size_t size;
int ret;
ginfo("len: %u\n", (unsigned int)len);
@ -165,27 +193,36 @@ static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer,
inode = filep->f_inode;
fb = (FAR struct fb_chardev_s *)inode->i_private;
/* Get panel info */
ret = fb_get_panelinfo(fb, &panelinfo);
if (ret < 0)
{
return ret;
}
fb->pollready = false;
/* Get the start and size of the transfer */
start = filep->f_pos;
if (start >= fb->fblen)
if (start >= panelinfo.fblen)
{
return -EFBIG; /* Cannot extend the framebuffer */
}
end = start + len;
if (end >= fb->fblen)
if (end >= panelinfo.fblen)
{
end = fb->fblen;
end = panelinfo.fblen;
}
size = end - start;
/* And transfer the data into the frame buffer */
memcpy(fb->fbmem + start, buffer, size);
memcpy(panelinfo.fbmem + start, buffer, size);
filep->f_pos += size;
return size;
}
@ -204,6 +241,7 @@ static off_t fb_seek(FAR struct file *filep, off_t offset, int whence)
{
FAR struct inode *inode;
FAR struct fb_chardev_s *fb;
struct fb_panelinfo_s panelinfo;
off_t newpos;
int ret;
@ -228,7 +266,17 @@ static off_t fb_seek(FAR struct file *filep, off_t offset, int whence)
break;
case SEEK_END:
newpos = fb->fblen + offset;
/* Get panel info */
ret = fb_get_panelinfo(fb, &panelinfo);
if (ret < 0)
{
return ret;
}
newpos = panelinfo.fblen + offset;
break;
default:
@ -388,9 +436,7 @@ static int fb_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
ret = fb->vtable->getoverlayinfo(fb->vtable, arg, &oinfo);
if (ret == OK)
{
fb->fbmem = oinfo.fbmem;
fb->fblen = oinfo.fblen;
fb->bpp = oinfo.bpp;
fb->overlay = arg;
}
}
break;
@ -704,7 +750,8 @@ static int fb_mmap(FAR struct file *filep, FAR struct mm_map_entry_s *map)
{
FAR struct inode *inode;
FAR struct fb_chardev_s *fb;
int ret = -EINVAL;
struct fb_panelinfo_s panelinfo;
int ret;
/* Get the framebuffer instance */
@ -712,16 +759,25 @@ static int fb_mmap(FAR struct file *filep, FAR struct mm_map_entry_s *map)
inode = filep->f_inode;
fb = (FAR struct fb_chardev_s *)inode->i_private;
/* Return the address corresponding to the start of frame buffer. */
/* Get panel info */
if (map->offset >= 0 && map->offset < fb->fblen &&
map->length && map->offset + map->length <= fb->fblen)
ret = fb_get_panelinfo(fb, &panelinfo);
if (ret < 0)
{
map->vaddr = (FAR char *)fb->fbmem + map->offset;
ret = OK;
return ret;
}
return ret;
/* Return the address corresponding to the start of frame buffer. */
if (map->offset >= 0 && map->offset < panelinfo.fblen &&
map->length && map->offset + map->length <= panelinfo.fblen)
{
map->vaddr = (FAR char *)panelinfo.fbmem + map->offset;
return OK;
}
return -EINVAL;
}
/****************************************************************************
@ -769,6 +825,56 @@ static int fb_poll(FAR struct file *filep, struct pollfd *fds, bool setup)
return OK;
}
/****************************************************************************
* Name: fb_get_panelinfo
****************************************************************************/
static int fb_get_panelinfo(FAR struct fb_chardev_s *fb,
FAR struct fb_panelinfo_s *panelinfo)
{
struct fb_planeinfo_s pinfo;
int ret;
#ifdef CONFIG_FB_OVERLAY
if (fb->overlay != FB_NO_OVERLAY)
{
struct fb_overlayinfo_s oinfo;
DEBUGASSERT(fb->vtable->getoverlayinfo != NULL);
memset(&oinfo, 0, sizeof(oinfo));
ret = fb->vtable->getoverlayinfo(fb->vtable, fb->overlay, &oinfo);
if (ret < 0)
{
gerr("ERROR: getoverlayinfo() failed: %d\n", ret);
return ret;
}
panelinfo->fbmem = oinfo.fbmem;
panelinfo->fblen = oinfo.fblen;
panelinfo->bpp = oinfo.bpp;
return OK;
}
#endif
DEBUGASSERT(fb->vtable != NULL);
DEBUGASSERT(fb->vtable->getplaneinfo != NULL);
memset(&pinfo, 0, sizeof(pinfo));
ret = fb->vtable->getplaneinfo(fb->vtable, fb->plane, &pinfo);
if (ret < 0)
{
gerr("ERROR: getplaneinfo() failed: %d\n", ret);
return ret;
}
panelinfo->fbmem = pinfo.fbmem;
panelinfo->fblen = pinfo.fblen;
panelinfo->bpp = pinfo.bpp;
return OK;
}
/****************************************************************************
* Name: fb_do_pollnotify
****************************************************************************/
@ -784,6 +890,10 @@ static void fb_do_pollnotify(wdparm_t arg)
poll_notify(&fb->fds, 1, POLLOUT);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fb_pollnotify
*
@ -820,10 +930,6 @@ void fb_pollnotify(FAR struct fb_vtable_s *vtable)
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: fb_register
*
@ -850,8 +956,8 @@ void fb_pollnotify(FAR struct fb_vtable_s *vtable)
int fb_register(int display, int plane)
{
FAR struct fb_chardev_s *fb;
struct fb_panelinfo_s panelinfo;
struct fb_videoinfo_s vinfo;
struct fb_planeinfo_s pinfo;
#ifdef CONFIG_FB_OVERLAY
struct fb_overlayinfo_s oinfo;
#endif
@ -867,6 +973,13 @@ int fb_register(int display, int plane)
return -ENOMEM;
}
#ifdef CONFIG_FB_OVERLAY
/* Set the default overlay number */
fb->overlay = FB_NO_OVERLAY;
#endif
/* Initialize the frame buffer device. */
ret = up_fbinitialize(display);
@ -902,22 +1015,18 @@ int fb_register(int display, int plane)
nplanes = vinfo.nplanes;
DEBUGASSERT(vinfo.nplanes > 0 && (unsigned)plane < vinfo.nplanes);
DEBUGASSERT(fb->vtable->getplaneinfo != NULL);
memset(&pinfo, 0, sizeof(pinfo));
ret = fb->vtable->getplaneinfo(fb->vtable, plane, &pinfo);
/* Get panel info */
ret = fb_get_panelinfo(fb, &panelinfo);
if (ret < 0)
{
gerr("ERROR: getplaneinfo() failed: %d\n", ret);
goto errout_with_fb;
}
fb->fbmem = pinfo.fbmem;
fb->fblen = pinfo.fblen;
fb->bpp = pinfo.bpp;
/* Clear the framebuffer memory */
memset(pinfo.fbmem, 0, pinfo.fblen);
memset(panelinfo.fbmem, 0, panelinfo.fblen);
#ifdef CONFIG_FB_OVERLAY
/* Initialize first overlay but do not select */