diff --git a/src/dev/arm/RealView.py b/src/dev/arm/RealView.py index 4db732d38..20112d426 100644 --- a/src/dev/arm/RealView.py +++ b/src/dev/arm/RealView.py @@ -298,6 +298,8 @@ class HDLcd(AmbaDmaDevice): pxl_clk = Param.ClockDomain("Pixel clock source") pixel_chunk = Param.Unsigned(32, "Number of pixels to handle in one batch") + virt_refresh_rate = Param.Frequency("20Hz", "Frame refresh rate " + "in KVM mode") class RealView(Platform): type = 'RealView' diff --git a/src/dev/arm/hdlcd.cc b/src/dev/arm/hdlcd.cc index a92ae4627..081fec2ff 100644 --- a/src/dev/arm/hdlcd.cc +++ b/src/dev/arm/hdlcd.cc @@ -65,6 +65,7 @@ HDLcd::HDLcd(const HDLcdParams *p) addrRanges{RangeSize(pioAddr, pioSize)}, enableCapture(p->enable_capture), pixelBufferSize(p->pixel_buffer_size), + virtRefreshRate(p->virt_refresh_rate), // Registers version(VERSION_RESETV), @@ -82,6 +83,7 @@ HDLcd::HDLcd(const HDLcdParams *p) pixel_format(0), red_select(0), green_select(0), blue_select(0), + virtRefreshEvent(this), // Other bmp(&pixelPump.fb), pic(NULL), conv(PixelConverter::rgba8888_le), pixelPump(*this, *p->pxl_clk, p->pixel_chunk) @@ -201,13 +203,19 @@ HDLcd::drainResume() { AmbaDmaDevice::drainResume(); - // We restored from an old checkpoint without a pixel pump, start - // an new refresh. This typically happens when restoring from old - // checkpoints. - if (enabled() && !pixelPump.active()) { - // Update timing parameter before rendering frames - pixelPump.updateTimings(displayTimings()); - pixelPump.start(); + if (enabled()) { + if (sys->bypassCaches()) { + // We restart the HDLCD if we are in KVM mode. This + // ensures that we always use the fast refresh logic if we + // resume in KVM mode. + cmdDisable(); + cmdEnable(); + } else if (!pixelPump.active()) { + // We restored from an old checkpoint without a pixel + // pump, start an new refresh. This typically happens when + // restoring from old checkpoints. + cmdEnable(); + } } // We restored from a checkpoint and need to update the VNC server @@ -215,6 +223,13 @@ HDLcd::drainResume() vnc->setDirty(); } +void +HDLcd::virtRefresh() +{ + pixelPump.renderFrame(); + schedule(virtRefreshEvent, (curTick() + virtRefreshRate)); +} + // read registers and frame buffer Tick HDLcd::read(PacketPtr pkt) @@ -482,13 +497,23 @@ HDLcd::cmdEnable() // Update timing parameter before rendering frames pixelPump.updateTimings(displayTimings()); - pixelPump.start(); + + if (sys->bypassCaches()) { + schedule(virtRefreshEvent, clockEdge()); + } else { + pixelPump.start(); + } } void HDLcd::cmdDisable() { pixelPump.stop(); + // Disable the virtual refresh event + if (virtRefreshEvent.scheduled()) { + assert(sys->bypassCaches()); + deschedule(virtRefreshEvent); + } dmaEngine->abortFrame(); } diff --git a/src/dev/arm/hdlcd.hh b/src/dev/arm/hdlcd.hh index acce6f191..4bca0bbbf 100644 --- a/src/dev/arm/hdlcd.hh +++ b/src/dev/arm/hdlcd.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013, 2015 ARM Limited + * Copyright (c) 2010-2013, 2015, 2017 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -116,6 +116,7 @@ class HDLcd: public AmbaDmaDevice const AddrRangeList addrRanges; const bool enableCapture; const Addr pixelBufferSize; + const Tick virtRefreshRate; protected: // Register handling /** ARM HDLcd register offsets */ @@ -344,6 +345,10 @@ class HDLcd: public AmbaDmaDevice HDLcd &parent; }; + /** Handler for fast frame refresh in KVM-mode */ + void virtRefresh(); + EventWrapper virtRefreshEvent; + /** Helper to write out bitmaps */ Bitmap bmp;