1/* 2 * Copyright (c) 2010-2013, 2015, 2017 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: Chris Emmons 38 * Andreas Sandberg 39 */ 40 41 42/** @file 43 * Implementiation of the ARM HDLcd controller. 44 * 45 * This implementation aims to have sufficient detail such that underrun 46 * conditions are reasonable / behave similar to reality. There are two 47 * 'engines' going at once. First, the DMA engine running at LCD clock 48 * frequency is responsible for filling the controller's internal buffer. 49 * The second engine runs at the pixel clock frequency and reads the pixels 50 * out of the internal buffer. The pixel rendering engine uses front / back 51 * porch and sync delays between lines and frames. 52 * 53 * If the pixel rendering engine does not have a pixel to display, it will 54 * cause an underrun event. The HDLcd controller, per spec, will stop 55 * issuing DMA requests for the rest of the frame and resume normal behavior 56 * on the subsequent frame. What pixels are rendered upon an underrun 57 * condition is different than the real hardware; while the user will see 58 * artifacts (previous frame mixed with current frame), it is not the same 59 * behavior as real hardware which repeats the last pixel value for the rest 60 * of the current frame. This compromise was made to save on memory and 61 * complexity and assumes that it is not important to accurately model the 62 * content of an underrun frame. 63 * 64 * KNOWN ISSUES 65 * <ul> 66 * <li>The HDLcd is implemented here as an AmbaDmaDevice, but it 67 * doesn't have an AMBA ID as far as I know. That is the only 68 * bit of the AmbaDmaDevice interface that is irrelevant to it, 69 * so a fake AMBA ID is used for now. I didn't think inserting 70 * an extra layer of hierachy between AmbaDmaDevice and 71 * DmaDevice would be helpful to anyone else, but that may be 72 * the right answer. 73 * </ul> 74 */ 75 76#ifndef __DEV_ARM_HDLCD_HH__ 77#define __DEV_ARM_HDLCD_HH__ 78 79#include <fstream> 80#include <memory> 81 82#include "base/framebuffer.hh" 83#include "base/imgwriter.hh" 84#include "base/output.hh" 85#include "dev/arm/amba_device.hh" 86#include "dev/pixelpump.hh" 87#include "sim/serialize.hh" 88 89class VncInput; 90struct HDLcdParams; 91class HDLcdPixelPump; 92 93class HDLcd: public AmbaDmaDevice 94{ 95 public: 96 HDLcd(const HDLcdParams *p); 97 ~HDLcd(); 98 99 void regStats() override; 100 101 void serialize(CheckpointOut &cp) const override; 102 void unserialize(CheckpointIn &cp) override; 103 104 void drainResume() override; 105 106 public: // IO device interface 107 Tick read(PacketPtr pkt) override; 108 Tick write(PacketPtr pkt) override; 109 110 AddrRangeList getAddrRanges() const override { return addrRanges; } 111 112 protected: // Parameters 113 VncInput *vnc; 114 const bool workaroundSwapRB; 115 const bool workaroundDmaLineCount; 116 const AddrRangeList addrRanges; 117 const bool enableCapture; 118 const Addr pixelBufferSize; 119 const Tick virtRefreshRate; 120 121 protected: // Register handling 122 /** ARM HDLcd register offsets */ 123 enum RegisterOffset { 124 Version = 0x0000, 125 Int_RawStat = 0x0010, 126 Int_Clear = 0x0014, 127 Int_Mask = 0x0018, 128 Int_Status = 0x001C, 129 Fb_Base = 0x0100, 130 Fb_Line_Length = 0x0104, 131 Fb_Line_Count = 0x0108, 132 Fb_Line_Pitch = 0x010C, 133 Bus_Options = 0x0110, 134 V_Sync = 0x0200, 135 V_Back_Porch = 0x0204, 136 V_Data = 0x0208, 137 V_Front_Porch = 0x020C, 138 H_Sync = 0x0210, 139 H_Back_Porch = 0x0214, 140 H_Data = 0x0218, 141 H_Front_Porch = 0x021C, 142 Polarities = 0x0220, 143 Command = 0x0230, 144 Pixel_Format = 0x0240, 145 Red_Select = 0x0244, 146 Green_Select = 0x0248, 147 Blue_Select = 0x024C, 148 }; 149 150 /** Reset value for Bus_Options register */ 151 static constexpr size_t BUS_OPTIONS_RESETV = 0x408; 152 153 /** Reset value for Version register */ 154 static constexpr size_t VERSION_RESETV = 0x1CDC0000; 155 156 /** AXI port width in bytes */ 157 static constexpr size_t AXI_PORT_WIDTH = 8; 158 159 /** max number of beats delivered in one dma burst */ 160 static constexpr size_t MAX_BURST_LEN = 16; 161 162 /** Maximum number of bytes per pixel */ 163 static constexpr size_t MAX_PIXEL_SIZE = 4; 164 165 /** 166 * @name RegisterFieldLayouts 167 * Bit layout declarations for multi-field registers. 168 */ 169 /**@{*/ 170 BitUnion32(VersionReg) 171 Bitfield<7,0> version_minor; 172 Bitfield<15,8> version_major; 173 Bitfield<31,16> product_id; 174 EndBitUnion(VersionReg) 175 176 static constexpr uint32_t INT_DMA_END = (1UL << 0); 177 static constexpr uint32_t INT_BUS_ERROR = (1UL << 1); 178 static constexpr uint32_t INT_VSYNC = (1UL << 2); 179 static constexpr uint32_t INT_UNDERRUN = (1UL << 3); 180 181 BitUnion32(FbLineCountReg) 182 Bitfield<11,0> fb_line_count; 183 Bitfield<31,12> reserved_31_12; 184 EndBitUnion(FbLineCountReg) 185 186 BitUnion32(BusOptsReg) 187 Bitfield<4,0> burst_len; 188 Bitfield<7,5> reserved_7_5; 189 Bitfield<11,8> max_outstanding; 190 Bitfield<31,12> reserved_31_12; 191 EndBitUnion(BusOptsReg) 192 193 BitUnion32(TimingReg) 194 Bitfield<11,0> val; 195 Bitfield<31,12> reserved_31_12; 196 EndBitUnion(TimingReg) 197 198 BitUnion32(PolaritiesReg) 199 Bitfield<0> vsync_polarity; 200 Bitfield<1> hsync_polarity; 201 Bitfield<2> dataen_polarity; 202 Bitfield<3> data_polarity; 203 Bitfield<4> pxlclk_polarity; 204 Bitfield<31,5> reserved_31_5; 205 EndBitUnion(PolaritiesReg) 206 207 BitUnion32(CommandReg) 208 Bitfield<0> enable; 209 Bitfield<31,1> reserved_31_1; 210 EndBitUnion(CommandReg) 211 212 BitUnion32(PixelFormatReg) 213 Bitfield<2,0> reserved_2_0; 214 Bitfield<4,3> bytes_per_pixel; 215 Bitfield<30,5> reserved_30_5; 216 Bitfield<31> big_endian; 217 EndBitUnion(PixelFormatReg) 218 219 BitUnion32(ColorSelectReg) 220 Bitfield<4,0> offset; 221 Bitfield<7,5> reserved_7_5; 222 Bitfield<11,8> size; 223 Bitfield<15,12> reserved_15_12; 224 Bitfield<23,16> default_color; 225 Bitfield<31,24> reserved_31_24; 226 EndBitUnion(ColorSelectReg) 227 /**@}*/ 228 229 /** 230 * @name HDLCDRegisters 231 * HDLCD register contents. 232 */ 233 /**@{*/ 234 const VersionReg version; /**< Version register */ 235 uint32_t int_rawstat; /**< Interrupt raw status register */ 236 uint32_t int_mask; /**< Interrupt mask register */ 237 uint32_t fb_base; /**< Frame buffer base address register */ 238 uint32_t fb_line_length; /**< Frame buffer Line length register */ 239 FbLineCountReg fb_line_count; /**< Frame buffer Line count register */ 240 int32_t fb_line_pitch; /**< Frame buffer Line pitch register */ 241 BusOptsReg bus_options; /**< Bus options register */ 242 TimingReg v_sync; /**< Vertical sync width register */ 243 TimingReg v_back_porch; /**< Vertical back porch width register */ 244 TimingReg v_data; /**< Vertical data width register */ 245 TimingReg v_front_porch; /**< Vertical front porch width register */ 246 TimingReg h_sync; /**< Horizontal sync width register */ 247 TimingReg h_back_porch; /**< Horizontal back porch width register */ 248 TimingReg h_data; /**< Horizontal data width register */ 249 TimingReg h_front_porch; /**< Horizontal front porch width reg */ 250 PolaritiesReg polarities; /**< Polarities register */ 251 CommandReg command; /**< Command register */ 252 PixelFormatReg pixel_format; /**< Pixel format register */ 253 ColorSelectReg red_select; /**< Red color select register */ 254 ColorSelectReg green_select; /**< Green color select register */ 255 ColorSelectReg blue_select; /**< Blue color select register */ 256 /** @} */ 257 258 uint32_t readReg(Addr offset); 259 void writeReg(Addr offset, uint32_t value); 260 261 PixelConverter pixelConverter() const; 262 DisplayTimings displayTimings() const; 263 264 void createDmaEngine(); 265 266 void cmdEnable(); 267 void cmdDisable(); 268 269 bool enabled() const { return command.enable; } 270 271 public: // Pixel pump callbacks 272 bool pxlNext(Pixel &p); 273 void pxlVSyncBegin(); 274 void pxlVSyncEnd(); 275 void pxlUnderrun(); 276 void pxlFrameDone(); 277 278 protected: // Interrupt handling 279 /** 280 * Assign new interrupt values and update interrupt signals 281 * 282 * A new interrupt is scheduled signalled if the set of unmasked 283 * interrupts goes empty to non-empty. Conversely, if the set of 284 * unmasked interrupts goes from non-empty to empty, the interrupt 285 * signal is cleared. 286 * 287 * @param ints New <i>raw</i> interrupt status 288 * @param mask New interrupt mask 289 */ 290 void setInterrupts(uint32_t ints, uint32_t mask); 291 292 /** 293 * Convenience function to update the interrupt mask 294 * 295 * @see setInterrupts 296 * @param mask New interrupt mask 297 */ 298 void intMask(uint32_t mask) { setInterrupts(int_rawstat, mask); } 299 300 /** 301 * Convenience function to raise a new interrupt 302 * 303 * @see setInterrupts 304 * @param ints Set of interrupts to raise 305 */ 306 void intRaise(uint32_t ints) { 307 setInterrupts(int_rawstat | ints, int_mask); 308 } 309 310 /** 311 * Convenience function to clear interrupts 312 * 313 * @see setInterrupts 314 * @param ints Set of interrupts to clear 315 */ 316 void intClear(uint32_t ints) { 317 setInterrupts(int_rawstat & ~ints, int_mask); 318 } 319 320 /** Masked interrupt status register */ 321 uint32_t intStatus() const { return int_rawstat & int_mask; } 322 323 protected: // Pixel output 324 class PixelPump : public BasePixelPump 325 { 326 public: 327 PixelPump(HDLcd &p, ClockDomain &pxl_clk, unsigned pixel_chunk) 328 : BasePixelPump(p, pxl_clk, pixel_chunk), parent(p) {} 329 330 void dumpSettings(); 331 332 protected: 333 bool nextPixel(Pixel &p) override { return parent.pxlNext(p); } 334 335 void onVSyncBegin() override { return parent.pxlVSyncBegin(); } 336 void onVSyncEnd() override { return parent.pxlVSyncEnd(); } 337 338 void onUnderrun(unsigned x, unsigned y) override { 339 parent.pxlUnderrun(); 340 } 341 342 void onFrameDone() override { parent.pxlFrameDone(); } 343 344 protected: 345 HDLcd &parent; 346 }; 347 348 /** Handler for fast frame refresh in KVM-mode */ 349 void virtRefresh(); 350 EventFunctionWrapper virtRefreshEvent; 351 352 /** Helper to write out bitmaps */ 353 std::unique_ptr<ImgWriter> imgWriter; 354 355 /** Image Format */ 356 Enums::ImageFormat imgFormat; 357 358 /** Picture of what the current frame buffer looks like */ 359 OutputStream *pic; 360 361 /** Cached pixel converter, set when the converter is enabled. */ 362 PixelConverter conv; 363 364 PixelPump pixelPump; 365 366 protected: // DMA handling 367 class DmaEngine : public DmaReadFifo 368 { 369 public: 370 DmaEngine(HDLcd &_parent, size_t size, 371 unsigned request_size, unsigned max_pending, 372 size_t line_size, ssize_t line_pitch, unsigned num_lines); 373 374 void startFrame(Addr fb_base); 375 void abortFrame(); 376 void dumpSettings(); 377 378 void serialize(CheckpointOut &cp) const override; 379 void unserialize(CheckpointIn &cp) override; 380 381 protected: 382 void onEndOfBlock() override; 383 void onIdle() override; 384 385 HDLcd &parent; 386 const size_t lineSize; 387 const ssize_t linePitch; 388 const unsigned numLines; 389 390 Addr nextLineAddr; 391 Addr frameEnd; 392 }; 393 394 std::unique_ptr<DmaEngine> dmaEngine; 395 396 protected: // Statistics 397 struct { 398 Stats::Scalar underruns; 399 } stats; 400}; 401 402#endif 403