All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode
@ 2011-07-22 15:59 Peter Maydell
  2011-07-22 15:59 ` [Qemu-devel] [PATCH 1/3] hw/pl110: Model the PL111 CLCD controller Peter Maydell
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Peter Maydell @ 2011-07-22 15:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

This patch series improves the emulation of the PL11x CLCD
controllers used by the various ARM dev boards.

vexpress-a9, realview-eb, realview-eb-mpcore, realview-pb-a8
and realview-pbx-a9 should all have a PL111, not a PL110;
the PL111 implements two extra pixel formats.
(I haven't implemented the hardware cursor support in the PL111;
we didn't implement it in the "pl110_versatile" either; Linux doesn't
use it, anyway.)

versatilepb has a PL110 but it also has an external mux controlled
by a system register which allows the OS to select whether the
16 bit graphics format should be 5551, RGB565 or BGR565.

In particular, Linux kernels 2.6.39 and above default to programming
the versatilepb for BGR565, so we need to support the mux control
rather than always assuming RGB565.

This is a bit of a cross between a new feature and a bug fix; my
guess is "not for 0.15" but if enough people complain about the
graphics being busted in versatilepb then it will end up in 0.15.1...


Peter Maydell (3):
  hw/pl110: Model the PL111 CLCD controller
  versatilepb: Implement SYS_CLCD mux control register bits
  vexpress, realview: Use pl111, not pl110

 hw/arm_sysctl.c     |   49 ++++++++++++++++++++-
 hw/pl110.c          |  115 ++++++++++++++++++++++++++++++++++++++++++--------
 hw/pl110_template.h |  102 ++++++++++++++++++++++++++++++++++++++++++---
 hw/realview.c       |    2 +-
 hw/syborg_fb.c      |   15 +++++-
 hw/versatilepb.c    |   13 ++++-
 hw/vexpress.c       |    2 +-
 7 files changed, 261 insertions(+), 37 deletions(-)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 1/3] hw/pl110: Model the PL111 CLCD controller
  2011-07-22 15:59 [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode Peter Maydell
@ 2011-07-22 15:59 ` Peter Maydell
  2011-07-22 15:59 ` [Qemu-devel] [PATCH 2/3] versatilepb: Implement SYS_CLCD mux control register bits Peter Maydell
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Peter Maydell @ 2011-07-22 15:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

Model the PL111 CLCD controller. This is a minor variation
on the PL110; the major programmer visible differences are
support for hardware cursor (unimplemented) and two new
pixel formats.

Since syborg_fb.c borrows the pl11x pixel drawing routines,
we also update it to cope with the new slightly larger array
of function pointers.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/pl110.c          |   94 ++++++++++++++++++++++++++++++++++++++---------
 hw/pl110_template.h |  102 +++++++++++++++++++++++++++++++++++++++++++++++---
 hw/syborg_fb.c      |   15 ++++++-
 3 files changed, 183 insertions(+), 28 deletions(-)

diff --git a/hw/pl110.c b/hw/pl110.c
index 06d2dfa..f931fb1 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -24,15 +24,25 @@ enum pl110_bppmode
     BPP_4,
     BPP_8,
     BPP_16,
-    BPP_32
+    BPP_32,
+    BPP_16_565, /* PL111 only */
+    BPP_12      /* PL111 only */
+};
+
+
+/* The Versatile/PB uses a slightly modified PL110 controller.  */
+enum pl110_version
+{
+    PL110,
+    PL110_VERSATILE,
+    PL111
 };
 
 typedef struct {
     SysBusDevice busdev;
     DisplayState *ds;
 
-    /* The Versatile/PB uses a slightly modified PL110 controller.  */
-    int versatile;
+    int version;
     uint32_t timing[4];
     uint32_t cr;
     uint32_t upbase;
@@ -53,7 +63,7 @@ static const VMStateDescription vmstate_pl110 = {
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_INT32(versatile, pl110_state),
+        VMSTATE_INT32(version, pl110_state),
         VMSTATE_UINT32_ARRAY(timing, pl110_state, 4),
         VMSTATE_UINT32(cr, pl110_state),
         VMSTATE_UINT32(upbase, pl110_state),
@@ -82,6 +92,17 @@ static const unsigned char pl110_versatile_id[] =
 #define pl110_versatile_id pl110_id
 #endif
 
+static const unsigned char pl111_id[] = {
+    0x11, 0x11, 0x24, 0x00, 0x0d, 0xf0, 0x05, 0xb1
+};
+
+/* Indexed by pl110_version */
+static const unsigned char *idregs[] = {
+    pl110_id,
+    pl110_versatile_id,
+    pl111_id
+};
+
 #include "pixel_ops.h"
 
 #define BITS 8
@@ -144,12 +165,30 @@ static void pl110_update_display(void *opaque)
     if (s->cr & PL110_CR_BGR)
         bpp_offset = 0;
     else
-        bpp_offset = 18;
+        bpp_offset = 24;
+
+    if ((s->version != PL111) && (s->bpp == BPP_16)) {
+        /* The PL110's native 16 bit mode is 5551; however
+         * most boards with a PL110 implement an external
+         * mux which allows bits to be reshuffled to give
+         * 565 format. The mux is typically controlled by
+         * an external system register.
+         * This should be controlled by a GPIO input pin
+         * so boards can wire it up to their register.
+         * For now, force 16 bit to be 565, to match
+         * previous QEMU PL110 model behaviour.
+         *
+         * The PL111 straightforwardly implements both
+         * 5551 and 565 under control of the bpp field
+         * in the LCDControl register.
+         */
+        bpp_offset += (BPP_16_565 - BPP_16);
+    }
 
     if (s->cr & PL110_CR_BEBO)
-        fn = fntable[s->bpp + 6 + bpp_offset];
+        fn = fntable[s->bpp + 8 + bpp_offset];
     else if (s->cr & PL110_CR_BEPO)
-        fn = fntable[s->bpp + 12 + bpp_offset];
+        fn = fntable[s->bpp + 16 + bpp_offset];
     else
         fn = fntable[s->bpp + bpp_offset];
 
@@ -167,6 +206,8 @@ static void pl110_update_display(void *opaque)
     case BPP_8:
         break;
     case BPP_16:
+    case BPP_16_565:
+    case BPP_12:
         src_width <<= 1;
         break;
     case BPP_32:
@@ -253,10 +294,7 @@ static uint32_t pl110_read(void *opaque, target_phys_addr_t offset)
     pl110_state *s = (pl110_state *)opaque;
 
     if (offset >= 0xfe0 && offset < 0x1000) {
-        if (s->versatile)
-            return pl110_versatile_id[(offset - 0xfe0) >> 2];
-        else
-            return pl110_id[(offset - 0xfe0) >> 2];
+        return idregs[s->version][(offset - 0xfe0) >> 2];
     }
     if (offset >= 0x200 && offset < 0x400) {
         return s->raw_pallette[(offset - 0x200) >> 2];
@@ -275,12 +313,14 @@ static uint32_t pl110_read(void *opaque, target_phys_addr_t offset)
     case 5: /* LCDLPBASE */
         return s->lpbase;
     case 6: /* LCDIMSC */
-	if (s->versatile)
-	  return s->cr;
+        if (s->version != PL110) {
+            return s->cr;
+        }
         return s->int_mask;
     case 7: /* LCDControl */
-	if (s->versatile)
-	  return s->int_mask;
+        if (s->version != PL110) {
+            return s->int_mask;
+        }
         return s->cr;
     case 8: /* LCDRIS */
         return s->int_status;
@@ -337,15 +377,17 @@ static void pl110_write(void *opaque, target_phys_addr_t offset,
         s->lpbase = val;
         break;
     case 6: /* LCDIMSC */
-        if (s->versatile)
+        if (s->version != PL110) {
             goto control;
+        }
     imsc:
         s->int_mask = val;
         pl110_update(s);
         break;
     case 7: /* LCDControl */
-        if (s->versatile)
+        if (s->version != PL110) {
             goto imsc;
+        }
     control:
         s->cr = val;
         s->bpp = (val >> 1) & 7;
@@ -393,7 +435,14 @@ static int pl110_init(SysBusDevice *dev)
 static int pl110_versatile_init(SysBusDevice *dev)
 {
     pl110_state *s = FROM_SYSBUS(pl110_state, dev);
-    s->versatile = 1;
+    s->version = PL110_VERSATILE;
+    return pl110_init(dev);
+}
+
+static int pl111_init(SysBusDevice *dev)
+{
+    pl110_state *s = FROM_SYSBUS(pl110_state, dev);
+    s->version = PL111;
     return pl110_init(dev);
 }
 
@@ -413,10 +462,19 @@ static SysBusDeviceInfo pl110_versatile_info = {
     .qdev.no_user = 1,
 };
 
+static SysBusDeviceInfo pl111_info = {
+    .init = pl111_init,
+    .qdev.name = "pl111",
+    .qdev.size = sizeof(pl110_state),
+    .qdev.vmsd = &vmstate_pl110,
+    .qdev.no_user = 1,
+};
+
 static void pl110_register_devices(void)
 {
     sysbus_register_withprop(&pl110_info);
     sysbus_register_withprop(&pl110_versatile_info);
+    sysbus_register_withprop(&pl111_info);
 }
 
 device_init(pl110_register_devices)
diff --git a/hw/pl110_template.h b/hw/pl110_template.h
index b3c9077..93671f2 100644
--- a/hw/pl110_template.h
+++ b/hw/pl110_template.h
@@ -43,49 +43,61 @@
 #include "pl110_template.h"
 #undef BORDER
 
-static drawfn glue(pl110_draw_fn_,BITS)[36] =
+static drawfn glue(pl110_draw_fn_,BITS)[48] =
 {
     glue(pl110_draw_line1_lblp_bgr,BITS),
     glue(pl110_draw_line2_lblp_bgr,BITS),
     glue(pl110_draw_line4_lblp_bgr,BITS),
     glue(pl110_draw_line8_lblp_bgr,BITS),
-    glue(pl110_draw_line16_lblp_bgr,BITS),
+    glue(pl110_draw_line16_555_lblp_bgr,BITS),
     glue(pl110_draw_line32_lblp_bgr,BITS),
+    glue(pl110_draw_line16_lblp_bgr,BITS),
+    glue(pl110_draw_line12_lblp_bgr,BITS),
 
     glue(pl110_draw_line1_bbbp_bgr,BITS),
     glue(pl110_draw_line2_bbbp_bgr,BITS),
     glue(pl110_draw_line4_bbbp_bgr,BITS),
     glue(pl110_draw_line8_bbbp_bgr,BITS),
-    glue(pl110_draw_line16_bbbp_bgr,BITS),
+    glue(pl110_draw_line16_555_bbbp_bgr,BITS),
     glue(pl110_draw_line32_bbbp_bgr,BITS),
+    glue(pl110_draw_line16_bbbp_bgr,BITS),
+    glue(pl110_draw_line12_bbbp_bgr,BITS),
 
     glue(pl110_draw_line1_lbbp_bgr,BITS),
     glue(pl110_draw_line2_lbbp_bgr,BITS),
     glue(pl110_draw_line4_lbbp_bgr,BITS),
     glue(pl110_draw_line8_lbbp_bgr,BITS),
-    glue(pl110_draw_line16_lbbp_bgr,BITS),
+    glue(pl110_draw_line16_555_lbbp_bgr,BITS),
     glue(pl110_draw_line32_lbbp_bgr,BITS),
+    glue(pl110_draw_line16_lbbp_bgr,BITS),
+    glue(pl110_draw_line12_lbbp_bgr,BITS),
 
     glue(pl110_draw_line1_lblp_rgb,BITS),
     glue(pl110_draw_line2_lblp_rgb,BITS),
     glue(pl110_draw_line4_lblp_rgb,BITS),
     glue(pl110_draw_line8_lblp_rgb,BITS),
-    glue(pl110_draw_line16_lblp_rgb,BITS),
+    glue(pl110_draw_line16_555_lblp_rgb,BITS),
     glue(pl110_draw_line32_lblp_rgb,BITS),
+    glue(pl110_draw_line16_lblp_rgb,BITS),
+    glue(pl110_draw_line12_lblp_rgb,BITS),
 
     glue(pl110_draw_line1_bbbp_rgb,BITS),
     glue(pl110_draw_line2_bbbp_rgb,BITS),
     glue(pl110_draw_line4_bbbp_rgb,BITS),
     glue(pl110_draw_line8_bbbp_rgb,BITS),
-    glue(pl110_draw_line16_bbbp_rgb,BITS),
+    glue(pl110_draw_line16_555_bbbp_rgb,BITS),
     glue(pl110_draw_line32_bbbp_rgb,BITS),
+    glue(pl110_draw_line16_bbbp_rgb,BITS),
+    glue(pl110_draw_line12_bbbp_rgb,BITS),
 
     glue(pl110_draw_line1_lbbp_rgb,BITS),
     glue(pl110_draw_line2_lbbp_rgb,BITS),
     glue(pl110_draw_line4_lbbp_rgb,BITS),
     glue(pl110_draw_line8_lbbp_rgb,BITS),
-    glue(pl110_draw_line16_lbbp_rgb,BITS),
+    glue(pl110_draw_line16_555_lbbp_rgb,BITS),
     glue(pl110_draw_line32_lbbp_rgb,BITS),
+    glue(pl110_draw_line16_lbbp_rgb,BITS),
+    glue(pl110_draw_line12_lbbp_rgb,BITS),
 };
 
 #undef BITS
@@ -299,6 +311,82 @@ static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_
     }
 }
 
+static void glue(pl110_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(pl110_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
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index 7e37364..ae3e0eb 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -217,15 +217,24 @@ static void syborg_fb_update_display(void *opaque)
     }
 
     if (s->rgb) {
-        bpp_offset = 18;
+        bpp_offset = 24;
     } else {
         bpp_offset = 0;
     }
     if (s->endian) {
+        bpp_offset += 8;
+    }
+    /* Our bpp constants mostly match the PL110/PL111 but
+     * not for the 16 bit case
+     */
+    switch (s->bpp) {
+    case BPP_SRC_16:
         bpp_offset += 6;
+        break;
+    default:
+        bpp_offset += s->bpp;
     }
-
-    fn = fntable[s->bpp + bpp_offset];
+    fn = fntable[bpp_offset];
 
     if (s->pitch) {
         src_width = s->pitch;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 2/3] versatilepb: Implement SYS_CLCD mux control register bits
  2011-07-22 15:59 [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode Peter Maydell
  2011-07-22 15:59 ` [Qemu-devel] [PATCH 1/3] hw/pl110: Model the PL111 CLCD controller Peter Maydell
