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