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