17753SWilliam.Wang@arm.com/*
210839Sandreas.sandberg@arm.com * Copyright (c) 2010-2012, 2015 ARM Limited
37753SWilliam.Wang@arm.com * All rights reserved
47753SWilliam.Wang@arm.com *
57753SWilliam.Wang@arm.com * The license below extends only to copyright in the software and shall
67753SWilliam.Wang@arm.com * not be construed as granting a license to any other intellectual
77753SWilliam.Wang@arm.com * property including but not limited to intellectual property relating
87753SWilliam.Wang@arm.com * to a hardware implementation of the functionality of the software
97753SWilliam.Wang@arm.com * licensed hereunder.  You may use the software subject to the license
107753SWilliam.Wang@arm.com * terms below provided that you ensure that this notice is replicated
117753SWilliam.Wang@arm.com * unmodified and in its entirety in all distributions of the software,
127753SWilliam.Wang@arm.com * modified or unmodified, in source code or in binary form.
137753SWilliam.Wang@arm.com *
147753SWilliam.Wang@arm.com * Redistribution and use in source and binary forms, with or without
157753SWilliam.Wang@arm.com * modification, are permitted provided that the following conditions are
167753SWilliam.Wang@arm.com * met: redistributions of source code must retain the above copyright
177753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer;
187753SWilliam.Wang@arm.com * redistributions in binary form must reproduce the above copyright
197753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer in the
207753SWilliam.Wang@arm.com * documentation and/or other materials provided with the distribution;
217753SWilliam.Wang@arm.com * neither the name of the copyright holders nor the names of its
227753SWilliam.Wang@arm.com * contributors may be used to endorse or promote products derived from
237753SWilliam.Wang@arm.com * this software without specific prior written permission.
247753SWilliam.Wang@arm.com *
257753SWilliam.Wang@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
267753SWilliam.Wang@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
277753SWilliam.Wang@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
287753SWilliam.Wang@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
297753SWilliam.Wang@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
307753SWilliam.Wang@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
317753SWilliam.Wang@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
327753SWilliam.Wang@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
337753SWilliam.Wang@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
347753SWilliam.Wang@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
357753SWilliam.Wang@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
367753SWilliam.Wang@arm.com *
377753SWilliam.Wang@arm.com * Authors: William Wang
387950SAli.Saidi@ARM.com *          Ali Saidi
397753SWilliam.Wang@arm.com */
407753SWilliam.Wang@arm.com
4111793Sbrandon.potter@amd.com#include "dev/arm/pl111.hh"
4211793Sbrandon.potter@amd.com
437950SAli.Saidi@ARM.com#include "base/output.hh"
447753SWilliam.Wang@arm.com#include "base/trace.hh"
4511793Sbrandon.potter@amd.com#include "base/vnc/vncinput.hh"
468245Snate@binkert.org#include "debug/PL111.hh"
478245Snate@binkert.org#include "debug/Uart.hh"
487753SWilliam.Wang@arm.com#include "dev/arm/amba_device.hh"
499525SAndreas.Sandberg@ARM.com#include "dev/arm/base_gic.hh"
507753SWilliam.Wang@arm.com#include "mem/packet.hh"
517753SWilliam.Wang@arm.com#include "mem/packet_access.hh"
529525SAndreas.Sandberg@ARM.com#include "sim/system.hh"
537753SWilliam.Wang@arm.com
548737Skoansin.tan@gmail.com// clang complains about std::set being overloaded with Packet::set if
558737Skoansin.tan@gmail.com// we open up the entire namespace std
568737Skoansin.tan@gmail.comusing std::vector;
578737Skoansin.tan@gmail.com
587753SWilliam.Wang@arm.com// initialize clcd registers
597753SWilliam.Wang@arm.comPl111::Pl111(const Params *p)
607753SWilliam.Wang@arm.com    : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0),
617753SWilliam.Wang@arm.com      lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0),
627950SAli.Saidi@ARM.com      lcdRis(0), lcdMis(0),
637753SWilliam.Wang@arm.com      clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
647753SWilliam.Wang@arm.com      clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
659157Sandreas.hansson@arm.com      clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0),
6610839Sandreas.sandberg@arm.com      pixelClock(p->pixel_clock),
6710839Sandreas.sandberg@arm.com      converter(PixelConverter::rgba8888_le), fb(LcdMaxWidth, LcdMaxHeight),
6810839Sandreas.sandberg@arm.com      vnc(p->vnc), bmp(&fb), pic(NULL),
699530SChris.Emmons@arm.com      width(LcdMaxWidth), height(LcdMaxHeight),
707950SAli.Saidi@ARM.com      bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
7112086Sspwilson2@wisc.edu      waterMark(0), dmaPendingNum(0),
7212086Sspwilson2@wisc.edu      readEvent([this]{ readFramebuffer(); }, name()),
7312086Sspwilson2@wisc.edu      fillFifoEvent([this]{ fillFifo(); }, name()),
749395SAndreas.Sandberg@ARM.com      dmaDoneEventAll(maxOutstandingDma, this),
759395SAndreas.Sandberg@ARM.com      dmaDoneEventFree(maxOutstandingDma),
7612086Sspwilson2@wisc.edu      intEvent([this]{ generateInterrupt(); }, name()),
7712086Sspwilson2@wisc.edu      enableCapture(p->enable_capture)
787753SWilliam.Wang@arm.com{
797753SWilliam.Wang@arm.com    pioSize = 0xFFFF;
807753SWilliam.Wang@arm.com
818737Skoansin.tan@gmail.com    dmaBuffer = new uint8_t[buffer_size];
827950SAli.Saidi@ARM.com
837753SWilliam.Wang@arm.com    memset(lcdPalette, 0, sizeof(lcdPalette));
847753SWilliam.Wang@arm.com    memset(cursorImage, 0, sizeof(cursorImage));
858737Skoansin.tan@gmail.com    memset(dmaBuffer, 0, buffer_size);
867950SAli.Saidi@ARM.com
879395SAndreas.Sandberg@ARM.com    for (int i = 0; i < maxOutstandingDma; ++i)
889395SAndreas.Sandberg@ARM.com        dmaDoneEventFree[i] = &dmaDoneEventAll[i];
899395SAndreas.Sandberg@ARM.com
909330Schander.sudanthi@arm.com    if (vnc)
9110839Sandreas.sandberg@arm.com        vnc->setFrameBuffer(&fb);
927753SWilliam.Wang@arm.com}
937753SWilliam.Wang@arm.com
949086Sandreas.hansson@arm.comPl111::~Pl111()
959086Sandreas.hansson@arm.com{
969086Sandreas.hansson@arm.com    delete[] dmaBuffer;
979086Sandreas.hansson@arm.com}
989086Sandreas.hansson@arm.com
997753SWilliam.Wang@arm.com// read registers and frame buffer
1007753SWilliam.Wang@arm.comTick
1017753SWilliam.Wang@arm.comPl111::read(PacketPtr pkt)
1027753SWilliam.Wang@arm.com{
1037753SWilliam.Wang@arm.com    // use a temporary data since the LCD registers are read/written with
1047753SWilliam.Wang@arm.com    // different size operations
1057753SWilliam.Wang@arm.com
1067753SWilliam.Wang@arm.com    uint32_t data = 0;
1077753SWilliam.Wang@arm.com
1087950SAli.Saidi@ARM.com    assert(pkt->getAddr() >= pioAddr &&
1097950SAli.Saidi@ARM.com           pkt->getAddr() < pioAddr + pioSize);
1107753SWilliam.Wang@arm.com
1117950SAli.Saidi@ARM.com    Addr daddr = pkt->getAddr() - pioAddr;
1127753SWilliam.Wang@arm.com
1137950SAli.Saidi@ARM.com    DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize());
1147753SWilliam.Wang@arm.com
1157950SAli.Saidi@ARM.com    switch (daddr) {
1167950SAli.Saidi@ARM.com      case LcdTiming0:
1177950SAli.Saidi@ARM.com        data = lcdTiming0;
1187950SAli.Saidi@ARM.com        break;
1197950SAli.Saidi@ARM.com      case LcdTiming1:
1207950SAli.Saidi@ARM.com        data = lcdTiming1;
1217950SAli.Saidi@ARM.com        break;
1227950SAli.Saidi@ARM.com      case LcdTiming2:
1237950SAli.Saidi@ARM.com        data = lcdTiming2;
1247950SAli.Saidi@ARM.com        break;
1257950SAli.Saidi@ARM.com      case LcdTiming3:
1267950SAli.Saidi@ARM.com        data = lcdTiming3;
1277950SAli.Saidi@ARM.com        break;
1287950SAli.Saidi@ARM.com      case LcdUpBase:
1297950SAli.Saidi@ARM.com        data = lcdUpbase;
1307950SAli.Saidi@ARM.com        break;
1317950SAli.Saidi@ARM.com      case LcdLpBase:
1327950SAli.Saidi@ARM.com        data = lcdLpbase;
1337950SAli.Saidi@ARM.com        break;
1347950SAli.Saidi@ARM.com      case LcdControl:
1357950SAli.Saidi@ARM.com        data = lcdControl;
1367950SAli.Saidi@ARM.com        break;
1377950SAli.Saidi@ARM.com      case LcdImsc:
1387950SAli.Saidi@ARM.com        data = lcdImsc;
1397950SAli.Saidi@ARM.com        break;
1407950SAli.Saidi@ARM.com      case LcdRis:
1417950SAli.Saidi@ARM.com        data = lcdRis;
1427950SAli.Saidi@ARM.com        break;
1437950SAli.Saidi@ARM.com      case LcdMis:
1447950SAli.Saidi@ARM.com        data = lcdMis;
1457950SAli.Saidi@ARM.com        break;
1467950SAli.Saidi@ARM.com      case LcdIcr:
1477950SAli.Saidi@ARM.com        panic("LCD register at offset %#x is Write-Only\n", daddr);
1487950SAli.Saidi@ARM.com        break;
1497950SAli.Saidi@ARM.com      case LcdUpCurr:
1507950SAli.Saidi@ARM.com        data = curAddr;
1517950SAli.Saidi@ARM.com        break;
1527950SAli.Saidi@ARM.com      case LcdLpCurr:
1537950SAli.Saidi@ARM.com        data = curAddr;
1547950SAli.Saidi@ARM.com        break;
1557950SAli.Saidi@ARM.com      case ClcdCrsrCtrl:
1567950SAli.Saidi@ARM.com        data = clcdCrsrCtrl;
1577950SAli.Saidi@ARM.com        break;
1587950SAli.Saidi@ARM.com      case ClcdCrsrConfig:
1597950SAli.Saidi@ARM.com        data = clcdCrsrConfig;
1607950SAli.Saidi@ARM.com        break;
1617950SAli.Saidi@ARM.com      case ClcdCrsrPalette0:
1627950SAli.Saidi@ARM.com        data = clcdCrsrPalette0;
1637950SAli.Saidi@ARM.com        break;
1647950SAli.Saidi@ARM.com      case ClcdCrsrPalette1:
1657950SAli.Saidi@ARM.com        data = clcdCrsrPalette1;
1667950SAli.Saidi@ARM.com        break;
1677950SAli.Saidi@ARM.com      case ClcdCrsrXY:
1687950SAli.Saidi@ARM.com        data = clcdCrsrXY;
1697950SAli.Saidi@ARM.com        break;
1707950SAli.Saidi@ARM.com      case ClcdCrsrClip:
1717950SAli.Saidi@ARM.com        data = clcdCrsrClip;
1727950SAli.Saidi@ARM.com        break;
1737950SAli.Saidi@ARM.com      case ClcdCrsrImsc:
1747950SAli.Saidi@ARM.com        data = clcdCrsrImsc;
1757950SAli.Saidi@ARM.com        break;
1767950SAli.Saidi@ARM.com      case ClcdCrsrIcr:
1777950SAli.Saidi@ARM.com        panic("CLCD register at offset %#x is Write-Only\n", daddr);
1787950SAli.Saidi@ARM.com        break;
1797950SAli.Saidi@ARM.com      case ClcdCrsrRis:
1807950SAli.Saidi@ARM.com        data = clcdCrsrRis;
1817950SAli.Saidi@ARM.com        break;
1827950SAli.Saidi@ARM.com      case ClcdCrsrMis:
1837950SAli.Saidi@ARM.com        data = clcdCrsrMis;
1847950SAli.Saidi@ARM.com        break;
1857950SAli.Saidi@ARM.com      default:
1869806Sstever@gmail.com        if (readId(pkt, AMBA_ID, pioAddr)) {
1877950SAli.Saidi@ARM.com            // Hack for variable size accesses
18813230Sgabeblack@google.com            data = pkt->getLE<uint32_t>();
1897753SWilliam.Wang@arm.com            break;
1907950SAli.Saidi@ARM.com        } else if (daddr >= CrsrImage && daddr <= 0xBFC) {
1917950SAli.Saidi@ARM.com            // CURSOR IMAGE
1927950SAli.Saidi@ARM.com            int index;
1937950SAli.Saidi@ARM.com            index = (daddr - CrsrImage) >> 2;
1947950SAli.Saidi@ARM.com            data= cursorImage[index];
1957753SWilliam.Wang@arm.com            break;
1967950SAli.Saidi@ARM.com        } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
1977950SAli.Saidi@ARM.com            // LCD Palette
1987950SAli.Saidi@ARM.com            int index;
1997950SAli.Saidi@ARM.com            index = (daddr - LcdPalette) >> 2;
2007950SAli.Saidi@ARM.com            data = lcdPalette[index];
2017753SWilliam.Wang@arm.com            break;
2027950SAli.Saidi@ARM.com        } else {
20310367SAndrew.Bardsley@arm.com            panic("Tried to read CLCD register at offset %#x that "
20410367SAndrew.Bardsley@arm.com                       "doesn't exist\n", daddr);
2057753SWilliam.Wang@arm.com            break;
2067753SWilliam.Wang@arm.com        }
2077753SWilliam.Wang@arm.com    }
2087753SWilliam.Wang@arm.com
2097753SWilliam.Wang@arm.com    switch(pkt->getSize()) {
2107753SWilliam.Wang@arm.com      case 1:
21113230Sgabeblack@google.com        pkt->setLE<uint8_t>(data);
2127753SWilliam.Wang@arm.com        break;
2137753SWilliam.Wang@arm.com      case 2:
21413230Sgabeblack@google.com        pkt->setLE<uint16_t>(data);
2157753SWilliam.Wang@arm.com        break;
2167753SWilliam.Wang@arm.com      case 4:
21713230Sgabeblack@google.com        pkt->setLE<uint32_t>(data);
2187753SWilliam.Wang@arm.com        break;
2197753SWilliam.Wang@arm.com      default:
2207753SWilliam.Wang@arm.com        panic("CLCD controller read size too big?\n");
2217753SWilliam.Wang@arm.com        break;
2227753SWilliam.Wang@arm.com    }
2237753SWilliam.Wang@arm.com
2247753SWilliam.Wang@arm.com    pkt->makeAtomicResponse();
2257753SWilliam.Wang@arm.com    return pioDelay;
2267753SWilliam.Wang@arm.com}
2277753SWilliam.Wang@arm.com
2287753SWilliam.Wang@arm.com// write registers and frame buffer
2297753SWilliam.Wang@arm.comTick
2307753SWilliam.Wang@arm.comPl111::write(PacketPtr pkt)
2317753SWilliam.Wang@arm.com{
2327753SWilliam.Wang@arm.com    // use a temporary data since the LCD registers are read/written with
2337753SWilliam.Wang@arm.com    // different size operations
2347753SWilliam.Wang@arm.com    //
2357753SWilliam.Wang@arm.com    uint32_t data = 0;
2367753SWilliam.Wang@arm.com
2377753SWilliam.Wang@arm.com    switch(pkt->getSize()) {
2387753SWilliam.Wang@arm.com      case 1:
23913230Sgabeblack@google.com        data = pkt->getLE<uint8_t>();
2407753SWilliam.Wang@arm.com        break;
2417753SWilliam.Wang@arm.com      case 2:
24213230Sgabeblack@google.com        data = pkt->getLE<uint16_t>();
2437753SWilliam.Wang@arm.com        break;
2447753SWilliam.Wang@arm.com      case 4:
24513230Sgabeblack@google.com        data = pkt->getLE<uint32_t>();
2467753SWilliam.Wang@arm.com        break;
2477753SWilliam.Wang@arm.com      default:
2487753SWilliam.Wang@arm.com        panic("PL111 CLCD controller write size too big?\n");
2497753SWilliam.Wang@arm.com        break;
2507753SWilliam.Wang@arm.com    }
2517753SWilliam.Wang@arm.com
2527950SAli.Saidi@ARM.com    assert(pkt->getAddr() >= pioAddr &&
2537950SAli.Saidi@ARM.com           pkt->getAddr() < pioAddr + pioSize);
2547753SWilliam.Wang@arm.com
2557950SAli.Saidi@ARM.com    Addr daddr = pkt->getAddr() - pioAddr;
2567753SWilliam.Wang@arm.com
2577950SAli.Saidi@ARM.com    DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr,
25813230Sgabeblack@google.com            pkt->getLE<uint8_t>(), pkt->getSize());
2597753SWilliam.Wang@arm.com
2607950SAli.Saidi@ARM.com    switch (daddr) {
2617950SAli.Saidi@ARM.com      case LcdTiming0:
2627950SAli.Saidi@ARM.com        lcdTiming0 = data;
2637950SAli.Saidi@ARM.com        // width = 16 * (PPL+1)
2647950SAli.Saidi@ARM.com        width = (lcdTiming0.ppl + 1) << 4;
2657950SAli.Saidi@ARM.com        break;
2667950SAli.Saidi@ARM.com      case LcdTiming1:
2677950SAli.Saidi@ARM.com        lcdTiming1 = data;
2687950SAli.Saidi@ARM.com        // height = LPP + 1
2697950SAli.Saidi@ARM.com        height = (lcdTiming1.lpp) + 1;
2707950SAli.Saidi@ARM.com        break;
2717950SAli.Saidi@ARM.com      case LcdTiming2:
2727950SAli.Saidi@ARM.com        lcdTiming2 = data;
2737950SAli.Saidi@ARM.com        break;
2747950SAli.Saidi@ARM.com      case LcdTiming3:
2757950SAli.Saidi@ARM.com        lcdTiming3 = data;
2767950SAli.Saidi@ARM.com        break;
2777950SAli.Saidi@ARM.com      case LcdUpBase:
2787950SAli.Saidi@ARM.com        lcdUpbase = data;
2797950SAli.Saidi@ARM.com        DPRINTF(PL111, "####### Upper panel base set to: %#x #######\n", lcdUpbase);
2807950SAli.Saidi@ARM.com        break;
2817950SAli.Saidi@ARM.com      case LcdLpBase:
2828508SAli.Saidi@ARM.com        warn_once("LCD dual screen mode not supported\n");
2837950SAli.Saidi@ARM.com        lcdLpbase = data;
2847950SAli.Saidi@ARM.com        DPRINTF(PL111, "###### Lower panel base set to: %#x #######\n", lcdLpbase);
2857950SAli.Saidi@ARM.com        break;
2867950SAli.Saidi@ARM.com      case LcdControl:
2877950SAli.Saidi@ARM.com        int old_lcdpwr;
2887950SAli.Saidi@ARM.com        old_lcdpwr = lcdControl.lcdpwr;
2897950SAli.Saidi@ARM.com        lcdControl = data;
2907753SWilliam.Wang@arm.com
2917950SAli.Saidi@ARM.com        DPRINTF(PL111, "LCD power is:%d\n", lcdControl.lcdpwr);
2927950SAli.Saidi@ARM.com
2937950SAli.Saidi@ARM.com        // LCD power enable
2947950SAli.Saidi@ARM.com        if (lcdControl.lcdpwr && !old_lcdpwr) {
2957950SAli.Saidi@ARM.com            updateVideoParams();
2967950SAli.Saidi@ARM.com            DPRINTF(PL111, " lcd size: height %d width %d\n", height, width);
2977950SAli.Saidi@ARM.com            waterMark = lcdControl.watermark ? 8 : 4;
2987950SAli.Saidi@ARM.com            startDma();
2997950SAli.Saidi@ARM.com        }
3007950SAli.Saidi@ARM.com        break;
3017950SAli.Saidi@ARM.com      case LcdImsc:
3027950SAli.Saidi@ARM.com        lcdImsc = data;
3037950SAli.Saidi@ARM.com        if (lcdImsc.vcomp)
3047950SAli.Saidi@ARM.com            panic("Interrupting on vcomp not supported\n");
3057950SAli.Saidi@ARM.com
3067950SAli.Saidi@ARM.com        lcdMis = lcdImsc & lcdRis;
3077950SAli.Saidi@ARM.com
3087950SAli.Saidi@ARM.com        if (!lcdMis)
3097950SAli.Saidi@ARM.com            gic->clearInt(intNum);
3107950SAli.Saidi@ARM.com
3117950SAli.Saidi@ARM.com         break;
3127950SAli.Saidi@ARM.com      case LcdRis:
3137950SAli.Saidi@ARM.com        panic("LCD register at offset %#x is Read-Only\n", daddr);
3147950SAli.Saidi@ARM.com        break;
3157950SAli.Saidi@ARM.com      case LcdMis:
3167950SAli.Saidi@ARM.com        panic("LCD register at offset %#x is Read-Only\n", daddr);
3177950SAli.Saidi@ARM.com        break;
3187950SAli.Saidi@ARM.com      case LcdIcr:
3197950SAli.Saidi@ARM.com        lcdRis = lcdRis & ~data;
3207950SAli.Saidi@ARM.com        lcdMis = lcdImsc & lcdRis;
3217950SAli.Saidi@ARM.com
3227950SAli.Saidi@ARM.com        if (!lcdMis)
3237950SAli.Saidi@ARM.com            gic->clearInt(intNum);
3247950SAli.Saidi@ARM.com
3257950SAli.Saidi@ARM.com        break;
3267950SAli.Saidi@ARM.com      case LcdUpCurr:
3277950SAli.Saidi@ARM.com        panic("LCD register at offset %#x is Read-Only\n", daddr);
3287950SAli.Saidi@ARM.com        break;
3297950SAli.Saidi@ARM.com      case LcdLpCurr:
3307950SAli.Saidi@ARM.com        panic("LCD register at offset %#x is Read-Only\n", daddr);
3317950SAli.Saidi@ARM.com        break;
3327950SAli.Saidi@ARM.com      case ClcdCrsrCtrl:
3337950SAli.Saidi@ARM.com        clcdCrsrCtrl = data;
3347950SAli.Saidi@ARM.com        break;
3357950SAli.Saidi@ARM.com      case ClcdCrsrConfig:
3367950SAli.Saidi@ARM.com        clcdCrsrConfig = data;
3377950SAli.Saidi@ARM.com        break;
3387950SAli.Saidi@ARM.com      case ClcdCrsrPalette0:
3397950SAli.Saidi@ARM.com        clcdCrsrPalette0 = data;
3407950SAli.Saidi@ARM.com        break;
3417950SAli.Saidi@ARM.com      case ClcdCrsrPalette1:
3427950SAli.Saidi@ARM.com        clcdCrsrPalette1 = data;
3437950SAli.Saidi@ARM.com        break;
3447950SAli.Saidi@ARM.com      case ClcdCrsrXY:
3457950SAli.Saidi@ARM.com        clcdCrsrXY = data;
3467950SAli.Saidi@ARM.com        break;
3477950SAli.Saidi@ARM.com      case ClcdCrsrClip:
3487950SAli.Saidi@ARM.com        clcdCrsrClip = data;
3497950SAli.Saidi@ARM.com        break;
3507950SAli.Saidi@ARM.com      case ClcdCrsrImsc:
3517950SAli.Saidi@ARM.com        clcdCrsrImsc = data;
3527950SAli.Saidi@ARM.com        break;
3537950SAli.Saidi@ARM.com      case ClcdCrsrIcr:
3547950SAli.Saidi@ARM.com        clcdCrsrIcr = data;
3557950SAli.Saidi@ARM.com        break;
3567950SAli.Saidi@ARM.com      case ClcdCrsrRis:
3577950SAli.Saidi@ARM.com        panic("CLCD register at offset %#x is Read-Only\n", daddr);
3587950SAli.Saidi@ARM.com        break;
3597950SAli.Saidi@ARM.com      case ClcdCrsrMis:
3607950SAli.Saidi@ARM.com        panic("CLCD register at offset %#x is Read-Only\n", daddr);
3617950SAli.Saidi@ARM.com        break;
3627950SAli.Saidi@ARM.com      default:
3637950SAli.Saidi@ARM.com        if (daddr >= CrsrImage && daddr <= 0xBFC) {
3647950SAli.Saidi@ARM.com            // CURSOR IMAGE
3657950SAli.Saidi@ARM.com            int index;
3667950SAli.Saidi@ARM.com            index = (daddr - CrsrImage) >> 2;
3677950SAli.Saidi@ARM.com            cursorImage[index] = data;
3687753SWilliam.Wang@arm.com            break;
3697950SAli.Saidi@ARM.com        } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
3707950SAli.Saidi@ARM.com            // LCD Palette
3717950SAli.Saidi@ARM.com            int index;
3727950SAli.Saidi@ARM.com            index = (daddr - LcdPalette) >> 2;
3737950SAli.Saidi@ARM.com            lcdPalette[index] = data;
3747753SWilliam.Wang@arm.com            break;
3757950SAli.Saidi@ARM.com        } else {
37610367SAndrew.Bardsley@arm.com            panic("Tried to write PL111 register at offset %#x that "
37710367SAndrew.Bardsley@arm.com                       "doesn't exist\n", daddr);
3787753SWilliam.Wang@arm.com            break;
3797753SWilliam.Wang@arm.com        }
3807753SWilliam.Wang@arm.com    }
3817753SWilliam.Wang@arm.com
3827753SWilliam.Wang@arm.com    pkt->makeAtomicResponse();
3837753SWilliam.Wang@arm.com    return pioDelay;
3847753SWilliam.Wang@arm.com}
3857753SWilliam.Wang@arm.com
38610839Sandreas.sandberg@arm.comPixelConverter
38710839Sandreas.sandberg@arm.comPl111::pixelConverter() const
38810839Sandreas.sandberg@arm.com{
38910839Sandreas.sandberg@arm.com    unsigned rw, gw, bw;
39010839Sandreas.sandberg@arm.com    unsigned offsets[3];
39110839Sandreas.sandberg@arm.com
39210839Sandreas.sandberg@arm.com    switch (lcdControl.lcdbpp) {
39310839Sandreas.sandberg@arm.com      case bpp24:
39410839Sandreas.sandberg@arm.com        rw = gw = bw = 8;
39510839Sandreas.sandberg@arm.com        offsets[0] = 0;
39610839Sandreas.sandberg@arm.com        offsets[1] = 8;
39710839Sandreas.sandberg@arm.com        offsets[2] = 16;
39810839Sandreas.sandberg@arm.com        break;
39910839Sandreas.sandberg@arm.com
40010839Sandreas.sandberg@arm.com      case bpp16m565:
40110839Sandreas.sandberg@arm.com        rw = 5;
40210839Sandreas.sandberg@arm.com        gw = 6;
40310839Sandreas.sandberg@arm.com        bw = 5;
40410839Sandreas.sandberg@arm.com        offsets[0] = 0;
40510839Sandreas.sandberg@arm.com        offsets[1] = 5;
40610839Sandreas.sandberg@arm.com        offsets[2] = 11;
40710839Sandreas.sandberg@arm.com        break;
40810839Sandreas.sandberg@arm.com
40910839Sandreas.sandberg@arm.com      default:
41010839Sandreas.sandberg@arm.com        panic("Unimplemented video mode\n");
41110839Sandreas.sandberg@arm.com    }
41210839Sandreas.sandberg@arm.com
41310839Sandreas.sandberg@arm.com    if (lcdControl.bgr) {
41410839Sandreas.sandberg@arm.com        return PixelConverter(
41510839Sandreas.sandberg@arm.com            bytesPerPixel,
41610839Sandreas.sandberg@arm.com            offsets[2], offsets[1], offsets[0],
41710839Sandreas.sandberg@arm.com            rw, gw, bw,
41810839Sandreas.sandberg@arm.com            LittleEndianByteOrder);
41910839Sandreas.sandberg@arm.com    } else {
42010839Sandreas.sandberg@arm.com        return PixelConverter(
42110839Sandreas.sandberg@arm.com            bytesPerPixel,
42210839Sandreas.sandberg@arm.com            offsets[0], offsets[1], offsets[2],
42310839Sandreas.sandberg@arm.com            rw, gw, bw,
42410839Sandreas.sandberg@arm.com            LittleEndianByteOrder);
42510839Sandreas.sandberg@arm.com    }
42610839Sandreas.sandberg@arm.com}
42710839Sandreas.sandberg@arm.com
4287753SWilliam.Wang@arm.comvoid
4297950SAli.Saidi@ARM.comPl111::updateVideoParams()
4307950SAli.Saidi@ARM.com{
43110839Sandreas.sandberg@arm.com    if (lcdControl.lcdbpp == bpp24) {
43210839Sandreas.sandberg@arm.com        bytesPerPixel = 4;
43310839Sandreas.sandberg@arm.com    } else if (lcdControl.lcdbpp == bpp16m565) {
43410839Sandreas.sandberg@arm.com        bytesPerPixel = 2;
43510839Sandreas.sandberg@arm.com    }
4367950SAli.Saidi@ARM.com
43710839Sandreas.sandberg@arm.com    fb.resize(width, height);
43810839Sandreas.sandberg@arm.com    converter = pixelConverter();
4397950SAli.Saidi@ARM.com
44010839Sandreas.sandberg@arm.com    // Workaround configuration bugs where multiple display
44110839Sandreas.sandberg@arm.com    // controllers are attached to the same VNC server by reattaching
44210839Sandreas.sandberg@arm.com    // enabled devices. This isn't ideal, but works as long as only
44310839Sandreas.sandberg@arm.com    // one display controller is active at a time.
44410839Sandreas.sandberg@arm.com    if (lcdControl.lcdpwr && vnc)
44510839Sandreas.sandberg@arm.com        vnc->setFrameBuffer(&fb);
4467950SAli.Saidi@ARM.com}
4477950SAli.Saidi@ARM.com
4487950SAli.Saidi@ARM.comvoid
4497950SAli.Saidi@ARM.comPl111::startDma()
4507950SAli.Saidi@ARM.com{
4517950SAli.Saidi@ARM.com    if (dmaPendingNum != 0 || readEvent.scheduled())
4527950SAli.Saidi@ARM.com        return;
4537950SAli.Saidi@ARM.com    readFramebuffer();
4547950SAli.Saidi@ARM.com}
4557950SAli.Saidi@ARM.com
4567950SAli.Saidi@ARM.comvoid
4577753SWilliam.Wang@arm.comPl111::readFramebuffer()
4587753SWilliam.Wang@arm.com{
4597753SWilliam.Wang@arm.com    // initialization for dma read from frame buffer to dma buffer
4607950SAli.Saidi@ARM.com    uint32_t length = height * width;
4617950SAli.Saidi@ARM.com    if (startAddr != lcdUpbase)
4627753SWilliam.Wang@arm.com        startAddr = lcdUpbase;
4637950SAli.Saidi@ARM.com
4647950SAli.Saidi@ARM.com    // Updating base address, interrupt if we're supposed to
4657950SAli.Saidi@ARM.com    lcdRis.baseaddr = 1;
4667950SAli.Saidi@ARM.com    if (!intEvent.scheduled())
4679648Sdam.sunwoo@arm.com        schedule(intEvent, clockEdge());
4687950SAli.Saidi@ARM.com
4697753SWilliam.Wang@arm.com    curAddr = 0;
4709394Sandreas.hansson@arm.com    startTime = curTick();
4717950SAli.Saidi@ARM.com
4727950SAli.Saidi@ARM.com    maxAddr = static_cast<Addr>(length * bytesPerPixel);
4737950SAli.Saidi@ARM.com
4747950SAli.Saidi@ARM.com    DPRINTF(PL111, " lcd frame buffer size of %d bytes \n", maxAddr);
4757950SAli.Saidi@ARM.com
4767753SWilliam.Wang@arm.com    fillFifo();
4777753SWilliam.Wang@arm.com}
4787753SWilliam.Wang@arm.com
4797753SWilliam.Wang@arm.comvoid
4807753SWilliam.Wang@arm.comPl111::fillFifo()
4817753SWilliam.Wang@arm.com{
4827753SWilliam.Wang@arm.com    while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) {
4837753SWilliam.Wang@arm.com        // concurrent dma reads need different dma done events
4847753SWilliam.Wang@arm.com        // due to assertion in scheduling state
4857753SWilliam.Wang@arm.com        ++dmaPendingNum;
4867950SAli.Saidi@ARM.com
4879395SAndreas.Sandberg@ARM.com        assert(!dmaDoneEventFree.empty());
4889395SAndreas.Sandberg@ARM.com        DmaDoneEvent *event(dmaDoneEventFree.back());
4899395SAndreas.Sandberg@ARM.com        dmaDoneEventFree.pop_back();
4909395SAndreas.Sandberg@ARM.com        assert(!event->scheduled());
4917950SAli.Saidi@ARM.com
4927950SAli.Saidi@ARM.com        // We use a uncachable request here because the requests from the CPU
4937950SAli.Saidi@ARM.com        // will be uncacheable as well. If we have uncacheable and cacheable
4947950SAli.Saidi@ARM.com        // requests in the memory system for the same address it won't be
4957950SAli.Saidi@ARM.com        // pleased
4968851Sandreas.hansson@arm.com        dmaPort.dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize,
4979395SAndreas.Sandberg@ARM.com                          event, curAddr + dmaBuffer,
4988851Sandreas.hansson@arm.com                          0, Request::UNCACHEABLE);
4997753SWilliam.Wang@arm.com        curAddr += dmaSize;
5007753SWilliam.Wang@arm.com    }
5017753SWilliam.Wang@arm.com}
5027753SWilliam.Wang@arm.com
5037753SWilliam.Wang@arm.comvoid
5047753SWilliam.Wang@arm.comPl111::dmaDone()
5057753SWilliam.Wang@arm.com{
5069394Sandreas.hansson@arm.com    DPRINTF(PL111, "DMA Done\n");
5079394Sandreas.hansson@arm.com
5089394Sandreas.hansson@arm.com    Tick maxFrameTime = lcdTiming2.cpl * height * pixelClock;
5097753SWilliam.Wang@arm.com
5107753SWilliam.Wang@arm.com    --dmaPendingNum;
5117753SWilliam.Wang@arm.com
5127753SWilliam.Wang@arm.com    if (maxAddr == curAddr && !dmaPendingNum) {
5139394Sandreas.hansson@arm.com        if ((curTick() - startTime) > maxFrameTime) {
5149394Sandreas.hansson@arm.com            warn("CLCD controller buffer underrun, took %d ticks when should"
5157823Ssteve.reinhardt@amd.com                 " have taken %d\n", curTick() - startTime, maxFrameTime);
5167950SAli.Saidi@ARM.com            lcdRis.underflow = 1;
5177950SAli.Saidi@ARM.com            if (!intEvent.scheduled())
5189648Sdam.sunwoo@arm.com                schedule(intEvent, clockEdge());
5197950SAli.Saidi@ARM.com        }
5207753SWilliam.Wang@arm.com
5217753SWilliam.Wang@arm.com        assert(!readEvent.scheduled());
52210839Sandreas.sandberg@arm.com        fb.copyIn(dmaBuffer, converter);
5239330Schander.sudanthi@arm.com        if (vnc)
5249330Schander.sudanthi@arm.com            vnc->setDirty();
5257753SWilliam.Wang@arm.com
5269939Sdam.sunwoo@arm.com        if (enableCapture) {
5279939Sdam.sunwoo@arm.com            DPRINTF(PL111, "-- write out frame buffer into bmp\n");
5287950SAli.Saidi@ARM.com
5299939Sdam.sunwoo@arm.com            if (!pic)
53011359Sandreas@sandberg.pp.se                pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()),
53111359Sandreas@sandberg.pp.se                                    true);
5329530SChris.Emmons@arm.com
5339939Sdam.sunwoo@arm.com            assert(pic);
53411359Sandreas@sandberg.pp.se            pic->stream()->seekp(0);
53511359Sandreas@sandberg.pp.se            bmp.write(*pic->stream());
5369939Sdam.sunwoo@arm.com        }
5377753SWilliam.Wang@arm.com
5389179Sandreas.hansson@arm.com        // schedule the next read based on when the last frame started
5399179Sandreas.hansson@arm.com        // and the desired fps (i.e. maxFrameTime), we turn the
5409394Sandreas.hansson@arm.com        // argument into a relative number of cycles in the future
5417950SAli.Saidi@ARM.com        if (lcdControl.lcden)
5429394Sandreas.hansson@arm.com            schedule(readEvent, clockEdge(ticksToCycles(startTime -
5439394Sandreas.hansson@arm.com                                                        curTick() +
5449394Sandreas.hansson@arm.com                                                        maxFrameTime)));
5457753SWilliam.Wang@arm.com    }
5467753SWilliam.Wang@arm.com
5477753SWilliam.Wang@arm.com    if (dmaPendingNum > (maxOutstandingDma - waterMark))
5487753SWilliam.Wang@arm.com        return;
5497753SWilliam.Wang@arm.com
5507753SWilliam.Wang@arm.com    if (!fillFifoEvent.scheduled())
5519648Sdam.sunwoo@arm.com        schedule(fillFifoEvent, clockEdge());
5527950SAli.Saidi@ARM.com}
5537753SWilliam.Wang@arm.com
5547753SWilliam.Wang@arm.comvoid
55510905Sandreas.sandberg@arm.comPl111::serialize(CheckpointOut &cp) const
5567753SWilliam.Wang@arm.com{
5577753SWilliam.Wang@arm.com    DPRINTF(PL111, "Serializing ARM PL111\n");
5587753SWilliam.Wang@arm.com
5597753SWilliam.Wang@arm.com    uint32_t lcdTiming0_serial = lcdTiming0;
5607753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdTiming0_serial);
5617753SWilliam.Wang@arm.com
5627753SWilliam.Wang@arm.com    uint32_t lcdTiming1_serial = lcdTiming1;
5637753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdTiming1_serial);
5647753SWilliam.Wang@arm.com
5657753SWilliam.Wang@arm.com    uint32_t lcdTiming2_serial = lcdTiming2;
5667753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdTiming2_serial);
5677753SWilliam.Wang@arm.com
5687753SWilliam.Wang@arm.com    uint32_t lcdTiming3_serial = lcdTiming3;
5697753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdTiming3_serial);
5707753SWilliam.Wang@arm.com
5717753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdUpbase);
5727753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdLpbase);
5737753SWilliam.Wang@arm.com
5747753SWilliam.Wang@arm.com    uint32_t lcdControl_serial = lcdControl;
5757753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdControl_serial);
5767753SWilliam.Wang@arm.com
5777753SWilliam.Wang@arm.com    uint8_t lcdImsc_serial = lcdImsc;
5787753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdImsc_serial);
5797753SWilliam.Wang@arm.com
5807753SWilliam.Wang@arm.com    uint8_t lcdRis_serial = lcdRis;
5817753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdRis_serial);
5827753SWilliam.Wang@arm.com
5837753SWilliam.Wang@arm.com    uint8_t lcdMis_serial = lcdMis;
5847753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdMis_serial);
5857753SWilliam.Wang@arm.com
5867753SWilliam.Wang@arm.com    SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
5877753SWilliam.Wang@arm.com    SERIALIZE_ARRAY(cursorImage, CrsrImageSize);
5887753SWilliam.Wang@arm.com
5897753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrCtrl);
5907753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrConfig);
5917753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrPalette0);
5927753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrPalette1);
5937753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrXY);
5947753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrClip);
5957753SWilliam.Wang@arm.com
5967753SWilliam.Wang@arm.com    uint8_t clcdCrsrImsc_serial = clcdCrsrImsc;
5977753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrImsc_serial);
5987753SWilliam.Wang@arm.com
5997753SWilliam.Wang@arm.com    uint8_t clcdCrsrIcr_serial = clcdCrsrIcr;
6007753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrIcr_serial);
6017753SWilliam.Wang@arm.com
6027753SWilliam.Wang@arm.com    uint8_t clcdCrsrRis_serial = clcdCrsrRis;
6037753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrRis_serial);
6047753SWilliam.Wang@arm.com
6057753SWilliam.Wang@arm.com    uint8_t clcdCrsrMis_serial = clcdCrsrMis;
6067753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrMis_serial);
6077753SWilliam.Wang@arm.com
6087753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(height);
6097753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(width);
6107950SAli.Saidi@ARM.com    SERIALIZE_SCALAR(bytesPerPixel);
6117753SWilliam.Wang@arm.com
6129415SChander.Sudanthi@arm.com    SERIALIZE_ARRAY(dmaBuffer, buffer_size);
6137753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(startTime);
6147753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(startAddr);
6157753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(maxAddr);
6167753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(curAddr);
6177753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(waterMark);
6187753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(dmaPendingNum);
6198062SAli.Saidi@ARM.com
6208062SAli.Saidi@ARM.com    Tick int_event_time = 0;
6218062SAli.Saidi@ARM.com    Tick read_event_time = 0;
6228062SAli.Saidi@ARM.com    Tick fill_fifo_event_time = 0;
6238062SAli.Saidi@ARM.com
6248062SAli.Saidi@ARM.com    if (readEvent.scheduled())
6258062SAli.Saidi@ARM.com        read_event_time = readEvent.when();
6268062SAli.Saidi@ARM.com    if (fillFifoEvent.scheduled())
6278062SAli.Saidi@ARM.com        fill_fifo_event_time = fillFifoEvent.when();
6288062SAli.Saidi@ARM.com    if (intEvent.scheduled())
6298062SAli.Saidi@ARM.com        int_event_time = intEvent.when();
6308062SAli.Saidi@ARM.com
6318062SAli.Saidi@ARM.com    SERIALIZE_SCALAR(read_event_time);
6328062SAli.Saidi@ARM.com    SERIALIZE_SCALAR(fill_fifo_event_time);
6338062SAli.Saidi@ARM.com    SERIALIZE_SCALAR(int_event_time);
6348062SAli.Saidi@ARM.com
6358062SAli.Saidi@ARM.com    vector<Tick> dma_done_event_tick;
6368062SAli.Saidi@ARM.com    dma_done_event_tick.resize(maxOutstandingDma);
6378062SAli.Saidi@ARM.com    for (int x = 0; x < maxOutstandingDma; x++) {
6389395SAndreas.Sandberg@ARM.com        dma_done_event_tick[x] = dmaDoneEventAll[x].scheduled() ?
6399395SAndreas.Sandberg@ARM.com            dmaDoneEventAll[x].when() : 0;
6408062SAli.Saidi@ARM.com    }
64110905Sandreas.sandberg@arm.com    SERIALIZE_CONTAINER(dma_done_event_tick);
6427753SWilliam.Wang@arm.com}
6437753SWilliam.Wang@arm.com
6447753SWilliam.Wang@arm.comvoid
64510905Sandreas.sandberg@arm.comPl111::unserialize(CheckpointIn &cp)
6467753SWilliam.Wang@arm.com{
6477753SWilliam.Wang@arm.com    DPRINTF(PL111, "Unserializing ARM PL111\n");
6487753SWilliam.Wang@arm.com
6497753SWilliam.Wang@arm.com    uint32_t lcdTiming0_serial;
6507753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdTiming0_serial);
6517753SWilliam.Wang@arm.com    lcdTiming0 = lcdTiming0_serial;
6527753SWilliam.Wang@arm.com
6537753SWilliam.Wang@arm.com    uint32_t lcdTiming1_serial;
6547753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdTiming1_serial);
6557753SWilliam.Wang@arm.com    lcdTiming1 = lcdTiming1_serial;
6567753SWilliam.Wang@arm.com
6577753SWilliam.Wang@arm.com    uint32_t lcdTiming2_serial;
6587753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdTiming2_serial);
6597753SWilliam.Wang@arm.com    lcdTiming2 = lcdTiming2_serial;
6607753SWilliam.Wang@arm.com
6617753SWilliam.Wang@arm.com    uint32_t lcdTiming3_serial;
6627753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdTiming3_serial);
6637753SWilliam.Wang@arm.com    lcdTiming3 = lcdTiming3_serial;
6647753SWilliam.Wang@arm.com
6657753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdUpbase);
6667753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdLpbase);
6677753SWilliam.Wang@arm.com
6687753SWilliam.Wang@arm.com    uint32_t lcdControl_serial;
6697753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdControl_serial);
6707753SWilliam.Wang@arm.com    lcdControl = lcdControl_serial;
6717753SWilliam.Wang@arm.com
6727753SWilliam.Wang@arm.com    uint8_t lcdImsc_serial;
6737753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdImsc_serial);
6747753SWilliam.Wang@arm.com    lcdImsc = lcdImsc_serial;
6757753SWilliam.Wang@arm.com
6767753SWilliam.Wang@arm.com    uint8_t lcdRis_serial;
6777753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdRis_serial);
6787753SWilliam.Wang@arm.com    lcdRis = lcdRis_serial;
6797753SWilliam.Wang@arm.com
6807753SWilliam.Wang@arm.com    uint8_t lcdMis_serial;
6817753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdMis_serial);
6827753SWilliam.Wang@arm.com    lcdMis = lcdMis_serial;
6837753SWilliam.Wang@arm.com
6847753SWilliam.Wang@arm.com    UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
6857753SWilliam.Wang@arm.com    UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize);
6867753SWilliam.Wang@arm.com
6877753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrCtrl);
6887753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrConfig);
6897753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrPalette0);
6907753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrPalette1);
6917753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrXY);
6927753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrClip);
6937753SWilliam.Wang@arm.com
6947753SWilliam.Wang@arm.com    uint8_t clcdCrsrImsc_serial;
6957753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrImsc_serial);
6967753SWilliam.Wang@arm.com    clcdCrsrImsc = clcdCrsrImsc_serial;
6977753SWilliam.Wang@arm.com
6987753SWilliam.Wang@arm.com    uint8_t clcdCrsrIcr_serial;
6997753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrIcr_serial);
7007753SWilliam.Wang@arm.com    clcdCrsrIcr = clcdCrsrIcr_serial;
7017753SWilliam.Wang@arm.com
7027753SWilliam.Wang@arm.com    uint8_t clcdCrsrRis_serial;
7037753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrRis_serial);
7047753SWilliam.Wang@arm.com    clcdCrsrRis = clcdCrsrRis_serial;
7057753SWilliam.Wang@arm.com
7067753SWilliam.Wang@arm.com    uint8_t clcdCrsrMis_serial;
7077753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
7087753SWilliam.Wang@arm.com    clcdCrsrMis = clcdCrsrMis_serial;
7097753SWilliam.Wang@arm.com
7107753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(height);
7117753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(width);
7127950SAli.Saidi@ARM.com    UNSERIALIZE_SCALAR(bytesPerPixel);
7137753SWilliam.Wang@arm.com
7149415SChander.Sudanthi@arm.com    UNSERIALIZE_ARRAY(dmaBuffer, buffer_size);
7157753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(startTime);
7167753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(startAddr);
7177753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(maxAddr);
7187753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(curAddr);
7197753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(waterMark);
7207753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(dmaPendingNum);
7217950SAli.Saidi@ARM.com
7228062SAli.Saidi@ARM.com    Tick int_event_time = 0;
7238062SAli.Saidi@ARM.com    Tick read_event_time = 0;
7248062SAli.Saidi@ARM.com    Tick fill_fifo_event_time = 0;
7258062SAli.Saidi@ARM.com
7268062SAli.Saidi@ARM.com    UNSERIALIZE_SCALAR(read_event_time);
7278062SAli.Saidi@ARM.com    UNSERIALIZE_SCALAR(fill_fifo_event_time);
7288062SAli.Saidi@ARM.com    UNSERIALIZE_SCALAR(int_event_time);
7298062SAli.Saidi@ARM.com
7308062SAli.Saidi@ARM.com    if (int_event_time)
7318062SAli.Saidi@ARM.com        schedule(intEvent, int_event_time);
7328062SAli.Saidi@ARM.com    if (read_event_time)
7338062SAli.Saidi@ARM.com        schedule(readEvent, read_event_time);
7348062SAli.Saidi@ARM.com    if (fill_fifo_event_time)
7358062SAli.Saidi@ARM.com        schedule(fillFifoEvent, fill_fifo_event_time);
7368062SAli.Saidi@ARM.com
7378062SAli.Saidi@ARM.com    vector<Tick> dma_done_event_tick;
7388062SAli.Saidi@ARM.com    dma_done_event_tick.resize(maxOutstandingDma);
73910905Sandreas.sandberg@arm.com    UNSERIALIZE_CONTAINER(dma_done_event_tick);
7409395SAndreas.Sandberg@ARM.com    dmaDoneEventFree.clear();
7418062SAli.Saidi@ARM.com    for (int x = 0; x < maxOutstandingDma; x++) {
7428062SAli.Saidi@ARM.com        if (dma_done_event_tick[x])
7439395SAndreas.Sandberg@ARM.com            schedule(dmaDoneEventAll[x], dma_done_event_tick[x]);
7449395SAndreas.Sandberg@ARM.com        else
7459395SAndreas.Sandberg@ARM.com            dmaDoneEventFree.push_back(&dmaDoneEventAll[x]);
7468062SAli.Saidi@ARM.com    }
7479395SAndreas.Sandberg@ARM.com    assert(maxOutstandingDma - dmaDoneEventFree.size() == dmaPendingNum);
7488062SAli.Saidi@ARM.com
7498197SAli.Saidi@ARM.com    if (lcdControl.lcdpwr) {
7508197SAli.Saidi@ARM.com        updateVideoParams();
75110839Sandreas.sandberg@arm.com        fb.copyIn(dmaBuffer, converter);
7529330Schander.sudanthi@arm.com        if (vnc)
7539330Schander.sudanthi@arm.com            vnc->setDirty();
7548197SAli.Saidi@ARM.com    }
7557753SWilliam.Wang@arm.com}
7567753SWilliam.Wang@arm.com
7577753SWilliam.Wang@arm.comvoid
7587753SWilliam.Wang@arm.comPl111::generateInterrupt()
7597753SWilliam.Wang@arm.com{
7607753SWilliam.Wang@arm.com    DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
7617950SAli.Saidi@ARM.com            (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis);
7627753SWilliam.Wang@arm.com    lcdMis = lcdImsc & lcdRis;
7637753SWilliam.Wang@arm.com
7647950SAli.Saidi@ARM.com    if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) {
7657753SWilliam.Wang@arm.com        gic->sendInt(intNum);
7667753SWilliam.Wang@arm.com        DPRINTF(PL111, " -- Generated\n");
7677753SWilliam.Wang@arm.com    }
7687753SWilliam.Wang@arm.com}
7697753SWilliam.Wang@arm.com
7708711Sandreas.hansson@arm.comAddrRangeList
7719090Sandreas.hansson@arm.comPl111::getAddrRanges() const
7727753SWilliam.Wang@arm.com{
7738711Sandreas.hansson@arm.com    AddrRangeList ranges;
7748711Sandreas.hansson@arm.com    ranges.push_back(RangeSize(pioAddr, pioSize));
7758711Sandreas.hansson@arm.com    return ranges;
7767753SWilliam.Wang@arm.com}
7777753SWilliam.Wang@arm.com
7787753SWilliam.Wang@arm.comPl111 *
7797753SWilliam.Wang@arm.comPl111Params::create()
7807753SWilliam.Wang@arm.com{
7817753SWilliam.Wang@arm.com    return new Pl111(this);
7827753SWilliam.Wang@arm.com}
7837753SWilliam.Wang@arm.com
7847753SWilliam.Wang@arm.com
785