1 /* 2 * Copyright (c) 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 #include "overlay.h" 31 #include "overlayWriteback.h" 32 #include "mdpWrapper.h" 33 34 namespace overlay { 35 36 //=========== class WritebackMem ============================================== 37 bool WritebackMem::manageMem(uint32_t size, bool isSecure) { 38 if(mBuf.bufSz() == size) { 39 return true; 40 } 41 if(mBuf.valid()) { 42 if(!mBuf.close()) { 43 ALOGE("%s error closing mem", __func__); 44 return false; 45 } 46 } 47 return alloc(size, isSecure); 48 } 49 50 bool WritebackMem::alloc(uint32_t size, bool isSecure) { 51 if(!mBuf.open(NUM_BUFS, size, isSecure)){ 52 ALOGE("%s: Failed to open", __func__); 53 mBuf.close(); 54 return false; 55 } 56 57 OVASSERT(MAP_FAILED != mBuf.addr(), "MAP failed"); 58 OVASSERT(mBuf.getFD() != -1, "getFd is -1"); 59 60 mCurrOffsetIndex = 0; 61 for (uint32_t i = 0; i < NUM_BUFS; i++) { 62 mOffsets[i] = i * size; 63 } 64 return true; 65 } 66 67 bool WritebackMem::dealloc() { 68 bool ret = true; 69 if(mBuf.valid()) { 70 ret = mBuf.close(); 71 } 72 return ret; 73 } 74 75 //=========== class Writeback ================================================= 76 Writeback::Writeback() : mXres(0), mYres(0), mOpFmt(-1) { 77 int fbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK); 78 if(!utils::openDev(mFd, fbNum, Res::fbPath, O_RDWR)) { 79 ALOGE("%s failed to init %s", __func__, Res::fbPath); 80 return; 81 } 82 startSession(); 83 } 84 85 Writeback::~Writeback() { 86 stopSession(); 87 if (!mFd.close()) { 88 ALOGE("%s error closing fd", __func__); 89 } 90 } 91 92 bool Writeback::startSession() { 93 if(!mdp_wrapper::wbInitStart(mFd.getFD())) { 94 ALOGE("%s failed", __func__); 95 return false; 96 } 97 return true; 98 } 99 100 bool Writeback::stopSession() { 101 if(mFd.valid()) { 102 if(!mdp_wrapper::wbStopTerminate(mFd.getFD())) { 103 ALOGE("%s failed", __func__); 104 return false; 105 } 106 } else { 107 ALOGE("%s Invalid fd", __func__); 108 return false; 109 } 110 return true; 111 } 112 113 bool Writeback::configureDpyInfo(int xres, int yres) { 114 if(mXres != xres || mYres != yres) { 115 fb_var_screeninfo vinfo; 116 memset(&vinfo, 0, sizeof(fb_var_screeninfo)); 117 if(!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) { 118 ALOGE("%s failed", __func__); 119 return false; 120 } 121 vinfo.xres = xres; 122 vinfo.yres = yres; 123 vinfo.xres_virtual = xres; 124 vinfo.yres_virtual = yres; 125 vinfo.xoffset = 0; 126 vinfo.yoffset = 0; 127 if(!mdp_wrapper::setVScreenInfo(mFd.getFD(), vinfo)) { 128 ALOGE("%s failed", __func__); 129 return false; 130 } 131 mXres = xres; 132 mYres = yres; 133 } 134 return true; 135 } 136 137 bool Writeback::configureMemory(uint32_t size, bool isSecure) { 138 if(!mWbMem.manageMem(size, isSecure)) { 139 ALOGE("%s failed, memory failure", __func__); 140 return false; 141 } 142 return true; 143 } 144 145 bool Writeback::queueBuffer(int opFd, uint32_t opOffset) { 146 memset(&mFbData, 0, sizeof(struct msmfb_data)); 147 //Queue 148 mFbData.offset = opOffset; 149 mFbData.memory_id = opFd; 150 mFbData.id = 0; 151 mFbData.flags = 0; 152 if(!mdp_wrapper::wbQueueBuffer(mFd.getFD(), mFbData)) { 153 ALOGE("%s: queuebuffer failed", __func__); 154 return false; 155 } 156 return true; 157 } 158 159 bool Writeback::dequeueBuffer() { 160 //Dequeue 161 mFbData.flags = MSMFB_WRITEBACK_DEQUEUE_BLOCKING; 162 if(!mdp_wrapper::wbDequeueBuffer(mFd.getFD(), mFbData)) { 163 ALOGE("%s: dequeuebuffer failed", __func__); 164 return false; 165 } 166 return true; 167 } 168 169 bool Writeback::writeSync(int opFd, uint32_t opOffset) { 170 if(!queueBuffer(opFd, opOffset)) { 171 return false; 172 } 173 if(!Overlay::displayCommit(mFd.getFD())) { 174 return false; 175 } 176 if(!dequeueBuffer()) { 177 return false; 178 } 179 return true; 180 } 181 182 bool Writeback::writeSync() { 183 mWbMem.useNextBuffer(); 184 return writeSync(mWbMem.getDstFd(), mWbMem.getOffset()); 185 } 186 187 bool Writeback::setOutputFormat(int mdpFormat) { 188 if(mdpFormat != mOpFmt) { 189 struct msmfb_metadata metadata; 190 memset(&metadata, 0 , sizeof(metadata)); 191 metadata.op = metadata_op_wb_format; 192 metadata.data.mixer_cfg.writeback_format = mdpFormat; 193 if (ioctl(mFd.getFD(), MSMFB_METADATA_SET, &metadata) < 0) { 194 ALOGE("Error setting MDP Writeback format"); 195 return false; 196 } 197 mOpFmt = mdpFormat; 198 } 199 return true; 200 } 201 202 int Writeback::getOutputFormat() { 203 if(mOpFmt < 0) { 204 struct msmfb_metadata metadata; 205 memset(&metadata, 0 , sizeof(metadata)); 206 metadata.op = metadata_op_wb_format; 207 if (ioctl(mFd.getFD(), MSMFB_METADATA_GET, &metadata) < 0) { 208 ALOGE("Error retrieving MDP Writeback format"); 209 return -1; 210 } 211 mOpFmt = metadata.data.mixer_cfg.writeback_format; 212 } 213 return mOpFmt; 214 } 215 216 //static 217 218 Writeback *Writeback::getInstance() { 219 if(sWb == NULL) { 220 sWb = new Writeback(); 221 } 222 sUsed = true; 223 return sWb; 224 } 225 226 void Writeback::configDone() { 227 if(sUsed == false && sWb) { 228 delete sWb; 229 sWb = NULL; 230 } 231 } 232 233 void Writeback::clear() { 234 sUsed = false; 235 if(sWb) { 236 delete sWb; 237 sWb = NULL; 238 } 239 } 240 241 bool Writeback::getDump(char *buf, size_t len) { 242 if(sWb) { 243 utils::getDump(buf, len, "WBData", sWb->mFbData); 244 char str[4] = {'\0'}; 245 snprintf(str, 4, "\n"); 246 strncat(buf, str, strlen(str)); 247 return true; 248 } 249 return false; 250 } 251 252 Writeback *Writeback::sWb = 0; 253 bool Writeback::sUsed = false; 254 255 } //namespace overlay 256