1 /* 2 * Copyright (c) 2015, 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 #define LOG_NIDEBUG 0 30 31 #include <errno.h> 32 #include <string.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 #include <dlfcn.h> 37 #include <stdlib.h> 38 #include <pthread.h> 39 #include <stdbool.h> 40 41 #define LOG_TAG "QCOMPowerHAL" 42 #include <utils/Log.h> 43 #include <hardware/hardware.h> 44 #include <hardware/power.h> 45 46 #include "utils.h" 47 #include "metadata-defs.h" 48 #include "hint-data.h" 49 #include "performance.h" 50 #include "power-common.h" 51 52 pthread_mutex_t video_encode_lock = PTHREAD_MUTEX_INITIALIZER; 53 uintptr_t video_encode_hint_counter = 0; 54 bool video_encode_hint_should_enable = false; 55 bool video_encode_hint_is_enabled = false; 56 57 static int new_hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 58 static int cur_hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 59 60 static const time_t VIDEO_ENCODE_DELAY_SECONDS = 2; 61 static const time_t VIDEO_ENCODE_DELAY_NSECONDS = 0; 62 63 static void* video_encode_hint_function(void* arg) { 64 struct timespec tv = {0}; 65 tv.tv_sec = VIDEO_ENCODE_DELAY_SECONDS; 66 tv.tv_nsec = VIDEO_ENCODE_DELAY_NSECONDS; 67 int nanosleep_ret = 0; 68 uintptr_t expected_counter = (uintptr_t)arg; 69 70 // delay the hint for two seconds 71 // the hint hotplugs the large CPUs, so this prevents the large CPUs from 72 // going offline until the camera has had time to startup 73 TEMP_FAILURE_RETRY(nanosleep(&tv, &tv)); 74 pthread_mutex_lock(&video_encode_lock); 75 76 // check to ensure we should still turn on hint from this particular thread 77 // if should_enable is true but counter is different, another thread owns hint 78 // if should_enable is false, we've already quit the camera 79 if (video_encode_hint_should_enable == true && video_encode_hint_counter == expected_counter) { 80 /* sched and cpufreq params 81 A53: 4 cores online at 1.2GHz max, 960 min 82 A57: 4 cores online at 384 max, 384 min 83 */ 84 int resource_values[] = {0x150C, 0x1F03, 0x2303}; 85 perform_hint_action(new_hint_id, 86 resource_values, sizeof(resource_values)/sizeof(resource_values[0])); 87 cur_hint_id = new_hint_id; 88 video_encode_hint_is_enabled = true; 89 video_encode_hint_should_enable = false; 90 } 91 92 pthread_mutex_unlock(&video_encode_lock); 93 return NULL; 94 } 95 96 static int display_hint_sent; 97 98 static int process_video_encode_hint(void *metadata) 99 { 100 char governor[80]; 101 struct video_encode_metadata_t video_encode_metadata; 102 103 if (get_scaling_governor(governor, sizeof(governor)) == -1) { 104 ALOGE("Can't obtain scaling governor."); 105 106 return HINT_NONE; 107 } 108 109 /* Initialize encode metadata struct fields */ 110 memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); 111 video_encode_metadata.state = -1; 112 video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 113 114 if (metadata) { 115 if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) == 116 -1) { 117 ALOGE("Error occurred while parsing metadata."); 118 return HINT_NONE; 119 } 120 } else { 121 return HINT_NONE; 122 } 123 124 if (video_encode_metadata.state == 1) { 125 if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 126 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 127 pthread_t video_encode_hint_thread; 128 pthread_mutex_lock(&video_encode_lock); 129 new_hint_id = video_encode_metadata.hint_id; 130 if (video_encode_hint_counter < 65535) { 131 video_encode_hint_counter++; 132 } else { 133 video_encode_hint_counter = 0; 134 } 135 // start new thread to launch hint 136 video_encode_hint_should_enable = true; 137 if (pthread_create(&video_encode_hint_thread, NULL, video_encode_hint_function, (void*)video_encode_hint_counter) != 0) { 138 ALOGE("Error constructing hint thread"); 139 video_encode_hint_should_enable = false; 140 pthread_mutex_unlock(&video_encode_lock); 141 return HINT_NONE; 142 } 143 pthread_detach(video_encode_hint_thread); 144 pthread_mutex_unlock(&video_encode_lock); 145 146 return HINT_HANDLED; 147 } 148 } else if (video_encode_metadata.state == 0) { 149 if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 150 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 151 pthread_mutex_lock(&video_encode_lock); 152 video_encode_hint_should_enable = false; 153 if (video_encode_hint_is_enabled == true) { 154 undo_hint_action(cur_hint_id); 155 video_encode_hint_is_enabled = false; 156 } 157 pthread_mutex_unlock(&video_encode_lock); 158 return HINT_HANDLED; 159 } 160 } 161 return HINT_NONE; 162 } 163 164 int power_hint_override(struct power_module *module, power_hint_t hint, void *data) 165 { 166 int ret_val = HINT_NONE; 167 switch(hint) { 168 case POWER_HINT_VIDEO_ENCODE: 169 ret_val = process_video_encode_hint(data); 170 break; 171 default: 172 break; 173 } 174 return ret_val; 175 } 176 177 int set_interactive_override(struct power_module *module, int on) 178 { 179 char governor[80]; 180 181 if (get_scaling_governor(governor, sizeof(governor)) == -1) { 182 ALOGE("Can't obtain scaling governor."); 183 184 return HINT_NONE; 185 } 186 187 if (!on) { 188 /* Display off */ 189 if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 190 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 191 // sched upmigrate = 99, sched downmigrate = 95 192 // keep the big cores around, but make them very hard to use 193 int resource_values[] = {0x4E63, 0x4F5F}; 194 if (!display_hint_sent) { 195 perform_hint_action(DISPLAY_STATE_HINT_ID, 196 resource_values, sizeof(resource_values)/sizeof(resource_values[0])); 197 display_hint_sent = 1; 198 return HINT_HANDLED; 199 } 200 } 201 } else { 202 /* Display on */ 203 if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 204 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 205 undo_hint_action(DISPLAY_STATE_HINT_ID); 206 display_hint_sent = 0; 207 return HINT_HANDLED; 208 } 209 } 210 return HINT_NONE; 211 } 212