power: apply angler/bullhead changes for 8994 and 8992

power-hal: Fix make file to use correct power hal library

Fix make file to use correct power hal library

Change-Id: Iffc6d61d48cba02860f92073ca31c945d970f3be

power: Update hint action for camera hint

Update the hint action of the camera hint to
switch the little/big configuration to 4+0
with the little cores running at 1.2GHz Fmax.

Change-Id: I7398412821b1420321d13e830a46e87241dccce4

Delay video encode power hint for 2s.

Improves camera startup significantly.

bug 24180717

Change-Id: I700684816e28805904e787cc3e0278ee5d5b60a6

Fix power hint.

There was a race where the power hint could be left enabled accidentally
if the camera was quit too quickly.

bug 24314633

Change-Id: I6e78534ab29c58f8d87ae55eedc9ff8fb0a8f7c8

Modify screen-off behavior.

Set sched_upmigrate to 99 and sched_downmigrate to 95 when the screen is
off. This will make it harder to use the big cores when the screen is
off (saving power), but will still allow them to be used in case there
is actually a heavyweight task running.

bug 24130678

Change-Id: I8a8638f62e18cc8fac819d95c17e97ed4ff7e193

power: modify touch boost to impact sched migration

Change-Id: I0ae372bf66b89393157f26adbcd81e394c8479ff

power: support duration hint to improve fling behavior

Change-Id: I3352ab9d55d0f978bdb09f5fe930fcde466e1e8a

power: extend little core freq boost during fling

Change-Id: I5c824ca6bc6a5a1fe51523ae9d1ece17546932bb

power: Change touch boost behavior: extent and handles.

This patch does three things:

1. Changes the upmigrate/downmigrate values based on the last boost.
Any touch within 750ms will result in higher upmigrate/downmigrate
values. This is used to approximate detection of constant
input (typing).

2. Moves to multiple handles for handling touch boost rather than
reusing the same handle for each successive component of the boost.

3. Rate limits the boost such that we don't boost more than every 250ms.

Change-Id: Iebc65c46d934ec518975a7452663ec872d0dee18

power: fix rate limiting for flings.

We were incorrectly limiting sched_upmigrate on a fling. Instead, allow
a fling to use the lowest sched_upmigrate.

Change-Id: I047a3f69748fb56f98caac902ed25d45e6289f01

power: Enable touch boost during camera on 8994

Previously, the video encode hint would hotplug the big cores off while
the camera was running in order to improve thermals and power
consumption. Instead, have the camera run the big cores at 384MHz so we
can still apply POWER_HINT_INTERACTION.

Change-Id: I5ee2559132a52ddba0ecba07bfb7238cc0d5770e
This commit is contained in:
Jake Weinstein 2015-12-28 00:42:13 +00:00
parent 7a05eb714d
commit c89b5f2310
5 changed files with 336 additions and 30 deletions

View File

@ -7,6 +7,7 @@ ifeq ($(call is-vendor-board-platform,QCOM),true)
include $(CLEAR_VARS)
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MULTILIB := both
LOCAL_SHARED_LIBRARIES := liblog libcutils libdl
LOCAL_SRC_FILES := power.c metadata-parser.c utils.c list.c hint-data.c

View File