@ 2011-07-22 15:59 ` Peter Maydell
  2011-07-22 15:59 ` [Qemu-devel] [PATCH 3/3] vexpress, realview: Use pl111, not pl110 Peter Maydell
  2011-07-26 10:12 ` [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode Peter Maydell
  3 siblings, 0 replies; 6+ messages in thread
From: Peter Maydell @ 2011-07-22 15:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

On the Versatile PB, PL110 graphics adaptor only natively supports
5551 pixel format; an external mux swaps bits around to allow
RGB565 and BGR565, under the control of bits [1:0] in the SYS_CLCD
system register.

Implement these SYS_CLCD register bits, and use a gpio line to
feed them out of the system register model, across the versatilepb
board and into the pl110 so we can select the right format.

This is necessary as recent Linux versatile kernels default to
programming the CLCD and mux for 16 bit BGR rather than 16 bit RGB.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm_sysctl.c  |   49 ++++++++++++++++++++++++++++++++++++++++++++++---
 hw/pl110.c       |   29 ++++++++++++++++++++++++-----
 hw/versatilepb.c |   13 ++++++++++---
 3 files changed, 80 insertions(+), 11 deletions(-)

diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 9225b58..d1ea3ef 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -17,6 +17,8 @@
 
 typedef struct {
     SysBusDevice busdev;
+    qemu_irq pl110_mux_ctrl;
+
     uint32_t sys_id;
     uint32_t leds;
     uint16_t lockval;
@@ -30,11 +32,12 @@ typedef struct {
     uint32_t sys_cfgdata;
     uint32_t sys_cfgctrl;
     uint32_t sys_cfgstat;
+    uint32_t sys_clcd;
 } arm_sysctl_state;
 
 static const VMStateDescription vmstate_arm_sysctl = {
     .name = "realview_sysctl",
-    .version_id = 2,
+    .version_id = 3,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(leds, arm_sysctl_state),
@@ -48,6 +51,7 @@ static const VMStateDescription vmstate_arm_sysctl = {
         VMSTATE_UINT32_V(sys_cfgdata, arm_sysctl_state, 2),
         VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2),
         VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2),
+        VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -78,6 +82,13 @@ static void arm_sysctl_reset(DeviceState *d)
     s->cfgdata2 = 0;
     s->flags = 0;
     s->resetlevel = 0;
+    if (board_id(s) == BOARD_ID_VEXPRESS) {
+        /* On VExpress this register will RAZ/WI */
+        s->sys_clcd = 0;
+    } else {
+        /* All others: CLCDID 0x1f, indicating VGA */
+        s->sys_clcd = 0x1f00;
+    }
 }
 
 static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
@@ -124,7 +135,7 @@ static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
     case 0x4c: /* FLASH */
         return 0;
     case 0x50: /* CLCD */
-        return 0x1000;
+        return s->sys_clcd;
     case 0x54: /* CLCDSER */
         return 0;
     case 0x58: /* BOOTCS */
@@ -232,7 +243,39 @@ static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
         /* nothing to do.  */
         break;
     case 0x4c: /* FLASH */
+        break;
     case 0x50: /* CLCD */
+        switch (board_id(s)) {
+        case BOARD_ID_PB926:
+            /* On 926 bits 13:8 are R/O, bits 1:0 control
+             * the mux that defines how to interpret the PL110
+             * graphics format, and other bits are r/w but we
+             * don't implement them to do anything.
+             */
+            s->sys_clcd &= 0x3f00;
+            s->sys_clcd |= val & ~0x3f00;
+            qemu_set_irq(s->pl110_mux_ctrl, val & 3);
+            break;
+        case BOARD_ID_EB:
+            /* The EB is the same except that there is no mux since
+             * the EB has a PL111.
+             */
+            s->sys_clcd &= 0x3f00;
+            s->sys_clcd |= val & ~0x3f00;
+            break;
+        case BOARD_ID_PBA8:
+        case BOARD_ID_PBX:
+            /* On PBA8 and PBX bit 7 is r/w and all other bits
+             * are either r/o or RAZ/WI.
+             */
+            s->sys_clcd &= (1 << 7);
+            s->sys_clcd |= val & ~(1 << 7);
+            break;
+        case BOARD_ID_VEXPRESS:
+        default:
+            /* On VExpress this register is unimplemented and will RAZ/WI */
+            break;
+        }
     case 0x54: /* CLCDSER */
     case 0x64: /* DMAPSR0 */
     case 0x68: /* DMAPSR1 */
@@ -334,7 +377,7 @@ static int arm_sysctl_init1(SysBusDevice *dev)
                                        DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2);
-    /* ??? Save/restore.  */
+    qdev_init_gpio_out(&s->busdev.qdev, &s->pl110_mux_ctrl, 1);
     return 0;
 }
 
diff --git a/hw/pl110.c b/hw/pl110.c
index f931fb1..1a0145c 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -53,6 +53,7 @@ typedef struct {
     int rows;
     enum pl110_bppmode bpp;
     int invalidate;
+    uint32_t mux_ctrl;
     uint32_t pallette[256];
     uint32_t raw_pallette[128];
     qemu_irq irq;
@@ -60,7 +61,7 @@ typedef struct {
 
 static const VMStateDescription vmstate_pl110 = {
     .name = "pl110",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
         VMSTATE_INT32(version, pl110_state),
@@ -76,6 +77,7 @@ static const VMStateDescription vmstate_pl110 = {
         VMSTATE_INT32(invalidate, pl110_state),
         VMSTATE_UINT32_ARRAY(pallette, pl110_state, 256),
         VMSTATE_UINT32_ARRAY(raw_pallette, pl110_state, 128),
+        VMSTATE_UINT32_V(mux_ctrl, pl110_state, 2),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -173,16 +175,26 @@ static void pl110_update_display(void *opaque)
          * mux which allows bits to be reshuffled to give
          * 565 format. The mux is typically controlled by
          * an external system register.
-         * This should be controlled by a GPIO input pin
+         * This is controlled by a GPIO input pin
          * so boards can wire it up to their register.
-         * For now, force 16 bit to be 565, to match
-         * previous QEMU PL110 model behaviour.
          *
          * The PL111 straightforwardly implements both
          * 5551 and 565 under control of the bpp field
          * in the LCDControl register.
          */
-        bpp_offset += (BPP_16_565 - BPP_16);
+        switch (s->mux_ctrl) {
+        case 3: /* 565 BGR */
+            bpp_offset = (BPP_16_565 - BPP_16);
+            break;
+        case 1: /* 5551 */
+            break;
+        case 0: /* 888; also if we have loaded vmstate from an old version */
+        case 2: /* 565 RGB */
+        default:
+            /* treat as 565 but honour BGR bit */
+            bpp_offset += (BPP_16_565 - BPP_16);
+            break;
+        }
     }
 
     if (s->cr & PL110_CR_BEBO)
@@ -416,6 +428,12 @@ static CPUWriteMemoryFunc * const pl110_writefn[] = {
    pl110_write
 };
 
+static void pl110_mux_ctrl_set(void *opaque, int line, int level)
+{
+    pl110_state *s = (pl110_state *)opaque;
+    s->mux_ctrl = level;
+}
+
 static int pl110_init(SysBusDevice *dev)
 {
     pl110_state *s = FROM_SYSBUS(pl110_state, dev);
@@ -426,6 +444,7 @@ static int pl110_init(SysBusDevice *dev)
                                        DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     sysbus_init_irq(dev, &s->irq);
+    qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1);
     s->ds = graphic_console_init(pl110_update_display,
                                  pl110_invalidate_display,
                                  NULL, NULL, s);
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 46b6a3f..eba0db1 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -180,7 +180,7 @@ static void versatile_init(ram_addr_t ram_size,
     qemu_irq *cpu_pic;
     qemu_irq pic[32];
     qemu_irq sic[32];
-    DeviceState *dev;
+    DeviceState *dev, *sysctl;
     PCIBus *pci_bus;
     NICInfo *nd;
     int n;
@@ -198,7 +198,12 @@ static void versatile_init(ram_addr_t ram_size,
     /* SDRAM at address zero.  */
     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 
-    arm_sysctl_init(0x10000000, 0x41007004, 0x02000000);
+    sysctl = qdev_create(NULL, "realview_sysctl");
+    qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
+    qdev_init_nofail(sysctl);
+    qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000);
+    sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
+
     cpu_pic = arm_pic_init_cpu(env);
     dev = sysbus_create_varargs("pl190", 0x10140000,
                                 cpu_pic[0], cpu_pic[1], NULL);
@@ -250,7 +255,9 @@ static void versatile_init(ram_addr_t ram_size,
 
     /* The versatile/PB actually has a modified Color LCD controller
        that includes hardware cursor support from the PL111.  */
-    sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
+    dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
+    /* Wire up the mux control signals from the SYS_CLCD register */
+    qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
 
     sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
     sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 3/3] vexpress, realview: Use pl111, not pl110
  2011-07-22 15:59 [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode Peter Maydell
  2011-07-22 15:59 ` [Qemu-devel] [PATCH 1/3] hw/pl110: Model the PL111 CLCD controller Peter Maydell
  2011-07-22 15:59 ` [Qemu-devel] [PATCH 2/3] versatilepb: Implement SYS_CLCD mux control register bits Peter Maydell
@ 2011-07-22 15:59 ` Peter Maydell
  2011-07-26 10:12 ` [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode Peter Maydell
  3 siblings, 0 replies; 6+ messages in thread
From: Peter Maydell @ 2011-07-22 15:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: patches

The Versatile Express, Realview EB, PBX A9 and PB A8 boards all
use a PL111 for their graphics, not a PL110. Now we model the
PL111, use it on these board models.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/realview.c |    2 +-
 hw/vexpress.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/realview.c b/hw/realview.c
index 82f3d82..c789739 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -251,7 +251,7 @@ static void realview_init(ram_addr_t ram_size,
     sysbus_create_simple("pl061", 0x10014000, pic[7]);
     gpio2 = sysbus_create_simple("pl061", 0x10015000, pic[8]);
 
-    sysbus_create_simple("pl110_versatile", 0x10020000, pic[23]);
+    sysbus_create_simple("pl111", 0x10020000, pic[23]);
 
     dev = sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL);
     /* Wire up MMC card detect and read-only signals. These have
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 9ffd332..c9766dd 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -150,7 +150,7 @@ static void vexpress_a9_init(ram_addr_t ram_size,
     /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
 
     /* 0x10020000 PL111 CLCD (daughterboard) */
-    sysbus_create_simple("pl110", 0x10020000, pic[44]);
+    sysbus_create_simple("pl111", 0x10020000, pic[44]);
 
     /* 0x10060000 AXI RAM */
     /* 0x100e0000 PL341 Dynamic Memory Controller */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode
  2011-07-22 15:59 [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode Peter Maydell
                   ` (2 preceding siblings ...)
  2011-07-22 15:59 ` [Qemu-devel] [PATCH 3/3] vexpress, realview: Use pl111, not pl110 Peter Maydell
@ 2011-07-26 10:12 ` Peter Maydell
  2011-07-26 11:59   ` Francis Moreau
  3 siblings, 1 reply; 6+ messages in thread
From: Peter Maydell @ 2011-07-26 10:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Francis Moreau, patches

On 22 July 2011 16:59, Peter Maydell <peter.maydell@linaro.org> wrote:
> This patch series improves the emulation of the PL11x CLCD
> controllers used by the various ARM dev boards.

> versatilepb has a PL110 but it also has an external mux controlled
> by a system register which allows the OS to select whether the
> 16 bit graphics format should be 5551, RGB565 or BGR565.
>
> In particular, Linux kernels 2.6.39 and above default to programming
> the versatilepb for BGR565, so we need to support the mux control
> rather than always assuming RGB565.

This issue was originally reported on IRC by Francis Moreau,
who has now kindly tested these patches and tells me that they
do indeed fix the issues he was seeing.

-- PMM

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode
  2011-07-26 10:12 ` [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode Peter Maydell
@ 2011-07-26 11:59   ` Francis Moreau
  0 siblings, 0 replies; 6+ messages in thread
From: Francis Moreau @ 2011-07-26 11:59 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, patches

On Tue, Jul 26, 2011 at 12:12 PM, Peter Maydell
<peter.maydell@linaro.org> wrote:
> On 22 July 2011 16:59, Peter Maydell <peter.maydell@linaro.org> wrote:
>> This patch series improves the emulation of the PL11x CLCD
>> controllers used by the various ARM dev boards.
>
>> versatilepb has a PL110 but it also has an external mux controlled
>> by a system register which allows the OS to select whether the
>> 16 bit graphics format should be 5551, RGB565 or BGR565.
>>
>> In particular, Linux kernels 2.6.39 and above default to programming
>> the versatilepb for BGR565, so we need to support the mux control
>> rather than always assuming RGB565.
>
> This issue was originally reported on IRC by Francis Moreau,
> who has now kindly tested these patches and tells me that they
> do indeed fix the issues he was seeing.

Yes I confirm.
-- 
Francis

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-07-26 11:59 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-22 15:59 [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode Peter Maydell
2011-07-22 15:59 ` [Qemu-devel] [PATCH 1/3] hw/pl110: Model the PL111 CLCD controller Peter Maydell
2011-07-22 15:59 ` [Qemu-devel] [PATCH 2/3] versatilepb: Implement SYS_CLCD mux control register bits Peter Maydell
2011-07-22 15:59 ` [Qemu-devel] [PATCH 3/3] vexpress, realview: Use pl111, not pl110 Peter Maydell
2011-07-26 10:12 ` [Qemu-devel] [PATCH 0/3] Add PL111, implement PL110 BGR mode Peter Maydell
2011-07-26 11:59   ` Francis Moreau

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.