summaryrefslogtreecommitdiff
path: root/hw/pl110.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2011-07-22 13:42:39 +0000
committerPeter Maydell <peter.maydell@linaro.org>2011-08-17 23:01:21 +0000
commit242ea2c6bc96473d37894b258a28a2162208228c (patch)
treeeb38f2714b260eddfd688ae3e2319e5314ef4037 /hw/pl110.c
parent4fbf55568bb53a27a8c6270f1d3e2f6daf05c705 (diff)
downloadqemu-242ea2c6bc96473d37894b258a28a2162208228c.tar.gz
versatilepb: Implement SYS_CLCD mux control register bits
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>
Diffstat (limited to 'hw/pl110.c')
-rw-r--r--hw/pl110.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/hw/pl110.c b/hw/pl110.c
index 384eba2198..4ac710a6ec 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);