1/* 2* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. 3* 4* Redistribution and use in source and binary forms, with or without 5* modification, are permitted provided that the following conditions are 6* met: 7* * Redistributions of source code must retain the above copyright 8* notice, this list of conditions and the following disclaimer. 9* * Redistributions in binary form must reproduce the above 10* copyright notice, this list of conditions and the following 11* disclaimer in the documentation and/or other materials provided 12* with the distribution. 13* * Neither the name of The Linux Foundation. nor the names of its 14* contributors may be used to endorse or promote products derived 15* from this software without specific prior written permission. 16* 17* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*/ 29 30#ifndef OVERLAY_H 31#define OVERLAY_H 32 33#include "overlayUtils.h" 34#include "mdp_version.h" 35#include "utils/threads.h" 36 37struct MetaData_t; 38namespace scale { 39class Scale; 40}; 41 42namespace overlay { 43class GenericPipe; 44 45class Overlay : utils::NoCopy { 46public: 47 enum { DMA_BLOCK_MODE, DMA_LINE_MODE }; 48 //Abstract Display types. Each backed by a LayerMixer, 49 //represented by a fb node. 50 //High res panels can be backed by 2 layer mixers and a single fb node. 51 enum { DPY_PRIMARY, DPY_EXTERNAL, DPY_WRITEBACK, DPY_UNUSED }; 52 enum { DPY_MAX = DPY_UNUSED }; 53 enum { MIXER_LEFT, MIXER_RIGHT, MIXER_UNUSED }; 54 enum { MIXER_DEFAULT = MIXER_LEFT, MIXER_MAX = MIXER_UNUSED }; 55 enum { MAX_FB_DEVICES = DPY_MAX }; 56 57 /* dtor close */ 58 ~Overlay(); 59 60 /* Marks the beginning of a drawing round, resets usage bits on pipes 61 * Should be called when drawing begins before any pipe config is done. 62 */ 63 void configBegin(); 64 65 /* Marks the end of config for this drawing round 66 * Will do garbage collection of pipe objects and thus calling UNSETs, 67 * closing FDs, removing rotator objects and memory, if allocated. 68 * Should be called after all pipe configs are done. 69 */ 70 void configDone(); 71 72 /* Returns an available pipe based on the type of pipe requested. When ANY 73 * is requested, the first available VG or RGB is returned. If no pipe is 74 * available for the display "dpy" then INV is returned. Note: If a pipe is 75 * assigned to a certain display, then it cannot be assigned to another 76 * display without being garbage-collected once. To add if a pipe is 77 * asisgned to a mixer within a display it cannot be reused for another 78 * mixer without being UNSET once*/ 79 utils::eDest nextPipe(utils::eMdpPipeType, int dpy, int mixer); 80 /* Returns the eDest corresponding to an already allocated pipeid. 81 * Useful for the reservation case, when libvpu reserves the pipe at its 82 * end, and expect the overlay to allocate a given pipe for a layer. 83 */ 84 utils::eDest reservePipe(int pipeid); 85 /* getting dest for the given pipeid */ 86 utils::eDest getDest(int pipeid); 87 /* getting overlay.pipeid for the given dest */ 88 int getPipeId(utils::eDest dest); 89 90 void setSource(const utils::PipeArgs args, utils::eDest dest); 91 void setCrop(const utils::Dim& d, utils::eDest dest); 92 void setColor(const uint32_t color, utils::eDest dest); 93 void setTransform(const int orientation, utils::eDest dest); 94 void setPosition(const utils::Dim& dim, utils::eDest dest); 95 void setVisualParams(const MetaData_t& data, utils::eDest dest); 96 bool commit(utils::eDest dest); 97 bool queueBuffer(int fd, uint32_t offset, utils::eDest dest); 98 99 /* pipe reservation session is running */ 100 bool sessionInProgress(utils::eDest dest); 101 /* pipe reservation session has ended*/ 102 bool isSessionEnded(utils::eDest dest); 103 /* start session for the pipe reservation */ 104 void startSession(utils::eDest dest); 105 /* end all started sesisons */ 106 void endAllSessions(); 107 /* Returns available ("unallocated") pipes for a display's mixer */ 108 int availablePipes(int dpy, int mixer); 109 /* Returns available ("unallocated") pipes for a display */ 110 int availablePipes(int dpy); 111 /* Returns available ("unallocated") pipe of given type for a display */ 112 int availablePipes(int dpy, utils::eMdpPipeType type); 113 /* Returns if any of the requested pipe type is attached to any of the 114 * displays 115 */ 116 bool isPipeTypeAttached(utils::eMdpPipeType type); 117 /* Returns pipe dump. Expects a NULL terminated buffer of big enough size 118 * to populate. 119 */ 120 void getDump(char *buf, size_t len); 121 /* Reset usage and allocation bits on all pipes for given display */ 122 void clear(int dpy); 123 /* Validate the set of pipes for a display and set them in driver */ 124 bool validateAndSet(const int& dpy, const int& fbFd); 125 126 /* Closes open pipes, called during startup */ 127 static int initOverlay(); 128 /* Returns the singleton instance of overlay */ 129 static Overlay* getInstance(); 130 static void setDMAMode(const int& mode); 131 static int getDMAMode(); 132 /* Returns the framebuffer node backing up the display */ 133 static int getFbForDpy(const int& dpy); 134 static bool displayCommit(const int& fd, const utils::Dim& roi); 135 static bool displayCommit(const int& fd); 136 137private: 138 /* Ctor setup */ 139 explicit Overlay(); 140 /*Validate index range, abort if invalid */ 141 void validate(int index); 142 static void setDMAMultiplexingSupported(); 143 void dump() const; 144 /* Returns the scalar object */ 145 static scale::Scale *getScalar(); 146 /* Creates a scalar object using libscale.so */ 147 static void initScalar(); 148 /* Destroys the scalar object using libscale.so */ 149 static void destroyScalar(); 150 151 /* Just like a Facebook for pipes, but much less profile info */ 152 struct PipeBook { 153 void init(); 154 void destroy(); 155 /* Check if pipe exists and return true, false otherwise */ 156 bool valid(); 157 158 /* Hardware pipe wrapper */ 159 GenericPipe *mPipe; 160 /* Display using this pipe. Refer to enums above */ 161 int mDisplay; 162 /* Mixer within a split display this pipe is attached to */ 163 int mMixer; 164 165 /* operations on bitmap */ 166 static bool pipeUsageUnchanged(); 167 static void setUse(int index); 168 static void resetUse(int index); 169 static bool isUsed(int index); 170 static bool isNotUsed(int index); 171 static void save(); 172 173 static void setAllocation(int index); 174 static void resetAllocation(int index); 175 static bool isAllocated(int index); 176 static bool isNotAllocated(int index); 177 178 static utils::eMdpPipeType getPipeType(utils::eDest dest); 179 static const char* getDestStr(utils::eDest dest); 180 181 static int NUM_PIPES; 182 static utils::eMdpPipeType pipeTypeLUT[utils::OV_MAX]; 183 /* Session for reserved pipes */ 184 enum Session { 185 NONE, 186 START, 187 END 188 }; 189 Session mSession; 190 191 private: 192 //usage tracks if a successful commit happened. So a pipe could be 193 //allocated to a display, but it may not end up using it for various 194 //reasons. If one display actually uses a pipe then it amy not be 195 //used by another display, without an UNSET in between. 196 static int sPipeUsageBitmap; 197 static int sLastUsageBitmap; 198 //Tracks which pipe objects are allocated. This does not imply that they 199 //will actually be used. For example, a display might choose to acquire 200 //3 pipe objects in one shot and proceed with config only if it gets all 201 //3. The bitmap helps allocate different pipe objects on each request. 202 static int sAllocatedBitmap; 203 }; 204 205 PipeBook mPipeBook[utils::OV_INVALID]; //Used as max 206 207 /* Dump string */ 208 char mDumpStr[1024]; 209 210 /* Singleton Instance*/ 211 static Overlay *sInstance; 212 static int sDpyFbMap[DPY_MAX]; 213 static int sDMAMode; 214 static bool sDMAMultiplexingSupported; 215 static void *sLibScaleHandle; 216 static scale::Scale *sScale; 217 218 friend class MdpCtrl; 219}; 220 221inline void Overlay::validate(int index) { 222 OVASSERT(index >=0 && index < PipeBook::NUM_PIPES, \ 223 "%s, Index out of bounds: %d", __FUNCTION__, index); 224 OVASSERT(mPipeBook[index].valid(), "Pipe does not exist %s", 225 PipeBook::getDestStr((utils::eDest)index)); 226} 227 228inline int Overlay::availablePipes(int dpy, int mixer) { 229 int avail = 0; 230 for(int i = 0; i < PipeBook::NUM_PIPES; i++) { 231 if( (mPipeBook[i].mDisplay == DPY_UNUSED || 232 mPipeBook[i].mDisplay == dpy) && 233 (mPipeBook[i].mMixer == MIXER_UNUSED || 234 mPipeBook[i].mMixer == mixer) && 235 PipeBook::isNotAllocated(i) && 236 !(Overlay::getDMAMode() == Overlay::DMA_BLOCK_MODE && 237 PipeBook::getPipeType((utils::eDest)i) == 238 utils::OV_MDP_PIPE_DMA)) { 239 avail++; 240 } 241 } 242 return avail; 243} 244 245inline int Overlay::availablePipes(int dpy) { 246 int avail = 0; 247 for(int i = 0; i < PipeBook::NUM_PIPES; i++) { 248 if( (mPipeBook[i].mDisplay == DPY_UNUSED || 249 mPipeBook[i].mDisplay == dpy) && 250 PipeBook::isNotAllocated(i) && 251 !(Overlay::getDMAMode() == Overlay::DMA_BLOCK_MODE && 252 PipeBook::getPipeType((utils::eDest)i) == 253 utils::OV_MDP_PIPE_DMA)) { 254 avail++; 255 } 256 } 257 return avail; 258} 259 260inline int Overlay::availablePipes(int dpy, utils::eMdpPipeType type) { 261 int avail = 0; 262 for(int i = 0; i < PipeBook::NUM_PIPES; i++) { 263 if((mPipeBook[i].mDisplay == DPY_UNUSED || 264 mPipeBook[i].mDisplay == dpy) && 265 PipeBook::isNotAllocated(i) && 266 type == PipeBook::getPipeType((utils::eDest)i)) { 267 avail++; 268 } 269 } 270 return avail; 271} 272 273inline void Overlay::setDMAMode(const int& mode) { 274 if(mode == DMA_LINE_MODE || mode == DMA_BLOCK_MODE) 275 sDMAMode = mode; 276} 277 278inline void Overlay::setDMAMultiplexingSupported() { 279 sDMAMultiplexingSupported = false; 280 if(qdutils::MDPVersion::getInstance().is8x26()) 281 sDMAMultiplexingSupported = true; 282} 283 284inline int Overlay::getDMAMode() { 285 return sDMAMode; 286} 287 288inline int Overlay::getFbForDpy(const int& dpy) { 289 OVASSERT(dpy >= 0 && dpy < DPY_MAX, "Invalid dpy %d", dpy); 290 return sDpyFbMap[dpy]; 291} 292 293inline scale::Scale *Overlay::getScalar() { 294 return sScale; 295} 296 297inline bool Overlay::PipeBook::valid() { 298 return (mPipe != NULL); 299} 300 301inline bool Overlay::PipeBook::pipeUsageUnchanged() { 302 return (sPipeUsageBitmap == sLastUsageBitmap); 303} 304 305inline void Overlay::PipeBook::setUse(int index) { 306 sPipeUsageBitmap |= (1 << index); 307} 308 309inline void Overlay::PipeBook::resetUse(int index) { 310 sPipeUsageBitmap &= ~(1 << index); 311} 312 313inline bool Overlay::PipeBook::isUsed(int index) { 314 return sPipeUsageBitmap & (1 << index); 315} 316 317inline bool Overlay::PipeBook::isNotUsed(int index) { 318 return !isUsed(index); 319} 320 321inline void Overlay::PipeBook::save() { 322 sLastUsageBitmap = sPipeUsageBitmap; 323} 324 325inline void Overlay::PipeBook::setAllocation(int index) { 326 sAllocatedBitmap |= (1 << index); 327} 328 329inline void Overlay::PipeBook::resetAllocation(int index) { 330 sAllocatedBitmap &= ~(1 << index); 331} 332 333inline bool Overlay::PipeBook::isAllocated(int index) { 334 return sAllocatedBitmap & (1 << index); 335} 336 337inline bool Overlay::PipeBook::isNotAllocated(int index) { 338 return !isAllocated(index); 339} 340 341inline utils::eMdpPipeType Overlay::PipeBook::getPipeType(utils::eDest dest) { 342 return pipeTypeLUT[(int)dest]; 343} 344 345inline void Overlay::startSession(utils::eDest dest) { 346 mPipeBook[(int)dest].mSession = PipeBook::START; 347} 348 349inline bool Overlay::sessionInProgress(utils::eDest dest) { 350 return (mPipeBook[(int)dest].mSession == PipeBook::START); 351} 352 353inline bool Overlay::isSessionEnded(utils::eDest dest) { 354 return (mPipeBook[(int)dest].mSession == PipeBook::END); 355} 356 357inline const char* Overlay::PipeBook::getDestStr(utils::eDest dest) { 358 switch(getPipeType(dest)) { 359 case utils::OV_MDP_PIPE_RGB: return "RGB"; 360 case utils::OV_MDP_PIPE_VG: return "VG"; 361 case utils::OV_MDP_PIPE_DMA: return "DMA"; 362 default: return "Invalid"; 363 } 364 return "Invalid"; 365} 366 367}; // overlay 368 369#endif // OVERLAY_H 370