jianglianfang commented on code in PR #10171:
URL: https://github.com/apache/nuttx/pull/10171#discussion_r1291019421


##########
drivers/video/goldfish_fb.c:
##########
@@ -0,0 +1,436 @@
+/****************************************************************************
+ * drivers/video/goldfish_fb.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <debug.h>
+#include <nuttx/config.h>
+#include <nuttx/video/fb.h>
+#include <nuttx/irq.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/mm/circbuf.h>
+
+/****************************************************************************
+ * Pre-processor definitions
+ ****************************************************************************/
+
+#ifndef putreg32
+#define putreg32(v, x) (*(volatile uint32_t *)(x) = (v))
+#endif
+
+#ifndef getreg32
+#define getreg32(x) (*(uint32_t *)(x))
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+enum
+{
+  GOLDFISH_FB_GET_WIDTH = 0x00,
+  GOLDFISH_FB_GET_HEIGHT = 0x04,
+  GOLDFISH_FB_INT_STATUS = 0x08,
+  GOLDFISH_FB_INT_ENABLE = 0x0c,
+  GOLDFISH_FB_SET_BASE = 0x10,
+  GOLDFISH_FB_SET_ROTATION = 0x14,
+  GOLDFISH_FB_SET_BLANK = 0x18,
+  GOLDFISH_FB_GET_PHYS_WIDTH = 0x1c,
+  GOLDFISH_FB_GET_PHYS_HEIGHT = 0x20,
+  GOLDFISH_FB_GET_FORMAT = 0x24,
+  GOLDFISH_FB_INT_VSYNC = 1U << 0,
+  GOLDFISH_FB_INT_UPDATE_DONE = 1U << 1,
+  GOLDFISH_FB_FORMAT_BRGA_8888 = 1,
+  GOLDFISH_FB_FORMAT_RGBX_8888 = 2,
+  GOLDFISH_FB_FORMAT_RGB_888 = 3,
+  GOLDFISH_FB_FORMAT_RGB_565 = 4,
+  GOLDFISH_FB_FORMAT_BGRA_8888 = 5,
+  GOLDFISH_FB_FORMAT_RGBA_5551 = 6,
+  GOLDFISH_FB_FORMAT_RGBA_4444 = 8
+};
+
+struct goldfish_fb_format_s
+{
+  uint8_t fmt;
+  uint8_t bpp;
+};
+
+struct goldfish_fb_s
+{
+  struct fb_vtable_s vtable;
+  struct fb_planeinfo_s planeinfo;
+  struct fb_videoinfo_s videoinfo;
+  FAR void *base;
+  int irq;
+  struct circbuf_s vsync;   /* Vsync event queued */
+#ifdef CONFIG_GOLDFISH_FB_VIDEO_MODE
+  bool busy; /* Only used in the video mode */
+  uintptr_t cur_buf;
+#endif
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static FAR struct goldfish_fb_s *g_goldfish_fb;
+
+static const struct goldfish_fb_format_s g_goldfish_format_map[] =
+{
+  [GOLDFISH_FB_FORMAT_BRGA_8888] =
+  {FB_FMT_RGBA32, 32},
+  [GOLDFISH_FB_FORMAT_RGBX_8888] =
+  {FB_FMT_RGB32, 32},
+  [GOLDFISH_FB_FORMAT_RGB_888] =
+  {FB_FMT_RGB24, 24},
+  [GOLDFISH_FB_FORMAT_RGB_565] =
+  {FB_FMT_RGB16_565, 16},
+  [GOLDFISH_FB_FORMAT_BGRA_8888] =
+  {FB_FMT_RGBA32, 32},
+  [GOLDFISH_FB_FORMAT_RGBA_5551] =
+  {FB_FMT_RGB16_555, 16},
+  [GOLDFISH_FB_FORMAT_RGBA_4444] =
+  {FB_FMT_RGBA16, 16},
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int goldfish_fb_pan_display(FAR struct fb_vtable_s *vtable,
+                                   FAR struct fb_planeinfo_s *pinfo);
+static int goldfish_getvideoinfo(FAR struct fb_vtable_s *vtable,
+                                 FAR struct fb_videoinfo_s *vinfo);
+static int goldfish_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno,
+                                 FAR struct fb_planeinfo_s *pinfo);
+static int goldfish_fb_interrupt(int irq, FAR void *dev_id, FAR void *arg);
+static void goldfish_fb_vsync_irq(FAR struct goldfish_fb_s *fb);
+static void goldfish_fb_framedone_irq(FAR struct goldfish_fb_s *fb);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: goldfish_fb_vsync_irq
+ ****************************************************************************/
+
+#ifdef CONFIG_GOLDFISH_FB_VIDEO_MODE
+static void goldfish_fb_vsync_irq(FAR struct goldfish_fb_s *fb)
+{
+  struct fb_planeinfo_s pinfo;
+
+  /* Attempte to retrieve a frame from the vsync queue */
+
+  ssize_t ret = circbuf_read(&fb->vsync, &pinfo,
+                             sizeof(struct fb_planeinfo_s));
+  DEBUGASSERT(ret <= 0 || ret == sizeof(struct fb_planeinfo_s));
+
+  fb->busy = true;
+  if (ret > 0)
+    {
+      fb->cur_buf = (uintptr_t)((uint8_t *)fb->planeinfo.fbmem +
+                                           fb->planeinfo.stride *
+                                           pinfo.yoffset);
+    }
+
+  if (fb->cur_buf)
+    {
+      /* Send buffer addr to GOLDFISH */
+
+      putreg32(fb->cur_buf, fb->base + GOLDFISH_FB_SET_BASE);
+    }
+}
+#else
+static void goldfish_fb_vsync_irq(FAR struct goldfish_fb_s *fb)
+{
+  struct fb_planeinfo_s pinfo;
+
+  /* Attempte to retrieve a frame from the vsync queue */
+
+  ssize_t ret = circbuf_read(&fb->vsync, &pinfo,
+                             sizeof(struct fb_planeinfo_s));
+  DEBUGASSERT(ret <= 0 || ret == sizeof(struct fb_planeinfo_s));
+
+  if (ret > 0)
+    {
+      uintptr_t buf = (uintptr_t)((uint8_t *)fb->planeinfo.fbmem +
+                                             fb->planeinfo.stride *
+                                             pinfo.yoffset);
+
+      /* Send buffer addr to GOLDFISH */
+
+      putreg32(buf, fb->base + GOLDFISH_FB_SET_BASE);
+    }
+}
+#endif
+
+/****************************************************************************
+ * Name: goldfish_fb_framedone_irq
+ ****************************************************************************/
+
+#ifdef CONFIG_GOLDFISH_FB_VIDEO_MODE
+static void goldfish_fb_framedone_irq(FAR struct goldfish_fb_s *fb)
+{
+  fb->busy = false;
+
+  if (fb->cur_buf && !circbuf_is_empty(&fb->vsync))
+    {
+      /* Clear the current frame buffer */
+
+      fb->cur_buf = 0;
+
+      /* After the sending is completed, notify the upper
+       * layer that the framebuffer can be written.
+       */
+
+      fb_pollnotify(&fb->vtable);
+    }
+}
+#else
+static void goldfish_fb_framedone_irq(FAR struct goldfish_fb_s *fb)
+{
+  /* After the sending is completed, notify the upper
+   * layer that the framebuffer can be written.
+   */
+
+  fb_pollnotify(&fb->vtable);
+}
+#endif
+
+/****************************************************************************
+ * Name: goldfish_fb_interrupt
+ ****************************************************************************/
+
+static int goldfish_fb_interrupt(int irq, FAR void *dev_id, FAR void *arg)
+{
+  FAR struct goldfish_fb_s *fb = arg;
+  irqstate_t flags;
+  uint32_t status;
+
+  flags = enter_critical_section();
+  status = getreg32(fb->base + GOLDFISH_FB_INT_STATUS);
+  if (status & GOLDFISH_FB_INT_VSYNC)
+    {
+      goldfish_fb_vsync_irq(fb);
+    }
+
+  else if (status & GOLDFISH_FB_INT_UPDATE_DONE)
+    {
+      goldfish_fb_framedone_irq(fb);
+    }
+
+  leave_critical_section(flags);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: goldfish_fb_pan_display
+ ****************************************************************************/
+
+static int goldfish_fb_pan_display(FAR struct fb_vtable_s *vtable,
+                                   FAR struct fb_planeinfo_s *pinfo)
+{
+  struct goldfish_fb_s *fb = (FAR struct goldfish_fb_s *)vtable;
+  irqstate_t flags;
+  ssize_t ret;
+
+  /** Disable the interrupt when writing to the queue to
+   *  prevent it from being modified by the interrupted
+   * thread during the writing process.
+   */
+
+  flags = enter_critical_section();
+
+  /* Write the planeinfo information submitted
+   * by the renderer to the queue
+   */
+
+  ret = circbuf_write(&fb->vsync, pinfo,
+                      sizeof(struct fb_planeinfo_s));
+  DEBUGASSERT(ret == sizeof(struct fb_planeinfo_s));
+
+#ifdef CONFIG_GOLDFISH_FB_VIDEO_MODE
+  if (fb->cur_buf && !fb->busy)
+    {
+      /* Clear the current frame buffer if not busy in transfering */
+
+      fb->cur_buf = 0;
+
+      /* Notify the upper layer that the framebuffer can be written */
+
+      fb_pollnotify(&fb->vtable);
+    }
+#endif
+
+  /* Re-enable interrupts */
+
+  leave_critical_section(flags);
+  return ret < 0 ? ret : 0;
+}
+
+/****************************************************************************
+ * Name: goldfish_getvideoinfo
+ ****************************************************************************/
+
+static int goldfish_getvideoinfo(FAR struct fb_vtable_s *vtable,
+                                 FAR struct fb_videoinfo_s *vinfo)
+{
+  FAR struct goldfish_fb_s *fb = (FAR struct goldfish_fb_s *)vtable;
+
+  ginfo("vtable=%p vinfo=%p\n", vtable, vinfo);
+  if (fb && vinfo)
+    {
+      memcpy(vinfo, &fb->videoinfo, sizeof(struct fb_videoinfo_s));
+      return OK;
+    }
+
+  gerr("ERROR: Returning EINVAL\n");
+  return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: goldfish_getplaneinfo
+ ****************************************************************************/
+
+static int goldfish_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno,
+                                 FAR struct fb_planeinfo_s *pinfo)
+{
+  FAR struct goldfish_fb_s *fb = (FAR struct goldfish_fb_s *)vtable;
+
+  ginfo("vtable=%p planeno=%d pinfo=%p\n", vtable, planeno, pinfo);
+  if (fb && planeno == 0 && pinfo)
+    {
+      memcpy(pinfo, &fb->planeinfo, sizeof(struct fb_planeinfo_s));
+      return OK;
+    }
+
+  gerr("ERROR: Returning EINVAL\n");
+  return -EINVAL;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_fbinitialize
+ ****************************************************************************/
+
+int up_fbinitialize(int display)
+{
+  FAR struct goldfish_fb_s *fb;
+  uint32_t fmt;
+  int ret = OK;
+
+  fb = (FAR struct goldfish_fb_s *)kmm_zalloc(sizeof(*fb));

Review Comment:
   Done.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to