blob: e7daa0876bb05ad8a9353ae7a15ce67d1be48a1c [file] [log] [blame]
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +05301/*
2 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
Michael Bestas47636f62018-05-25 21:30:28 +03003 * Copyright (C) 2018 The LineageOS Project
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +05304 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 * * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer in the documentation and/or other materials provided
13 * with the distribution.
14 * * Neither the name of The Linux Foundation nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#define LOG_NIDEBUG 0
32
33#include <errno.h>
BeYkeRYktbd52e812018-12-13 06:42:35 +090034#include <time.h>
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +053035#include <string.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <fcntl.h>
39#include <dlfcn.h>
40#include <stdlib.h>
41
Michael Bestas1add9ac2018-03-25 22:56:44 +030042#define LOG_TAG "QCOM PowerHAL"
Ethan Chena42f4a82018-03-01 21:31:15 -080043#include <log/log.h>
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +053044#include <hardware/hardware.h>
45#include <hardware/power.h>
46
47#include "utils.h"
48#include "metadata-defs.h"
49#include "hint-data.h"
50#include "performance.h"
51#include "power-common.h"
52
Nikhil Kumar Kansal839d56f2017-04-18 15:50:25 +053053#define MIN_VAL(X,Y) ((X>Y)?(Y):(X))
54
tomascus8b038b12019-02-19 17:15:58 +110055const int kMaxLaunchDuration = 5000; /* ms */
BeYkeRYktbd52e812018-12-13 06:42:35 +090056const int kMaxInteractiveDuration = 5000; /* ms */
tomascus1c38bac2019-02-13 14:42:27 +110057const int kMinInteractiveDuration = 400; /* ms */
BeYkeRYktbd52e812018-12-13 06:42:35 +090058
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +053059static int video_encode_hint_sent;
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +053060
dianlujitao93023a22018-09-06 17:45:43 +080061static int current_power_profile = PROFILE_BALANCED;
62
63static int profile_high_performance[] = {
64 ALL_CPUS_PWR_CLPS_DIS_V3, 0x1,
65 SCHED_BOOST_ON_V3, 0x1,
66 SCHED_MOSTLY_IDLE_NR_RUN, 0x1,
67 SCHED_SPILL_NR_RUN, 0x1,
68 SCHED_RESTRICT_CLUSTER_SPILL, 0x0,
69 SCHED_GROUP_DOWN_MIGRATE, 0x5F,
70 SCHED_GROUP_UP_MIGRATE, 0x64,
71 CPUS_ONLINE_MIN_BIG, 0x4,
72 MIN_FREQ_BIG_CORE_0, 0xFFF,
73 MIN_FREQ_LITTLE_CORE_0, 0xFFF,
74};
75
76static int profile_power_save[] = {
77 CPUS_ONLINE_MAX_BIG, 0x2,
78 MAX_FREQ_BIG_CORE_0, 0x0,
79 MAX_FREQ_LITTLE_CORE_0, 0x0,
80};
81
82static int profile_bias_power[] = {
83 CPUS_ONLINE_MAX_BIG, 0x2,
84 MAX_FREQ_BIG_CORE_0_RESIDX, 0x3,
85 MAX_FREQ_LITTLE_CORE_0_RESIDX, 0x1,
86};
87
88static int profile_bias_performance[] = {
89 MIN_FREQ_BIG_CORE_0_RESIDX, 0x3,
90 MIN_FREQ_LITTLE_CORE_0_RESIDX, 0x2,
91};
92
93#ifdef INTERACTION_BOOST
94int get_number_of_profiles()
95{
96 return 5;
97}
98#endif
99
dianlujitao8780cb72019-02-23 20:24:57 +0800100static int set_power_profile(void *data)
dianlujitao93023a22018-09-06 17:45:43 +0800101{
dianlujitao8780cb72019-02-23 20:24:57 +0800102 int profile = data ? *((int*)data) : 0;
dianlujitao93023a22018-09-06 17:45:43 +0800103 int ret = -EINVAL;
104 const char *profile_name = NULL;
105
106 if (profile == current_power_profile)
107 return 0;
108
109 ALOGV("%s: Profile=%d", __func__, profile);
110
111 if (current_power_profile != PROFILE_BALANCED) {
112 undo_hint_action(DEFAULT_PROFILE_HINT_ID);
113 ALOGV("%s: Hint undone", __func__);
114 current_power_profile = PROFILE_BALANCED;
115 }
116
117 if (profile == PROFILE_POWER_SAVE) {
118 ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_power_save,
119 ARRAY_SIZE(profile_power_save));
120 profile_name = "powersave";
121
122 } else if (profile == PROFILE_HIGH_PERFORMANCE) {
123 ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID,
124 profile_high_performance, ARRAY_SIZE(profile_high_performance));
125 profile_name = "performance";
126
127 } else if (profile == PROFILE_BIAS_POWER) {
128 ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_bias_power,
129 ARRAY_SIZE(profile_bias_power));
130 profile_name = "bias power";
131
132 } else if (profile == PROFILE_BIAS_PERFORMANCE) {
133 ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID,
134 profile_bias_performance, ARRAY_SIZE(profile_bias_performance));
135 profile_name = "bias perf";
136 } else if (profile == PROFILE_BALANCED) {
137 ret = 0;
138 profile_name = "balanced";
139 }
140
141 if (ret == 0) {
142 current_power_profile = profile;
143 ALOGD("%s: Set %s mode", __func__, profile_name);
144 }
145 return ret;
146}
147
Zhao Wei Liew6fe52522016-07-19 19:57:06 +0800148/**
Zhao Wei Liew143f8072018-11-02 00:33:14 +0000149 * Returns true if the target is SDM630.
Zhao Wei Liew6fe52522016-07-19 19:57:06 +0800150 */
151static bool is_target_SDM630(void)
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530152{
Zhao Wei Liew143f8072018-11-02 00:33:14 +0000153 static int is_SDM630 = -1;
Zhao Wei Liew6fe52522016-07-19 19:57:06 +0800154 int soc_id;
155
Zhao Wei Liew143f8072018-11-02 00:33:14 +0000156 if (is_SDM630 >= 0)
157 return is_SDM630;
158
Zhao Wei Liew6fe52522016-07-19 19:57:06 +0800159 soc_id = get_soc_id();
Zhao Wei Liew143f8072018-11-02 00:33:14 +0000160 is_SDM630 = soc_id == 318 || soc_id == 327;
Zhao Wei Liew6fe52522016-07-19 19:57:06 +0800161
162 return is_SDM630;
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530163}
164
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530165static void process_video_encode_hint(void *metadata)
166{
167 char governor[80];
168 int resource_values[20];
169 int num_resources;
170 struct video_encode_metadata_t video_encode_metadata;
171
Michael Bestas47636f62018-05-25 21:30:28 +0300172 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU0) == -1) {
173 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU1) == -1) {
174 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU2) == -1) {
175 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU3) == -1) {
176 ALOGE("Can't obtain scaling governor.");
177 return;
178 }
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530179 }
Michael Bestas47636f62018-05-25 21:30:28 +0300180 }
181 }
182
183 if (!metadata) {
184 return;
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530185 }
186
187 /* Initialize encode metadata struct fields. */
188 memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
189 video_encode_metadata.state = -1;
190 video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
191
Michael Bestas47636f62018-05-25 21:30:28 +0300192 if (parse_video_encode_metadata((char *)metadata,
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530193 &video_encode_metadata) == -1) {
Michael Bestas47636f62018-05-25 21:30:28 +0300194 ALOGE("Error occurred while parsing metadata.");
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530195 return;
196 }
197
198 if (video_encode_metadata.state == 1) {
Ethan Chen4b4acdf2018-03-01 21:41:04 -0800199 if (is_interactive_governor(governor)) {
Michael Bestas47636f62018-05-25 21:30:28 +0300200 if (is_target_SDM630()) {
201 /*
202 1. CPUfreq params
203 - hispeed freq for big - 1113Mhz
204 - go hispeed load for big - 95
205 - above_hispeed_delay for big - 40ms
206 - target loads - 95
207 - nr_run - 5
208 2. BusDCVS V2 params
209 - Sample_ms of 10ms
210 */
211 int res[] = {
212 HISPEED_FREQ_BIG, 0x459,
213 GO_HISPEED_LOAD_BIG, 0x5F,
214 ABOVE_HISPEED_DELAY_BIG, 0x4,
215 TARGET_LOADS_BIG, 0x5F,
dianlujitao5eb472d2018-09-06 21:43:14 +0800216 SCHED_SPILL_NR_RUN, 0X5,
Michael Bestas47636f62018-05-25 21:30:28 +0300217 CPUBW_HWMON_SAMPLE_MS, 0xA
218 };
Nikhil Kumar Kansal839d56f2017-04-18 15:50:25 +0530219 memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
Zhao Wei Liewd4fe61e2016-06-26 11:37:59 +0800220 num_resources = ARRAY_SIZE(res);
Michael Bestas47636f62018-05-25 21:30:28 +0300221 } else {
222 /*
223 1. CPUfreq params
224 - hispeed freq for little - 902Mhz
225 - go hispeed load for little - 95
226 - above_hispeed_delay for little - 40ms
227 2. BusDCVS V2 params
228 - Sample_ms of 10ms
229 */
230 int res[] = {
231 HISPEED_FREQ_LITTLE, 0x386,
232 GO_HISPEED_LOAD_LITTLE, 0x5F,
233 ABOVE_HISPEED_DELAY_LITTLE, 0x4,
234 CPUBW_HWMON_SAMPLE_MS, 0xA
235 };
Nikhil Kumar Kansal839d56f2017-04-18 15:50:25 +0530236 memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
Zhao Wei Liewd4fe61e2016-06-26 11:37:59 +0800237 num_resources = ARRAY_SIZE(res);
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530238 }
Michael Bestas50a6e282018-05-25 21:33:46 +0300239 if (!video_encode_hint_sent) {
240 perform_hint_action(video_encode_metadata.hint_id,
241 resource_values, num_resources);
242 video_encode_hint_sent = 1;
243 }
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530244 }
245 } else if (video_encode_metadata.state == 0) {
Ethan Chen4b4acdf2018-03-01 21:41:04 -0800246 if (is_interactive_governor(governor)) {
Michael Bestas50a6e282018-05-25 21:33:46 +0300247 undo_hint_action(video_encode_metadata.hint_id);
248 video_encode_hint_sent = 0;
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530249 }
250 }
Michael Bestas47636f62018-05-25 21:30:28 +0300251}
252
tomascus8b038b12019-02-19 17:15:58 +1100253static int process_activity_launch_hint(void *data)
BeYkeRYktbd52e812018-12-13 06:42:35 +0900254{
tomascus8b038b12019-02-19 17:15:58 +1100255 static int launch_handle = -1;
256 static int launch_mode = 0;
257
258 // release lock early if launch has finished
259 if (!data) {
260 if (CHECK_HANDLE(launch_handle)) {
261 release_request(launch_handle);
262 launch_handle = -1;
263 }
264 launch_mode = 0;
265 return HINT_HANDLED;
266 }
267
268 if (!launch_mode) {
269 launch_handle = perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST,
270 kMaxLaunchDuration, LAUNCH_BOOST_V1);
271 if (!CHECK_HANDLE(launch_handle)) {
272 ALOGE("Failed to perform launch boost");
273 return HINT_NONE;
274 }
275 launch_mode = 1;
276 }
277 return HINT_HANDLED;
BeYkeRYktbd52e812018-12-13 06:42:35 +0900278}
279
280static void process_interaction_hint(void *data)
281{
282 static struct timespec s_previous_boost_timespec;
283 static int s_previous_duration = 0;
284
285 struct timespec cur_boost_timespec;
286 long long elapsed_time;
287 int duration = kMinInteractiveDuration;
288
289 if (data) {
290 int input_duration = *((int*)data);
291 if (input_duration > duration) {
292 duration = (input_duration > kMaxInteractiveDuration) ?
293 kMaxInteractiveDuration : input_duration;
294 }
295 }
296
297 clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec);
298
299 elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec);
300 // don't hint if previous hint's duration covers this hint's duration
301 if ((s_previous_duration * 1000) > (elapsed_time + duration * 1000)) {
302 return;
303 }
304 s_previous_boost_timespec = cur_boost_timespec;
305 s_previous_duration = duration;
306
tomascus1c38bac2019-02-13 14:42:27 +1100307 perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, duration, SCROLL_VERTICAL);
BeYkeRYktbd52e812018-12-13 06:42:35 +0900308}
309
Michael Bestas47636f62018-05-25 21:30:28 +0300310int power_hint_override(power_hint_t hint, void *data)
311{
dianlujitao93023a22018-09-06 17:45:43 +0800312 if (hint == POWER_HINT_SET_PROFILE) {
dianlujitao8780cb72019-02-23 20:24:57 +0800313 if (set_power_profile(data) < 0)
dianlujitao93023a22018-09-06 17:45:43 +0800314 ALOGE("Setting power profile failed. perf HAL not started?");
315 return HINT_HANDLED;
316 }
317
318 // Skip other hints in high/low power modes
319 if (current_power_profile == PROFILE_POWER_SAVE ||
320 current_power_profile == PROFILE_HIGH_PERFORMANCE) {
321 return HINT_HANDLED;
322 }
323
Michael Bestas47636f62018-05-25 21:30:28 +0300324 switch (hint) {
325 case POWER_HINT_VSYNC:
326 break;
327 case POWER_HINT_VIDEO_ENCODE:
328 process_video_encode_hint(data);
329 return HINT_HANDLED;
BeYkeRYktbd52e812018-12-13 06:42:35 +0900330 case POWER_HINT_INTERACTION:
331 process_interaction_hint(data);
332 return HINT_HANDLED;
333 case POWER_HINT_LAUNCH:
tomascus8b038b12019-02-19 17:15:58 +1100334 return process_activity_launch_hint(data);
Michael Bestas47636f62018-05-25 21:30:28 +0300335 default:
336 break;
337 }
338 return HINT_NONE;
339}
340
341int set_interactive_override(int on)
342{
343 char governor[80];
344 int resource_values[20];
345 int num_resources;
346
347 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU0) == -1) {
348 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU1) == -1) {
349 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU2) == -1) {
350 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU3) == -1) {
351 ALOGE("Can't obtain scaling governor.");
352 return HINT_NONE;
353 }
354 }
355 }
356 }
357
358 if (!on) {
359 /* Display off. */
360 if (is_interactive_governor(governor)) {
361 if (is_target_SDM630()) {
362 /*
363 1. CPUfreq params
364 - hispeed freq for big - 1113Mhz
365 - go hispeed load for big - 95
366 - above_hispeed_delay for big - 40ms
367 2. BusDCVS V2 params
368 - Sample_ms of 10ms
369 */
370 int res[] = {
371 HISPEED_FREQ_BIG, 0x459,
372 GO_HISPEED_LOAD_BIG, 0x5F,
373 ABOVE_HISPEED_DELAY_BIG, 0x4,
374 CPUBW_HWMON_SAMPLE_MS, 0xA
375 };
376 memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
377 num_resources = ARRAY_SIZE(res);
378 } else {
379 /*
380 1. CPUfreq params
381 - hispeed freq for little - 902Mhz
382 - go hispeed load for little - 95
383 - above_hispeed_delay for little - 40ms
384 2. BusDCVS V2 params
385 - Sample_ms of 10ms
386 3. Sched group upmigrate - 500
387 */
388 int res[] = {
389 HISPEED_FREQ_LITTLE, 0x386,
390 GO_HISPEED_LOAD_LITTLE, 0x5F,
391 ABOVE_HISPEED_DELAY_LITTLE, 0x4,
392 CPUBW_HWMON_SAMPLE_MS, 0xA,
393 SCHED_GROUP_UP_MIGRATE, 0x1F4
394 };
395 memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
396 num_resources = ARRAY_SIZE(res);
397
398 }
399 perform_hint_action(DISPLAY_STATE_HINT_ID,
400 resource_values, num_resources);
401 }
402 } else {
403 /* Display on. */
404 if (is_interactive_governor(governor)) {
405 undo_hint_action(DISPLAY_STATE_HINT_ID);
406 }
407 }
408 return HINT_HANDLED;
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530409}