All of lore.kernel.org
 help / color / mirror / Atom feed
From: Valentin Manea <valentin.manea@gmail.com>
To: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Cc: Jia Liu <proljc@gmail.com>, Stefan Hajnoczi <stefanha@redhat.com>
Subject: [Qemu-devel] [PATCH v3 2/4] hw/display: Add OpenCores FB device support
Date: Sun, 05 Oct 2014 14:05:15 +0300	[thread overview]
Message-ID: <543125EB.3070900@gmail.com> (raw)
In-Reply-To: <54312525.8040407@mrs.ro>

>From edfd91e325a8c1806140c7468e187781d0b20ea9 Mon Sep 17 00:00:00 2001
From: Valentin Manea <valentin.manea@gmail.com>
Date: Sun, 21 Sep 2014 10:57:55 +0300
Subject: [PATCH 2/4] target-openrisc: Add OpenCores FB device support

Add support for the OpenCores Framebuffer device and enable it by
default in the OpenRISC asim machine.

The OpenCores display device is a simple open source framebuffer device
created http://opencores.org/project,vgafb

Signed-off-by: Valentin Manea <valentin.manea@gmail.com>
---
 default-configs/or32-softmmu.mak |   2 +
 hw/display/Makefile.objs         |   1 +
 hw/display/ocfb.c                | 315 ++++++++++++++++++++++++++++++++++++++
 hw/display/ocfb.c.old            | 321 +++++++++++++++++++++++++++++++++++++++
 hw/openrisc/openrisc_asim.c      |   8 +-
 5 files changed, 646 insertions(+), 1 deletion(-)
 create mode 100644 hw/display/ocfb.c

diff --git a/default-configs/or32-softmmu.mak b/default-configs/or32-softmmu.mak
index c3ff078..036f591 100644
--- a/default-configs/or32-softmmu.mak
+++ b/default-configs/or32-softmmu.mak
@@ -5,3 +5,5 @@ CONFIG_OPENCORES_ETH=y
 CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_IDE_MMIO=y
+CONFIG_FRAMEBUFFER=y
+CONFIG_OPENCORESFB=y
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index 7ed76a9..4a755e6 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -33,3 +33,4 @@ obj-$(CONFIG_CG3) += cg3.o
 obj-$(CONFIG_VGA) += vga.o
 
 common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
