1/* |
2 * Copyright (c) 2010-2013, 2015 ARM Limited |
3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated --- 21 unchanged lines hidden (view full) --- 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Chris Emmons 38 */ 39 |
40#include "dev/arm/hdlcd.hh" 41 |
42#include "base/vnc/vncinput.hh" |
43#include "base/output.hh" 44#include "base/trace.hh" 45#include "debug/HDLcd.hh" 46#include "debug/Uart.hh" 47#include "dev/arm/amba_device.hh" 48#include "dev/arm/base_gic.hh" |
49#include "mem/packet.hh" 50#include "mem/packet_access.hh" 51#include "sim/system.hh" 52 53using std::vector; 54 55 56// initialize hdlcd registers 57HDLcd::HDLcd(const Params *p) 58 : AmbaDmaDevice(p), version(VERSION_RESETV), 59 int_rawstat(0), int_clear(0), int_mask(0), int_status(0), 60 fb_base(0), fb_line_length(0), fb_line_count(0), fb_line_pitch(0), 61 bus_options(BUS_OPTIONS_RESETV), 62 v_sync(0), v_back_porch(0), v_data(0), v_front_porch(0), 63 h_sync(0), h_back_porch(0), h_data(0), h_front_porch(0), 64 polarities(0), command(0), pixel_format(0), 65 red_select(0), green_select(0), blue_select(0), |
66 pixelClock(p->pixel_clock), 67 fb(0, 0), vnc(p->vnc), bmp(&fb), pic(NULL), |
68 frameReadStartTime(0), 69 dmaStartAddr(0), dmaCurAddr(0), dmaMaxAddr(0), dmaPendingNum(0), |
70 frameUnderrun(false), pixelBufferSize(0), |
71 pixelIndex(0), doUpdateParams(false), frameUnderway(false), 72 dmaBytesInFlight(0), 73 startFrameEvent(this), endFrameEvent(this), renderPixelEvent(this), 74 fillPixelBufferEvent(this), intEvent(this), 75 dmaDoneEventAll(MAX_OUTSTANDING_DMA_REQ_CAPACITY, this), 76 dmaDoneEventFree(MAX_OUTSTANDING_DMA_REQ_CAPACITY), 77 enableCapture(p->enable_capture) 78{ 79 pioSize = 0xFFFF; 80 81 for (int i = 0; i < MAX_OUTSTANDING_DMA_REQ_CAPACITY; ++i) 82 dmaDoneEventFree[i] = &dmaDoneEventAll[i]; 83 84 if (vnc) |
85 vnc->setFrameBuffer(&fb); |
86} 87 88HDLcd::~HDLcd() 89{ |
90} 91 92// read registers and frame buffer 93Tick 94HDLcd::read(PacketPtr pkt) 95{ 96 uint32_t data = 0; 97 const Addr daddr = pkt->getAddr() - pioAddr; --- 211 unchanged lines hidden (view full) --- 309 310 pkt->makeAtomicResponse(); 311 return pioDelay; 312} 313 314void 315HDLcd::updateVideoParams(bool unserializing = false) 316{ |
317 const uint16_t bpp M5_VAR_USED = bytesPerPixel() << 3; |
318 |
319 // Workaround configuration bugs where multiple display 320 // controllers are attached to the same VNC server by reattaching 321 // enabled devices. This isn't ideal, but works as long as only 322 // one display controller is active at a time. 323 if (command.enable && vnc) 324 vnc->setFrameBuffer(&fb); 325 |
326 // updating these parameters while LCD is enabled is not supported 327 if (frameUnderway && !unserializing) 328 panic("Attempting to change some HDLCD parameters while the controller" 329 " is active is not allowed"); 330 331 // resize the virtualDisplayBuffer unless we are unserializing - it may 332 // have changed size 333 // there must be no outstanding DMA transactions for this to work 334 if (!unserializing) { 335 assert(dmaPendingNum == 0); |
336 |
337 virtualDisplayBuffer.resize(bytesPerPixel() * area()); 338 fb.resize(width(), height()); 339 fb.clear(); |
340 |
341 std::fill(virtualDisplayBuffer.begin(), virtualDisplayBuffer.end(), 342 0); 343 } |
344 345 DPRINTF(HDLcd, "bpp = %d\n", bpp); 346 DPRINTF(HDLcd, "display size = %d x %d\n", width(), height()); 347#if TRACING_ON 348 const size_t totalLinesPerFrame = v_back_porch.val + 1 + 349 v_data.val + 1 + 350 v_front_porch.val + 1 + 351 v_sync.val + 1; 352 const double fps = (double)SimClock::Frequency / 353 (double)(PClksPerLine() * totalLinesPerFrame * pixelClock); 354#endif 355 DPRINTF(HDLcd, "simulated refresh rate ~ %.1ffps generating ~ %.1fMB/s " 356 "traffic ([%.1fMHz, T=%d sim clocks] pclk, %d bpp => %.1fMB/s peak requirement)\n", 357 fps, |
358 fps * virtualDisplayBuffer.size() / 1024 / 1024, |
359 (double)SimClock::Frequency / pixelClock / 1000000.0, 360 pixelClock, 361 bpp, 362 (double)(SimClock::Frequency / pixelClock * (bpp / 8)) / 1024 / 1024); |
363} 364 365void 366HDLcd::startFrame() 367{ 368 // 0. Check that we are in the appropriate state 369 assert(!frameUnderway); 370 if (!command.enable) 371 return; 372 DPRINTF(HDLcd, "Frame read started\n"); 373 if (doUpdateParams) { 374 updateVideoParams(); 375 doUpdateParams = false; 376 } 377 frameUnderway = true; |
378 assert(!virtualDisplayBuffer.empty()); |
379 assert(pixelBufferSize == 0); 380 assert(dmaBytesInFlight == 0); 381 assert(dmaPendingNum == 0); 382 assert(dmaDoneEventFree.size() == dmaDoneEventAll.size()); 383 assert(!renderPixelEvent.scheduled()); 384 // currently only support positive line pitches equal to the line length 385 assert(width() * bytesPerPixel() == fb_line_pitch); 386 --- 43 unchanged lines hidden (view full) --- 430 dmaDoneEventFree.pop_back(); 431 assert(event); 432 assert(!event->scheduled()); 433 434 // We use a uncachable request here because the requests from the CPU 435 // will be uncacheable as well. If we have uncacheable and cacheable 436 // requests in the memory system for the same address it won't be 437 // pleased |
438 uint8_t *const dma_dst( 439 virtualDisplayBuffer.data() + dmaCurAddr - dmaStartAddr); |
440 event->setTransactionSize(transaction_size); 441 dmaPort.dmaAction(MemCmd::ReadReq, dmaCurAddr, transaction_size, event, |
442 dma_dst, 0, Request::UNCACHEABLE); |
443 dmaCurAddr += transaction_size; 444 dmaBytesInFlight += transaction_size; 445 } 446} 447 448void 449HDLcd::renderPixel() 450{ --- 45 unchanged lines hidden (view full) --- 496 } 497 } else { 498 nextEventTick += pixelClock * count; 499 } 500 501 schedule(renderPixelEvent, nextEventTick); 502} 503 |
504PixelConverter 505HDLcd::pixelConverter() const 506{ 507 return PixelConverter( 508 bytesPerPixel(), 509 red_select.offset, green_select.offset, blue_select.offset, 510 red_select.size, green_select.size, blue_select.size, 511 pixel_format.big_endian ? BigEndianByteOrder : LittleEndianByteOrder); 512} 513 |
514void 515HDLcd::endFrame() { 516 assert(pixelBufferSize == 0); 517 assert(dmaPendingNum == 0); 518 assert(dmaBytesInFlight == 0); 519 assert(dmaDoneEventFree.size() == dmaDoneEventAll.size()); 520 |
521 fb.copyIn(virtualDisplayBuffer, pixelConverter()); 522 |
523 if (vnc) 524 vnc->setDirty(); 525 526 if (enableCapture) { 527 if (!pic) 528 pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true); 529 |
530 assert(pic); 531 pic->seekp(0); |
532 bmp.write(*pic); |
533 } 534 535 // start the next frame 536 frameUnderway = false; 537 startFrame(); 538} 539 540void --- 81 unchanged lines hidden (view full) --- 622 623 SERIALIZE_SCALAR(frameReadStartTime); 624 SERIALIZE_SCALAR(dmaStartAddr); 625 SERIALIZE_SCALAR(dmaCurAddr); 626 SERIALIZE_SCALAR(dmaMaxAddr); 627 SERIALIZE_SCALAR(dmaPendingNum); 628 SERIALIZE_SCALAR(frameUnderrun); 629 |
630 arrayParamOut(os, "virtualDisplayBuffer", virtualDisplayBuffer); |
631 632 SERIALIZE_SCALAR(pixelBufferSize); 633 SERIALIZE_SCALAR(pixelIndex); 634 SERIALIZE_SCALAR(doUpdateParams); 635 SERIALIZE_SCALAR(frameUnderway); 636 SERIALIZE_SCALAR(dmaBytesInFlight); 637 638 Tick start_event_time = 0; --- 95 unchanged lines hidden (view full) --- 734 UNSERIALIZE_SCALAR(frameReadStartTime); 735 UNSERIALIZE_SCALAR(dmaStartAddr); 736 UNSERIALIZE_SCALAR(dmaCurAddr); 737 UNSERIALIZE_SCALAR(dmaMaxAddr); 738 UNSERIALIZE_SCALAR(dmaPendingNum); 739 UNSERIALIZE_SCALAR(frameUnderrun); 740 UNSERIALIZE_SCALAR(dmaBytesInFlight); 741 |
742 arrayParamIn(cp, section, "virtualDisplayBuffer", virtualDisplayBuffer); |
743 744 UNSERIALIZE_SCALAR(pixelBufferSize); 745 UNSERIALIZE_SCALAR(pixelIndex); 746 UNSERIALIZE_SCALAR(doUpdateParams); 747 UNSERIALIZE_SCALAR(frameUnderway); 748 749 Tick start_event_time = 0; 750 Tick end_event_time = 0; --- 27 unchanged lines hidden (view full) --- 778 schedule(dmaDoneEventAll[x], dma_done_event_tick[x]); 779 } else 780 dmaDoneEventFree.push_back(&dmaDoneEventAll[x]); 781 } 782 assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY - dmaDoneEventFree.size() == dmaPendingNum); 783 784 if (frameUnderway) { 785 updateVideoParams(true); |
786 fb.resize(width(), height()); 787 fb.copyIn(virtualDisplayBuffer, pixelConverter()); |
788 if (vnc) 789 vnc->setDirty(); 790 } 791} 792 793void 794HDLcd::generateInterrupt() 795{ --- 24 unchanged lines hidden --- |