dev: Fix the Pl111 timings by separating pixel and DMA clock
authorAndreas Hansson <andreas.hansson@arm.com>
Mon, 7 Jan 2013 18:05:36 +0000 (13:05 -0500)
committerAndreas Hansson <andreas.hansson@arm.com>
Mon, 7 Jan 2013 18:05:36 +0000 (13:05 -0500)
This patch fixes the Pl111 timings by creating a separate clock for
the pixel timings. The device clock is used for all interactions with
the memory system, just like the AHB clock on the actual module.

The result without this patch is that the module only is allowed to
send one request every tick of the 24MHz clock which causes a huge
backlog.

src/dev/arm/RealView.py
src/dev/arm/pl111.cc
src/dev/arm/pl111.hh

index 51a82f4386fca3af5577385a111bc5d4febbcf31..f2fc9c0af2055da3586b12050e3265c34ae12adc 100644 (file)
@@ -148,8 +148,7 @@ class Pl050(AmbaIntDevice):
 class Pl111(AmbaDmaDevice):
     type = 'Pl111'
     cxx_header = "dev/arm/pl111.hh"
-    # Override the default clock
-    clock = '24MHz'
+    pixel_clock = Param.Clock('24MHz', "Pixel clock")
     vnc   = Param.VncInput(Parent.any, "Vnc server for remote frame buffer display")
     amba_id = 0x00141111
 
index c68f606cd444f5900f8d9397a86651bff27c1caa..2973cda27645f7412f8138221bfca34fce09e35c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2012 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -64,6 +64,7 @@ Pl111::Pl111(const Params *p)
       clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
       clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
       clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0),
+      pixelClock(p->pixel_clock),
       vnc(p->vnc), bmp(NULL), width(LcdMaxWidth), height(LcdMaxHeight),
       bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
       waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
@@ -440,14 +441,12 @@ Pl111::readFramebuffer()
         schedule(intEvent, nextCycle());
 
     curAddr = 0;
-    startTime = curCycle();
+    startTime = curTick();
 
     maxAddr = static_cast<Addr>(length * bytesPerPixel);
 
     DPRINTF(PL111, " lcd frame buffer size of %d bytes \n", maxAddr);
 
-    dmaPendingNum = 0;
-
     fillFifo();
 }
 
@@ -475,13 +474,15 @@ Pl111::fillFifo()
 void
 Pl111::dmaDone()
 {
-    Cycles maxFrameTime(lcdTiming2.cpl * height);
+    DPRINTF(PL111, "DMA Done\n");
+
+    Tick maxFrameTime = lcdTiming2.cpl * height * pixelClock;
 
     --dmaPendingNum;
 
     if (maxAddr == curAddr && !dmaPendingNum) {
-        if ((curCycle() - startTime) > maxFrameTime) {
-            warn("CLCD controller buffer underrun, took %d cycles when should"
+        if ((curTick() - startTime) > maxFrameTime) {
+            warn("CLCD controller buffer underrun, took %d ticks when should"
                  " have taken %d\n", curTick() - startTime, maxFrameTime);
             lcdRis.underflow = 1;
             if (!intEvent.scheduled())
@@ -500,14 +501,11 @@ Pl111::dmaDone()
 
         // schedule the next read based on when the last frame started
         // and the desired fps (i.e. maxFrameTime), we turn the
-        // argument into a relative number of cycles in the future by
-        // subtracting curCycle()
+        // argument into a relative number of cycles in the future
         if (lcdControl.lcden)
-            // @todo: This is a terrible way of doing the time
-            // keeping, make it all relative
-            schedule(readEvent,
-                     clockEdge(Cycles(startTime - curCycle() +
-                                      maxFrameTime)));
+            schedule(readEvent, clockEdge(ticksToCycles(startTime -
+                                                        curTick() +
+                                                        maxFrameTime)));
     }
 
     if (dmaPendingNum > (maxOutstandingDma - waterMark))
index 49512fcc00ba58f67d8760ee21315256945280f2..2388e1c7ab0e895bdc5bcc397041031c0cc8e83a 100644 (file)
@@ -227,6 +227,9 @@ class Pl111: public AmbaDmaDevice
     /** Cursor masked interrupt status register - const */
     InterruptReg clcdCrsrMis;
 
+    /** Pixel clock */
+    Tick pixelClock;
+
     /** VNC server */
     VncInput *vnc;