+common-obj-$(CONFIG_OPENCORESFB) += ocfb.o
diff --git a/hw/display/ocfb.c b/hw/display/ocfb.c
new file mode 100644
index 0000000..fb2b7df
--- /dev/null
+++ b/hw/display/ocfb.c
@@ -0,0 +1,315 @@
+/*
+ * OpenCores framebuffer device
+ *
+ * Copyright (c) 2014 Valentin Manea
+ * Based on work by Sebastian Macke for jor1k http://s-macke.github.io/jor1k/
+ * Based on Arm PrimeCell PL110 Color LCD Controller by Paul Brook
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/display/framebuffer.h"
+#include "ui/console.h"
+
+/* VGA defines */
+#define VGA_CTRL       0x000
+#define VGA_STAT       0x004
+#define VGA_HTIM       0x008
+#define VGA_VTIM       0x00c
+#define VGA_HVLEN      0x010
+#define VGA_VBARA      0x014
+#define VGA_PALETTE    0x800
+
+#define VGA_CTRL_VEN   0x00000001 /* Video Enable */
+#define VGA_CTRL_HIE   0x00000002 /* HSync Interrupt Enable */
+#define VGA_CTRL_PC    0x00000800 /* 8-bit Pseudo Color Enable*/
+#define VGA_CTRL_CD8   0x00000000 /* Color Depth 8 */
+#define VGA_CTRL_CD16  0x00000200 /* Color Depth 16 */
+#define VGA_CTRL_CD24  0x00000400 /* Color Depth 24 */
+#define VGA_CTRL_CD32  0x00000600 /* Color Depth 32 */
+#define VGA_CTRL_CD    0x00000E00 /* Color Depth Mask */
+#define VGA_CTRL_VBL1  0x00000000 /* Burst Length 1 */
+#define VGA_CTRL_VBL2  0x00000080 /* Burst Length 2 */
+#define VGA_CTRL_VBL4  0x00000100 /* Burst Length 4 */
+#define VGA_CTRL_VBL8  0x00000180 /* Burst Length 8 */
+
+#define PALETTE_SIZE   256
+
+#define TYPE_OCFB "ocfb"
+#define OCFB(obj) OBJECT_CHECK(OCFBState, (obj), TYPE_OCFB)
+
+#ifdef DEBUG
+#define DPRINTF(fmt, ...)                                \
+    do { printf("ocfb: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+typedef struct OCFBState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+    QemuConsole *con;
+    /* RAM fragment containing framebuffer */
+    MemoryRegionSection mem_section;
+    uint32_t cr;
+    hwaddr   fb;
+    uint32_t fb_size;
+    uint32_t cols;
+    uint32_t rows;
+    uint32_t bpp;
+    uint32_t invalidate;
+    qemu_irq irq;
+} OCFBState;
+
+static int vmstate_ocfb_post_load(void *opaque, int version_id);
+
+static const VMStateDescription vmstate_ocfb = {
+    .name = "ocfb",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .post_load = vmstate_ocfb_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(cr, OCFBState),
+        VMSTATE_UINT32(fb_size, OCFBState),
+        VMSTATE_UINT64(fb, OCFBState),
+        VMSTATE_UINT32(cols, OCFBState),
+        VMSTATE_UINT32(rows, OCFBState),
+        VMSTATE_UINT32(bpp, OCFBState),
+        VMSTATE_UINT32(invalidate, OCFBState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int ocfb_enabled(OCFBState *s)
+{
+  return s->cr & VGA_CTRL_VEN;
+}
+
+static void ocfb_update_display(void *opaque)
+{
+    OCFBState *s = (OCFBState *)opaque;
+
+    if (!ocfb_enabled(s)) {
+        return;
+    }
+
+    memory_region_sync_dirty_bitmap(s->mem_section.mr);
+
+    int dirty = memory_region_get_dirty(s->mem_section.mr,
+          s->mem_section.offset_within_region, s->fb_size,
+          DIRTY_MEMORY_VGA);
+
+    if (dirty || s->invalidate) {
+        dpy_gfx_update(s->con, 0, 0, s->cols, s->rows);
+    }
+    s->invalidate = 0;
+    memory_region_reset_dirty(s->mem_section.mr,
+          s->mem_section.offset_within_region, s->fb_size,
+          DIRTY_MEMORY_VGA);
+}
+
+static void ocfb_invalidate_display(void *opaque)
+{
+    OCFBState *s = (OCFBState *)opaque;
+    s->invalidate = 1;
+}
+
+static void ocfb_ref_fb(OCFBState *s, hwaddr base, uint64_t src_len)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(s);
+
+    memory_region_unref(s->mem_section.mr);
+    s->mem_section = memory_region_find(sysbus_address_space(sbd), base,
+                                        src_len);
+    assert(s->mem_section.mr);
+    assert(s->mem_section.offset_within_address_space == base);
+
+    if (int128_get64(s->mem_section.size) != src_len ||
+            !memory_region_is_ram(s->mem_section.mr)) {
+        hw_error("Invalid framebuffer address!\n");
+    }
+}
+
+static uint64_t ocfb_read(void *opaque, hwaddr offset,
+                           unsigned size)
+{
+    DPRINTF("read at 0x%08X\n", (unsigned int)offset);
+    return 0;
+}
+
+
+static void ocfb_enable_console(OCFBState *s)
+{
+    DisplaySurface *surface;
+    if (!s->rows || !s->cols || !s->bpp) {
+        return;
+    }
+    if (!s->fb) {
+        return;
+    }
+    int stride = (s->cols * s->bpp) / 8;
+    s->fb_size = stride * s->rows;
+
+    ocfb_ref_fb(s, s->fb, s->fb_size);
+
+    pixman_format_code_t format = qemu_default_pixman_format(s->bpp, false);
+    /* console.c supported depth -> buffer can be used directly */
+    surface = qemu_create_displaysurface_guestmem(s->cols, s->rows, format,
+                                                  0, s->fb);
+    dpy_gfx_replace_surface(s->con, surface);
+}
+
+static inline void ocfb_read_htim(OCFBState *s, uint32_t val)
+{
+    /* uint32_t hsync_len = ((val >> 24) & 0xF) + 1;
+    uint32_t right_margin = ((val >> 16) & 0xF) + 1;*/
+    uint32_t xres = (val & 0xFFFF) + 1;
+    s->cols = xres;
+    DPRINTF("VGA_HTIM param, xres = %u!\n", s->cols);
+}
+
+static inline void ocfb_read_vtim(OCFBState *s, uint32_t val)
+{
+    /*uint32_t vsync_len = ((val >> 24) & 0xF) + 1;
+    uint32_t lower_margin = ((val >> 16) & 0xF) + 1;*/
+    uint32_t yres = (val & 0xFFFF) + 1;
+    s->rows = yres;
+    DPRINTF("VGA_VTIM param, yres = %u!\n", s->rows);
+}
+
+static void ocfb_write(void *opaque, hwaddr offset,
+                        uint64_t val, unsigned size)
+{
+    OCFBState *s = (OCFBState *)opaque;
+
+    DPRINTF("write at 0x%08X 0x%08X\n",
+             (unsigned int)offset, (unsigned int)val);
+
+    switch (offset) {
+    case VGA_CTRL:
+        s->cr = val;
+
+        if ((s->cr & VGA_CTRL_CD) == VGA_CTRL_CD32) {
+            s->bpp = 32;
+        } else if ((s->cr & VGA_CTRL_CD) == VGA_CTRL_CD24) {
+            s->bpp = 32;
+        } else if ((s->cr & VGA_CTRL_CD) == VGA_CTRL_CD16) {
+            s->bpp = 16;
+        } else {
+            hw_error("Unsupported framebuffer color mode!\n");
+        }
+
+        ocfb_invalidate_display(s);
+        if (ocfb_enabled(s)) {
+            DPRINTF("Enable FB!\n");
+            ocfb_enable_console(s);
+        }
+
+        break;
+    case VGA_STAT:
+        DPRINTF("VGA_STAT param!\n");
+        break;
+    case VGA_HTIM:
+        ocfb_read_htim(s, val);
+        break;
+    case VGA_VTIM:
+        ocfb_read_vtim(s, val);
+        break;
+    case VGA_HVLEN:
+        DPRINTF("VGA_HVLEN param!\n");
+        break;
+    case VGA_VBARA:
+        DPRINTF("framebuffer@0x%08X!\n", (unsigned int)val);
+        s->fb = val;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset %x\n", __func__, (int)offset);
+    }
+}
+
+static const MemoryRegionOps ocfb_ops = {
+    .read = ocfb_read,
+    .write = ocfb_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int vmstate_ocfb_post_load(void *opaque, int version_id)
+{
+    OCFBState *s = opaque;
+    /* Make sure we redraw, and at the right size */
+    ocfb_invalidate_display(s);
+    return 0;
+}
+
+static const GraphicHwOps ocfb_gfx_ops = {
+    .invalidate  = ocfb_invalidate_display,
+    .gfx_update  = ocfb_update_display,
+};
+
+static int ocfb_initfn(SysBusDevice *sbd)
+{
+    DeviceState *dev = DEVICE(sbd);
+    OCFBState *s = OCFB(dev);
+
+    memory_region_init_io(&s->iomem, OBJECT(s), &ocfb_ops, s, "ocfb", 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq);
+
+    s->con = graphic_console_init(dev, 0, &ocfb_gfx_ops, s);
+
+    return 0;
+}
+
+static void ocfb_init(Object *obj)
+{
+    OCFBState *s = OCFB(obj);
+
+    s->fb = 0;
+    s->cols = 0;
+    s->rows = 0;
+    s->bpp = 0;
+}
+
+static void ocfb_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = ocfb_initfn;
+    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+    dc->vmsd = &vmstate_ocfb;
+}
+
+static const TypeInfo ocfb_info = {
+    .name          = TYPE_OCFB,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(OCFBState),
+    .instance_init = ocfb_init,
+    .class_init    = ocfb_class_init,
+};
+
+static void ocfb_register_types(void)
+{
+    type_register_static(&ocfb_info);
+}
+
+type_init(ocfb_register_types)
diff --git a/hw/openrisc/openrisc_asim.c b/hw/openrisc/openrisc_asim.c
index 80aa5ed..7752d22 100644
--- a/hw/openrisc/openrisc_asim.c
+++ b/hw/openrisc/openrisc_asim.c
@@ -44,13 +44,15 @@
 enum {
     OR_UART0,
     OR_IDE,
-    OR_OPENETH
+    OR_OPENETH,
+    OR_FRAMEBUFFER
 };
 
 static hwaddr mem_map[] = {
     [OR_UART0] = 0x90000000,
     [OR_IDE] = 0x9e000000,
     [OR_OPENETH] = 0x92000000,
+    [OR_FRAMEBUFFER] = 0x91000000
 };
 
 
@@ -183,6 +185,10 @@ static void openrisc_sim_init(MachineState *machine)
     openrisc_sim_ide_init(get_system_memory(), mem_map[OR_IDE],
                      mem_map[OR_IDE] + 0x100, cpu->env.irq[15]);
 
+    /* OpenCores FrameBuffer device */
+    sysbus_create_simple("ocfb", mem_map[OR_FRAMEBUFFER], cpu->env.irq[8]);
+
+
 
     cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu);
 }
-- 
1.9.1

  parent reply	other threads:[~2014-10-05 11:05 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-05 11:01 [Qemu-devel] [PATCH v3 0/4] target-openrisc: Machine improvements take three Valentin Manea
2014-10-05 11:03 ` [Qemu-devel] [PATCH v3 1/4] target-openrisc: New machine with IDE support Valentin Manea
2014-10-05 12:04   ` Jia Liu
2014-10-05 11:05 ` Valentin Manea [this message]
2014-10-05 12:07   ` [Qemu-devel] [PATCH v3 2/4] hw/display: Add OpenCores FB device support Jia Liu
2014-10-05 11:06 ` [Qemu-devel] [PATCH v3 3/4] hw/input: Add OpenCores keyboard " Valentin Manea
2014-10-05 12:08   ` Jia Liu
2014-10-05 11:07 ` [Qemu-devel] [PATCH v3 4/4] hw/input: Add LPC32XX touchscreen device Valentin Manea
2014-10-05 12:08   ` Jia Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=543125EB.3070900@gmail.com \
    --to=valentin.manea@gmail.com \
    --cc=proljc@gmail.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.