hdlcd.cc revision 10840:48039363f67a
1955SN/A/* 2955SN/A * Copyright (c) 2010-2013, 2015 ARM Limited 31762SN/A * All rights reserved 4955SN/A * 5955SN/A * The license below extends only to copyright in the software and shall 6955SN/A * not be construed as granting a license to any other intellectual 7955SN/A * property including but not limited to intellectual property relating 8955SN/A * to a hardware implementation of the functionality of the software 9955SN/A * licensed hereunder. You may use the software subject to the license 10955SN/A * terms below provided that you ensure that this notice is replicated 11955SN/A * unmodified and in its entirety in all distributions of the software, 12955SN/A * modified or unmodified, in source code or in binary form. 13955SN/A * 14955SN/A * Redistribution and use in source and binary forms, with or without 15955SN/A * modification, are permitted provided that the following conditions are 16955SN/A * met: redistributions of source code must retain the above copyright 17955SN/A * notice, this list of conditions and the following disclaimer; 18955SN/A * redistributions in binary form must reproduce the above copyright 19955SN/A * notice, this list of conditions and the following disclaimer in the 20955SN/A * documentation and/or other materials provided with the distribution; 21955SN/A * neither the name of the copyright holders nor the names of its 22955SN/A * contributors may be used to endorse or promote products derived from 23955SN/A * this software without specific prior written permission. 24955SN/A * 25955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282665Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292665Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 352632Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 362632Sstever@eecs.umich.edu * 372632Sstever@eecs.umich.edu * Authors: Chris Emmons 382632Sstever@eecs.umich.edu */ 39955SN/A 402632Sstever@eecs.umich.edu#include "dev/arm/hdlcd.hh" 412632Sstever@eecs.umich.edu 422761Sstever@eecs.umich.edu#include "base/vnc/vncinput.hh" 432632Sstever@eecs.umich.edu#include "base/output.hh" 442632Sstever@eecs.umich.edu#include "base/trace.hh" 452632Sstever@eecs.umich.edu#include "debug/HDLcd.hh" 462761Sstever@eecs.umich.edu#include "debug/Uart.hh" 472761Sstever@eecs.umich.edu#include "dev/arm/amba_device.hh" 482761Sstever@eecs.umich.edu#include "dev/arm/base_gic.hh" 492632Sstever@eecs.umich.edu#include "mem/packet.hh" 502632Sstever@eecs.umich.edu#include "mem/packet_access.hh" 512761Sstever@eecs.umich.edu#include "sim/system.hh" 522761Sstever@eecs.umich.edu 532761Sstever@eecs.umich.eduusing std::vector; 542761Sstever@eecs.umich.edu 552761Sstever@eecs.umich.edu 562632Sstever@eecs.umich.edu// initialize hdlcd registers 572632Sstever@eecs.umich.eduHDLcd::HDLcd(const Params *p) 582632Sstever@eecs.umich.edu : AmbaDmaDevice(p), version(VERSION_RESETV), 592632Sstever@eecs.umich.edu int_rawstat(0), int_clear(0), int_mask(0), int_status(0), 602632Sstever@eecs.umich.edu fb_base(0), fb_line_length(0), fb_line_count(0), fb_line_pitch(0), 612632Sstever@eecs.umich.edu bus_options(BUS_OPTIONS_RESETV), 622632Sstever@eecs.umich.edu v_sync(0), v_back_porch(0), v_data(0), v_front_porch(0), 63955SN/A h_sync(0), h_back_porch(0), h_data(0), h_front_porch(0), 64955SN/A polarities(0), command(0), pixel_format(0), 65955SN/A red_select(0), green_select(0), blue_select(0), 66955SN/A pixelClock(p->pixel_clock), 67955SN/A fb(0, 0), vnc(p->vnc), bmp(&fb), pic(NULL), 685396Ssaidi@eecs.umich.edu frameReadStartTime(0), 694202Sbinkertn@umich.edu dmaStartAddr(0), dmaCurAddr(0), dmaMaxAddr(0), dmaPendingNum(0), 705342Sstever@gmail.com frameUnderrun(false), pixelBufferSize(0), 71955SN/A pixelIndex(0), doUpdateParams(false), frameUnderway(false), 725273Sstever@gmail.com dmaBytesInFlight(0), 735273Sstever@gmail.com startFrameEvent(this), endFrameEvent(this), renderPixelEvent(this), 742656Sstever@eecs.umich.edu fillPixelBufferEvent(this), intEvent(this), 752656Sstever@eecs.umich.edu dmaDoneEventAll(MAX_OUTSTANDING_DMA_REQ_CAPACITY, this), 762656Sstever@eecs.umich.edu dmaDoneEventFree(MAX_OUTSTANDING_DMA_REQ_CAPACITY), 772656Sstever@eecs.umich.edu enableCapture(p->enable_capture), 782656Sstever@eecs.umich.edu workaround_swap_rb(p->workaround_swap_rb) 792656Sstever@eecs.umich.edu{ 802656Sstever@eecs.umich.edu pioSize = 0xFFFF; 812653Sstever@eecs.umich.edu 825227Ssaidi@eecs.umich.edu for (int i = 0; i < MAX_OUTSTANDING_DMA_REQ_CAPACITY; ++i) 835227Ssaidi@eecs.umich.edu dmaDoneEventFree[i] = &dmaDoneEventAll[i]; 845227Ssaidi@eecs.umich.edu 855227Ssaidi@eecs.umich.edu if (vnc) 865396Ssaidi@eecs.umich.edu vnc->setFrameBuffer(&fb); 875396Ssaidi@eecs.umich.edu} 885396Ssaidi@eecs.umich.edu 895396Ssaidi@eecs.umich.eduHDLcd::~HDLcd() 905396Ssaidi@eecs.umich.edu{ 915396Ssaidi@eecs.umich.edu} 925396Ssaidi@eecs.umich.edu 935396Ssaidi@eecs.umich.edu// read registers and frame buffer 945396Ssaidi@eecs.umich.eduTick 955396Ssaidi@eecs.umich.eduHDLcd::read(PacketPtr pkt) 965396Ssaidi@eecs.umich.edu{ 975396Ssaidi@eecs.umich.edu uint32_t data = 0; 985396Ssaidi@eecs.umich.edu const Addr daddr = pkt->getAddr() - pioAddr; 995396Ssaidi@eecs.umich.edu 1005396Ssaidi@eecs.umich.edu DPRINTF(HDLcd, "read register BASE+0x%04x size=%d\n", daddr, 1015396Ssaidi@eecs.umich.edu pkt->getSize()); 1025396Ssaidi@eecs.umich.edu 1035396Ssaidi@eecs.umich.edu assert(pkt->getAddr() >= pioAddr && 1045396Ssaidi@eecs.umich.edu pkt->getAddr() < pioAddr + pioSize && 1055396Ssaidi@eecs.umich.edu pkt->getSize() == 4); 1065396Ssaidi@eecs.umich.edu 1075396Ssaidi@eecs.umich.edu switch (daddr) { 1085396Ssaidi@eecs.umich.edu case Version: 1095396Ssaidi@eecs.umich.edu data = version; 1105396Ssaidi@eecs.umich.edu break; 1115396Ssaidi@eecs.umich.edu case Int_RawStat: 1125396Ssaidi@eecs.umich.edu data = int_rawstat; 1135396Ssaidi@eecs.umich.edu break; 1145396Ssaidi@eecs.umich.edu case Int_Clear: 1155396Ssaidi@eecs.umich.edu panic("HDLCD INT_CLEAR register is Write-Only\n"); 1165396Ssaidi@eecs.umich.edu break; 1175396Ssaidi@eecs.umich.edu case Int_Mask: 1185396Ssaidi@eecs.umich.edu data = int_mask; 1195396Ssaidi@eecs.umich.edu break; 1205396Ssaidi@eecs.umich.edu case Int_Status: 1215396Ssaidi@eecs.umich.edu data = int_status; 1225396Ssaidi@eecs.umich.edu break; 1235396Ssaidi@eecs.umich.edu case Fb_Base: 1245396Ssaidi@eecs.umich.edu data = fb_base; 1255396Ssaidi@eecs.umich.edu break; 1265396Ssaidi@eecs.umich.edu case Fb_Line_Length: 1275396Ssaidi@eecs.umich.edu data = fb_line_length; 1285396Ssaidi@eecs.umich.edu break; 1295396Ssaidi@eecs.umich.edu case Fb_Line_Count: 1305396Ssaidi@eecs.umich.edu data = fb_line_count; 1315396Ssaidi@eecs.umich.edu break; 1325396Ssaidi@eecs.umich.edu case Fb_Line_Pitch: 1335396Ssaidi@eecs.umich.edu data = fb_line_pitch; 1345396Ssaidi@eecs.umich.edu break; 1355396Ssaidi@eecs.umich.edu case Bus_Options: 1365396Ssaidi@eecs.umich.edu data = bus_options; 1375396Ssaidi@eecs.umich.edu break; 1385396Ssaidi@eecs.umich.edu case V_Sync: 1395396Ssaidi@eecs.umich.edu data = v_sync; 1405396Ssaidi@eecs.umich.edu break; 1415396Ssaidi@eecs.umich.edu case V_Back_Porch: 1425396Ssaidi@eecs.umich.edu data = v_back_porch; 1435396Ssaidi@eecs.umich.edu break; 1445396Ssaidi@eecs.umich.edu case V_Data: 1455396Ssaidi@eecs.umich.edu data = v_data; 1465396Ssaidi@eecs.umich.edu break; 1475396Ssaidi@eecs.umich.edu case V_Front_Porch: 1485396Ssaidi@eecs.umich.edu data = v_front_porch; 1495396Ssaidi@eecs.umich.edu break; 1504781Snate@binkert.org case H_Sync: 1511852SN/A data = h_sync; 152955SN/A break; 153955SN/A case H_Back_Porch: 154955SN/A data = h_back_porch; 1553717Sstever@eecs.umich.edu break; 1563716Sstever@eecs.umich.edu case H_Data: 157955SN/A data = h_data; 1581533SN/A break; 1593716Sstever@eecs.umich.edu case H_Front_Porch: 1601533SN/A data = h_front_porch; 1614678Snate@binkert.org break; 1624678Snate@binkert.org case Polarities: 1634678Snate@binkert.org data = polarities; 1644678Snate@binkert.org break; 1654678Snate@binkert.org case Command: 1664678Snate@binkert.org data = command; 1674678Snate@binkert.org break; 1684678Snate@binkert.org case Pixel_Format: 1694678Snate@binkert.org data = pixel_format; 1704678Snate@binkert.org break; 1714678Snate@binkert.org case Red_Select: 1724678Snate@binkert.org data = red_select; 1734678Snate@binkert.org break; 1744678Snate@binkert.org case Green_Select: 1754678Snate@binkert.org data = green_select; 1764678Snate@binkert.org break; 1774678Snate@binkert.org case Blue_Select: 1784678Snate@binkert.org data = blue_select; 1794678Snate@binkert.org break; 1804678Snate@binkert.org default: 1814678Snate@binkert.org panic("Tried to read HDLCD register that doesn't exist\n", daddr); 1824973Ssaidi@eecs.umich.edu break; 1834678Snate@binkert.org } 1844678Snate@binkert.org 1854678Snate@binkert.org pkt->set<uint32_t>(data); 1864678Snate@binkert.org pkt->makeAtomicResponse(); 1874678Snate@binkert.org return pioDelay; 1884678Snate@binkert.org} 189955SN/A 190955SN/A// write registers and frame buffer 1912632Sstever@eecs.umich.eduTick 1922632Sstever@eecs.umich.eduHDLcd::write(PacketPtr pkt) 193955SN/A{ 194955SN/A assert(pkt->getAddr() >= pioAddr && 195955SN/A pkt->getAddr() < pioAddr + pioSize && 196955SN/A pkt->getSize() == 4); 1972632Sstever@eecs.umich.edu 198955SN/A const uint32_t data = pkt->get<uint32_t>(); 1992632Sstever@eecs.umich.edu const Addr daddr = pkt->getAddr() - pioAddr; 2002632Sstever@eecs.umich.edu 2012632Sstever@eecs.umich.edu DPRINTF(HDLcd, "write register BASE+%0x04x <= 0x%08x\n", daddr, 2022632Sstever@eecs.umich.edu pkt->get<uint32_t>()); 2032632Sstever@eecs.umich.edu 2042632Sstever@eecs.umich.edu switch (daddr) { 2052632Sstever@eecs.umich.edu case Version: 2062632Sstever@eecs.umich.edu panic("HDLCD VERSION register is read-Only\n"); 2072632Sstever@eecs.umich.edu break; 2082632Sstever@eecs.umich.edu case Int_RawStat: 2092632Sstever@eecs.umich.edu int_rawstat = data; 2102632Sstever@eecs.umich.edu break; 2112632Sstever@eecs.umich.edu case Int_Clear: 2123718Sstever@eecs.umich.edu int_clear = data; 2133718Sstever@eecs.umich.edu break; 2143718Sstever@eecs.umich.edu case Int_Mask: 2153718Sstever@eecs.umich.edu int_mask = data; 2163718Sstever@eecs.umich.edu break; 2173718Sstever@eecs.umich.edu case Int_Status: 2183718Sstever@eecs.umich.edu panic("HDLCD INT_STATUS register is read-Only\n"); 2193718Sstever@eecs.umich.edu break; 2203718Sstever@eecs.umich.edu case Fb_Base: 2213718Sstever@eecs.umich.edu fb_base = data; 2223718Sstever@eecs.umich.edu DPRINTF(HDLcd, "HDLCD Frame Buffer located at addr 0x%08x\n", fb_base); 2233718Sstever@eecs.umich.edu break; 2243718Sstever@eecs.umich.edu case Fb_Line_Length: 2252634Sstever@eecs.umich.edu fb_line_length = data; 2262634Sstever@eecs.umich.edu DPRINTF(HDLcd, "HDLCD res = %d x %d\n", width(), height()); 2272632Sstever@eecs.umich.edu break; 2282638Sstever@eecs.umich.edu case Fb_Line_Count: 2292632Sstever@eecs.umich.edu fb_line_count = data; 2302632Sstever@eecs.umich.edu DPRINTF(HDLcd, "HDLCD res = %d x %d\n", width(), height()); 2312632Sstever@eecs.umich.edu break; 2322632Sstever@eecs.umich.edu case Fb_Line_Pitch: 2332632Sstever@eecs.umich.edu fb_line_pitch = data; 2342632Sstever@eecs.umich.edu break; 2351858SN/A case Bus_Options: { 2363716Sstever@eecs.umich.edu BusOptsReg old_bus_options; 2372638Sstever@eecs.umich.edu old_bus_options = bus_options; 2382638Sstever@eecs.umich.edu bus_options = data; 2392638Sstever@eecs.umich.edu if (bus_options.max_outstanding != old_bus_options.max_outstanding) 2402638Sstever@eecs.umich.edu DPRINTF(HDLcd, 2412638Sstever@eecs.umich.edu "Changing HDLcd outstanding dma transactions from %d to %d\n", 2422638Sstever@eecs.umich.edu old_bus_options.max_outstanding, bus_options.max_outstanding); 2432638Sstever@eecs.umich.edu if (bus_options.burst_len != old_bus_options.burst_len) 2443716Sstever@eecs.umich.edu DPRINTF(HDLcd, 2452634Sstever@eecs.umich.edu "Changing HDLcd dma burst length from %d bytes to %d bytes\n", 2462634Sstever@eecs.umich.edu old_bus_options.burst_len, bus_options.burst_len); } 247955SN/A break; 2485341Sstever@gmail.com case V_Sync: 2495341Sstever@gmail.com v_sync = data; 2505341Sstever@gmail.com break; 2515341Sstever@gmail.com case V_Back_Porch: 252955SN/A v_back_porch = data; 253955SN/A break; 254955SN/A case V_Data: 255955SN/A v_data = data; 256955SN/A break; 257955SN/A case V_Front_Porch: 258955SN/A v_front_porch = data; 2591858SN/A break; 2601858SN/A case H_Sync: 2612632Sstever@eecs.umich.edu h_sync = data; 262955SN/A break; 2634494Ssaidi@eecs.umich.edu case H_Back_Porch: 2644494Ssaidi@eecs.umich.edu h_back_porch = data; 2653716Sstever@eecs.umich.edu break; 2661105SN/A case H_Data: 2672667Sstever@eecs.umich.edu h_data = data; 2682667Sstever@eecs.umich.edu break; 2692667Sstever@eecs.umich.edu case H_Front_Porch: 2702667Sstever@eecs.umich.edu h_front_porch = data; 2712667Sstever@eecs.umich.edu break; 2722667Sstever@eecs.umich.edu case Polarities: 2731869SN/A polarities = data; 2741869SN/A break; 2751869SN/A case Command: { 2761869SN/A CommandReg new_command; 2771869SN/A new_command = data; 2781065SN/A if (new_command.enable != command.enable) { 2795341Sstever@gmail.com DPRINTF(HDLcd, "HDLCD switched %s\n", 2805341Sstever@gmail.com new_command.enable==0 ? "off" : "on"); 2815341Sstever@gmail.com if (new_command.enable) { 2825341Sstever@gmail.com doUpdateParams = true; 2835341Sstever@gmail.com if (!frameUnderway) { 2845341Sstever@gmail.com schedule(startFrameEvent, clockEdge()); 2855341Sstever@gmail.com } 2865341Sstever@gmail.com } 2875341Sstever@gmail.com } 2885341Sstever@gmail.com command = new_command; } 2895341Sstever@gmail.com break; 2905341Sstever@gmail.com case Pixel_Format: 2915341Sstever@gmail.com pixel_format = data; 2925341Sstever@gmail.com DPRINTF(HDLcd, "HDLCD res = %d x %d\n", width(), height()); 2935341Sstever@gmail.com DPRINTF(HDLcd, "HDLCD bytes per pixel = %d\n", bytesPerPixel()); 2945341Sstever@gmail.com DPRINTF(HDLcd, "HDLCD endianness = %s\n", 2955341Sstever@gmail.com pixel_format.big_endian ? "big" : "little"); 2965341Sstever@gmail.com break; 2975341Sstever@gmail.com case Red_Select: 2985341Sstever@gmail.com red_select = data; 2995341Sstever@gmail.com break; 3005341Sstever@gmail.com case Green_Select: 3015341Sstever@gmail.com green_select = data; 3025341Sstever@gmail.com break; 3035341Sstever@gmail.com case Blue_Select: 3045341Sstever@gmail.com blue_select = data; 3055341Sstever@gmail.com break; 3065341Sstever@gmail.com default: 3075341Sstever@gmail.com panic("Tried to write HDLCD register that doesn't exist\n", daddr); 3085341Sstever@gmail.com break; 3095341Sstever@gmail.com } 3105341Sstever@gmail.com 3115341Sstever@gmail.com pkt->makeAtomicResponse(); 3125341Sstever@gmail.com return pioDelay; 3135341Sstever@gmail.com} 3145341Sstever@gmail.com 3155341Sstever@gmail.comvoid 3165341Sstever@gmail.comHDLcd::updateVideoParams(bool unserializing = false) 3175341Sstever@gmail.com{ 3185341Sstever@gmail.com const uint16_t bpp M5_VAR_USED = bytesPerPixel() << 3; 3195341Sstever@gmail.com 3205341Sstever@gmail.com // Workaround configuration bugs where multiple display 3215341Sstever@gmail.com // controllers are attached to the same VNC server by reattaching 3225341Sstever@gmail.com // enabled devices. This isn't ideal, but works as long as only 3235341Sstever@gmail.com // one display controller is active at a time. 3245341Sstever@gmail.com if (command.enable && vnc) 3255341Sstever@gmail.com vnc->setFrameBuffer(&fb); 3265341Sstever@gmail.com 3275341Sstever@gmail.com // updating these parameters while LCD is enabled is not supported 3285344Sstever@gmail.com if (frameUnderway && !unserializing) 3295341Sstever@gmail.com panic("Attempting to change some HDLCD parameters while the controller" 3305341Sstever@gmail.com " is active is not allowed"); 3315341Sstever@gmail.com 3325341Sstever@gmail.com // resize the virtualDisplayBuffer unless we are unserializing - it may 3335341Sstever@gmail.com // have changed size 3342632Sstever@eecs.umich.edu // there must be no outstanding DMA transactions for this to work 3355199Sstever@gmail.com if (!unserializing) { 3363918Ssaidi@eecs.umich.edu assert(dmaPendingNum == 0); 3373918Ssaidi@eecs.umich.edu 3383940Ssaidi@eecs.umich.edu virtualDisplayBuffer.resize(bytesPerPixel() * area()); 3394781Snate@binkert.org fb.resize(width(), height()); 3404781Snate@binkert.org fb.clear(); 3413918Ssaidi@eecs.umich.edu 3424781Snate@binkert.org std::fill(virtualDisplayBuffer.begin(), virtualDisplayBuffer.end(), 3434781Snate@binkert.org 0); 3443918Ssaidi@eecs.umich.edu } 3454781Snate@binkert.org 3464781Snate@binkert.org DPRINTF(HDLcd, "bpp = %d\n", bpp); 3473940Ssaidi@eecs.umich.edu DPRINTF(HDLcd, "display size = %d x %d\n", width(), height()); 3483942Ssaidi@eecs.umich.edu#if TRACING_ON 3493940Ssaidi@eecs.umich.edu const size_t totalLinesPerFrame = v_back_porch.val + 1 + 3503918Ssaidi@eecs.umich.edu v_data.val + 1 + 3513918Ssaidi@eecs.umich.edu v_front_porch.val + 1 + 352955SN/A v_sync.val + 1; 3531858SN/A const double fps = (double)SimClock::Frequency / 3543918Ssaidi@eecs.umich.edu (double)(PClksPerLine() * totalLinesPerFrame * pixelClock); 3553918Ssaidi@eecs.umich.edu#endif 3563918Ssaidi@eecs.umich.edu DPRINTF(HDLcd, "simulated refresh rate ~ %.1ffps generating ~ %.1fMB/s " 3573918Ssaidi@eecs.umich.edu "traffic ([%.1fMHz, T=%d sim clocks] pclk, %d bpp => %.1fMB/s peak requirement)\n", 3583940Ssaidi@eecs.umich.edu fps, 3593940Ssaidi@eecs.umich.edu fps * virtualDisplayBuffer.size() / 1024 / 1024, 3603918Ssaidi@eecs.umich.edu (double)SimClock::Frequency / pixelClock / 1000000.0, 3613918Ssaidi@eecs.umich.edu pixelClock, 3623918Ssaidi@eecs.umich.edu bpp, 3633918Ssaidi@eecs.umich.edu (double)(SimClock::Frequency / pixelClock * (bpp / 8)) / 1024 / 1024); 3643918Ssaidi@eecs.umich.edu} 3653918Ssaidi@eecs.umich.edu 3663918Ssaidi@eecs.umich.eduvoid 3673918Ssaidi@eecs.umich.eduHDLcd::startFrame() 3683918Ssaidi@eecs.umich.edu{ 3693940Ssaidi@eecs.umich.edu // 0. Check that we are in the appropriate state 3703918Ssaidi@eecs.umich.edu assert(!frameUnderway); 3713918Ssaidi@eecs.umich.edu if (!command.enable) 3721851SN/A return; 3731851SN/A DPRINTF(HDLcd, "Frame read started\n"); 3741858SN/A if (doUpdateParams) { 3755200Sstever@gmail.com updateVideoParams(); 376955SN/A doUpdateParams = false; 3773053Sstever@eecs.umich.edu } 3783053Sstever@eecs.umich.edu frameUnderway = true; 3793053Sstever@eecs.umich.edu assert(!virtualDisplayBuffer.empty()); 3803053Sstever@eecs.umich.edu assert(pixelBufferSize == 0); 3813053Sstever@eecs.umich.edu assert(dmaBytesInFlight == 0); 3823053Sstever@eecs.umich.edu assert(dmaPendingNum == 0); 3833053Sstever@eecs.umich.edu assert(dmaDoneEventFree.size() == dmaDoneEventAll.size()); 3843053Sstever@eecs.umich.edu assert(!renderPixelEvent.scheduled()); 3853053Sstever@eecs.umich.edu // currently only support positive line pitches equal to the line length 3864742Sstever@eecs.umich.edu assert(width() * bytesPerPixel() == fb_line_pitch); 3874742Sstever@eecs.umich.edu 3883053Sstever@eecs.umich.edu // 1. Start DMA'ing the frame; subsequent transactions created as we go 3893053Sstever@eecs.umich.edu dmaCurAddr = dmaStartAddr = fb_base; 3903053Sstever@eecs.umich.edu dmaMaxAddr = static_cast<Addr>(width() * height() * bytesPerPixel()) + 3913053Sstever@eecs.umich.edu dmaCurAddr; 3923053Sstever@eecs.umich.edu frameReadStartTime = curTick(); 3933053Sstever@eecs.umich.edu pixelIndex = 0; 3943053Sstever@eecs.umich.edu frameUnderrun = false; 3953053Sstever@eecs.umich.edu fillPixelBuffer(); 3963053Sstever@eecs.umich.edu 3972667Sstever@eecs.umich.edu // 2. Schedule first pixelclock read; subsequent reads generated as we go 3984554Sbinkertn@umich.edu Tick firstPixelReadTick = curTick() + pixelClock * ( 3994554Sbinkertn@umich.edu PClksPerLine() * (v_sync.val + 1 + 4002667Sstever@eecs.umich.edu v_back_porch.val + 1) + 4014554Sbinkertn@umich.edu h_sync.val + 1 + 4024554Sbinkertn@umich.edu h_back_porch.val + 1); 4034554Sbinkertn@umich.edu schedule(renderPixelEvent, firstPixelReadTick); 4044554Sbinkertn@umich.edu} 4054554Sbinkertn@umich.edu 4064554Sbinkertn@umich.eduvoid 4074554Sbinkertn@umich.eduHDLcd::fillPixelBuffer() 4084781Snate@binkert.org{ 4094554Sbinkertn@umich.edu // - am I under the LCD dma transaction total? 4104554Sbinkertn@umich.edu // - do I have more data to transfer? 4112667Sstever@eecs.umich.edu // - have I not yet underrun for this frame? 4124554Sbinkertn@umich.edu // - is there room to put the data in the pixel buffer including any 4134554Sbinkertn@umich.edu // outstanding dma transfers in flight? 4144554Sbinkertn@umich.edu while ((dmaPendingNum < maxOutstandingDma()) && 4154554Sbinkertn@umich.edu (dmaMaxAddr > dmaCurAddr) && 4162667Sstever@eecs.umich.edu !frameUnderrun && 4174554Sbinkertn@umich.edu bytesFreeInPixelBuffer() > dmaBurstLength() * AXI_PORT_WIDTH) { 4182667Sstever@eecs.umich.edu // try largest transaction size allowed first but switch to smaller 4194554Sbinkertn@umich.edu // sizes for trailing bytes 4204554Sbinkertn@umich.edu size_t transaction_size = dmaBurstLength() * AXI_PORT_WIDTH; 4212667Sstever@eecs.umich.edu while (transaction_size > (dmaMaxAddr - dmaCurAddr)) 4222638Sstever@eecs.umich.edu transaction_size >>= 1; 4232638Sstever@eecs.umich.edu assert(transaction_size > 0); 4242638Sstever@eecs.umich.edu 4253716Sstever@eecs.umich.edu // concurrent dma reads need different dma done events 4263716Sstever@eecs.umich.edu // due to assertion in scheduling state 4271858SN/A ++dmaPendingNum; 4285227Ssaidi@eecs.umich.edu 4295227Ssaidi@eecs.umich.edu assert(!dmaDoneEventFree.empty()); 4305227Ssaidi@eecs.umich.edu DmaDoneEvent *event(dmaDoneEventFree.back()); 4315227Ssaidi@eecs.umich.edu dmaDoneEventFree.pop_back(); 4325227Ssaidi@eecs.umich.edu assert(event); 4335227Ssaidi@eecs.umich.edu assert(!event->scheduled()); 4345227Ssaidi@eecs.umich.edu 4355227Ssaidi@eecs.umich.edu // We use a uncachable request here because the requests from the CPU 4365227Ssaidi@eecs.umich.edu // will be uncacheable as well. If we have uncacheable and cacheable 4375227Ssaidi@eecs.umich.edu // requests in the memory system for the same address it won't be 4385227Ssaidi@eecs.umich.edu // pleased 4395227Ssaidi@eecs.umich.edu uint8_t *const dma_dst( 4405274Ssaidi@eecs.umich.edu virtualDisplayBuffer.data() + dmaCurAddr - dmaStartAddr); 4415227Ssaidi@eecs.umich.edu event->setTransactionSize(transaction_size); 4425227Ssaidi@eecs.umich.edu dmaPort.dmaAction(MemCmd::ReadReq, dmaCurAddr, transaction_size, event, 4435227Ssaidi@eecs.umich.edu dma_dst, 0, Request::UNCACHEABLE); 4445204Sstever@gmail.com dmaCurAddr += transaction_size; 4455204Sstever@gmail.com dmaBytesInFlight += transaction_size; 4465204Sstever@gmail.com } 4475204Sstever@gmail.com} 4485204Sstever@gmail.com 4495204Sstever@gmail.comvoid 4505204Sstever@gmail.comHDLcd::renderPixel() 4515204Sstever@gmail.com{ 4525204Sstever@gmail.com // try to handle multiple pixels at a time; doing so reduces the accuracy 4535204Sstever@gmail.com // of the underrun detection but lowers simulation overhead 4545204Sstever@gmail.com const size_t count = 32; 4555204Sstever@gmail.com assert(width() % count == 0); // not set up to handle trailing pixels 4565204Sstever@gmail.com 4575204Sstever@gmail.com // have we underrun on this frame anytime before? 4585204Sstever@gmail.com if (frameUnderrun) { 4595204Sstever@gmail.com // the LCD controller gives up on a frame if an underrun occurs and 4605204Sstever@gmail.com // resumes regular operation on the next frame 4615204Sstever@gmail.com pixelBufferSize = 0; 4625204Sstever@gmail.com } else { 4633118Sstever@eecs.umich.edu // did we underrun on this set of pixels? 4643118Sstever@eecs.umich.edu if (pixelBufferSize < bytesPerPixel() * count) { 4653118Sstever@eecs.umich.edu warn("HDLcd controller buffer underrun\n"); 4663118Sstever@eecs.umich.edu frameUnderrun = true; 4673118Sstever@eecs.umich.edu int_rawstat.underrun = 1; 4683118Sstever@eecs.umich.edu if (!intEvent.scheduled()) 4693118Sstever@eecs.umich.edu schedule(intEvent, clockEdge()); 4703118Sstever@eecs.umich.edu } else { 4713118Sstever@eecs.umich.edu // emulate the pixel read from the internal buffer 4723118Sstever@eecs.umich.edu pixelBufferSize -= bytesPerPixel() * count; 4733118Sstever@eecs.umich.edu } 4743716Sstever@eecs.umich.edu } 4753118Sstever@eecs.umich.edu 4763118Sstever@eecs.umich.edu // the DMA may have previously stalled due to the buffer being full; 4773118Sstever@eecs.umich.edu // give it a kick; it knows not to fill if at end of frame, underrun, etc 4783118Sstever@eecs.umich.edu if (!fillPixelBufferEvent.scheduled()) 4793118Sstever@eecs.umich.edu schedule(fillPixelBufferEvent, clockEdge()); 4803118Sstever@eecs.umich.edu 4813118Sstever@eecs.umich.edu // schedule the next pixel read according to where it is in the frame 4823118Sstever@eecs.umich.edu pixelIndex += count; 4833118Sstever@eecs.umich.edu assert(pixelIndex <= width() * height()); 4843716Sstever@eecs.umich.edu size_t x = pixelIndex % width(); 4853118Sstever@eecs.umich.edu Tick nextEventTick = curTick(); 4863118Sstever@eecs.umich.edu if (x == 0) { 4873118Sstever@eecs.umich.edu // start of new line 4883118Sstever@eecs.umich.edu nextEventTick += pixelClock * ((h_front_porch.val + 1) + 4893118Sstever@eecs.umich.edu (h_back_porch.val + 1) + 4903118Sstever@eecs.umich.edu (h_sync.val + 1)); 4913118Sstever@eecs.umich.edu if (pixelIndex == width() * height()) { 4923118Sstever@eecs.umich.edu // end of frame 4933118Sstever@eecs.umich.edu nextEventTick += PClksPerLine() * (v_front_porch.val + 1) * 4943118Sstever@eecs.umich.edu pixelClock; 4953483Ssaidi@eecs.umich.edu schedule(endFrameEvent, nextEventTick); 4963494Ssaidi@eecs.umich.edu return; 4973494Ssaidi@eecs.umich.edu } 4983483Ssaidi@eecs.umich.edu } else { 4993483Ssaidi@eecs.umich.edu nextEventTick += pixelClock * count; 5003483Ssaidi@eecs.umich.edu } 5013053Sstever@eecs.umich.edu 5023053Sstever@eecs.umich.edu schedule(renderPixelEvent, nextEventTick); 5033918Ssaidi@eecs.umich.edu} 5043053Sstever@eecs.umich.edu 5053053Sstever@eecs.umich.eduPixelConverter 5063053Sstever@eecs.umich.eduHDLcd::pixelConverter() const 5073053Sstever@eecs.umich.edu{ 5083053Sstever@eecs.umich.edu ByteOrder byte_order( 5091858SN/A pixel_format.big_endian ? BigEndianByteOrder : LittleEndianByteOrder); 5101858SN/A 5111858SN/A /* Some Linux kernels have a broken driver that swaps the red and 5121858SN/A * blue color select registers. */ 5131858SN/A if (!workaround_swap_rb) { 5141858SN/A return PixelConverter( 5151859SN/A bytesPerPixel(), 5161858SN/A red_select.offset, green_select.offset, blue_select.offset, 5171858SN/A red_select.size, green_select.size, blue_select.size, 5181858SN/A byte_order); 5191859SN/A } else { 5201859SN/A return PixelConverter( 5211862SN/A bytesPerPixel(), 5223053Sstever@eecs.umich.edu blue_select.offset, green_select.offset, red_select.offset, 5233053Sstever@eecs.umich.edu blue_select.size, green_select.size, red_select.size, 5243053Sstever@eecs.umich.edu byte_order); 5253053Sstever@eecs.umich.edu } 5261859SN/A} 5271859SN/A 5281859SN/Avoid 5291859SN/AHDLcd::endFrame() { 5301859SN/A assert(pixelBufferSize == 0); 5311859SN/A assert(dmaPendingNum == 0); 5321859SN/A assert(dmaBytesInFlight == 0); 5331859SN/A assert(dmaDoneEventFree.size() == dmaDoneEventAll.size()); 5341862SN/A 5351859SN/A fb.copyIn(virtualDisplayBuffer, pixelConverter()); 5361859SN/A 5371859SN/A if (vnc) 5381858SN/A vnc->setDirty(); 5391858SN/A 5402139SN/A if (enableCapture) { 5414202Sbinkertn@umich.edu if (!pic) 5424202Sbinkertn@umich.edu pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true); 5432139SN/A 5442155SN/A assert(pic); 5454202Sbinkertn@umich.edu pic->seekp(0); 5464202Sbinkertn@umich.edu bmp.write(*pic); 5474202Sbinkertn@umich.edu } 5482155SN/A 5491869SN/A // start the next frame 5501869SN/A frameUnderway = false; 5511869SN/A startFrame(); 5521869SN/A} 5534202Sbinkertn@umich.edu 5544202Sbinkertn@umich.eduvoid 5554202Sbinkertn@umich.eduHDLcd::dmaDone(DmaDoneEvent *event) 5564202Sbinkertn@umich.edu{ 5574202Sbinkertn@umich.edu const size_t transactionLength = event->getTransactionSize(); 5584202Sbinkertn@umich.edu assert(pixelBufferSize + transactionLength < PIXEL_BUFFER_CAPACITY); 5594202Sbinkertn@umich.edu assert(dmaCurAddr <= dmaMaxAddr); 5604202Sbinkertn@umich.edu 5615341Sstever@gmail.com dmaDoneEventFree.push_back(event); 5625341Sstever@gmail.com --dmaPendingNum; 5635341Sstever@gmail.com assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY - dmaDoneEventFree.size() == 5645342Sstever@gmail.com dmaPendingNum); 5655342Sstever@gmail.com 5664202Sbinkertn@umich.edu // add the data to the pixel buffer 5674202Sbinkertn@umich.edu dmaBytesInFlight -= transactionLength; 5684202Sbinkertn@umich.edu pixelBufferSize += transactionLength; 5694202Sbinkertn@umich.edu 5704202Sbinkertn@umich.edu // schedule another dma transaction if: 5711869SN/A // - we're not done reading the frame 5724202Sbinkertn@umich.edu // - there is sufficient room in the pixel buffer for another transaction 5731869SN/A // - another fillPixelBufferEvent is not already scheduled 5742508SN/A const size_t targetTransSize = dmaBurstLength() * AXI_PORT_WIDTH; 5752508SN/A if ((dmaCurAddr < dmaMaxAddr) && 5762508SN/A (bytesFreeInPixelBuffer() + targetTransSize < PIXEL_BUFFER_CAPACITY) && 5772508SN/A !fillPixelBufferEvent.scheduled()) { 5784202Sbinkertn@umich.edu schedule(fillPixelBufferEvent, clockEdge()); 5791869SN/A } 5805385Sstever@gmail.com} 5815385Sstever@gmail.com 5825385Sstever@gmail.comvoid 5835385Sstever@gmail.comHDLcd::serialize(std::ostream &os) 5841869SN/A{ 5851869SN/A DPRINTF(HDLcd, "Serializing ARM HDLCD\n"); 5861869SN/A 5871869SN/A const uint32_t version_serial = version; 5881869SN/A SERIALIZE_SCALAR(version_serial); 5891965SN/A const uint32_t int_rawstat_serial = int_rawstat; 5901965SN/A SERIALIZE_SCALAR(int_rawstat_serial); 5911965SN/A const uint32_t int_clear_serial = int_clear; 5921869SN/A SERIALIZE_SCALAR(int_clear_serial); 5931869SN/A const uint32_t int_mask_serial = int_mask; 5942733Sktlim@umich.edu SERIALIZE_SCALAR(int_mask_serial); 5951884SN/A const uint32_t int_status_serial = int_status; 5963356Sbinkertn@umich.edu SERIALIZE_SCALAR(int_status_serial); 5973356Sbinkertn@umich.edu 5983356Sbinkertn@umich.edu SERIALIZE_SCALAR(fb_base); 5994773Snate@binkert.org SERIALIZE_SCALAR(fb_line_length); 6001869SN/A 6011858SN/A const uint32_t fb_line_count_serial = fb_line_count; 6021869SN/A SERIALIZE_SCALAR(fb_line_count_serial); 6031869SN/A 6041869SN/A SERIALIZE_SCALAR(fb_line_pitch); 6051858SN/A 6062761Sstever@eecs.umich.edu const uint32_t bus_options_serial = bus_options; 6071869SN/A SERIALIZE_SCALAR(bus_options_serial); 6085385Sstever@gmail.com const uint32_t v_sync_serial = v_sync; 6095385Sstever@gmail.com SERIALIZE_SCALAR(v_sync_serial); 6103584Ssaidi@eecs.umich.edu const uint32_t v_back_porch_serial = v_back_porch; 6111869SN/A SERIALIZE_SCALAR(v_back_porch_serial); 6121869SN/A const uint32_t v_data_serial = v_data; 6131869SN/A SERIALIZE_SCALAR(v_data_serial); 6141869SN/A const uint32_t v_front_porch_serial = v_front_porch; 6151869SN/A SERIALIZE_SCALAR(v_front_porch_serial); 6161869SN/A const uint32_t h_sync_serial = h_sync; 6171858SN/A SERIALIZE_SCALAR(h_sync_serial); 618955SN/A const uint32_t h_back_porch_serial = h_back_porch; 619955SN/A SERIALIZE_SCALAR(h_back_porch_serial); 6201869SN/A const uint32_t h_data_serial = h_data; 6211869SN/A SERIALIZE_SCALAR(h_data_serial); 6221869SN/A const uint32_t h_front_porch_serial = h_front_porch; 6231869SN/A SERIALIZE_SCALAR(h_front_porch_serial); 6241869SN/A const uint32_t polarities_serial = polarities; 6251869SN/A SERIALIZE_SCALAR(polarities_serial); 6261869SN/A const uint32_t command_serial = command; 6271869SN/A SERIALIZE_SCALAR(command_serial); 6281869SN/A const uint32_t pixel_format_serial = pixel_format; 6291869SN/A SERIALIZE_SCALAR(pixel_format_serial); 6301869SN/A const uint32_t red_select_serial = red_select; 6311869SN/A SERIALIZE_SCALAR(red_select_serial); 6321869SN/A const uint32_t green_select_serial = green_select; 6331869SN/A SERIALIZE_SCALAR(green_select_serial); 6341869SN/A const uint32_t blue_select_serial = blue_select; 6351869SN/A SERIALIZE_SCALAR(blue_select_serial); 6361869SN/A 6371869SN/A SERIALIZE_SCALAR(frameReadStartTime); 6381869SN/A SERIALIZE_SCALAR(dmaStartAddr); 6391869SN/A SERIALIZE_SCALAR(dmaCurAddr); 6401869SN/A SERIALIZE_SCALAR(dmaMaxAddr); 6411869SN/A SERIALIZE_SCALAR(dmaPendingNum); 6421869SN/A SERIALIZE_SCALAR(frameUnderrun); 6431869SN/A 6441869SN/A arrayParamOut(os, "virtualDisplayBuffer", virtualDisplayBuffer); 6451869SN/A 6461869SN/A SERIALIZE_SCALAR(pixelBufferSize); 6471869SN/A SERIALIZE_SCALAR(pixelIndex); 6481869SN/A SERIALIZE_SCALAR(doUpdateParams); 6493716Sstever@eecs.umich.edu SERIALIZE_SCALAR(frameUnderway); 6503356Sbinkertn@umich.edu SERIALIZE_SCALAR(dmaBytesInFlight); 6513356Sbinkertn@umich.edu 6523356Sbinkertn@umich.edu Tick start_event_time = 0; 6533356Sbinkertn@umich.edu Tick end_event_time = 0; 6543356Sbinkertn@umich.edu Tick render_pixel_event_time = 0; 6553356Sbinkertn@umich.edu Tick fill_pixel_buffer_event_time = 0; 6564781Snate@binkert.org Tick int_event_time = 0; 6571869SN/A if (startFrameEvent.scheduled()) 6581869SN/A start_event_time = startFrameEvent.when(); 6591869SN/A if (endFrameEvent.scheduled()) 6601869SN/A end_event_time = endFrameEvent.when(); 6611869SN/A if (renderPixelEvent.scheduled()) 6621869SN/A render_pixel_event_time = renderPixelEvent.when(); 6631869SN/A if (fillPixelBufferEvent.scheduled()) 6642655Sstever@eecs.umich.edu fill_pixel_buffer_event_time = fillPixelBufferEvent.when(); 6652655Sstever@eecs.umich.edu if (intEvent.scheduled()) 6662655Sstever@eecs.umich.edu int_event_time = intEvent.when(); 6672655Sstever@eecs.umich.edu SERIALIZE_SCALAR(start_event_time); 6682655Sstever@eecs.umich.edu SERIALIZE_SCALAR(end_event_time); 6692655Sstever@eecs.umich.edu SERIALIZE_SCALAR(render_pixel_event_time); 6702655Sstever@eecs.umich.edu SERIALIZE_SCALAR(fill_pixel_buffer_event_time); 6712655Sstever@eecs.umich.edu SERIALIZE_SCALAR(int_event_time); 6722655Sstever@eecs.umich.edu 6732655Sstever@eecs.umich.edu vector<Tick> dma_done_event_tick(MAX_OUTSTANDING_DMA_REQ_CAPACITY); 6742655Sstever@eecs.umich.edu vector<size_t> dma_done_event_burst_len(MAX_OUTSTANDING_DMA_REQ_CAPACITY); 6752655Sstever@eecs.umich.edu for (int x = 0; x < MAX_OUTSTANDING_DMA_REQ_CAPACITY; ++x) { 6762655Sstever@eecs.umich.edu dma_done_event_tick[x] = dmaDoneEventAll[x].scheduled() ? 6772655Sstever@eecs.umich.edu dmaDoneEventAll[x].when() : 0; 6782655Sstever@eecs.umich.edu dma_done_event_burst_len[x] = dmaDoneEventAll[x].scheduled() ? 6792655Sstever@eecs.umich.edu dmaDoneEventAll[x].getTransactionSize() : 0; 6802655Sstever@eecs.umich.edu } 6812655Sstever@eecs.umich.edu arrayParamOut(os, "dma_done_event_tick", dma_done_event_tick); 6822655Sstever@eecs.umich.edu arrayParamOut(os, "dma_done_event_burst_length", dma_done_event_burst_len); 6832655Sstever@eecs.umich.edu} 6842655Sstever@eecs.umich.edu 6852655Sstever@eecs.umich.eduvoid 6862655Sstever@eecs.umich.eduHDLcd::unserialize(Checkpoint *cp, const std::string §ion) 6872655Sstever@eecs.umich.edu{ 6882655Sstever@eecs.umich.edu uint32_t version_serial, int_rawstat_serial, int_clear_serial, 6892655Sstever@eecs.umich.edu int_mask_serial, int_status_serial, fb_line_count_serial, 6902638Sstever@eecs.umich.edu bus_options_serial, v_sync_serial, v_back_porch_serial, 6912638Sstever@eecs.umich.edu v_data_serial, v_front_porch_serial, h_sync_serial, 6923716Sstever@eecs.umich.edu h_back_porch_serial, h_data_serial, h_front_porch_serial, 6932638Sstever@eecs.umich.edu polarities_serial, command_serial, pixel_format_serial, 6942638Sstever@eecs.umich.edu red_select_serial, green_select_serial, blue_select_serial; 6951869SN/A 6961869SN/A DPRINTF(HDLcd, "Unserializing ARM HDLCD\n"); 6973546Sgblack@eecs.umich.edu 6983546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(version_serial); 6993546Sgblack@eecs.umich.edu version = version_serial; 7003546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(int_rawstat_serial); 7014202Sbinkertn@umich.edu int_rawstat = int_rawstat_serial; 7023546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(int_clear_serial); 7033546Sgblack@eecs.umich.edu int_clear = int_clear_serial; 7043546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(int_mask_serial); 7053546Sgblack@eecs.umich.edu int_mask = int_mask_serial; 7063546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(int_status_serial); 7074781Snate@binkert.org int_status = int_status_serial; 7084781Snate@binkert.org 7094781Snate@binkert.org UNSERIALIZE_SCALAR(fb_base); 7104781Snate@binkert.org UNSERIALIZE_SCALAR(fb_line_length); 7114781Snate@binkert.org 7124781Snate@binkert.org UNSERIALIZE_SCALAR(fb_line_count_serial); 7134781Snate@binkert.org fb_line_count = fb_line_count_serial; 7144781Snate@binkert.org 7154781Snate@binkert.org UNSERIALIZE_SCALAR(fb_line_pitch); 7164781Snate@binkert.org 7174781Snate@binkert.org UNSERIALIZE_SCALAR(bus_options_serial); 7184781Snate@binkert.org bus_options = bus_options_serial; 7193546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(v_sync_serial); 7203546Sgblack@eecs.umich.edu v_sync = v_sync_serial; 7213546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(v_back_porch_serial); 7224781Snate@binkert.org v_back_porch = v_back_porch_serial; 7233546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(v_data_serial); 7243546Sgblack@eecs.umich.edu v_data = v_data_serial; 7253546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(v_front_porch_serial); 7263546Sgblack@eecs.umich.edu v_front_porch = v_front_porch_serial; 7273546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(h_sync_serial); 7283546Sgblack@eecs.umich.edu h_sync = h_sync_serial; 7293546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(h_back_porch_serial); 7303546Sgblack@eecs.umich.edu h_back_porch = h_back_porch_serial; 7313546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(h_data_serial); 7323546Sgblack@eecs.umich.edu h_data = h_data_serial; 7334202Sbinkertn@umich.edu UNSERIALIZE_SCALAR(h_front_porch_serial); 7343546Sgblack@eecs.umich.edu h_front_porch = h_front_porch_serial; 7353546Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(polarities_serial); 7363546Sgblack@eecs.umich.edu polarities = polarities_serial; 737955SN/A UNSERIALIZE_SCALAR(command_serial); 738955SN/A command = command_serial; 739955SN/A UNSERIALIZE_SCALAR(pixel_format_serial); 740955SN/A pixel_format = pixel_format_serial; 7411858SN/A UNSERIALIZE_SCALAR(red_select_serial); 7421858SN/A red_select = red_select_serial; 7431858SN/A UNSERIALIZE_SCALAR(green_select_serial); 7442632Sstever@eecs.umich.edu green_select = green_select_serial; 7452632Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(blue_select_serial); 7465343Sstever@gmail.com blue_select = blue_select_serial; 7475343Sstever@gmail.com 7485343Sstever@gmail.com UNSERIALIZE_SCALAR(frameReadStartTime); 7494773Snate@binkert.org UNSERIALIZE_SCALAR(dmaStartAddr); 7504773Snate@binkert.org UNSERIALIZE_SCALAR(dmaCurAddr); 7512632Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(dmaMaxAddr); 7522632Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(dmaPendingNum); 7532632Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(frameUnderrun); 7542023SN/A UNSERIALIZE_SCALAR(dmaBytesInFlight); 7552632Sstever@eecs.umich.edu 7562632Sstever@eecs.umich.edu arrayParamIn(cp, section, "virtualDisplayBuffer", virtualDisplayBuffer); 7572632Sstever@eecs.umich.edu 7582632Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(pixelBufferSize); 7592632Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(pixelIndex); 7603716Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(doUpdateParams); 7615342Sstever@gmail.com UNSERIALIZE_SCALAR(frameUnderway); 7622632Sstever@eecs.umich.edu 7632632Sstever@eecs.umich.edu Tick start_event_time = 0; 7642632Sstever@eecs.umich.edu Tick end_event_time = 0; 7652632Sstever@eecs.umich.edu Tick render_pixel_event_time = 0; 7662023SN/A Tick fill_pixel_buffer_event_time = 0; 7672632Sstever@eecs.umich.edu Tick int_event_time = 0; 7682632Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(start_event_time); 7695342Sstever@gmail.com UNSERIALIZE_SCALAR(end_event_time); 7701889SN/A UNSERIALIZE_SCALAR(render_pixel_event_time); 7712632Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(fill_pixel_buffer_event_time); 7722632Sstever@eecs.umich.edu UNSERIALIZE_SCALAR(int_event_time); 7732632Sstever@eecs.umich.edu if (start_event_time) 7742632Sstever@eecs.umich.edu schedule(startFrameEvent, start_event_time); 7753716Sstever@eecs.umich.edu if (end_event_time) 7763716Sstever@eecs.umich.edu schedule(endFrameEvent, end_event_time); 7775342Sstever@gmail.com if (render_pixel_event_time) 7782632Sstever@eecs.umich.edu schedule(renderPixelEvent, render_pixel_event_time); 7792632Sstever@eecs.umich.edu if (fill_pixel_buffer_event_time) 7802632Sstever@eecs.umich.edu schedule(fillPixelBufferEvent, fill_pixel_buffer_event_time); 7812632Sstever@eecs.umich.edu if (int_event_time) 7822632Sstever@eecs.umich.edu schedule(intEvent, int_event_time); 7832632Sstever@eecs.umich.edu 7842632Sstever@eecs.umich.edu vector<Tick> dma_done_event_tick(MAX_OUTSTANDING_DMA_REQ_CAPACITY); 7851888SN/A vector<Tick> dma_done_event_burst_len(MAX_OUTSTANDING_DMA_REQ_CAPACITY); 7861888SN/A arrayParamIn(cp, section, "dma_done_event_tick", dma_done_event_tick); 7871869SN/A arrayParamIn(cp, section, "dma_done_event_burst_length", dma_done_event_burst_len); 7881869SN/A dmaDoneEventFree.clear(); 7891858SN/A for (int x = 0; x < MAX_OUTSTANDING_DMA_REQ_CAPACITY; ++x) { 7905341Sstever@gmail.com if (dma_done_event_tick[x]) { 7912598SN/A dmaDoneEventAll[x].setTransactionSize(dma_done_event_burst_len[x]); 7922598SN/A schedule(dmaDoneEventAll[x], dma_done_event_tick[x]); 7932598SN/A } else 7942598SN/A dmaDoneEventFree.push_back(&dmaDoneEventAll[x]); 7951858SN/A } 7961858SN/A assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY - dmaDoneEventFree.size() == dmaPendingNum); 7971858SN/A 7981858SN/A if (frameUnderway) { 7991858SN/A updateVideoParams(true); 8001858SN/A fb.resize(width(), height()); 8011858SN/A fb.copyIn(virtualDisplayBuffer, pixelConverter()); 8021858SN/A if (vnc) 8031858SN/A vnc->setDirty(); 8041871SN/A } 8051858SN/A} 8061858SN/A 8071858SN/Avoid 8081858SN/AHDLcd::generateInterrupt() 8091858SN/A{ 8101858SN/A int_status = int_rawstat & int_mask; 8111858SN/A DPRINTF(HDLcd, "Generate Interrupt: int_rawstat=0x%08x int_mask=0x%08x " 8121858SN/A "int_status=0x%08x\n", 8131858SN/A (uint32_t)int_rawstat, (uint32_t)int_mask, (uint32_t)int_status); 8141858SN/A 8151858SN/A if (int_status != 0) { 8161859SN/A gic->sendInt(intNum); 8171859SN/A DPRINTF(HDLcd, " -- Generated\n"); 8181869SN/A } 8191888SN/A} 8202632Sstever@eecs.umich.edu 8211869SN/AAddrRangeList 8221884SN/AHDLcd::getAddrRanges() const 8231884SN/A{ 8241884SN/A AddrRangeList ranges; 8251884SN/A ranges.push_back(RangeSize(pioAddr, pioSize)); 8261884SN/A return ranges; 8271884SN/A} 8281965SN/A 8291965SN/AHDLcd * 8301965SN/AHDLcdParams::create() 8312761Sstever@eecs.umich.edu{ 8321869SN/A return new HDLcd(this); 8331869SN/A} 8342632Sstever@eecs.umich.edu