lcd_framebuffer.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. /****************************************************************************
  2. * drivers/lcd/lcd_frambuffer.c
  3. *
  4. * Copyright (C) 2017=-2018 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <stdint.h>
  40. #include <string.h>
  41. #include <assert.h>
  42. #include <errno.h>
  43. #include <debug.h>
  44. #include <nuttx/board.h>
  45. #include <nuttx/kmalloc.h>
  46. #include <nuttx/nx/nx.h>
  47. #include <nuttx/nx/nxglib.h>
  48. #include <nuttx/lcd/lcd.h>
  49. #include <nuttx/video/fb.h>
  50. #ifdef CONFIG_LCD_FRAMEBUFFER
  51. /****************************************************************************
  52. * Pre-processor Definitions
  53. ****************************************************************************/
  54. /* At present, only video plane 0 is supported */
  55. #define VIDEO_PLANE 0
  56. /****************************************************************************
  57. * Private Types
  58. ****************************************************************************/
  59. /* This structure describes the LCD frambuffer */
  60. struct lcdfb_dev_s
  61. {
  62. struct fb_vtable_s vtable; /* Must be cast compatible with lcdfb_dev_s */
  63. FAR struct lcdfb_dev_s *flink; /* Supports a singly linked list */
  64. FAR struct lcd_dev_s *lcd; /* Contained LCD device */
  65. FAR uint8_t *fbmem; /* Allocated framebuffer */
  66. FAR struct lcd_planeinfo_s pinfo; /* LCD plane info */
  67. size_t fblen; /* Size of the framebuffer in bytes */
  68. fb_coord_t xres; /* Horizontal resolution in pixel columns */
  69. fb_coord_t yres; /* Vertical resolution in pixel rows */
  70. fb_coord_t stride; /* Width of a row in bytes */
  71. uint8_t display; /* Display number */
  72. };
  73. /****************************************************************************
  74. * Private Function Prototypes
  75. ****************************************************************************/
  76. /* Update the LCD when there is a change to the framebuffer */
  77. static int lcdfb_update(FAR struct lcdfb_dev_s *priv,
  78. FAR const struct nxgl_rect_s *rect);
  79. /* Get information about the video controller configuration and the
  80. * configuration of each color plane.
  81. */
  82. static int lcdfb_getvideoinfo(FAR struct fb_vtable_s *vtable,
  83. FAR struct fb_videoinfo_s *vinfo);
  84. static int lcdfb_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno,
  85. FAR struct fb_planeinfo_s *pinfo);
  86. /* The following is provided only if the video hardware supports RGB color
  87. * mapping
  88. */
  89. #ifdef CONFIG_FB_CMAP
  90. static int lcdfb_getcmap(FAR struct fb_vtable_s *vtable,
  91. FAR struct fb_cmap_s *cmap);
  92. static int lcdfb_putcmap(FAR struct fb_vtable_s *vtable,
  93. FAR const struct fb_cmap_s *cmap);
  94. #endif
  95. /* The following is provided only if the video hardware supports a hardware
  96. * cursor
  97. */
  98. #ifdef CONFIG_FB_HWCURSOR
  99. static int lcdfb_getcursor(FAR struct fb_vtable_s *vtable,
  100. FAR struct fb_cursorattrib_s *attrib);
  101. static int lcdfb_setcursor(FAR struct fb_vtable_s *vtable,
  102. FAR struct fb_setcursor_s *settings);
  103. #endif
  104. /****************************************************************************
  105. * Private Data
  106. ****************************************************************************/
  107. /* This is a singly linked list that supports look-up of framebuffer state
  108. * using the display number.
  109. */
  110. static FAR struct lcdfb_dev_s *g_lcdfb;
  111. /****************************************************************************
  112. * Private Functions
  113. ****************************************************************************/
  114. /****************************************************************************
  115. * Name: lcdfb_find
  116. *
  117. * Description:
  118. * Find the LCD framebuffer state associated with the display.
  119. *
  120. ****************************************************************************/
  121. static FAR struct lcdfb_dev_s *lcdfb_find(int display)
  122. {
  123. FAR struct lcdfb_dev_s *priv;
  124. /* Look up the LCD framebuffer state structure for this display.
  125. *
  126. * REVISIT: If many LCD framebuffers are used, then this lookup would be
  127. * a performance issue.
  128. * REVISIT: Semaphore protections is needed if there is concurrent access.
  129. */
  130. for (priv = g_lcdfb; priv != NULL; priv = priv->flink)
  131. {
  132. if (priv->display == display)
  133. {
  134. return priv;
  135. }
  136. }
  137. return NULL;
  138. }
  139. /****************************************************************************
  140. * Name: lcdfb_update
  141. *
  142. * Description:
  143. * Update the LCD when there is a change to the framebuffer.
  144. *
  145. ****************************************************************************/
  146. static int lcdfb_update(FAR struct lcdfb_dev_s *priv,
  147. FAR const struct nxgl_rect_s *rect)
  148. {
  149. FAR struct lcd_planeinfo_s *pinfo = &priv->pinfo;
  150. FAR uint8_t *run;
  151. fb_coord_t row;
  152. fb_coord_t startx;
  153. fb_coord_t endx;
  154. fb_coord_t width;
  155. fb_coord_t starty;
  156. fb_coord_t endy;
  157. int ret;
  158. /* Clip to fit in the framebuffer */
  159. startx = rect->pt1.x;
  160. if (startx < 0)
  161. {
  162. startx = 0;
  163. }
  164. endx = rect->pt2.x;
  165. if (endx >= priv->xres)
  166. {
  167. endx = priv->xres-1;
  168. }
  169. starty = rect->pt1.y;
  170. if (starty < 0)
  171. {
  172. starty = 0;
  173. }
  174. endy = rect->pt2.y;
  175. if (endy >= priv->yres)
  176. {
  177. endy = priv->yres-1;
  178. }
  179. /* If the display uses a value of BPP < 8, then we may have to extend the
  180. * rectangle on the left so that it is byte aligned. Works for BPP={1,2,4}
  181. */
  182. if (pinfo->bpp < 8)
  183. {
  184. unsigned int pixperbyte = 8 / pinfo->bpp;
  185. startx &= ~(pixperbyte - 1);
  186. }
  187. width = endx - startx + 1;
  188. /* Get the starting position in the framebuffer */
  189. run = priv->fbmem + starty * priv->stride;
  190. run += (startx * pinfo->bpp + 7) >> 3;
  191. for (row = starty; row <= endy; row++)
  192. {
  193. /* REVISIT: Some LCD hardware certain aligment requirements on DMA
  194. * memory.
  195. */
  196. ret = pinfo->putrun(row, startx, run, width);
  197. if (ret < 0)
  198. {
  199. return ret;
  200. }
  201. run += priv->stride;
  202. }
  203. return OK;
  204. }
  205. /****************************************************************************
  206. * Name: lcdfb_getvideoinfo
  207. ****************************************************************************/
  208. static int lcdfb_getvideoinfo(FAR struct fb_vtable_s *vtable,
  209. FAR struct fb_videoinfo_s *vinfo)
  210. {
  211. FAR struct lcdfb_dev_s *priv;
  212. FAR struct lcd_dev_s *lcd;
  213. int ret = -EINVAL;
  214. lcdinfo("vtable=%p vinfo=%p\n", vtable, vinfo);
  215. DEBUGASSERT(vtable != NULL && vinfo != NULL);
  216. priv = (FAR struct lcdfb_dev_s *)vtable;
  217. if (priv != NULL && vinfo != NULL)
  218. {
  219. /* Get the video info from the contained LCD */
  220. lcd = priv->lcd;
  221. DEBUGASSERT(lcd->getvideoinfo != NULL);
  222. ret = lcd->getvideoinfo(lcd, vinfo);
  223. if (ret < 0)
  224. {
  225. lcderr("ERROR: LCD getvideoinfo() failed: %d\n", ret);
  226. }
  227. }
  228. return ret;
  229. }
  230. /****************************************************************************
  231. * Name: lcdfb_getplaneinfo
  232. ****************************************************************************/
  233. static int lcdfb_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno,
  234. FAR struct fb_planeinfo_s *pinfo)
  235. {
  236. FAR struct lcdfb_dev_s *priv;
  237. int ret = -EINVAL;
  238. lcdinfo("vtable=%p planeno=%d pinfo=%p\n", vtable, planeno, pinfo);
  239. DEBUGASSERT(vtable != NULL && planeno == VIDEO_PLANE && pinfo != NULL);
  240. priv = (FAR struct lcdfb_dev_s *)vtable;
  241. if (priv != NULL && planeno == VIDEO_PLANE && pinfo != NULL)
  242. {
  243. /* Return the plane info */
  244. pinfo->fbmem = priv->fbmem;
  245. pinfo->fblen = priv->fblen;
  246. pinfo->stride = priv->stride;
  247. pinfo->display = priv->display;
  248. pinfo->bpp = priv->pinfo.bpp;
  249. ret = OK;
  250. }
  251. return ret;
  252. }
  253. /****************************************************************************
  254. * Name: lcdfb_getcmap
  255. ****************************************************************************/
  256. #ifdef CONFIG_FB_CMAP
  257. static int lcdfb_getcmap(FAR struct fb_vtable_s *vtable,
  258. FAR struct fb_cmap_s *cmap)
  259. {
  260. FAR struct lcdfb_dev_s *priv;
  261. FAR struct lcd_dev_s *lcd;
  262. int ret = -EINVAL;
  263. lcdinfo("vtable=%p cmap=%p\n", vtable, cmap);
  264. DEBUGASSERT(vtable != NULL && cmap != NULL);
  265. priv = (FAR struct lcdfb_dev_s *)vtable;
  266. if (priv != NULL && cmap != NULL)
  267. {
  268. /* Get the video info from the contained LCD */
  269. lcd = priv->lcd
  270. DEBUGASSERT(lcd->getcmap != NULL);
  271. ret = lcd->getcmap(lcd, cmap);
  272. if (ret < 0)
  273. {
  274. lcderr("ERROR: LCD getcmap() failed: %d\n", ret);
  275. }
  276. }
  277. return ret;
  278. }
  279. #endif
  280. /****************************************************************************
  281. * Name: lcdfb_putcmap
  282. ****************************************************************************/
  283. #ifdef CONFIG_FB_CMAP
  284. static int lcdfb_putcmap(FAR struct fb_vtable_s *vtable,
  285. FAR const struct fb_cmap_s *cmap)
  286. {
  287. FAR struct lcdfb_dev_s *priv;
  288. FAR struct lcd_dev_s *lcd;
  289. int ret = -EINVAL;
  290. lcdinfo("vtable=%p cmap=%p\n", vtable, cmap);
  291. DEBUGASSERT(vtable != NULL && cmap != NULL);
  292. priv = (FAR struct lcdfb_dev_s *)vtable;
  293. if (priv != NULL && cmap != NULL)
  294. {
  295. /* Get the video info from the contained LCD */
  296. lcd = priv->lcd
  297. DEBUGASSERT(lcd->putcmap != NULL);
  298. ret = lcd->putcmap(lcd, cmap);
  299. if (ret < 0)
  300. {
  301. lcderr("ERROR: LCD putcmap() failed: %d\n", ret);
  302. }
  303. }
  304. return ret;
  305. }
  306. #endif
  307. /****************************************************************************
  308. * Name: lcdfb_getcursor
  309. ****************************************************************************/
  310. #ifdef CONFIG_FB_HWCURSOR
  311. static int lcdfb_getcursor(FAR struct fb_vtable_s *vtable,
  312. FAR struct fb_cursorattrib_s *attrib)
  313. {
  314. lcdinfo("vtable=%p attrib=%p\n", vtable, attrib);
  315. FAR struct lcdfb_dev_s *priv;
  316. FAR struct lcd_dev_s *lcd;
  317. int ret = -EINVAL;
  318. lcdinfo("vtable=%p attrib=%p\n", vtable, attrib);
  319. DEBUGASSERT(vtable != NULL && attrib != NULL);
  320. priv = (FAR struct lcdfb_dev_s *)vtable;
  321. if (priv != NULL && attrib != NULL)
  322. {
  323. /* Get the video info from the contained LCD */
  324. lcd = priv->lcd
  325. DEBUGASSERT(lcd->getcursor != NULL);
  326. ret = lcd->getcursor(lcd, attrib);
  327. if (ret < 0)
  328. {
  329. lcderr("ERROR: LCD getcursor() failed: %d\n", ret);
  330. }
  331. }
  332. return ret;
  333. }
  334. #endif
  335. /****************************************************************************
  336. * Name: lcdfb_setcursor
  337. ****************************************************************************/
  338. #ifdef CONFIG_FB_HWCURSOR
  339. static int lcdfb_setcursor(FAR struct fb_vtable_s *vtable,
  340. FAR struct fb_setcursor_s *settings)
  341. {
  342. FAR struct lcdfb_dev_s *priv;
  343. FAR struct lcd_dev_s *lcd;
  344. int ret = -EINVAL;
  345. lcdinfo("vtable=%p settings=%p\n", vtable, settings);
  346. DEBUGASSERT(vtable != NULL && settings != NULL);
  347. priv = (FAR struct lcdfb_dev_s *)vtable;
  348. if (priv != NULL && settings != NULL)
  349. {
  350. /* Get the video info from the contained LCD */
  351. lcd = priv->lcd
  352. DEBUGASSERT(lcd->setcursor != NULL);
  353. ret = lcd->setcursor(lcd, settings);
  354. if (ret < 0)
  355. {
  356. lcderr("ERROR: LCD setcursor() failed: %d\n", ret);
  357. }
  358. }
  359. return ret;
  360. }
  361. #endif
  362. /****************************************************************************
  363. * Public Functions
  364. ****************************************************************************/
  365. /****************************************************************************
  366. * Name: up_fbinitialize
  367. *
  368. * Description:
  369. * Initialize the framebuffer video hardware associated with the display.
  370. *
  371. * Input Parameters:
  372. * display - In the case of hardware with multiple displays, this
  373. * specifies the display. Normally this is zero.
  374. *
  375. * Returned Value:
  376. * Zero is returned on success; a negated errno value is returned on any
  377. * failure.
  378. *
  379. ****************************************************************************/
  380. int up_fbinitialize(int display)
  381. {
  382. FAR struct lcdfb_dev_s *priv;
  383. FAR struct lcd_dev_s *lcd;
  384. struct fb_videoinfo_s vinfo;
  385. struct nxgl_rect_s rect;
  386. int ret;
  387. lcdinfo("display=%d\n", display);
  388. DEBUGASSERT((unsigned)display < UINT8_MAX);
  389. /* Allocate the framebuffer state structure */
  390. priv = (FAR struct lcdfb_dev_s *)kmm_zalloc(sizeof(struct lcdfb_dev_s));
  391. if (priv == NULL)
  392. {
  393. lcderr("ERROR: Failed to allocate state structure\n");
  394. return -ENOMEM;
  395. }
  396. /* Initialize the LCD-independent fields of the state structure */
  397. priv->display = display;
  398. priv->vtable.getvideoinfo = lcdfb_getvideoinfo,
  399. priv->vtable.getplaneinfo = lcdfb_getplaneinfo,
  400. #ifdef CONFIG_FB_CMAP
  401. priv->vtable.getcmap = lcdfb_getcmap,
  402. priv->vtable.putcmap = lcdfb_putcmap,
  403. #endif
  404. #ifdef CONFIG_FB_HWCURSOR
  405. priv->vtable.getcursor = lcdfb_getcursor,
  406. priv->vtable.setcursor = lcdfb_setcursor,
  407. #endif
  408. #ifdef CONFIG_LCD_EXTERNINIT
  409. /* Use external graphics driver initialization */
  410. lcd = board_graphics_setup(display);
  411. if (lcd == NULL)
  412. {
  413. gerr("ERROR: board_graphics_setup failed, devno=%d\n", display);
  414. return EXIT_FAILURE;
  415. }
  416. #else
  417. /* Initialize the LCD device */
  418. ret = board_lcd_initialize();
  419. if (ret < 0)
  420. {
  421. lcderr("ERROR: board_lcd_initialize() failed: %d\n", ret);
  422. goto errout_with_state;
  423. }
  424. /* Get the device instance */
  425. lcd = board_lcd_getdev(display);
  426. if (lcd == NULL)
  427. {
  428. lcderr("ERROR: board_lcd_getdev failed, devno=%d\n", display);
  429. ret = -ENODEV;
  430. goto errout_with_lcd;
  431. }
  432. #endif
  433. priv->lcd = lcd;
  434. /* Initialize the LCD-dependent fields of the state structure */
  435. DEBUGASSERT(lcd->getvideoinfo != NULL);
  436. ret = lcd->getvideoinfo(lcd, &vinfo);
  437. if (ret < 0)
  438. {
  439. lcderr("ERROR: LCD getvideoinfo() failed: %d\n", ret);
  440. goto errout_with_lcd;
  441. }
  442. priv->xres = vinfo.xres;
  443. priv->yres = vinfo.yres;
  444. DEBUGASSERT(lcd->getplaneinfo != NULL);
  445. ret = lcd->getplaneinfo(lcd, VIDEO_PLANE, &priv->pinfo);
  446. if (ret < 0)
  447. {
  448. lcderr("ERROR: LCD getplaneinfo() failed: %d\n", ret);
  449. goto errout_with_lcd;
  450. }
  451. /* Allocate (and clear) the framebuffer */
  452. priv->stride = ((size_t)priv->xres * priv->pinfo.bpp + 7) >> 3;
  453. priv->fblen = priv->stride * priv->yres;
  454. priv->fbmem = (FAR uint8_t *)kmm_zalloc(priv->fblen);
  455. if (priv->fbmem == NULL)
  456. {
  457. lcderr("ERROR: Failed to allocate frame buffer memory\n");
  458. ret = -ENOMEM;
  459. goto errout_with_lcd;
  460. }
  461. /* Add the state structure to the list of framebuffer interfaces */
  462. priv->flink = g_lcdfb;
  463. g_lcdfb = priv;
  464. /* Write the entire framebuffer to the LCD */
  465. rect.pt1.x = 0;
  466. rect.pt1.y = 0;
  467. rect.pt2.x = priv->xres - 1;
  468. rect.pt2.y = priv->yres - 1;
  469. ret = lcdfb_update(priv, &rect);
  470. if (ret < 0)
  471. {
  472. lcderr("FB update failed: %d\n", ret);
  473. }
  474. /* Turn the LCD on at 75% power */
  475. (void)priv->lcd->setpower(priv->lcd, ((3*CONFIG_LCD_MAXPOWER + 3)/4));
  476. return OK;
  477. errout_with_lcd:
  478. #ifndef CONFIG_LCD_EXTERNINIT
  479. board_lcd_uninitialize();
  480. errout_with_state:
  481. #endif
  482. kmm_free(priv);
  483. return ret;
  484. }
  485. /****************************************************************************
  486. * Name: up_fbgetvplane
  487. *
  488. * Description:
  489. * Return a a reference to the framebuffer object for the specified video
  490. * plane of the specified plane. Many OSDs support multiple planes of video.
  491. *
  492. * Input Parameters:
  493. * display - In the case of hardware with multiple displays, this
  494. * specifies the display. Normally this is zero.
  495. * vplane - Identifies the plane being queried.
  496. *
  497. * Returned Value:
  498. * A non-NULL pointer to the frame buffer access structure is returned on
  499. * success; NULL is returned on any failure.
  500. *
  501. ****************************************************************************/
  502. FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane)
  503. {
  504. FAR struct lcdfb_dev_s *priv;
  505. lcdinfo("display=%d vplane=%d\n", display, vplane);
  506. DEBUGASSERT(vplane == VIDEO_PLANE);
  507. /* Look up the LCD framebuffer state structure for this display. */
  508. priv = lcdfb_find(display);
  509. if (priv == NULL)
  510. {
  511. lcderr("ERROR: lcd_find(%d) failed\n", display);
  512. return NULL;
  513. }
  514. return &priv->vtable;
  515. }
  516. /****************************************************************************
  517. * Name: up_fbuninitialize
  518. *
  519. * Description:
  520. * Uninitialize the framebuffer support for the specified display.
  521. *
  522. * Input Parameters:
  523. * display - In the case of hardware with multiple displays, this
  524. * specifies the display. Normally this is zero.
  525. *
  526. * Returned Value:
  527. * None
  528. *
  529. ****************************************************************************/
  530. void up_fbuninitialize(int display)
  531. {
  532. FAR struct lcdfb_dev_s *priv;
  533. FAR struct lcdfb_dev_s *prev;
  534. /* Find the LCD framebuffer state associated with this display.
  535. * REVISIT: Semaphore protections is needed if there is concurrent access.
  536. */
  537. for (prev = NULL, priv = g_lcdfb;
  538. priv != NULL;
  539. prev = priv, priv = priv->flink)
  540. {
  541. if (priv->display == display)
  542. {
  543. /* Remove the state structure from the list */
  544. if (prev != NULL)
  545. {
  546. prev->flink = priv->flink;
  547. }
  548. else
  549. {
  550. g_lcdfb = priv->flink;
  551. }
  552. #ifndef CONFIG_LCD_EXTERNINIT
  553. /* Uninitialize the LCD */
  554. board_lcd_uninitialize();
  555. #endif
  556. /* Free the frame buffer allocation */
  557. kmm_free(priv->fbmem);
  558. /* Free the state structure allocation */
  559. kmm_free(priv);
  560. break;
  561. }
  562. }
  563. }
  564. /****************************************************************************
  565. * Name: nx_notify_rectangle
  566. *
  567. * Description:
  568. * When CONFIG_LCD_UPDATE=y, then the graphics system will callout to
  569. * inform some external module that the display has been updated. This
  570. * would be useful in a couple for cases.
  571. *
  572. * - When a serial LCD is used, but a framebuffer is used to access the
  573. * LCD. In this case, the update callout can be used to refresh the
  574. * affected region of the display.
  575. *
  576. * - When VNC is enabled. This is case, this callout is necessary to
  577. * update the remote frame buffer to match the local framebuffer.
  578. *
  579. * When this feature is enabled, some external logic must provide this
  580. * interface. This is the function that will handle the notification. It
  581. * receives the rectangular region that was updated on the provided plane.
  582. *
  583. * NOTE: This function is also required for use with the LCD framebuffer
  584. * driver front end when CONFIG_LCD_UPDATE=y, although that use does not
  585. * depend on CONFIG_NX (and this function seems misnamed in that case).
  586. *
  587. ****************************************************************************/
  588. #if defined(CONFIG_LCD_UPDATE) || defined(CONFIG_NX_UPDATE)
  589. void nx_notify_rectangle(FAR NX_PLANEINFOTYPE *pinfo,
  590. FAR const struct nxgl_rect_s *rect)
  591. {
  592. FAR struct fb_planeinfo_s *fpinfo = (FAR struct fb_planeinfo_s *)pinfo;
  593. FAR struct lcdfb_dev_s *priv;
  594. int ret;
  595. DEBUGASSERT(fpinfo != NULL && rect != NULL);
  596. /* Look up the LCD framebuffer state structure for this display.
  597. *
  598. * REVISIT: If many LCD framebuffers are used, then this lookup would be
  599. * a performance issue.
  600. */
  601. priv = lcdfb_find(fpinfo->display);
  602. if (priv != NULL)
  603. {
  604. ret = lcdfb_update(priv, rect);
  605. if (ret < 0)
  606. {
  607. lcderr("FB update failed: %d\n", ret);
  608. }
  609. }
  610. }
  611. #endif
  612. #endif /* CONFIG_LCD_FRAMEBUFFER */