6a3c2aded6
* Simplify EINTR/ECANCEL error handling 1. Add semaphore uninterruptible wait function 2 .Replace semaphore wait loop with a single uninterruptible wait 3. Replace all sem_xxx to nxsem_xxx * Unify the void cast usage 1. Remove void cast for function because many place ignore the returned value witout cast 2. Replace void cast for variable with UNUSED macro
755 lines
21 KiB
C
755 lines
21 KiB
C
/****************************************************************************
|
|
* drivers/lcd/lcd_frambuffer.c
|
|
*
|
|
* Copyright (C) 2017=-2018 Gregory Nutt. All rights reserved.
|
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
|
* used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <debug.h>
|
|
|
|
#include <nuttx/board.h>
|
|
#include <nuttx/kmalloc.h>
|
|
#include <nuttx/nx/nx.h>
|
|
#include <nuttx/nx/nxglib.h>
|
|
#include <nuttx/lcd/lcd.h>
|
|
#include <nuttx/video/fb.h>
|
|
|
|
#ifdef CONFIG_LCD_FRAMEBUFFER
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
/* At present, only video plane 0 is supported */
|
|
|
|
#define VIDEO_PLANE 0
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
/* This structure describes the LCD frambuffer */
|
|
|
|
struct lcdfb_dev_s
|
|
{
|
|
struct fb_vtable_s vtable; /* Must be cast compatible with lcdfb_dev_s */
|
|
FAR struct lcdfb_dev_s *flink; /* Supports a singly linked list */
|
|
FAR struct lcd_dev_s *lcd; /* Contained LCD device */
|
|
FAR uint8_t *fbmem; /* Allocated framebuffer */
|
|
FAR struct lcd_planeinfo_s pinfo; /* LCD plane info */
|
|
size_t fblen; /* Size of the framebuffer in bytes */
|
|
fb_coord_t xres; /* Horizontal resolution in pixel columns */
|
|
fb_coord_t yres; /* Vertical resolution in pixel rows */
|
|
fb_coord_t stride; /* Width of a row in bytes */
|
|
uint8_t display; /* Display number */
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Function Prototypes
|
|
****************************************************************************/
|
|
|
|
/* Update the LCD when there is a change to the framebuffer */
|
|
|
|
static int lcdfb_update(FAR struct lcdfb_dev_s *priv,
|
|
FAR const struct nxgl_rect_s *rect);
|
|
|
|
/* Get information about the video controller configuration and the
|
|
* configuration of each color plane.
|
|
*/
|
|
|
|
static int lcdfb_getvideoinfo(FAR struct fb_vtable_s *vtable,
|
|
FAR struct fb_videoinfo_s *vinfo);
|
|
static int lcdfb_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno,
|
|
FAR struct fb_planeinfo_s *pinfo);
|
|
|
|
/* The following is provided only if the video hardware supports RGB color
|
|
* mapping
|
|
*/
|
|
|
|
#ifdef CONFIG_FB_CMAP
|
|
static int lcdfb_getcmap(FAR struct fb_vtable_s *vtable,
|
|
FAR struct fb_cmap_s *cmap);
|
|
static int lcdfb_putcmap(FAR struct fb_vtable_s *vtable,
|
|
FAR const struct fb_cmap_s *cmap);
|
|
#endif
|
|
|
|
/* The following is provided only if the video hardware supports a hardware
|
|
* cursor
|
|
*/
|
|
|
|
#ifdef CONFIG_FB_HWCURSOR
|
|
static int lcdfb_getcursor(FAR struct fb_vtable_s *vtable,
|
|
FAR struct fb_cursorattrib_s *attrib);
|
|
static int lcdfb_setcursor(FAR struct fb_vtable_s *vtable,
|
|
FAR struct fb_setcursor_s *settings);
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
/* This is a singly linked list that supports look-up of framebuffer state
|
|
* using the display number.
|
|
*/
|
|
|
|
static FAR struct lcdfb_dev_s *g_lcdfb;
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: lcdfb_find
|
|
*
|
|
* Description:
|
|
* Find the LCD framebuffer state associated with the display.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static FAR struct lcdfb_dev_s *lcdfb_find(int display)
|
|
{
|
|
FAR struct lcdfb_dev_s *priv;
|
|
|
|
/* Look up the LCD framebuffer state structure for this display.
|
|
*
|
|
* REVISIT: If many LCD framebuffers are used, then this lookup would be
|
|
* a performance issue.
|
|
* REVISIT: Semaphore protections is needed if there is concurrent access.
|
|
*/
|
|
|
|
for (priv = g_lcdfb; priv != NULL; priv = priv->flink)
|
|
{
|
|
if (priv->display == display)
|
|
{
|
|
return priv;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: lcdfb_update
|
|
*
|
|
* Description:
|
|
* Update the LCD when there is a change to the framebuffer.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int lcdfb_update(FAR struct lcdfb_dev_s *priv,
|
|
FAR const struct nxgl_rect_s *rect)
|
|
{
|
|
FAR struct lcd_planeinfo_s *pinfo = &priv->pinfo;
|
|
FAR uint8_t *run;
|
|
fb_coord_t row;
|
|
fb_coord_t startx;
|
|
fb_coord_t endx;
|
|
fb_coord_t width;
|
|
fb_coord_t starty;
|
|
fb_coord_t endy;
|
|
int ret;
|
|
|
|
/* Clip to fit in the framebuffer */
|
|
|
|
startx = rect->pt1.x;
|
|
if (startx < 0)
|
|
{
|
|
startx = 0;
|
|
}
|
|
|
|
endx = rect->pt2.x;
|
|
if (endx >= priv->xres)
|
|
{
|
|
endx = priv->xres-1;
|
|
}
|
|
|
|
starty = rect->pt1.y;
|
|
if (starty < 0)
|
|
{
|
|
starty = 0;
|
|
}
|
|
|
|
endy = rect->pt2.y;
|
|
if (endy >= priv->yres)
|
|
{
|
|
endy = priv->yres-1;
|
|
}
|
|
|
|
/* If the display uses a value of BPP < 8, then we may have to extend the
|
|
* rectangle on the left so that it is byte aligned. Works for BPP={1,2,4}
|
|
*/
|
|
|
|
if (pinfo->bpp < 8)
|
|
{
|
|
unsigned int pixperbyte = 8 / pinfo->bpp;
|
|
startx &= ~(pixperbyte - 1);
|
|
}
|
|
|
|
width = endx - startx + 1;
|
|
|
|
/* Get the starting position in the framebuffer */
|
|
|
|
run = priv->fbmem + starty * priv->stride;
|
|
run += (startx * pinfo->bpp + 7) >> 3;
|
|
|
|
for (row = starty; row <= endy; row++)
|
|
{
|
|
/* REVISIT: Some LCD hardware certain aligment requirements on DMA
|
|
* memory.
|
|
*/
|
|
|
|
ret = pinfo->putrun(row, startx, run, width);
|
|
if (ret < 0)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
run += priv->stride;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: lcdfb_getvideoinfo
|
|
****************************************************************************/
|
|
|
|
static int lcdfb_getvideoinfo(FAR struct fb_vtable_s *vtable,
|
|
FAR struct fb_videoinfo_s *vinfo)
|
|
{
|
|
FAR struct lcdfb_dev_s *priv;
|
|
FAR struct lcd_dev_s *lcd;
|
|
int ret = -EINVAL;
|
|
|
|
lcdinfo("vtable=%p vinfo=%p\n", vtable, vinfo);
|
|
|
|
DEBUGASSERT(vtable != NULL && vinfo != NULL);
|
|
priv = (FAR struct lcdfb_dev_s *)vtable;
|
|
|
|
if (priv != NULL && vinfo != NULL)
|
|
{
|
|
/* Get the video info from the contained LCD */
|
|
|
|
lcd = priv->lcd;
|
|
DEBUGASSERT(lcd->getvideoinfo != NULL);
|
|
ret = lcd->getvideoinfo(lcd, vinfo);
|
|
if (ret < 0)
|
|
{
|
|
lcderr("ERROR: LCD getvideoinfo() failed: %d\n", ret);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: lcdfb_getplaneinfo
|
|
****************************************************************************/
|
|
|
|
static int lcdfb_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno,
|
|
FAR struct fb_planeinfo_s *pinfo)
|
|
{
|
|
FAR struct lcdfb_dev_s *priv;
|
|
int ret = -EINVAL;
|
|
|
|
lcdinfo("vtable=%p planeno=%d pinfo=%p\n", vtable, planeno, pinfo);
|
|
|
|
DEBUGASSERT(vtable != NULL && planeno == VIDEO_PLANE && pinfo != NULL);
|
|
priv = (FAR struct lcdfb_dev_s *)vtable;
|
|
|
|
if (priv != NULL && planeno == VIDEO_PLANE && pinfo != NULL)
|
|
{
|
|
/* Return the plane info */
|
|
|
|
pinfo->fbmem = priv->fbmem;
|
|
pinfo->fblen = priv->fblen;
|
|
pinfo->stride = priv->stride;
|
|
pinfo->display = priv->display;
|
|
pinfo->bpp = priv->pinfo.bpp;
|
|
|
|
ret = OK;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: lcdfb_getcmap
|
|
****************************************************************************/
|
|
|
|
#ifdef CONFIG_FB_CMAP
|
|
static int lcdfb_getcmap(FAR struct fb_vtable_s *vtable,
|
|
FAR struct fb_cmap_s *cmap)
|
|
{
|
|
FAR struct lcdfb_dev_s *priv;
|
|
FAR struct lcd_dev_s *lcd;
|
|
int ret = -EINVAL;
|
|
|
|
lcdinfo("vtable=%p cmap=%p\n", vtable, cmap);
|
|
|
|
DEBUGASSERT(vtable != NULL && cmap != NULL);
|
|
priv = (FAR struct lcdfb_dev_s *)vtable;
|
|
|
|
if (priv != NULL && cmap != NULL)
|
|
{
|
|
/* Get the video info from the contained LCD */
|
|
|
|
lcd = priv->lcd
|
|
DEBUGASSERT(lcd->getcmap != NULL);
|
|
ret = lcd->getcmap(lcd, cmap);
|
|
if (ret < 0)
|
|
{
|
|
lcderr("ERROR: LCD getcmap() failed: %d\n", ret);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Name: lcdfb_putcmap
|
|
****************************************************************************/
|
|
|
|
#ifdef CONFIG_FB_CMAP
|
|
static int lcdfb_putcmap(FAR struct fb_vtable_s *vtable,
|
|
FAR const struct fb_cmap_s *cmap)
|
|
{
|
|
FAR struct lcdfb_dev_s *priv;
|
|
FAR struct lcd_dev_s *lcd;
|
|
int ret = -EINVAL;
|
|
|
|
lcdinfo("vtable=%p cmap=%p\n", vtable, cmap);
|
|
|
|
DEBUGASSERT(vtable != NULL && cmap != NULL);
|
|
priv = (FAR struct lcdfb_dev_s *)vtable;
|
|
|
|
if (priv != NULL && cmap != NULL)
|
|
{
|
|
/* Get the video info from the contained LCD */
|
|
|
|
lcd = priv->lcd
|
|
DEBUGASSERT(lcd->putcmap != NULL);
|
|
ret = lcd->putcmap(lcd, cmap);
|
|
if (ret < 0)
|
|
{
|
|
lcderr("ERROR: LCD putcmap() failed: %d\n", ret);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Name: lcdfb_getcursor
|
|
****************************************************************************/
|
|
|
|
#ifdef CONFIG_FB_HWCURSOR
|
|
static int lcdfb_getcursor(FAR struct fb_vtable_s *vtable,
|
|
FAR struct fb_cursorattrib_s *attrib)
|
|
{
|
|
lcdinfo("vtable=%p attrib=%p\n", vtable, attrib);
|
|
FAR struct lcdfb_dev_s *priv;
|
|
FAR struct lcd_dev_s *lcd;
|
|
int ret = -EINVAL;
|
|
|
|
lcdinfo("vtable=%p attrib=%p\n", vtable, attrib);
|
|
|
|
DEBUGASSERT(vtable != NULL && attrib != NULL);
|
|
priv = (FAR struct lcdfb_dev_s *)vtable;
|
|
|
|
if (priv != NULL && attrib != NULL)
|
|
{
|
|
/* Get the video info from the contained LCD */
|
|
|
|
lcd = priv->lcd
|
|
DEBUGASSERT(lcd->getcursor != NULL);
|
|
ret = lcd->getcursor(lcd, attrib);
|
|
if (ret < 0)
|
|
{
|
|
lcderr("ERROR: LCD getcursor() failed: %d\n", ret);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Name: lcdfb_setcursor
|
|
****************************************************************************/
|
|
|
|
#ifdef CONFIG_FB_HWCURSOR
|
|
static int lcdfb_setcursor(FAR struct fb_vtable_s *vtable,
|
|
FAR struct fb_setcursor_s *settings)
|
|
{
|
|
FAR struct lcdfb_dev_s *priv;
|
|
FAR struct lcd_dev_s *lcd;
|
|
int ret = -EINVAL;
|
|
|
|
lcdinfo("vtable=%p settings=%p\n", vtable, settings);
|
|
|
|
DEBUGASSERT(vtable != NULL && settings != NULL);
|
|
priv = (FAR struct lcdfb_dev_s *)vtable;
|
|
|
|
if (priv != NULL && settings != NULL)
|
|
{
|
|
/* Get the video info from the contained LCD */
|
|
|
|
lcd = priv->lcd
|
|
DEBUGASSERT(lcd->setcursor != NULL);
|
|
ret = lcd->setcursor(lcd, settings);
|
|
if (ret < 0)
|
|
{
|
|
lcderr("ERROR: LCD setcursor() failed: %d\n", ret);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: up_fbinitialize
|
|
*
|
|
* Description:
|
|
* Initialize the framebuffer video hardware associated with the display.
|
|
*
|
|
* Input Parameters:
|
|
* display - In the case of hardware with multiple displays, this
|
|
* specifies the display. Normally this is zero.
|
|
*
|
|
* Returned Value:
|
|
* Zero is returned on success; a negated errno value is returned on any
|
|
* failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int up_fbinitialize(int display)
|
|
{
|
|
FAR struct lcdfb_dev_s *priv;
|
|
FAR struct lcd_dev_s *lcd;
|
|
struct fb_videoinfo_s vinfo;
|
|
struct nxgl_rect_s rect;
|
|
int ret;
|
|
|
|
lcdinfo("display=%d\n", display);
|
|
DEBUGASSERT((unsigned)display < UINT8_MAX);
|
|
|
|
/* Allocate the framebuffer state structure */
|
|
|
|
priv = (FAR struct lcdfb_dev_s *)kmm_zalloc(sizeof(struct lcdfb_dev_s));
|
|
if (priv == NULL)
|
|
{
|
|
lcderr("ERROR: Failed to allocate state structure\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Initialize the LCD-independent fields of the state structure */
|
|
|
|
priv->display = display;
|
|
|
|
priv->vtable.getvideoinfo = lcdfb_getvideoinfo,
|
|
priv->vtable.getplaneinfo = lcdfb_getplaneinfo,
|
|
#ifdef CONFIG_FB_CMAP
|
|
priv->vtable.getcmap = lcdfb_getcmap,
|
|
priv->vtable.putcmap = lcdfb_putcmap,
|
|
#endif
|
|
#ifdef CONFIG_FB_HWCURSOR
|
|
priv->vtable.getcursor = lcdfb_getcursor,
|
|
priv->vtable.setcursor = lcdfb_setcursor,
|
|
#endif
|
|
|
|
#ifdef CONFIG_LCD_EXTERNINIT
|
|
/* Use external graphics driver initialization */
|
|
|
|
lcd = board_graphics_setup(display);
|
|
if (lcd == NULL)
|
|
{
|
|
gerr("ERROR: board_graphics_setup failed, devno=%d\n", display);
|
|
return EXIT_FAILURE;
|
|
}
|
|
#else
|
|
/* Initialize the LCD device */
|
|
|
|
ret = board_lcd_initialize();
|
|
if (ret < 0)
|
|
{
|
|
lcderr("ERROR: board_lcd_initialize() failed: %d\n", ret);
|
|
goto errout_with_state;
|
|
}
|
|
|
|
/* Get the device instance */
|
|
|
|
lcd = board_lcd_getdev(display);
|
|
if (lcd == NULL)
|
|
{
|
|
lcderr("ERROR: board_lcd_getdev failed, devno=%d\n", display);
|
|
ret = -ENODEV;
|
|
goto errout_with_lcd;
|
|
}
|
|
#endif
|
|
|
|
priv->lcd = lcd;
|
|
|
|
/* Initialize the LCD-dependent fields of the state structure */
|
|
|
|
DEBUGASSERT(lcd->getvideoinfo != NULL);
|
|
ret = lcd->getvideoinfo(lcd, &vinfo);
|
|
if (ret < 0)
|
|
{
|
|
lcderr("ERROR: LCD getvideoinfo() failed: %d\n", ret);
|
|
goto errout_with_lcd;
|
|
}
|
|
|
|
priv->xres = vinfo.xres;
|
|
priv->yres = vinfo.yres;
|
|
|
|
DEBUGASSERT(lcd->getplaneinfo != NULL);
|
|
ret = lcd->getplaneinfo(lcd, VIDEO_PLANE, &priv->pinfo);
|
|
if (ret < 0)
|
|
{
|
|
lcderr("ERROR: LCD getplaneinfo() failed: %d\n", ret);
|
|
goto errout_with_lcd;
|
|
}
|
|
|
|
/* Allocate (and clear) the framebuffer */
|
|
|
|
priv->stride = ((size_t)priv->xres * priv->pinfo.bpp + 7) >> 3;
|
|
priv->fblen = priv->stride * priv->yres;
|
|
|
|
priv->fbmem = (FAR uint8_t *)kmm_zalloc(priv->fblen);
|
|
if (priv->fbmem == NULL)
|
|
{
|
|
lcderr("ERROR: Failed to allocate frame buffer memory\n");
|
|
ret = -ENOMEM;
|
|
goto errout_with_lcd;
|
|
}
|
|
|
|
/* Add the state structure to the list of framebuffer interfaces */
|
|
|
|
priv->flink = g_lcdfb;
|
|
g_lcdfb = priv;
|
|
|
|
/* Write the entire framebuffer to the LCD */
|
|
|
|
rect.pt1.x = 0;
|
|
rect.pt1.y = 0;
|
|
rect.pt2.x = priv->xres - 1;
|
|
rect.pt2.y = priv->yres - 1;
|
|
|
|
ret = lcdfb_update(priv, &rect);
|
|
if (ret < 0)
|
|
{
|
|
lcderr("FB update failed: %d\n", ret);
|
|
}
|
|
|
|
/* Turn the LCD on at 75% power */
|
|
|
|
priv->lcd->setpower(priv->lcd, ((3*CONFIG_LCD_MAXPOWER + 3)/4));
|
|
return OK;
|
|
|
|
errout_with_lcd:
|
|
#ifndef CONFIG_LCD_EXTERNINIT
|
|
board_lcd_uninitialize();
|
|
|
|
errout_with_state:
|
|
#endif
|
|
kmm_free(priv);
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: up_fbgetvplane
|
|
*
|
|
* Description:
|
|
* Return a a reference to the framebuffer object for the specified video
|
|
* plane of the specified plane. Many OSDs support multiple planes of video.
|
|
*
|
|
* Input Parameters:
|
|
* display - In the case of hardware with multiple displays, this
|
|
* specifies the display. Normally this is zero.
|
|
* vplane - Identifies the plane being queried.
|
|
*
|
|
* Returned Value:
|
|
* A non-NULL pointer to the frame buffer access structure is returned on
|
|
* success; NULL is returned on any failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane)
|
|
{
|
|
FAR struct lcdfb_dev_s *priv;
|
|
|
|
lcdinfo("display=%d vplane=%d\n", display, vplane);
|
|
DEBUGASSERT(vplane == VIDEO_PLANE);
|
|
|
|
/* Look up the LCD framebuffer state structure for this display. */
|
|
|
|
priv = lcdfb_find(display);
|
|
if (priv == NULL)
|
|
{
|
|
lcderr("ERROR: lcd_find(%d) failed\n", display);
|
|
return NULL;
|
|
}
|
|
|
|
return &priv->vtable;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: up_fbuninitialize
|
|
*
|
|
* Description:
|
|
* Uninitialize the framebuffer support for the specified display.
|
|
*
|
|
* Input Parameters:
|
|
* display - In the case of hardware with multiple displays, this
|
|
* specifies the display. Normally this is zero.
|
|
*
|
|
* Returned Value:
|
|
* None
|
|
*
|
|
****************************************************************************/
|
|
|
|
void up_fbuninitialize(int display)
|
|
{
|
|
FAR struct lcdfb_dev_s *priv;
|
|
FAR struct lcdfb_dev_s *prev;
|
|
|
|
/* Find the LCD framebuffer state associated with this display.
|
|
* REVISIT: Semaphore protections is needed if there is concurrent access.
|
|
*/
|
|
|
|
for (prev = NULL, priv = g_lcdfb;
|
|
priv != NULL;
|
|
prev = priv, priv = priv->flink)
|
|
{
|
|
if (priv->display == display)
|
|
{
|
|
/* Remove the state structure from the list */
|
|
|
|
if (prev != NULL)
|
|
{
|
|
prev->flink = priv->flink;
|
|
}
|
|
else
|
|
{
|
|
g_lcdfb = priv->flink;
|
|
}
|
|
|
|
#ifndef CONFIG_LCD_EXTERNINIT
|
|
/* Uninitialize the LCD */
|
|
|
|
board_lcd_uninitialize();
|
|
#endif
|
|
|
|
/* Free the frame buffer allocation */
|
|
|
|
kmm_free(priv->fbmem);
|
|
|
|
/* Free the state structure allocation */
|
|
|
|
kmm_free(priv);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: nx_notify_rectangle
|
|
*
|
|
* Description:
|
|
* When CONFIG_LCD_UPDATE=y, then the graphics system will callout to
|
|
* inform some external module that the display has been updated. This
|
|
* would be useful in a couple for cases.
|
|
*
|
|
* - When a serial LCD is used, but a framebuffer is used to access the
|
|
* LCD. In this case, the update callout can be used to refresh the
|
|
* affected region of the display.
|
|
*
|
|
* - When VNC is enabled. This is case, this callout is necessary to
|
|
* update the remote frame buffer to match the local framebuffer.
|
|
*
|
|
* When this feature is enabled, some external logic must provide this
|
|
* interface. This is the function that will handle the notification. It
|
|
* receives the rectangular region that was updated on the provided plane.
|
|
*
|
|
* NOTE: This function is also required for use with the LCD framebuffer
|
|
* driver front end when CONFIG_LCD_UPDATE=y, although that use does not
|
|
* depend on CONFIG_NX (and this function seems misnamed in that case).
|
|
*
|
|
****************************************************************************/
|
|
|
|
#if defined(CONFIG_LCD_UPDATE) || defined(CONFIG_NX_UPDATE)
|
|
void nx_notify_rectangle(FAR NX_PLANEINFOTYPE *pinfo,
|
|
FAR const struct nxgl_rect_s *rect)
|
|
{
|
|
FAR struct fb_planeinfo_s *fpinfo = (FAR struct fb_planeinfo_s *)pinfo;
|
|
FAR struct lcdfb_dev_s *priv;
|
|
int ret;
|
|
|
|
DEBUGASSERT(fpinfo != NULL && rect != NULL);
|
|
|
|
/* Look up the LCD framebuffer state structure for this display.
|
|
*
|
|
* REVISIT: If many LCD framebuffers are used, then this lookup would be
|
|
* a performance issue.
|
|
*/
|
|
|
|
priv = lcdfb_find(fpinfo->display);
|
|
if (priv != NULL)
|
|
{
|
|
ret = lcdfb_update(priv, rect);
|
|
if (ret < 0)
|
|
{
|
|
lcderr("FB update failed: %d\n", ret);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#endif /* CONFIG_LCD_FRAMEBUFFER */
|