1 /* Copyright (c) 2015, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 #define LOG_TAG "QCameraPerf" 31 32 #include <cutils/properties.h> 33 #include <stdlib.h> 34 #include <utils/Log.h> 35 #include "QCameraPerf.h" 36 37 #ifdef CDBG 38 #undef CDBG 39 #endif //#ifdef CDBG 40 #define CDBG(fmt, args...) ALOGD_IF(gCamHalLogLevel >= 2, fmt, ##args) 41 42 #ifdef CDBG_HIGH 43 #undef CDBG_HIGH 44 #endif //#ifdef CDBG_HIGH 45 #define CDBG_HIGH(fmt, args...) ALOGD_IF(gCamHalLogLevel >= 1, fmt, ##args) 46 47 48 namespace qcamera { 49 50 extern volatile uint32_t gCamHalLogLevel; 51 52 /*=========================================================================== 53 * FUNCTION : QCameraPerfLock constructor 54 * 55 * DESCRIPTION: initialize member variables 56 * 57 * PARAMETERS : 58 * None 59 * 60 * RETURN : void 61 * 62 *==========================================================================*/ 63 QCameraPerfLock::QCameraPerfLock() : 64 perf_lock_acq(NULL), 65 perf_lock_rel(NULL), 66 mDlHandle(NULL), 67 mPerfLockEnable(0), 68 mPerfLockHandle(-1), 69 mPerfLockHandleTimed(-1), 70 mTimerSet(0), 71 mPerfLockTimeout(0), 72 mStartTimeofLock(0) 73 { 74 } 75 76 /*=========================================================================== 77 * FUNCTION : QCameraPerfLock destructor 78 * 79 * DESCRIPTION: class desctructor 80 * 81 * PARAMETERS : 82 * None 83 * 84 * RETURN : void 85 * 86 *==========================================================================*/ 87 QCameraPerfLock::~QCameraPerfLock() 88 { 89 lock_deinit(); 90 } 91 92 93 /*=========================================================================== 94 * FUNCTION : lock_init 95 * 96 * DESCRIPTION: opens the performance lib and initilizes the perf lock functions 97 * 98 * PARAMETERS : 99 * None 100 * 101 * RETURN : void 102 * 103 *==========================================================================*/ 104 void QCameraPerfLock::lock_init() 105 { 106 const char *rc; 107 char value[PROPERTY_VALUE_MAX]; 108 int len; 109 110 CDBG("%s E", __func__); 111 Mutex::Autolock lock(mLock); 112 113 property_get("persist.camera.perflock.enable", value, "1"); 114 mPerfLockEnable = atoi(value); 115 mCurrentPowerHintEnable = 0; 116 #ifdef HAS_MULTIMEDIA_HINTS 117 if (hw_get_module(POWER_HARDWARE_MODULE_ID, (const hw_module_t **)&m_pPowerModule)) { 118 ALOGE("%s: %s module not found", __func__, POWER_HARDWARE_MODULE_ID); 119 } 120 #endif 121 122 if (mPerfLockEnable) { 123 perf_lock_acq = NULL; 124 perf_lock_rel = NULL; 125 mPerfLockHandle = -1; 126 /* Retrieve name of vendor extension library */ 127 if (property_get("ro.vendor.extension_library", value, NULL) <= 0) { 128 goto cleanup; 129 } 130 131 mDlHandle = dlopen(value, RTLD_NOW | RTLD_LOCAL); 132 if (mDlHandle == NULL) { 133 goto cleanup; 134 } 135 136 dlerror(); 137 138 perf_lock_acq = (int (*) (int, int, int[], int))dlsym(mDlHandle, "perf_lock_acq"); 139 if ((rc = dlerror()) != NULL) { 140 ALOGE("%s: failed to perf_lock_acq function handle", __func__); 141 goto cleanup; 142 } 143 144 perf_lock_rel = (int (*) (int))dlsym(mDlHandle, "perf_lock_rel"); 145 if ((rc = dlerror()) != NULL) { 146 ALOGE("%s: failed to perf_lock_rel function handle", __func__); 147 goto cleanup; 148 } 149 CDBG("%s X", __func__); 150 return; 151 152 cleanup: 153 perf_lock_acq = NULL; 154 perf_lock_rel = NULL; 155 mPerfLockEnable = 0; 156 if (mDlHandle) { 157 dlclose(mDlHandle); 158 mDlHandle = NULL; 159 } 160 } 161 CDBG("%s X", __func__); 162 } 163 164 /*=========================================================================== 165 * FUNCTION : lock_deinit 166 * 167 * DESCRIPTION: deinitialize the perf lock parameters 168 * 169 * PARAMETERS : 170 * None 171 * 172 * RETURN : void 173 * 174 *==========================================================================*/ 175 void QCameraPerfLock::lock_deinit() 176 { 177 Mutex::Autolock lock(mLock); 178 if (mPerfLockEnable) { 179 CDBG("%s E", __func__); 180 if (mDlHandle) { 181 perf_lock_acq = NULL; 182 perf_lock_rel = NULL; 183 184 dlclose(mDlHandle); 185 mDlHandle = NULL; 186 } 187 mPerfLockEnable = 0; 188 CDBG("%s X", __func__); 189 } 190 } 191 192 /*=========================================================================== 193 * FUNCTION : isTimerReset 194 * 195 * DESCRIPTION: Check if timout duration is reached 196 * 197 * PARAMETERS : None 198 * 199 * RETURN : true if timeout reached 200 * false if timeout not reached 201 * 202 *==========================================================================*/ 203 bool QCameraPerfLock::isTimerReset() 204 { 205 Mutex::Autolock lock(mLock); 206 if (mPerfLockEnable && mTimerSet) { 207 nsecs_t timeDiff = systemTime() - mStartTimeofLock; 208 if (ns2ms(timeDiff) > (uint32_t)mPerfLockTimeout) { 209 mTimerSet = 0; 210 return true; 211 } 212 } 213 return false; 214 } 215 216 /*=========================================================================== 217 * FUNCTION : start_timer 218 * 219 * DESCRIPTION: get the start of the timer 220 * 221 * PARAMETERS : 222 * @timer_val: timer duration in milliseconds 223 * 224 * RETURN : int32_t type of status 225 * NO_ERROR -- success 226 * none-zero failure code 227 * 228 *==========================================================================*/ 229 void QCameraPerfLock::startTimer(uint32_t timer_val) 230 { 231 mStartTimeofLock = systemTime(); 232 mTimerSet = 1; 233 mPerfLockTimeout = timer_val; 234 } 235 236 /*=========================================================================== 237 * FUNCTION : lock_acq_timed 238 * 239 * DESCRIPTION: Acquire the performance lock for the specified duration. 240 * If an existing lock timeout has not elapsed, extend the 241 * lock further for the specified duration 242 * 243 * PARAMETERS : 244 * @timer_val: lock duration 245 * 246 * RETURN : int32_t type of status 247 * NO_ERROR -- success 248 * none-zero failure code 249 * 250 *==========================================================================*/ 251 int32_t QCameraPerfLock::lock_acq_timed(int32_t timer_val) 252 { 253 int32_t ret = -1; 254 255 CDBG("%s E", __func__); 256 Mutex::Autolock lock(mLock); 257 258 if (mPerfLockEnable) { 259 int32_t perf_lock_params[] = { 260 ALL_CPUS_PWR_CLPS_DIS, 261 CPU0_MIN_FREQ_TURBO_MAX, 262 CPU4_MIN_FREQ_TURBO_MAX 263 }; 264 if (mTimerSet) { 265 nsecs_t curElapsedTime = systemTime() - mStartTimeofLock; 266 int32_t pendingTimeout = mPerfLockTimeout - ns2ms(curElapsedTime); 267 timer_val += pendingTimeout; 268 } 269 startTimer(timer_val); 270 271 // Disable power hint when acquiring the perf lock 272 if (mCurrentPowerHintEnable) { 273 CDBG_HIGH("%s mCurrentPowerHintEnable %d", __func__ ,mCurrentPowerHintEnable); 274 powerHintInternal(mCurrentPowerHint, 0); 275 } 276 277 if ((NULL != perf_lock_acq) && (mPerfLockHandleTimed < 0)) { 278 ret = (*perf_lock_acq)(mPerfLockHandleTimed, timer_val, perf_lock_params, 279 sizeof(perf_lock_params) / sizeof(int32_t)); 280 CDBG("%s ret %d", __func__, ret); 281 if (ret < 0) { 282 ALOGE("%s: failed to acquire lock", __func__); 283 } else { 284 mPerfLockHandleTimed = ret; 285 } 286 } 287 CDBG("%s perf_handle_acq %d ",__func__, mPerfLockHandleTimed); 288 } 289 290 CDBG("%s X", __func__); 291 return ret; 292 } 293 294 /*=========================================================================== 295 * FUNCTION : lock_acq 296 * 297 * DESCRIPTION: acquire the performance lock 298 * 299 * PARAMETERS : 300 * None 301 * 302 * RETURN : int32_t type of status 303 * NO_ERROR -- success 304 * none-zero failure code 305 * 306 *==========================================================================*/ 307 int32_t QCameraPerfLock::lock_acq() 308 { 309 int32_t ret = -1; 310 311 CDBG("%s E", __func__); 312 Mutex::Autolock lock(mLock); 313 314 if (mPerfLockEnable) { 315 int32_t perf_lock_params[] = { 316 ALL_CPUS_PWR_CLPS_DIS, 317 CPU0_MIN_FREQ_TURBO_MAX, 318 CPU4_MIN_FREQ_TURBO_MAX 319 }; 320 321 // Disable power hint when acquiring the perf lock 322 if (mCurrentPowerHintEnable) { 323 powerHintInternal(mCurrentPowerHint, 0); 324 } 325 326 if ((NULL != perf_lock_acq) && (mPerfLockHandle < 0)) { 327 ret = (*perf_lock_acq)(mPerfLockHandle, ONE_SEC, perf_lock_params, 328 sizeof(perf_lock_params) / sizeof(int32_t)); 329 CDBG("%s ret %d", __func__, ret); 330 if (ret < 0) { 331 ALOGE("%s: failed to acquire lock", __func__); 332 } else { 333 mPerfLockHandle = ret; 334 } 335 } 336 CDBG("%s perf_handle_acq %d ",__func__, mPerfLockHandle); 337 } 338 339 CDBG("%s X", __func__); 340 return ret; 341 } 342 343 /*=========================================================================== 344 * FUNCTION : lock_rel_timed 345 * 346 * DESCRIPTION: release the performance lock 347 * 348 * PARAMETERS : 349 * None 350 * 351 * RETURN : int32_t type of status 352 * NO_ERROR -- success 353 * none-zero failure code 354 * 355 *==========================================================================*/ 356 int32_t QCameraPerfLock::lock_rel_timed() 357 { 358 int ret = -1; 359 Mutex::Autolock lock(mLock); 360 if (mPerfLockEnable) { 361 CDBG("%s E", __func__); 362 if (mPerfLockHandleTimed < 0) { 363 ALOGE("%s: mPerfLockHandle < 0,check if lock is acquired", __func__); 364 return ret; 365 } 366 CDBG("%s perf_handle_rel %d ",__func__, mPerfLockHandleTimed); 367 368 if ((NULL != perf_lock_rel) && (0 <= mPerfLockHandleTimed)) { 369 ret = (*perf_lock_rel)(mPerfLockHandleTimed); 370 if (ret < 0) { 371 ALOGE("%s: failed to release lock", __func__); 372 } 373 mPerfLockHandleTimed = -1; 374 } 375 376 if ((mCurrentPowerHintEnable == 1) && (mTimerSet == 0)) { 377 powerHintInternal(mCurrentPowerHint, mCurrentPowerHintEnable); 378 } 379 CDBG("%s X", __func__); 380 } 381 return ret; 382 } 383 384 /*=========================================================================== 385 * FUNCTION : lock_rel 386 * 387 * DESCRIPTION: release the performance lock 388 * 389 * PARAMETERS : 390 * None 391 * 392 * RETURN : int32_t type of status 393 * NO_ERROR -- success 394 * none-zero failure code 395 * 396 *==========================================================================*/ 397 int32_t QCameraPerfLock::lock_rel() 398 { 399 int ret = -1; 400 Mutex::Autolock lock(mLock); 401 if (mPerfLockEnable) { 402 CDBG("%s E", __func__); 403 if (mPerfLockHandle < 0) { 404 ALOGE("%s: mPerfLockHandle < 0,check if lock is acquired", __func__); 405 return ret; 406 } 407 CDBG("%s perf_handle_rel %d ",__func__, mPerfLockHandle); 408 409 if ((NULL != perf_lock_rel) && (0 <= mPerfLockHandle)) { 410 ret = (*perf_lock_rel)(mPerfLockHandle); 411 if (ret < 0) { 412 ALOGE("%s: failed to release lock", __func__); 413 } 414 mPerfLockHandle = -1; 415 } 416 417 if ((mCurrentPowerHintEnable == 1) && (mTimerSet == 0)) { 418 powerHintInternal(mCurrentPowerHint, mCurrentPowerHintEnable); 419 } 420 CDBG("%s X", __func__); 421 } 422 return ret; 423 } 424 425 /*=========================================================================== 426 * FUNCTION : powerHintInternal 427 * 428 * DESCRIPTION: Sets the requested power hint and state to power HAL. 429 * 430 * PARAMETERS : 431 * enable : Enable power hint if set to 1. Disable if set to 0. 432 * RETURN : void 433 * 434 *==========================================================================*/ 435 void QCameraPerfLock::powerHintInternal(power_hint_t hint, uint32_t enable) 436 { 437 #ifdef HAS_MULTIMEDIA_HINTS 438 if (m_pPowerModule != NULL) { 439 if (enable == 1) { 440 m_pPowerModule->powerHint(m_pPowerModule, hint, (void *)"state=1"); 441 } 442 else { 443 m_pPowerModule->powerHint(m_pPowerModule, hint, (void *)"state=0"); 444 } 445 } 446 #endif 447 } 448 449 /*=========================================================================== 450 * FUNCTION : powerHint 451 * 452 * DESCRIPTION: Sets the requested power hint and state to power HAL. 453 * 454 * PARAMETERS : 455 * hint : Power hint 456 * enable : Enable power hint if set to 1. Disable if set to 0. 457 * RETURN : void 458 * 459 *==========================================================================*/ 460 void QCameraPerfLock::powerHint(power_hint_t hint, uint32_t enable) 461 { 462 #ifdef HAS_MULTIMEDIA_HINTS 463 if (mCurrentPowerHintEnable) { 464 //disable previous hint 465 powerHintInternal(mCurrentPowerHint, 0); 466 } 467 powerHintInternal(hint, enable); 468 469 mCurrentPowerHint = hint; 470 mCurrentPowerHintEnable = enable; 471 #endif 472 } 473 474 }; // namespace qcamera 475