2 * Copyright (c) 2010-2013 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 "base/vnc/vncinput.hh"
41 #include "base/bitmap.hh"
42 #include "base/output.hh"
43 #include "base/trace.hh"
44 #include "debug/HDLcd.hh"
45 #include "debug/Uart.hh"
46 #include "dev/arm/amba_device.hh"
47 #include "dev/arm/base_gic.hh"
48 #include "dev/arm/hdlcd.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
), vnc(p
->vnc
), bmp(NULL
), pic(NULL
),
67 frameReadStartTime(0),
68 dmaStartAddr(0), dmaCurAddr(0), dmaMaxAddr(0), dmaPendingNum(0),
69 frameUnderrun(false), virtualDisplayBuffer(NULL
), pixelBufferSize(0),
70 pixelIndex(0), doUpdateParams(false), frameUnderway(false),
72 startFrameEvent(this), endFrameEvent(this), renderPixelEvent(this),
73 fillPixelBufferEvent(this), intEvent(this),
74 dmaDoneEventAll(MAX_OUTSTANDING_DMA_REQ_CAPACITY
, this),
75 dmaDoneEventFree(MAX_OUTSTANDING_DMA_REQ_CAPACITY
),
76 enableCapture(p
->enable_capture
)
80 for (int i
= 0; i
< MAX_OUTSTANDING_DMA_REQ_CAPACITY
; ++i
)
81 dmaDoneEventFree
[i
] = &dmaDoneEventAll
[i
];
84 vnc
->setFramebufferAddr(NULL
);
89 if (virtualDisplayBuffer
)
90 delete [] virtualDisplayBuffer
;
93 // read registers and frame buffer
95 HDLcd::read(PacketPtr pkt
)
98 const Addr daddr
= pkt
->getAddr() - pioAddr
;
100 DPRINTF(HDLcd
, "read register BASE+0x%04x size=%d\n", daddr
,
103 assert(pkt
->getAddr() >= pioAddr
&&
104 pkt
->getAddr() < pioAddr
+ pioSize
&&
105 pkt
->getSize() == 4);
115 panic("HDLCD INT_CLEAR register is Write-Only\n");
127 data
= fb_line_length
;
130 data
= fb_line_count
;
133 data
= fb_line_pitch
;
148 data
= v_front_porch
;
160 data
= h_front_porch
;
181 panic("Tried to read HDLCD register that doesn't exist\n", daddr
);
185 pkt
->set
<uint32_t>(data
);
186 pkt
->makeAtomicResponse();
190 // write registers and frame buffer
192 HDLcd::write(PacketPtr pkt
)
194 assert(pkt
->getAddr() >= pioAddr
&&
195 pkt
->getAddr() < pioAddr
+ pioSize
&&
196 pkt
->getSize() == 4);
198 const uint32_t data
= pkt
->get
<uint32_t>();
199 const Addr daddr
= pkt
->getAddr() - pioAddr
;
201 DPRINTF(HDLcd
, "write register BASE+%0x04x <= 0x%08x\n", daddr
,
202 pkt
->get
<uint32_t>());
206 panic("HDLCD VERSION register is read-Only\n");
218 panic("HDLCD INT_STATUS register is read-Only\n");
222 DPRINTF(HDLcd
, "HDLCD Frame Buffer located at addr 0x%08x\n", fb_base
);
225 fb_line_length
= data
;
226 DPRINTF(HDLcd
, "HDLCD res = %d x %d\n", width(), height());
229 fb_line_count
= data
;
230 DPRINTF(HDLcd
, "HDLCD res = %d x %d\n", width(), height());
233 fb_line_pitch
= data
;
236 BusOptsReg old_bus_options
;
237 old_bus_options
= bus_options
;
239 if (bus_options
.max_outstanding
!= old_bus_options
.max_outstanding
)
241 "Changing HDLcd outstanding dma transactions from %d to %d\n",
242 old_bus_options
.max_outstanding
, bus_options
.max_outstanding
);
243 if (bus_options
.burst_len
!= old_bus_options
.burst_len
)
245 "Changing HDLcd dma burst length from %d bytes to %d bytes\n",
246 old_bus_options
.burst_len
, bus_options
.burst_len
); }
258 v_front_porch
= data
;
270 h_front_porch
= data
;
276 CommandReg new_command
;
278 if (new_command
.enable
!= command
.enable
) {
279 DPRINTF(HDLcd
, "HDLCD switched %s\n",
280 new_command
.enable
==0 ? "off" : "on");
281 if (new_command
.enable
) {
282 doUpdateParams
= true;
283 if (!frameUnderway
) {
284 schedule(startFrameEvent
, clockEdge());
288 command
= new_command
; }
292 DPRINTF(HDLcd
, "HDLCD res = %d x %d\n", width(), height());
293 DPRINTF(HDLcd
, "HDLCD bytes per pixel = %d\n", bytesPerPixel());
294 DPRINTF(HDLcd
, "HDLCD endianness = %s\n",
295 pixel_format
.big_endian
? "big" : "little");
307 panic("Tried to write HDLCD register that doesn't exist\n", daddr
);
311 pkt
->makeAtomicResponse();
316 HDLcd::updateVideoParams(bool unserializing
= false)
318 const uint16_t bpp
= bytesPerPixel() << 3;
319 const size_t buffer_size
= bytesPerPixel() * width() * height();
321 // updating these parameters while LCD is enabled is not supported
322 if (frameUnderway
&& !unserializing
)
323 panic("Attempting to change some HDLCD parameters while the controller"
324 " is active is not allowed");
326 // resize the virtualDisplayBuffer unless we are unserializing - it may
328 // there must be no outstanding DMA transactions for this to work
329 if (!unserializing
) {
330 assert(dmaPendingNum
== 0);
331 if (virtualDisplayBuffer
)
332 delete [] virtualDisplayBuffer
;
333 virtualDisplayBuffer
= new uint8_t[buffer_size
];
334 memset(virtualDisplayBuffer
, 0, buffer_size
);
337 assert(virtualDisplayBuffer
);
339 vnc
->setFramebufferAddr(virtualDisplayBuffer
);
344 DPRINTF(HDLcd
, "bpp = %d\n", bpp
);
345 DPRINTF(HDLcd
, "display size = %d x %d\n", width(), height());
347 const size_t totalLinesPerFrame
= v_back_porch
.val
+ 1 +
349 v_front_porch
.val
+ 1 +
351 const double fps
= (double)SimClock::Frequency
/
352 (double)(PClksPerLine() * totalLinesPerFrame
* pixelClock
);
354 DPRINTF(HDLcd
, "simulated refresh rate ~ %.1ffps generating ~ %.1fMB/s "
355 "traffic ([%.1fMHz, T=%d sim clocks] pclk, %d bpp => %.1fMB/s peak requirement)\n",
357 fps
* buffer_size
/ 1024 / 1024,
358 (double)SimClock::Frequency
/ pixelClock
/ 1000000.0,
361 (double)(SimClock::Frequency
/ pixelClock
* (bpp
/ 8)) / 1024 / 1024);
363 if (pixel_format
.big_endian
)
364 panic("Big Endian pixel format not implemented by HDLcd controller");
368 (red_select
.size
== 8) &&
369 (blue_select
.size
== 8) &&
370 (green_select
.size
== 8) &&
371 (green_select
.offset
== 8)) {
372 if ((blue_select
.offset
== 0) &&
373 (red_select
.offset
== 16)) {
374 vnc
->setFrameBufferParams(VideoConvert::rgb8888
, width(),
376 bmp
= new Bitmap(VideoConvert::rgb8888
, width(), height(),
377 virtualDisplayBuffer
);
378 DPRINTF(HDLcd
, "color mode: rgb888\n");
379 } else if ((red_select
.offset
== 0) &&
380 (blue_select
.offset
== 16)) {
381 vnc
->setFrameBufferParams(VideoConvert::bgr8888
, width(),
383 bmp
= new Bitmap(VideoConvert::bgr8888
, width(), height(),
384 virtualDisplayBuffer
);
385 DPRINTF(HDLcd
, "color mode: bgr888\n");
387 } else if ((bpp
== 16) &&
388 (red_select
.size
== 5) &&
389 (blue_select
.size
== 5) &&
390 (green_select
.size
== 6) &&
391 (green_select
.offset
== 5)) {
392 if ((blue_select
.offset
== 0) &&
393 (red_select
.offset
== 11)) {
394 vnc
->setFrameBufferParams(VideoConvert::rgb565
, width(),
396 bmp
= new Bitmap(VideoConvert::rgb565
, width(), height(),
397 virtualDisplayBuffer
);
398 DPRINTF(HDLcd
, "color mode: rgb565\n");
399 } else if ((red_select
.offset
== 0) &&
400 (blue_select
.offset
== 11)) {
401 vnc
->setFrameBufferParams(VideoConvert::bgr565
, width(),
403 bmp
= new Bitmap(VideoConvert::bgr565
, width(), height(),
404 virtualDisplayBuffer
);
405 DPRINTF(HDLcd
, "color mode: bgr565\n");
408 DPRINTF(HDLcd
, "color mode: undefined\n");
409 panic("Unimplemented video mode\n");
417 // 0. Check that we are in the appropriate state
418 assert(!frameUnderway
);
421 DPRINTF(HDLcd
, "Frame read started\n");
422 if (doUpdateParams
) {
424 doUpdateParams
= false;
426 frameUnderway
= true;
427 assert(virtualDisplayBuffer
);
428 assert(pixelBufferSize
== 0);
429 assert(dmaBytesInFlight
== 0);
430 assert(dmaPendingNum
== 0);
431 assert(dmaDoneEventFree
.size() == dmaDoneEventAll
.size());
432 assert(!renderPixelEvent
.scheduled());
433 // currently only support positive line pitches equal to the line length
434 assert(width() * bytesPerPixel() == fb_line_pitch
);
436 // 1. Start DMA'ing the frame; subsequent transactions created as we go
437 dmaCurAddr
= dmaStartAddr
= fb_base
;
438 dmaMaxAddr
= static_cast<Addr
>(width() * height() * bytesPerPixel()) +
440 frameReadStartTime
= curTick();
442 frameUnderrun
= false;
445 // 2. Schedule first pixelclock read; subsequent reads generated as we go
446 Tick firstPixelReadTick
= curTick() + pixelClock
* (
447 PClksPerLine() * (v_sync
.val
+ 1 +
448 v_back_porch
.val
+ 1) +
450 h_back_porch
.val
+ 1);
451 schedule(renderPixelEvent
, firstPixelReadTick
);
455 HDLcd::fillPixelBuffer()
457 // - am I under the LCD dma transaction total?
458 // - do I have more data to transfer?
459 // - have I not yet underrun for this frame?
460 // - is there room to put the data in the pixel buffer including any
461 // outstanding dma transfers in flight?
462 while ((dmaPendingNum
< maxOutstandingDma()) &&
463 (dmaMaxAddr
> dmaCurAddr
) &&
465 bytesFreeInPixelBuffer() > dmaBurstLength() * AXI_PORT_WIDTH
) {
466 // try largest transaction size allowed first but switch to smaller
467 // sizes for trailing bytes
468 size_t transaction_size
= dmaBurstLength() * AXI_PORT_WIDTH
;
469 while (transaction_size
> (dmaMaxAddr
- dmaCurAddr
))
470 transaction_size
>>= 1;
471 assert(transaction_size
> 0);
473 // concurrent dma reads need different dma done events
474 // due to assertion in scheduling state
477 assert(!dmaDoneEventFree
.empty());
478 DmaDoneEvent
*event(dmaDoneEventFree
.back());
479 dmaDoneEventFree
.pop_back();
481 assert(!event
->scheduled());
483 // We use a uncachable request here because the requests from the CPU
484 // will be uncacheable as well. If we have uncacheable and cacheable
485 // requests in the memory system for the same address it won't be
487 event
->setTransactionSize(transaction_size
);
488 dmaPort
.dmaAction(MemCmd::ReadReq
, dmaCurAddr
, transaction_size
, event
,
489 virtualDisplayBuffer
+ dmaCurAddr
- dmaStartAddr
,
490 0, Request::UNCACHEABLE
);
491 dmaCurAddr
+= transaction_size
;
492 dmaBytesInFlight
+= transaction_size
;
499 // try to handle multiple pixels at a time; doing so reduces the accuracy
500 // of the underrun detection but lowers simulation overhead
501 const size_t count
= 32;
502 assert(width() % count
== 0); // not set up to handle trailing pixels
504 // have we underrun on this frame anytime before?
506 // the LCD controller gives up on a frame if an underrun occurs and
507 // resumes regular operation on the next frame
510 // did we underrun on this set of pixels?
511 if (pixelBufferSize
< bytesPerPixel() * count
) {
512 warn("HDLcd controller buffer underrun\n");
513 frameUnderrun
= true;
514 int_rawstat
.underrun
= 1;
515 if (!intEvent
.scheduled())
516 schedule(intEvent
, clockEdge());
518 // emulate the pixel read from the internal buffer
519 pixelBufferSize
-= bytesPerPixel() * count
;
523 // the DMA may have previously stalled due to the buffer being full;
524 // give it a kick; it knows not to fill if at end of frame, underrun, etc
525 if (!fillPixelBufferEvent
.scheduled())
526 schedule(fillPixelBufferEvent
, clockEdge());
528 // schedule the next pixel read according to where it is in the frame
530 assert(pixelIndex
<= width() * height());
531 size_t x
= pixelIndex
% width();
532 Tick nextEventTick
= curTick();
535 nextEventTick
+= pixelClock
* ((h_front_porch
.val
+ 1) +
536 (h_back_porch
.val
+ 1) +
538 if (pixelIndex
== width() * height()) {
540 nextEventTick
+= PClksPerLine() * (v_front_porch
.val
+ 1) *
542 schedule(endFrameEvent
, nextEventTick
);
546 nextEventTick
+= pixelClock
* count
;
549 schedule(renderPixelEvent
, nextEventTick
);
554 assert(pixelBufferSize
== 0);
555 assert(dmaPendingNum
== 0);
556 assert(dmaBytesInFlight
== 0);
557 assert(dmaDoneEventFree
.size() == dmaDoneEventAll
.size());
564 pic
= simout
.create(csprintf("%s.framebuffer.bmp", sys
->name()), true);
572 // start the next frame
573 frameUnderway
= false;
578 HDLcd::dmaDone(DmaDoneEvent
*event
)
580 const size_t transactionLength
= event
->getTransactionSize();
581 assert(pixelBufferSize
+ transactionLength
< PIXEL_BUFFER_CAPACITY
);
582 assert(dmaCurAddr
<= dmaMaxAddr
);
584 dmaDoneEventFree
.push_back(event
);
586 assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY
- dmaDoneEventFree
.size() ==
589 // add the data to the pixel buffer
590 dmaBytesInFlight
-= transactionLength
;
591 pixelBufferSize
+= transactionLength
;
593 // schedule another dma transaction if:
594 // - we're not done reading the frame
595 // - there is sufficient room in the pixel buffer for another transaction
596 // - another fillPixelBufferEvent is not already scheduled
597 const size_t targetTransSize
= dmaBurstLength() * AXI_PORT_WIDTH
;
598 if ((dmaCurAddr
< dmaMaxAddr
) &&
599 (bytesFreeInPixelBuffer() + targetTransSize
< PIXEL_BUFFER_CAPACITY
) &&
600 !fillPixelBufferEvent
.scheduled()) {
601 schedule(fillPixelBufferEvent
, clockEdge());
606 HDLcd::serialize(std::ostream
&os
)
608 DPRINTF(HDLcd
, "Serializing ARM HDLCD\n");
610 const uint32_t version_serial
= version
;
611 SERIALIZE_SCALAR(version_serial
);
612 const uint32_t int_rawstat_serial
= int_rawstat
;
613 SERIALIZE_SCALAR(int_rawstat_serial
);
614 const uint32_t int_clear_serial
= int_clear
;
615 SERIALIZE_SCALAR(int_clear_serial
);
616 const uint32_t int_mask_serial
= int_mask
;
617 SERIALIZE_SCALAR(int_mask_serial
);
618 const uint32_t int_status_serial
= int_status
;
619 SERIALIZE_SCALAR(int_status_serial
);
621 SERIALIZE_SCALAR(fb_base
);
622 SERIALIZE_SCALAR(fb_line_length
);
624 const uint32_t fb_line_count_serial
= fb_line_count
;
625 SERIALIZE_SCALAR(fb_line_count_serial
);
627 SERIALIZE_SCALAR(fb_line_pitch
);
629 const uint32_t bus_options_serial
= bus_options
;
630 SERIALIZE_SCALAR(bus_options_serial
);
631 const uint32_t v_sync_serial
= v_sync
;
632 SERIALIZE_SCALAR(v_sync_serial
);
633 const uint32_t v_back_porch_serial
= v_back_porch
;
634 SERIALIZE_SCALAR(v_back_porch_serial
);
635 const uint32_t v_data_serial
= v_data
;
636 SERIALIZE_SCALAR(v_data_serial
);
637 const uint32_t v_front_porch_serial
= v_front_porch
;
638 SERIALIZE_SCALAR(v_front_porch_serial
);
639 const uint32_t h_sync_serial
= h_sync
;
640 SERIALIZE_SCALAR(h_sync_serial
);
641 const uint32_t h_back_porch_serial
= h_back_porch
;
642 SERIALIZE_SCALAR(h_back_porch_serial
);
643 const uint32_t h_data_serial
= h_data
;
644 SERIALIZE_SCALAR(h_data_serial
);
645 const uint32_t h_front_porch_serial
= h_front_porch
;
646 SERIALIZE_SCALAR(h_front_porch_serial
);
647 const uint32_t polarities_serial
= polarities
;
648 SERIALIZE_SCALAR(polarities_serial
);
649 const uint32_t command_serial
= command
;
650 SERIALIZE_SCALAR(command_serial
);
651 const uint32_t pixel_format_serial
= pixel_format
;
652 SERIALIZE_SCALAR(pixel_format_serial
);
653 const uint32_t red_select_serial
= red_select
;
654 SERIALIZE_SCALAR(red_select_serial
);
655 const uint32_t green_select_serial
= green_select
;
656 SERIALIZE_SCALAR(green_select_serial
);
657 const uint32_t blue_select_serial
= blue_select
;
658 SERIALIZE_SCALAR(blue_select_serial
);
660 SERIALIZE_SCALAR(frameReadStartTime
);
661 SERIALIZE_SCALAR(dmaStartAddr
);
662 SERIALIZE_SCALAR(dmaCurAddr
);
663 SERIALIZE_SCALAR(dmaMaxAddr
);
664 SERIALIZE_SCALAR(dmaPendingNum
);
665 SERIALIZE_SCALAR(frameUnderrun
);
667 const size_t buffer_size
= bytesPerPixel() * width() * height();
668 SERIALIZE_ARRAY(virtualDisplayBuffer
, buffer_size
);
670 SERIALIZE_SCALAR(pixelBufferSize
);
671 SERIALIZE_SCALAR(pixelIndex
);
672 SERIALIZE_SCALAR(doUpdateParams
);
673 SERIALIZE_SCALAR(frameUnderway
);
674 SERIALIZE_SCALAR(dmaBytesInFlight
);
676 Tick start_event_time
= 0;
677 Tick end_event_time
= 0;
678 Tick render_pixel_event_time
= 0;
679 Tick fill_pixel_buffer_event_time
= 0;
680 Tick int_event_time
= 0;
681 if (startFrameEvent
.scheduled())
682 start_event_time
= startFrameEvent
.when();
683 if (endFrameEvent
.scheduled())
684 end_event_time
= endFrameEvent
.when();
685 if (renderPixelEvent
.scheduled())
686 render_pixel_event_time
= renderPixelEvent
.when();
687 if (fillPixelBufferEvent
.scheduled())
688 fill_pixel_buffer_event_time
= fillPixelBufferEvent
.when();
689 if (intEvent
.scheduled())
690 int_event_time
= intEvent
.when();
691 SERIALIZE_SCALAR(start_event_time
);
692 SERIALIZE_SCALAR(end_event_time
);
693 SERIALIZE_SCALAR(render_pixel_event_time
);
694 SERIALIZE_SCALAR(fill_pixel_buffer_event_time
);
695 SERIALIZE_SCALAR(int_event_time
);
697 vector
<Tick
> dma_done_event_tick(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
698 vector
<size_t> dma_done_event_burst_len(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
699 for (int x
= 0; x
< MAX_OUTSTANDING_DMA_REQ_CAPACITY
; ++x
) {
700 dma_done_event_tick
[x
] = dmaDoneEventAll
[x
].scheduled() ?
701 dmaDoneEventAll
[x
].when() : 0;
702 dma_done_event_burst_len
[x
] = dmaDoneEventAll
[x
].scheduled() ?
703 dmaDoneEventAll
[x
].getTransactionSize() : 0;
705 arrayParamOut(os
, "dma_done_event_tick", dma_done_event_tick
);
706 arrayParamOut(os
, "dma_done_event_burst_length", dma_done_event_burst_len
);
710 HDLcd::unserialize(Checkpoint
*cp
, const std::string
§ion
)
712 uint32_t version_serial
, int_rawstat_serial
, int_clear_serial
,
713 int_mask_serial
, int_status_serial
, fb_line_count_serial
,
714 bus_options_serial
, v_sync_serial
, v_back_porch_serial
,
715 v_data_serial
, v_front_porch_serial
, h_sync_serial
,
716 h_back_porch_serial
, h_data_serial
, h_front_porch_serial
,
717 polarities_serial
, command_serial
, pixel_format_serial
,
718 red_select_serial
, green_select_serial
, blue_select_serial
;
720 DPRINTF(HDLcd
, "Unserializing ARM HDLCD\n");
722 UNSERIALIZE_SCALAR(version_serial
);
723 version
= version_serial
;
724 UNSERIALIZE_SCALAR(int_rawstat_serial
);
725 int_rawstat
= int_rawstat_serial
;
726 UNSERIALIZE_SCALAR(int_clear_serial
);
727 int_clear
= int_clear_serial
;
728 UNSERIALIZE_SCALAR(int_mask_serial
);
729 int_mask
= int_mask_serial
;
730 UNSERIALIZE_SCALAR(int_status_serial
);
731 int_status
= int_status_serial
;
733 UNSERIALIZE_SCALAR(fb_base
);
734 UNSERIALIZE_SCALAR(fb_line_length
);
736 UNSERIALIZE_SCALAR(fb_line_count_serial
);
737 fb_line_count
= fb_line_count_serial
;
739 UNSERIALIZE_SCALAR(fb_line_pitch
);
741 UNSERIALIZE_SCALAR(bus_options_serial
);
742 bus_options
= bus_options_serial
;
743 UNSERIALIZE_SCALAR(v_sync_serial
);
744 v_sync
= v_sync_serial
;
745 UNSERIALIZE_SCALAR(v_back_porch_serial
);
746 v_back_porch
= v_back_porch_serial
;
747 UNSERIALIZE_SCALAR(v_data_serial
);
748 v_data
= v_data_serial
;
749 UNSERIALIZE_SCALAR(v_front_porch_serial
);
750 v_front_porch
= v_front_porch_serial
;
751 UNSERIALIZE_SCALAR(h_sync_serial
);
752 h_sync
= h_sync_serial
;
753 UNSERIALIZE_SCALAR(h_back_porch_serial
);
754 h_back_porch
= h_back_porch_serial
;
755 UNSERIALIZE_SCALAR(h_data_serial
);
756 h_data
= h_data_serial
;
757 UNSERIALIZE_SCALAR(h_front_porch_serial
);
758 h_front_porch
= h_front_porch_serial
;
759 UNSERIALIZE_SCALAR(polarities_serial
);
760 polarities
= polarities_serial
;
761 UNSERIALIZE_SCALAR(command_serial
);
762 command
= command_serial
;
763 UNSERIALIZE_SCALAR(pixel_format_serial
);
764 pixel_format
= pixel_format_serial
;
765 UNSERIALIZE_SCALAR(red_select_serial
);
766 red_select
= red_select_serial
;
767 UNSERIALIZE_SCALAR(green_select_serial
);
768 green_select
= green_select_serial
;
769 UNSERIALIZE_SCALAR(blue_select_serial
);
770 blue_select
= blue_select_serial
;
772 UNSERIALIZE_SCALAR(frameReadStartTime
);
773 UNSERIALIZE_SCALAR(dmaStartAddr
);
774 UNSERIALIZE_SCALAR(dmaCurAddr
);
775 UNSERIALIZE_SCALAR(dmaMaxAddr
);
776 UNSERIALIZE_SCALAR(dmaPendingNum
);
777 UNSERIALIZE_SCALAR(frameUnderrun
);
778 UNSERIALIZE_SCALAR(dmaBytesInFlight
);
780 const size_t buffer_size
= bytesPerPixel() * width() * height();
781 virtualDisplayBuffer
= new uint8_t[buffer_size
];
782 UNSERIALIZE_ARRAY(virtualDisplayBuffer
, buffer_size
);
784 UNSERIALIZE_SCALAR(pixelBufferSize
);
785 UNSERIALIZE_SCALAR(pixelIndex
);
786 UNSERIALIZE_SCALAR(doUpdateParams
);
787 UNSERIALIZE_SCALAR(frameUnderway
);
789 Tick start_event_time
= 0;
790 Tick end_event_time
= 0;
791 Tick render_pixel_event_time
= 0;
792 Tick fill_pixel_buffer_event_time
= 0;
793 Tick int_event_time
= 0;
794 UNSERIALIZE_SCALAR(start_event_time
);
795 UNSERIALIZE_SCALAR(end_event_time
);
796 UNSERIALIZE_SCALAR(render_pixel_event_time
);
797 UNSERIALIZE_SCALAR(fill_pixel_buffer_event_time
);
798 UNSERIALIZE_SCALAR(int_event_time
);
799 if (start_event_time
)
800 schedule(startFrameEvent
, start_event_time
);
802 schedule(endFrameEvent
, end_event_time
);
803 if (render_pixel_event_time
)
804 schedule(renderPixelEvent
, render_pixel_event_time
);
805 if (fill_pixel_buffer_event_time
)
806 schedule(fillPixelBufferEvent
, fill_pixel_buffer_event_time
);
808 schedule(intEvent
, int_event_time
);
810 vector
<Tick
> dma_done_event_tick(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
811 vector
<Tick
> dma_done_event_burst_len(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
812 arrayParamIn(cp
, section
, "dma_done_event_tick", dma_done_event_tick
);
813 arrayParamIn(cp
, section
, "dma_done_event_burst_length", dma_done_event_burst_len
);
814 dmaDoneEventFree
.clear();
815 for (int x
= 0; x
< MAX_OUTSTANDING_DMA_REQ_CAPACITY
; ++x
) {
816 if (dma_done_event_tick
[x
]) {
817 dmaDoneEventAll
[x
].setTransactionSize(dma_done_event_burst_len
[x
]);
818 schedule(dmaDoneEventAll
[x
], dma_done_event_tick
[x
]);
820 dmaDoneEventFree
.push_back(&dmaDoneEventAll
[x
]);
822 assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY
- dmaDoneEventFree
.size() == dmaPendingNum
);
825 updateVideoParams(true);
832 HDLcd::generateInterrupt()
834 int_status
= int_rawstat
& int_mask
;
835 DPRINTF(HDLcd
, "Generate Interrupt: int_rawstat=0x%08x int_mask=0x%08x "
836 "int_status=0x%08x\n",
837 (uint32_t)int_rawstat
, (uint32_t)int_mask
, (uint32_t)int_status
);
839 if (int_status
!= 0) {
840 gic
->sendInt(intNum
);
841 DPRINTF(HDLcd
, " -- Generated\n");
846 HDLcd::getAddrRanges() const
848 AddrRangeList ranges
;
849 ranges
.push_back(RangeSize(pioAddr
, pioSize
));
854 HDLcdParams::create()
856 return new HDLcd(this);