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 *==========================================================================*/
QCameraPerfLock()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 *==========================================================================*/
~QCameraPerfLock()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 *==========================================================================*/
lock_init()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 *==========================================================================*/
lock_deinit()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 *==========================================================================*/
isTimerReset()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 *==========================================================================*/
startTimer(uint32_t timer_val)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 *==========================================================================*/
lock_acq_timed(int32_t timer_val)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 *==========================================================================*/
lock_acq()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 *==========================================================================*/
lock_rel_timed()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 *==========================================================================*/
lock_rel()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 *==========================================================================*/
powerHintInternal(power_hint_t hint,uint32_t enable)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 *==========================================================================*/
powerHint(power_hint_t hint,uint32_t enable)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