hdlcd.cc revision 12086:069c529a76fd
11060SN/A/* 22702Sktlim@umich.edu * Copyright (c) 2010-2013, 2015, 2017 ARM Limited 36973Stjones1@inf.ed.ac.uk * All rights reserved 41060SN/A * 51060SN/A * The license below extends only to copyright in the software and shall 61060SN/A * not be construed as granting a license to any other intellectual 71060SN/A * property including but not limited to intellectual property relating 81060SN/A * to a hardware implementation of the functionality of the software 91060SN/A * licensed hereunder. You may use the software subject to the license 101060SN/A * terms below provided that you ensure that this notice is replicated 111060SN/A * unmodified and in its entirety in all distributions of the software, 121060SN/A * modified or unmodified, in source code or in binary form. 131060SN/A * 141060SN/A * Redistribution and use in source and binary forms, with or without 151060SN/A * 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 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, 306973Stjones1@inf.ed.ac.uk * 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 331464SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 341464SN/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. 362731Sktlim@umich.edu * 372292SN/A * Authors: Chris Emmons 381464SN/A * Andreas Sandberg 391060SN/A */ 402669Sktlim@umich.edu 417720Sgblack@eecs.umich.edu#include "dev/arm/hdlcd.hh" 421060SN/A 431060SN/A#include "base/output.hh" 441858SN/A#include "base/trace.hh" 456658Snate@binkert.org#include "base/vnc/vncinput.hh" 463770Sgblack@eecs.umich.edu#include "debug/Checkpoint.hh" 471464SN/A#include "debug/HDLcd.hh" 481464SN/A#include "dev/arm/amba_device.hh" 492669Sktlim@umich.edu#include "dev/arm/base_gic.hh" 501060SN/A#include "mem/packet.hh" 516973Stjones1@inf.ed.ac.uk#include "mem/packet_access.hh" 522669Sktlim@umich.edu#include "params/HDLcd.hh" 537678Sgblack@eecs.umich.edu#include "sim/system.hh" 542292SN/A 556023Snate@binkert.orgusing std::vector; 561060SN/A 571060SN/A 581060SN/A// initialize hdlcd registers 591060SN/AHDLcd::HDLcd(const HDLcdParams *p) 601060SN/A : AmbaDmaDevice(p, 0xFFFF), 611060SN/A // Parameters 621061SN/A vnc(p->vnc), 631061SN/A workaroundSwapRB(p->workaround_swap_rb), 641060SN/A workaroundDmaLineCount(p->workaround_dma_line_count), 651060SN/A addrRanges{RangeSize(pioAddr, pioSize)}, 661061SN/A enableCapture(p->enable_capture), 671060SN/A pixelBufferSize(p->pixel_buffer_size), 681060SN/A virtRefreshRate(p->virt_refresh_rate), 691060SN/A 702733Sktlim@umich.edu // Registers 712733Sktlim@umich.edu version(VERSION_RESETV), 721060SN/A int_rawstat(0), int_mask(0), 732292SN/A 742107SN/A fb_base(0), fb_line_length(0), fb_line_count(0), fb_line_pitch(0), 752690Sktlim@umich.edu bus_options(BUS_OPTIONS_RESETV), 762107SN/A 772690Sktlim@umich.edu v_sync(0), v_back_porch(0), v_data(0), v_front_porch(0), 782690Sktlim@umich.edu h_sync(0), h_back_porch(0), h_data(0), h_front_porch(0), 791060SN/A polarities(0), 802292SN/A 812292SN/A command(0), 822292SN/A 832292SN/A pixel_format(0), 842292SN/A red_select(0), green_select(0), blue_select(0), 852292SN/A 861060SN/A virtRefreshEvent([this]{ virtRefresh(); }, name()), 875543Ssaidi@eecs.umich.edu // Other 885543Ssaidi@eecs.umich.edu bmp(&pixelPump.fb), pic(NULL), conv(PixelConverter::rgba8888_le), 891060SN/A pixelPump(*this, *p->pxl_clk, p->pixel_chunk) 901060SN/A{ 912292SN/A if (vnc) 922107SN/A vnc->setFrameBuffer(&pixelPump.fb); 931060SN/A} 941060SN/A 951060SN/AHDLcd::~HDLcd() 961060SN/A{ 971060SN/A} 981060SN/A 992292SN/Avoid 1001060SN/AHDLcd::regStats() 1011060SN/A{ 1025358Sgblack@eecs.umich.edu AmbaDmaDevice::regStats(); 1035358Sgblack@eecs.umich.edu 1045358Sgblack@eecs.umich.edu using namespace Stats; 1055358Sgblack@eecs.umich.edu 1065358Sgblack@eecs.umich.edu stats.underruns 1075358Sgblack@eecs.umich.edu .name(name() + ".underruns") 1085358Sgblack@eecs.umich.edu .desc("number of buffer underruns") 1095358Sgblack@eecs.umich.edu .flags(nozero) 1105358Sgblack@eecs.umich.edu ; 1115358Sgblack@eecs.umich.edu} 1125358Sgblack@eecs.umich.edu 1135358Sgblack@eecs.umich.eduvoid 1145358Sgblack@eecs.umich.eduHDLcd::serialize(CheckpointOut &cp) const 1152292SN/A{ 1162292SN/A DPRINTF(Checkpoint, "Serializing ARM HDLCD\n"); 1172292SN/A 1182292SN/A SERIALIZE_SCALAR(int_rawstat); 1192292SN/A SERIALIZE_SCALAR(int_mask); 1202292SN/A 1212292SN/A SERIALIZE_SCALAR(fb_base); 1221060SN/A SERIALIZE_SCALAR(fb_line_length); 1232132SN/A SERIALIZE_SCALAR(fb_line_count); 1241060SN/A SERIALIZE_SCALAR(fb_line_pitch); 1257520Sgblack@eecs.umich.edu SERIALIZE_SCALAR(bus_options); 1267520Sgblack@eecs.umich.edu 1272292SN/A SERIALIZE_SCALAR(v_sync); 1282292SN/A SERIALIZE_SCALAR(v_back_porch); 1292292SN/A SERIALIZE_SCALAR(v_data); 1302292SN/A SERIALIZE_SCALAR(v_front_porch); 1312292SN/A 1322292SN/A SERIALIZE_SCALAR(h_sync); 1332292SN/A SERIALIZE_SCALAR(h_back_porch); 1342292SN/A SERIALIZE_SCALAR(h_data); 1351060SN/A SERIALIZE_SCALAR(h_front_porch); 1366973Stjones1@inf.ed.ac.uk 1376973Stjones1@inf.ed.ac.uk SERIALIZE_SCALAR(polarities); 1387520Sgblack@eecs.umich.edu 1397520Sgblack@eecs.umich.edu SERIALIZE_SCALAR(command); 1407520Sgblack@eecs.umich.edu SERIALIZE_SCALAR(pixel_format); 1416974Stjones1@inf.ed.ac.uk SERIALIZE_SCALAR(red_select); 1426974Stjones1@inf.ed.ac.uk SERIALIZE_SCALAR(green_select); 1436974Stjones1@inf.ed.ac.uk SERIALIZE_SCALAR(blue_select); 1446974Stjones1@inf.ed.ac.uk 1456973Stjones1@inf.ed.ac.uk SERIALIZE_OBJ(pixelPump); 1466974Stjones1@inf.ed.ac.uk if (enabled()) 1476974Stjones1@inf.ed.ac.uk dmaEngine->serializeSection(cp, "dmaEngine"); 1486973Stjones1@inf.ed.ac.uk} 1496973Stjones1@inf.ed.ac.uk 1506973Stjones1@inf.ed.ac.ukvoid 1516973Stjones1@inf.ed.ac.ukHDLcd::unserialize(CheckpointIn &cp) 1521060SN/A{ 1531684SN/A DPRINTF(Checkpoint, "Unserializing ARM HDLCD\n"); 1541060SN/A 1551060SN/A UNSERIALIZE_SCALAR(int_rawstat); 1561060SN/A UNSERIALIZE_SCALAR(int_mask); 1571060SN/A 1582731Sktlim@umich.edu UNSERIALIZE_SCALAR(fb_base); 1592731Sktlim@umich.edu UNSERIALIZE_SCALAR(fb_line_length); 1602731Sktlim@umich.edu UNSERIALIZE_SCALAR(fb_line_count); 1612731Sktlim@umich.edu UNSERIALIZE_SCALAR(fb_line_pitch); 1622731Sktlim@umich.edu UNSERIALIZE_SCALAR(bus_options); 1632731Sktlim@umich.edu 1642731Sktlim@umich.edu UNSERIALIZE_SCALAR(v_sync); 1652731Sktlim@umich.edu UNSERIALIZE_SCALAR(v_back_porch); 1662731Sktlim@umich.edu UNSERIALIZE_SCALAR(v_data); 1672731Sktlim@umich.edu UNSERIALIZE_SCALAR(v_front_porch); 1682731Sktlim@umich.edu 1692731Sktlim@umich.edu UNSERIALIZE_SCALAR(h_sync); 1702731Sktlim@umich.edu UNSERIALIZE_SCALAR(h_back_porch); 1712731Sktlim@umich.edu UNSERIALIZE_SCALAR(h_data); 1722731Sktlim@umich.edu UNSERIALIZE_SCALAR(h_front_porch); 1732731Sktlim@umich.edu 1742731Sktlim@umich.edu UNSERIALIZE_SCALAR(polarities); 1752731Sktlim@umich.edu 1762731Sktlim@umich.edu UNSERIALIZE_SCALAR(command); 1772731Sktlim@umich.edu UNSERIALIZE_SCALAR(pixel_format); 1782731Sktlim@umich.edu UNSERIALIZE_SCALAR(red_select); 1792731Sktlim@umich.edu UNSERIALIZE_SCALAR(green_select); 1802731Sktlim@umich.edu UNSERIALIZE_SCALAR(blue_select); 1812731Sktlim@umich.edu 1822731Sktlim@umich.edu { 1832292SN/A // Try to unserialize the pixel pump. It might not exist if 1842731Sktlim@umich.edu // we're unserializing an old checkpoint. 1852731Sktlim@umich.edu ScopedCheckpointSection sec(cp, "pixelPump"); 1861060SN/A if (cp.sectionExists(Serializable::currentSection())) 1871060SN/A pixelPump.unserialize(cp); 1886221Snate@binkert.org } 1891060SN/A 1901060SN/A if (enabled()) { 1911060SN/A // Create the DMA engine and read its state from the 1921060SN/A // checkpoint. We don't need to worry about the pixel pump as 1932292SN/A // it is a proper SimObject. 1942292SN/A createDmaEngine(); 1952292SN/A dmaEngine->unserializeSection(cp, "dmaEngine"); 1962733Sktlim@umich.edu 1972733Sktlim@umich.edu conv = pixelConverter(); 1981060SN/A } 1992680Sktlim@umich.edu} 2002292SN/A 2011060SN/Avoid 2021060SN/AHDLcd::drainResume() 2032132SN/A{ 2041060SN/A AmbaDmaDevice::drainResume(); 2052702Sktlim@umich.edu 2062669Sktlim@umich.edu if (enabled()) { 2072292SN/A if (sys->bypassCaches()) { 2081060SN/A // We restart the HDLCD if we are in KVM mode. This 2091060SN/A // ensures that we always use the fast refresh logic if we 2101060SN/A // resume in KVM mode. 2114032Sktlim@umich.edu cmdDisable(); 2124032Sktlim@umich.edu cmdEnable(); 2134032Sktlim@umich.edu } else if (!pixelPump.active()) { 2141060SN/A // We restored from an old checkpoint without a pixel 2151060SN/A // pump, start an new refresh. This typically happens when 2161060SN/A // restoring from old checkpoints. 2171060SN/A cmdEnable(); 2181060SN/A } 2191060SN/A } 2201060SN/A 2211060SN/A // We restored from a checkpoint and need to update the VNC server 2221060SN/A if (pixelPump.active() && vnc) 2231060SN/A vnc->setDirty(); 2241060SN/A} 2251060SN/A 2261464SN/Avoid 2271464SN/AHDLcd::virtRefresh() 2282356SN/A{ 2291464SN/A pixelPump.renderFrame(); 2301464SN/A schedule(virtRefreshEvent, (curTick() + virtRefreshRate)); 2311060SN/A} 2321464SN/A 2331464SN/A// read registers and frame buffer 2341464SN/ATick 2351464SN/AHDLcd::read(PacketPtr pkt) 2361060SN/A{ 2373326Sktlim@umich.edu assert(pkt->getAddr() >= pioAddr && 2383326Sktlim@umich.edu pkt->getAddr() < pioAddr + pioSize); 2393326Sktlim@umich.edu 2407597Sminkyu.jeong@arm.com const Addr daddr(pkt->getAddr() - pioAddr); 2417597Sminkyu.jeong@arm.com panic_if(pkt->getSize() != 4, 2427597Sminkyu.jeong@arm.com "Unhandled read size (address: 0x.4x, size: %u)", 2433965Sgblack@eecs.umich.edu daddr, pkt->getSize()); 2447720Sgblack@eecs.umich.edu 2457720Sgblack@eecs.umich.edu const uint32_t data(readReg(daddr)); 2461060SN/A DPRINTF(HDLcd, "read register 0x%04x: 0x%x\n", daddr, data); 2477720Sgblack@eecs.umich.edu 2487720Sgblack@eecs.umich.edu pkt->set<uint32_t>(data); 2494636Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 2503794Sgblack@eecs.umich.edu return pioDelay; 2513794Sgblack@eecs.umich.edu} 2523794Sgblack@eecs.umich.edu 2533965Sgblack@eecs.umich.edu// write registers and frame buffer 2543965Sgblack@eecs.umich.eduTick 2552292SN/AHDLcd::write(PacketPtr pkt) 2562292SN/A{ 2572292SN/A assert(pkt->getAddr() >= pioAddr && 2582292SN/A pkt->getAddr() < pioAddr + pioSize); 2592292SN/A 2602292SN/A const Addr daddr(pkt->getAddr() - pioAddr); 2611060SN/A panic_if(pkt->getSize() != 4, 2621060SN/A "Unhandled read size (address: 0x.4x, size: %u)", 2631060SN/A daddr, pkt->getSize()); 2643770Sgblack@eecs.umich.edu const uint32_t data(pkt->get<uint32_t>()); 2653770Sgblack@eecs.umich.edu DPRINTF(HDLcd, "write register 0x%04x: 0x%x\n", daddr, data); 2663770Sgblack@eecs.umich.edu 2673770Sgblack@eecs.umich.edu writeReg(daddr, data); 2683770Sgblack@eecs.umich.edu 2693770Sgblack@eecs.umich.edu pkt->makeAtomicResponse(); 2703770Sgblack@eecs.umich.edu return pioDelay; 2713770Sgblack@eecs.umich.edu} 2723770Sgblack@eecs.umich.edu 2733770Sgblack@eecs.umich.eduuint32_t 2743770Sgblack@eecs.umich.eduHDLcd::readReg(Addr offset) 2753770Sgblack@eecs.umich.edu{ 2763770Sgblack@eecs.umich.edu switch (offset) { 2773770Sgblack@eecs.umich.edu case Version: return version; 2783770Sgblack@eecs.umich.edu 2793770Sgblack@eecs.umich.edu case Int_RawStat: return int_rawstat; 2803770Sgblack@eecs.umich.edu case Int_Clear: 2813770Sgblack@eecs.umich.edu panic("HDLCD INT_CLEAR register is Write-Only\n"); 2823770Sgblack@eecs.umich.edu case Int_Mask: return int_mask; 2833770Sgblack@eecs.umich.edu case Int_Status: return intStatus(); 2843770Sgblack@eecs.umich.edu 2853770Sgblack@eecs.umich.edu case Fb_Base: return fb_base; 2863770Sgblack@eecs.umich.edu case Fb_Line_Length: return fb_line_length; 2873770Sgblack@eecs.umich.edu case Fb_Line_Count: return fb_line_count; 2883770Sgblack@eecs.umich.edu case Fb_Line_Pitch: return fb_line_pitch; 2893770Sgblack@eecs.umich.edu case Bus_Options: return bus_options; 2901060SN/A 2913770Sgblack@eecs.umich.edu case V_Sync: return v_sync; 2923770Sgblack@eecs.umich.edu case V_Back_Porch: return v_back_porch; 2933770Sgblack@eecs.umich.edu case V_Data: return v_data; 2943770Sgblack@eecs.umich.edu case V_Front_Porch: return v_front_porch; 2953770Sgblack@eecs.umich.edu case H_Sync: return h_sync; 2963770Sgblack@eecs.umich.edu case H_Back_Porch: return h_back_porch; 2973770Sgblack@eecs.umich.edu case H_Data: return h_data; 2983770Sgblack@eecs.umich.edu case H_Front_Porch: return h_front_porch; 2993770Sgblack@eecs.umich.edu case Polarities: return polarities; 3003770Sgblack@eecs.umich.edu 3013770Sgblack@eecs.umich.edu case Command: return command; 3023770Sgblack@eecs.umich.edu case Pixel_Format: return pixel_format; 3033770Sgblack@eecs.umich.edu case Red_Select: return red_select; 3043770Sgblack@eecs.umich.edu case Green_Select: return green_select; 3053770Sgblack@eecs.umich.edu case Blue_Select: return blue_select; 3063770Sgblack@eecs.umich.edu 3073770Sgblack@eecs.umich.edu default: 3083770Sgblack@eecs.umich.edu panic("Tried to read HDLCD register that doesn't exist\n", offset); 3093770Sgblack@eecs.umich.edu } 3103770Sgblack@eecs.umich.edu} 3113770Sgblack@eecs.umich.edu 3123770Sgblack@eecs.umich.eduvoid 3133770Sgblack@eecs.umich.eduHDLcd::writeReg(Addr offset, uint32_t value) 3143770Sgblack@eecs.umich.edu{ 3153770Sgblack@eecs.umich.edu switch (offset) { 3163770Sgblack@eecs.umich.edu case Version: 3173770Sgblack@eecs.umich.edu panic("HDLCD VERSION register is read-Only\n"); 3183770Sgblack@eecs.umich.edu 3193770Sgblack@eecs.umich.edu case Int_RawStat: 3203770Sgblack@eecs.umich.edu intRaise(value); 3213770Sgblack@eecs.umich.edu return; 3223770Sgblack@eecs.umich.edu case Int_Clear: 3233770Sgblack@eecs.umich.edu intClear(value); 3243770Sgblack@eecs.umich.edu return; 3253770Sgblack@eecs.umich.edu case Int_Mask: 3263770Sgblack@eecs.umich.edu intMask(value); 3273770Sgblack@eecs.umich.edu return; 3283770Sgblack@eecs.umich.edu case Int_Status: 3293770Sgblack@eecs.umich.edu panic("HDLCD INT_STATUS register is read-Only\n"); 3303770Sgblack@eecs.umich.edu break; 3313770Sgblack@eecs.umich.edu 3323770Sgblack@eecs.umich.edu case Fb_Base: 3333770Sgblack@eecs.umich.edu fb_base = value; 3343770Sgblack@eecs.umich.edu return; 3353770Sgblack@eecs.umich.edu 3363770Sgblack@eecs.umich.edu case Fb_Line_Length: 3373770Sgblack@eecs.umich.edu fb_line_length = value; 3383770Sgblack@eecs.umich.edu return; 3393770Sgblack@eecs.umich.edu 3403770Sgblack@eecs.umich.edu case Fb_Line_Count: 3413770Sgblack@eecs.umich.edu fb_line_count = value; 3423770Sgblack@eecs.umich.edu return; 3433770Sgblack@eecs.umich.edu 3443770Sgblack@eecs.umich.edu case Fb_Line_Pitch: 3453770Sgblack@eecs.umich.edu fb_line_pitch = value; 3463770Sgblack@eecs.umich.edu return; 3473770Sgblack@eecs.umich.edu 3483770Sgblack@eecs.umich.edu case Bus_Options: { 3493770Sgblack@eecs.umich.edu const BusOptsReg old_bus_options(bus_options); 3503770Sgblack@eecs.umich.edu bus_options = value; 3513770Sgblack@eecs.umich.edu 3523770Sgblack@eecs.umich.edu if (bus_options.max_outstanding != old_bus_options.max_outstanding) { 3533770Sgblack@eecs.umich.edu DPRINTF(HDLcd, 3543770Sgblack@eecs.umich.edu "Changing HDLcd outstanding DMA transactions: %d -> %d\n", 3553770Sgblack@eecs.umich.edu old_bus_options.max_outstanding, 3563770Sgblack@eecs.umich.edu bus_options.max_outstanding); 3573770Sgblack@eecs.umich.edu 3583770Sgblack@eecs.umich.edu } 3593770Sgblack@eecs.umich.edu 3603770Sgblack@eecs.umich.edu if (bus_options.burst_len != old_bus_options.burst_len) { 3613770Sgblack@eecs.umich.edu DPRINTF(HDLcd, 3624636Sgblack@eecs.umich.edu "Changing HDLcd DMA burst flags: 0x%x -> 0x%x\n", 3634636Sgblack@eecs.umich.edu old_bus_options.burst_len, bus_options.burst_len); 3647720Sgblack@eecs.umich.edu } 3657720Sgblack@eecs.umich.edu } return; 3664636Sgblack@eecs.umich.edu 3674636Sgblack@eecs.umich.edu case V_Sync: 3684636Sgblack@eecs.umich.edu v_sync = value; 3697720Sgblack@eecs.umich.edu return; 3707720Sgblack@eecs.umich.edu case V_Back_Porch: 3713770Sgblack@eecs.umich.edu v_back_porch = value; 3722292SN/A return; 3732292SN/A case V_Data: 3747720Sgblack@eecs.umich.edu v_data = value; 3757720Sgblack@eecs.umich.edu return; 3762292SN/A case V_Front_Porch: 3772292SN/A v_front_porch = value; 3782292SN/A return; 3797720Sgblack@eecs.umich.edu 3807720Sgblack@eecs.umich.edu case H_Sync: 3811060SN/A h_sync = value; 3822292SN/A return; 3832292SN/A case H_Back_Porch: 3842292SN/A h_back_porch = value; 3852107SN/A return; 3861060SN/A case H_Data: 3871060SN/A h_data = value; 3881060SN/A return; 3891060SN/A case H_Front_Porch: 3901464SN/A h_front_porch = value; 3911684SN/A return; 3921464SN/A 3931060SN/A case Polarities: 3941464SN/A polarities = value; 3951060SN/A return; 3961060SN/A 3971060SN/A case Command: { 3981060SN/A const CommandReg new_command(value); 3991060SN/A 4001060SN/A if (new_command.enable != command.enable) { 4013326Sktlim@umich.edu DPRINTF(HDLcd, "HDLCD switched %s\n", 4025712Shsul@eecs.umich.edu new_command.enable ? "on" : "off"); 4033326Sktlim@umich.edu 4045714Shsul@eecs.umich.edu if (new_command.enable) { 4055714Shsul@eecs.umich.edu cmdEnable(); 4065714Shsul@eecs.umich.edu } else { 4071060SN/A cmdDisable(); 4082132SN/A } 4091060SN/A } 4101060SN/A command = new_command; 4111060SN/A } return; 4121060SN/A 4132292SN/A case Pixel_Format: 4141060SN/A pixel_format = value; 4151060SN/A return; 4161060SN/A 4177720Sgblack@eecs.umich.edu case Red_Select: 4187720Sgblack@eecs.umich.edu red_select = value; 4193965Sgblack@eecs.umich.edu return; 4207720Sgblack@eecs.umich.edu case Green_Select: 4213965Sgblack@eecs.umich.edu green_select = value; 4222935Sksewell@umich.edu return; 4237720Sgblack@eecs.umich.edu case Blue_Select: 4241060SN/A blue_select = value; 4253794Sgblack@eecs.umich.edu return; 4267720Sgblack@eecs.umich.edu 4273794Sgblack@eecs.umich.edu default: 4283794Sgblack@eecs.umich.edu panic("Tried to write HDLCD register that doesn't exist\n", offset); 4297720Sgblack@eecs.umich.edu return; 4301060SN/A } 4314636Sgblack@eecs.umich.edu} 4327720Sgblack@eecs.umich.edu 4334636Sgblack@eecs.umich.eduPixelConverter 4341060SN/AHDLcd::pixelConverter() const 4353794Sgblack@eecs.umich.edu{ 4363794Sgblack@eecs.umich.edu ByteOrder byte_order( 4373794Sgblack@eecs.umich.edu pixel_format.big_endian ? BigEndianByteOrder : LittleEndianByteOrder); 4383794Sgblack@eecs.umich.edu 4393794Sgblack@eecs.umich.edu /* Some Linux kernels have a broken driver that swaps the red and 4403794Sgblack@eecs.umich.edu * blue color select registers. */ 4413794Sgblack@eecs.umich.edu if (!workaroundSwapRB) { 4423794Sgblack@eecs.umich.edu return PixelConverter( 4433794Sgblack@eecs.umich.edu pixel_format.bytes_per_pixel + 1, 4441060SN/A red_select.offset, green_select.offset, blue_select.offset, 4451060SN/A red_select.size, green_select.size, blue_select.size, 4462935Sksewell@umich.edu byte_order); 4473794Sgblack@eecs.umich.edu } else { 4487720Sgblack@eecs.umich.edu return PixelConverter( 4497720Sgblack@eecs.umich.edu pixel_format.bytes_per_pixel + 1, 4507720Sgblack@eecs.umich.edu blue_select.offset, green_select.offset, red_select.offset, 4513794Sgblack@eecs.umich.edu blue_select.size, green_select.size, red_select.size, 4523794Sgblack@eecs.umich.edu byte_order); 4531060SN/A } 4541060SN/A} 4551060SN/A 4565543Ssaidi@eecs.umich.eduDisplayTimings 4575543Ssaidi@eecs.umich.eduHDLcd::displayTimings() const 4585543Ssaidi@eecs.umich.edu{ 4595543Ssaidi@eecs.umich.edu return DisplayTimings( 4602336SN/A h_data.val + 1, v_data.val + 1, 4612336SN/A h_back_porch.val + 1, h_sync.val + 1, h_front_porch.val + 1, 4621060SN/A v_back_porch.val + 1, v_sync.val + 1, v_front_porch.val + 1); 4631060SN/A} 4641060SN/A 4655543Ssaidi@eecs.umich.eduvoid 4665543Ssaidi@eecs.umich.eduHDLcd::createDmaEngine() 4675543Ssaidi@eecs.umich.edu{ 4685543Ssaidi@eecs.umich.edu if (bus_options.max_outstanding == 0) { 4695543Ssaidi@eecs.umich.edu warn("Maximum number of outstanding DMA transfers set to 0."); 4705543Ssaidi@eecs.umich.edu return; 4711060SN/A } 4725543Ssaidi@eecs.umich.edu 4735543Ssaidi@eecs.umich.edu const uint32_t dma_burst_flags(bus_options.burst_len); 4742935Sksewell@umich.edu const uint32_t dma_burst_len( 4751060SN/A dma_burst_flags ? 4761060SN/A (1UL << (findMsbSet(dma_burst_flags) - 1)) : 4772292SN/A MAX_BURST_LEN); 4782731Sktlim@umich.edu // Some drivers seem to set the DMA line count incorrectly. This 4792292SN/A // could either be a driver bug or a specification bug. Unlike for 4802731Sktlim@umich.edu // timings, the specification does not require 1 to be added to 4817784SAli.Saidi@ARM.com // the DMA engine's line count. 4821060SN/A const uint32_t dma_lines( 4831060SN/A fb_line_count + (workaroundDmaLineCount ? 1 : 0)); 4841060SN/A 4852292SN/A dmaEngine.reset(new DmaEngine( 4862336SN/A *this, pixelBufferSize, 4872308SN/A AXI_PORT_WIDTH * dma_burst_len, 4884828Sgblack@eecs.umich.edu bus_options.max_outstanding, 4894654Sgblack@eecs.umich.edu fb_line_length, fb_line_pitch, dma_lines)); 4904654Sgblack@eecs.umich.edu} 4914636Sgblack@eecs.umich.edu 4924654Sgblack@eecs.umich.eduvoid 4934654Sgblack@eecs.umich.eduHDLcd::cmdEnable() 4944636Sgblack@eecs.umich.edu{ 4952292SN/A createDmaEngine(); 4962292SN/A conv = pixelConverter(); 4972731Sktlim@umich.edu 4982292SN/A // Update timing parameter before rendering frames 4992292SN/A pixelPump.updateTimings(displayTimings()); 5002731Sktlim@umich.edu 5012292SN/A if (sys->bypassCaches()) { 5022292SN/A schedule(virtRefreshEvent, clockEdge()); 5032731Sktlim@umich.edu } else { 5042292SN/A pixelPump.start(); 5052292SN/A } 5062731Sktlim@umich.edu} 5072292SN/A 5082292SN/Avoid 5092731Sktlim@umich.eduHDLcd::cmdDisable() 5102292SN/A{ 5112292SN/A pixelPump.stop(); 5122731Sktlim@umich.edu // Disable the virtual refresh event 5132292SN/A if (virtRefreshEvent.scheduled()) { 5142731Sktlim@umich.edu assert(sys->bypassCaches()); 5152731Sktlim@umich.edu deschedule(virtRefreshEvent); 5162292SN/A } 5172292SN/A dmaEngine->abortFrame(); 5182292SN/A} 5192292SN/A 5202292SN/Abool 5212292SN/AHDLcd::pxlNext(Pixel &p) 5222731Sktlim@umich.edu{ 5231060SN/A uint8_t pixel_data[MAX_PIXEL_SIZE]; 5241464SN/A assert(conv.length <= sizeof(pixel_data)); 5251464SN/A if (dmaEngine->tryGet(pixel_data, conv.length)) { 5261464SN/A p = conv.toPixel(pixel_data); 5271464SN/A return true; 5287720Sgblack@eecs.umich.edu } else { 5297720Sgblack@eecs.umich.edu return false; 5301464SN/A } 5312292SN/A} 5325543Ssaidi@eecs.umich.edu 5331684SN/Avoid 5342292SN/AHDLcd::pxlVSyncBegin() 5351060SN/A{ 5361060SN/A DPRINTF(HDLcd, "Raising VSYNC interrupt.\n"); 5371060SN/A intRaise(INT_VSYNC); 5381060SN/A} 5391060SN/A 5401060SN/Avoid 5411060SN/AHDLcd::pxlVSyncEnd() 5421060SN/A{ 5432292SN/A DPRINTF(HDLcd, "End of VSYNC, starting DMA engine\n"); 5441060SN/A dmaEngine->startFrame(fb_base); 5451060SN/A} 5462292SN/A 5471060SN/Avoid 5481684SN/AHDLcd::pxlUnderrun() 5491464SN/A{ 5501684SN/A DPRINTF(HDLcd, "Buffer underrun, stopping DMA fill.\n"); 5511684SN/A ++stats.underruns; 5522356SN/A intRaise(INT_UNDERRUN); 5531684SN/A dmaEngine->abortFrame(); 5541684SN/A} 5551464SN/A 5561060SN/Avoid 5572702Sktlim@umich.eduHDLcd::pxlFrameDone() 5583735Sstever@eecs.umich.edu{ 5591060SN/A DPRINTF(HDLcd, "Reached end of last visible line.\n"); 5603326Sktlim@umich.edu 5613326Sktlim@umich.edu if (dmaEngine->size()) { 5621060SN/A warn("HDLCD %u bytes still in FIFO after frame: Ensure that DMA " 5631060SN/A "and PixelPump configuration is consistent\n", 5642702Sktlim@umich.edu dmaEngine->size()); 5653735Sstever@eecs.umich.edu dmaEngine->dumpSettings(); 5663735Sstever@eecs.umich.edu pixelPump.dumpSettings(); 5672690Sktlim@umich.edu } 5683326Sktlim@umich.edu 5693326Sktlim@umich.edu if (vnc) 5703326Sktlim@umich.edu vnc->setDirty(); 5713326Sktlim@umich.edu 5723326Sktlim@umich.edu if (enableCapture) { 5733326Sktlim@umich.edu if (!pic) { 5743326Sktlim@umich.edu pic = simout.create( 5753326Sktlim@umich.edu csprintf("%s.framebuffer.bmp", sys->name()), 5762690Sktlim@umich.edu true); 5772690Sktlim@umich.edu } 5782702Sktlim@umich.edu 5793735Sstever@eecs.umich.edu assert(pic); 5801060SN/A pic->stream()->seekp(0); 5813326Sktlim@umich.edu bmp.write(*pic->stream()); 5823326Sktlim@umich.edu } 5832308SN/A} 5841060SN/A 5852702Sktlim@umich.eduvoid 5863735Sstever@eecs.umich.eduHDLcd::setInterrupts(uint32_t ints, uint32_t mask) 5873735Sstever@eecs.umich.edu{ 5882308SN/A const bool old_ints(intStatus()); 5893326Sktlim@umich.edu 5903326Sktlim@umich.edu int_mask = mask; 5912308SN/A int_rawstat = ints; 5921060SN/A 5932702Sktlim@umich.edu if (!old_ints && intStatus()) { 5943735Sstever@eecs.umich.edu gic->sendInt(intNum); 5952308SN/A } else if (old_ints && !intStatus()) { 5963326Sktlim@umich.edu gic->clearInt(intNum); 5973326Sktlim@umich.edu } 5981060SN/A} 5991060SN/A 6002190SN/AHDLcd::DmaEngine::DmaEngine(HDLcd &_parent, size_t size, 6012292SN/A unsigned request_size, unsigned max_pending, 6022190SN/A size_t line_size, ssize_t line_pitch, unsigned num_lines) 6032331SN/A : DmaReadFifo( 6042292SN/A _parent.dmaPort, size, request_size, max_pending, 6052190SN/A Request::UNCACHEABLE), 6061684SN/A parent(_parent), 6071464SN/A lineSize(line_size), linePitch(line_pitch), numLines(num_lines), 6081464SN/A nextLineAddr(0) 6091464SN/A{ 6101464SN/A} 6111464SN/A 6121684SN/Avoid 6132731Sktlim@umich.eduHDLcd::DmaEngine::serialize(CheckpointOut &cp) const 6141464SN/A{ 6152292SN/A DmaReadFifo::serialize(cp); 6162731Sktlim@umich.edu 6171464SN/A SERIALIZE_SCALAR(nextLineAddr); 6182731Sktlim@umich.edu SERIALIZE_SCALAR(frameEnd); 6192731Sktlim@umich.edu} 6202308SN/A 6212731Sktlim@umich.eduvoid 6222731Sktlim@umich.eduHDLcd::DmaEngine::unserialize(CheckpointIn &cp) 6232308SN/A{ 6241060SN/A DmaReadFifo::unserialize(cp); 6252731Sktlim@umich.edu 6261060SN/A UNSERIALIZE_SCALAR(nextLineAddr); 6271060SN/A UNSERIALIZE_SCALAR(frameEnd); 6282731Sktlim@umich.edu} 6291060SN/A 6304032Sktlim@umich.eduvoid 6314032Sktlim@umich.eduHDLcd::DmaEngine::startFrame(Addr fb_base) 6324032Sktlim@umich.edu{ 6331060SN/A nextLineAddr = fb_base; 6342731Sktlim@umich.edu frameEnd = fb_base + numLines * linePitch; 6351060SN/A 6361060SN/A startFill(nextLineAddr, lineSize); 6372731Sktlim@umich.edu} 6381060SN/A 6394032Sktlim@umich.eduvoid 6404032Sktlim@umich.eduHDLcd::DmaEngine::abortFrame() 6414032Sktlim@umich.edu{ 6421060SN/A nextLineAddr = frameEnd; 6432731Sktlim@umich.edu stopFill(); 6441060SN/A flush(); 6451060SN/A} 6462731Sktlim@umich.edu 6471060SN/A 6481060SN/Avoid 6492731Sktlim@umich.eduHDLcd::DmaEngine::dumpSettings() 6501060SN/A{ 6511061SN/A inform("DMA line size: %u bytes", lineSize); 6522731Sktlim@umich.edu inform("DMA line pitch: %i bytes", linePitch); 6531061SN/A inform("DMA num lines: %u", numLines); 6541060SN/A} 6552731Sktlim@umich.edu 6562731Sktlim@umich.eduvoid 6572731Sktlim@umich.eduHDLcd::DmaEngine::onEndOfBlock() 6582731Sktlim@umich.edu{ 6592731Sktlim@umich.edu if (nextLineAddr == frameEnd) 6601060SN/A // We're done with this frame. Ignore calls to this method 6612292SN/A // until the next frame has been started. 6622731Sktlim@umich.edu return; 6632292SN/A 6642292SN/A nextLineAddr += linePitch; 6652731Sktlim@umich.edu if (nextLineAddr != frameEnd) 6662292SN/A startFill(nextLineAddr, lineSize); 6671060SN/A} 6682731Sktlim@umich.edu 6691060SN/Avoid 6701060SN/AHDLcd::DmaEngine::onIdle() 6712731Sktlim@umich.edu{ 6721060SN/A parent.intRaise(INT_DMA_END); 6732292SN/A} 6742292SN/A 6752292SN/Avoid 6762731Sktlim@umich.eduHDLcd::PixelPump::dumpSettings() 6772292SN/A{ 6782292SN/A const DisplayTimings &t(timings()); 6792731Sktlim@umich.edu 6802731Sktlim@umich.edu inform("PixelPump width: %u", t.width); 6812731Sktlim@umich.edu inform("PixelPump height: %u", t.height); 6822731Sktlim@umich.edu 6832292SN/A inform("PixelPump horizontal back porch: %u", t.hBackPorch); 6841060SN/A inform("PixelPump horizontal fron porch: %u", t.hFrontPorch); 6852731Sktlim@umich.edu inform("PixelPump horizontal fron porch: %u", t.hSync); 6861060SN/A 6871060SN/A inform("PixelPump vertical back porch: %u", t.vBackPorch); 6882731Sktlim@umich.edu inform("PixelPump vertical fron porch: %u", t.vFrontPorch); 6892292SN/A inform("PixelPump vertical fron porch: %u", t.vSync); 6902292SN/A} 6912292SN/A 6922292SN/A 6932292SN/AHDLcd * 6942731Sktlim@umich.eduHDLcdParams::create() 6952292SN/A{ 6962292SN/A return new HDLcd(this); 6972731Sktlim@umich.edu} 6982731Sktlim@umich.edu