X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fdev%2Farm%2Fpl111.cc;h=7560ec4b95727aab9f4bcdf1032fd469406b8133;hb=90ed58bcb1791b36e2ecc585ff91b842b1d89610;hp=2973cda27645f7412f8138221bfca34fce09e35c;hpb=fffdc6a45019639cd8f899fa81eeb732db3e6f8c;p=gem5.git diff --git a/src/dev/arm/pl111.cc b/src/dev/arm/pl111.cc index 2973cda27..7560ec4b9 100644 --- a/src/dev/arm/pl111.cc +++ b/src/dev/arm/pl111.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 ARM Limited + * Copyright (c) 2010-2012, 2015 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -38,24 +38,23 @@ * Ali Saidi */ -#include "base/vnc/vncinput.hh" -#include "base/bitmap.hh" +#include "dev/arm/pl111.hh" + #include "base/output.hh" #include "base/trace.hh" +#include "base/vnc/vncinput.hh" #include "debug/PL111.hh" #include "debug/Uart.hh" #include "dev/arm/amba_device.hh" -#include "dev/arm/gic.hh" -#include "dev/arm/pl111.hh" +#include "dev/arm/base_gic.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" +#include "sim/system.hh" // clang complains about std::set being overloaded with Packet::set if // we open up the entire namespace std using std::vector; -using namespace AmbaDev; - // initialize clcd registers Pl111::Pl111(const Params *p) : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0), @@ -65,24 +64,31 @@ Pl111::Pl111(const Params *p) clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0), clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), pixelClock(p->pixel_clock), - vnc(p->vnc), bmp(NULL), width(LcdMaxWidth), height(LcdMaxHeight), + converter(PixelConverter::rgba8888_le), fb(LcdMaxWidth, LcdMaxHeight), + vnc(p->vnc), bmp(&fb), pic(NULL), + width(LcdMaxWidth), height(LcdMaxHeight), bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0), - waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this), - dmaDoneEvent(maxOutstandingDma, this), intEvent(this) + waterMark(0), dmaPendingNum(0), + readEvent([this]{ readFramebuffer(); }, name()), + fillFifoEvent([this]{ fillFifo(); }, name()), + dmaDoneEventAll(maxOutstandingDma, this), + dmaDoneEventFree(maxOutstandingDma), + intEvent([this]{ generateInterrupt(); }, name()), + enableCapture(p->enable_capture) { pioSize = 0xFFFF; - pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true); - - const int buffer_size = LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t); dmaBuffer = new uint8_t[buffer_size]; memset(lcdPalette, 0, sizeof(lcdPalette)); memset(cursorImage, 0, sizeof(cursorImage)); memset(dmaBuffer, 0, buffer_size); + for (int i = 0; i < maxOutstandingDma; ++i) + dmaDoneEventFree[i] = &dmaDoneEventAll[i]; + if (vnc) - vnc->setFramebufferAddr(dmaBuffer); + vnc->setFrameBuffer(&fb); } Pl111::~Pl111() @@ -103,7 +109,6 @@ Pl111::read(PacketPtr pkt) pkt->getAddr() < pioAddr + pioSize); Addr daddr = pkt->getAddr() - pioAddr; - pkt->allocate(); DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize()); @@ -178,9 +183,9 @@ Pl111::read(PacketPtr pkt) data = clcdCrsrMis; break; default: - if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) { + if (readId(pkt, AMBA_ID, pioAddr)) { // Hack for variable size accesses - data = pkt->get(); + data = pkt->getLE(); break; } else if (daddr >= CrsrImage && daddr <= 0xBFC) { // CURSOR IMAGE @@ -195,21 +200,21 @@ Pl111::read(PacketPtr pkt) data = lcdPalette[index]; break; } else { - panic("Tried to read CLCD register at offset %#x that \ - doesn't exist\n", daddr); + panic("Tried to read CLCD register at offset %#x that " + "doesn't exist\n", daddr); break; } } switch(pkt->getSize()) { case 1: - pkt->set(data); + pkt->setLE(data); break; case 2: - pkt->set(data); + pkt->setLE(data); break; case 4: - pkt->set(data); + pkt->setLE(data); break; default: panic("CLCD controller read size too big?\n"); @@ -231,13 +236,13 @@ Pl111::write(PacketPtr pkt) switch(pkt->getSize()) { case 1: - data = pkt->get(); + data = pkt->getLE(); break; case 2: - data = pkt->get(); + data = pkt->getLE(); break; case 4: - data = pkt->get(); + data = pkt->getLE(); break; default: panic("PL111 CLCD controller write size too big?\n"); @@ -250,7 +255,7 @@ Pl111::write(PacketPtr pkt) Addr daddr = pkt->getAddr() - pioAddr; DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr, - pkt->get(), pkt->getSize()); + pkt->getLE(), pkt->getSize()); switch (daddr) { case LcdTiming0: @@ -368,8 +373,8 @@ Pl111::write(PacketPtr pkt) lcdPalette[index] = data; break; } else { - panic("Tried to write PL111 register at offset %#x that \ - doesn't exist\n", daddr); + panic("Tried to write PL111 register at offset %#x that " + "doesn't exist\n", daddr); break; } } @@ -378,45 +383,66 @@ Pl111::write(PacketPtr pkt) return pioDelay; } +PixelConverter +Pl111::pixelConverter() const +{ + unsigned rw, gw, bw; + unsigned offsets[3]; + + switch (lcdControl.lcdbpp) { + case bpp24: + rw = gw = bw = 8; + offsets[0] = 0; + offsets[1] = 8; + offsets[2] = 16; + break; + + case bpp16m565: + rw = 5; + gw = 6; + bw = 5; + offsets[0] = 0; + offsets[1] = 5; + offsets[2] = 11; + break; + + default: + panic("Unimplemented video mode\n"); + } + + if (lcdControl.bgr) { + return PixelConverter( + bytesPerPixel, + offsets[2], offsets[1], offsets[0], + rw, gw, bw, + LittleEndianByteOrder); + } else { + return PixelConverter( + bytesPerPixel, + offsets[0], offsets[1], offsets[2], + rw, gw, bw, + LittleEndianByteOrder); + } +} + void Pl111::updateVideoParams() { - if (lcdControl.lcdbpp == bpp24) { - bytesPerPixel = 4; - } else if (lcdControl.lcdbpp == bpp16m565) { - bytesPerPixel = 2; - } + if (lcdControl.lcdbpp == bpp24) { + bytesPerPixel = 4; + } else if (lcdControl.lcdbpp == bpp16m565) { + bytesPerPixel = 2; + } - if (vnc) { - if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr) - vnc->setFrameBufferParams(VideoConvert::bgr8888, width, - height); - else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr) - vnc->setFrameBufferParams(VideoConvert::rgb8888, width, - height); - else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr) - vnc->setFrameBufferParams(VideoConvert::bgr565, width, - height); - else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr) - vnc->setFrameBufferParams(VideoConvert::rgb565, width, - height); - else - panic("Unimplemented video mode\n"); - } + fb.resize(width, height); + converter = pixelConverter(); - if (bmp) - delete bmp; - - if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr) - bmp = new Bitmap(VideoConvert::bgr8888, width, height, dmaBuffer); - else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr) - bmp = new Bitmap(VideoConvert::rgb8888, width, height, dmaBuffer); - else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr) - bmp = new Bitmap(VideoConvert::bgr565, width, height, dmaBuffer); - else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr) - bmp = new Bitmap(VideoConvert::rgb565, width, height, dmaBuffer); - else - panic("Unimplemented video mode\n"); + // Workaround configuration bugs where multiple display + // controllers are attached to the same VNC server by reattaching + // enabled devices. This isn't ideal, but works as long as only + // one display controller is active at a time. + if (lcdControl.lcdpwr && vnc) + vnc->setFrameBuffer(&fb); } void @@ -438,7 +464,7 @@ Pl111::readFramebuffer() // Updating base address, interrupt if we're supposed to lcdRis.baseaddr = 1; if (!intEvent.scheduled()) - schedule(intEvent, nextCycle()); + schedule(intEvent, clockEdge()); curAddr = 0; startTime = curTick(); @@ -458,14 +484,17 @@ Pl111::fillFifo() // due to assertion in scheduling state ++dmaPendingNum; - assert(!dmaDoneEvent[dmaPendingNum-1].scheduled()); + assert(!dmaDoneEventFree.empty()); + DmaDoneEvent *event(dmaDoneEventFree.back()); + dmaDoneEventFree.pop_back(); + assert(!event->scheduled()); // We use a uncachable request here because the requests from the CPU // will be uncacheable as well. If we have uncacheable and cacheable // requests in the memory system for the same address it won't be // pleased dmaPort.dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize, - &dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer, + event, curAddr + dmaBuffer, 0, Request::UNCACHEABLE); curAddr += dmaSize; } @@ -486,18 +515,25 @@ Pl111::dmaDone() " have taken %d\n", curTick() - startTime, maxFrameTime); lcdRis.underflow = 1; if (!intEvent.scheduled()) - schedule(intEvent, nextCycle()); + schedule(intEvent, clockEdge()); } assert(!readEvent.scheduled()); + fb.copyIn(dmaBuffer, converter); if (vnc) vnc->setDirty(); - DPRINTF(PL111, "-- write out frame buffer into bmp\n"); + if (enableCapture) { + DPRINTF(PL111, "-- write out frame buffer into bmp\n"); - assert(bmp); - pic->seekp(0); - bmp->write(pic); + if (!pic) + pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), + true); + + assert(pic); + pic->stream()->seekp(0); + bmp.write(*pic->stream()); + } // schedule the next read based on when the last frame started // and the desired fps (i.e. maxFrameTime), we turn the @@ -512,11 +548,11 @@ Pl111::dmaDone() return; if (!fillFifoEvent.scheduled()) - schedule(fillFifoEvent, nextCycle()); + schedule(fillFifoEvent, clockEdge()); } void -Pl111::serialize(std::ostream &os) +Pl111::serialize(CheckpointOut &cp) const { DPRINTF(PL111, "Serializing ARM PL111\n"); @@ -573,7 +609,7 @@ Pl111::serialize(std::ostream &os) SERIALIZE_SCALAR(width); SERIALIZE_SCALAR(bytesPerPixel); - SERIALIZE_ARRAY(dmaBuffer, height * width); + SERIALIZE_ARRAY(dmaBuffer, buffer_size); SERIALIZE_SCALAR(startTime); SERIALIZE_SCALAR(startAddr); SERIALIZE_SCALAR(maxAddr); @@ -599,14 +635,14 @@ Pl111::serialize(std::ostream &os) vector dma_done_event_tick; dma_done_event_tick.resize(maxOutstandingDma); for (int x = 0; x < maxOutstandingDma; x++) { - dma_done_event_tick[x] = dmaDoneEvent[x].scheduled() ? - dmaDoneEvent[x].when() : 0; + dma_done_event_tick[x] = dmaDoneEventAll[x].scheduled() ? + dmaDoneEventAll[x].when() : 0; } - arrayParamOut(os, "dma_done_event_tick", dma_done_event_tick); + SERIALIZE_CONTAINER(dma_done_event_tick); } void -Pl111::unserialize(Checkpoint *cp, const std::string §ion) +Pl111::unserialize(CheckpointIn &cp) { DPRINTF(PL111, "Unserializing ARM PL111\n"); @@ -675,7 +711,7 @@ Pl111::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(width); UNSERIALIZE_SCALAR(bytesPerPixel); - UNSERIALIZE_ARRAY(dmaBuffer, height * width); + UNSERIALIZE_ARRAY(dmaBuffer, buffer_size); UNSERIALIZE_SCALAR(startTime); UNSERIALIZE_SCALAR(startAddr); UNSERIALIZE_SCALAR(maxAddr); @@ -700,14 +736,19 @@ Pl111::unserialize(Checkpoint *cp, const std::string §ion) vector dma_done_event_tick; dma_done_event_tick.resize(maxOutstandingDma); - arrayParamIn(cp, section, "dma_done_event_tick", dma_done_event_tick); + UNSERIALIZE_CONTAINER(dma_done_event_tick); + dmaDoneEventFree.clear(); for (int x = 0; x < maxOutstandingDma; x++) { if (dma_done_event_tick[x]) - schedule(dmaDoneEvent[x], dma_done_event_tick[x]); + schedule(dmaDoneEventAll[x], dma_done_event_tick[x]); + else + dmaDoneEventFree.push_back(&dmaDoneEventAll[x]); } + assert(maxOutstandingDma - dmaDoneEventFree.size() == dmaPendingNum); if (lcdControl.lcdpwr) { updateVideoParams(); + fb.copyIn(dmaBuffer, converter); if (vnc) vnc->setDirty(); }