@@ -849,6 +849,36 @@ config VIDEO_MCDE_SIMPLE
before u-boot starts, and u-boot will simply render to the pre-
allocated frame buffer surface.
+config VIDEO_RAMFB
+ bool "QEMU ramfb display driver for in-RAM display"
+ depends on QFW
+ help
+ Enables a RAM based simple frame buffer driver which uses qfw to
+ notify the hypervisor about the location of a Frame Buffer allocated
+ in guest RAM as well as its properties.
+
+if VIDEO_RAMFB
+
+config VIDEO_RAMFB_SIZE_X
+ int "Width of ramfb display (X resolution)"
+ default 1280
+ help
+ Sets the width of the ramfb display.
+
+ These two options control the size of the display set up by QEMU.
+ Typical sizes are 1024 x 768 or 1280 x 1024.
+
+config VIDEO_RAMFB_SIZE_Y
+ int "Height of ramfb display (Y resolution)"
+ default 1024
+ help
+ Sets the height of the ramfb display.
+
+ These two options control the size of the display set up by QEMU.
+ Typical sizes are 1024 x 768 or 1280 x 1024.
+
+endif
+
config OSD
bool "Enable OSD support"
depends on DM
@@ -75,6 +75,7 @@ obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o
obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o
obj-$(CONFIG_VIDEO_VESA) += vesa.o
obj-$(CONFIG_VIDEO_SEPS525) += seps525.o
+obj-$(CONFIG_VIDEO_RAMFB) += ramfb.o
obj-$(CONFIG_VIDEO_ZYNQMP_DPSUB) += zynqmp/
obj-y += bridge/
new file mode 100644
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 Alexander Graf
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <video.h>
+#include <asm/global_data.h>
+#include <qfw.h>
+
+#define fourcc_code(a, b, c, d) ((u32)(a) | ((u32)(b) << 8) | \
+ ((u32)(c) << 16) | ((u32)(d) << 24))
+#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4')
+
+#define RAMFB_WIDTH CONFIG_VIDEO_RAMFB_SIZE_X
+#define RAMFB_HEIGHT CONFIG_VIDEO_RAMFB_SIZE_Y
+#define RAMFB_BPIX VIDEO_BPP32
+#define RAMFB_FORMAT VIDEO_X8R8G8B8
+
+static int ramfb_probe(struct udevice *dev)
+{
+ struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+ struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+ u32 selector;
+ int ret;
+ struct fw_file *file;
+ struct udevice *qfw;
+ struct dm_qfw_ops *ops;
+ struct qfw_dma dma = {};
+ struct ramfb_cfg cfg = {
+ .addr = cpu_to_be64(plat->base),
+ .fourcc = cpu_to_be32(DRM_FORMAT_XRGB8888),
+ .flags = 0,
+ .width = cpu_to_be32(RAMFB_WIDTH),
+ .height = cpu_to_be32(RAMFB_HEIGHT),
+ .stride = 0,
+ };
+
+ if (plat->base == 0)
+ return -EPROBE_DEFER;
+
+ debug("%s: Frame buffer base %lx\n", __func__, plat->base);
+
+ ret = qfw_get_dev(&qfw);
+ if (ret)
+ return -EPROBE_DEFER;
+
+ ops = dm_qfw_get_ops(qfw);
+ if (!ops)
+ return -EPROBE_DEFER;
+
+ file = qfw_find_file(qfw, "etc/ramfb");
+ if (!file) {
+ /* No ramfb available. At least we tried. */
+ return -ENOENT;
+ }
+
+ uc_priv->xsize = RAMFB_WIDTH;
+ uc_priv->ysize = RAMFB_HEIGHT;
+ uc_priv->bpix = RAMFB_BPIX;
+ uc_priv->format = RAMFB_FORMAT;
+ uc_priv->fb = (void *)plat->base;
+ uc_priv->fb_size = plat->size;
+
+ selector = be16_to_cpu(file->cfg.select);
+ dma.length = cpu_to_be32(sizeof(cfg));
+ dma.address = cpu_to_be64((uintptr_t)&cfg);
+ dma.control = cpu_to_be32(FW_CFG_DMA_WRITE | FW_CFG_DMA_SELECT |
+ (selector << 16));
+
+ barrier();
+
+ /* Send a DMA write request which enables the screen */
+ ops->read_entry_dma(qfw, &dma);
+
+ return 0;
+}
+
+static int ramfb_bind(struct udevice *dev)
+{
+ struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+ /* Set the maximum supported resolution */
+ uc_plat->size = RAMFB_WIDTH * RAMFB_HEIGHT * VNBYTES(RAMFB_BPIX);
+ debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(ramfb) = {
+ .name = "ramfb",
+ .id = UCLASS_VIDEO,
+ .probe = ramfb_probe,
+ .bind = ramfb_bind,
+};
@@ -142,6 +142,16 @@ struct bios_linker_entry {
};
} __packed;
+/* ramfb configuration details to read into etc/ramfb fw_cfg file */
+struct ramfb_cfg {
+ __be64 addr; /* Address of an allocated framebuffer */
+ __be32 fourcc; /* Pixel format in Linux DRM fourcc code */
+ __be32 flags; /* Unknown, appears unused */
+ __be32 width; /* Width of the requested ramfb display */
+ __be32 height; /* Height of the requested ramfb display */
+ __be32 stride; /* Number of bytes per line? */
+} __packed;
+
/* DMA transfer control data between UCLASS_QFW and QEMU. */
struct qfw_dma {
__be32 control;