/*
 * Copyright (c) 2010-2013, 2015, 2017 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Chris Emmons
 *          Andreas Sandberg
 */


/** @file
 * Implementiation of the ARM HDLcd controller.
 *
 * This implementation aims to have sufficient detail such that underrun
 * conditions are reasonable / behave similar to reality.  There are two
 * 'engines' going at once.  First, the DMA engine running at LCD clock
 * frequency is responsible for filling the controller's internal buffer.
 * The second engine runs at the pixel clock frequency and reads the pixels
 * out of the internal buffer.  The pixel rendering engine uses front / back
 * porch and sync delays between lines and frames.
 *
 * If the pixel rendering engine does not have a pixel to display, it will
 * cause an underrun event.  The HDLcd controller, per spec, will stop
 * issuing DMA requests for the rest of the frame and resume normal behavior
 * on the subsequent frame.  What pixels are rendered upon an underrun
 * condition is different than the real hardware; while the user will see
 * artifacts (previous frame mixed with current frame), it is not the same
 * behavior as real hardware which repeats the last pixel value for the rest
 * of the current frame.  This compromise was made to save on memory and
 * complexity and assumes that it is not important to accurately model the
 * content of an underrun frame.
 *
 * KNOWN ISSUES
 * <ul>
 *   <li>The HDLcd is implemented here as an AmbaDmaDevice, but it
 *       doesn't have an AMBA ID as far as I know.  That is the only
 *       bit of the AmbaDmaDevice interface that is irrelevant to it,
 *       so a fake AMBA ID is used for now.  I didn't think inserting
 *       an extra layer of hierachy between AmbaDmaDevice and
 *       DmaDevice would be helpful to anyone else, but that may be
 *       the right answer.
 * </ul>
 */

#ifndef __DEV_ARM_HDLCD_HH__
#define __DEV_ARM_HDLCD_HH__

#include <fstream>
#include <memory>

#include "base/framebuffer.hh"
#include "base/imgwriter.hh"
#include "base/output.hh"
#include "dev/arm/amba_device.hh"
#include "dev/pixelpump.hh"
#include "sim/serialize.hh"

class VncInput;
struct HDLcdParams;
class HDLcdPixelPump;

class HDLcd: public AmbaDmaDevice
{
  public:
    HDLcd(const HDLcdParams *p);
    ~HDLcd();

    void regStats() override;

    void serialize(CheckpointOut &cp) const override;
    void unserialize(CheckpointIn &cp) override;

    void drainResume() override;

  public: // IO device interface
    Tick read(PacketPtr pkt) override;
    Tick write(PacketPtr pkt) override;

    AddrRangeList getAddrRanges() const override { return addrRanges; }

  protected: // Parameters
    VncInput *vnc;
    const bool workaroundSwapRB;
    const bool workaroundDmaLineCount;
    const AddrRangeList addrRanges;
    const bool enableCapture;
    const Addr pixelBufferSize;
    const Tick virtRefreshRate;

  protected: // Register handling
    /** ARM HDLcd register offsets */
    enum RegisterOffset {
        Version          = 0x0000,
        Int_RawStat      = 0x0010,
        Int_Clear        = 0x0014,
        Int_Mask         = 0x0018,
        Int_Status       = 0x001C,
        Fb_Base          = 0x0100,
        Fb_Line_Length   = 0x0104,
        Fb_Line_Count    = 0x0108,
        Fb_Line_Pitch    = 0x010C,
        Bus_Options      = 0x0110,
        V_Sync           = 0x0200,
        V_Back_Porch     = 0x0204,
        V_Data           = 0x0208,
        V_Front_Porch    = 0x020C,
        H_Sync           = 0x0210,
        H_Back_Porch     = 0x0214,
        H_Data           = 0x0218,
        H_Front_Porch    = 0x021C,
        Polarities       = 0x0220,
        Command          = 0x0230,
        Pixel_Format     = 0x0240,
        Red_Select       = 0x0244,
        Green_Select     = 0x0248,
        Blue_Select      = 0x024C,
    };

    /** Reset value for Bus_Options register */
    static constexpr size_t BUS_OPTIONS_RESETV = 0x408;

    /** Reset value for Version register */
    static constexpr size_t VERSION_RESETV = 0x1CDC0000;

    /** AXI port width in bytes */
    static constexpr size_t AXI_PORT_WIDTH = 8;

    /** max number of beats delivered in one dma burst */
    static constexpr size_t MAX_BURST_LEN = 16;

    /** Maximum number of bytes per pixel */
    static constexpr size_t MAX_PIXEL_SIZE = 4;

    /**
     * @name RegisterFieldLayouts
     * Bit layout declarations for multi-field registers.
     */
    /**@{*/
    BitUnion32(VersionReg)
        Bitfield<7,0>   version_minor;
        Bitfield<15,8>  version_major;
        Bitfield<31,16> product_id;
    EndBitUnion(VersionReg)

    static constexpr uint32_t INT_DMA_END = (1UL << 0);
    static constexpr uint32_t INT_BUS_ERROR = (1UL << 1);
    static constexpr uint32_t INT_VSYNC = (1UL << 2);
    static constexpr uint32_t INT_UNDERRUN = (1UL << 3);

    BitUnion32(FbLineCountReg)
        Bitfield<11,0>  fb_line_count;
        Bitfield<31,12> reserved_31_12;
    EndBitUnion(FbLineCountReg)

    BitUnion32(BusOptsReg)
        Bitfield<4,0>   burst_len;
        Bitfield<7,5>   reserved_7_5;
        Bitfield<11,8>  max_outstanding;
        Bitfield<31,12> reserved_31_12;
    EndBitUnion(BusOptsReg)

    BitUnion32(TimingReg)
        Bitfield<11,0>  val;
        Bitfield<31,12> reserved_31_12;
    EndBitUnion(TimingReg)

    BitUnion32(PolaritiesReg)
        Bitfield<0>    vsync_polarity;
        Bitfield<1>    hsync_polarity;
        Bitfield<2>    dataen_polarity;
        Bitfield<3>    data_polarity;
        Bitfield<4>    pxlclk_polarity;
        Bitfield<31,5> reserved_31_5;
    EndBitUnion(PolaritiesReg)

    BitUnion32(CommandReg)
        Bitfield<0>    enable;
        Bitfield<31,1> reserved_31_1;
    EndBitUnion(CommandReg)

    BitUnion32(PixelFormatReg)
        Bitfield<2,0>  reserved_2_0;
        Bitfield<4,3>  bytes_per_pixel;
        Bitfield<30,5> reserved_30_5;
        Bitfield<31>   big_endian;
    EndBitUnion(PixelFormatReg)

    BitUnion32(ColorSelectReg)
        Bitfield<4,0>   offset;
        Bitfield<7,5>   reserved_7_5;
        Bitfield<11,8>  size;
        Bitfield<15,12> reserved_15_12;
        Bitfield<23,16> default_color;
        Bitfield<31,24> reserved_31_24;
    EndBitUnion(ColorSelectReg)
    /**@}*/

    /**
     * @name HDLCDRegisters
     * HDLCD register contents.
     */
    /**@{*/
    const VersionReg version;       /**< Version register */
    uint32_t int_rawstat;           /**< Interrupt raw status register */
    uint32_t int_mask;              /**< Interrupt mask register */
    uint32_t fb_base;               /**< Frame buffer base address register */
    uint32_t fb_line_length;        /**< Frame buffer Line length register */
    FbLineCountReg fb_line_count;   /**< Frame buffer Line count register */
    int32_t fb_line_pitch;          /**< Frame buffer Line pitch register */
    BusOptsReg bus_options;         /**< Bus options register */
    TimingReg v_sync;               /**< Vertical sync width register */
    TimingReg v_back_porch;         /**< Vertical back porch width register */
    TimingReg v_data;               /**< Vertical data width register */
    TimingReg v_front_porch;        /**< Vertical front porch width register */
    TimingReg h_sync;               /**< Horizontal sync width register */
    TimingReg h_back_porch;         /**< Horizontal back porch width register */
    TimingReg h_data;               /**< Horizontal data width register */
    TimingReg h_front_porch;        /**< Horizontal front porch width reg */
    PolaritiesReg polarities;       /**< Polarities register */
    CommandReg command;             /**< Command register */
    PixelFormatReg pixel_format;    /**< Pixel format register */
    ColorSelectReg red_select;      /**< Red color select register */
    ColorSelectReg green_select;    /**< Green color select register */
    ColorSelectReg blue_select;     /**< Blue color select register */
    /** @} */

    uint32_t readReg(Addr offset);
    void writeReg(Addr offset, uint32_t value);

    PixelConverter pixelConverter() const;
    DisplayTimings displayTimings() const;

    void createDmaEngine();

    void cmdEnable();
    void cmdDisable();

    bool enabled() const { return command.enable; }

  public: // Pixel pump callbacks
    bool pxlNext(Pixel &p);
    void pxlVSyncBegin();
    void pxlVSyncEnd();
    void pxlUnderrun();
    void pxlFrameDone();

  protected: // Interrupt handling
    /**
     * Assign new interrupt values and update interrupt signals
     *
     * A new interrupt is scheduled signalled if the set of unmasked
     * interrupts goes empty to non-empty. Conversely, if the set of
     * unmasked interrupts goes from non-empty to empty, the interrupt
     * signal is cleared.
     *
     * @param ints New <i>raw</i> interrupt status
     * @param mask New interrupt mask
     */
    void setInterrupts(uint32_t ints, uint32_t mask);

    /**
     * Convenience function to update the interrupt mask
     *
     * @see setInterrupts
     * @param mask New interrupt mask
     */
    void intMask(uint32_t mask) { setInterrupts(int_rawstat, mask); }

    /**
     * Convenience function to raise a new interrupt
     *
     * @see setInterrupts
     * @param ints Set of interrupts to raise
     */
    void intRaise(uint32_t ints) {
        setInterrupts(int_rawstat | ints, int_mask);
    }

    /**
     * Convenience function to clear interrupts
     *
     * @see setInterrupts
     * @param ints Set of interrupts to clear
     */
    void intClear(uint32_t ints) {
        setInterrupts(int_rawstat & ~ints, int_mask);
    }

    /** Masked interrupt status register */
    uint32_t intStatus() const { return int_rawstat & int_mask; }

  protected: // Pixel output
    class PixelPump : public BasePixelPump
    {
      public:
        PixelPump(HDLcd &p, ClockDomain &pxl_clk, unsigned pixel_chunk)
            : BasePixelPump(p, pxl_clk, pixel_chunk), parent(p) {}

        void dumpSettings();

      protected:
        bool nextPixel(Pixel &p) override { return parent.pxlNext(p); }

        void onVSyncBegin() override { return parent.pxlVSyncBegin(); }
        void onVSyncEnd() override { return parent.pxlVSyncEnd(); }

        void onUnderrun(unsigned x, unsigned y) override {
            parent.pxlUnderrun();
        }

        void onFrameDone() override { parent.pxlFrameDone(); }

      protected:
        HDLcd &parent;
    };

    /** Handler for fast frame refresh in KVM-mode */
    void virtRefresh();
    EventFunctionWrapper virtRefreshEvent;

    /** Helper to write out bitmaps */
    std::unique_ptr<ImgWriter> imgWriter;

    /** Image Format */
    Enums::ImageFormat imgFormat;

    /** Picture of what the current frame buffer looks like */
    OutputStream *pic;

    /** Cached pixel converter, set when the converter is enabled. */
    PixelConverter conv;

    PixelPump pixelPump;

  protected: // DMA handling
    class DmaEngine : public DmaReadFifo
    {
      public:
        DmaEngine(HDLcd &_parent, size_t size,
                  unsigned request_size, unsigned max_pending,
                  size_t line_size, ssize_t line_pitch, unsigned num_lines);

        void startFrame(Addr fb_base);
        void abortFrame();
        void dumpSettings();

        void serialize(CheckpointOut &cp) const override;
        void unserialize(CheckpointIn &cp) override;

      protected:
        void onEndOfBlock() override;
        void onIdle() override;

        HDLcd &parent;
        const size_t lineSize;
        const ssize_t linePitch;
        const unsigned numLines;

        Addr nextLineAddr;
        Addr frameEnd;
    };

    std::unique_ptr<DmaEngine> dmaEngine;

  protected: // Statistics
    struct {
        Stats::Scalar underruns;
    } stats;
};

#endif
