2 * Copyright (c) 2010-2013, 2015 ARM Limited
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
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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.
37 * Authors: Chris Emmons
40 #include "dev/arm/hdlcd.hh"
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"
56 // initialize hdlcd registers
57 HDLcd::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),
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
)
81 for (int i
= 0; i
< MAX_OUTSTANDING_DMA_REQ_CAPACITY
; ++i
)
82 dmaDoneEventFree
[i
] = &dmaDoneEventAll
[i
];
85 vnc
->setFrameBuffer(&fb
);
92 // read registers and frame buffer
94 HDLcd::read(PacketPtr pkt
)
97 const Addr daddr
= pkt
->getAddr() - pioAddr
;
99 DPRINTF(HDLcd
, "read register BASE+0x%04x size=%d\n", daddr
,
102 assert(pkt
->getAddr() >= pioAddr
&&
103 pkt
->getAddr() < pioAddr
+ pioSize
&&
104 pkt
->getSize() == 4);
114 panic("HDLCD INT_CLEAR register is Write-Only\n");
126 data
= fb_line_length
;
129 data
= fb_line_count
;
132 data
= fb_line_pitch
;
147 data
= v_front_porch
;
159 data
= h_front_porch
;
180 panic("Tried to read HDLCD register that doesn't exist\n", daddr
);
184 pkt
->set
<uint32_t>(data
);
185 pkt
->makeAtomicResponse();
189 // write registers and frame buffer
191 HDLcd::write(PacketPtr pkt
)
193 assert(pkt
->getAddr() >= pioAddr
&&
194 pkt
->getAddr() < pioAddr
+ pioSize
&&
195 pkt
->getSize() == 4);
197 const uint32_t data
= pkt
->get
<uint32_t>();
198 const Addr daddr
= pkt
->getAddr() - pioAddr
;
200 DPRINTF(HDLcd
, "write register BASE+%0x04x <= 0x%08x\n", daddr
,
201 pkt
->get
<uint32_t>());
205 panic("HDLCD VERSION register is read-Only\n");
217 panic("HDLCD INT_STATUS register is read-Only\n");
221 DPRINTF(HDLcd
, "HDLCD Frame Buffer located at addr 0x%08x\n", fb_base
);
224 fb_line_length
= data
;
225 DPRINTF(HDLcd
, "HDLCD res = %d x %d\n", width(), height());
228 fb_line_count
= data
;
229 DPRINTF(HDLcd
, "HDLCD res = %d x %d\n", width(), height());
232 fb_line_pitch
= data
;
235 BusOptsReg old_bus_options
;
236 old_bus_options
= bus_options
;
238 if (bus_options
.max_outstanding
!= old_bus_options
.max_outstanding
)
240 "Changing HDLcd outstanding dma transactions from %d to %d\n",
241 old_bus_options
.max_outstanding
, bus_options
.max_outstanding
);
242 if (bus_options
.burst_len
!= old_bus_options
.burst_len
)
244 "Changing HDLcd dma burst length from %d bytes to %d bytes\n",
245 old_bus_options
.burst_len
, bus_options
.burst_len
); }
257 v_front_porch
= data
;
269 h_front_porch
= data
;
275 CommandReg new_command
;
277 if (new_command
.enable
!= command
.enable
) {
278 DPRINTF(HDLcd
, "HDLCD switched %s\n",
279 new_command
.enable
==0 ? "off" : "on");
280 if (new_command
.enable
) {
281 doUpdateParams
= true;
282 if (!frameUnderway
) {
283 schedule(startFrameEvent
, clockEdge());
287 command
= new_command
; }
291 DPRINTF(HDLcd
, "HDLCD res = %d x %d\n", width(), height());
292 DPRINTF(HDLcd
, "HDLCD bytes per pixel = %d\n", bytesPerPixel());
293 DPRINTF(HDLcd
, "HDLCD endianness = %s\n",
294 pixel_format
.big_endian
? "big" : "little");
306 panic("Tried to write HDLCD register that doesn't exist\n", daddr
);
310 pkt
->makeAtomicResponse();
315 HDLcd::updateVideoParams(bool unserializing
= false)
317 const uint16_t bpp M5_VAR_USED
= bytesPerPixel() << 3;
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
);
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");
331 // resize the virtualDisplayBuffer unless we are unserializing - it may
333 // there must be no outstanding DMA transactions for this to work
334 if (!unserializing
) {
335 assert(dmaPendingNum
== 0);
337 virtualDisplayBuffer
.resize(bytesPerPixel() * area());
338 fb
.resize(width(), height());
341 std::fill(virtualDisplayBuffer
.begin(), virtualDisplayBuffer
.end(),
345 DPRINTF(HDLcd
, "bpp = %d\n", bpp
);
346 DPRINTF(HDLcd
, "display size = %d x %d\n", width(), height());
348 const size_t totalLinesPerFrame
= v_back_porch
.val
+ 1 +
350 v_front_porch
.val
+ 1 +
352 const double fps
= (double)SimClock::Frequency
/
353 (double)(PClksPerLine() * totalLinesPerFrame
* pixelClock
);
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",
358 fps
* virtualDisplayBuffer
.size() / 1024 / 1024,
359 (double)SimClock::Frequency
/ pixelClock
/ 1000000.0,
362 (double)(SimClock::Frequency
/ pixelClock
* (bpp
/ 8)) / 1024 / 1024);
368 // 0. Check that we are in the appropriate state
369 assert(!frameUnderway
);
372 DPRINTF(HDLcd
, "Frame read started\n");
373 if (doUpdateParams
) {
375 doUpdateParams
= false;
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
);
387 // 1. Start DMA'ing the frame; subsequent transactions created as we go
388 dmaCurAddr
= dmaStartAddr
= fb_base
;
389 dmaMaxAddr
= static_cast<Addr
>(width() * height() * bytesPerPixel()) +
391 frameReadStartTime
= curTick();
393 frameUnderrun
= false;
396 // 2. Schedule first pixelclock read; subsequent reads generated as we go
397 Tick firstPixelReadTick
= curTick() + pixelClock
* (
398 PClksPerLine() * (v_sync
.val
+ 1 +
399 v_back_porch
.val
+ 1) +
401 h_back_porch
.val
+ 1);
402 schedule(renderPixelEvent
, firstPixelReadTick
);
406 HDLcd::fillPixelBuffer()
408 // - am I under the LCD dma transaction total?
409 // - do I have more data to transfer?
410 // - have I not yet underrun for this frame?
411 // - is there room to put the data in the pixel buffer including any
412 // outstanding dma transfers in flight?
413 while ((dmaPendingNum
< maxOutstandingDma()) &&
414 (dmaMaxAddr
> dmaCurAddr
) &&
416 bytesFreeInPixelBuffer() > dmaBurstLength() * AXI_PORT_WIDTH
) {
417 // try largest transaction size allowed first but switch to smaller
418 // sizes for trailing bytes
419 size_t transaction_size
= dmaBurstLength() * AXI_PORT_WIDTH
;
420 while (transaction_size
> (dmaMaxAddr
- dmaCurAddr
))
421 transaction_size
>>= 1;
422 assert(transaction_size
> 0);
424 // concurrent dma reads need different dma done events
425 // due to assertion in scheduling state
428 assert(!dmaDoneEventFree
.empty());
429 DmaDoneEvent
*event(dmaDoneEventFree
.back());
430 dmaDoneEventFree
.pop_back();
432 assert(!event
->scheduled());
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
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
;
451 // try to handle multiple pixels at a time; doing so reduces the accuracy
452 // of the underrun detection but lowers simulation overhead
453 const size_t count
= 32;
454 assert(width() % count
== 0); // not set up to handle trailing pixels
456 // have we underrun on this frame anytime before?
458 // the LCD controller gives up on a frame if an underrun occurs and
459 // resumes regular operation on the next frame
462 // did we underrun on this set of pixels?
463 if (pixelBufferSize
< bytesPerPixel() * count
) {
464 warn("HDLcd controller buffer underrun\n");
465 frameUnderrun
= true;
466 int_rawstat
.underrun
= 1;
467 if (!intEvent
.scheduled())
468 schedule(intEvent
, clockEdge());
470 // emulate the pixel read from the internal buffer
471 pixelBufferSize
-= bytesPerPixel() * count
;
475 // the DMA may have previously stalled due to the buffer being full;
476 // give it a kick; it knows not to fill if at end of frame, underrun, etc
477 if (!fillPixelBufferEvent
.scheduled())
478 schedule(fillPixelBufferEvent
, clockEdge());
480 // schedule the next pixel read according to where it is in the frame
482 assert(pixelIndex
<= width() * height());
483 size_t x
= pixelIndex
% width();
484 Tick nextEventTick
= curTick();
487 nextEventTick
+= pixelClock
* ((h_front_porch
.val
+ 1) +
488 (h_back_porch
.val
+ 1) +
490 if (pixelIndex
== width() * height()) {
492 nextEventTick
+= PClksPerLine() * (v_front_porch
.val
+ 1) *
494 schedule(endFrameEvent
, nextEventTick
);
498 nextEventTick
+= pixelClock
* count
;
501 schedule(renderPixelEvent
, nextEventTick
);
505 HDLcd::pixelConverter() const
507 return PixelConverter(
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
);
516 assert(pixelBufferSize
== 0);
517 assert(dmaPendingNum
== 0);
518 assert(dmaBytesInFlight
== 0);
519 assert(dmaDoneEventFree
.size() == dmaDoneEventAll
.size());
521 fb
.copyIn(virtualDisplayBuffer
, pixelConverter());
528 pic
= simout
.create(csprintf("%s.framebuffer.bmp", sys
->name()), true);
535 // start the next frame
536 frameUnderway
= false;
541 HDLcd::dmaDone(DmaDoneEvent
*event
)
543 const size_t transactionLength
= event
->getTransactionSize();
544 assert(pixelBufferSize
+ transactionLength
< PIXEL_BUFFER_CAPACITY
);
545 assert(dmaCurAddr
<= dmaMaxAddr
);
547 dmaDoneEventFree
.push_back(event
);
549 assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY
- dmaDoneEventFree
.size() ==
552 // add the data to the pixel buffer
553 dmaBytesInFlight
-= transactionLength
;
554 pixelBufferSize
+= transactionLength
;
556 // schedule another dma transaction if:
557 // - we're not done reading the frame
558 // - there is sufficient room in the pixel buffer for another transaction
559 // - another fillPixelBufferEvent is not already scheduled
560 const size_t targetTransSize
= dmaBurstLength() * AXI_PORT_WIDTH
;
561 if ((dmaCurAddr
< dmaMaxAddr
) &&
562 (bytesFreeInPixelBuffer() + targetTransSize
< PIXEL_BUFFER_CAPACITY
) &&
563 !fillPixelBufferEvent
.scheduled()) {
564 schedule(fillPixelBufferEvent
, clockEdge());
569 HDLcd::serialize(std::ostream
&os
)
571 DPRINTF(HDLcd
, "Serializing ARM HDLCD\n");
573 const uint32_t version_serial
= version
;
574 SERIALIZE_SCALAR(version_serial
);
575 const uint32_t int_rawstat_serial
= int_rawstat
;
576 SERIALIZE_SCALAR(int_rawstat_serial
);
577 const uint32_t int_clear_serial
= int_clear
;
578 SERIALIZE_SCALAR(int_clear_serial
);
579 const uint32_t int_mask_serial
= int_mask
;
580 SERIALIZE_SCALAR(int_mask_serial
);
581 const uint32_t int_status_serial
= int_status
;
582 SERIALIZE_SCALAR(int_status_serial
);
584 SERIALIZE_SCALAR(fb_base
);
585 SERIALIZE_SCALAR(fb_line_length
);
587 const uint32_t fb_line_count_serial
= fb_line_count
;
588 SERIALIZE_SCALAR(fb_line_count_serial
);
590 SERIALIZE_SCALAR(fb_line_pitch
);
592 const uint32_t bus_options_serial
= bus_options
;
593 SERIALIZE_SCALAR(bus_options_serial
);
594 const uint32_t v_sync_serial
= v_sync
;
595 SERIALIZE_SCALAR(v_sync_serial
);
596 const uint32_t v_back_porch_serial
= v_back_porch
;
597 SERIALIZE_SCALAR(v_back_porch_serial
);
598 const uint32_t v_data_serial
= v_data
;
599 SERIALIZE_SCALAR(v_data_serial
);
600 const uint32_t v_front_porch_serial
= v_front_porch
;
601 SERIALIZE_SCALAR(v_front_porch_serial
);
602 const uint32_t h_sync_serial
= h_sync
;
603 SERIALIZE_SCALAR(h_sync_serial
);
604 const uint32_t h_back_porch_serial
= h_back_porch
;
605 SERIALIZE_SCALAR(h_back_porch_serial
);
606 const uint32_t h_data_serial
= h_data
;
607 SERIALIZE_SCALAR(h_data_serial
);
608 const uint32_t h_front_porch_serial
= h_front_porch
;
609 SERIALIZE_SCALAR(h_front_porch_serial
);
610 const uint32_t polarities_serial
= polarities
;
611 SERIALIZE_SCALAR(polarities_serial
);
612 const uint32_t command_serial
= command
;
613 SERIALIZE_SCALAR(command_serial
);
614 const uint32_t pixel_format_serial
= pixel_format
;
615 SERIALIZE_SCALAR(pixel_format_serial
);
616 const uint32_t red_select_serial
= red_select
;
617 SERIALIZE_SCALAR(red_select_serial
);
618 const uint32_t green_select_serial
= green_select
;
619 SERIALIZE_SCALAR(green_select_serial
);
620 const uint32_t blue_select_serial
= blue_select
;
621 SERIALIZE_SCALAR(blue_select_serial
);
623 SERIALIZE_SCALAR(frameReadStartTime
);
624 SERIALIZE_SCALAR(dmaStartAddr
);
625 SERIALIZE_SCALAR(dmaCurAddr
);
626 SERIALIZE_SCALAR(dmaMaxAddr
);
627 SERIALIZE_SCALAR(dmaPendingNum
);
628 SERIALIZE_SCALAR(frameUnderrun
);
630 arrayParamOut(os
, "virtualDisplayBuffer", virtualDisplayBuffer
);
632 SERIALIZE_SCALAR(pixelBufferSize
);
633 SERIALIZE_SCALAR(pixelIndex
);
634 SERIALIZE_SCALAR(doUpdateParams
);
635 SERIALIZE_SCALAR(frameUnderway
);
636 SERIALIZE_SCALAR(dmaBytesInFlight
);
638 Tick start_event_time
= 0;
639 Tick end_event_time
= 0;
640 Tick render_pixel_event_time
= 0;
641 Tick fill_pixel_buffer_event_time
= 0;
642 Tick int_event_time
= 0;
643 if (startFrameEvent
.scheduled())
644 start_event_time
= startFrameEvent
.when();
645 if (endFrameEvent
.scheduled())
646 end_event_time
= endFrameEvent
.when();
647 if (renderPixelEvent
.scheduled())
648 render_pixel_event_time
= renderPixelEvent
.when();
649 if (fillPixelBufferEvent
.scheduled())
650 fill_pixel_buffer_event_time
= fillPixelBufferEvent
.when();
651 if (intEvent
.scheduled())
652 int_event_time
= intEvent
.when();
653 SERIALIZE_SCALAR(start_event_time
);
654 SERIALIZE_SCALAR(end_event_time
);
655 SERIALIZE_SCALAR(render_pixel_event_time
);
656 SERIALIZE_SCALAR(fill_pixel_buffer_event_time
);
657 SERIALIZE_SCALAR(int_event_time
);
659 vector
<Tick
> dma_done_event_tick(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
660 vector
<size_t> dma_done_event_burst_len(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
661 for (int x
= 0; x
< MAX_OUTSTANDING_DMA_REQ_CAPACITY
; ++x
) {
662 dma_done_event_tick
[x
] = dmaDoneEventAll
[x
].scheduled() ?
663 dmaDoneEventAll
[x
].when() : 0;
664 dma_done_event_burst_len
[x
] = dmaDoneEventAll
[x
].scheduled() ?
665 dmaDoneEventAll
[x
].getTransactionSize() : 0;
667 arrayParamOut(os
, "dma_done_event_tick", dma_done_event_tick
);
668 arrayParamOut(os
, "dma_done_event_burst_length", dma_done_event_burst_len
);
672 HDLcd::unserialize(Checkpoint
*cp
, const std::string
§ion
)
674 uint32_t version_serial
, int_rawstat_serial
, int_clear_serial
,
675 int_mask_serial
, int_status_serial
, fb_line_count_serial
,
676 bus_options_serial
, v_sync_serial
, v_back_porch_serial
,
677 v_data_serial
, v_front_porch_serial
, h_sync_serial
,
678 h_back_porch_serial
, h_data_serial
, h_front_porch_serial
,
679 polarities_serial
, command_serial
, pixel_format_serial
,
680 red_select_serial
, green_select_serial
, blue_select_serial
;
682 DPRINTF(HDLcd
, "Unserializing ARM HDLCD\n");
684 UNSERIALIZE_SCALAR(version_serial
);
685 version
= version_serial
;
686 UNSERIALIZE_SCALAR(int_rawstat_serial
);
687 int_rawstat
= int_rawstat_serial
;
688 UNSERIALIZE_SCALAR(int_clear_serial
);
689 int_clear
= int_clear_serial
;
690 UNSERIALIZE_SCALAR(int_mask_serial
);
691 int_mask
= int_mask_serial
;
692 UNSERIALIZE_SCALAR(int_status_serial
);
693 int_status
= int_status_serial
;
695 UNSERIALIZE_SCALAR(fb_base
);
696 UNSERIALIZE_SCALAR(fb_line_length
);
698 UNSERIALIZE_SCALAR(fb_line_count_serial
);
699 fb_line_count
= fb_line_count_serial
;
701 UNSERIALIZE_SCALAR(fb_line_pitch
);
703 UNSERIALIZE_SCALAR(bus_options_serial
);
704 bus_options
= bus_options_serial
;
705 UNSERIALIZE_SCALAR(v_sync_serial
);
706 v_sync
= v_sync_serial
;
707 UNSERIALIZE_SCALAR(v_back_porch_serial
);
708 v_back_porch
= v_back_porch_serial
;
709 UNSERIALIZE_SCALAR(v_data_serial
);
710 v_data
= v_data_serial
;
711 UNSERIALIZE_SCALAR(v_front_porch_serial
);
712 v_front_porch
= v_front_porch_serial
;
713 UNSERIALIZE_SCALAR(h_sync_serial
);
714 h_sync
= h_sync_serial
;
715 UNSERIALIZE_SCALAR(h_back_porch_serial
);
716 h_back_porch
= h_back_porch_serial
;
717 UNSERIALIZE_SCALAR(h_data_serial
);
718 h_data
= h_data_serial
;
719 UNSERIALIZE_SCALAR(h_front_porch_serial
);
720 h_front_porch
= h_front_porch_serial
;
721 UNSERIALIZE_SCALAR(polarities_serial
);
722 polarities
= polarities_serial
;
723 UNSERIALIZE_SCALAR(command_serial
);
724 command
= command_serial
;
725 UNSERIALIZE_SCALAR(pixel_format_serial
);
726 pixel_format
= pixel_format_serial
;
727 UNSERIALIZE_SCALAR(red_select_serial
);
728 red_select
= red_select_serial
;
729 UNSERIALIZE_SCALAR(green_select_serial
);
730 green_select
= green_select_serial
;
731 UNSERIALIZE_SCALAR(blue_select_serial
);
732 blue_select
= blue_select_serial
;
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
);
742 arrayParamIn(cp
, section
, "virtualDisplayBuffer", virtualDisplayBuffer
);
744 UNSERIALIZE_SCALAR(pixelBufferSize
);
745 UNSERIALIZE_SCALAR(pixelIndex
);
746 UNSERIALIZE_SCALAR(doUpdateParams
);
747 UNSERIALIZE_SCALAR(frameUnderway
);
749 Tick start_event_time
= 0;
750 Tick end_event_time
= 0;
751 Tick render_pixel_event_time
= 0;
752 Tick fill_pixel_buffer_event_time
= 0;
753 Tick int_event_time
= 0;
754 UNSERIALIZE_SCALAR(start_event_time
);
755 UNSERIALIZE_SCALAR(end_event_time
);
756 UNSERIALIZE_SCALAR(render_pixel_event_time
);
757 UNSERIALIZE_SCALAR(fill_pixel_buffer_event_time
);
758 UNSERIALIZE_SCALAR(int_event_time
);
759 if (start_event_time
)
760 schedule(startFrameEvent
, start_event_time
);
762 schedule(endFrameEvent
, end_event_time
);
763 if (render_pixel_event_time
)
764 schedule(renderPixelEvent
, render_pixel_event_time
);
765 if (fill_pixel_buffer_event_time
)
766 schedule(fillPixelBufferEvent
, fill_pixel_buffer_event_time
);
768 schedule(intEvent
, int_event_time
);
770 vector
<Tick
> dma_done_event_tick(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
771 vector
<Tick
> dma_done_event_burst_len(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
772 arrayParamIn(cp
, section
, "dma_done_event_tick", dma_done_event_tick
);
773 arrayParamIn(cp
, section
, "dma_done_event_burst_length", dma_done_event_burst_len
);
774 dmaDoneEventFree
.clear();
775 for (int x
= 0; x
< MAX_OUTSTANDING_DMA_REQ_CAPACITY
; ++x
) {
776 if (dma_done_event_tick
[x
]) {
777 dmaDoneEventAll
[x
].setTransactionSize(dma_done_event_burst_len
[x
]);
778 schedule(dmaDoneEventAll
[x
], dma_done_event_tick
[x
]);
780 dmaDoneEventFree
.push_back(&dmaDoneEventAll
[x
]);
782 assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY
- dmaDoneEventFree
.size() == dmaPendingNum
);
785 updateVideoParams(true);
786 fb
.resize(width(), height());
787 fb
.copyIn(virtualDisplayBuffer
, pixelConverter());
794 HDLcd::generateInterrupt()
796 int_status
= int_rawstat
& int_mask
;
797 DPRINTF(HDLcd
, "Generate Interrupt: int_rawstat=0x%08x int_mask=0x%08x "
798 "int_status=0x%08x\n",
799 (uint32_t)int_rawstat
, (uint32_t)int_mask
, (uint32_t)int_status
);
801 if (int_status
!= 0) {
802 gic
->sendInt(intNum
);
803 DPRINTF(HDLcd
, " -- Generated\n");
808 HDLcd::getAddrRanges() const
810 AddrRangeList ranges
;
811 ranges
.push_back(RangeSize(pioAddr
, pioSize
));
816 HDLcdParams::create()
818 return new HDLcd(this);