1 /* 2 * Copyright (c) 2013-2014 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 <unistd.h> 31 #include <overlay.h> 32 #include <overlayUtils.h> 33 #include <overlayWriteback.h> 34 #include <mdp_version.h> 35 #include "hwc_ad.h" 36 #include "hwc_utils.h" 37 38 #define DEBUG 0 39 using namespace overlay; 40 using namespace overlay::utils; 41 namespace qhwc { 42 43 //Helper to write data to ad node 44 static void adWrite(const int& value) { 45 const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK); 46 char wbFbPath[256]; 47 snprintf (wbFbPath, sizeof(wbFbPath), 48 "/sys/class/graphics/fb%d/ad", wbFbNum); 49 int adFd = open(wbFbPath, O_WRONLY); 50 if(adFd >= 0) { 51 char opStr[4] = ""; 52 snprintf(opStr, sizeof(opStr), "%d", value); 53 ssize_t ret = write(adFd, opStr, strlen(opStr)); 54 if(ret < 0) { 55 ALOGE("%s: Failed to write %d with error %s", 56 __func__, value, strerror(errno)); 57 } else if (ret == 0){ 58 ALOGE("%s Nothing written to ad", __func__); 59 } else { 60 ALOGD_IF(DEBUG, "%s: Wrote %d to ad", __func__, value); 61 } 62 close(adFd); 63 } else { 64 ALOGE("%s: Failed to open /sys/class/graphics/fb%d/ad with error %s", 65 __func__, wbFbNum, strerror(errno)); 66 } 67 } 68 69 //Helper to read data from ad node 70 static int adRead() { 71 const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK); 72 int ret = -1; 73 char wbFbPath[256]; 74 snprintf (wbFbPath, sizeof(wbFbPath), 75 "/sys/class/graphics/fb%d/ad", wbFbNum); 76 int adFd = open(wbFbPath, O_RDONLY); 77 if(adFd >= 0) { 78 char opStr[4]; 79 ssize_t bytesRead = read(adFd, opStr, sizeof(opStr) - 1); 80 if(bytesRead > 0) { 81 opStr[bytesRead] = '\0'; 82 //Should return -1, 0 or 1 83 ret = atoi(opStr); 84 ALOGD_IF(DEBUG, "%s: Read %d from ad", __func__, ret); 85 } else if(bytesRead == 0) { 86 ALOGE("%s: ad node empty", __func__); 87 } else { 88 ALOGE("%s: Read from ad node failed with error %s", __func__, 89 strerror(errno)); 90 } 91 close(adFd); 92 } else { 93 ALOGD("%s: /sys/class/graphics/fb%d/ad could not be opened : %s", 94 __func__, wbFbNum, strerror(errno)); 95 } 96 return ret; 97 } 98 99 AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) : 100 mTurnedOff(true), mFeatureEnabled(false), 101 mDest(overlay::utils::OV_INVALID) 102 { 103 //Values in ad node: 104 //-1 means feature is disabled on device 105 // 0 means feature exists but turned off, will be turned on by hwc 106 // 1 means feature is turned on by hwc 107 // Plus, we do this feature only on split primary displays. 108 // Plus, we do this feature only if ro.qcom.ad=2 109 110 char property[PROPERTY_VALUE_MAX]; 111 const int ENABLED = 2; 112 int val = 0; 113 114 if(property_get("ro.qcom.ad", property, "0") > 0) { 115 val = atoi(property); 116 } 117 118 if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) && 119 val == ENABLED) { 120 ALOGD_IF(DEBUG, "Assertive display feature supported"); 121 mFeatureEnabled = true; 122 // If feature exists but is turned off, set mTurnedOff to true 123 mTurnedOff = adRead() > 0 ? false : true; 124 } 125 } 126 127 void AssertiveDisplay::markDoable(hwc_context_t *ctx, 128 const hwc_display_contents_1_t* list) { 129 mDoable = false; 130 if(mFeatureEnabled && 131 !isSecondaryConnected(ctx) && 132 ctx->listStats[HWC_DISPLAY_PRIMARY].yuvCount == 1) { 133 int nYuvIndex = ctx->listStats[HWC_DISPLAY_PRIMARY].yuvIndices[0]; 134 const hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex]; 135 private_handle_t *hnd = (private_handle_t *)layer->handle; 136 qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance(); 137 if(hnd && hnd->width <= (int) mdpHw.getMaxMixerWidth()) { 138 mDoable = true; 139 } 140 } 141 } 142 143 void AssertiveDisplay::turnOffAD() { 144 if(mFeatureEnabled) { 145 if(!mTurnedOff) { 146 const int off = 0; 147 adWrite(off); 148 mTurnedOff = true; 149 } 150 } 151 mDoable = false; 152 } 153 154 bool AssertiveDisplay::prepare(hwc_context_t *ctx, 155 const hwc_rect_t& crop, 156 const Whf& whf, 157 const private_handle_t *hnd) { 158 if(!isDoable()) { 159 //Cleanup one time during this switch 160 turnOffAD(); 161 return false; 162 } 163 164 Overlay::PipeSpecs pipeSpecs; 165 pipeSpecs.formatClass = Overlay::FORMAT_YUV; 166 pipeSpecs.dpy = overlay::Overlay::DPY_WRITEBACK; 167 pipeSpecs.fb = false; 168 169 ovutils::eDest dest = ctx->mOverlay->getPipe(pipeSpecs); 170 if(dest == OV_INVALID) { 171 ALOGE("%s failed: No VG pipe available", __func__); 172 mDoable = false; 173 return false; 174 } 175 176 overlay::Writeback *wb = overlay::Writeback::getInstance(); 177 178 //Set Security flag on writeback 179 if(isSecureBuffer(hnd)) { 180 if(!wb->setSecure(isSecureBuffer(hnd))) { 181 ALOGE("Failure in setting WB secure flag for ad"); 182 return false; 183 } 184 } 185 186 if(!wb->configureDpyInfo(hnd->width, hnd->height)) { 187 ALOGE("%s: config display failed", __func__); 188 mDoable = false; 189 return false; 190 } 191 192 int tmpW, tmpH; 193 size_t size; 194 int format = ovutils::getHALFormat(wb->getOutputFormat()); 195 if(format < 0) { 196 ALOGE("%s invalid format %d", __func__, format); 197 mDoable = false; 198 return false; 199 } 200 201 size = getBufferSizeAndDimensions(hnd->width, hnd->height, 202 format, tmpW, tmpH); 203 204 if(!wb->configureMemory((uint32_t)size)) { 205 ALOGE("%s: config memory failed", __func__); 206 mDoable = false; 207 return false; 208 } 209 210 eMdpFlags mdpFlags = OV_MDP_FLAGS_NONE; 211 if(isSecureBuffer(hnd)) { 212 ovutils::setMdpFlags(mdpFlags, 213 ovutils::OV_MDP_SECURE_OVERLAY_SESSION); 214 } 215 216 PipeArgs parg(mdpFlags, whf, ZORDER_0, 217 ROT_FLAGS_NONE); 218 hwc_rect_t dst = crop; //input same as output 219 220 if(configMdp(ctx->mOverlay, parg, OVERLAY_TRANSFORM_0, crop, dst, NULL, 221 dest) < 0) { 222 ALOGE("%s: configMdp failed", __func__); 223 mDoable = false; 224 return false; 225 } 226 227 mDest = dest; 228 int wbFd = wb->getFbFd(); 229 if(mFeatureEnabled && wbFd >= 0 && 230 !ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK, wbFd)) 231 { 232 ALOGE("%s: Failed to validate and set overlay for dpy %d" 233 ,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK); 234 turnOffAD(); 235 return false; 236 } 237 238 // Only turn on AD if there are no errors during configuration stage 239 // and if it was previously in OFF state. 240 if(mFeatureEnabled && mTurnedOff) { 241 //write to sysfs, one time during this switch 242 const int on = 1; 243 adWrite(on); 244 mTurnedOff = false; 245 } 246 247 return true; 248 } 249 250 bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) { 251 if(!isDoable()) { 252 return false; 253 } 254 255 if (!ctx->mOverlay->queueBuffer(fd, offset, mDest)) { 256 ALOGE("%s: queueBuffer failed", __func__); 257 return false; 258 } 259 260 overlay::Writeback *wb = overlay::Writeback::getInstance(); 261 if(!wb->writeSync()) { 262 return false; 263 } 264 265 return true; 266 } 267 268 int AssertiveDisplay::getDstFd() const { 269 overlay::Writeback *wb = overlay::Writeback::getInstance(); 270 return wb->getDstFd(); 271 } 272 273 uint32_t AssertiveDisplay::getDstOffset() const { 274 overlay::Writeback *wb = overlay::Writeback::getInstance(); 275 return wb->getOffset(); 276 } 277 278 } 279