[PATCH 2/4] ramfb: Add driver for ramfb display

Simon Glass sjg at chromium.org
Sat Mar 12 03:25:14 CET 2022


Hi Alex,

On Sun, 27 Feb 2022 at 07:40, Alexander Graf <agraf at csgraf.de> wrote:
>
> QEMU implements multiple ways to expose graphics output to the virt
> machine, but most of them are incompatible with hardware virtualization.
>
> The one that does work reliably is ramfb. It's a very simple mechanism
> in which the guest reserves a memory region for the frame buffer and then
> notifies the host about its location and properties. The host then just
> displays the contents of the frame buffer on screen.
>
> This patch implements a trivial version of a ramfb driver - hard coded
> to a single resolution.
>
> Signed-off-by: Alexander Graf <agraf at csgraf.de>
> ---
>  drivers/video/Kconfig     |   8 +++
>  drivers/video/MAINTAINERS |   4 ++
>  drivers/video/Makefile    |   1 +
>  drivers/video/ramfb.c     | 104 ++++++++++++++++++++++++++++++++++++++
>  4 files changed, 117 insertions(+)
>  create mode 100644 drivers/video/MAINTAINERS
>  create mode 100644 drivers/video/ramfb.c
>
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index ff8e11f648..73a9e20534 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -871,6 +871,14 @@ 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 EFI_LOADER && DM_VIDEO && 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.
> +
>  config OSD
>         bool "Enable OSD support"
>         depends on DM
> diff --git a/drivers/video/MAINTAINERS b/drivers/video/MAINTAINERS
> new file mode 100644
> index 0000000000..74c258a314
> --- /dev/null
> +++ b/drivers/video/MAINTAINERS
> @@ -0,0 +1,4 @@
> +QEMU RAMFB VIDEO DRIVER
> +M:     Alexander Graf <agraf at csgraf.de>
> +S:     Maintained
> +F:     drivers/video/ramfb.c
> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> index 4038395b12..6cfec17072 100644
> --- a/drivers/video/Makefile
> +++ b/drivers/video/Makefile
> @@ -74,6 +74,7 @@ obj-$(CONFIG_VIDEO_TEGRA20) += tegra.o
>  obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
>  obj-$(CONFIG_VIDEO_VESA) += vesa.o
>  obj-$(CONFIG_VIDEO_SEPS525) += seps525.o
> +obj-$(CONFIG_VIDEO_RAMFB) += ramfb.o
>
>  obj-y += bridge/
>  obj-y += sunxi/
> diff --git a/drivers/video/ramfb.c b/drivers/video/ramfb.c
> new file mode 100644
> index 0000000000..c46bfa3baa
> --- /dev/null
> +++ b/drivers/video/ramfb.c
> @@ -0,0 +1,104 @@
> +// 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 <efi_loader.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 DEFAULT_WIDTH  1280
> +#define DEFAULT_HEIGHT 900
> +#define DEFAULT_BPIX   VIDEO_BPP32
> +#define DEFAULT_FORMAT VIDEO_X8R8G8B8
> +
> +struct ramfb_cfg {

Should that be in a qemu header file somewhere? Anyway, please add comments.

> +       u64 addr;
> +       u32 fourcc;
> +       u32 flags;
> +       u32 width;
> +       u32 height;
> +       u32 stride;
> +} __packed;
> +
> +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;
> +       u64 base;
> +       u64 size;
> +       efi_status_t ret;
> +       struct fw_file *file;
> +       struct udevice *qfw;
> +       struct dm_qfw_ops *ops;
> +       struct qfw_dma dma = {};
> +       struct ramfb_cfg cfg = {
> +               .addr = 0,
> +               .fourcc = cpu_to_be32(DRM_FORMAT_XRGB8888),
> +               .flags = 0,
> +               .width = cpu_to_be32(DEFAULT_WIDTH),
> +               .height = cpu_to_be32(DEFAULT_HEIGHT),
> +               .stride = 0,
> +       };
> +
> +       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;
> +       }
> +
> +       size = DEFAULT_WIDTH * DEFAULT_HEIGHT * VNBYTES(DEFAULT_BPIX);
> +       ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +                                EFI_RESERVED_MEMORY_TYPE,
> +                                efi_size_in_pages(size), &base);

Please see video-uclass.c for how to to allocate the frame buffer.
This has nothing to do with EFI.

> +       if (ret != EFI_SUCCESS)
> +               return -ENOMEM;
> +
> +       debug("%s: base=%llx, size=%llu\n", __func__, base, size);
> +
> +       cfg.addr = cpu_to_be64(base);
> +       plat->base = base;
> +       plat->size = size;
> +       uc_priv->xsize = DEFAULT_WIDTH;
> +       uc_priv->ysize = DEFAULT_HEIGHT;
> +       uc_priv->bpix = DEFAULT_BPIX;
> +       uc_priv->format = DEFAULT_FORMAT;
> +       uc_priv->fb = (void *)base;
> +       uc_priv->fb_size = 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;
> +}
> +
> +U_BOOT_DRIVER(ramfb) = {
> +       .name   = "ramfb",
> +       .id     = UCLASS_VIDEO,
> +       .probe  = ramfb_probe,

You need a bind() method too.

> +};
> --
> 2.32.0
>

Regards,
Simon


More information about the U-Boot mailing list