hdlcd.hh revision 10839
19646SChris.Emmons@arm.com/*
210839Sandreas.sandberg@arm.com * Copyright (c) 2010-2013, 2015 ARM Limited
39646SChris.Emmons@arm.com * All rights reserved
49646SChris.Emmons@arm.com *
59646SChris.Emmons@arm.com * The license below extends only to copyright in the software and shall
69646SChris.Emmons@arm.com * not be construed as granting a license to any other intellectual
79646SChris.Emmons@arm.com * property including but not limited to intellectual property relating
89646SChris.Emmons@arm.com * to a hardware implementation of the functionality of the software
99646SChris.Emmons@arm.com * licensed hereunder.  You may use the software subject to the license
109646SChris.Emmons@arm.com * terms below provided that you ensure that this notice is replicated
119646SChris.Emmons@arm.com * unmodified and in its entirety in all distributions of the software,
129646SChris.Emmons@arm.com * modified or unmodified, in source code or in binary form.
139646SChris.Emmons@arm.com *
149646SChris.Emmons@arm.com * Redistribution and use in source and binary forms, with or without
159646SChris.Emmons@arm.com * modification, are permitted provided that the following conditions are
169646SChris.Emmons@arm.com * met: redistributions of source code must retain the above copyright
179646SChris.Emmons@arm.com * notice, this list of conditions and the following disclaimer;
189646SChris.Emmons@arm.com * redistributions in binary form must reproduce the above copyright
199646SChris.Emmons@arm.com * notice, this list of conditions and the following disclaimer in the
209646SChris.Emmons@arm.com * documentation and/or other materials provided with the distribution;
219646SChris.Emmons@arm.com * neither the name of the copyright holders nor the names of its
229646SChris.Emmons@arm.com * contributors may be used to endorse or promote products derived from
239646SChris.Emmons@arm.com * this software without specific prior written permission.
249646SChris.Emmons@arm.com *
259646SChris.Emmons@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
269646SChris.Emmons@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
279646SChris.Emmons@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
289646SChris.Emmons@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
299646SChris.Emmons@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
309646SChris.Emmons@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
319646SChris.Emmons@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
329646SChris.Emmons@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
339646SChris.Emmons@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
349646SChris.Emmons@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
359646SChris.Emmons@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
369646SChris.Emmons@arm.com *
379646SChris.Emmons@arm.com * Authors: Chris Emmons
389646SChris.Emmons@arm.com */
399646SChris.Emmons@arm.com
409646SChris.Emmons@arm.com
419646SChris.Emmons@arm.com/** @file
429646SChris.Emmons@arm.com * Implementiation of the ARM HDLcd controller.
439646SChris.Emmons@arm.com *
449646SChris.Emmons@arm.com * This implementation aims to have sufficient detail such that underrun
459646SChris.Emmons@arm.com * conditions are reasonable / behave similar to reality.  There are two
469646SChris.Emmons@arm.com * 'engines' going at once.  First, the DMA engine running at LCD clock
479646SChris.Emmons@arm.com * frequency is responsible for filling the controller's internal buffer.
489646SChris.Emmons@arm.com * The second engine runs at the pixel clock frequency and reads the pixels
499646SChris.Emmons@arm.com * out of the internal buffer.  The pixel rendering engine uses front / back
509646SChris.Emmons@arm.com * porch and sync delays between lines and frames.
519646SChris.Emmons@arm.com *
529646SChris.Emmons@arm.com * If the pixel rendering engine does not have a pixel to display, it will
539646SChris.Emmons@arm.com * cause an underrun event.  The HDLcd controller, per spec, will stop
549646SChris.Emmons@arm.com * issuing DMA requests for the rest of the frame and resume normal behavior
559646SChris.Emmons@arm.com * on the subsequent frame.  What pixels are rendered upon an underrun
569646SChris.Emmons@arm.com * condition is different than the real hardware; while the user will see
579646SChris.Emmons@arm.com * artifacts (previous frame mixed with current frame), it is not the same
589646SChris.Emmons@arm.com * behavior as real hardware which repeats the last pixel value for the rest
599646SChris.Emmons@arm.com * of the current frame.  This compromise was made to save on memory and
609646SChris.Emmons@arm.com * complexity and assumes that it is not important to accurately model the
619646SChris.Emmons@arm.com * content of an underrun frame.
629646SChris.Emmons@arm.com *
639646SChris.Emmons@arm.com * KNOWN ISSUES
649646SChris.Emmons@arm.com * 1.  The default kernel driver used in testing sets the line count to one
659646SChris.Emmons@arm.com * less than the expected 768.  However, it also sets the v_count to 767.
669646SChris.Emmons@arm.com * The controller specifies that 1 should be added to v_count but does not
679646SChris.Emmons@arm.com * specify adding 1 to the line count.  The driver is probably wrong.
689646SChris.Emmons@arm.com * However, to sync these two numbers up, this model uses fb_line_count and
699646SChris.Emmons@arm.com * fb_line_length rather than using v_data or h_data values to determine the
709646SChris.Emmons@arm.com * width and height of the frame; those values are ignored.
719646SChris.Emmons@arm.com * 2.  The HDLcd is implemented here as an AmbaDmaDevice, but it doesn't have
729646SChris.Emmons@arm.com * an AMBA ID as far as I know.  That is the only bit of the AmbaDmaDevice
739646SChris.Emmons@arm.com * interface that is irrelevant to it, so a fake AMBA ID is used for now.
749646SChris.Emmons@arm.com * I didn't think inserting an extra layer of hierachy between AmbaDmaDevice
759646SChris.Emmons@arm.com * and DmaDevice would be helpful to anyone else, but that may be the right
769646SChris.Emmons@arm.com * answer.
779646SChris.Emmons@arm.com * 3.  The internal buffer size is either 1 or 2 KB depending on which
789646SChris.Emmons@arm.com * specification is referenced for the different Versatile Express tiles.
799646SChris.Emmons@arm.com * This implementation uses the larger 2 KB buffer by default.
809646SChris.Emmons@arm.com */
819646SChris.Emmons@arm.com
829646SChris.Emmons@arm.com#ifndef __DEV_ARM_HDLCD_HH__
839646SChris.Emmons@arm.com#define __DEV_ARM_HDLCD_HH__
849646SChris.Emmons@arm.com
859646SChris.Emmons@arm.com#include <fstream>
8610839Sandreas.sandberg@arm.com#include <memory>
879646SChris.Emmons@arm.com
8810839Sandreas.sandberg@arm.com#include "base/bitmap.hh"
8910839Sandreas.sandberg@arm.com#include "base/framebuffer.hh"
909646SChris.Emmons@arm.com#include "dev/arm/amba_device.hh"
919646SChris.Emmons@arm.com#include "params/HDLcd.hh"
929646SChris.Emmons@arm.com#include "sim/serialize.hh"
939646SChris.Emmons@arm.com
949646SChris.Emmons@arm.comclass VncInput;
959646SChris.Emmons@arm.com
969646SChris.Emmons@arm.comclass HDLcd: public AmbaDmaDevice
979646SChris.Emmons@arm.com{
989646SChris.Emmons@arm.com  protected:
999646SChris.Emmons@arm.com    /** fake AMBA ID -- unused */
1009646SChris.Emmons@arm.com    static const uint64_t AMBA_ID       = ULL(0xb105f00d00141000);
1019646SChris.Emmons@arm.com
1029646SChris.Emmons@arm.com    /** ARM HDLcd register offsets */
1039646SChris.Emmons@arm.com    enum RegisterOffset {
1049646SChris.Emmons@arm.com        Version          = 0x0000,
1059646SChris.Emmons@arm.com        Int_RawStat      = 0x0010,
1069646SChris.Emmons@arm.com        Int_Clear        = 0x0014,
1079646SChris.Emmons@arm.com        Int_Mask         = 0x0018,
1089646SChris.Emmons@arm.com        Int_Status       = 0x001C,
1099646SChris.Emmons@arm.com        Fb_Base          = 0x0100,
1109646SChris.Emmons@arm.com        Fb_Line_Length   = 0x0104,
1119646SChris.Emmons@arm.com        Fb_Line_Count    = 0x0108,
1129646SChris.Emmons@arm.com        Fb_Line_Pitch    = 0x010C,
1139646SChris.Emmons@arm.com        Bus_Options      = 0x0110,
1149646SChris.Emmons@arm.com        V_Sync           = 0x0200,
1159646SChris.Emmons@arm.com        V_Back_Porch     = 0x0204,
1169646SChris.Emmons@arm.com        V_Data           = 0x0208,
1179646SChris.Emmons@arm.com        V_Front_Porch    = 0x020C,
1189646SChris.Emmons@arm.com        H_Sync           = 0x0210,
1199646SChris.Emmons@arm.com        H_Back_Porch     = 0x0214,
1209646SChris.Emmons@arm.com        H_Data           = 0x0218,
1219646SChris.Emmons@arm.com        H_Front_Porch    = 0x021C,
1229646SChris.Emmons@arm.com        Polarities       = 0x0220,
1239646SChris.Emmons@arm.com        Command          = 0x0230,
1249646SChris.Emmons@arm.com        Pixel_Format     = 0x0240,
1259646SChris.Emmons@arm.com        Red_Select       = 0x0244,
1269646SChris.Emmons@arm.com        Green_Select     = 0x0248,
1279646SChris.Emmons@arm.com        Blue_Select      = 0x024C };
1289646SChris.Emmons@arm.com
1299646SChris.Emmons@arm.com    /** Reset value for Bus_Options register */
1309646SChris.Emmons@arm.com    static const size_t BUS_OPTIONS_RESETV = 0x408;
1319646SChris.Emmons@arm.com
1329646SChris.Emmons@arm.com    /** Reset value for Version register */
1339646SChris.Emmons@arm.com    static const size_t VERSION_RESETV = 0x1CDC0000;
1349646SChris.Emmons@arm.com
1359646SChris.Emmons@arm.com    /** max number of outstanding DMA requests possible */
1369646SChris.Emmons@arm.com    static const size_t MAX_OUTSTANDING_DMA_REQ_CAPACITY = 16;
1379646SChris.Emmons@arm.com
1389646SChris.Emmons@arm.com    /** max number of beats delivered in one dma burst */
1399646SChris.Emmons@arm.com    static const size_t MAX_BURST_LEN = 16;
1409646SChris.Emmons@arm.com
1419646SChris.Emmons@arm.com    /** size of internal buffer in bytes */
1429646SChris.Emmons@arm.com    static const size_t PIXEL_BUFFER_CAPACITY = 2048;
1439646SChris.Emmons@arm.com
1449646SChris.Emmons@arm.com    /** AXI port width in bytes */
1459646SChris.Emmons@arm.com    static const size_t AXI_PORT_WIDTH = 8;
1469646SChris.Emmons@arm.com
14710839Sandreas.sandberg@arm.com    static const size_t MAX_BURST_SIZE = MAX_BURST_LEN * AXI_PORT_WIDTH;
14810839Sandreas.sandberg@arm.com
1499646SChris.Emmons@arm.com    /**
1509646SChris.Emmons@arm.com     * @name RegisterFieldLayouts
1519646SChris.Emmons@arm.com     * Bit layout declarations for multi-field registers.
1529646SChris.Emmons@arm.com     */
1539646SChris.Emmons@arm.com    /**@{*/
1549646SChris.Emmons@arm.com    BitUnion32(VersionReg)
1559646SChris.Emmons@arm.com        Bitfield<7,0>   version_minor;
1569646SChris.Emmons@arm.com        Bitfield<15,8>  version_major;
1579646SChris.Emmons@arm.com        Bitfield<31,16> product_id;
1589646SChris.Emmons@arm.com    EndBitUnion(VersionReg)
1599646SChris.Emmons@arm.com
1609646SChris.Emmons@arm.com    BitUnion32(InterruptReg)
1619646SChris.Emmons@arm.com        Bitfield<0> dma_end;
1629646SChris.Emmons@arm.com        Bitfield<1> bus_error;
1639646SChris.Emmons@arm.com        Bitfield<2> vsync;
1649646SChris.Emmons@arm.com        Bitfield<3> underrun;
1659646SChris.Emmons@arm.com    EndBitUnion(InterruptReg)
1669646SChris.Emmons@arm.com
1679646SChris.Emmons@arm.com    BitUnion32(FbLineCountReg)
1689646SChris.Emmons@arm.com        Bitfield<11,0>  fb_line_count;
1699646SChris.Emmons@arm.com        Bitfield<31,12> reserved_31_12;
1709646SChris.Emmons@arm.com    EndBitUnion(FbLineCountReg)
1719646SChris.Emmons@arm.com
1729646SChris.Emmons@arm.com    BitUnion32(BusOptsReg)
1739646SChris.Emmons@arm.com        Bitfield<4,0>   burst_len;
1749646SChris.Emmons@arm.com        Bitfield<7,5>   reserved_7_5;
1759646SChris.Emmons@arm.com        Bitfield<11,8>  max_outstanding;
1769646SChris.Emmons@arm.com        Bitfield<31,12> reserved_31_12;
1779646SChris.Emmons@arm.com    EndBitUnion(BusOptsReg)
1789646SChris.Emmons@arm.com
1799646SChris.Emmons@arm.com    BitUnion32(TimingReg)
1809646SChris.Emmons@arm.com        Bitfield<11,0>  val;
1819646SChris.Emmons@arm.com        Bitfield<31,12> reserved_31_12;
1829646SChris.Emmons@arm.com    EndBitUnion(TimingReg)
1839646SChris.Emmons@arm.com
1849646SChris.Emmons@arm.com    BitUnion32(PolaritiesReg)
1859646SChris.Emmons@arm.com        Bitfield<0>    vsync_polarity;
1869646SChris.Emmons@arm.com        Bitfield<1>    hsync_polarity;
1879646SChris.Emmons@arm.com        Bitfield<2>    dataen_polarity;
1889646SChris.Emmons@arm.com        Bitfield<3>    data_polarity;
1899646SChris.Emmons@arm.com        Bitfield<4>    pxlclk_polarity;
1909646SChris.Emmons@arm.com        Bitfield<31,5> reserved_31_5;
1919646SChris.Emmons@arm.com    EndBitUnion(PolaritiesReg)
1929646SChris.Emmons@arm.com
1939646SChris.Emmons@arm.com    BitUnion32(CommandReg)
1949646SChris.Emmons@arm.com        Bitfield<0>    enable;
1959646SChris.Emmons@arm.com        Bitfield<31,1> reserved_31_1;
1969646SChris.Emmons@arm.com    EndBitUnion(CommandReg)
1979646SChris.Emmons@arm.com
1989646SChris.Emmons@arm.com    BitUnion32(PixelFormatReg)
1999646SChris.Emmons@arm.com        Bitfield<2,0>  reserved_2_0;
2009646SChris.Emmons@arm.com        Bitfield<4,3>  bytes_per_pixel;
2019646SChris.Emmons@arm.com        Bitfield<30,5> reserved_30_5;
2029646SChris.Emmons@arm.com        Bitfield<31>   big_endian;
2039646SChris.Emmons@arm.com    EndBitUnion(PixelFormatReg)
2049646SChris.Emmons@arm.com
2059646SChris.Emmons@arm.com    BitUnion32(ColorSelectReg)
2069646SChris.Emmons@arm.com        Bitfield<4,0>   offset;
2079646SChris.Emmons@arm.com        Bitfield<7,5>   reserved_7_5;
2089646SChris.Emmons@arm.com        Bitfield<11,8>  size;
2099646SChris.Emmons@arm.com        Bitfield<15,12> reserved_15_12;
2109646SChris.Emmons@arm.com        Bitfield<23,16> default_color;
2119646SChris.Emmons@arm.com        Bitfield<31,24> reserved_31_24;
2129646SChris.Emmons@arm.com    EndBitUnion(ColorSelectReg)
2139646SChris.Emmons@arm.com    /**@}*/
2149646SChris.Emmons@arm.com
2159646SChris.Emmons@arm.com    /**
2169646SChris.Emmons@arm.com     * @name HDLCDRegisters
2179646SChris.Emmons@arm.com     * HDLCD register contents.
2189646SChris.Emmons@arm.com     */
2199646SChris.Emmons@arm.com    /**@{*/
2209646SChris.Emmons@arm.com    VersionReg version;             /**< Version register */
2219646SChris.Emmons@arm.com    InterruptReg int_rawstat;       /**< Interrupt raw status register */
2229646SChris.Emmons@arm.com    InterruptReg int_clear;         /**< Interrupt clear register */
2239646SChris.Emmons@arm.com    InterruptReg int_mask;          /**< Interrupt mask register */
2249646SChris.Emmons@arm.com    InterruptReg int_status;        /**< Interrupt status register */
2259646SChris.Emmons@arm.com    uint32_t fb_base;               /**< Frame buffer base address register */
2269646SChris.Emmons@arm.com    uint32_t fb_line_length;        /**< Frame buffer Line length register */
2279646SChris.Emmons@arm.com    FbLineCountReg fb_line_count;   /**< Frame buffer Line count register */
2289646SChris.Emmons@arm.com    uint32_t fb_line_pitch;         /**< Frame buffer Line pitch register */
2299646SChris.Emmons@arm.com    BusOptsReg bus_options;         /**< Bus options register */
2309646SChris.Emmons@arm.com    TimingReg v_sync;               /**< Vertical sync width register */
2319646SChris.Emmons@arm.com    TimingReg v_back_porch;         /**< Vertical back porch width register */
2329646SChris.Emmons@arm.com    TimingReg v_data;               /**< Vertical data width register */
2339646SChris.Emmons@arm.com    TimingReg v_front_porch;        /**< Vertical front porch width register */
2349646SChris.Emmons@arm.com    TimingReg h_sync;               /**< Horizontal sync width register */
2359646SChris.Emmons@arm.com    TimingReg h_back_porch;         /**< Horizontal back porch width register */
2369646SChris.Emmons@arm.com    TimingReg h_data;               /**< Horizontal data width register */
2379646SChris.Emmons@arm.com    TimingReg h_front_porch;        /**< Horizontal front porch width reg */
2389646SChris.Emmons@arm.com    PolaritiesReg polarities;       /**< Polarities register */
2399646SChris.Emmons@arm.com    CommandReg command;             /**< Command register */
2409646SChris.Emmons@arm.com    PixelFormatReg pixel_format;    /**< Pixel format register */
2419646SChris.Emmons@arm.com    ColorSelectReg red_select;      /**< Red color select register */
2429646SChris.Emmons@arm.com    ColorSelectReg green_select;    /**< Green color select register */
2439646SChris.Emmons@arm.com    ColorSelectReg blue_select;     /**< Blue color select register */
2449646SChris.Emmons@arm.com    /** @} */
2459646SChris.Emmons@arm.com
2469646SChris.Emmons@arm.com    /** Pixel clock period */
2479646SChris.Emmons@arm.com    const Tick pixelClock;
2489646SChris.Emmons@arm.com
24910839Sandreas.sandberg@arm.com    FrameBuffer fb;
25010839Sandreas.sandberg@arm.com
2519646SChris.Emmons@arm.com    /** VNC server */
2529646SChris.Emmons@arm.com    VncInput *vnc;
2539646SChris.Emmons@arm.com
2549646SChris.Emmons@arm.com    /** Helper to write out bitmaps */
25510839Sandreas.sandberg@arm.com    Bitmap bmp;
2569646SChris.Emmons@arm.com
2579646SChris.Emmons@arm.com    /** Picture of what the current frame buffer looks like */
2589646SChris.Emmons@arm.com    std::ostream *pic;
2599646SChris.Emmons@arm.com
2609646SChris.Emmons@arm.com    /**
2619646SChris.Emmons@arm.com     * Event wrapper for dmaDone()
2629646SChris.Emmons@arm.com     *
2639646SChris.Emmons@arm.com     * This event call pushes its this pointer onto the freeDoneEvent vector
2649646SChris.Emmons@arm.com     * and calls dmaDone() when triggered.  While most of the time the burst
2659646SChris.Emmons@arm.com     * length of a transaction will be the max burst length set by the driver,
2669646SChris.Emmons@arm.com     * any trailing bytes must be handled with smaller lengths thus requiring
2679646SChris.Emmons@arm.com     * the configurable burst length option.
2689646SChris.Emmons@arm.com     */
2699646SChris.Emmons@arm.com    class DmaDoneEvent : public Event
2709646SChris.Emmons@arm.com    {
2719646SChris.Emmons@arm.com      private:
2729646SChris.Emmons@arm.com        /** Reference to HDLCD that issued the corresponding DMA transaction */
2739646SChris.Emmons@arm.com        HDLcd &obj;
2749646SChris.Emmons@arm.com
2759646SChris.Emmons@arm.com        /** Transaction size */
2769646SChris.Emmons@arm.com        size_t transSize;
2779646SChris.Emmons@arm.com
2789646SChris.Emmons@arm.com      public:
2799646SChris.Emmons@arm.com        /**
2809646SChris.Emmons@arm.com         * Constructor.
2819646SChris.Emmons@arm.com         *
2829646SChris.Emmons@arm.com         * @param _obj HDLCD that issued the corresponding DMA transaction
2839646SChris.Emmons@arm.com         */
2849646SChris.Emmons@arm.com        DmaDoneEvent(HDLcd *_obj)
2859646SChris.Emmons@arm.com            : Event(), obj(*_obj), transSize(0) {}
2869646SChris.Emmons@arm.com
2879646SChris.Emmons@arm.com        /**
2889646SChris.Emmons@arm.com         * Sets the size of this transaction.
2899646SChris.Emmons@arm.com         *
2909646SChris.Emmons@arm.com         * @param len size of the transaction in bytes
2919646SChris.Emmons@arm.com         */
2929646SChris.Emmons@arm.com        void setTransactionSize(size_t len) {
2939646SChris.Emmons@arm.com            transSize = len;
2949646SChris.Emmons@arm.com        }
2959646SChris.Emmons@arm.com
2969646SChris.Emmons@arm.com        /**
2979646SChris.Emmons@arm.com         * Gets the size of this transaction.
2989646SChris.Emmons@arm.com         *
2999646SChris.Emmons@arm.com         * @return size of this transaction in bytes
3009646SChris.Emmons@arm.com         */
3019646SChris.Emmons@arm.com        size_t getTransactionSize() const {
3029646SChris.Emmons@arm.com            return transSize;
3039646SChris.Emmons@arm.com        }
3049646SChris.Emmons@arm.com
3059646SChris.Emmons@arm.com        void process() {
3069646SChris.Emmons@arm.com            obj.dmaDone(this);
3079646SChris.Emmons@arm.com        }
3089646SChris.Emmons@arm.com
3099646SChris.Emmons@arm.com        const std::string name() const {
3109646SChris.Emmons@arm.com            return obj.name() + ".DmaDoneEvent";
3119646SChris.Emmons@arm.com        }
3129646SChris.Emmons@arm.com    };
3139646SChris.Emmons@arm.com
3149646SChris.Emmons@arm.com    /** Start time for frame buffer dma read */
3159646SChris.Emmons@arm.com    Tick frameReadStartTime;
3169646SChris.Emmons@arm.com
3179646SChris.Emmons@arm.com    /** Starting address for the current frame */
3189646SChris.Emmons@arm.com    Addr dmaStartAddr;
3199646SChris.Emmons@arm.com
3209646SChris.Emmons@arm.com    /** Next address the dma should read from */
3219646SChris.Emmons@arm.com    Addr dmaCurAddr;
3229646SChris.Emmons@arm.com
3239646SChris.Emmons@arm.com    /** One byte past the address of the last byte the dma should read
3249646SChris.Emmons@arm.com      * from */
3259646SChris.Emmons@arm.com    Addr dmaMaxAddr;
3269646SChris.Emmons@arm.com
3279646SChris.Emmons@arm.com    /** Number of pending dma reads */
3289646SChris.Emmons@arm.com    size_t dmaPendingNum;
3299646SChris.Emmons@arm.com
3309646SChris.Emmons@arm.com    /** Flag indicating whether current frame has underrun */
3319646SChris.Emmons@arm.com    bool frameUnderrun;
3329646SChris.Emmons@arm.com
3339646SChris.Emmons@arm.com    /** HDLcd virtual display buffer */
33410839Sandreas.sandberg@arm.com    std::vector<uint8_t> virtualDisplayBuffer;
3359646SChris.Emmons@arm.com
3369646SChris.Emmons@arm.com    /** Size of the pixel buffer */
3379646SChris.Emmons@arm.com    size_t pixelBufferSize;
3389646SChris.Emmons@arm.com
3399646SChris.Emmons@arm.com    /** Index of the next pixel to render */
3409646SChris.Emmons@arm.com    size_t pixelIndex;
3419646SChris.Emmons@arm.com
3429646SChris.Emmons@arm.com    /** Flag indicating whether video parameters need updating */
3439646SChris.Emmons@arm.com    bool doUpdateParams;
3449646SChris.Emmons@arm.com
3459646SChris.Emmons@arm.com    /** Flag indicating whether a frame read / display is in progress */
3469646SChris.Emmons@arm.com    bool frameUnderway;
3479646SChris.Emmons@arm.com
3489646SChris.Emmons@arm.com    /**
3499646SChris.Emmons@arm.com     * Number of bytes in flight from DMA that have not reached the pixel
3509646SChris.Emmons@arm.com     * buffer yet
3519646SChris.Emmons@arm.com     */
3529646SChris.Emmons@arm.com    uint32_t dmaBytesInFlight;
3539646SChris.Emmons@arm.com
3549646SChris.Emmons@arm.com    /**
3559646SChris.Emmons@arm.com     * Gets the number of oustanding DMA transactions allowed on the bus at a
3569646SChris.Emmons@arm.com     * time.
3579646SChris.Emmons@arm.com     *
3589646SChris.Emmons@arm.com     * @return gets the driver-specified number of outstanding DMA transactions
3599646SChris.Emmons@arm.com     *         from the hdlcd controller that are allowed on the bus at a time
3609646SChris.Emmons@arm.com     */
3619646SChris.Emmons@arm.com    inline uint16_t maxOutstandingDma() const {
3629646SChris.Emmons@arm.com        return bus_options.max_outstanding;
3639646SChris.Emmons@arm.com    }
3649646SChris.Emmons@arm.com
3659646SChris.Emmons@arm.com    /**
3669646SChris.Emmons@arm.com     * Gets the number of bytes free in the pixel buffer.
3679646SChris.Emmons@arm.com     *
3689646SChris.Emmons@arm.com     * @return number of bytes free in the internal pixel buffer
3699646SChris.Emmons@arm.com     */
3709646SChris.Emmons@arm.com    inline uint32_t bytesFreeInPixelBuffer() const {
3719646SChris.Emmons@arm.com        return PIXEL_BUFFER_CAPACITY - (pixelBufferSize + dmaBytesInFlight);
3729646SChris.Emmons@arm.com    }
3739646SChris.Emmons@arm.com
3749646SChris.Emmons@arm.com    /**
3759646SChris.Emmons@arm.com     * Gets the number of beats-per-burst for bus transactions.
3769646SChris.Emmons@arm.com     *
3779646SChris.Emmons@arm.com     * @return number of beats-per-burst per HDLcd DMA transaction
3789646SChris.Emmons@arm.com     */
3799646SChris.Emmons@arm.com    inline size_t dmaBurstLength() const {
3809646SChris.Emmons@arm.com        assert(bus_options.burst_len <= MAX_BURST_LEN);
3819646SChris.Emmons@arm.com        return bus_options.burst_len;
3829646SChris.Emmons@arm.com    }
3839646SChris.Emmons@arm.com
3849646SChris.Emmons@arm.com    /**
3859646SChris.Emmons@arm.com     * Gets the number of bytes per pixel.
3869646SChris.Emmons@arm.com     *
3879646SChris.Emmons@arm.com     * @return bytes per pixel
3889646SChris.Emmons@arm.com     */
3899646SChris.Emmons@arm.com    inline size_t bytesPerPixel() const {
3909646SChris.Emmons@arm.com        return pixel_format.bytes_per_pixel + 1;
3919646SChris.Emmons@arm.com    }
3929646SChris.Emmons@arm.com
3939646SChris.Emmons@arm.com    /**
3949646SChris.Emmons@arm.com     * Gets frame buffer width.
3959646SChris.Emmons@arm.com     *
3969646SChris.Emmons@arm.com     * @return frame buffer width (pixels per line)
3979646SChris.Emmons@arm.com     */
3989646SChris.Emmons@arm.com    inline size_t width() const {
3999646SChris.Emmons@arm.com        return fb_line_length / bytesPerPixel();
4009646SChris.Emmons@arm.com    }
4019646SChris.Emmons@arm.com
4029646SChris.Emmons@arm.com    /**
4039646SChris.Emmons@arm.com     * Gets frame buffer height.
4049646SChris.Emmons@arm.com     *
4059646SChris.Emmons@arm.com     * @return frame buffer height (lines per panel)
4069646SChris.Emmons@arm.com     */
4079646SChris.Emmons@arm.com    inline size_t height() const {
4089646SChris.Emmons@arm.com        return fb_line_count.fb_line_count;
4099646SChris.Emmons@arm.com    }
4109646SChris.Emmons@arm.com
41110839Sandreas.sandberg@arm.com    inline size_t area() const { return height() * width(); }
41210839Sandreas.sandberg@arm.com
4139646SChris.Emmons@arm.com    /**
4149646SChris.Emmons@arm.com     * Gets the total number of pixel clocks per display line.
4159646SChris.Emmons@arm.com     *
4169646SChris.Emmons@arm.com     * @return number of pixel clocks per display line including porch delays
4179646SChris.Emmons@arm.com     *         and horizontal sync time
4189646SChris.Emmons@arm.com     */
4199646SChris.Emmons@arm.com    inline uint64_t PClksPerLine() const {
4209646SChris.Emmons@arm.com        return h_back_porch.val + 1 +
4219646SChris.Emmons@arm.com               h_data.val + 1 +
4229646SChris.Emmons@arm.com               h_front_porch.val + 1 +
4239646SChris.Emmons@arm.com               h_sync.val + 1;
4249646SChris.Emmons@arm.com    }
4259646SChris.Emmons@arm.com
4269646SChris.Emmons@arm.com    /** Send updated parameters to the vnc server */
4279646SChris.Emmons@arm.com    void updateVideoParams(bool unserializing);
4289646SChris.Emmons@arm.com
4299646SChris.Emmons@arm.com    /** Generates an interrupt */
4309646SChris.Emmons@arm.com    void generateInterrupt();
4319646SChris.Emmons@arm.com
4329646SChris.Emmons@arm.com    /** Start reading the next frame */
4339646SChris.Emmons@arm.com    void startFrame();
4349646SChris.Emmons@arm.com
4359646SChris.Emmons@arm.com    /** End of frame reached */
4369646SChris.Emmons@arm.com    void endFrame();
4379646SChris.Emmons@arm.com
4389646SChris.Emmons@arm.com    /** Generate DMA read requests from frame buffer into pixel buffer */
4399646SChris.Emmons@arm.com    void fillPixelBuffer();
4409646SChris.Emmons@arm.com
4419646SChris.Emmons@arm.com    /** DMA done event */
4429646SChris.Emmons@arm.com    void dmaDone(DmaDoneEvent *event);
4439646SChris.Emmons@arm.com
4449646SChris.Emmons@arm.com    /** Called when it is time to render a pixel */
4459646SChris.Emmons@arm.com    void renderPixel();
4469646SChris.Emmons@arm.com
44710839Sandreas.sandberg@arm.com    PixelConverter pixelConverter() const;
44810839Sandreas.sandberg@arm.com
4499646SChris.Emmons@arm.com    /** Start of frame event */
4509646SChris.Emmons@arm.com    EventWrapper<HDLcd, &HDLcd::startFrame> startFrameEvent;
4519646SChris.Emmons@arm.com
4529646SChris.Emmons@arm.com    /** End of frame event */
4539646SChris.Emmons@arm.com    EventWrapper<HDLcd, &HDLcd::endFrame> endFrameEvent;
4549646SChris.Emmons@arm.com
4559646SChris.Emmons@arm.com    /** Pixel render event */
4569646SChris.Emmons@arm.com    EventWrapper<HDLcd, &HDLcd::renderPixel> renderPixelEvent;
4579646SChris.Emmons@arm.com
4589646SChris.Emmons@arm.com    /** Fill fifo */
4599646SChris.Emmons@arm.com    EventWrapper<HDLcd, &HDLcd::fillPixelBuffer> fillPixelBufferEvent;
4609646SChris.Emmons@arm.com
4619646SChris.Emmons@arm.com    /** Wrapper to create an event out of the interrupt */
4629646SChris.Emmons@arm.com    EventWrapper<HDLcd, &HDLcd::generateInterrupt> intEvent;
4639646SChris.Emmons@arm.com
4649646SChris.Emmons@arm.com    /**@{*/
4659646SChris.Emmons@arm.com    /**
4669646SChris.Emmons@arm.com     * All pre-allocated DMA done events
4679646SChris.Emmons@arm.com     *
4689646SChris.Emmons@arm.com     * The HDLCD model preallocates maxOutstandingDma() number of
4699646SChris.Emmons@arm.com     * DmaDoneEvents to avoid having to heap allocate every single
4709646SChris.Emmons@arm.com     * event when it is needed. In order to keep track of which events
4719646SChris.Emmons@arm.com     * are in flight and which are ready to be used, we use two
4729646SChris.Emmons@arm.com     * different vectors. dmaDoneEventAll contains <i>all</i>
4739646SChris.Emmons@arm.com     * DmaDoneEvents that the object may use, while dmaDoneEventFree
4749646SChris.Emmons@arm.com     * contains a list of currently <i>unused</i> events. When an
4759646SChris.Emmons@arm.com     * event needs to be scheduled, the last element of the
4769646SChris.Emmons@arm.com     * dmaDoneEventFree is used and removed from the list. When an
4779646SChris.Emmons@arm.com     * event fires, it is added to the end of the
4789646SChris.Emmons@arm.com     * dmaEventFreeList. dmaDoneEventAll is never used except for in
4799646SChris.Emmons@arm.com     * initialization and serialization.
4809646SChris.Emmons@arm.com     */
4819646SChris.Emmons@arm.com    std::vector<DmaDoneEvent> dmaDoneEventAll;
4829646SChris.Emmons@arm.com
4839646SChris.Emmons@arm.com    /** Unused DMA done events that are ready to be scheduled */
4849646SChris.Emmons@arm.com    std::vector<DmaDoneEvent *> dmaDoneEventFree;
4859646SChris.Emmons@arm.com    /**@}*/
4869646SChris.Emmons@arm.com
4879939Sdam.sunwoo@arm.com    bool enableCapture;
4889939Sdam.sunwoo@arm.com
4899646SChris.Emmons@arm.com  public:
4909646SChris.Emmons@arm.com    typedef HDLcdParams Params;
4919646SChris.Emmons@arm.com
4929646SChris.Emmons@arm.com    const Params *
4939646SChris.Emmons@arm.com    params() const
4949646SChris.Emmons@arm.com    {
4959646SChris.Emmons@arm.com        return dynamic_cast<const Params *>(_params);
4969646SChris.Emmons@arm.com    }
4979646SChris.Emmons@arm.com    HDLcd(const Params *p);
4989646SChris.Emmons@arm.com    ~HDLcd();
4999646SChris.Emmons@arm.com
5009646SChris.Emmons@arm.com    virtual Tick read(PacketPtr pkt);
5019646SChris.Emmons@arm.com    virtual Tick write(PacketPtr pkt);
5029646SChris.Emmons@arm.com
5039646SChris.Emmons@arm.com    virtual void serialize(std::ostream &os);
5049646SChris.Emmons@arm.com    virtual void unserialize(Checkpoint *cp, const std::string &section);
5059646SChris.Emmons@arm.com
5069646SChris.Emmons@arm.com    /**
5079646SChris.Emmons@arm.com     * Determine the address ranges that this device responds to.
5089646SChris.Emmons@arm.com     *
5099646SChris.Emmons@arm.com     * @return a list of non-overlapping address ranges
5109646SChris.Emmons@arm.com     */
5119646SChris.Emmons@arm.com    AddrRangeList getAddrRanges() const;
5129646SChris.Emmons@arm.com};
5139646SChris.Emmons@arm.com
5149646SChris.Emmons@arm.com#endif
515