@ -35,8 +35,10 @@
#include <fcntl.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#define LOG_TAG "QCOM PowerHAL"
#define LOG_TAG "QCOMPowerHAL"
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/power.h>
@ -47,6 +49,50 @@
#include "performance.h"
#include "power-common.h"
pthread_mutex_t video_encode_lock = PTHREAD_MUTEX_INITIALIZER;
uintptr_t video_encode_hint_counter = 0;
bool video_encode_hint_should_enable = false;
bool video_encode_hint_is_enabled = false;
static int new_hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
static int cur_hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
static const time_t VIDEO_ENCODE_DELAY_SECONDS = 2;
static const time_t VIDEO_ENCODE_DELAY_NSECONDS = 0;
static void* video_encode_hint_function(void* arg) {
struct timespec tv = {0};
tv.tv_sec = VIDEO_ENCODE_DELAY_SECONDS;
tv.tv_nsec = VIDEO_ENCODE_DELAY_NSECONDS;
int nanosleep_ret = 0;
uintptr_t expected_counter = (uintptr_t)arg;
// delay the hint for two seconds
// the hint hotplugs the large CPUs, so this prevents the large CPUs from
// going offline until the camera has had time to startup
TEMP_FAILURE_RETRY(nanosleep(&tv, &tv));
pthread_mutex_lock(&video_encode_lock);
// check to ensure we should still turn on hint from this particular thread
// if should_enable is true but counter is different, another thread owns hint
// if should_enable is false, we've already quit the camera
if (video_encode_hint_should_enable == true && video_encode_hint_counter == expected_counter) {
/* sched and cpufreq params
A53: 4 cores online at 1.2GHz max, 960 min
A57: 4 cores online at 384 max, 384 min
*/
int resource_values[] = {0x150C, 0x1F03, 0x2303};
perform_hint_action(new_hint_id,
resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
cur_hint_id = new_hint_id;
video_encode_hint_is_enabled = true;
video_encode_hint_should_enable = false;
}
pthread_mutex_unlock(&video_encode_lock);
return NULL;
}
static int display_hint_sent;
static int process_video_encode_hint(void *metadata)
@ -78,22 +124,37 @@ static int process_video_encode_hint(void *metadata)
if (video_encode_metadata.state == 1) {
if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
/* sched and cpufreq params
* hispeed freq - 768 MHz
* target load - 90
* above_hispeed_delay - 40ms
* sched_small_tsk - 50
*/
int resource_values[] = {0x2C07, 0x2F5A, 0x2704, 0x4032};
pthread_t video_encode_hint_thread;
pthread_mutex_lock(&video_encode_lock);
new_hint_id = video_encode_metadata.hint_id;
if (video_encode_hint_counter < 65535) {
video_encode_hint_counter++;
} else {
video_encode_hint_counter = 0;
}
// start new thread to launch hint
video_encode_hint_should_enable = true;
if (pthread_create(&video_encode_hint_thread, NULL, video_encode_hint_function, (void*)video_encode_hint_counter) != 0) {
ALOGE("Error constructing hint thread");
video_encode_hint_should_enable = false;
pthread_mutex_unlock(&video_encode_lock);
return HINT_NONE;
}
pthread_detach(video_encode_hint_thread);
pthread_mutex_unlock(&video_encode_lock);
perform_hint_action(video_encode_metadata.hint_id,
resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
return HINT_HANDLED;
}
} else if (video_encode_metadata.state == 0) {
if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
undo_hint_action(video_encode_metadata.hint_id);
pthread_mutex_lock(&video_encode_lock);
video_encode_hint_should_enable = false;
if (video_encode_hint_is_enabled == true) {
undo_hint_action(cur_hint_id);
video_encode_hint_is_enabled = false;
}
pthread_mutex_unlock(&video_encode_lock);
return HINT_HANDLED;
}
}
@ -107,6 +168,83 @@ int power_hint_override(struct power_module *module, power_hint_t hint, void *da
case POWER_HINT_VIDEO_ENCODE:
ret_val = process_video_encode_hint(data);
break;
case POWER_HINT_INTERACTION:
{
int duration_hint = 0;
static unsigned long long previous_boost_time = 0;
// little core freq bump for 1.5s
int resources[] = {0x20C};
int duration = 1500;
static int handle_little = 0;
// big core freq bump for 500ms
int resources_big[] = {0x2312, 0x1F08};
int duration_big = 500;
static int handle_big = 0;
// sched_downmigrate lowered to 10 for 1s at most
// should be half of upmigrate
int resources_downmigrate[] = {0x4F00};
int duration_downmigrate = 1000;
static int handle_downmigrate = 0;
// sched_upmigrate lowered to at most 20 for 500ms
// set threshold based on elapsed time since last boost
int resources_upmigrate[] = {0x4E00};
int duration_upmigrate = 500;
static int handle_upmigrate = 0;
// set duration hint
if (data) {
duration_hint = *((int*)data);
}
struct timeval cur_boost_timeval = {0, 0};
gettimeofday(&cur_boost_timeval, NULL);
unsigned long long cur_boost_time = cur_boost_timeval.tv_sec * 1000000 + cur_boost_timeval.tv_usec;
double elapsed_time = (double)(cur_boost_time - previous_boost_time);
if (elapsed_time > 750000)
elapsed_time = 750000;
// don't hint if it's been less than 250ms since last boost
// also detect if we're doing anything resembling a fling
// support additional boosting in case of flings
else if (elapsed_time < 250000 && duration_hint <= 750)
return;
// keep sched_upmigrate high when flinging
if (duration_hint >= 750)
upmigrate_value = 20;
// 95: default upmigrate for phone
// 20: upmigrate for sporadic touch
// 750ms: a completely arbitrary threshold for last touch
int upmigrate_value = 95 - (int)(75. * ((elapsed_time*elapsed_time) / (750000.*750000.)));
previous_boost_time = cur_boost_time;
resources_upmigrate[0] = resources_upmigrate[0] | upmigrate_value;
resources_downmigrate[0] = resources_downmigrate[0] | (upmigrate_value / 2);
// modify downmigrate duration based on interaction data hint
// 1000 <= duration_downmigrate <= 5000
// extend little core freq bump past downmigrate to soften downmigrates
if (duration_hint > 1000) {
if (duration_hint < 5000) {
duration_downmigrate = duration_hint;
duration = duration_hint + 750;
} else {
duration_downmigrate = 5000;
duration = 5750;
}
}
handle_little = interaction_with_handle(handle_little,duration, sizeof(resources)/sizeof(resources[0]), resources);
handle_big = interaction_with_handle(handle_big, duration_big, sizeof(resources_big)/sizeof(resources_big[0]), resources_big);
handle_downmigrate = interaction_with_handle(handle_downmigrate, duration_downmigrate, sizeof(resources_downmigrate)/sizeof(resources_downmigrate[0]), resources_downmigrate);
handle_upmigrate = interaction_with_handle(handle_upmigrate, duration_upmigrate, sizeof(resources_upmigrate)/sizeof(resources_upmigrate[0]), resources_upmigrate);
ret_val = HINT_HANDLED;
}
break;
default:
break;
}
@ -127,7 +265,9 @@ int set_interactive_override(struct power_module *module, int on)
/* Display off */
if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
int resource_values[] = {0x777}; /* 4+0 core config in display off */
// sched upmigrate = 99, sched downmigrate = 95
// keep the big cores around, but make them very hard to use
int resource_values[] = {0x4E63, 0x4F5F};
if (!display_hint_sent) {
perform_hint_action(DISPLAY_STATE_HINT_ID,
resource_values, sizeof(resource_values)/sizeof(resource_values[0]));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, The Linux Foundation. All rights reserved.
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@ -35,8 +35,10 @@
#include <fcntl.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#define LOG_TAG "QCOM PowerHAL"
#define LOG_TAG "QCOMPowerHAL"
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/power.h>
@ -47,6 +49,50 @@
#include "performance.h"
#include "power-common.h"
pthread_mutex_t video_encode_lock = PTHREAD_MUTEX_INITIALIZER;
uintptr_t video_encode_hint_counter = 0;
bool video_encode_hint_should_enable = false;
bool video_encode_hint_is_enabled = false;
static int new_hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
static int cur_hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
static const time_t VIDEO_ENCODE_DELAY_SECONDS = 2;
static const time_t VIDEO_ENCODE_DELAY_NSECONDS = 0;
static void* video_encode_hint_function(void* arg) {
struct timespec tv = {0};
tv.tv_sec = VIDEO_ENCODE_DELAY_SECONDS;
tv.tv_nsec = VIDEO_ENCODE_DELAY_NSECONDS;
int nanosleep_ret = 0;
uintptr_t expected_counter = (uintptr_t)arg;
// delay the hint for two seconds
// the hint hotplugs the large CPUs, so this prevents the large CPUs from
// going offline until the camera has had time to startup
TEMP_FAILURE_RETRY(nanosleep(&tv, &tv));
pthread_mutex_lock(&video_encode_lock);
// check to ensure we should still turn on hint from this particular thread
// if should_enable is true but counter is different, another thread owns hint
// if should_enable is false, we've already quit the camera
if (video_encode_hint_should_enable == true && video_encode_hint_counter == expected_counter) {
/* sched and cpufreq params
A53: 4 cores online at 1.2GHz max, 960 min
A57: 4 cores online at 384 max, 384 min
*/
int resource_values[] = {0x150C, 0x1F03, 0x2303};
perform_hint_action(new_hint_id,
resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
cur_hint_id = new_hint_id;
video_encode_hint_is_enabled = true;
video_encode_hint_should_enable = false;
}
pthread_mutex_unlock(&video_encode_lock);
return NULL;
}
static int display_hint_sent;
static int process_video_encode_hint(void *metadata)
@ -78,35 +124,131 @@ static int process_video_encode_hint(void *metadata)
if (video_encode_metadata.state == 1) {
if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
/* sched and cpufreq params
* hispeed freq - 768 MHz
* target load - 90
* above_hispeed_delay - 40ms
* sched_small_tsk - 50
*/
int resource_values[] = {0x2C07, 0x2F5A, 0x2704, 0x4032};
pthread_t video_encode_hint_thread;
pthread_mutex_lock(&video_encode_lock);
new_hint_id = video_encode_metadata.hint_id;
if (video_encode_hint_counter < 65535) {
video_encode_hint_counter++;
} else {
video_encode_hint_counter = 0;
}
// start new thread to launch hint
video_encode_hint_should_enable = true;
if (pthread_create(&video_encode_hint_thread, NULL, video_encode_hint_function, (void*)video_encode_hint_counter) != 0) {
ALOGE("Error constructing hint thread");
video_encode_hint_should_enable = false;
pthread_mutex_unlock(&video_encode_lock);
return HINT_NONE;
}
pthread_detach(video_encode_hint_thread);
pthread_mutex_unlock(&video_encode_lock);
perform_hint_action(video_encode_metadata.hint_id,
resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
return HINT_HANDLED;
}
} else if (video_encode_metadata.state == 0) {
if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
undo_hint_action(video_encode_metadata.hint_id);
pthread_mutex_lock(&video_encode_lock);
video_encode_hint_should_enable = false;
if (video_encode_hint_is_enabled == true) {
undo_hint_action(cur_hint_id);
video_encode_hint_is_enabled = false;
}
pthread_mutex_unlock(&video_encode_lock);
return HINT_HANDLED;
}
}
return HINT_NONE;
}
int power_hint_override(struct power_module *module, power_hint_t hint, void *data)
/* Declare function before use */
int interaction(int duration, int num_args, int opt_list[]);
int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[]);
static void power_hint_override(struct power_module *module, power_hint_t hint, void *data)
{
int ret_val = HINT_NONE;
switch(hint) {
case POWER_HINT_VIDEO_ENCODE:
ret_val = process_video_encode_hint(data);
break;
case POWER_HINT_INTERACTION:
{
int duration_hint = 0;
static unsigned long long previous_boost_time = 0;
// little core freq bump for 1.5s
int resources[] = {0x20C};
int duration = 1500;
static int handle_little = 0;
// big core freq bump for 500ms
int resources_big[] = {0x2312, 0x1F08};
int duration_big = 500;
static int handle_big = 0;
// sched_downmigrate lowered to 10 for 1s at most
// should be half of upmigrate
int resources_downmigrate[] = {0x4F00};
int duration_downmigrate = 1000;
static int handle_downmigrate = 0;
// sched_upmigrate lowered to at most 20 for 500ms
// set threshold based on elapsed time since last boost
int resources_upmigrate[] = {0x4E00};
int duration_upmigrate = 500;
static int handle_upmigrate = 0;
// set duration hint
if (data) {
duration_hint = *((int*)data);
}
struct timeval cur_boost_timeval = {0, 0};
gettimeofday(&cur_boost_timeval, NULL);
unsigned long long cur_boost_time = cur_boost_timeval.tv_sec * 1000000 + cur_boost_timeval.tv_usec;
double elapsed_time = (double)(cur_boost_time - previous_boost_time);
if (elapsed_time > 750000)
elapsed_time = 750000;
// don't hint if it's been less than 250ms since last boost
// also detect if we're doing anything resembling a fling
// support additional boosting in case of flings
else if (elapsed_time < 250000 && duration_hint <= 750)
return;
// 95: default upmigrate for phone
// 20: upmigrate for sporadic touch
// 750ms: a completely arbitrary threshold for last touch
int upmigrate_value = 95 - (int)(75. * ((elapsed_time*elapsed_time) / (750000.*750000.)));
// keep sched_upmigrate high when flinging
if (duration_hint >= 750)
upmigrate_value = 20;
previous_boost_time = cur_boost_time;
resources_upmigrate[0] = resources_upmigrate[0] | upmigrate_value;
resources_downmigrate[0] = resources_downmigrate[0] | (upmigrate_value / 2);
// modify downmigrate duration based on interaction data hint
// 1000 <= duration_downmigrate <= 5000
// extend little core freq bump past downmigrate to soften downmigrates
if (duration_hint > 1000) {
if (duration_hint < 5000) {
duration_downmigrate = duration_hint;
duration = duration_hint + 750;
} else {
duration_downmigrate = 5000;
duration = 5750;
}
}
handle_little = interaction_with_handle(handle_little,duration, sizeof(resources)/sizeof(resources[0]), resources);
handle_big = interaction_with_handle(handle_big, duration_big, sizeof(resources_big)/sizeof(resources_big[0]), resources_big);
handle_downmigrate = interaction_with_handle(handle_downmigrate, duration_downmigrate, sizeof(resources_downmigrate)/sizeof(resources_downmigrate[0]), resources_downmigrate);
handle_upmigrate = interaction_with_handle(handle_upmigrate, duration_upmigrate, sizeof(resources_upmigrate)/sizeof(resources_upmigrate[0]), resources_upmigrate);
ret_val = HINT_HANDLED;
}
break;
default:
break;
}
@ -127,7 +269,9 @@ int set_interactive_override(struct power_module *module, int on)
/* Display off */
if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
int resource_values[] = {0x777}; /* 4+0 core config in display off */
// sched upmigrate = 99, sched downmigrate = 95
// keep the big cores around, but make them very hard to use
int resource_values[] = {0x4E63, 0x4F5F};
if (!display_hint_sent) {
perform_hint_action(DISPLAY_STATE_HINT_ID,
resource_values, sizeof(resource_values)/sizeof(resource_values[0]));

View File

@ -195,6 +195,11 @@ int __attribute__ ((weak)) power_hint_override(struct power_module *module, powe
return HINT_NONE;
}
/* Declare function before use */
int interaction(int duration, int num_args, int opt_list[]);
int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[]);
static void power_hint(struct power_module *module, power_hint_t hint,
void *data)
{

View File

@ -39,7 +39,7 @@
#include "hint-data.h"
#include "power-common.h"
#define LOG_TAG "QCOM PowerHAL"
#define LOG_TAG "QCOMPowerHAL"
#include <utils/Log.h>
char scaling_gov_path[4][80] ={
@ -198,12 +198,12 @@ int get_scaling_governor_check_cores(char governor[], int size,int core_num)
return 0;
}
void interaction(int duration, int num_args, int opt_list[])
int interaction(int duration, int num_args, int opt_list[])
{
static int lock_handle = 0;
int lock_handle = 0;
if (duration < 0 || num_args < 1 || opt_list[0] == NULL)
return;
return 0;
if (qcopt_handle) {
if (perf_lock_acq) {
@ -212,6 +212,22 @@ void interaction(int duration, int num_args, int opt_list[])
ALOGE("Failed to acquire lock.");
}
}
return lock_handle;
}
int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[])
{
if (duration < 0 || num_args < 1 || opt_list[0] == NULL)
return 0;
if (qcopt_handle) {
if (perf_lock_acq) {
lock_handle = perf_lock_acq(lock_handle, duration, opt_list, num_args);
if (lock_handle == -1)
ALOGE("Failed to acquire lock.");
}
}
return lock_handle;
}
void perform_hint_action(int hint_id, int resource_values[], int num_resources)