Home | History | Annotate | Download | only in util
      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