qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 08/18] hw: add QEMU model for Faraday LCD controller


From: Dante
Subject: [Qemu-devel] [PATCH 08/18] hw: add QEMU model for Faraday LCD controller
Date: Fri, 18 Jan 2013 14:30:51 +0800

Signed-off-by: Kuo-Jung Su <address@hidden>
---
 hw/ftlcdc200.c          |  494 +++++++++++++++++++++++++++++++++++++++++++++++
 hw/ftlcdc200.h          |  101 ++++++++++
 hw/ftlcdc200_template.h |  395 +++++++++++++++++++++++++++++++++++++
 3 files changed, 990 insertions(+)
 create mode 100644 hw/ftlcdc200.c
 create mode 100644 hw/ftlcdc200.h
 create mode 100644 hw/ftlcdc200_template.h

diff --git a/hw/ftlcdc200.c b/hw/ftlcdc200.c
new file mode 100644
index 0000000..a221051
--- /dev/null
+++ b/hw/ftlcdc200.c
@@ -0,0 +1,494 @@
+/*
+ * Faraday FTLCDC200 Color LCD Controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su <address@hidden>
+ *
+ * This code is licensed under the GNU LGPL
+ */
+
+#include "sysbus.h"
+#include "ui/console.h"
+#include "framebuffer.h"
+#include "ui/pixel_ops.h"
+
+#include "ftlcdc200.h"
+
+enum ftlcdc200_irqpin {
+    IRQ_GLOBAL = 0,
+    IRQ_VSTATUS,
+    IRQ_BASEUPT,
+    IRQ_FIFOUR,
+    IRQ_BUSERR,
+};
+
+enum ftlcdc200_bppmode {
+    BPP_1 = 0,
+    BPP_2,
+    BPP_4,
+    BPP_8,
+    BPP_16,
+    BPP_32,
+    BPP_16_565,
+    BPP_12,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    DisplayState *ds;
+    qemu_irq irq[5];
+    int cols;
+    int rows;
+    enum ftlcdc200_bppmode bpp;
+    int invalidate;
+    uint32_t palette[256];
+    uint32_t raw_palette[128];
+    
+    /* hw register caches */
+    
+    uint32_t fer;    /* function enable register */
+    uint32_t ppr;    /* panel pixel register */
+    uint32_t ier;    /* interrupt enable register */
+    uint32_t isr;    /* interrupt status register */
+    uint32_t sppr;    /* serail panel pixel register */
+    
+    uint32_t fb[4];    /* frame buffer base address register */
+    uint32_t ht;    /* horizontal timing control register */
+    uint32_t vt0;    /* vertital timing control register 0 */
+    uint32_t vt1;    /* vertital timing control register 1 */
+    uint32_t pol;    /* polarity */
+    
+} ftlcdc200_state;
+
+static int vmstate_ftlcdc200_post_load(void *opaque, int version_id);
+
+static const VMStateDescription vmstate_ftlcdc200 = {
+    .name = "ftlcdc200",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .post_load = vmstate_ftlcdc200_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(cols, ftlcdc200_state),
+        VMSTATE_INT32(rows, ftlcdc200_state),
+        VMSTATE_UINT32(bpp, ftlcdc200_state),
+        VMSTATE_INT32(invalidate, ftlcdc200_state),
+        VMSTATE_UINT32_ARRAY(palette, ftlcdc200_state, 256),
+        VMSTATE_UINT32_ARRAY(raw_palette, ftlcdc200_state, 128),
+        VMSTATE_UINT32(fer, ftlcdc200_state),
+        VMSTATE_UINT32(ppr, ftlcdc200_state),
+        VMSTATE_UINT32(ier, ftlcdc200_state),
+        VMSTATE_UINT32(isr, ftlcdc200_state),
+        VMSTATE_UINT32(sppr, ftlcdc200_state),
+        VMSTATE_UINT32_ARRAY(fb, ftlcdc200_state, 4),
+        VMSTATE_UINT32(ht, ftlcdc200_state),
+        VMSTATE_UINT32(vt0, ftlcdc200_state),
+        VMSTATE_UINT32(vt1, ftlcdc200_state),
+        VMSTATE_UINT32(pol, ftlcdc200_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+#define BITS 8
+#include "ftlcdc200_template.h"
+#define BITS 15
+#include "ftlcdc200_template.h"
+#define BITS 16
+#include "ftlcdc200_template.h"
+#define BITS 24
+#include "ftlcdc200_template.h"
+#define BITS 32
+#include "ftlcdc200_template.h"
+
+static int ftlcdc200_enabled(ftlcdc200_state *s)
+{
+    uint32_t mask = FER_EN | FER_ON;
+    return ((s->fer & mask) == mask) && s->bpp && s->cols && s->rows && 
s->fb[0];
+}
+
+/* Update interrupts.  */
+static inline void ftlcdc200_update_irq(ftlcdc200_state *s)
+{
+    uint32_t mask = s->ier & s->isr;
+    
+    if (mask) {
+        qemu_irq_raise(s->irq[IRQ_GLOBAL]);
+        qemu_set_irq(s->irq[IRQ_FIFOUR],  (mask & 0x01) ? 1 : 0);
+        qemu_set_irq(s->irq[IRQ_BASEUPT], (mask & 0x02) ? 1 : 0);
+        qemu_set_irq(s->irq[IRQ_VSTATUS], (mask & 0x04) ? 1 : 0);
+        qemu_set_irq(s->irq[IRQ_BUSERR],  (mask & 0x08) ? 1 : 0);
+    } else {
+        qemu_irq_lower(s->irq[IRQ_GLOBAL]);
+        qemu_irq_lower(s->irq[IRQ_VSTATUS]);
+        qemu_irq_lower(s->irq[IRQ_BASEUPT]);
+        qemu_irq_lower(s->irq[IRQ_FIFOUR]);
+        qemu_irq_lower(s->irq[IRQ_BUSERR]);
+    }
+}
+
+static void ftlcdc200_update_display(void *opaque)
+{
+    ftlcdc200_state *s = (ftlcdc200_state *)opaque;
+    drawfn* fntable;
+    drawfn fn;
+    int dest_width;
+    int src_width;
+    int bpp_offset;
+    int first;
+    int last;
+
+    if (!ftlcdc200_enabled(s))
+        return;
+        
+    //printf("[qemu] ftlcdc200_update_display: res=%dx%d, fb=0x%08x\n", 
s->cols, s->rows, s->fb[0]);
+
+    switch (ds_get_bits_per_pixel(s->ds)) {
+    case 0:
+        return;
+    case 8:
+        fntable = ftlcdc200_draw_fn_8;
+        dest_width = 1;
+        break;
+    case 15:
+        fntable = ftlcdc200_draw_fn_15;
+        dest_width = 2;
+        break;
+    case 16:
+        fntable = ftlcdc200_draw_fn_16;
+        dest_width = 2;
+        break;
+    case 24:
+        fntable = ftlcdc200_draw_fn_24;
+        dest_width = 3;
+        break;
+    case 32:
+        fntable = ftlcdc200_draw_fn_32;
+        dest_width = 4;
+        break;
+    default:
+        fprintf(stderr, "ftlcdc200: Bad color depth\n");
+        exit(1);
+    }
+    
+#if 1
+    bpp_offset = 0;
+    fn = fntable[s->bpp + bpp_offset];
+#else
+    if (s->ppr & PPR_BGR)
+        bpp_offset = 0;
+    else
+        bpp_offset = 24;
+
+    if ((s->ppr & PPR_ENDIAN_MASK) == PPR_ENDIAN_BBBP)
+        fn = fntable[s->bpp + 8 + bpp_offset];
+    else
+        fn = fntable[s->bpp + bpp_offset];
+#endif
+
+    //printf("[qemu] ftlcdc200_update_display: bpp=%d, ds=%d\n",
+    //    s->bpp, ds_get_bits_per_pixel(s->ds));
+
+    src_width = s->cols;
+    switch (s->bpp) {
+    case BPP_1:
+        src_width >>= 3;
+        break;
+    case BPP_2:
+        src_width >>= 2;
+        break;
+    case BPP_4:
+        src_width >>= 1;
+        break;
+    case BPP_8:
+        break;
+    case BPP_16:
+    case BPP_16_565:
+    case BPP_12:
+        src_width <<= 1;
+        break;
+    case BPP_32:
+        src_width <<= 2;
+        break;
+    }
+    dest_width *= s->cols;
+    first = 0;
+    framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev),
+                               s->fb[0], s->cols, s->rows,
+                               src_width, dest_width, 0,
+                               s->invalidate,
+                               fn, s->palette,
+                               &first, &last);
+    if (s->ier & (IER_VCOMP | IER_NEXTFB)) {
+        s->isr |= (IER_VCOMP | IER_NEXTFB);
+        ftlcdc200_update_irq(s);
+    }
+    if (first >= 0) {
+        dpy_gfx_update(s->ds, 0, first, s->cols, last - first + 1);
+    }
+    s->invalidate = 0;
+}
+
+static void ftlcdc200_invalidate_display(void * opaque)
+{
+    ftlcdc200_state *s = (ftlcdc200_state *)opaque;
+    s->invalidate = 1;
+    if (ftlcdc200_enabled(s)) {
+        qemu_console_resize(s->ds, s->cols, s->rows);
+    }
+}
+
+static void ftlcdc200_update_palette(ftlcdc200_state *s, int n)
+{
+    int i;
+    uint32_t raw;
+    unsigned int r, g, b;
+
+    raw = s->raw_palette[n];
+    n <<= 1;
+    for (i = 0; i < 2; i++) {
+        r = (raw & 0x1f) << 3;
+        raw >>= 5;
+        g = (raw & 0x1f) << 3;
+        raw >>= 5;
+        b = (raw & 0x1f) << 3;
+        /* The I bit is ignored.  */
+        raw >>= 6;
+        switch (ds_get_bits_per_pixel(s->ds)) {
+        case 8:
+            s->palette[n] = rgb_to_pixel8(r, g, b);
+            break;
+        case 15:
+            s->palette[n] = rgb_to_pixel15(r, g, b);
+            break;
+        case 16:
+            s->palette[n] = rgb_to_pixel16(r, g, b);
+            break;
+        case 24:
+        case 32:
+            s->palette[n] = rgb_to_pixel32(r, g, b);
+            break;
+        }
+        n++;
+    }
+}
+
+static void ftlcdc200_resize(ftlcdc200_state *s, int width, int height)
+{
+    if (width != s->cols || height != s->rows) {
+        if (ftlcdc200_enabled(s)) {
+            qemu_console_resize(s->ds, width, height);
+        }
+    }
+    s->cols = width;
+    s->rows = height;
+}
+
+static uint64_t ftlcdc200_mem_read(void *opaque, hwaddr addr,
+                           unsigned size)
+{
+    ftlcdc200_state *s = (ftlcdc200_state *)opaque;
+
+    switch (addr) {
+    case REG_FER:
+        return s->fer;
+    case REG_PPR:
+        return s->ppr;
+    case REG_IER:
+        return s->ier;
+    case REG_ISR:
+        return s->isr;
+    case REG_FB0:
+        return s->fb[0];
+    case REG_FB1:
+        return s->fb[1];
+    case REG_FB2:
+        return s->fb[2];
+    case REG_FB3:
+        return s->fb[3];
+    case REG_HT:
+        return s->ht;
+    case REG_VT0:
+        return s->vt0;
+    case REG_VT1:
+        return s->vt1;
+    case REG_POL:
+        return s->pol;
+    case REG_SPPR:
+        return s->sppr;
+    default:
+        return 0;
+    }
+}
+
+static void ftlcdc200_mem_write(void *opaque, hwaddr addr,
+                        uint64_t val, unsigned size)
+{
+    ftlcdc200_state *s = (ftlcdc200_state *)opaque;
+    int n;
+    
+    /* For simplicity invalidate the display whenever a control register
+       is written to.  */
+    s->invalidate = 1;
+
+    if (addr >= 0xA00 && addr < 0xC00) {
+        /* Palette.  */
+        n = (addr - 0xA00) >> 2;
+        s->raw_palette[(addr - 0xA00) >> 2] = val;
+        ftlcdc200_update_palette(s, n);
+        return;
+    }
+
+    switch (addr) {
+    case REG_FER:
+        s->fer = (uint32_t)val;
+        if (ftlcdc200_enabled(s))
+            qemu_console_resize(s->ds, s->cols, s->rows);
+        break;
+    case REG_PPR:
+        s->ppr = (uint32_t)val;
+        switch(s->ppr & PPR_RGB_MASK) {
+        case PPR_RGB1:
+            s->bpp = BPP_1;
+            break;
+        case PPR_RGB2:
+            s->bpp = BPP_2;
+            break;
+        case PPR_RGB4:
+            s->bpp = BPP_4;
+            break;
+        case PPR_RGB8:
+            s->bpp = BPP_8;
+            break;
+        case PPR_RGB12:
+            s->bpp = BPP_12;
+            break;
+        case PPR_RGB16_555:
+            s->bpp = BPP_16;
+            break;
+        case PPR_RGB16_565:
+            s->bpp = BPP_16_565;
+            break;
+        case PPR_RGB24:
+        default:
+            s->bpp = BPP_32;
+            break;
+        }
+        if (ftlcdc200_enabled(s))
+            qemu_console_resize(s->ds, s->cols, s->rows);
+        break;
+    case REG_IER:
+        s->ier = (uint32_t)val;
+        ftlcdc200_update_irq(s);
+        break;
+    case REG_ISCR:
+        s->isr &= ~((uint32_t)val);
+        ftlcdc200_update_irq(s);
+        break;
+    case REG_FB0:
+        s->fb[0] = (uint32_t)val;
+        break;
+    case REG_FB1:
+        s->fb[1] = (uint32_t)val;
+        break;
+    case REG_FB2:
+        s->fb[2] = (uint32_t)val;
+        break;
+    case REG_FB3:
+        s->fb[3] = (uint32_t)val;
+        break;
+    case REG_HT:
+        s->ht = (uint32_t)val;
+        n = ((s->ht & 0xff) + 1) << 4;
+        ftlcdc200_resize(s, n, s->rows);
+        break;
+    case REG_VT0:
+        s->vt0 = (uint32_t)val;
+        n = (s->vt0 & 0xfff) + 1;
+        ftlcdc200_resize(s, s->cols, n);
+        break;
+    case REG_VT1:
+        s->vt1 = (uint32_t)val;
+        break;
+    case REG_POL:
+        s->pol = (uint32_t)val;
+        break;
+    case REG_SPPR:
+        s->sppr = (uint32_t)val;
+        break;
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps ftlcdc200_ops = {
+    .read  = ftlcdc200_mem_read,
+    .write = ftlcdc200_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int vmstate_ftlcdc200_post_load(void *opaque, int version_id)
+{
+    ftlcdc200_state *s = opaque;
+    /* Make sure we redraw, and at the right size */
+    ftlcdc200_invalidate_display(s);
+    return 0;
+}
+
+static int ftlcdc200_init(SysBusDevice *dev)
+{
+    ftlcdc200_state *s = FROM_SYSBUS(ftlcdc200_state, dev);
+    
+    s->fer   = 0;
+    s->ppr   = 0;
+    s->ier   = 0;
+    s->isr   = 0;
+    s->sppr  = 0;
+    s->fb[0] = 0;
+    s->fb[1] = 0;
+    s->fb[2] = 0;
+    s->fb[3] = 0;
+    s->ht    = 0;
+    s->vt0   = 0;
+    s->vt1   = 0;
+    s->pol   = 0;
+    s->cols  = 0;
+    s->rows  = 0;
+    s->bpp   = 0;
+    s->invalidate = 1;
+
+    memory_region_init_io(&s->iomem, &ftlcdc200_ops, s, "ftlcdc200", 0x10000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq[IRQ_GLOBAL]);
+    sysbus_init_irq(dev, &s->irq[IRQ_VSTATUS]);
+    sysbus_init_irq(dev, &s->irq[IRQ_BASEUPT]);
+    sysbus_init_irq(dev, &s->irq[IRQ_FIFOUR]);
+    sysbus_init_irq(dev, &s->irq[IRQ_BUSERR]);
+    s->ds = graphic_console_init(ftlcdc200_update_display,
+                                 ftlcdc200_invalidate_display,
+                                 NULL, NULL, s);
+    return 0;
+}
+
+static void ftlcdc200_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = ftlcdc200_init;
+    dc->no_user = 1;
+    dc->vmsd = &vmstate_ftlcdc200;
+}
+
+static TypeInfo ftlcdc200_info = {
+    .name          = "ftlcdc200",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(ftlcdc200_state),
+    .class_init    = ftlcdc200_class_init,
+};
+
+static void ftlcdc200_register_types(void)
+{
+    type_register_static(&ftlcdc200_info);
+}
+
+type_init(ftlcdc200_register_types)
diff --git a/hw/ftlcdc200.h b/hw/ftlcdc200.h
new file mode 100644
index 0000000..772f5a7
--- /dev/null
+++ b/hw/ftlcdc200.h
@@ -0,0 +1,101 @@
+#ifndef __FTLCDC2XX_H__
+#define __FTLCDC2XX_H__
+
+/* HW Registers */
+
+#define REG_FER        0x00000
+#define REG_PPR        0x00004
+#define REG_IER        0x00008
+#define REG_ISCR    0x0000C
+#define REG_ISR        0x00010
+#define REG_FB0        0x00018
+#define REG_FB1        0x00024
+#define REG_FB2        0x00030
+#define REG_FB3        0x0003C
+
+#define REG_HT        0x00100
+#define REG_VT0        0x00104
+#define REG_VT1        0x00108
+#define REG_POL        0x0010C
+
+#define REG_SPPR    0x00200
+#define REG_CCIR    0x00204
+
+/* LCD Function Enable Register */
+#define FER_EN        (1 << 0)
+#define FER_ON        (1 << 1)
+#define FER_YUV420    (3 << 2)
+#define FER_YUV422    (2 << 2)
+#define FER_YUV        (1 << 3)
+
+/* LCD Panel Pixel Register */
+#define PPR_BPP_1        (0 << 0)
+#define PPR_BPP_2        (1 << 0)
+#define PPR_BPP_4        (2 << 0)
+#define PPR_BPP_8        (3 << 0)
+#define PPR_BPP_16        (4 << 0)
+#define PPR_BPP_24        (5 << 0)
+#define PPR_BPP_MASK    (7 << 0)
+#define PPR_PWROFF        (1 << 3)
+#define PPR_BGR            (1 << 4)
+#define PPR_ENDIAN_LBLP    (0 << 5)
+#define PPR_ENDIAN_BBBP    (1 << 5)
+#define PPR_ENDIAN_LBBP    (2 << 5)
+#define PPR_ENDIAN_MASK    (3 << 5)
+#define PPR_RGB1        (PPR_BPP_1)
+#define PPR_RGB2        (PPR_BPP_2)
+#define PPR_RGB4        (PPR_BPP_4)
+#define PPR_RGB8        (PPR_BPP_8)
+#define PPR_RGB12        (PPR_BPP_16 | (2 << 7))
+#define PPR_RGB16_555    (PPR_BPP_16 | (1 << 7))
+#define PPR_RGB16_565    (PPR_BPP_16 | (0 << 7))
+#define PPR_RGB24        (PPR_BPP_24)
+#define PPR_RGB32        (PPR_BPP_24)
+#define PPR_RGB_MASK    (PPR_BPP_MASK | (3 << 7))
+#define PPR_VCOMP_VSYNC    (0 << 9)
+#define PPR_VCOMP_VBP    (1 << 9)
+#define PPR_VCOMP_VAIMG    (2 << 9)
+#define PPR_VCOMP_VFP    (3 << 9)
+#define PPR_VCOMP_MASK    (3 << 9)
+
+/* LCD Interrupt Enable Register */
+#define IER_FIFOUR        (1 << 0)
+#define IER_NEXTFB        (1 << 1)
+#define IER_VCOMP        (1 << 2)
+#define IER_BUSERR        (1 << 3)
+
+/* LCD Interrupt Status Register */
+#define ISR_FIFOUR        (1 << 0)
+#define ISR_NEXTFB        (1 << 1)
+#define ISR_VCOMP        (1 << 2)
+#define ISR_BUSERR        (1 << 3)
+
+/* LCD Horizontal Timing Control Register */
+#define HT_HBP(x)        ((((x) - 1) & 0xff) << 24)
+#define HT_HFP(x)        ((((x) - 1) & 0xff) << 16)
+#define HT_HSYNC(x)        ((((x) - 1) & 0xff) << 8)
+#define HT_PL(x)        (((x >> 4) - 1) & 0xff)
+
+/* LCD Vertical Timing Control Register 0 */
+#define VT0_VFP(x)        (((x) & 0xff) << 24)
+#define VT0_VSYNC(x)    ((((x) - 1) & 0x3f) << 16)
+#define VT0_LF(x)        (((x) - 1) & 0xfff)
+
+/* LCD Polarity Control Register */
+#define POL_IVS            (1 << 0)
+#define POL_IHS            (1 << 1)
+#define POL_ICK            (1 << 2)
+#define POL_IDE            (1 << 3)
+#define POL_IPWR        (1 << 4)
+#define POL_DIV(x)        ((((x) - 1) & 0x7f) << 8)
+
+/* LCD Serial Panel Pixel Register */
+#define SPPR_SERIAL        (1 << 0)
+#define SPPR_DELTA        (1 << 1)
+#define SPPR_CS_RGB        (0 << 2)
+#define SPPR_CS_BRG        (1 << 2)
+#define SPPR_CS_GBR        (2 << 2)
+#define SPPR_LSR        (1 << 4)
+#define SPPR_AUO052        (1 << 5)
+
+#endif /* __FTLCDC2XX_H__ */
diff --git a/hw/ftlcdc200_template.h b/hw/ftlcdc200_template.h
new file mode 100644
index 0000000..24c34da
--- /dev/null
+++ b/hw/ftlcdc200_template.h
@@ -0,0 +1,395 @@
+/*
+ * Faraday FTLCDC200 Color LCD Controller
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su <address@hidden>
+ *
+ * This code is licensed under the GNU LGPL
+ *
+ * Framebuffer format conversion routines.
+ */
+
+#ifndef ORDER
+
+#if BITS == 8
+#define COPY_PIXEL(to, from) *(to++) = from
+#elif BITS == 15 || BITS == 16
+#define COPY_PIXEL(to, from) *(uint16_t *)to = from; to += 2;
+#elif BITS == 24
+#define COPY_PIXEL(to, from) \
+  *(to++) = from; *(to++) = (from) >> 8; *(to++) = (from) >> 16
+#elif BITS == 32
+#define COPY_PIXEL(to, from) *(uint32_t *)to = from; to += 4;
+#else
+#error unknown bit depth
+#endif
+
+#undef RGB
+#define BORDER bgr
+#define ORDER 0
+#include "ftlcdc200_template.h"
+#define ORDER 1
+#include "ftlcdc200_template.h"
+#define ORDER 2
+#include "ftlcdc200_template.h"
+#undef BORDER
+#define RGB
+#define BORDER rgb
+#define ORDER 0
+#include "ftlcdc200_template.h"
+#define ORDER 1
+#include "ftlcdc200_template.h"
+#define ORDER 2
+#include "ftlcdc200_template.h"
+#undef BORDER
+
+static drawfn glue(ftlcdc200_draw_fn_,BITS)[48] =
+{
+    glue(ftlcdc200_draw_line1_lblp_bgr,BITS),
+    glue(ftlcdc200_draw_line2_lblp_bgr,BITS),
+    glue(ftlcdc200_draw_line4_lblp_bgr,BITS),
+    glue(ftlcdc200_draw_line8_lblp_bgr,BITS),
+    glue(ftlcdc200_draw_line16_555_lblp_bgr,BITS),
+    glue(ftlcdc200_draw_line32_lblp_bgr,BITS),
+    glue(ftlcdc200_draw_line16_lblp_bgr,BITS),
+    glue(ftlcdc200_draw_line12_lblp_bgr,BITS),
+
+    glue(ftlcdc200_draw_line1_bbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line2_bbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line4_bbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line8_bbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line16_555_bbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line32_bbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line16_bbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line12_bbbp_bgr,BITS),
+
+    glue(ftlcdc200_draw_line1_lbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line2_lbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line4_lbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line8_lbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line16_555_lbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line32_lbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line16_lbbp_bgr,BITS),
+    glue(ftlcdc200_draw_line12_lbbp_bgr,BITS),
+
+    glue(ftlcdc200_draw_line1_lblp_rgb,BITS),
+    glue(ftlcdc200_draw_line2_lblp_rgb,BITS),
+    glue(ftlcdc200_draw_line4_lblp_rgb,BITS),
+    glue(ftlcdc200_draw_line8_lblp_rgb,BITS),
+    glue(ftlcdc200_draw_line16_555_lblp_rgb,BITS),
+    glue(ftlcdc200_draw_line32_lblp_rgb,BITS),
+    glue(ftlcdc200_draw_line16_lblp_rgb,BITS),
+    glue(ftlcdc200_draw_line12_lblp_rgb,BITS),
+
+    glue(ftlcdc200_draw_line1_bbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line2_bbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line4_bbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line8_bbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line16_555_bbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line32_bbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line16_bbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line12_bbbp_rgb,BITS),
+
+    glue(ftlcdc200_draw_line1_lbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line2_lbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line4_lbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line8_lbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line16_555_lbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line32_lbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line16_lbbp_rgb,BITS),
+    glue(ftlcdc200_draw_line12_lbbp_rgb,BITS),
+};
+
+#undef BITS
+#undef COPY_PIXEL
+
+#else
+
+#if ORDER == 0
+#define NAME glue(glue(lblp_, BORDER), BITS)
+#ifdef HOST_WORDS_BIGENDIAN
+#define SWAP_WORDS 1
+#endif
+#elif ORDER == 1
+#define NAME glue(glue(bbbp_, BORDER), BITS)
+#ifndef HOST_WORDS_BIGENDIAN
+#define SWAP_WORDS 1
+#endif
+#else
+#define SWAP_PIXELS 1
+#define NAME glue(glue(lbbp_, BORDER), BITS)
+#ifdef HOST_WORDS_BIGENDIAN
+#define SWAP_WORDS 1
+#endif
+#endif
+
+#define FN_2(x, y) FN(x, y) FN(x+1, y)
+#define FN_4(x, y) FN_2(x, y) FN_2(x+2, y)
+#define FN_8(y) FN_4(0, y) FN_4(4, y)
+
+static void glue(ftlcdc200_draw_line1_,NAME)(void *opaque, uint8_t *d, const 
uint8_t *src, int width, int deststep)
+{
+    uint32_t *palette = opaque;
+    uint32_t data;
+    while (width > 0) {
+        data = *(uint32_t *)src;
+#ifdef SWAP_PIXELS
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 7 - (x))) & 1]);
+#else
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x) + y)) & 1]);
+#endif
+#ifdef SWAP_WORDS
+        FN_8(24)
+        FN_8(16)
+        FN_8(8)
+        FN_8(0)
+#else
+        FN_8(0)
+        FN_8(8)
+        FN_8(16)
+        FN_8(24)
+#endif
+#undef FN
+        width -= 32;
+        src += 4;
+    }
+}
+
+static void glue(ftlcdc200_draw_line2_,NAME)(void *opaque, uint8_t *d, const 
uint8_t *src, int width, int deststep)
+{
+    uint32_t *palette = opaque;
+    uint32_t data;
+    while (width > 0) {
+        data = *(uint32_t *)src;
+#ifdef SWAP_PIXELS
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 6 - (x)*2)) & 3]);
+#else
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*2 + y)) & 3]);
+#endif
+#ifdef SWAP_WORDS
+        FN_4(0, 24)
+        FN_4(0, 16)
+        FN_4(0, 8)
+        FN_4(0, 0)
+#else
+        FN_4(0, 0)
+        FN_4(0, 8)
+        FN_4(0, 16)
+        FN_4(0, 24)
+#endif
+#undef FN
+        width -= 16;
+        src += 4;
+    }
+}
+
+static void glue(ftlcdc200_draw_line4_,NAME)(void *opaque, uint8_t *d, const 
uint8_t *src, int width, int deststep)
+{
+    uint32_t *palette = opaque;
+    uint32_t data;
+    while (width > 0) {
+        data = *(uint32_t *)src;
+#ifdef SWAP_PIXELS
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 4 - (x)*4)) & 0xf]);
+#else
+#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*4 + y)) & 0xf]);
+#endif
+#ifdef SWAP_WORDS
+        FN_2(0, 24)
+        FN_2(0, 16)
+        FN_2(0, 8)
+        FN_2(0, 0)
+#else
+        FN_2(0, 0)
+        FN_2(0, 8)
+        FN_2(0, 16)
+        FN_2(0, 24)
+#endif
+#undef FN
+        width -= 8;
+        src += 4;
+    }
+}
+
+static void glue(ftlcdc200_draw_line8_,NAME)(void *opaque, uint8_t *d, const 
uint8_t *src, int width, int deststep)
+{
+    uint32_t *palette = opaque;
+    uint32_t data;
+    while (width > 0) {
+        data = *(uint32_t *)src;
+#define FN(x) COPY_PIXEL(d, palette[(data >> (x)) & 0xff]);
+#ifdef SWAP_WORDS
+        FN(24)
+        FN(16)
+        FN(8)
+        FN(0)
+#else
+        FN(0)
+        FN(8)
+        FN(16)
+        FN(24)
+#endif
+#undef FN
+        width -= 4;
+        src += 4;
+    }
+}
+
+static void glue(ftlcdc200_draw_line16_,NAME)(void *opaque, uint8_t *d, const 
uint8_t *src, int width, int deststep)
+{
+    uint32_t data;
+    unsigned int r, g, b;
+    while (width > 0) {
+        data = *(uint32_t *)src;
+#ifdef SWAP_WORDS
+        data = bswap32(data);
+#endif
+#ifdef RGB
+#define LSB r
+#define MSB b
+#else
+#define LSB b
+#define MSB r
+#endif
+#if 0
+        LSB = data & 0x1f;
+        data >>= 5;
+        g = data & 0x3f;
+        data >>= 6;
+        MSB = data & 0x1f;
+        data >>= 5;
+#else
+        LSB = (data & 0x1f) << 3;
+        data >>= 5;
+        g = (data & 0x3f) << 2;
+        data >>= 6;
+        MSB = (data & 0x1f) << 3;
+        data >>= 5;
+#endif
+        COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+        LSB = (data & 0x1f) << 3;
+        data >>= 5;
+        g = (data & 0x3f) << 2;
+        data >>= 6;
+        MSB = (data & 0x1f) << 3;
+        data >>= 5;
+        COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+#undef MSB
+#undef LSB
+        width -= 2;
+        src += 4;
+    }
+}
+
+static void glue(ftlcdc200_draw_line32_,NAME)(void *opaque, uint8_t *d, const 
uint8_t *src, int width, int deststep)
+{
+    uint32_t data;
+    unsigned int r, g, b;
+    while (width > 0) {
+        data = *(uint32_t *)src;
+#ifdef RGB
+#define LSB r
+#define MSB b
+#else
+#define LSB b
+#define MSB r
+#endif
+#ifndef SWAP_WORDS
+        LSB = data & 0xff;
+        g = (data >> 8) & 0xff;
+        MSB = (data >> 16) & 0xff;
+#else
+        LSB = (data >> 24) & 0xff;
+        g = (data >> 16) & 0xff;
+        MSB = (data >> 8) & 0xff;
+#endif
+        COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+#undef MSB
+#undef LSB
+        width--;
+        src += 4;
+    }
+}
+
+static void glue(ftlcdc200_draw_line16_555_,NAME)(void *opaque, uint8_t *d, 
const uint8_t *src, int width, int deststep)
+{
+    /* RGB 555 plus an intensity bit (which we ignore) */
+    uint32_t data;
+    unsigned int r, g, b;
+    while (width > 0) {
+        data = *(uint32_t *)src;
+#ifdef SWAP_WORDS
+        data = bswap32(data);
+#endif
+#ifdef RGB
+#define LSB r
+#define MSB b
+#else
+#define LSB b
+#define MSB r
+#endif
+        LSB = (data & 0x1f) << 3;
+        data >>= 5;
+        g = (data & 0x1f) << 3;
+        data >>= 5;
+        MSB = (data & 0x1f) << 3;
+        data >>= 5;
+        COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+        LSB = (data & 0x1f) << 3;
+        data >>= 5;
+        g = (data & 0x1f) << 3;
+        data >>= 5;
+        MSB = (data & 0x1f) << 3;
+        data >>= 6;
+        COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+#undef MSB
+#undef LSB
+        width -= 2;
+        src += 4;
+    }
+}
+
+static void glue(ftlcdc200_draw_line12_,NAME)(void *opaque, uint8_t *d, const 
uint8_t *src, int width, int deststep)
+{
+    /* RGB 444 with 4 bits of zeroes at the top of each halfword */
+    uint32_t data;
+    unsigned int r, g, b;
+    while (width > 0) {
+        data = *(uint32_t *)src;
+#ifdef SWAP_WORDS
+        data = bswap32(data);
+#endif
+#ifdef RGB
+#define LSB r
+#define MSB b
+#else
+#define LSB b
+#define MSB r
+#endif
+        LSB = (data & 0xf) << 4;
+        data >>= 4;
+        g = (data & 0xf) << 4;
+        data >>= 4;
+        MSB = (data & 0xf) << 4;
+        data >>= 8;
+        COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+        LSB = (data & 0xf) << 4;
+        data >>= 4;
+        g = (data & 0xf) << 4;
+        data >>= 4;
+        MSB = (data & 0xf) << 4;
+        data >>= 8;
+        COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
+#undef MSB
+#undef LSB
+        width -= 2;
+        src += 4;
+    }
+}
+
+#undef SWAP_PIXELS
+#undef NAME
+#undef SWAP_WORDS
+#undef ORDER
+
+#endif
-- 
1.7.9.5


********************* Confidentiality Notice ************************
This electronic message and any attachments may contain
confidential and legally privileged information or
information which is otherwise protected from disclosure.
If you are not the intended recipient,please do not disclose
the contents, either in whole or in part, to anyone,and
immediately delete the message and any attachments from
your computer system and destroy all hard copies.
Thank you for your cooperation.
***********************************************************************




reply via email to

[Prev in Thread] Current Thread [Next in Thread]