pl111.cc (7950:1120b07dd4b0) pl111.cc (8062:ef46ec5373dd)
1/*
2 * Copyright (c) 2010 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
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
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.
24 *
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.
36 *
37 * Authors: William Wang
38 * Ali Saidi
39 */
40
41#include "base/bitmap.hh"
42#include "base/output.hh"
43#include "base/trace.hh"
44#include "base/vnc/vncserver.hh"
45#include "dev/arm/amba_device.hh"
46#include "dev/arm/gic.hh"
47#include "dev/arm/pl111.hh"
48#include "mem/packet.hh"
49#include "mem/packet_access.hh"
50
51using namespace AmbaDev;
52
53// initialize clcd registers
54Pl111::Pl111(const Params *p)
55 : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0),
56 lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0),
57 lcdRis(0), lcdMis(0),
58 clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
59 clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
60 clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), clock(p->clock),
61 vncserver(p->vnc), bmp(NULL), width(LcdMaxWidth), height(LcdMaxHeight),
62 bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
63 waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
64 dmaDoneEvent(maxOutstandingDma, this), intEvent(this)
65{
66 pioSize = 0xFFFF;
67
68 pic = simout.create("framebuffer.bmp", true);
69
70 dmaBuffer = new uint8_t[LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t)];
71
72 memset(lcdPalette, 0, sizeof(lcdPalette));
73 memset(cursorImage, 0, sizeof(cursorImage));
74 memset(dmaBuffer, 0, sizeof(dmaBuffer));
75
76 if (vncserver)
77 vncserver->setFramebufferAddr(dmaBuffer);
78}
79
80// read registers and frame buffer
81Tick
82Pl111::read(PacketPtr pkt)
83{
84 // use a temporary data since the LCD registers are read/written with
85 // different size operations
86
87 uint32_t data = 0;
88
89 assert(pkt->getAddr() >= pioAddr &&
90 pkt->getAddr() < pioAddr + pioSize);
91
92 Addr daddr = pkt->getAddr() - pioAddr;
93 pkt->allocate();
94
95 DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize());
96
97 switch (daddr) {
98 case LcdTiming0:
99 data = lcdTiming0;
100 break;
101 case LcdTiming1:
102 data = lcdTiming1;
103 break;
104 case LcdTiming2:
105 data = lcdTiming2;
106 break;
107 case LcdTiming3:
108 data = lcdTiming3;
109 break;
110 case LcdUpBase:
111 data = lcdUpbase;
112 break;
113 case LcdLpBase:
114 data = lcdLpbase;
115 break;
116 case LcdControl:
117 data = lcdControl;
118 break;
119 case LcdImsc:
120 data = lcdImsc;
121 break;
122 case LcdRis:
123 data = lcdRis;
124 break;
125 case LcdMis:
126 data = lcdMis;
127 break;
128 case LcdIcr:
129 panic("LCD register at offset %#x is Write-Only\n", daddr);
130 break;
131 case LcdUpCurr:
132 data = curAddr;
133 break;
134 case LcdLpCurr:
135 data = curAddr;
136 break;
137 case ClcdCrsrCtrl:
138 data = clcdCrsrCtrl;
139 break;
140 case ClcdCrsrConfig:
141 data = clcdCrsrConfig;
142 break;
143 case ClcdCrsrPalette0:
144 data = clcdCrsrPalette0;
145 break;
146 case ClcdCrsrPalette1:
147 data = clcdCrsrPalette1;
148 break;
149 case ClcdCrsrXY:
150 data = clcdCrsrXY;
151 break;
152 case ClcdCrsrClip:
153 data = clcdCrsrClip;
154 break;
155 case ClcdCrsrImsc:
156 data = clcdCrsrImsc;
157 break;
158 case ClcdCrsrIcr:
159 panic("CLCD register at offset %#x is Write-Only\n", daddr);
160 break;
161 case ClcdCrsrRis:
162 data = clcdCrsrRis;
163 break;
164 case ClcdCrsrMis:
165 data = clcdCrsrMis;
166 break;
167 default:
168 if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) {
169 // Hack for variable size accesses
170 data = pkt->get<uint32_t>();
171 break;
172 } else if (daddr >= CrsrImage && daddr <= 0xBFC) {
173 // CURSOR IMAGE
174 int index;
175 index = (daddr - CrsrImage) >> 2;
176 data= cursorImage[index];
177 break;
178 } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
179 // LCD Palette
180 int index;
181 index = (daddr - LcdPalette) >> 2;
182 data = lcdPalette[index];
183 break;
184 } else {
185 panic("Tried to read CLCD register at offset %#x that \
186 doesn't exist\n", daddr);
187 break;
188 }
189 }
190
191 switch(pkt->getSize()) {
192 case 1:
193 pkt->set<uint8_t>(data);
194 break;
195 case 2:
196 pkt->set<uint16_t>(data);
197 break;
198 case 4:
199 pkt->set<uint32_t>(data);
200 break;
201 default:
202 panic("CLCD controller read size too big?\n");
203 break;
204 }
205
206 pkt->makeAtomicResponse();
207 return pioDelay;
208}
209
210// write registers and frame buffer
211Tick
212Pl111::write(PacketPtr pkt)
213{
214 // use a temporary data since the LCD registers are read/written with
215 // different size operations
216 //
217 uint32_t data = 0;
218
219 switch(pkt->getSize()) {
220 case 1:
221 data = pkt->get<uint8_t>();
222 break;
223 case 2:
224 data = pkt->get<uint16_t>();
225 break;
226 case 4:
227 data = pkt->get<uint32_t>();
228 break;
229 default:
230 panic("PL111 CLCD controller write size too big?\n");
231 break;
232 }
233
234 assert(pkt->getAddr() >= pioAddr &&
235 pkt->getAddr() < pioAddr + pioSize);
236
237 Addr daddr = pkt->getAddr() - pioAddr;
238
239 DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr,
240 pkt->get<uint8_t>(), pkt->getSize());
241
242 switch (daddr) {
243 case LcdTiming0:
244 lcdTiming0 = data;
245 // width = 16 * (PPL+1)
246 width = (lcdTiming0.ppl + 1) << 4;
247 break;
248 case LcdTiming1:
249 lcdTiming1 = data;
250 // height = LPP + 1
251 height = (lcdTiming1.lpp) + 1;
252 break;
253 case LcdTiming2:
254 lcdTiming2 = data;
255 break;
256 case LcdTiming3:
257 lcdTiming3 = data;
258 break;
259 case LcdUpBase:
260 lcdUpbase = data;
261 DPRINTF(PL111, "####### Upper panel base set to: %#x #######\n", lcdUpbase);
262 break;
263 case LcdLpBase:
264 warn("LCD dual screen mode not supported\n");
265 lcdLpbase = data;
266 DPRINTF(PL111, "###### Lower panel base set to: %#x #######\n", lcdLpbase);
267 break;
268 case LcdControl:
269 int old_lcdpwr;
270 old_lcdpwr = lcdControl.lcdpwr;
271 lcdControl = data;
272
273 DPRINTF(PL111, "LCD power is:%d\n", lcdControl.lcdpwr);
274
275 // LCD power enable
276 if (lcdControl.lcdpwr && !old_lcdpwr) {
277 updateVideoParams();
278 DPRINTF(PL111, " lcd size: height %d width %d\n", height, width);
279 waterMark = lcdControl.watermark ? 8 : 4;
280 startDma();
281 }
282 break;
283 case LcdImsc:
284 lcdImsc = data;
285 if (lcdImsc.vcomp)
286 panic("Interrupting on vcomp not supported\n");
287
288 lcdMis = lcdImsc & lcdRis;
289
290 if (!lcdMis)
291 gic->clearInt(intNum);
292
293 break;
294 case LcdRis:
295 panic("LCD register at offset %#x is Read-Only\n", daddr);
296 break;
297 case LcdMis:
298 panic("LCD register at offset %#x is Read-Only\n", daddr);
299 break;
300 case LcdIcr:
301 lcdRis = lcdRis & ~data;
302 lcdMis = lcdImsc & lcdRis;
303
304 if (!lcdMis)
305 gic->clearInt(intNum);
306
307 break;
308 case LcdUpCurr:
309 panic("LCD register at offset %#x is Read-Only\n", daddr);
310 break;
311 case LcdLpCurr:
312 panic("LCD register at offset %#x is Read-Only\n", daddr);
313 break;
314 case ClcdCrsrCtrl:
315 clcdCrsrCtrl = data;
316 break;
317 case ClcdCrsrConfig:
318 clcdCrsrConfig = data;
319 break;
320 case ClcdCrsrPalette0:
321 clcdCrsrPalette0 = data;
322 break;
323 case ClcdCrsrPalette1:
324 clcdCrsrPalette1 = data;
325 break;
326 case ClcdCrsrXY:
327 clcdCrsrXY = data;
328 break;
329 case ClcdCrsrClip:
330 clcdCrsrClip = data;
331 break;
332 case ClcdCrsrImsc:
333 clcdCrsrImsc = data;
334 break;
335 case ClcdCrsrIcr:
336 clcdCrsrIcr = data;
337 break;
338 case ClcdCrsrRis:
339 panic("CLCD register at offset %#x is Read-Only\n", daddr);
340 break;
341 case ClcdCrsrMis:
342 panic("CLCD register at offset %#x is Read-Only\n", daddr);
343 break;
344 default:
345 if (daddr >= CrsrImage && daddr <= 0xBFC) {
346 // CURSOR IMAGE
347 int index;
348 index = (daddr - CrsrImage) >> 2;
349 cursorImage[index] = data;
350 break;
351 } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
352 // LCD Palette
353 int index;
354 index = (daddr - LcdPalette) >> 2;
355 lcdPalette[index] = data;
356 break;
357 } else {
358 panic("Tried to write PL111 register at offset %#x that \
359 doesn't exist\n", daddr);
360 break;
361 }
362 }
363
364 pkt->makeAtomicResponse();
365 return pioDelay;
366}
367
368void
369Pl111::updateVideoParams()
370{
371 if (lcdControl.lcdbpp == bpp24) {
372 bytesPerPixel = 4;
373 } else if (lcdControl.lcdbpp == bpp16m565) {
374 bytesPerPixel = 2;
375 }
376
377 if (vncserver) {
378 if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
379 vncserver->setFrameBufferParams(VideoConvert::bgr8888, width,
380 height);
381 else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
382 vncserver->setFrameBufferParams(VideoConvert::rgb8888, width,
383 height);
384 else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
385 vncserver->setFrameBufferParams(VideoConvert::bgr565, width,
386 height);
387 else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
388 vncserver->setFrameBufferParams(VideoConvert::rgb565, width,
389 height);
390 else
391 panic("Unimplemented video mode\n");
392 }
393
394 if (bmp)
395 delete bmp;
396
397 if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
398 bmp = new Bitmap(VideoConvert::bgr8888, width, height, dmaBuffer);
399 else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
400 bmp = new Bitmap(VideoConvert::rgb8888, width, height, dmaBuffer);
401 else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
402 bmp = new Bitmap(VideoConvert::bgr565, width, height, dmaBuffer);
403 else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
404 bmp = new Bitmap(VideoConvert::rgb565, width, height, dmaBuffer);
405 else
406 panic("Unimplemented video mode\n");
407}
408
409void
410Pl111::startDma()
411{
412 if (dmaPendingNum != 0 || readEvent.scheduled())
413 return;
414 readFramebuffer();
415}
416
417void
418Pl111::readFramebuffer()
419{
420 // initialization for dma read from frame buffer to dma buffer
421 uint32_t length = height * width;
422 if (startAddr != lcdUpbase)
423 startAddr = lcdUpbase;
424
425 // Updating base address, interrupt if we're supposed to
426 lcdRis.baseaddr = 1;
427 if (!intEvent.scheduled())
428 schedule(intEvent, nextCycle());
429
430 curAddr = 0;
431 startTime = curTick();
432
433 maxAddr = static_cast<Addr>(length * bytesPerPixel);
434
435 DPRINTF(PL111, " lcd frame buffer size of %d bytes \n", maxAddr);
436
437 dmaPendingNum = 0;
438
439 fillFifo();
440}
441
442void
443Pl111::fillFifo()
444{
445 while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) {
446 // concurrent dma reads need different dma done events
447 // due to assertion in scheduling state
448 ++dmaPendingNum;
449
450 assert(!dmaDoneEvent[dmaPendingNum-1].scheduled());
451
452 // We use a uncachable request here because the requests from the CPU
453 // will be uncacheable as well. If we have uncacheable and cacheable
454 // requests in the memory system for the same address it won't be
455 // pleased
456 dmaPort->dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize,
457 &dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer, 0,
458 Request::UNCACHEABLE);
459 curAddr += dmaSize;
460 }
461}
462
463void
464Pl111::dmaDone()
465{
466 Tick maxFrameTime = lcdTiming2.cpl * height * clock;
467
468 --dmaPendingNum;
469
470 if (maxAddr == curAddr && !dmaPendingNum) {
471 if ((curTick() - startTime) > maxFrameTime) {
472 warn("CLCD controller buffer underrun, took %d cycles when should"
473 " have taken %d\n", curTick() - startTime, maxFrameTime);
474 lcdRis.underflow = 1;
475 if (!intEvent.scheduled())
476 schedule(intEvent, nextCycle());
477 }
478
479 assert(!readEvent.scheduled());
480 if (vncserver)
481 vncserver->setDirty();
482
483 DPRINTF(PL111, "-- write out frame buffer into bmp\n");
484
485 assert(bmp);
486 pic->seekp(0);
487 bmp->write(pic);
488
489 DPRINTF(PL111, "-- schedule next dma read event at %d tick \n",
490 maxFrameTime + curTick());
491
492 if (lcdControl.lcden)
493 schedule(readEvent, nextCycle(startTime + maxFrameTime));
494 }
495
496 if (dmaPendingNum > (maxOutstandingDma - waterMark))
497 return;
498
499 if (!fillFifoEvent.scheduled())
500 schedule(fillFifoEvent, nextCycle());
501}
502
503
504Tick
505Pl111::nextCycle()
506{
507 Tick nextTick = curTick() + clock - 1;
508 nextTick -= nextTick%clock;
509 return nextTick;
510}
511
512Tick
513Pl111::nextCycle(Tick beginTick)
514{
515 Tick nextTick = beginTick;
516 if (nextTick%clock!=0)
517 nextTick = nextTick - (nextTick%clock) + clock;
518
519 assert(nextTick >= curTick());
520 return nextTick;
521}
522
523void
524Pl111::serialize(std::ostream &os)
525{
526 DPRINTF(PL111, "Serializing ARM PL111\n");
527
528 uint32_t lcdTiming0_serial = lcdTiming0;
529 SERIALIZE_SCALAR(lcdTiming0_serial);
530
531 uint32_t lcdTiming1_serial = lcdTiming1;
532 SERIALIZE_SCALAR(lcdTiming1_serial);
533
534 uint32_t lcdTiming2_serial = lcdTiming2;
535 SERIALIZE_SCALAR(lcdTiming2_serial);
536
537 uint32_t lcdTiming3_serial = lcdTiming3;
538 SERIALIZE_SCALAR(lcdTiming3_serial);
539
540 SERIALIZE_SCALAR(lcdUpbase);
541 SERIALIZE_SCALAR(lcdLpbase);
542
543 uint32_t lcdControl_serial = lcdControl;
544 SERIALIZE_SCALAR(lcdControl_serial);
545
546 uint8_t lcdImsc_serial = lcdImsc;
547 SERIALIZE_SCALAR(lcdImsc_serial);
548
549 uint8_t lcdRis_serial = lcdRis;
550 SERIALIZE_SCALAR(lcdRis_serial);
551
552 uint8_t lcdMis_serial = lcdMis;
553 SERIALIZE_SCALAR(lcdMis_serial);
554
555 SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
556 SERIALIZE_ARRAY(cursorImage, CrsrImageSize);
557
558 SERIALIZE_SCALAR(clcdCrsrCtrl);
559 SERIALIZE_SCALAR(clcdCrsrConfig);
560 SERIALIZE_SCALAR(clcdCrsrPalette0);
561 SERIALIZE_SCALAR(clcdCrsrPalette1);
562 SERIALIZE_SCALAR(clcdCrsrXY);
563 SERIALIZE_SCALAR(clcdCrsrClip);
564
565 uint8_t clcdCrsrImsc_serial = clcdCrsrImsc;
566 SERIALIZE_SCALAR(clcdCrsrImsc_serial);
567
568 uint8_t clcdCrsrIcr_serial = clcdCrsrIcr;
569 SERIALIZE_SCALAR(clcdCrsrIcr_serial);
570
571 uint8_t clcdCrsrRis_serial = clcdCrsrRis;
572 SERIALIZE_SCALAR(clcdCrsrRis_serial);
573
574 uint8_t clcdCrsrMis_serial = clcdCrsrMis;
575 SERIALIZE_SCALAR(clcdCrsrMis_serial);
576
577 SERIALIZE_SCALAR(clock);
578 SERIALIZE_SCALAR(height);
579 SERIALIZE_SCALAR(width);
580 SERIALIZE_SCALAR(bytesPerPixel);
581
582 SERIALIZE_ARRAY(dmaBuffer, height * width);
583 SERIALIZE_SCALAR(startTime);
584 SERIALIZE_SCALAR(startAddr);
585 SERIALIZE_SCALAR(maxAddr);
586 SERIALIZE_SCALAR(curAddr);
587 SERIALIZE_SCALAR(waterMark);
588 SERIALIZE_SCALAR(dmaPendingNum);
1/*
2 * Copyright (c) 2010 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
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
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.
24 *
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.
36 *
37 * Authors: William Wang
38 * Ali Saidi
39 */
40
41#include "base/bitmap.hh"
42#include "base/output.hh"
43#include "base/trace.hh"
44#include "base/vnc/vncserver.hh"
45#include "dev/arm/amba_device.hh"
46#include "dev/arm/gic.hh"
47#include "dev/arm/pl111.hh"
48#include "mem/packet.hh"
49#include "mem/packet_access.hh"
50
51using namespace AmbaDev;
52
53// initialize clcd registers
54Pl111::Pl111(const Params *p)
55 : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0),
56 lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0),
57 lcdRis(0), lcdMis(0),
58 clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
59 clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
60 clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), clock(p->clock),
61 vncserver(p->vnc), bmp(NULL), width(LcdMaxWidth), height(LcdMaxHeight),
62 bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
63 waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
64 dmaDoneEvent(maxOutstandingDma, this), intEvent(this)
65{
66 pioSize = 0xFFFF;
67
68 pic = simout.create("framebuffer.bmp", true);
69
70 dmaBuffer = new uint8_t[LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t)];
71
72 memset(lcdPalette, 0, sizeof(lcdPalette));
73 memset(cursorImage, 0, sizeof(cursorImage));
74 memset(dmaBuffer, 0, sizeof(dmaBuffer));
75
76 if (vncserver)
77 vncserver->setFramebufferAddr(dmaBuffer);
78}
79
80// read registers and frame buffer
81Tick
82Pl111::read(PacketPtr pkt)
83{
84 // use a temporary data since the LCD registers are read/written with
85 // different size operations
86
87 uint32_t data = 0;
88
89 assert(pkt->getAddr() >= pioAddr &&
90 pkt->getAddr() < pioAddr + pioSize);
91
92 Addr daddr = pkt->getAddr() - pioAddr;
93 pkt->allocate();
94
95 DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize());
96
97 switch (daddr) {
98 case LcdTiming0:
99 data = lcdTiming0;
100 break;
101 case LcdTiming1:
102 data = lcdTiming1;
103 break;
104 case LcdTiming2:
105 data = lcdTiming2;
106 break;
107 case LcdTiming3:
108 data = lcdTiming3;
109 break;
110 case LcdUpBase:
111 data = lcdUpbase;
112 break;
113 case LcdLpBase:
114 data = lcdLpbase;
115 break;
116 case LcdControl:
117 data = lcdControl;
118 break;
119 case LcdImsc:
120 data = lcdImsc;
121 break;
122 case LcdRis:
123 data = lcdRis;
124 break;
125 case LcdMis:
126 data = lcdMis;
127 break;
128 case LcdIcr:
129 panic("LCD register at offset %#x is Write-Only\n", daddr);
130 break;
131 case LcdUpCurr:
132 data = curAddr;
133 break;
134 case LcdLpCurr:
135 data = curAddr;
136 break;
137 case ClcdCrsrCtrl:
138 data = clcdCrsrCtrl;
139 break;
140 case ClcdCrsrConfig:
141 data = clcdCrsrConfig;
142 break;
143 case ClcdCrsrPalette0:
144 data = clcdCrsrPalette0;
145 break;
146 case ClcdCrsrPalette1:
147 data = clcdCrsrPalette1;
148 break;
149 case ClcdCrsrXY:
150 data = clcdCrsrXY;
151 break;
152 case ClcdCrsrClip:
153 data = clcdCrsrClip;
154 break;
155 case ClcdCrsrImsc:
156 data = clcdCrsrImsc;
157 break;
158 case ClcdCrsrIcr:
159 panic("CLCD register at offset %#x is Write-Only\n", daddr);
160 break;
161 case ClcdCrsrRis:
162 data = clcdCrsrRis;
163 break;
164 case ClcdCrsrMis:
165 data = clcdCrsrMis;
166 break;
167 default:
168 if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) {
169 // Hack for variable size accesses
170 data = pkt->get<uint32_t>();
171 break;
172 } else if (daddr >= CrsrImage && daddr <= 0xBFC) {
173 // CURSOR IMAGE
174 int index;
175 index = (daddr - CrsrImage) >> 2;
176 data= cursorImage[index];
177 break;
178 } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
179 // LCD Palette
180 int index;
181 index = (daddr - LcdPalette) >> 2;
182 data = lcdPalette[index];
183 break;
184 } else {
185 panic("Tried to read CLCD register at offset %#x that \
186 doesn't exist\n", daddr);
187 break;
188 }
189 }
190
191 switch(pkt->getSize()) {
192 case 1:
193 pkt->set<uint8_t>(data);
194 break;
195 case 2:
196 pkt->set<uint16_t>(data);
197 break;
198 case 4:
199 pkt->set<uint32_t>(data);
200 break;
201 default:
202 panic("CLCD controller read size too big?\n");
203 break;
204 }
205
206 pkt->makeAtomicResponse();
207 return pioDelay;
208}
209
210// write registers and frame buffer
211Tick
212Pl111::write(PacketPtr pkt)
213{
214 // use a temporary data since the LCD registers are read/written with
215 // different size operations
216 //
217 uint32_t data = 0;
218
219 switch(pkt->getSize()) {
220 case 1:
221 data = pkt->get<uint8_t>();
222 break;
223 case 2:
224 data = pkt->get<uint16_t>();
225 break;
226 case 4:
227 data = pkt->get<uint32_t>();
228 break;
229 default:
230 panic("PL111 CLCD controller write size too big?\n");
231 break;
232 }
233
234 assert(pkt->getAddr() >= pioAddr &&
235 pkt->getAddr() < pioAddr + pioSize);
236
237 Addr daddr = pkt->getAddr() - pioAddr;
238
239 DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr,
240 pkt->get<uint8_t>(), pkt->getSize());
241
242 switch (daddr) {
243 case LcdTiming0:
244 lcdTiming0 = data;
245 // width = 16 * (PPL+1)
246 width = (lcdTiming0.ppl + 1) << 4;
247 break;
248 case LcdTiming1:
249 lcdTiming1 = data;
250 // height = LPP + 1
251 height = (lcdTiming1.lpp) + 1;
252 break;
253 case LcdTiming2:
254 lcdTiming2 = data;
255 break;
256 case LcdTiming3:
257 lcdTiming3 = data;
258 break;
259 case LcdUpBase:
260 lcdUpbase = data;
261 DPRINTF(PL111, "####### Upper panel base set to: %#x #######\n", lcdUpbase);
262 break;
263 case LcdLpBase:
264 warn("LCD dual screen mode not supported\n");
265 lcdLpbase = data;
266 DPRINTF(PL111, "###### Lower panel base set to: %#x #######\n", lcdLpbase);
267 break;
268 case LcdControl:
269 int old_lcdpwr;
270 old_lcdpwr = lcdControl.lcdpwr;
271 lcdControl = data;
272
273 DPRINTF(PL111, "LCD power is:%d\n", lcdControl.lcdpwr);
274
275 // LCD power enable
276 if (lcdControl.lcdpwr && !old_lcdpwr) {
277 updateVideoParams();
278 DPRINTF(PL111, " lcd size: height %d width %d\n", height, width);
279 waterMark = lcdControl.watermark ? 8 : 4;
280 startDma();
281 }
282 break;
283 case LcdImsc:
284 lcdImsc = data;
285 if (lcdImsc.vcomp)
286 panic("Interrupting on vcomp not supported\n");
287
288 lcdMis = lcdImsc & lcdRis;
289
290 if (!lcdMis)
291 gic->clearInt(intNum);
292
293 break;
294 case LcdRis:
295 panic("LCD register at offset %#x is Read-Only\n", daddr);
296 break;
297 case LcdMis:
298 panic("LCD register at offset %#x is Read-Only\n", daddr);
299 break;
300 case LcdIcr:
301 lcdRis = lcdRis & ~data;
302 lcdMis = lcdImsc & lcdRis;
303
304 if (!lcdMis)
305 gic->clearInt(intNum);
306
307 break;
308 case LcdUpCurr:
309 panic("LCD register at offset %#x is Read-Only\n", daddr);
310 break;
311 case LcdLpCurr:
312 panic("LCD register at offset %#x is Read-Only\n", daddr);
313 break;
314 case ClcdCrsrCtrl:
315 clcdCrsrCtrl = data;
316 break;
317 case ClcdCrsrConfig:
318 clcdCrsrConfig = data;
319 break;
320 case ClcdCrsrPalette0:
321 clcdCrsrPalette0 = data;
322 break;
323 case ClcdCrsrPalette1:
324 clcdCrsrPalette1 = data;
325 break;
326 case ClcdCrsrXY:
327 clcdCrsrXY = data;
328 break;
329 case ClcdCrsrClip:
330 clcdCrsrClip = data;
331 break;
332 case ClcdCrsrImsc:
333 clcdCrsrImsc = data;
334 break;
335 case ClcdCrsrIcr:
336 clcdCrsrIcr = data;
337 break;
338 case ClcdCrsrRis:
339 panic("CLCD register at offset %#x is Read-Only\n", daddr);
340 break;
341 case ClcdCrsrMis:
342 panic("CLCD register at offset %#x is Read-Only\n", daddr);
343 break;
344 default:
345 if (daddr >= CrsrImage && daddr <= 0xBFC) {
346 // CURSOR IMAGE
347 int index;
348 index = (daddr - CrsrImage) >> 2;
349 cursorImage[index] = data;
350 break;
351 } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
352 // LCD Palette
353 int index;
354 index = (daddr - LcdPalette) >> 2;
355 lcdPalette[index] = data;
356 break;
357 } else {
358 panic("Tried to write PL111 register at offset %#x that \
359 doesn't exist\n", daddr);
360 break;
361 }
362 }
363
364 pkt->makeAtomicResponse();
365 return pioDelay;
366}
367
368void
369Pl111::updateVideoParams()
370{
371 if (lcdControl.lcdbpp == bpp24) {
372 bytesPerPixel = 4;
373 } else if (lcdControl.lcdbpp == bpp16m565) {
374 bytesPerPixel = 2;
375 }
376
377 if (vncserver) {
378 if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
379 vncserver->setFrameBufferParams(VideoConvert::bgr8888, width,
380 height);
381 else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
382 vncserver->setFrameBufferParams(VideoConvert::rgb8888, width,
383 height);
384 else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
385 vncserver->setFrameBufferParams(VideoConvert::bgr565, width,
386 height);
387 else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
388 vncserver->setFrameBufferParams(VideoConvert::rgb565, width,
389 height);
390 else
391 panic("Unimplemented video mode\n");
392 }
393
394 if (bmp)
395 delete bmp;
396
397 if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
398 bmp = new Bitmap(VideoConvert::bgr8888, width, height, dmaBuffer);
399 else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
400 bmp = new Bitmap(VideoConvert::rgb8888, width, height, dmaBuffer);
401 else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
402 bmp = new Bitmap(VideoConvert::bgr565, width, height, dmaBuffer);
403 else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
404 bmp = new Bitmap(VideoConvert::rgb565, width, height, dmaBuffer);
405 else
406 panic("Unimplemented video mode\n");
407}
408
409void
410Pl111::startDma()
411{
412 if (dmaPendingNum != 0 || readEvent.scheduled())
413 return;
414 readFramebuffer();
415}
416
417void
418Pl111::readFramebuffer()
419{
420 // initialization for dma read from frame buffer to dma buffer
421 uint32_t length = height * width;
422 if (startAddr != lcdUpbase)
423 startAddr = lcdUpbase;
424
425 // Updating base address, interrupt if we're supposed to
426 lcdRis.baseaddr = 1;
427 if (!intEvent.scheduled())
428 schedule(intEvent, nextCycle());
429
430 curAddr = 0;
431 startTime = curTick();
432
433 maxAddr = static_cast<Addr>(length * bytesPerPixel);
434
435 DPRINTF(PL111, " lcd frame buffer size of %d bytes \n", maxAddr);
436
437 dmaPendingNum = 0;
438
439 fillFifo();
440}
441
442void
443Pl111::fillFifo()
444{
445 while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) {
446 // concurrent dma reads need different dma done events
447 // due to assertion in scheduling state
448 ++dmaPendingNum;
449
450 assert(!dmaDoneEvent[dmaPendingNum-1].scheduled());
451
452 // We use a uncachable request here because the requests from the CPU
453 // will be uncacheable as well. If we have uncacheable and cacheable
454 // requests in the memory system for the same address it won't be
455 // pleased
456 dmaPort->dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize,
457 &dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer, 0,
458 Request::UNCACHEABLE);
459 curAddr += dmaSize;
460 }
461}
462
463void
464Pl111::dmaDone()
465{
466 Tick maxFrameTime = lcdTiming2.cpl * height * clock;
467
468 --dmaPendingNum;
469
470 if (maxAddr == curAddr && !dmaPendingNum) {
471 if ((curTick() - startTime) > maxFrameTime) {
472 warn("CLCD controller buffer underrun, took %d cycles when should"
473 " have taken %d\n", curTick() - startTime, maxFrameTime);
474 lcdRis.underflow = 1;
475 if (!intEvent.scheduled())
476 schedule(intEvent, nextCycle());
477 }
478
479 assert(!readEvent.scheduled());
480 if (vncserver)
481 vncserver->setDirty();
482
483 DPRINTF(PL111, "-- write out frame buffer into bmp\n");
484
485 assert(bmp);
486 pic->seekp(0);
487 bmp->write(pic);
488
489 DPRINTF(PL111, "-- schedule next dma read event at %d tick \n",
490 maxFrameTime + curTick());
491
492 if (lcdControl.lcden)
493 schedule(readEvent, nextCycle(startTime + maxFrameTime));
494 }
495
496 if (dmaPendingNum > (maxOutstandingDma - waterMark))
497 return;
498
499 if (!fillFifoEvent.scheduled())
500 schedule(fillFifoEvent, nextCycle());
501}
502
503
504Tick
505Pl111::nextCycle()
506{
507 Tick nextTick = curTick() + clock - 1;
508 nextTick -= nextTick%clock;
509 return nextTick;
510}
511
512Tick
513Pl111::nextCycle(Tick beginTick)
514{
515 Tick nextTick = beginTick;
516 if (nextTick%clock!=0)
517 nextTick = nextTick - (nextTick%clock) + clock;
518
519 assert(nextTick >= curTick());
520 return nextTick;
521}
522
523void
524Pl111::serialize(std::ostream &os)
525{
526 DPRINTF(PL111, "Serializing ARM PL111\n");
527
528 uint32_t lcdTiming0_serial = lcdTiming0;
529 SERIALIZE_SCALAR(lcdTiming0_serial);
530
531 uint32_t lcdTiming1_serial = lcdTiming1;
532 SERIALIZE_SCALAR(lcdTiming1_serial);
533
534 uint32_t lcdTiming2_serial = lcdTiming2;
535 SERIALIZE_SCALAR(lcdTiming2_serial);
536
537 uint32_t lcdTiming3_serial = lcdTiming3;
538 SERIALIZE_SCALAR(lcdTiming3_serial);
539
540 SERIALIZE_SCALAR(lcdUpbase);
541 SERIALIZE_SCALAR(lcdLpbase);
542
543 uint32_t lcdControl_serial = lcdControl;
544 SERIALIZE_SCALAR(lcdControl_serial);
545
546 uint8_t lcdImsc_serial = lcdImsc;
547 SERIALIZE_SCALAR(lcdImsc_serial);
548
549 uint8_t lcdRis_serial = lcdRis;
550 SERIALIZE_SCALAR(lcdRis_serial);
551
552 uint8_t lcdMis_serial = lcdMis;
553 SERIALIZE_SCALAR(lcdMis_serial);
554
555 SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
556 SERIALIZE_ARRAY(cursorImage, CrsrImageSize);
557
558 SERIALIZE_SCALAR(clcdCrsrCtrl);
559 SERIALIZE_SCALAR(clcdCrsrConfig);
560 SERIALIZE_SCALAR(clcdCrsrPalette0);
561 SERIALIZE_SCALAR(clcdCrsrPalette1);
562 SERIALIZE_SCALAR(clcdCrsrXY);
563 SERIALIZE_SCALAR(clcdCrsrClip);
564
565 uint8_t clcdCrsrImsc_serial = clcdCrsrImsc;
566 SERIALIZE_SCALAR(clcdCrsrImsc_serial);
567
568 uint8_t clcdCrsrIcr_serial = clcdCrsrIcr;
569 SERIALIZE_SCALAR(clcdCrsrIcr_serial);
570
571 uint8_t clcdCrsrRis_serial = clcdCrsrRis;
572 SERIALIZE_SCALAR(clcdCrsrRis_serial);
573
574 uint8_t clcdCrsrMis_serial = clcdCrsrMis;
575 SERIALIZE_SCALAR(clcdCrsrMis_serial);
576
577 SERIALIZE_SCALAR(clock);
578 SERIALIZE_SCALAR(height);
579 SERIALIZE_SCALAR(width);
580 SERIALIZE_SCALAR(bytesPerPixel);
581
582 SERIALIZE_ARRAY(dmaBuffer, height * width);
583 SERIALIZE_SCALAR(startTime);
584 SERIALIZE_SCALAR(startAddr);
585 SERIALIZE_SCALAR(maxAddr);
586 SERIALIZE_SCALAR(curAddr);
587 SERIALIZE_SCALAR(waterMark);
588 SERIALIZE_SCALAR(dmaPendingNum);
589
590 Tick int_event_time = 0;
591 Tick read_event_time = 0;
592 Tick fill_fifo_event_time = 0;
593
594 if (readEvent.scheduled())
595 read_event_time = readEvent.when();
596 if (fillFifoEvent.scheduled())
597 fill_fifo_event_time = fillFifoEvent.when();
598 if (intEvent.scheduled())
599 int_event_time = intEvent.when();
600
601 SERIALIZE_SCALAR(read_event_time);
602 SERIALIZE_SCALAR(fill_fifo_event_time);
603 SERIALIZE_SCALAR(int_event_time);
604
605 vector<Tick> dma_done_event_tick;
606 dma_done_event_tick.resize(maxOutstandingDma);
607 for (int x = 0; x < maxOutstandingDma; x++) {
608 dma_done_event_tick[x] = dmaDoneEvent[x].scheduled() ?
609 dmaDoneEvent[x].when() : 0;
610 }
611 arrayParamOut(os, "dma_done_event_tick", dma_done_event_tick);
589}
590
591void
592Pl111::unserialize(Checkpoint *cp, const std::string &section)
593{
594 DPRINTF(PL111, "Unserializing ARM PL111\n");
595
596 uint32_t lcdTiming0_serial;
597 UNSERIALIZE_SCALAR(lcdTiming0_serial);
598 lcdTiming0 = lcdTiming0_serial;
599
600 uint32_t lcdTiming1_serial;
601 UNSERIALIZE_SCALAR(lcdTiming1_serial);
602 lcdTiming1 = lcdTiming1_serial;
603
604 uint32_t lcdTiming2_serial;
605 UNSERIALIZE_SCALAR(lcdTiming2_serial);
606 lcdTiming2 = lcdTiming2_serial;
607
608 uint32_t lcdTiming3_serial;
609 UNSERIALIZE_SCALAR(lcdTiming3_serial);
610 lcdTiming3 = lcdTiming3_serial;
611
612 UNSERIALIZE_SCALAR(lcdUpbase);
613 UNSERIALIZE_SCALAR(lcdLpbase);
614
615 uint32_t lcdControl_serial;
616 UNSERIALIZE_SCALAR(lcdControl_serial);
617 lcdControl = lcdControl_serial;
618
619 uint8_t lcdImsc_serial;
620 UNSERIALIZE_SCALAR(lcdImsc_serial);
621 lcdImsc = lcdImsc_serial;
622
623 uint8_t lcdRis_serial;
624 UNSERIALIZE_SCALAR(lcdRis_serial);
625 lcdRis = lcdRis_serial;
626
627 uint8_t lcdMis_serial;
628 UNSERIALIZE_SCALAR(lcdMis_serial);
629 lcdMis = lcdMis_serial;
630
631 UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
632 UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize);
633
634 UNSERIALIZE_SCALAR(clcdCrsrCtrl);
635 UNSERIALIZE_SCALAR(clcdCrsrConfig);
636 UNSERIALIZE_SCALAR(clcdCrsrPalette0);
637 UNSERIALIZE_SCALAR(clcdCrsrPalette1);
638 UNSERIALIZE_SCALAR(clcdCrsrXY);
639 UNSERIALIZE_SCALAR(clcdCrsrClip);
640
641 uint8_t clcdCrsrImsc_serial;
642 UNSERIALIZE_SCALAR(clcdCrsrImsc_serial);
643 clcdCrsrImsc = clcdCrsrImsc_serial;
644
645 uint8_t clcdCrsrIcr_serial;
646 UNSERIALIZE_SCALAR(clcdCrsrIcr_serial);
647 clcdCrsrIcr = clcdCrsrIcr_serial;
648
649 uint8_t clcdCrsrRis_serial;
650 UNSERIALIZE_SCALAR(clcdCrsrRis_serial);
651 clcdCrsrRis = clcdCrsrRis_serial;
652
653 uint8_t clcdCrsrMis_serial;
654 UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
655 clcdCrsrMis = clcdCrsrMis_serial;
656
657 UNSERIALIZE_SCALAR(clock);
658 UNSERIALIZE_SCALAR(height);
659 UNSERIALIZE_SCALAR(width);
660 UNSERIALIZE_SCALAR(bytesPerPixel);
661
662 UNSERIALIZE_ARRAY(dmaBuffer, height * width);
663 UNSERIALIZE_SCALAR(startTime);
664 UNSERIALIZE_SCALAR(startAddr);
665 UNSERIALIZE_SCALAR(maxAddr);
666 UNSERIALIZE_SCALAR(curAddr);
667 UNSERIALIZE_SCALAR(waterMark);
668 UNSERIALIZE_SCALAR(dmaPendingNum);
669
612}
613
614void
615Pl111::unserialize(Checkpoint *cp, const std::string &section)
616{
617 DPRINTF(PL111, "Unserializing ARM PL111\n");
618
619 uint32_t lcdTiming0_serial;
620 UNSERIALIZE_SCALAR(lcdTiming0_serial);
621 lcdTiming0 = lcdTiming0_serial;
622
623 uint32_t lcdTiming1_serial;
624 UNSERIALIZE_SCALAR(lcdTiming1_serial);
625 lcdTiming1 = lcdTiming1_serial;
626
627 uint32_t lcdTiming2_serial;
628 UNSERIALIZE_SCALAR(lcdTiming2_serial);
629 lcdTiming2 = lcdTiming2_serial;
630
631 uint32_t lcdTiming3_serial;
632 UNSERIALIZE_SCALAR(lcdTiming3_serial);
633 lcdTiming3 = lcdTiming3_serial;
634
635 UNSERIALIZE_SCALAR(lcdUpbase);
636 UNSERIALIZE_SCALAR(lcdLpbase);
637
638 uint32_t lcdControl_serial;
639 UNSERIALIZE_SCALAR(lcdControl_serial);
640 lcdControl = lcdControl_serial;
641
642 uint8_t lcdImsc_serial;
643 UNSERIALIZE_SCALAR(lcdImsc_serial);
644 lcdImsc = lcdImsc_serial;
645
646 uint8_t lcdRis_serial;
647 UNSERIALIZE_SCALAR(lcdRis_serial);
648 lcdRis = lcdRis_serial;
649
650 uint8_t lcdMis_serial;
651 UNSERIALIZE_SCALAR(lcdMis_serial);
652 lcdMis = lcdMis_serial;
653
654 UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
655 UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize);
656
657 UNSERIALIZE_SCALAR(clcdCrsrCtrl);
658 UNSERIALIZE_SCALAR(clcdCrsrConfig);
659 UNSERIALIZE_SCALAR(clcdCrsrPalette0);
660 UNSERIALIZE_SCALAR(clcdCrsrPalette1);
661 UNSERIALIZE_SCALAR(clcdCrsrXY);
662 UNSERIALIZE_SCALAR(clcdCrsrClip);
663
664 uint8_t clcdCrsrImsc_serial;
665 UNSERIALIZE_SCALAR(clcdCrsrImsc_serial);
666 clcdCrsrImsc = clcdCrsrImsc_serial;
667
668 uint8_t clcdCrsrIcr_serial;
669 UNSERIALIZE_SCALAR(clcdCrsrIcr_serial);
670 clcdCrsrIcr = clcdCrsrIcr_serial;
671
672 uint8_t clcdCrsrRis_serial;
673 UNSERIALIZE_SCALAR(clcdCrsrRis_serial);
674 clcdCrsrRis = clcdCrsrRis_serial;
675
676 uint8_t clcdCrsrMis_serial;
677 UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
678 clcdCrsrMis = clcdCrsrMis_serial;
679
680 UNSERIALIZE_SCALAR(clock);
681 UNSERIALIZE_SCALAR(height);
682 UNSERIALIZE_SCALAR(width);
683 UNSERIALIZE_SCALAR(bytesPerPixel);
684
685 UNSERIALIZE_ARRAY(dmaBuffer, height * width);
686 UNSERIALIZE_SCALAR(startTime);
687 UNSERIALIZE_SCALAR(startAddr);
688 UNSERIALIZE_SCALAR(maxAddr);
689 UNSERIALIZE_SCALAR(curAddr);
690 UNSERIALIZE_SCALAR(waterMark);
691 UNSERIALIZE_SCALAR(dmaPendingNum);
692
693 Tick int_event_time = 0;
694 Tick read_event_time = 0;
695 Tick fill_fifo_event_time = 0;
696
697 UNSERIALIZE_SCALAR(read_event_time);
698 UNSERIALIZE_SCALAR(fill_fifo_event_time);
699 UNSERIALIZE_SCALAR(int_event_time);
700
701 if (int_event_time)
702 schedule(intEvent, int_event_time);
703 if (read_event_time)
704 schedule(readEvent, read_event_time);
705 if (fill_fifo_event_time)
706 schedule(fillFifoEvent, fill_fifo_event_time);
707
708 vector<Tick> dma_done_event_tick;
709 dma_done_event_tick.resize(maxOutstandingDma);
710 arrayParamIn(cp, section, "dma_done_event_tick", dma_done_event_tick);
711 for (int x = 0; x < maxOutstandingDma; x++) {
712 if (dma_done_event_tick[x])
713 schedule(dmaDoneEvent[x], dma_done_event_tick[x]);
714 }
715
670 updateVideoParams();
671 if (vncserver)
672 vncserver->setDirty();
673}
674
675void
676Pl111::generateInterrupt()
677{
678 DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
679 (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis);
680 lcdMis = lcdImsc & lcdRis;
681
682 if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) {
683 gic->sendInt(intNum);
684 DPRINTF(PL111, " -- Generated\n");
685 }
686}
687
688void
689Pl111::addressRanges(AddrRangeList& range_list)
690{
691 range_list.clear();
692 range_list.push_back(RangeSize(pioAddr, pioSize));
693}
694
695Pl111 *
696Pl111Params::create()
697{
698 return new Pl111(this);
699}
700
701
716 updateVideoParams();
717 if (vncserver)
718 vncserver->setDirty();
719}
720
721void
722Pl111::generateInterrupt()
723{
724 DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
725 (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis);
726 lcdMis = lcdImsc & lcdRis;
727
728 if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) {
729 gic->sendInt(intNum);
730 DPRINTF(PL111, " -- Generated\n");
731 }
732}
733
734void
735Pl111::addressRanges(AddrRangeList& range_list)
736{
737 range_list.clear();
738 range_list.push_back(RangeSize(pioAddr, pioSize));
739}
740
741Pl111 *
742Pl111Params::create()
743{
744 return new Pl111(this);
745}
746
747