1d6aed566Sopenharmony_ci/**************************************************************************** 2d6aed566Sopenharmony_ci * video/fb.c 3d6aed566Sopenharmony_ci * Framebuffer character driver 4d6aed566Sopenharmony_ci * 5d6aed566Sopenharmony_ci * Copyright (C) 2017 Gregory Nutt. All rights reserved. 6d6aed566Sopenharmony_ci * Author: Gregory Nutt <gnutt@nuttx.org> 7d6aed566Sopenharmony_ci * 8d6aed566Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 9d6aed566Sopenharmony_ci * modification, are permitted provided that the following conditions 10d6aed566Sopenharmony_ci * are met: 11d6aed566Sopenharmony_ci * 12d6aed566Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 13d6aed566Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 14d6aed566Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 15d6aed566Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 16d6aed566Sopenharmony_ci * the documentation and/or other materials provided with the 17d6aed566Sopenharmony_ci * distribution. 18d6aed566Sopenharmony_ci * 3. Neither the name NuttX nor the names of its contributors may be 19d6aed566Sopenharmony_ci * used to endorse or promote products derived from this software 20d6aed566Sopenharmony_ci * without specific prior written permission. 21d6aed566Sopenharmony_ci * 22d6aed566Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23d6aed566Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24d6aed566Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25d6aed566Sopenharmony_ci * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26d6aed566Sopenharmony_ci * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27d6aed566Sopenharmony_ci * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28d6aed566Sopenharmony_ci * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 29d6aed566Sopenharmony_ci * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30d6aed566Sopenharmony_ci * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31d6aed566Sopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32d6aed566Sopenharmony_ci * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33d6aed566Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGE. 34d6aed566Sopenharmony_ci * 35d6aed566Sopenharmony_ci ****************************************************************************/ 36d6aed566Sopenharmony_ci 37d6aed566Sopenharmony_ci/**************************************************************************** 38d6aed566Sopenharmony_ci * Included Files 39d6aed566Sopenharmony_ci ****************************************************************************/ 40d6aed566Sopenharmony_ci 41d6aed566Sopenharmony_ci#include "fb.h" 42d6aed566Sopenharmony_ci 43d6aed566Sopenharmony_ci#include "errno.h" 44d6aed566Sopenharmony_ci#include "string.h" 45d6aed566Sopenharmony_ci 46d6aed566Sopenharmony_ci#define gerr PRINT_ERR 47d6aed566Sopenharmony_ci#define DEBUGASSERT LOS_ASSERT 48d6aed566Sopenharmony_ci 49d6aed566Sopenharmony_ci/**************************************************************************** 50d6aed566Sopenharmony_ci * Private Types 51d6aed566Sopenharmony_ci ****************************************************************************/ 52d6aed566Sopenharmony_ci 53d6aed566Sopenharmony_ci/* This structure defines one framebuffer device. Note that which is 54d6aed566Sopenharmony_ci * everything in this structure is constant data set up and initialization 55d6aed566Sopenharmony_ci * time. Therefore, no there is requirement for serialized access to this 56d6aed566Sopenharmony_ci * structure. 57d6aed566Sopenharmony_ci */ 58d6aed566Sopenharmony_ci 59d6aed566Sopenharmony_cistruct fb_chardev_s { 60d6aed566Sopenharmony_ci struct fb_vtable_s *vtable; /* Framebuffer interface */ 61d6aed566Sopenharmony_ci void *fbmem; /* Start of frame buffer memory */ 62d6aed566Sopenharmony_ci size_t fblen; /* Size of the framebuffer */ 63d6aed566Sopenharmony_ci uint8_t plane; /* Video plan number */ 64d6aed566Sopenharmony_ci uint8_t bpp; /* Bits per pixel */ 65d6aed566Sopenharmony_ci}; 66d6aed566Sopenharmony_ci 67d6aed566Sopenharmony_ci#define FB_DEV_MAXNUM 32 68d6aed566Sopenharmony_cistatic struct fb_chardev_s *g_fb_dev[FB_DEV_MAXNUM] = {NULL}; 69d6aed566Sopenharmony_ci 70d6aed566Sopenharmony_ci/**************************************************************************** 71d6aed566Sopenharmony_ci * Public Functions 72d6aed566Sopenharmony_ci ****************************************************************************/ 73d6aed566Sopenharmony_ciint fb_open(const char *key, struct fb_mem **result) 74d6aed566Sopenharmony_ci{ 75d6aed566Sopenharmony_ci struct fb_mem *fbmem = NULL; 76d6aed566Sopenharmony_ci struct fb_chardev_s *fb; 77d6aed566Sopenharmony_ci struct fb_vtable_s *vtable; 78d6aed566Sopenharmony_ci int ret = -EINVAL; 79d6aed566Sopenharmony_ci 80d6aed566Sopenharmony_ci if (key == NULL || strlen(key) >= PATH_MAX) { 81d6aed566Sopenharmony_ci return -EINVAL; 82d6aed566Sopenharmony_ci } 83d6aed566Sopenharmony_ci FbMemHold(); 84d6aed566Sopenharmony_ci ret = FbMemLookup(key, &fbmem, 0); 85d6aed566Sopenharmony_ci FbMemDrop(); 86d6aed566Sopenharmony_ci if (ret == 0) { 87d6aed566Sopenharmony_ci fb = (struct fb_chardev_s *)fbmem->data; 88d6aed566Sopenharmony_ci if (fb == NULL) { 89d6aed566Sopenharmony_ci return -ENODEV; 90d6aed566Sopenharmony_ci } 91d6aed566Sopenharmony_ci 92d6aed566Sopenharmony_ci vtable = fb->vtable; 93d6aed566Sopenharmony_ci if (vtable == NULL) { 94d6aed566Sopenharmony_ci return -EINVAL; 95d6aed566Sopenharmony_ci } 96d6aed566Sopenharmony_ci 97d6aed566Sopenharmony_ci if (vtable->fb_open) { 98d6aed566Sopenharmony_ci ret = vtable->fb_open(vtable); 99d6aed566Sopenharmony_ci if (ret == 0) { 100d6aed566Sopenharmony_ci *result = fbmem; 101d6aed566Sopenharmony_ci } 102d6aed566Sopenharmony_ci } 103d6aed566Sopenharmony_ci } 104d6aed566Sopenharmony_ci return ret; 105d6aed566Sopenharmony_ci} 106d6aed566Sopenharmony_ci 107d6aed566Sopenharmony_ciint fb_close(struct fb_mem *fbmem) 108d6aed566Sopenharmony_ci{ 109d6aed566Sopenharmony_ci struct fb_chardev_s *fb; 110d6aed566Sopenharmony_ci struct fb_vtable_s *vtable; 111d6aed566Sopenharmony_ci int ret = -EINVAL; 112d6aed566Sopenharmony_ci 113d6aed566Sopenharmony_ci fb = (struct fb_chardev_s *)fbmem->data; 114d6aed566Sopenharmony_ci if (fb == NULL) { 115d6aed566Sopenharmony_ci return -ENODEV; 116d6aed566Sopenharmony_ci } 117d6aed566Sopenharmony_ci 118d6aed566Sopenharmony_ci vtable = fb->vtable; 119d6aed566Sopenharmony_ci if (vtable == NULL) { 120d6aed566Sopenharmony_ci return -EINVAL; 121d6aed566Sopenharmony_ci } 122d6aed566Sopenharmony_ci 123d6aed566Sopenharmony_ci if (vtable->fb_release) { 124d6aed566Sopenharmony_ci ret = vtable->fb_release(vtable); 125d6aed566Sopenharmony_ci } 126d6aed566Sopenharmony_ci return ret; 127d6aed566Sopenharmony_ci} 128d6aed566Sopenharmony_ci 129d6aed566Sopenharmony_ciint fb_ioctl(struct fb_mem *fbMem, int cmd, unsigned long arg) 130d6aed566Sopenharmony_ci{ 131d6aed566Sopenharmony_ci struct fb_chardev_s *fb = NULL; 132d6aed566Sopenharmony_ci int ret; 133d6aed566Sopenharmony_ci 134d6aed566Sopenharmony_ci /* Get the framebuffer instance */ 135d6aed566Sopenharmony_ci fb = (struct fb_chardev_s *)fbMem->data; 136d6aed566Sopenharmony_ci /* Process the IOCTL command */ 137d6aed566Sopenharmony_ci 138d6aed566Sopenharmony_ci switch (cmd) { 139d6aed566Sopenharmony_ci case FIOC_MMAP: 140d6aed566Sopenharmony_ci { /* Get color plane info */ 141d6aed566Sopenharmony_ci void **ppv = (void **)((uintptr_t)arg); 142d6aed566Sopenharmony_ci /* Return the address corresponding to the start of frame buffer. */ 143d6aed566Sopenharmony_ci DEBUGASSERT(ppv != NULL); 144d6aed566Sopenharmony_ci *ppv = fb->fbmem; 145d6aed566Sopenharmony_ci ret = OK; 146d6aed566Sopenharmony_ci } 147d6aed566Sopenharmony_ci break; 148d6aed566Sopenharmony_ci 149d6aed566Sopenharmony_ci case FBIOGET_VIDEOINFO: 150d6aed566Sopenharmony_ci { /* Get color plane info */ 151d6aed566Sopenharmony_ci struct fb_videoinfo_s *vinfo = (struct fb_videoinfo_s *)((uintptr_t)arg); 152d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->getvideoinfo != NULL); 153d6aed566Sopenharmony_ci ret = fb->vtable->getvideoinfo(fb->vtable, &vinfo); 154d6aed566Sopenharmony_ci } 155d6aed566Sopenharmony_ci break; 156d6aed566Sopenharmony_ci 157d6aed566Sopenharmony_ci case FBIOGET_PLANEINFO: 158d6aed566Sopenharmony_ci { /* Get video plane info */ 159d6aed566Sopenharmony_ci struct fb_planeinfo_s *pinfo = (struct fb_planeinfo_s *)((uintptr_t)arg); 160d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->getplaneinfo != NULL); 161d6aed566Sopenharmony_ci ret = fb->vtable->getplaneinfo(fb->vtable, fb->plane, &pinfo); 162d6aed566Sopenharmony_ci } 163d6aed566Sopenharmony_ci break; 164d6aed566Sopenharmony_ci 165d6aed566Sopenharmony_ci#ifdef CONFIG_FB_CMAP 166d6aed566Sopenharmony_ci case FBIOGET_CMAP: 167d6aed566Sopenharmony_ci { /* Get RGB color mapping */ 168d6aed566Sopenharmony_ci struct fb_cmap_s *cmap = (struct fb_cmap_s *)((uintptr_t)arg); 169d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->getcmap != NULL); 170d6aed566Sopenharmony_ci ret = fb->vtable->getcmap(fb->vtable, &cmap); 171d6aed566Sopenharmony_ci } 172d6aed566Sopenharmony_ci break; 173d6aed566Sopenharmony_ci 174d6aed566Sopenharmony_ci case FBIOPUT_CMAP: 175d6aed566Sopenharmony_ci { /* Put RGB color mapping */ 176d6aed566Sopenharmony_ci struct fb_cmap_s *cmap = (struct fb_cmap_s *)((uintptr_t)arg); 177d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->putcmap != NULL); 178d6aed566Sopenharmony_ci ret = fb->vtable->putcmap(fb->vtable, &cmap); 179d6aed566Sopenharmony_ci } 180d6aed566Sopenharmony_ci break; 181d6aed566Sopenharmony_ci#endif 182d6aed566Sopenharmony_ci#ifdef CONFIG_FB_HWCURSOR 183d6aed566Sopenharmony_ci case FBIOGET_CURSOR: 184d6aed566Sopenharmony_ci { /* Get cursor attributes */ 185d6aed566Sopenharmony_ci struct fb_cursorattrib_s *attrib = (struct fb_cursorattrib_s *)((uintptr_t)arg); 186d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->getcursor != NULL); 187d6aed566Sopenharmony_ci ret = fb->vtable->getcursor(fb->vtable, &attrib); 188d6aed566Sopenharmony_ci } 189d6aed566Sopenharmony_ci break; 190d6aed566Sopenharmony_ci 191d6aed566Sopenharmony_ci case FBIOPUT_CURSOR: 192d6aed566Sopenharmony_ci { /* Set cursor attributes */ 193d6aed566Sopenharmony_ci struct fb_setcursor_s *cursor = (struct fb_setcursor_s *)((uintptr_t)arg); 194d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->setcursor != NULL); 195d6aed566Sopenharmony_ci ret = fb->vtable->setcursor(fb->vtable, &cursor); 196d6aed566Sopenharmony_ci } 197d6aed566Sopenharmony_ci break; 198d6aed566Sopenharmony_ci#endif 199d6aed566Sopenharmony_ci 200d6aed566Sopenharmony_ci#ifdef CONFIG_FB_UPDATE 201d6aed566Sopenharmony_ci case FBIO_UPDATE: 202d6aed566Sopenharmony_ci { /* Update the modified framebuffer data */ 203d6aed566Sopenharmony_ci struct fb_area_s *area = (struct fb_area_s *)((uintptr_t)arg); 204d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->updatearea != NULL); 205d6aed566Sopenharmony_ci ret = fb->vtable->updatearea(fb->vtable, area); 206d6aed566Sopenharmony_ci } 207d6aed566Sopenharmony_ci break; 208d6aed566Sopenharmony_ci#endif 209d6aed566Sopenharmony_ci 210d6aed566Sopenharmony_ci#ifdef CONFIG_FB_SYNC 211d6aed566Sopenharmony_ci case FBIO_WAITFORVSYNC: 212d6aed566Sopenharmony_ci { /* Wait upon vertical sync */ 213d6aed566Sopenharmony_ci ret = fb->vtable->waitforvsync(fb->vtable); 214d6aed566Sopenharmony_ci } 215d6aed566Sopenharmony_ci break; 216d6aed566Sopenharmony_ci#endif 217d6aed566Sopenharmony_ci 218d6aed566Sopenharmony_ci#ifdef CONFIG_FB_OVERLAY 219d6aed566Sopenharmony_ci case FBIO_SELECT_OVERLAY: 220d6aed566Sopenharmony_ci { /* Select video overlay */ 221d6aed566Sopenharmony_ci struct fb_overlayinfo_s oinfo; 222d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->getoverlayinfo != NULL); 223d6aed566Sopenharmony_ci ret = fb->vtable->getoverlayinfo(fb->vtable, arg, &oinfo); 224d6aed566Sopenharmony_ci if (ret == OK) { 225d6aed566Sopenharmony_ci fb->fbmem = oinfo.fbmem; 226d6aed566Sopenharmony_ci fb->fblen = oinfo.fblen; 227d6aed566Sopenharmony_ci fb->bpp = oinfo.bpp; 228d6aed566Sopenharmony_ci } 229d6aed566Sopenharmony_ci } 230d6aed566Sopenharmony_ci break; 231d6aed566Sopenharmony_ci 232d6aed566Sopenharmony_ci case FBIOGET_OVERLAYINFO: 233d6aed566Sopenharmony_ci { /* Get video overlay info */ 234d6aed566Sopenharmony_ci struct fb_overlayinfo_s *oinfo = (struct fb_overlayinfo_s *)((uintptr_t)arg); 235d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->getoverlayinfo != NULL); 236d6aed566Sopenharmony_ci ret = fb->vtable->getoverlayinfo(fb->vtable, oinfo->overlay, &oinfo); 237d6aed566Sopenharmony_ci } 238d6aed566Sopenharmony_ci break; 239d6aed566Sopenharmony_ci 240d6aed566Sopenharmony_ci case FBIOSET_TRANSP: 241d6aed566Sopenharmony_ci { /* Set video overlay transparency */ 242d6aed566Sopenharmony_ci struct fb_overlayinfo_s *oinfo = (struct fb_overlayinfo_s *)((uintptr_t)arg); 243d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->settransp != NULL); 244d6aed566Sopenharmony_ci ret = fb->vtable->settransp(fb->vtable, &oinfo); 245d6aed566Sopenharmony_ci } 246d6aed566Sopenharmony_ci break; 247d6aed566Sopenharmony_ci 248d6aed566Sopenharmony_ci case FBIOSET_CHROMAKEY: 249d6aed566Sopenharmony_ci { /* Set video overlay chroma key */ 250d6aed566Sopenharmony_ci struct fb_overlayinfo_s *oinfo = (struct fb_overlayinfo_s *)((uintptr_t)arg); 251d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->setchromakey != NULL); 252d6aed566Sopenharmony_ci ret = fb->vtable->setchromakey(fb->vtable, &oinfo); 253d6aed566Sopenharmony_ci } 254d6aed566Sopenharmony_ci break; 255d6aed566Sopenharmony_ci 256d6aed566Sopenharmony_ci case FBIOSET_COLOR: 257d6aed566Sopenharmony_ci { /* Set video overlay color */ 258d6aed566Sopenharmony_ci struct fb_overlayinfo_s *oinfo = (struct fb_overlayinfo_s *)((uintptr_t)arg); 259d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->setcolor != NULL); 260d6aed566Sopenharmony_ci ret = fb->vtable->setcolor(fb->vtable, &oinfo); 261d6aed566Sopenharmony_ci } 262d6aed566Sopenharmony_ci break; 263d6aed566Sopenharmony_ci 264d6aed566Sopenharmony_ci case FBIOSET_BLANK: 265d6aed566Sopenharmony_ci { /* Blank or unblank video overlay */ 266d6aed566Sopenharmony_ci struct fb_overlayinfo_s *oinfo = (struct fb_overlayinfo_s *)((uintptr_t)arg); 267d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->setblank != NULL); 268d6aed566Sopenharmony_ci ret = fb->vtable->setblank(fb->vtable, &oinfo); 269d6aed566Sopenharmony_ci } 270d6aed566Sopenharmony_ci break; 271d6aed566Sopenharmony_ci 272d6aed566Sopenharmony_ci case FBIOSET_AREA: 273d6aed566Sopenharmony_ci { /* Set active video overlay area */ 274d6aed566Sopenharmony_ci struct fb_overlayinfo_s *oinfo = (struct fb_overlayinfo_s *)((uintptr_t)arg); 275d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->setarea != NULL); 276d6aed566Sopenharmony_ci ret = fb->vtable->setarea(fb->vtable, &oinfo); 277d6aed566Sopenharmony_ci } 278d6aed566Sopenharmony_ci break; 279d6aed566Sopenharmony_ci 280d6aed566Sopenharmony_ci#ifdef CONFIG_FB_OVERLAY_BLIT 281d6aed566Sopenharmony_ci case FBIOSET_BLIT: 282d6aed566Sopenharmony_ci { /* Blit operation between video overlays */ 283d6aed566Sopenharmony_ci struct fb_overlayblit_s *blit = (struct fb_overlayblit_s *)((uintptr_t)arg); 284d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->blit != NULL); 285d6aed566Sopenharmony_ci ret = fb->vtable->blit(fb->vtable, &blit); 286d6aed566Sopenharmony_ci } 287d6aed566Sopenharmony_ci break; 288d6aed566Sopenharmony_ci 289d6aed566Sopenharmony_ci case FBIOSET_BLEND: 290d6aed566Sopenharmony_ci { /* Blend operation between video overlays */ 291d6aed566Sopenharmony_ci struct fb_overlayblend_s *blend = (struct fb_overlayblend_s *)((uintptr_t)arg); 292d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->blend != NULL); 293d6aed566Sopenharmony_ci ret = fb->vtable->blend(fb->vtable, &blend); 294d6aed566Sopenharmony_ci } 295d6aed566Sopenharmony_ci break; 296d6aed566Sopenharmony_ci#endif 297d6aed566Sopenharmony_ci#endif /* CONFIG_FB_OVERLAY */ 298d6aed566Sopenharmony_ci 299d6aed566Sopenharmony_ci default: 300d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable != NULL && fb->vtable->fb_ioctl != NULL); 301d6aed566Sopenharmony_ci ret = fb->vtable->fb_ioctl(fb->vtable, cmd, arg); 302d6aed566Sopenharmony_ci break; 303d6aed566Sopenharmony_ci } 304d6aed566Sopenharmony_ci 305d6aed566Sopenharmony_ci return ret; 306d6aed566Sopenharmony_ci} 307d6aed566Sopenharmony_ci 308d6aed566Sopenharmony_ciint getplaneinfo(struct fb_mem *fbmem, struct fb_planeinfo_s **result) 309d6aed566Sopenharmony_ci{ 310d6aed566Sopenharmony_ci int ret; 311d6aed566Sopenharmony_ci struct fb_chardev_s *fb; 312d6aed566Sopenharmony_ci 313d6aed566Sopenharmony_ci fb = (struct fb_chardev_s *)fbmem->data; 314d6aed566Sopenharmony_ci 315d6aed566Sopenharmony_ci struct fb_planeinfo_s pinfo; 316d6aed566Sopenharmony_ci 317d6aed566Sopenharmony_ci ret = fb->vtable->getplaneinfo(fb->vtable, fb->plane, &pinfo); 318d6aed566Sopenharmony_ci if (ret == 0) { 319d6aed566Sopenharmony_ci *result = &pinfo; 320d6aed566Sopenharmony_ci } 321d6aed566Sopenharmony_ci 322d6aed566Sopenharmony_ci return 0; 323d6aed566Sopenharmony_ci} 324d6aed566Sopenharmony_ci 325d6aed566Sopenharmony_ci/**************************************************************************** 326d6aed566Sopenharmony_ci * Name: fb_register 327d6aed566Sopenharmony_ci * 328d6aed566Sopenharmony_ci * Description: 329d6aed566Sopenharmony_ci * Register the framebuffer character device at /dev/fbN where N is the 330d6aed566Sopenharmony_ci * display number if the devices supports only a single plane. If the 331d6aed566Sopenharmony_ci * hardware supports multiple color planes, then the device will be 332d6aed566Sopenharmony_ci * registered at /dev/fbN.M where N is the again display number but M 333d6aed566Sopenharmony_ci * is the display plane. 334d6aed566Sopenharmony_ci * 335d6aed566Sopenharmony_ci * Input Parameters: 336d6aed566Sopenharmony_ci * display - The display number for the case of boards supporting multiple 337d6aed566Sopenharmony_ci * displays or for hardware that supports multiple 338d6aed566Sopenharmony_ci * layers (each layer is consider a display). Typically zero. 339d6aed566Sopenharmony_ci * plane - Identifies the color plane on hardware that supports separate 340d6aed566Sopenharmony_ci * framebuffer "planes" for each color component. 341d6aed566Sopenharmony_ci * 342d6aed566Sopenharmony_ci * Returned Value: 343d6aed566Sopenharmony_ci * Zero (OK) is returned success; a negated errno value is returned on any 344d6aed566Sopenharmony_ci * failure. 345d6aed566Sopenharmony_ci * 346d6aed566Sopenharmony_ci ****************************************************************************/ 347d6aed566Sopenharmony_ci 348d6aed566Sopenharmony_ciint fb_register(int display, int plane) 349d6aed566Sopenharmony_ci{ 350d6aed566Sopenharmony_ci struct fb_chardev_s *fb = NULL; 351d6aed566Sopenharmony_ci struct fb_videoinfo_s vinfo; 352d6aed566Sopenharmony_ci struct fb_planeinfo_s pinfo; 353d6aed566Sopenharmony_ci#ifdef CONFIG_FB_OVERLAY 354d6aed566Sopenharmony_ci struct fb_overlayinfo_s oinfo; 355d6aed566Sopenharmony_ci#endif 356d6aed566Sopenharmony_ci char devname[16]; 357d6aed566Sopenharmony_ci int nplanes; 358d6aed566Sopenharmony_ci int ret; 359d6aed566Sopenharmony_ci 360d6aed566Sopenharmony_ci if (display < 0 || display >= FB_DEV_MAXNUM) return -EINVAL; 361d6aed566Sopenharmony_ci 362d6aed566Sopenharmony_ci /* Allocate a framebuffer state instance */ 363d6aed566Sopenharmony_ci fb = (struct fb_chardev_s *)malloc(sizeof(struct fb_chardev_s)); 364d6aed566Sopenharmony_ci if (fb == NULL) { 365d6aed566Sopenharmony_ci return -ENOMEM; 366d6aed566Sopenharmony_ci } 367d6aed566Sopenharmony_ci 368d6aed566Sopenharmony_ci /* Initialize the frame buffer device. */ 369d6aed566Sopenharmony_ci ret = up_fbinitialize(display); 370d6aed566Sopenharmony_ci if (ret < 0) { 371d6aed566Sopenharmony_ci gerr("ERROR: up_fbinitialize() failed for display %d: %d\n", display, ret); 372d6aed566Sopenharmony_ci goto errout_with_fb; 373d6aed566Sopenharmony_ci } 374d6aed566Sopenharmony_ci 375d6aed566Sopenharmony_ci DEBUGASSERT((unsigned)plane <= UINT8_MAX); 376d6aed566Sopenharmony_ci fb->plane = plane; 377d6aed566Sopenharmony_ci 378d6aed566Sopenharmony_ci fb->vtable = up_fbgetvplane(display, plane); 379d6aed566Sopenharmony_ci if (fb->vtable == NULL) { 380d6aed566Sopenharmony_ci gerr("ERROR: up_fbgetvplane() failed, vplane=%d\n", plane); 381d6aed566Sopenharmony_ci goto errout_with_fb; 382d6aed566Sopenharmony_ci } 383d6aed566Sopenharmony_ci 384d6aed566Sopenharmony_ci /* Initialize the frame buffer instance. */ 385d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable->getvideoinfo != NULL); 386d6aed566Sopenharmony_ci ret = fb->vtable->getvideoinfo(fb->vtable, &vinfo); 387d6aed566Sopenharmony_ci if (ret < 0) { 388d6aed566Sopenharmony_ci gerr("ERROR: getvideoinfo() failed: %d\n", ret); 389d6aed566Sopenharmony_ci goto errout_with_fb; 390d6aed566Sopenharmony_ci } 391d6aed566Sopenharmony_ci 392d6aed566Sopenharmony_ci nplanes = vinfo.nplanes; 393d6aed566Sopenharmony_ci DEBUGASSERT(vinfo.nplanes > 0 && (unsigned)plane < vinfo.nplanes); 394d6aed566Sopenharmony_ci 395d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable->getplaneinfo != NULL); 396d6aed566Sopenharmony_ci ret = fb->vtable->getplaneinfo(fb->vtable, plane, &pinfo); 397d6aed566Sopenharmony_ci if (ret < 0) { 398d6aed566Sopenharmony_ci gerr("ERROR: getplaneinfo() failed: %d\n", ret); 399d6aed566Sopenharmony_ci goto errout_with_fb; 400d6aed566Sopenharmony_ci } 401d6aed566Sopenharmony_ci 402d6aed566Sopenharmony_ci fb->fbmem = pinfo.fbmem; 403d6aed566Sopenharmony_ci fb->fblen = pinfo.fblen; 404d6aed566Sopenharmony_ci fb->bpp = pinfo.bpp; 405d6aed566Sopenharmony_ci 406d6aed566Sopenharmony_ci /* Clear the framebuffer memory */ 407d6aed566Sopenharmony_ci memset(pinfo.fbmem, 0, pinfo.fblen); 408d6aed566Sopenharmony_ci 409d6aed566Sopenharmony_ci#ifdef CONFIG_FB_OVERLAY 410d6aed566Sopenharmony_ci /* Initialize first overlay but do not select */ 411d6aed566Sopenharmony_ci DEBUGASSERT(fb->vtable->getoverlayinfo != NULL); 412d6aed566Sopenharmony_ci ret = fb->vtable->getoverlayinfo(fb->vtable, 0, &oinfo); 413d6aed566Sopenharmony_ci if (ret < 0) { 414d6aed566Sopenharmony_ci gerr("ERROR: getoverlayinfo() failed: %d\n", ret); 415d6aed566Sopenharmony_ci goto errout_with_fb; 416d6aed566Sopenharmony_ci } 417d6aed566Sopenharmony_ci 418d6aed566Sopenharmony_ci /* Clear the overlay memory. Necessary when plane 0 and overlay 0 419d6aed566Sopenharmony_ci * different. 420d6aed566Sopenharmony_ci */ 421d6aed566Sopenharmony_ci 422d6aed566Sopenharmony_ci memset(oinfo.fbmem, 0, oinfo.fblen); 423d6aed566Sopenharmony_ci#endif 424d6aed566Sopenharmony_ci 425d6aed566Sopenharmony_ci /* Register the framebuffer device */ 426d6aed566Sopenharmony_ci if (nplanes < 2) { 427d6aed566Sopenharmony_ci (void)sprintf_s(devname, 16, "/dev/fb%d", display); 428d6aed566Sopenharmony_ci } else { 429d6aed566Sopenharmony_ci (void)sprintf_s(devname, 16, "/dev/fb%d.%d", display, plane); 430d6aed566Sopenharmony_ci } 431d6aed566Sopenharmony_ci 432d6aed566Sopenharmony_ci ret = register_driver(devname, (void *)fb); 433d6aed566Sopenharmony_ci if (ret < 0) { 434d6aed566Sopenharmony_ci gerr("ERROR: register_driver() failed: %d\n", ret); 435d6aed566Sopenharmony_ci goto errout_with_fb; 436d6aed566Sopenharmony_ci } 437d6aed566Sopenharmony_ci 438d6aed566Sopenharmony_ci g_fb_dev[display] = fb; 439d6aed566Sopenharmony_ci 440d6aed566Sopenharmony_ci return OK; 441d6aed566Sopenharmony_ci 442d6aed566Sopenharmony_cierrout_with_fb: 443d6aed566Sopenharmony_ci free(fb); 444d6aed566Sopenharmony_ci return ret; 445d6aed566Sopenharmony_ci} 446d6aed566Sopenharmony_ci 447d6aed566Sopenharmony_ciint fb_unregister(int display) 448d6aed566Sopenharmony_ci{ 449d6aed566Sopenharmony_ci struct fb_chardev_s *fb = NULL; 450d6aed566Sopenharmony_ci char devname[16]; 451d6aed566Sopenharmony_ci 452d6aed566Sopenharmony_ci if (display < 0 || display >= FB_DEV_MAXNUM) return -EINVAL; 453d6aed566Sopenharmony_ci 454d6aed566Sopenharmony_ci (void)sprintf_s(devname, 16, "/dev/fb%d", display); 455d6aed566Sopenharmony_ci unregister_driver(devname); 456d6aed566Sopenharmony_ci 457d6aed566Sopenharmony_ci up_fbuninitialize(display); 458d6aed566Sopenharmony_ci 459d6aed566Sopenharmony_ci fb = g_fb_dev[display]; 460d6aed566Sopenharmony_ci free(fb); 461d6aed566Sopenharmony_ci g_fb_dev[display] = NULL; 462d6aed566Sopenharmony_ci 463d6aed566Sopenharmony_ci return 0; 464d6aed566Sopenharmony_ci}