pl111.cc revision 10367:bf52480abd01
11060SN/A/* 27944SGiacomo.Gabrielli@arm.com * Copyright (c) 2010-2012 ARM Limited 37944SGiacomo.Gabrielli@arm.com * All rights reserved 47944SGiacomo.Gabrielli@arm.com * 57944SGiacomo.Gabrielli@arm.com * The license below extends only to copyright in the software and shall 67944SGiacomo.Gabrielli@arm.com * not be construed as granting a license to any other intellectual 77944SGiacomo.Gabrielli@arm.com * property including but not limited to intellectual property relating 87944SGiacomo.Gabrielli@arm.com * to a hardware implementation of the functionality of the software 97944SGiacomo.Gabrielli@arm.com * licensed hereunder. You may use the software subject to the license 107944SGiacomo.Gabrielli@arm.com * terms below provided that you ensure that this notice is replicated 117944SGiacomo.Gabrielli@arm.com * unmodified and in its entirety in all distributions of the software, 127944SGiacomo.Gabrielli@arm.com * modified or unmodified, in source code or in binary form. 137944SGiacomo.Gabrielli@arm.com * 142702Sktlim@umich.edu * Redistribution and use in source and binary forms, with or without 156973Stjones1@inf.ed.ac.uk * modification, are permitted provided that the following conditions are 161060SN/A * met: redistributions of source code must retain the above copyright 171060SN/A * notice, this list of conditions and the following disclaimer; 181060SN/A * redistributions in binary form must reproduce the above copyright 191060SN/A * notice, this list of conditions and the following disclaimer in the 201060SN/A * documentation and/or other materials provided with the distribution; 211060SN/A * neither the name of the copyright holders nor the names of its 221060SN/A * contributors may be used to endorse or promote products derived from 231060SN/A * this software without specific prior written permission. 241060SN/A * 251060SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 261060SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 271060SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 281060SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 291060SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 301060SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 311060SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 321060SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 331060SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 341060SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 351060SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 361060SN/A * 371060SN/A * Authors: William Wang 381060SN/A * Ali Saidi 391060SN/A */ 402665Ssaidi@eecs.umich.edu 412665Ssaidi@eecs.umich.edu#include "base/vnc/vncinput.hh" 426973Stjones1@inf.ed.ac.uk#include "base/bitmap.hh" 431060SN/A#include "base/output.hh" 441060SN/A#include "base/trace.hh" 451464SN/A#include "debug/PL111.hh" 461464SN/A#include "debug/Uart.hh" 471060SN/A#include "dev/arm/amba_device.hh" 482731Sktlim@umich.edu#include "dev/arm/base_gic.hh" 492292SN/A#include "dev/arm/pl111.hh" 501464SN/A#include "mem/packet.hh" 518733Sgeoffrey.blake@arm.com#include "mem/packet_access.hh" 521060SN/A#include "sim/system.hh" 537720Sgblack@eecs.umich.edu 541060SN/A// clang complains about std::set being overloaded with Packet::set if 556658Snate@binkert.org// we open up the entire namespace std 568887Sgeoffrey.blake@arm.comusing std::vector; 573770Sgblack@eecs.umich.edu 581464SN/A// initialize clcd registers 591464SN/APl111::Pl111(const Params *p) 602669Sktlim@umich.edu : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0), 611060SN/A lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0), 626973Stjones1@inf.ed.ac.uk lcdRis(0), lcdMis(0), 632669Sktlim@umich.edu clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0), 647678Sgblack@eecs.umich.edu clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0), 658817Sgblack@eecs.umich.edu clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), 662292SN/A pixelClock(p->pixel_clock), vnc(p->vnc), bmp(NULL), pic(NULL), 676023Snate@binkert.org width(LcdMaxWidth), height(LcdMaxHeight), 681060SN/A bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0), 691060SN/A waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this), 701060SN/A dmaDoneEventAll(maxOutstandingDma, this), 711060SN/A dmaDoneEventFree(maxOutstandingDma), 721060SN/A intEvent(this), enableCapture(p->enable_capture) 731060SN/A{ 741060SN/A pioSize = 0xFFFF; 759044SAli.Saidi@ARM.com 761060SN/A dmaBuffer = new uint8_t[buffer_size]; 771060SN/A 781060SN/A memset(lcdPalette, 0, sizeof(lcdPalette)); 792733Sktlim@umich.edu memset(cursorImage, 0, sizeof(cursorImage)); 802733Sktlim@umich.edu memset(dmaBuffer, 0, buffer_size); 811060SN/A 822292SN/A for (int i = 0; i < maxOutstandingDma; ++i) 832107SN/A dmaDoneEventFree[i] = &dmaDoneEventAll[i]; 842690Sktlim@umich.edu 852107SN/A if (vnc) 862690Sktlim@umich.edu vnc->setFramebufferAddr(dmaBuffer); 872690Sktlim@umich.edu} 881060SN/A 892292SN/APl111::~Pl111() 902292SN/A{ 918486Sgblack@eecs.umich.edu delete[] dmaBuffer; 922292SN/A} 932292SN/A 942292SN/A// read registers and frame buffer 952292SN/ATick 961060SN/APl111::read(PacketPtr pkt) 975543Ssaidi@eecs.umich.edu{ 988902Sandreas.hansson@arm.com // use a temporary data since the LCD registers are read/written with 991060SN/A // different size operations 1001060SN/A 1012292SN/A uint32_t data = 0; 1022107SN/A 1038502Sgblack@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && 1041060SN/A pkt->getAddr() < pioAddr + pioSize); 1051060SN/A 1061060SN/A Addr daddr = pkt->getAddr() - pioAddr; 1071060SN/A pkt->allocate(); 1081060SN/A 1091060SN/A DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize()); 1102292SN/A 1111060SN/A switch (daddr) { 1121060SN/A case LcdTiming0: 1135358Sgblack@eecs.umich.edu data = lcdTiming0; 1145358Sgblack@eecs.umich.edu break; 1155358Sgblack@eecs.umich.edu case LcdTiming1: 1165358Sgblack@eecs.umich.edu data = lcdTiming1; 1175358Sgblack@eecs.umich.edu break; 1185358Sgblack@eecs.umich.edu case LcdTiming2: 1195358Sgblack@eecs.umich.edu data = lcdTiming2; 1205358Sgblack@eecs.umich.edu break; 1215358Sgblack@eecs.umich.edu case LcdTiming3: 1225358Sgblack@eecs.umich.edu data = lcdTiming3; 1235358Sgblack@eecs.umich.edu break; 1245358Sgblack@eecs.umich.edu case LcdUpBase: 1255358Sgblack@eecs.umich.edu data = lcdUpbase; 1268444Sgblack@eecs.umich.edu break; 1277520Sgblack@eecs.umich.edu case LcdLpBase: 1288444Sgblack@eecs.umich.edu data = lcdLpbase; 1298444Sgblack@eecs.umich.edu break; 1307520Sgblack@eecs.umich.edu case LcdControl: 1316974Stjones1@inf.ed.ac.uk data = lcdControl; 1326974Stjones1@inf.ed.ac.uk break; 1336974Stjones1@inf.ed.ac.uk case LcdImsc: 1346974Stjones1@inf.ed.ac.uk data = lcdImsc; 1356973Stjones1@inf.ed.ac.uk break; 1366974Stjones1@inf.ed.ac.uk case LcdRis: 1376974Stjones1@inf.ed.ac.uk data = lcdRis; 1386973Stjones1@inf.ed.ac.uk break; 1396973Stjones1@inf.ed.ac.uk case LcdMis: 1406973Stjones1@inf.ed.ac.uk data = lcdMis; 1416973Stjones1@inf.ed.ac.uk break; 1421060SN/A case LcdIcr: 1437944SGiacomo.Gabrielli@arm.com panic("LCD register at offset %#x is Write-Only\n", daddr); 1447944SGiacomo.Gabrielli@arm.com break; 1457944SGiacomo.Gabrielli@arm.com case LcdUpCurr: 1467944SGiacomo.Gabrielli@arm.com data = curAddr; 1477944SGiacomo.Gabrielli@arm.com break; 1487944SGiacomo.Gabrielli@arm.com case LcdLpCurr: 1498545Ssaidi@eecs.umich.edu data = curAddr; 1508545Ssaidi@eecs.umich.edu break; 1518545Ssaidi@eecs.umich.edu case ClcdCrsrCtrl: 1528545Ssaidi@eecs.umich.edu data = clcdCrsrCtrl; 1538545Ssaidi@eecs.umich.edu break; 1548545Ssaidi@eecs.umich.edu case ClcdCrsrConfig: 1558545Ssaidi@eecs.umich.edu data = clcdCrsrConfig; 1568545Ssaidi@eecs.umich.edu break; 1578545Ssaidi@eecs.umich.edu case ClcdCrsrPalette0: 1588545Ssaidi@eecs.umich.edu data = clcdCrsrPalette0; 1598545Ssaidi@eecs.umich.edu break; 1608545Ssaidi@eecs.umich.edu case ClcdCrsrPalette1: 1618545Ssaidi@eecs.umich.edu data = clcdCrsrPalette1; 1627944SGiacomo.Gabrielli@arm.com break; 1637944SGiacomo.Gabrielli@arm.com case ClcdCrsrXY: 1647944SGiacomo.Gabrielli@arm.com data = clcdCrsrXY; 1657944SGiacomo.Gabrielli@arm.com break; 1667944SGiacomo.Gabrielli@arm.com case ClcdCrsrClip: 1677944SGiacomo.Gabrielli@arm.com data = clcdCrsrClip; 1687944SGiacomo.Gabrielli@arm.com break; 1697944SGiacomo.Gabrielli@arm.com case ClcdCrsrImsc: 1707944SGiacomo.Gabrielli@arm.com data = clcdCrsrImsc; 1717944SGiacomo.Gabrielli@arm.com break; 1727944SGiacomo.Gabrielli@arm.com case ClcdCrsrIcr: 1737944SGiacomo.Gabrielli@arm.com panic("CLCD register at offset %#x is Write-Only\n", daddr); 1747944SGiacomo.Gabrielli@arm.com break; 1757944SGiacomo.Gabrielli@arm.com case ClcdCrsrRis: 1767944SGiacomo.Gabrielli@arm.com data = clcdCrsrRis; 1777944SGiacomo.Gabrielli@arm.com break; 1787944SGiacomo.Gabrielli@arm.com case ClcdCrsrMis: 1798733Sgeoffrey.blake@arm.com data = clcdCrsrMis; 1808733Sgeoffrey.blake@arm.com break; 1818733Sgeoffrey.blake@arm.com default: 1821684SN/A if (readId(pkt, AMBA_ID, pioAddr)) { 1831060SN/A // Hack for variable size accesses 1841060SN/A data = pkt->get<uint32_t>(); 1851060SN/A break; 1861060SN/A } else if (daddr >= CrsrImage && daddr <= 0xBFC) { 1872731Sktlim@umich.edu // CURSOR IMAGE 1882731Sktlim@umich.edu int index; 1892731Sktlim@umich.edu index = (daddr - CrsrImage) >> 2; 1902731Sktlim@umich.edu data= cursorImage[index]; 1912731Sktlim@umich.edu break; 1922731Sktlim@umich.edu } else if (daddr >= LcdPalette && daddr <= 0x3FC) { 1932731Sktlim@umich.edu // LCD Palette 1942731Sktlim@umich.edu int index; 1952731Sktlim@umich.edu index = (daddr - LcdPalette) >> 2; 1962731Sktlim@umich.edu data = lcdPalette[index]; 1972731Sktlim@umich.edu break; 1982731Sktlim@umich.edu } else { 1992731Sktlim@umich.edu panic("Tried to read CLCD register at offset %#x that " 2002731Sktlim@umich.edu "doesn't exist\n", daddr); 2012731Sktlim@umich.edu break; 2022731Sktlim@umich.edu } 2032731Sktlim@umich.edu } 2042731Sktlim@umich.edu 2052731Sktlim@umich.edu switch(pkt->getSize()) { 2062731Sktlim@umich.edu case 1: 2072731Sktlim@umich.edu pkt->set<uint8_t>(data); 2082731Sktlim@umich.edu break; 2092731Sktlim@umich.edu case 2: 2102731Sktlim@umich.edu pkt->set<uint16_t>(data); 2112731Sktlim@umich.edu break; 2122292SN/A case 4: 2132731Sktlim@umich.edu pkt->set<uint32_t>(data); 2142731Sktlim@umich.edu break; 2151060SN/A default: 2161060SN/A panic("CLCD controller read size too big?\n"); 2176221Snate@binkert.org break; 2181060SN/A } 2191060SN/A 2201060SN/A pkt->makeAtomicResponse(); 2211060SN/A return pioDelay; 2222292SN/A} 2232292SN/A 2242292SN/A// write registers and frame buffer 2252733Sktlim@umich.eduTick 2262733Sktlim@umich.eduPl111::write(PacketPtr pkt) 2271060SN/A{ 2282680Sktlim@umich.edu // use a temporary data since the LCD registers are read/written with 2292292SN/A // different size operations 2301060SN/A // 2311060SN/A uint32_t data = 0; 2322132SN/A 2331060SN/A switch(pkt->getSize()) { 2342702Sktlim@umich.edu case 1: 2352669Sktlim@umich.edu data = pkt->get<uint8_t>(); 2362292SN/A break; 2371060SN/A case 2: 2381060SN/A data = pkt->get<uint16_t>(); 2391060SN/A break; 2408199SAli.Saidi@ARM.com case 4: 2418199SAli.Saidi@ARM.com data = pkt->get<uint32_t>(); 2428199SAli.Saidi@ARM.com break; 2434032Sktlim@umich.edu default: 2444032Sktlim@umich.edu panic("PL111 CLCD controller write size too big?\n"); 2454032Sktlim@umich.edu break; 2461060SN/A } 2471060SN/A 2481060SN/A assert(pkt->getAddr() >= pioAddr && 2491060SN/A pkt->getAddr() < pioAddr + pioSize); 2501060SN/A 2511060SN/A Addr daddr = pkt->getAddr() - pioAddr; 2521464SN/A 2531464SN/A DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr, 2541464SN/A pkt->get<uint8_t>(), pkt->getSize()); 2558733Sgeoffrey.blake@arm.com 2568733Sgeoffrey.blake@arm.com switch (daddr) { 2578733Sgeoffrey.blake@arm.com case LcdTiming0: 2588733Sgeoffrey.blake@arm.com lcdTiming0 = data; 2591464SN/A // width = 16 * (PPL+1) 2601060SN/A width = (lcdTiming0.ppl + 1) << 4; 2618733Sgeoffrey.blake@arm.com break; 2628733Sgeoffrey.blake@arm.com case LcdTiming1: 2631464SN/A lcdTiming1 = data; 2648733Sgeoffrey.blake@arm.com // height = LPP + 1 2651060SN/A height = (lcdTiming1.lpp) + 1; 2663326Sktlim@umich.edu break; 2673326Sktlim@umich.edu case LcdTiming2: 2683326Sktlim@umich.edu lcdTiming2 = data; 2697597Sminkyu.jeong@arm.com break; 2707597Sminkyu.jeong@arm.com case LcdTiming3: 2717597Sminkyu.jeong@arm.com lcdTiming3 = data; 2723965Sgblack@eecs.umich.edu break; 2737720Sgblack@eecs.umich.edu case LcdUpBase: 2747720Sgblack@eecs.umich.edu lcdUpbase = data; 2751060SN/A DPRINTF(PL111, "####### Upper panel base set to: %#x #######\n", lcdUpbase); 2767720Sgblack@eecs.umich.edu break; 2777720Sgblack@eecs.umich.edu case LcdLpBase: 2784636Sgblack@eecs.umich.edu warn_once("LCD dual screen mode not supported\n"); 2793794Sgblack@eecs.umich.edu lcdLpbase = data; 2803794Sgblack@eecs.umich.edu DPRINTF(PL111, "###### Lower panel base set to: %#x #######\n", lcdLpbase); 2813794Sgblack@eecs.umich.edu break; 2823965Sgblack@eecs.umich.edu case LcdControl: 2833965Sgblack@eecs.umich.edu int old_lcdpwr; 2842292SN/A old_lcdpwr = lcdControl.lcdpwr; 2852292SN/A lcdControl = data; 2862292SN/A 2872292SN/A DPRINTF(PL111, "LCD power is:%d\n", lcdControl.lcdpwr); 2882292SN/A 2892292SN/A // LCD power enable 2901060SN/A if (lcdControl.lcdpwr && !old_lcdpwr) { 2911060SN/A updateVideoParams(); 2921060SN/A DPRINTF(PL111, " lcd size: height %d width %d\n", height, width); 2933770Sgblack@eecs.umich.edu waterMark = lcdControl.watermark ? 8 : 4; 2943770Sgblack@eecs.umich.edu startDma(); 2953770Sgblack@eecs.umich.edu } 2963770Sgblack@eecs.umich.edu break; 2973770Sgblack@eecs.umich.edu case LcdImsc: 2983770Sgblack@eecs.umich.edu lcdImsc = data; 2993770Sgblack@eecs.umich.edu if (lcdImsc.vcomp) 3003770Sgblack@eecs.umich.edu panic("Interrupting on vcomp not supported\n"); 3013770Sgblack@eecs.umich.edu 3023770Sgblack@eecs.umich.edu lcdMis = lcdImsc & lcdRis; 3033770Sgblack@eecs.umich.edu 3043770Sgblack@eecs.umich.edu if (!lcdMis) 3053770Sgblack@eecs.umich.edu gic->clearInt(intNum); 3063770Sgblack@eecs.umich.edu 3073770Sgblack@eecs.umich.edu break; 3083770Sgblack@eecs.umich.edu case LcdRis: 3093770Sgblack@eecs.umich.edu panic("LCD register at offset %#x is Read-Only\n", daddr); 3103770Sgblack@eecs.umich.edu break; 3113770Sgblack@eecs.umich.edu case LcdMis: 3123770Sgblack@eecs.umich.edu panic("LCD register at offset %#x is Read-Only\n", daddr); 3133770Sgblack@eecs.umich.edu break; 3143770Sgblack@eecs.umich.edu case LcdIcr: 3153770Sgblack@eecs.umich.edu lcdRis = lcdRis & ~data; 3163770Sgblack@eecs.umich.edu lcdMis = lcdImsc & lcdRis; 3173770Sgblack@eecs.umich.edu 3183770Sgblack@eecs.umich.edu if (!lcdMis) 3191060SN/A gic->clearInt(intNum); 3203770Sgblack@eecs.umich.edu 3213770Sgblack@eecs.umich.edu break; 3223770Sgblack@eecs.umich.edu case LcdUpCurr: 3233770Sgblack@eecs.umich.edu panic("LCD register at offset %#x is Read-Only\n", daddr); 3243770Sgblack@eecs.umich.edu break; 3253770Sgblack@eecs.umich.edu case LcdLpCurr: 3263770Sgblack@eecs.umich.edu panic("LCD register at offset %#x is Read-Only\n", daddr); 3273770Sgblack@eecs.umich.edu break; 3283770Sgblack@eecs.umich.edu case ClcdCrsrCtrl: 3293770Sgblack@eecs.umich.edu clcdCrsrCtrl = data; 3303770Sgblack@eecs.umich.edu break; 3313770Sgblack@eecs.umich.edu case ClcdCrsrConfig: 3323770Sgblack@eecs.umich.edu clcdCrsrConfig = data; 3333770Sgblack@eecs.umich.edu break; 3343770Sgblack@eecs.umich.edu case ClcdCrsrPalette0: 3353770Sgblack@eecs.umich.edu clcdCrsrPalette0 = data; 3363770Sgblack@eecs.umich.edu break; 3373770Sgblack@eecs.umich.edu case ClcdCrsrPalette1: 3383770Sgblack@eecs.umich.edu clcdCrsrPalette1 = data; 3393770Sgblack@eecs.umich.edu break; 3403770Sgblack@eecs.umich.edu case ClcdCrsrXY: 3413770Sgblack@eecs.umich.edu clcdCrsrXY = data; 3423770Sgblack@eecs.umich.edu break; 3433770Sgblack@eecs.umich.edu case ClcdCrsrClip: 3443770Sgblack@eecs.umich.edu clcdCrsrClip = data; 3453770Sgblack@eecs.umich.edu break; 3463770Sgblack@eecs.umich.edu case ClcdCrsrImsc: 3473770Sgblack@eecs.umich.edu clcdCrsrImsc = data; 3483770Sgblack@eecs.umich.edu break; 3493770Sgblack@eecs.umich.edu case ClcdCrsrIcr: 3503770Sgblack@eecs.umich.edu clcdCrsrIcr = data; 3513770Sgblack@eecs.umich.edu break; 3523770Sgblack@eecs.umich.edu case ClcdCrsrRis: 3533770Sgblack@eecs.umich.edu panic("CLCD register at offset %#x is Read-Only\n", daddr); 3543770Sgblack@eecs.umich.edu break; 3553770Sgblack@eecs.umich.edu case ClcdCrsrMis: 3563770Sgblack@eecs.umich.edu panic("CLCD register at offset %#x is Read-Only\n", daddr); 3573770Sgblack@eecs.umich.edu break; 3583770Sgblack@eecs.umich.edu default: 3593770Sgblack@eecs.umich.edu if (daddr >= CrsrImage && daddr <= 0xBFC) { 3603770Sgblack@eecs.umich.edu // CURSOR IMAGE 3613770Sgblack@eecs.umich.edu int index; 3623770Sgblack@eecs.umich.edu index = (daddr - CrsrImage) >> 2; 3633770Sgblack@eecs.umich.edu cursorImage[index] = data; 3643770Sgblack@eecs.umich.edu break; 3653770Sgblack@eecs.umich.edu } else if (daddr >= LcdPalette && daddr <= 0x3FC) { 3663770Sgblack@eecs.umich.edu // LCD Palette 3673770Sgblack@eecs.umich.edu int index; 3683770Sgblack@eecs.umich.edu index = (daddr - LcdPalette) >> 2; 3693770Sgblack@eecs.umich.edu lcdPalette[index] = data; 3703770Sgblack@eecs.umich.edu break; 3713770Sgblack@eecs.umich.edu } else { 3723770Sgblack@eecs.umich.edu panic("Tried to write PL111 register at offset %#x that " 3733770Sgblack@eecs.umich.edu "doesn't exist\n", daddr); 3743770Sgblack@eecs.umich.edu break; 3753770Sgblack@eecs.umich.edu } 3763770Sgblack@eecs.umich.edu } 3773770Sgblack@eecs.umich.edu 3783770Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 3793770Sgblack@eecs.umich.edu return pioDelay; 3803770Sgblack@eecs.umich.edu} 3813770Sgblack@eecs.umich.edu 3823770Sgblack@eecs.umich.eduvoid 3833770Sgblack@eecs.umich.eduPl111::updateVideoParams() 3843770Sgblack@eecs.umich.edu{ 3853770Sgblack@eecs.umich.edu if (lcdControl.lcdbpp == bpp24) { 3863770Sgblack@eecs.umich.edu bytesPerPixel = 4; 3873770Sgblack@eecs.umich.edu } else if (lcdControl.lcdbpp == bpp16m565) { 3883770Sgblack@eecs.umich.edu bytesPerPixel = 2; 3893770Sgblack@eecs.umich.edu } 3903770Sgblack@eecs.umich.edu 3914636Sgblack@eecs.umich.edu if (vnc) { 3924636Sgblack@eecs.umich.edu if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr) 3937720Sgblack@eecs.umich.edu vnc->setFrameBufferParams(VideoConvert::bgr8888, width, 3947720Sgblack@eecs.umich.edu height); 3954636Sgblack@eecs.umich.edu else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr) 3964636Sgblack@eecs.umich.edu vnc->setFrameBufferParams(VideoConvert::rgb8888, width, 3974636Sgblack@eecs.umich.edu height); 3988502Sgblack@eecs.umich.edu else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr) 3998502Sgblack@eecs.umich.edu vnc->setFrameBufferParams(VideoConvert::bgr565, width, 4008502Sgblack@eecs.umich.edu height); 4013770Sgblack@eecs.umich.edu else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr) 4022292SN/A vnc->setFrameBufferParams(VideoConvert::rgb565, width, 4032292SN/A height); 4042292SN/A else 4058502Sgblack@eecs.umich.edu panic("Unimplemented video mode\n"); 4061060SN/A } 4071060SN/A 4081060SN/A if (bmp) 4091060SN/A delete bmp; 4101464SN/A 4111684SN/A if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr) 4121464SN/A bmp = new Bitmap(VideoConvert::bgr8888, width, height, dmaBuffer); 4131060SN/A else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr) 4141464SN/A bmp = new Bitmap(VideoConvert::rgb8888, width, height, dmaBuffer); 4151060SN/A else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr) 4161060SN/A bmp = new Bitmap(VideoConvert::bgr565, width, height, dmaBuffer); 4171060SN/A else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr) 4181060SN/A bmp = new Bitmap(VideoConvert::rgb565, width, height, dmaBuffer); 4191060SN/A else 4201060SN/A panic("Unimplemented video mode\n"); 4213326Sktlim@umich.edu} 4225712Shsul@eecs.umich.edu 4233326Sktlim@umich.eduvoid 4248832SAli.Saidi@ARM.comPl111::startDma() 4258832SAli.Saidi@ARM.com{ 4268832SAli.Saidi@ARM.com if (dmaPendingNum != 0 || readEvent.scheduled()) 4275714Shsul@eecs.umich.edu return; 4285714Shsul@eecs.umich.edu readFramebuffer(); 4295714Shsul@eecs.umich.edu} 4301060SN/A 4312132SN/Avoid 4321060SN/APl111::readFramebuffer() 4331060SN/A{ 4341060SN/A // initialization for dma read from frame buffer to dma buffer 4351060SN/A uint32_t length = height * width; 4362292SN/A if (startAddr != lcdUpbase) 4371060SN/A startAddr = lcdUpbase; 4381060SN/A 4391060SN/A // Updating base address, interrupt if we're supposed to 4407720Sgblack@eecs.umich.edu lcdRis.baseaddr = 1; 4417720Sgblack@eecs.umich.edu if (!intEvent.scheduled()) 4423965Sgblack@eecs.umich.edu schedule(intEvent, clockEdge()); 4437720Sgblack@eecs.umich.edu 4443965Sgblack@eecs.umich.edu curAddr = 0; 4452935Sksewell@umich.edu startTime = curTick(); 4467720Sgblack@eecs.umich.edu 4471060SN/A maxAddr = static_cast<Addr>(length * bytesPerPixel); 4483794Sgblack@eecs.umich.edu 4497720Sgblack@eecs.umich.edu DPRINTF(PL111, " lcd frame buffer size of %d bytes \n", maxAddr); 4503794Sgblack@eecs.umich.edu 4513794Sgblack@eecs.umich.edu fillFifo(); 4527720Sgblack@eecs.umich.edu} 4531060SN/A 4544636Sgblack@eecs.umich.eduvoid 4557720Sgblack@eecs.umich.eduPl111::fillFifo() 4564636Sgblack@eecs.umich.edu{ 4571060SN/A while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) { 4583794Sgblack@eecs.umich.edu // concurrent dma reads need different dma done events 4593794Sgblack@eecs.umich.edu // due to assertion in scheduling state 4603794Sgblack@eecs.umich.edu ++dmaPendingNum; 4613794Sgblack@eecs.umich.edu 4623794Sgblack@eecs.umich.edu assert(!dmaDoneEventFree.empty()); 4633794Sgblack@eecs.umich.edu DmaDoneEvent *event(dmaDoneEventFree.back()); 4643794Sgblack@eecs.umich.edu dmaDoneEventFree.pop_back(); 4653794Sgblack@eecs.umich.edu assert(!event->scheduled()); 4663794Sgblack@eecs.umich.edu 4671060SN/A // We use a uncachable request here because the requests from the CPU 4681060SN/A // will be uncacheable as well. If we have uncacheable and cacheable 4692935Sksewell@umich.edu // requests in the memory system for the same address it won't be 4703794Sgblack@eecs.umich.edu // pleased 4717720Sgblack@eecs.umich.edu dmaPort.dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize, 4727720Sgblack@eecs.umich.edu event, curAddr + dmaBuffer, 4737720Sgblack@eecs.umich.edu 0, Request::UNCACHEABLE); 4743794Sgblack@eecs.umich.edu curAddr += dmaSize; 4753794Sgblack@eecs.umich.edu } 4761060SN/A} 4771060SN/A 4781060SN/Avoid 4795543Ssaidi@eecs.umich.eduPl111::dmaDone() 4805543Ssaidi@eecs.umich.edu{ 4815543Ssaidi@eecs.umich.edu DPRINTF(PL111, "DMA Done\n"); 4825543Ssaidi@eecs.umich.edu 4832336SN/A Tick maxFrameTime = lcdTiming2.cpl * height * pixelClock; 4842336SN/A 4851060SN/A --dmaPendingNum; 4861060SN/A 4875543Ssaidi@eecs.umich.edu if (maxAddr == curAddr && !dmaPendingNum) { 4885543Ssaidi@eecs.umich.edu if ((curTick() - startTime) > maxFrameTime) { 4895543Ssaidi@eecs.umich.edu warn("CLCD controller buffer underrun, took %d ticks when should" 4905543Ssaidi@eecs.umich.edu " have taken %d\n", curTick() - startTime, maxFrameTime); 4915543Ssaidi@eecs.umich.edu lcdRis.underflow = 1; 4925543Ssaidi@eecs.umich.edu if (!intEvent.scheduled()) 4931060SN/A schedule(intEvent, clockEdge()); 4945543Ssaidi@eecs.umich.edu } 4955543Ssaidi@eecs.umich.edu 4962935Sksewell@umich.edu assert(!readEvent.scheduled()); 4971060SN/A if (vnc) 4981060SN/A vnc->setDirty(); 4992292SN/A 5002731Sktlim@umich.edu if (enableCapture) { 5012292SN/A DPRINTF(PL111, "-- write out frame buffer into bmp\n"); 5022731Sktlim@umich.edu 5037784SAli.Saidi@ARM.com if (!pic) 5041060SN/A pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true); 5051060SN/A 5061060SN/A assert(bmp); 5072292SN/A assert(pic); 5082336SN/A pic->seekp(0); 5092308SN/A bmp->write(pic); 5104828Sgblack@eecs.umich.edu } 5114654Sgblack@eecs.umich.edu 5124654Sgblack@eecs.umich.edu // schedule the next read based on when the last frame started 5134636Sgblack@eecs.umich.edu // and the desired fps (i.e. maxFrameTime), we turn the 5144654Sgblack@eecs.umich.edu // argument into a relative number of cycles in the future 5154654Sgblack@eecs.umich.edu if (lcdControl.lcden) 5164636Sgblack@eecs.umich.edu schedule(readEvent, clockEdge(ticksToCycles(startTime - 5172292SN/A curTick() + 5182292SN/A maxFrameTime))); 5192731Sktlim@umich.edu } 5202292SN/A 5212292SN/A if (dmaPendingNum > (maxOutstandingDma - waterMark)) 5222731Sktlim@umich.edu return; 5232292SN/A 5242292SN/A if (!fillFifoEvent.scheduled()) 5252731Sktlim@umich.edu schedule(fillFifoEvent, clockEdge()); 5262292SN/A} 5272292SN/A 5282731Sktlim@umich.eduvoid 5292292SN/APl111::serialize(std::ostream &os) 5302292SN/A{ 5312731Sktlim@umich.edu DPRINTF(PL111, "Serializing ARM PL111\n"); 5322292SN/A 5332292SN/A uint32_t lcdTiming0_serial = lcdTiming0; 5342731Sktlim@umich.edu SERIALIZE_SCALAR(lcdTiming0_serial); 5352292SN/A 5362731Sktlim@umich.edu uint32_t lcdTiming1_serial = lcdTiming1; 5372731Sktlim@umich.edu SERIALIZE_SCALAR(lcdTiming1_serial); 5382292SN/A 5392292SN/A uint32_t lcdTiming2_serial = lcdTiming2; 5402292SN/A SERIALIZE_SCALAR(lcdTiming2_serial); 5412292SN/A 5422292SN/A uint32_t lcdTiming3_serial = lcdTiming3; 5432292SN/A SERIALIZE_SCALAR(lcdTiming3_serial); 5442731Sktlim@umich.edu 5451060SN/A SERIALIZE_SCALAR(lcdUpbase); 5461464SN/A SERIALIZE_SCALAR(lcdLpbase); 5471464SN/A 5481464SN/A uint32_t lcdControl_serial = lcdControl; 5491464SN/A SERIALIZE_SCALAR(lcdControl_serial); 5507720Sgblack@eecs.umich.edu 5517720Sgblack@eecs.umich.edu uint8_t lcdImsc_serial = lcdImsc; 5521464SN/A SERIALIZE_SCALAR(lcdImsc_serial); 5532292SN/A 5545543Ssaidi@eecs.umich.edu uint8_t lcdRis_serial = lcdRis; 5551684SN/A SERIALIZE_SCALAR(lcdRis_serial); 5562292SN/A 5571060SN/A uint8_t lcdMis_serial = lcdMis; 5581060SN/A SERIALIZE_SCALAR(lcdMis_serial); 5591060SN/A 5601060SN/A SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize); 5611060SN/A SERIALIZE_ARRAY(cursorImage, CrsrImageSize); 5621060SN/A 5631060SN/A SERIALIZE_SCALAR(clcdCrsrCtrl); 5641060SN/A SERIALIZE_SCALAR(clcdCrsrConfig); 5652292SN/A SERIALIZE_SCALAR(clcdCrsrPalette0); 5661060SN/A SERIALIZE_SCALAR(clcdCrsrPalette1); 5671060SN/A SERIALIZE_SCALAR(clcdCrsrXY); 5682292SN/A SERIALIZE_SCALAR(clcdCrsrClip); 5691060SN/A 5708733Sgeoffrey.blake@arm.com uint8_t clcdCrsrImsc_serial = clcdCrsrImsc; 5718733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(clcdCrsrImsc_serial); 5728733Sgeoffrey.blake@arm.com 5738733Sgeoffrey.blake@arm.com uint8_t clcdCrsrIcr_serial = clcdCrsrIcr; 5748733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(clcdCrsrIcr_serial); 5758733Sgeoffrey.blake@arm.com 5768733Sgeoffrey.blake@arm.com uint8_t clcdCrsrRis_serial = clcdCrsrRis; 5778733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(clcdCrsrRis_serial); 5788733Sgeoffrey.blake@arm.com 5791684SN/A uint8_t clcdCrsrMis_serial = clcdCrsrMis; 5808733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(clcdCrsrMis_serial); 5818733Sgeoffrey.blake@arm.com 5828733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(height); 5838733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(width); 5848733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(bytesPerPixel); 5858733Sgeoffrey.blake@arm.com 5861684SN/A SERIALIZE_ARRAY(dmaBuffer, buffer_size); 5878733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(startTime); 5888733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(startAddr); 5898733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(maxAddr); 5908733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(curAddr); 5918733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(waterMark); 5928733Sgeoffrey.blake@arm.com SERIALIZE_SCALAR(dmaPendingNum); 5938733Sgeoffrey.blake@arm.com 5948733Sgeoffrey.blake@arm.com Tick int_event_time = 0; 5958733Sgeoffrey.blake@arm.com Tick read_event_time = 0; 5968733Sgeoffrey.blake@arm.com Tick fill_fifo_event_time = 0; 5971060SN/A 5982702Sktlim@umich.edu if (readEvent.scheduled()) 5993735Sstever@eecs.umich.edu read_event_time = readEvent.when(); 6001060SN/A if (fillFifoEvent.scheduled()) 6018733Sgeoffrey.blake@arm.com fill_fifo_event_time = fillFifoEvent.when(); 6021060SN/A if (intEvent.scheduled()) 6031060SN/A int_event_time = intEvent.when(); 6042702Sktlim@umich.edu 6053735Sstever@eecs.umich.edu SERIALIZE_SCALAR(read_event_time); 6063735Sstever@eecs.umich.edu SERIALIZE_SCALAR(fill_fifo_event_time); 6072690Sktlim@umich.edu SERIALIZE_SCALAR(int_event_time); 6088733Sgeoffrey.blake@arm.com 6098733Sgeoffrey.blake@arm.com vector<Tick> dma_done_event_tick; 6108733Sgeoffrey.blake@arm.com dma_done_event_tick.resize(maxOutstandingDma); 6118733Sgeoffrey.blake@arm.com for (int x = 0; x < maxOutstandingDma; x++) { 6123326Sktlim@umich.edu dma_done_event_tick[x] = dmaDoneEventAll[x].scheduled() ? 6132690Sktlim@umich.edu dmaDoneEventAll[x].when() : 0; 6142690Sktlim@umich.edu } 6152702Sktlim@umich.edu arrayParamOut(os, "dma_done_event_tick", dma_done_event_tick); 6163735Sstever@eecs.umich.edu} 6171060SN/A 6188733Sgeoffrey.blake@arm.comvoid 6192308SN/APl111::unserialize(Checkpoint *cp, const std::string §ion) 6201060SN/A{ 6212702Sktlim@umich.edu DPRINTF(PL111, "Unserializing ARM PL111\n"); 6223735Sstever@eecs.umich.edu 6233735Sstever@eecs.umich.edu uint32_t lcdTiming0_serial; 6242308SN/A UNSERIALIZE_SCALAR(lcdTiming0_serial); 6258733Sgeoffrey.blake@arm.com lcdTiming0 = lcdTiming0_serial; 6262308SN/A 6271060SN/A uint32_t lcdTiming1_serial; 6282702Sktlim@umich.edu UNSERIALIZE_SCALAR(lcdTiming1_serial); 6293735Sstever@eecs.umich.edu lcdTiming1 = lcdTiming1_serial; 6302308SN/A 6318733Sgeoffrey.blake@arm.com uint32_t lcdTiming2_serial; 6321060SN/A UNSERIALIZE_SCALAR(lcdTiming2_serial); 6331060SN/A lcdTiming2 = lcdTiming2_serial; 6342190SN/A 6352292SN/A uint32_t lcdTiming3_serial; 6362190SN/A UNSERIALIZE_SCALAR(lcdTiming3_serial); 6372331SN/A lcdTiming3 = lcdTiming3_serial; 6382292SN/A 6392190SN/A UNSERIALIZE_SCALAR(lcdUpbase); 6401684SN/A UNSERIALIZE_SCALAR(lcdLpbase); 6411464SN/A 6421464SN/A uint32_t lcdControl_serial; 6431464SN/A UNSERIALIZE_SCALAR(lcdControl_serial); 6441464SN/A lcdControl = lcdControl_serial; 6451464SN/A 6461684SN/A uint8_t lcdImsc_serial; 6472731Sktlim@umich.edu UNSERIALIZE_SCALAR(lcdImsc_serial); 6481464SN/A lcdImsc = lcdImsc_serial; 6492292SN/A 6502731Sktlim@umich.edu uint8_t lcdRis_serial; 6511464SN/A UNSERIALIZE_SCALAR(lcdRis_serial); 6522731Sktlim@umich.edu lcdRis = lcdRis_serial; 6532731Sktlim@umich.edu 6542308SN/A uint8_t lcdMis_serial; 6552731Sktlim@umich.edu UNSERIALIZE_SCALAR(lcdMis_serial); 6562731Sktlim@umich.edu lcdMis = lcdMis_serial; 6572308SN/A 6581060SN/A UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize); 6592731Sktlim@umich.edu UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize); 6601060SN/A 6611060SN/A UNSERIALIZE_SCALAR(clcdCrsrCtrl); 6622731Sktlim@umich.edu UNSERIALIZE_SCALAR(clcdCrsrConfig); 6631060SN/A UNSERIALIZE_SCALAR(clcdCrsrPalette0); 6644032Sktlim@umich.edu UNSERIALIZE_SCALAR(clcdCrsrPalette1); 6654032Sktlim@umich.edu UNSERIALIZE_SCALAR(clcdCrsrXY); 6664032Sktlim@umich.edu UNSERIALIZE_SCALAR(clcdCrsrClip); 6671060SN/A 6682731Sktlim@umich.edu uint8_t clcdCrsrImsc_serial; 6691060SN/A UNSERIALIZE_SCALAR(clcdCrsrImsc_serial); 6701060SN/A clcdCrsrImsc = clcdCrsrImsc_serial; 6712731Sktlim@umich.edu 6721060SN/A uint8_t clcdCrsrIcr_serial; 6734032Sktlim@umich.edu UNSERIALIZE_SCALAR(clcdCrsrIcr_serial); 6744032Sktlim@umich.edu clcdCrsrIcr = clcdCrsrIcr_serial; 6754032Sktlim@umich.edu 6761060SN/A uint8_t clcdCrsrRis_serial; 6772731Sktlim@umich.edu UNSERIALIZE_SCALAR(clcdCrsrRis_serial); 6781060SN/A clcdCrsrRis = clcdCrsrRis_serial; 6791060SN/A 6802731Sktlim@umich.edu uint8_t clcdCrsrMis_serial; 6811060SN/A UNSERIALIZE_SCALAR(clcdCrsrMis_serial); 6821060SN/A clcdCrsrMis = clcdCrsrMis_serial; 6832731Sktlim@umich.edu 6841060SN/A UNSERIALIZE_SCALAR(height); 6851061SN/A UNSERIALIZE_SCALAR(width); 6862731Sktlim@umich.edu UNSERIALIZE_SCALAR(bytesPerPixel); 6871061SN/A 6881060SN/A UNSERIALIZE_ARRAY(dmaBuffer, buffer_size); 6892731Sktlim@umich.edu UNSERIALIZE_SCALAR(startTime); 6902731Sktlim@umich.edu UNSERIALIZE_SCALAR(startAddr); 6912731Sktlim@umich.edu UNSERIALIZE_SCALAR(maxAddr); 6922731Sktlim@umich.edu UNSERIALIZE_SCALAR(curAddr); 6932731Sktlim@umich.edu UNSERIALIZE_SCALAR(waterMark); 6941060SN/A UNSERIALIZE_SCALAR(dmaPendingNum); 6952292SN/A 6962731Sktlim@umich.edu Tick int_event_time = 0; 6972292SN/A Tick read_event_time = 0; 6982292SN/A Tick fill_fifo_event_time = 0; 6992731Sktlim@umich.edu 7002292SN/A UNSERIALIZE_SCALAR(read_event_time); 7011060SN/A UNSERIALIZE_SCALAR(fill_fifo_event_time); 7022731Sktlim@umich.edu UNSERIALIZE_SCALAR(int_event_time); 7031060SN/A 7041060SN/A if (int_event_time) 7052731Sktlim@umich.edu schedule(intEvent, int_event_time); 7061060SN/A if (read_event_time) 7072292SN/A schedule(readEvent, read_event_time); 7082292SN/A if (fill_fifo_event_time) 7092292SN/A schedule(fillFifoEvent, fill_fifo_event_time); 7102731Sktlim@umich.edu 7112292SN/A vector<Tick> dma_done_event_tick; 7122292SN/A dma_done_event_tick.resize(maxOutstandingDma); 7132731Sktlim@umich.edu arrayParamIn(cp, section, "dma_done_event_tick", dma_done_event_tick); 7142731Sktlim@umich.edu dmaDoneEventFree.clear(); 7152731Sktlim@umich.edu for (int x = 0; x < maxOutstandingDma; x++) { 7162731Sktlim@umich.edu if (dma_done_event_tick[x]) 7172292SN/A schedule(dmaDoneEventAll[x], dma_done_event_tick[x]); 7181060SN/A else 7192731Sktlim@umich.edu dmaDoneEventFree.push_back(&dmaDoneEventAll[x]); 7201060SN/A } 7211060SN/A assert(maxOutstandingDma - dmaDoneEventFree.size() == dmaPendingNum); 7222731Sktlim@umich.edu 7232292SN/A if (lcdControl.lcdpwr) { 7242292SN/A updateVideoParams(); 7252292SN/A if (vnc) 7262292SN/A vnc->setDirty(); 7272292SN/A } 7282731Sktlim@umich.edu} 7292292SN/A 7302292SN/Avoid 7312731Sktlim@umich.eduPl111::generateInterrupt() 7322731Sktlim@umich.edu{ 7332731Sktlim@umich.edu DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n", 7342731Sktlim@umich.edu (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis); 7352292SN/A lcdMis = lcdImsc & lcdRis; 7362292SN/A 7372731Sktlim@umich.edu if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) { 7382292SN/A gic->sendInt(intNum); 7392292SN/A DPRINTF(PL111, " -- Generated\n"); 7402731Sktlim@umich.edu } 7412292SN/A} 7422292SN/A 7432292SN/AAddrRangeList 7442292SN/APl111::getAddrRanges() const 7452292SN/A{ 7462731Sktlim@umich.edu AddrRangeList ranges; 7472292SN/A ranges.push_back(RangeSize(pioAddr, pioSize)); 7482292SN/A return ranges; 7492731Sktlim@umich.edu} 7502731Sktlim@umich.edu 7512731Sktlim@umich.eduPl111 * 7522731Sktlim@umich.eduPl111Params::create() 7532292SN/A{ 7542292SN/A return new Pl111(this); 7552731Sktlim@umich.edu} 7562292SN/A 7572292SN/A 7582731Sktlim@umich.edu