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);
117 panic("HDLCD INT_CLEAR register is Write-Only\n");
129 data
= fb_line_length
;
132 data
= fb_line_count
;
135 data
= fb_line_pitch
;
150 data
= v_front_porch
;
162 data
= h_front_porch
;
183 panic("Tried to read HDLCD register that doesn't exist\n", daddr
);
187 pkt
->set
<uint32_t>(data
);
188 pkt
->makeAtomicResponse();
192 // write registers and frame buffer
194 HDLcd::write(PacketPtr pkt
)
196 assert(pkt
->getAddr() >= pioAddr
&&
197 pkt
->getAddr() < pioAddr
+ pioSize
&&
198 pkt
->getSize() == 4);
200 const uint32_t data
= pkt
->get
<uint32_t>();
201 const Addr daddr
= pkt
->getAddr() - pioAddr
;
203 DPRINTF(HDLcd
, "write register BASE+%0x04x <= 0x%08x\n", daddr
,
204 pkt
->get
<uint32_t>());
208 panic("HDLCD VERSION register is read-Only\n");
220 panic("HDLCD INT_STATUS register is read-Only\n");
224 DPRINTF(HDLcd
, "HDLCD Frame Buffer located at addr 0x%08x\n", fb_base
);
227 fb_line_length
= data
;
228 DPRINTF(HDLcd
, "HDLCD res = %d x %d\n", width(), height());
231 fb_line_count
= data
;
232 DPRINTF(HDLcd
, "HDLCD res = %d x %d\n", width(), height());
235 fb_line_pitch
= data
;
238 BusOptsReg old_bus_options
;
239 old_bus_options
= bus_options
;
241 if (bus_options
.max_outstanding
!= old_bus_options
.max_outstanding
)
243 "Changing HDLcd outstanding dma transactions from %d to %d\n",
244 old_bus_options
.max_outstanding
, bus_options
.max_outstanding
);
245 if (bus_options
.burst_len
!= old_bus_options
.burst_len
)
247 "Changing HDLcd dma burst length from %d bytes to %d bytes\n",
248 old_bus_options
.burst_len
, bus_options
.burst_len
); }
260 v_front_porch
= data
;
272 h_front_porch
= data
;
278 CommandReg new_command
;
280 if (new_command
.enable
!= command
.enable
) {
281 DPRINTF(HDLcd
, "HDLCD switched %s\n",
282 new_command
.enable
==0 ? "off" : "on");
283 if (new_command
.enable
) {
284 doUpdateParams
= true;
285 if (!frameUnderway
) {
286 schedule(startFrameEvent
, clockEdge());
290 command
= new_command
; }
294 DPRINTF(HDLcd
, "HDLCD res = %d x %d\n", width(), height());
295 DPRINTF(HDLcd
, "HDLCD bytes per pixel = %d\n", bytesPerPixel());
296 DPRINTF(HDLcd
, "HDLCD endianness = %s\n",
297 pixel_format
.big_endian
? "big" : "little");
309 panic("Tried to write HDLCD register that doesn't exist\n", daddr
);
313 pkt
->makeAtomicResponse();
318 HDLcd::updateVideoParams(bool unserializing
= false)
320 const uint16_t bpp
= bytesPerPixel() << 3;
321 const size_t buffer_size
= bytesPerPixel() * width() * height();
323 // updating these parameters while LCD is enabled is not supported
324 if (frameUnderway
&& !unserializing
)
325 panic("Attempting to change some HDLCD parameters while the controller"
326 " is active is not allowed");
328 // resize the virtualDisplayBuffer unless we are unserializing - it may
330 // there must be no outstanding DMA transactions for this to work
331 if (!unserializing
) {
332 assert(dmaPendingNum
== 0);
333 if (virtualDisplayBuffer
)
334 delete [] virtualDisplayBuffer
;
335 virtualDisplayBuffer
= new uint8_t[buffer_size
];
336 memset(virtualDisplayBuffer
, 0, buffer_size
);
339 assert(virtualDisplayBuffer
);
341 vnc
->setFramebufferAddr(virtualDisplayBuffer
);
346 DPRINTF(HDLcd
, "bpp = %d\n", bpp
);
347 DPRINTF(HDLcd
, "display size = %d x %d\n", width(), height());
349 const size_t totalLinesPerFrame
= v_back_porch
.val
+ 1 +
351 v_front_porch
.val
+ 1 +
353 const double fps
= (double)SimClock::Frequency
/
354 (double)(PClksPerLine() * totalLinesPerFrame
* pixelClock
);
356 DPRINTF(HDLcd
, "simulated refresh rate ~ %.1ffps generating ~ %.1fMB/s "
357 "traffic ([%.1fMHz, T=%d sim clocks] pclk, %d bpp => %.1fMB/s peak requirement)\n",
359 fps
* buffer_size
/ 1024 / 1024,
360 (double)SimClock::Frequency
/ pixelClock
/ 1000000.0,
363 (double)(SimClock::Frequency
/ pixelClock
* (bpp
/ 8)) / 1024 / 1024);
365 if (pixel_format
.big_endian
)
366 panic("Big Endian pixel format not implemented by HDLcd controller");
370 (red_select
.size
== 8) &&
371 (blue_select
.size
== 8) &&
372 (green_select
.size
== 8) &&
373 (green_select
.offset
== 8)) {
374 if ((blue_select
.offset
== 0) &&
375 (red_select
.offset
== 16)) {
376 vnc
->setFrameBufferParams(VideoConvert::rgb8888
, width(),
378 bmp
= new Bitmap(VideoConvert::rgb8888
, width(), height(),
379 virtualDisplayBuffer
);
380 DPRINTF(HDLcd
, "color mode: rgb888\n");
381 } else if ((red_select
.offset
== 0) &&
382 (blue_select
.offset
== 16)) {
383 vnc
->setFrameBufferParams(VideoConvert::bgr8888
, width(),
385 bmp
= new Bitmap(VideoConvert::bgr8888
, width(), height(),
386 virtualDisplayBuffer
);
387 DPRINTF(HDLcd
, "color mode: bgr888\n");
389 } else if ((bpp
== 16) &&
390 (red_select
.size
== 5) &&
391 (blue_select
.size
== 5) &&
392 (green_select
.size
== 6) &&
393 (green_select
.offset
== 5)) {
394 if ((blue_select
.offset
== 0) &&
395 (red_select
.offset
== 11)) {
396 vnc
->setFrameBufferParams(VideoConvert::rgb565
, width(),
398 bmp
= new Bitmap(VideoConvert::rgb565
, width(), height(),
399 virtualDisplayBuffer
);
400 DPRINTF(HDLcd
, "color mode: rgb565\n");
401 } else if ((red_select
.offset
== 0) &&
402 (blue_select
.offset
== 11)) {
403 vnc
->setFrameBufferParams(VideoConvert::bgr565
, width(),
405 bmp
= new Bitmap(VideoConvert::bgr565
, width(), height(),
406 virtualDisplayBuffer
);
407 DPRINTF(HDLcd
, "color mode: bgr565\n");
410 DPRINTF(HDLcd
, "color mode: undefined\n");
411 panic("Unimplemented video mode\n");
419 // 0. Check that we are in the appropriate state
420 assert(!frameUnderway
);
423 DPRINTF(HDLcd
, "Frame read started\n");
424 if (doUpdateParams
) {
426 doUpdateParams
= false;
428 frameUnderway
= true;
429 assert(virtualDisplayBuffer
);
430 assert(pixelBufferSize
== 0);
431 assert(dmaBytesInFlight
== 0);
432 assert(dmaPendingNum
== 0);
433 assert(dmaDoneEventFree
.size() == dmaDoneEventAll
.size());
434 assert(!renderPixelEvent
.scheduled());
435 // currently only support positive line pitches equal to the line length
436 assert(width() * bytesPerPixel() == fb_line_pitch
);
438 // 1. Start DMA'ing the frame; subsequent transactions created as we go
439 dmaCurAddr
= dmaStartAddr
= fb_base
;
440 dmaMaxAddr
= static_cast<Addr
>(width() * height() * bytesPerPixel()) +
442 frameReadStartTime
= curTick();
444 frameUnderrun
= false;
447 // 2. Schedule first pixelclock read; subsequent reads generated as we go
448 Tick firstPixelReadTick
= curTick() + pixelClock
* (
449 PClksPerLine() * (v_sync
.val
+ 1 +
450 v_back_porch
.val
+ 1) +
452 h_back_porch
.val
+ 1);
453 schedule(renderPixelEvent
, firstPixelReadTick
);
457 HDLcd::fillPixelBuffer()
459 // - am I under the LCD dma transaction total?
460 // - do I have more data to transfer?
461 // - have I not yet underrun for this frame?
462 // - is there room to put the data in the pixel buffer including any
463 // outstanding dma transfers in flight?
464 while ((dmaPendingNum
< maxOutstandingDma()) &&
465 (dmaMaxAddr
> dmaCurAddr
) &&
467 bytesFreeInPixelBuffer() > dmaBurstLength() * AXI_PORT_WIDTH
) {
468 // try largest transaction size allowed first but switch to smaller
469 // sizes for trailing bytes
470 size_t transaction_size
= dmaBurstLength() * AXI_PORT_WIDTH
;
471 while (transaction_size
> (dmaMaxAddr
- dmaCurAddr
))
472 transaction_size
>>= 1;
473 assert(transaction_size
> 0);
475 // concurrent dma reads need different dma done events
476 // due to assertion in scheduling state
479 assert(!dmaDoneEventFree
.empty());
480 DmaDoneEvent
*event(dmaDoneEventFree
.back());
481 dmaDoneEventFree
.pop_back();
483 assert(!event
->scheduled());
485 // We use a uncachable request here because the requests from the CPU
486 // will be uncacheable as well. If we have uncacheable and cacheable
487 // requests in the memory system for the same address it won't be
489 event
->setTransactionSize(transaction_size
);
490 dmaPort
.dmaAction(MemCmd::ReadReq
, dmaCurAddr
, transaction_size
, event
,
491 virtualDisplayBuffer
+ dmaCurAddr
- dmaStartAddr
,
492 0, Request::UNCACHEABLE
);
493 dmaCurAddr
+= transaction_size
;
494 dmaBytesInFlight
+= transaction_size
;
501 // try to handle multiple pixels at a time; doing so reduces the accuracy
502 // of the underrun detection but lowers simulation overhead
503 const size_t count
= 32;
504 assert(width() % count
== 0); // not set up to handle trailing pixels
506 // have we underrun on this frame anytime before?
508 // the LCD controller gives up on a frame if an underrun occurs and
509 // resumes regular operation on the next frame
512 // did we underrun on this set of pixels?
513 if (pixelBufferSize
< bytesPerPixel() * count
) {
514 warn("HDLcd controller buffer underrun\n");
515 frameUnderrun
= true;
516 int_rawstat
.underrun
= 1;
517 if (!intEvent
.scheduled())
518 schedule(intEvent
, clockEdge());
520 // emulate the pixel read from the internal buffer
521 pixelBufferSize
-= bytesPerPixel() * count
;
525 // the DMA may have previously stalled due to the buffer being full;
526 // give it a kick; it knows not to fill if at end of frame, underrun, etc
527 if (!fillPixelBufferEvent
.scheduled())
528 schedule(fillPixelBufferEvent
, clockEdge());
530 // schedule the next pixel read according to where it is in the frame
532 assert(pixelIndex
<= width() * height());
533 size_t x
= pixelIndex
% width();
534 Tick nextEventTick
= curTick();
537 nextEventTick
+= pixelClock
* ((h_front_porch
.val
+ 1) +
538 (h_back_porch
.val
+ 1) +
540 if (pixelIndex
== width() * height()) {
542 nextEventTick
+= PClksPerLine() * (v_front_porch
.val
+ 1) *
544 schedule(endFrameEvent
, nextEventTick
);
548 nextEventTick
+= pixelClock
* count
;
551 schedule(renderPixelEvent
, nextEventTick
);
556 assert(pixelBufferSize
== 0);
557 assert(dmaPendingNum
== 0);
558 assert(dmaBytesInFlight
== 0);
559 assert(dmaDoneEventFree
.size() == dmaDoneEventAll
.size());
566 pic
= simout
.create(csprintf("%s.framebuffer.bmp", sys
->name()), true);
574 // start the next frame
575 frameUnderway
= false;
580 HDLcd::dmaDone(DmaDoneEvent
*event
)
582 const size_t transactionLength
= event
->getTransactionSize();
583 assert(pixelBufferSize
+ transactionLength
< PIXEL_BUFFER_CAPACITY
);
584 assert(dmaCurAddr
<= dmaMaxAddr
);
586 dmaDoneEventFree
.push_back(event
);
588 assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY
- dmaDoneEventFree
.size() ==
591 // add the data to the pixel buffer
592 dmaBytesInFlight
-= transactionLength
;
593 pixelBufferSize
+= transactionLength
;
595 // schedule another dma transaction if:
596 // - we're not done reading the frame
597 // - there is sufficient room in the pixel buffer for another transaction
598 // - another fillPixelBufferEvent is not already scheduled
599 const size_t targetTransSize
= dmaBurstLength() * AXI_PORT_WIDTH
;
600 if ((dmaCurAddr
< dmaMaxAddr
) &&
601 (bytesFreeInPixelBuffer() + targetTransSize
< PIXEL_BUFFER_CAPACITY
) &&
602 !fillPixelBufferEvent
.scheduled()) {
603 schedule(fillPixelBufferEvent
, clockEdge());
608 HDLcd::serialize(std::ostream
&os
)
610 DPRINTF(HDLcd
, "Serializing ARM HDLCD\n");
612 const uint32_t version_serial
= version
;
613 SERIALIZE_SCALAR(version_serial
);
614 const uint32_t int_rawstat_serial
= int_rawstat
;
615 SERIALIZE_SCALAR(int_rawstat_serial
);
616 const uint32_t int_clear_serial
= int_clear
;
617 SERIALIZE_SCALAR(int_clear_serial
);
618 const uint32_t int_mask_serial
= int_mask
;
619 SERIALIZE_SCALAR(int_mask_serial
);
620 const uint32_t int_status_serial
= int_status
;
621 SERIALIZE_SCALAR(int_status_serial
);
623 SERIALIZE_SCALAR(fb_base
);
624 SERIALIZE_SCALAR(fb_line_length
);
626 const uint32_t fb_line_count_serial
= fb_line_count
;
627 SERIALIZE_SCALAR(fb_line_count_serial
);
629 SERIALIZE_SCALAR(fb_line_pitch
);
631 const uint32_t bus_options_serial
= bus_options
;
632 SERIALIZE_SCALAR(bus_options_serial
);
633 const uint32_t v_sync_serial
= v_sync
;
634 SERIALIZE_SCALAR(v_sync_serial
);
635 const uint32_t v_back_porch_serial
= v_back_porch
;
636 SERIALIZE_SCALAR(v_back_porch_serial
);
637 const uint32_t v_data_serial
= v_data
;
638 SERIALIZE_SCALAR(v_data_serial
);
639 const uint32_t v_front_porch_serial
= v_front_porch
;
640 SERIALIZE_SCALAR(v_front_porch_serial
);
641 const uint32_t h_sync_serial
= h_sync
;
642 SERIALIZE_SCALAR(h_sync_serial
);
643 const uint32_t h_back_porch_serial
= h_back_porch
;
644 SERIALIZE_SCALAR(h_back_porch_serial
);
645 const uint32_t h_data_serial
= h_data
;
646 SERIALIZE_SCALAR(h_data_serial
);
647 const uint32_t h_front_porch_serial
= h_front_porch
;
648 SERIALIZE_SCALAR(h_front_porch_serial
);
649 const uint32_t polarities_serial
= polarities
;
650 SERIALIZE_SCALAR(polarities_serial
);
651 const uint32_t command_serial
= command
;
652 SERIALIZE_SCALAR(command_serial
);
653 const uint32_t pixel_format_serial
= pixel_format
;
654 SERIALIZE_SCALAR(pixel_format_serial
);
655 const uint32_t red_select_serial
= red_select
;
656 SERIALIZE_SCALAR(red_select_serial
);
657 const uint32_t green_select_serial
= green_select
;
658 SERIALIZE_SCALAR(green_select_serial
);
659 const uint32_t blue_select_serial
= blue_select
;
660 SERIALIZE_SCALAR(blue_select_serial
);
662 SERIALIZE_SCALAR(frameReadStartTime
);
663 SERIALIZE_SCALAR(dmaStartAddr
);
664 SERIALIZE_SCALAR(dmaCurAddr
);
665 SERIALIZE_SCALAR(dmaMaxAddr
);
666 SERIALIZE_SCALAR(dmaPendingNum
);
667 SERIALIZE_SCALAR(frameUnderrun
);
669 const size_t buffer_size
= bytesPerPixel() * width() * height();
670 SERIALIZE_ARRAY(virtualDisplayBuffer
, buffer_size
);
672 SERIALIZE_SCALAR(pixelBufferSize
);
673 SERIALIZE_SCALAR(pixelIndex
);
674 SERIALIZE_SCALAR(doUpdateParams
);
675 SERIALIZE_SCALAR(frameUnderway
);
676 SERIALIZE_SCALAR(dmaBytesInFlight
);
678 Tick start_event_time
= 0;
679 Tick end_event_time
= 0;
680 Tick render_pixel_event_time
= 0;
681 Tick fill_pixel_buffer_event_time
= 0;
682 Tick int_event_time
= 0;
683 if (startFrameEvent
.scheduled())
684 start_event_time
= startFrameEvent
.when();
685 if (endFrameEvent
.scheduled())
686 end_event_time
= endFrameEvent
.when();
687 if (renderPixelEvent
.scheduled())
688 render_pixel_event_time
= renderPixelEvent
.when();
689 if (fillPixelBufferEvent
.scheduled())
690 fill_pixel_buffer_event_time
= fillPixelBufferEvent
.when();
691 if (intEvent
.scheduled())
692 int_event_time
= intEvent
.when();
693 SERIALIZE_SCALAR(start_event_time
);
694 SERIALIZE_SCALAR(end_event_time
);
695 SERIALIZE_SCALAR(render_pixel_event_time
);
696 SERIALIZE_SCALAR(fill_pixel_buffer_event_time
);
697 SERIALIZE_SCALAR(int_event_time
);
699 vector
<Tick
> dma_done_event_tick(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
700 vector
<size_t> dma_done_event_burst_len(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
701 for (int x
= 0; x
< MAX_OUTSTANDING_DMA_REQ_CAPACITY
; ++x
) {
702 dma_done_event_tick
[x
] = dmaDoneEventAll
[x
].scheduled() ?
703 dmaDoneEventAll
[x
].when() : 0;
704 dma_done_event_burst_len
[x
] = dmaDoneEventAll
[x
].scheduled() ?
705 dmaDoneEventAll
[x
].getTransactionSize() : 0;
707 arrayParamOut(os
, "dma_done_event_tick", dma_done_event_tick
);
708 arrayParamOut(os
, "dma_done_event_burst_length", dma_done_event_burst_len
);
712 HDLcd::unserialize(Checkpoint
*cp
, const std::string
§ion
)
714 uint32_t version_serial
, int_rawstat_serial
, int_clear_serial
,
715 int_mask_serial
, int_status_serial
, fb_line_count_serial
,
716 bus_options_serial
, v_sync_serial
, v_back_porch_serial
,
717 v_data_serial
, v_front_porch_serial
, h_sync_serial
,
718 h_back_porch_serial
, h_data_serial
, h_front_porch_serial
,
719 polarities_serial
, command_serial
, pixel_format_serial
,
720 red_select_serial
, green_select_serial
, blue_select_serial
;
722 DPRINTF(HDLcd
, "Unserializing ARM HDLCD\n");
724 UNSERIALIZE_SCALAR(version_serial
);
725 version
= version_serial
;
726 UNSERIALIZE_SCALAR(int_rawstat_serial
);
727 int_rawstat
= int_rawstat_serial
;
728 UNSERIALIZE_SCALAR(int_clear_serial
);
729 int_clear
= int_clear_serial
;
730 UNSERIALIZE_SCALAR(int_mask_serial
);
731 int_mask
= int_mask_serial
;
732 UNSERIALIZE_SCALAR(int_status_serial
);
733 int_status
= int_status_serial
;
735 UNSERIALIZE_SCALAR(fb_base
);
736 UNSERIALIZE_SCALAR(fb_line_length
);
738 UNSERIALIZE_SCALAR(fb_line_count_serial
);
739 fb_line_count
= fb_line_count_serial
;
741 UNSERIALIZE_SCALAR(fb_line_pitch
);
743 UNSERIALIZE_SCALAR(bus_options_serial
);
744 bus_options
= bus_options_serial
;
745 UNSERIALIZE_SCALAR(v_sync_serial
);
746 v_sync
= v_sync_serial
;
747 UNSERIALIZE_SCALAR(v_back_porch_serial
);
748 v_back_porch
= v_back_porch_serial
;
749 UNSERIALIZE_SCALAR(v_data_serial
);
750 v_data
= v_data_serial
;
751 UNSERIALIZE_SCALAR(v_front_porch_serial
);
752 v_front_porch
= v_front_porch_serial
;
753 UNSERIALIZE_SCALAR(h_sync_serial
);
754 h_sync
= h_sync_serial
;
755 UNSERIALIZE_SCALAR(h_back_porch_serial
);
756 h_back_porch
= h_back_porch_serial
;
757 UNSERIALIZE_SCALAR(h_data_serial
);
758 h_data
= h_data_serial
;
759 UNSERIALIZE_SCALAR(h_front_porch_serial
);
760 h_front_porch
= h_front_porch_serial
;
761 UNSERIALIZE_SCALAR(polarities_serial
);
762 polarities
= polarities_serial
;
763 UNSERIALIZE_SCALAR(command_serial
);
764 command
= command_serial
;
765 UNSERIALIZE_SCALAR(pixel_format_serial
);
766 pixel_format
= pixel_format_serial
;
767 UNSERIALIZE_SCALAR(red_select_serial
);
768 red_select
= red_select_serial
;
769 UNSERIALIZE_SCALAR(green_select_serial
);
770 green_select
= green_select_serial
;
771 UNSERIALIZE_SCALAR(blue_select_serial
);
772 blue_select
= blue_select_serial
;
774 UNSERIALIZE_SCALAR(frameReadStartTime
);
775 UNSERIALIZE_SCALAR(dmaStartAddr
);
776 UNSERIALIZE_SCALAR(dmaCurAddr
);
777 UNSERIALIZE_SCALAR(dmaMaxAddr
);
778 UNSERIALIZE_SCALAR(dmaPendingNum
);
779 UNSERIALIZE_SCALAR(frameUnderrun
);
780 UNSERIALIZE_SCALAR(dmaBytesInFlight
);
782 const size_t buffer_size
= bytesPerPixel() * width() * height();
783 virtualDisplayBuffer
= new uint8_t[buffer_size
];
784 UNSERIALIZE_ARRAY(virtualDisplayBuffer
, buffer_size
);
786 UNSERIALIZE_SCALAR(pixelBufferSize
);
787 UNSERIALIZE_SCALAR(pixelIndex
);
788 UNSERIALIZE_SCALAR(doUpdateParams
);
789 UNSERIALIZE_SCALAR(frameUnderway
);
791 Tick start_event_time
= 0;
792 Tick end_event_time
= 0;
793 Tick render_pixel_event_time
= 0;
794 Tick fill_pixel_buffer_event_time
= 0;
795 Tick int_event_time
= 0;
796 UNSERIALIZE_SCALAR(start_event_time
);
797 UNSERIALIZE_SCALAR(end_event_time
);
798 UNSERIALIZE_SCALAR(render_pixel_event_time
);
799 UNSERIALIZE_SCALAR(fill_pixel_buffer_event_time
);
800 UNSERIALIZE_SCALAR(int_event_time
);
801 if (start_event_time
)
802 schedule(startFrameEvent
, start_event_time
);
804 schedule(endFrameEvent
, end_event_time
);
805 if (render_pixel_event_time
)
806 schedule(renderPixelEvent
, render_pixel_event_time
);
807 if (fill_pixel_buffer_event_time
)
808 schedule(fillPixelBufferEvent
, fill_pixel_buffer_event_time
);
810 schedule(intEvent
, int_event_time
);
812 vector
<Tick
> dma_done_event_tick(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
813 vector
<Tick
> dma_done_event_burst_len(MAX_OUTSTANDING_DMA_REQ_CAPACITY
);
814 arrayParamIn(cp
, section
, "dma_done_event_tick", dma_done_event_tick
);
815 arrayParamIn(cp
, section
, "dma_done_event_burst_length", dma_done_event_burst_len
);
816 dmaDoneEventFree
.clear();
817 for (int x
= 0; x
< MAX_OUTSTANDING_DMA_REQ_CAPACITY
; ++x
) {
818 if (dma_done_event_tick
[x
]) {
819 dmaDoneEventAll
[x
].setTransactionSize(dma_done_event_burst_len
[x
]);
820 schedule(dmaDoneEventAll
[x
], dma_done_event_tick
[x
]);
822 dmaDoneEventFree
.push_back(&dmaDoneEventAll
[x
]);
824 assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY
- dmaDoneEventFree
.size() == dmaPendingNum
);
827 updateVideoParams(true);
834 HDLcd::generateInterrupt()
836 int_status
= int_rawstat
& int_mask
;
837 DPRINTF(HDLcd
, "Generate Interrupt: int_rawstat=0x%08x int_mask=0x%08x "
838 "int_status=0x%08x\n",
839 (uint32_t)int_rawstat
, (uint32_t)int_mask
, (uint32_t)int_status
);
841 if (int_status
!= 0) {
842 gic
->sendInt(intNum
);
843 DPRINTF(HDLcd
, " -- Generated\n");
848 HDLcd::getAddrRanges() const
850 AddrRangeList ranges
;
851 ranges
.push_back(RangeSize(pioAddr
, pioSize
));
856 HDLcdParams::create()
858 return new HDLcd(this);