dev, arm: Render HDLCD frames at a fixed rate in KVM
Use the new fast scan-out API in the PixelPump to render frames at a fixed frame rate in KVM mode. The refresh rate when running in KVM can be controlled by the virt_refresh_rate parameter. Change-Id: Ib3c78f174e3f8f4ca8a9b723c4e5d311a433b8aa Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-on: https://gem5-review.googlesource.com/2242 Reviewed-by: Rahul Thakur <rjthakur@google.com>
This commit is contained in:
parent
9dd54d10ab
commit
846a17308c
3 changed files with 41 additions and 9 deletions
|
@ -298,6 +298,8 @@ class HDLcd(AmbaDmaDevice):
|
||||||
|
|
||||||
pxl_clk = Param.ClockDomain("Pixel clock source")
|
pxl_clk = Param.ClockDomain("Pixel clock source")
|
||||||
pixel_chunk = Param.Unsigned(32, "Number of pixels to handle in one batch")
|
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):
|
class RealView(Platform):
|
||||||
type = 'RealView'
|
type = 'RealView'
|
||||||
|
|
|
@ -65,6 +65,7 @@ HDLcd::HDLcd(const HDLcdParams *p)
|
||||||
addrRanges{RangeSize(pioAddr, pioSize)},
|
addrRanges{RangeSize(pioAddr, pioSize)},
|
||||||
enableCapture(p->enable_capture),
|
enableCapture(p->enable_capture),
|
||||||
pixelBufferSize(p->pixel_buffer_size),
|
pixelBufferSize(p->pixel_buffer_size),
|
||||||
|
virtRefreshRate(p->virt_refresh_rate),
|
||||||
|
|
||||||
// Registers
|
// Registers
|
||||||
version(VERSION_RESETV),
|
version(VERSION_RESETV),
|
||||||
|
@ -82,6 +83,7 @@ HDLcd::HDLcd(const HDLcdParams *p)
|
||||||
pixel_format(0),
|
pixel_format(0),
|
||||||
red_select(0), green_select(0), blue_select(0),
|
red_select(0), green_select(0), blue_select(0),
|
||||||
|
|
||||||
|
virtRefreshEvent(this),
|
||||||
// Other
|
// Other
|
||||||
bmp(&pixelPump.fb), pic(NULL), conv(PixelConverter::rgba8888_le),
|
bmp(&pixelPump.fb), pic(NULL), conv(PixelConverter::rgba8888_le),
|
||||||
pixelPump(*this, *p->pxl_clk, p->pixel_chunk)
|
pixelPump(*this, *p->pxl_clk, p->pixel_chunk)
|
||||||
|
@ -201,13 +203,19 @@ HDLcd::drainResume()
|
||||||
{
|
{
|
||||||
AmbaDmaDevice::drainResume();
|
AmbaDmaDevice::drainResume();
|
||||||
|
|
||||||
// We restored from an old checkpoint without a pixel pump, start
|
if (enabled()) {
|
||||||
// an new refresh. This typically happens when restoring from old
|
if (sys->bypassCaches()) {
|
||||||
// checkpoints.
|
// We restart the HDLCD if we are in KVM mode. This
|
||||||
if (enabled() && !pixelPump.active()) {
|
// ensures that we always use the fast refresh logic if we
|
||||||
// Update timing parameter before rendering frames
|
// resume in KVM mode.
|
||||||
pixelPump.updateTimings(displayTimings());
|
cmdDisable();
|
||||||
pixelPump.start();
|
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
|
// We restored from a checkpoint and need to update the VNC server
|
||||||
|
@ -215,6 +223,13 @@ HDLcd::drainResume()
|
||||||
vnc->setDirty();
|
vnc->setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HDLcd::virtRefresh()
|
||||||
|
{
|
||||||
|
pixelPump.renderFrame();
|
||||||
|
schedule(virtRefreshEvent, (curTick() + virtRefreshRate));
|
||||||
|
}
|
||||||
|
|
||||||
// read registers and frame buffer
|
// read registers and frame buffer
|
||||||
Tick
|
Tick
|
||||||
HDLcd::read(PacketPtr pkt)
|
HDLcd::read(PacketPtr pkt)
|
||||||
|
@ -482,13 +497,23 @@ HDLcd::cmdEnable()
|
||||||
|
|
||||||
// Update timing parameter before rendering frames
|
// Update timing parameter before rendering frames
|
||||||
pixelPump.updateTimings(displayTimings());
|
pixelPump.updateTimings(displayTimings());
|
||||||
|
|
||||||
|
if (sys->bypassCaches()) {
|
||||||
|
schedule(virtRefreshEvent, clockEdge());
|
||||||
|
} else {
|
||||||
pixelPump.start();
|
pixelPump.start();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HDLcd::cmdDisable()
|
HDLcd::cmdDisable()
|
||||||
{
|
{
|
||||||
pixelPump.stop();
|
pixelPump.stop();
|
||||||
|
// Disable the virtual refresh event
|
||||||
|
if (virtRefreshEvent.scheduled()) {
|
||||||
|
assert(sys->bypassCaches());
|
||||||
|
deschedule(virtRefreshEvent);
|
||||||
|
}
|
||||||
dmaEngine->abortFrame();
|
dmaEngine->abortFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010-2013, 2015 ARM Limited
|
* Copyright (c) 2010-2013, 2015, 2017 ARM Limited
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* The license below extends only to copyright in the software and shall
|
* The license below extends only to copyright in the software and shall
|
||||||
|
@ -116,6 +116,7 @@ class HDLcd: public AmbaDmaDevice
|
||||||
const AddrRangeList addrRanges;
|
const AddrRangeList addrRanges;
|
||||||
const bool enableCapture;
|
const bool enableCapture;
|
||||||
const Addr pixelBufferSize;
|
const Addr pixelBufferSize;
|
||||||
|
const Tick virtRefreshRate;
|
||||||
|
|
||||||
protected: // Register handling
|
protected: // Register handling
|
||||||
/** ARM HDLcd register offsets */
|
/** ARM HDLcd register offsets */
|
||||||
|
@ -344,6 +345,10 @@ class HDLcd: public AmbaDmaDevice
|
||||||
HDLcd &parent;
|
HDLcd &parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Handler for fast frame refresh in KVM-mode */
|
||||||
|
void virtRefresh();
|
||||||
|
EventWrapper<HDLcd, &HDLcd::virtRefresh> virtRefreshEvent;
|
||||||
|
|
||||||
/** Helper to write out bitmaps */
|
/** Helper to write out bitmaps */
|
||||||
Bitmap bmp;
|
Bitmap bmp;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue