| /* | 
 | * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. | 
 | * | 
 | * 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 Linux Foundation. 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 "AS IS" AND ANY EXPRESS OR IMPLIED | 
 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 
 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT | 
 | * 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. | 
 | */ | 
 |  | 
 | #ifndef OVERLAY_H | 
 | #define OVERLAY_H | 
 |  | 
 | #include "overlayUtils.h" | 
 | #include "mdp_version.h" | 
 | #include "utils/threads.h" | 
 |  | 
 | struct MetaData_t; | 
 |  | 
 | namespace overlay { | 
 | class GenericPipe; | 
 |  | 
 | class Overlay : utils::NoCopy { | 
 | public: | 
 |     enum { DMA_BLOCK_MODE, DMA_LINE_MODE }; | 
 |     //Abstract Display types. Each backed by a LayerMixer, | 
 |     //represented by a fb node. | 
 |     //High res panels can be backed by 2 layer mixers and a single fb node. | 
 |     enum { DPY_PRIMARY, DPY_EXTERNAL, DPY_WRITEBACK, DPY_UNUSED }; | 
 |     enum { DPY_MAX = DPY_UNUSED }; | 
 |     enum { MIXER_LEFT, MIXER_RIGHT, MIXER_UNUSED }; | 
 |     enum { MIXER_DEFAULT = MIXER_LEFT, MIXER_MAX = MIXER_UNUSED }; | 
 |     enum { MAX_FB_DEVICES = DPY_MAX }; | 
 |     enum { FORMAT_YUV, FORMAT_RGB }; | 
 |  | 
 |     struct PipeSpecs { | 
 |         PipeSpecs() : formatClass(FORMAT_RGB), needsScaling(false), fb(false), | 
 |                 dpy(DPY_PRIMARY), mixer(MIXER_DEFAULT), numActiveDisplays(1) {} | 
 |         int formatClass; | 
 |         bool needsScaling; | 
 |         bool fb; | 
 |         int dpy; | 
 |         int mixer; | 
 |         int numActiveDisplays; | 
 |     }; | 
 |  | 
 |     /* dtor close */ | 
 |     ~Overlay(); | 
 |  | 
 |     /* Marks the beginning of a drawing round, resets usage bits on pipes | 
 |      * Should be called when drawing begins before any pipe config is done. | 
 |      */ | 
 |     void configBegin(); | 
 |  | 
 |     /* Marks the end of config for this drawing round | 
 |      * Will do garbage collection of pipe objects and thus calling UNSETs, | 
 |      * closing FDs, removing rotator objects and memory, if allocated. | 
 |      * Should be called after all pipe configs are done. | 
 |      */ | 
 |     void configDone(); | 
 |  | 
 |     /* Get a pipe that supported the specified format class (yuv, rgb) and has | 
 |      * scaling capabilities. | 
 |      */ | 
 |     utils::eDest getPipe(const PipeSpecs& pipeSpecs); | 
 |     /* Returns the eDest corresponding to an already allocated pipeid. | 
 |      * Useful for the reservation case, when libvpu reserves the pipe at its | 
 |      * end, and expect the overlay to allocate a given pipe for a layer. | 
 |      */ | 
 |     utils::eDest reservePipe(int pipeid); | 
 |     /* getting dest for the given pipeid */ | 
 |     utils::eDest getDest(int pipeid); | 
 |     /* getting overlay.pipeid for the given dest */ | 
 |     int getPipeId(utils::eDest dest); | 
 |  | 
 |     void setSource(const utils::PipeArgs args, utils::eDest dest); | 
 |     void setCrop(const utils::Dim& d, utils::eDest dest); | 
 |     void setColor(const uint32_t color, utils::eDest dest); | 
 |     void setTransform(const int orientation, utils::eDest dest); | 
 |     void setPosition(const utils::Dim& dim, utils::eDest dest); | 
 |     void setVisualParams(const MetaData_t& data, utils::eDest dest); | 
 |     bool commit(utils::eDest dest); | 
 |     bool queueBuffer(int fd, uint32_t offset, utils::eDest dest); | 
 |  | 
 |     /* pipe reservation session is running */ | 
 |     bool sessionInProgress(utils::eDest dest); | 
 |     /* pipe reservation session has ended*/ | 
 |     bool isSessionEnded(utils::eDest dest); | 
 |     /* start session for the pipe reservation */ | 
 |     void startSession(utils::eDest dest); | 
 |     /* end all started sesisons */ | 
 |     void endAllSessions(); | 
 |     /* Returns available ("unallocated") pipes for a display's mixer */ | 
 |     int availablePipes(int dpy, int mixer); | 
 |     /* Returns available ("unallocated") pipes for a display */ | 
 |     int availablePipes(int dpy); | 
 |     /* Returns available ("unallocated") pipe of given type for a display */ | 
 |     int availablePipes(int dpy, utils::eMdpPipeType type); | 
 |     /* Returns if any of the requested pipe type is attached to any of the | 
 |      * displays | 
 |      */ | 
 |     bool isPipeTypeAttached(utils::eMdpPipeType type); | 
 |     /* Compare pipe priorities and return | 
 |      * 1 if 1st pipe has a higher priority | 
 |      * 0 if both have the same priority | 
 |      *-1 if 2nd pipe has a higher priority | 
 |      */ | 
 |     int comparePipePriority(utils::eDest pipe1Index, utils::eDest pipe2Index); | 
 |     /* Returns pipe dump. Expects a NULL terminated buffer of big enough size | 
 |      * to populate. | 
 |      */ | 
 |     /* Returns if DMA pipe multiplexing is supported by the mdss driver */ | 
 |     static bool isDMAMultiplexingSupported(); | 
 |     /* Returns if UI scaling on external is supported on the targets */ | 
 |     static bool isUIScalingOnExternalSupported(); | 
 |     void getDump(char *buf, size_t len); | 
 |     /* Reset usage and allocation bits on all pipes for given display */ | 
 |     void clear(int dpy); | 
 |     /* Validate the set of pipes for a display and set them in driver */ | 
 |     bool validateAndSet(const int& dpy, const int& fbFd); | 
 |  | 
 |     /* Closes open pipes, called during startup */ | 
 |     static int initOverlay(); | 
 |     /* Returns the singleton instance of overlay */ | 
 |     static Overlay* getInstance(); | 
 |     static void setDMAMode(const int& mode); | 
 |     static int getDMAMode(); | 
 |     /* Returns the framebuffer node backing up the display */ | 
 |     static int getFbForDpy(const int& dpy); | 
 |  | 
 |     static bool displayCommit(const int& fd); | 
 |     /* Overloads display commit with ROI's of each halves. | 
 |      * Single interface panels will only update left ROI. */ | 
 |     static bool displayCommit(const int& fd, const utils::Dim& lRoi, | 
 |                               const utils::Dim& rRoi); | 
 |  | 
 | private: | 
 |     /* Ctor setup */ | 
 |     explicit Overlay(); | 
 |     /*Validate index range, abort if invalid */ | 
 |     void validate(int index); | 
 |     static void setDMAMultiplexingSupported(); | 
 |     void dump() const; | 
 |     /* Returns an available pipe based on the type of pipe requested. When ANY | 
 |      * is requested, the first available VG or RGB is returned. If no pipe is | 
 |      * available for the display "dpy" then INV is returned. Note: If a pipe is | 
 |      * assigned to a certain display, then it cannot be assigned to another | 
 |      * display without being garbage-collected once. To add if a pipe is | 
 |      * asisgned to a mixer within a display it cannot be reused for another | 
 |      * mixer without being UNSET once*/ | 
 |     utils::eDest nextPipe(utils::eMdpPipeType, int dpy, int mixer); | 
 |     /* Helpers that enfore target specific policies while returning pipes */ | 
 |     utils::eDest getPipe_8x26(const PipeSpecs& pipeSpecs); | 
 |     utils::eDest getPipe_8x16(const PipeSpecs& pipeSpecs); | 
 |     utils::eDest getPipe_8x39(const PipeSpecs& pipeSpecs); | 
 |     utils::eDest getPipe_8994(const PipeSpecs& pipeSpecs); | 
 |  | 
 |     /* Returns the handle to libscale.so's programScale function */ | 
 |     static int (*getFnProgramScale())(struct mdp_overlay_list *); | 
 |     /* Creates a scalar object using libscale.so */ | 
 |     static void initScalar(); | 
 |     /* Destroys the scalar object using libscale.so */ | 
 |     static void destroyScalar(); | 
 |     /* Sets the pipe type RGB/VG/DMA*/ | 
 |     void setPipeType(utils::eDest pipeIndex, const utils::eMdpPipeType pType); | 
 |  | 
 |     /* Just like a Facebook for pipes, but much less profile info */ | 
 |     struct PipeBook { | 
 |         void init(); | 
 |         void destroy(); | 
 |         /* Check if pipe exists and return true, false otherwise */ | 
 |         bool valid(); | 
 |  | 
 |         /* Hardware pipe wrapper */ | 
 |         GenericPipe *mPipe; | 
 |         /* Display using this pipe. Refer to enums above */ | 
 |         int mDisplay; | 
 |         /* Mixer within a split display this pipe is attached to */ | 
 |         int mMixer; | 
 |  | 
 |         /* operations on bitmap */ | 
 |         static bool pipeUsageUnchanged(); | 
 |         static void setUse(int index); | 
 |         static void resetUse(int index); | 
 |         static bool isUsed(int index); | 
 |         static bool isNotUsed(int index); | 
 |         static void save(); | 
 |  | 
 |         static void setAllocation(int index); | 
 |         static void resetAllocation(int index); | 
 |         static bool isAllocated(int index); | 
 |         static bool isNotAllocated(int index); | 
 |  | 
 |         static utils::eMdpPipeType getPipeType(utils::eDest dest); | 
 |         static const char* getDestStr(utils::eDest dest); | 
 |  | 
 |         static int NUM_PIPES; | 
 |         static utils::eMdpPipeType pipeTypeLUT[utils::OV_MAX]; | 
 |         /* Session for reserved pipes */ | 
 |         enum Session { | 
 |             NONE, | 
 |             START, | 
 |             END | 
 |         }; | 
 |         Session mSession; | 
 |  | 
 |     private: | 
 |         //usage tracks if a successful commit happened. So a pipe could be | 
 |         //allocated to a display, but it may not end up using it for various | 
 |         //reasons. If one display actually uses a pipe then it amy not be | 
 |         //used by another display, without an UNSET in between. | 
 |         static int sPipeUsageBitmap; | 
 |         static int sLastUsageBitmap; | 
 |         //Tracks which pipe objects are allocated. This does not imply that they | 
 |         //will actually be used. For example, a display might choose to acquire | 
 |         //3 pipe objects in one shot and proceed with config only if it gets all | 
 |         //3. The bitmap helps allocate different pipe objects on each request. | 
 |         static int sAllocatedBitmap; | 
 |     }; | 
 |  | 
 |     PipeBook mPipeBook[utils::OV_INVALID]; //Used as max | 
 |  | 
 |     /* Dump string */ | 
 |     char mDumpStr[1024]; | 
 |  | 
 |     /* Singleton Instance*/ | 
 |     static Overlay *sInstance; | 
 |     static int sDpyFbMap[DPY_MAX]; | 
 |     static int sDMAMode; | 
 |     static bool sDMAMultiplexingSupported; | 
 |     static void *sLibScaleHandle; | 
 |     static int (*sFnProgramScale)(struct mdp_overlay_list *); | 
 |  | 
 |     friend class MdpCtrl; | 
 | }; | 
 |  | 
 | inline void Overlay::validate(int index) { | 
 |     OVASSERT(index >=0 && index < PipeBook::NUM_PIPES, \ | 
 |         "%s, Index out of bounds: %d", __FUNCTION__, index); | 
 |     OVASSERT(mPipeBook[index].valid(), "Pipe does not exist %s", | 
 |             PipeBook::getDestStr((utils::eDest)index)); | 
 | } | 
 |  | 
 | inline int Overlay::availablePipes(int dpy, int mixer) { | 
 |     int avail = 0; | 
 |     for(int i = 0; i < PipeBook::NUM_PIPES; i++) { | 
 |         if( (mPipeBook[i].mDisplay == DPY_UNUSED || | 
 |              mPipeBook[i].mDisplay == dpy) && | 
 |             (mPipeBook[i].mMixer == MIXER_UNUSED || | 
 |              mPipeBook[i].mMixer == mixer) && | 
 |             PipeBook::isNotAllocated(i) && | 
 |             !(Overlay::getDMAMode() == Overlay::DMA_BLOCK_MODE && | 
 |               PipeBook::getPipeType((utils::eDest)i) == | 
 |               utils::OV_MDP_PIPE_DMA)) { | 
 |             avail++; | 
 |         } | 
 |     } | 
 |     return avail; | 
 | } | 
 |  | 
 | inline int Overlay::availablePipes(int dpy) { | 
 |     int avail = 0; | 
 |     for(int i = 0; i < PipeBook::NUM_PIPES; i++) { | 
 |         if( (mPipeBook[i].mDisplay == DPY_UNUSED || | 
 |              mPipeBook[i].mDisplay == dpy) && | 
 |             PipeBook::isNotAllocated(i) && | 
 |             !(Overlay::getDMAMode() == Overlay::DMA_BLOCK_MODE && | 
 |               PipeBook::getPipeType((utils::eDest)i) == | 
 |               utils::OV_MDP_PIPE_DMA)) { | 
 |             avail++; | 
 |         } | 
 |     } | 
 |     return avail; | 
 | } | 
 |  | 
 | inline int Overlay::availablePipes(int dpy, utils::eMdpPipeType type) { | 
 |     int avail = 0; | 
 |     for(int i = 0; i < PipeBook::NUM_PIPES; i++) { | 
 |         if((mPipeBook[i].mDisplay == DPY_UNUSED || | 
 |             mPipeBook[i].mDisplay == dpy) && | 
 |             PipeBook::isNotAllocated(i) && | 
 |             type == PipeBook::getPipeType((utils::eDest)i)) { | 
 |             avail++; | 
 |         } | 
 |     } | 
 |     return avail; | 
 | } | 
 |  | 
 | inline void Overlay::setDMAMode(const int& mode) { | 
 |     if(mode == DMA_LINE_MODE || mode == DMA_BLOCK_MODE) | 
 |         sDMAMode = mode; | 
 | } | 
 |  | 
 | inline void Overlay::setDMAMultiplexingSupported() { | 
 |     sDMAMultiplexingSupported = false; | 
 |     if(qdutils::MDPVersion::getInstance().is8x26()) | 
 |         sDMAMultiplexingSupported = true; | 
 | } | 
 |  | 
 | inline bool Overlay::isDMAMultiplexingSupported() { | 
 |     return sDMAMultiplexingSupported; | 
 | } | 
 |  | 
 | inline bool Overlay::isUIScalingOnExternalSupported() { | 
 |     if(qdutils::MDPVersion::getInstance().is8x26() or | 
 |        qdutils::MDPVersion::getInstance().is8x16() or | 
 |        qdutils::MDPVersion::getInstance().is8x39()) { | 
 |         return false; | 
 |     } | 
 |     return true; | 
 | } | 
 |  | 
 | inline int Overlay::getDMAMode() { | 
 |     return sDMAMode; | 
 | } | 
 |  | 
 | inline int Overlay::getFbForDpy(const int& dpy) { | 
 |     OVASSERT(dpy >= 0 && dpy < DPY_MAX, "Invalid dpy %d", dpy); | 
 |     return sDpyFbMap[dpy]; | 
 | } | 
 |  | 
 | inline int (*Overlay::getFnProgramScale())(struct mdp_overlay_list *) { | 
 |     return sFnProgramScale; | 
 | } | 
 |  | 
 | inline bool Overlay::PipeBook::valid() { | 
 |     return (mPipe != NULL); | 
 | } | 
 |  | 
 | inline bool Overlay::PipeBook::pipeUsageUnchanged() { | 
 |     return (sPipeUsageBitmap == sLastUsageBitmap); | 
 | } | 
 |  | 
 | inline void Overlay::PipeBook::setUse(int index) { | 
 |     sPipeUsageBitmap |= (1 << index); | 
 | } | 
 |  | 
 | inline void Overlay::PipeBook::resetUse(int index) { | 
 |     sPipeUsageBitmap &= ~(1 << index); | 
 | } | 
 |  | 
 | inline bool Overlay::PipeBook::isUsed(int index) { | 
 |     return sPipeUsageBitmap & (1 << index); | 
 | } | 
 |  | 
 | inline bool Overlay::PipeBook::isNotUsed(int index) { | 
 |     return !isUsed(index); | 
 | } | 
 |  | 
 | inline void Overlay::PipeBook::save() { | 
 |     sLastUsageBitmap = sPipeUsageBitmap; | 
 | } | 
 |  | 
 | inline void Overlay::PipeBook::setAllocation(int index) { | 
 |     sAllocatedBitmap |= (1 << index); | 
 | } | 
 |  | 
 | inline void Overlay::PipeBook::resetAllocation(int index) { | 
 |     sAllocatedBitmap &= ~(1 << index); | 
 | } | 
 |  | 
 | inline bool Overlay::PipeBook::isAllocated(int index) { | 
 |     return sAllocatedBitmap & (1 << index); | 
 | } | 
 |  | 
 | inline bool Overlay::PipeBook::isNotAllocated(int index) { | 
 |     return !isAllocated(index); | 
 | } | 
 |  | 
 | inline utils::eMdpPipeType Overlay::PipeBook::getPipeType(utils::eDest dest) { | 
 |     return pipeTypeLUT[(int)dest]; | 
 | } | 
 |  | 
 | inline void Overlay::startSession(utils::eDest dest) { | 
 |     mPipeBook[(int)dest].mSession = PipeBook::START; | 
 | } | 
 |  | 
 | inline bool Overlay::sessionInProgress(utils::eDest dest) { | 
 |     return (mPipeBook[(int)dest].mSession == PipeBook::START); | 
 | } | 
 |  | 
 | inline bool Overlay::isSessionEnded(utils::eDest dest) { | 
 |     return (mPipeBook[(int)dest].mSession == PipeBook::END); | 
 | } | 
 |  | 
 | inline const char* Overlay::PipeBook::getDestStr(utils::eDest dest) { | 
 |     switch(getPipeType(dest)) { | 
 |         case utils::OV_MDP_PIPE_RGB: return "RGB"; | 
 |         case utils::OV_MDP_PIPE_VG: return "VG"; | 
 |         case utils::OV_MDP_PIPE_DMA: return "DMA"; | 
 |         default: return "Invalid"; | 
 |     } | 
 |     return "Invalid"; | 
 | } | 
 |  | 
 | }; // overlay | 
 |  | 
 | #endif // OVERLAY_H |