blob: ac1137e8950116a50778d4ba2b0aab74111dda82 [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>
34#include <string.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <fcntl.h>
38#include <dlfcn.h>
39#include <stdlib.h>
40
Michael Bestas1add9ac2018-03-25 22:56:44 +030041#define LOG_TAG "QCOM PowerHAL"
Ethan Chena42f4a82018-03-01 21:31:15 -080042#include <log/log.h>
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +053043#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
Nikhil Kumar Kansal839d56f2017-04-18 15:50:25 +053052#define MIN_VAL(X,Y) ((X>Y)?(Y):(X))
53
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +053054static int video_encode_hint_sent;
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +053055
dianlujitao93023a22018-09-06 17:45:43 +080056static int current_power_profile = PROFILE_BALANCED;
57
58static int profile_high_performance[] = {
59 ALL_CPUS_PWR_CLPS_DIS_V3, 0x1,
60 SCHED_BOOST_ON_V3, 0x1,
61 SCHED_MOSTLY_IDLE_NR_RUN, 0x1,
62 SCHED_SPILL_NR_RUN, 0x1,
63 SCHED_RESTRICT_CLUSTER_SPILL, 0x0,
64 SCHED_GROUP_DOWN_MIGRATE, 0x5F,
65 SCHED_GROUP_UP_MIGRATE, 0x64,
66 CPUS_ONLINE_MIN_BIG, 0x4,
67 MIN_FREQ_BIG_CORE_0, 0xFFF,
68 MIN_FREQ_LITTLE_CORE_0, 0xFFF,
69};
70
71static int profile_power_save[] = {
72 CPUS_ONLINE_MAX_BIG, 0x2,
73 MAX_FREQ_BIG_CORE_0, 0x0,
74 MAX_FREQ_LITTLE_CORE_0, 0x0,
75};
76
77static int profile_bias_power[] = {
78 CPUS_ONLINE_MAX_BIG, 0x2,
79 MAX_FREQ_BIG_CORE_0_RESIDX, 0x3,
80 MAX_FREQ_LITTLE_CORE_0_RESIDX, 0x1,
81};
82
83static int profile_bias_performance[] = {
84 MIN_FREQ_BIG_CORE_0_RESIDX, 0x3,
85 MIN_FREQ_LITTLE_CORE_0_RESIDX, 0x2,
86};
87
88#ifdef INTERACTION_BOOST
89int get_number_of_profiles()
90{
91 return 5;
92}
93#endif
94
95static int set_power_profile(int profile)
96{
97 int ret = -EINVAL;
98 const char *profile_name = NULL;
99
100 if (profile == current_power_profile)
101 return 0;
102
103 ALOGV("%s: Profile=%d", __func__, profile);
104
105 if (current_power_profile != PROFILE_BALANCED) {
106 undo_hint_action(DEFAULT_PROFILE_HINT_ID);
107 ALOGV("%s: Hint undone", __func__);
108 current_power_profile = PROFILE_BALANCED;
109 }
110
111 if (profile == PROFILE_POWER_SAVE) {
112 ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_power_save,
113 ARRAY_SIZE(profile_power_save));
114 profile_name = "powersave";
115
116 } else if (profile == PROFILE_HIGH_PERFORMANCE) {
117 ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID,
118 profile_high_performance, ARRAY_SIZE(profile_high_performance));
119 profile_name = "performance";
120
121 } else if (profile == PROFILE_BIAS_POWER) {
122 ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_bias_power,
123 ARRAY_SIZE(profile_bias_power));
124 profile_name = "bias power";
125
126 } else if (profile == PROFILE_BIAS_PERFORMANCE) {
127 ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID,
128 profile_bias_performance, ARRAY_SIZE(profile_bias_performance));
129 profile_name = "bias perf";
130 } else if (profile == PROFILE_BALANCED) {
131 ret = 0;
132 profile_name = "balanced";
133 }
134
135 if (ret == 0) {
136 current_power_profile = profile;
137 ALOGD("%s: Set %s mode", __func__, profile_name);
138 }
139 return ret;
140}
141
Zhao Wei Liew6fe52522016-07-19 19:57:06 +0800142/**
143 * If target is SDM630:
144 * return true
145 * else:
146 * return false
147 */
148static bool is_target_SDM630(void)
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530149{
Zhao Wei Liew6fe52522016-07-19 19:57:06 +0800150 static bool is_SDM630 = false;
151 int soc_id;
152
153 soc_id = get_soc_id();
154 if (soc_id == 318 || soc_id == 327)
155 is_SDM630 = true;
156
157 return is_SDM630;
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530158}
159
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530160static void process_video_encode_hint(void *metadata)
161{
162 char governor[80];
163 int resource_values[20];
164 int num_resources;
165 struct video_encode_metadata_t video_encode_metadata;
166
Michael Bestas47636f62018-05-25 21:30:28 +0300167 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU0) == -1) {
168 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU1) == -1) {
169 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU2) == -1) {
170 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU3) == -1) {
171 ALOGE("Can't obtain scaling governor.");
172 return;
173 }
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530174 }
Michael Bestas47636f62018-05-25 21:30:28 +0300175 }
176 }
177
178 if (!metadata) {
179 return;
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530180 }
181
182 /* Initialize encode metadata struct fields. */
183 memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
184 video_encode_metadata.state = -1;
185 video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
186
Michael Bestas47636f62018-05-25 21:30:28 +0300187 if (parse_video_encode_metadata((char *)metadata,
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530188 &video_encode_metadata) == -1) {
Michael Bestas47636f62018-05-25 21:30:28 +0300189 ALOGE("Error occurred while parsing metadata.");
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530190 return;
191 }
192
193 if (video_encode_metadata.state == 1) {
Ethan Chen4b4acdf2018-03-01 21:41:04 -0800194 if (is_interactive_governor(governor)) {
Michael Bestas47636f62018-05-25 21:30:28 +0300195 if (is_target_SDM630()) {
196 /*
197 1. CPUfreq params
198 - hispeed freq for big - 1113Mhz
199 - go hispeed load for big - 95
200 - above_hispeed_delay for big - 40ms
201 - target loads - 95
202 - nr_run - 5
203 2. BusDCVS V2 params
204 - Sample_ms of 10ms
205 */
206 int res[] = {
207 HISPEED_FREQ_BIG, 0x459,
208 GO_HISPEED_LOAD_BIG, 0x5F,
209 ABOVE_HISPEED_DELAY_BIG, 0x4,
210 TARGET_LOADS_BIG, 0x5F,
dianlujitao5eb472d2018-09-06 21:43:14 +0800211 SCHED_SPILL_NR_RUN, 0X5,
Michael Bestas47636f62018-05-25 21:30:28 +0300212 CPUBW_HWMON_SAMPLE_MS, 0xA
213 };
Nikhil Kumar Kansal839d56f2017-04-18 15:50:25 +0530214 memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
Zhao Wei Liewd4fe61e2016-06-26 11:37:59 +0800215 num_resources = ARRAY_SIZE(res);
Michael Bestas47636f62018-05-25 21:30:28 +0300216 } else {
217 /*
218 1. CPUfreq params
219 - hispeed freq for little - 902Mhz
220 - go hispeed load for little - 95
221 - above_hispeed_delay for little - 40ms
222 2. BusDCVS V2 params
223 - Sample_ms of 10ms
224 */
225 int res[] = {
226 HISPEED_FREQ_LITTLE, 0x386,
227 GO_HISPEED_LOAD_LITTLE, 0x5F,
228 ABOVE_HISPEED_DELAY_LITTLE, 0x4,
229 CPUBW_HWMON_SAMPLE_MS, 0xA
230 };
Nikhil Kumar Kansal839d56f2017-04-18 15:50:25 +0530231 memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
Zhao Wei Liewd4fe61e2016-06-26 11:37:59 +0800232 num_resources = ARRAY_SIZE(res);
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530233 }
Michael Bestas50a6e282018-05-25 21:33:46 +0300234 if (!video_encode_hint_sent) {
235 perform_hint_action(video_encode_metadata.hint_id,
236 resource_values, num_resources);
237 video_encode_hint_sent = 1;
238 }
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530239 }
240 } else if (video_encode_metadata.state == 0) {
Ethan Chen4b4acdf2018-03-01 21:41:04 -0800241 if (is_interactive_governor(governor)) {
Michael Bestas50a6e282018-05-25 21:33:46 +0300242 undo_hint_action(video_encode_metadata.hint_id);
243 video_encode_hint_sent = 0;
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530244 }
245 }
Michael Bestas47636f62018-05-25 21:30:28 +0300246}
247
248int power_hint_override(power_hint_t hint, void *data)
249{
dianlujitao93023a22018-09-06 17:45:43 +0800250 if (hint == POWER_HINT_SET_PROFILE) {
251 if (set_power_profile(*(int32_t *)data) < 0)
252 ALOGE("Setting power profile failed. perf HAL not started?");
253 return HINT_HANDLED;
254 }
255
256 // Skip other hints in high/low power modes
257 if (current_power_profile == PROFILE_POWER_SAVE ||
258 current_power_profile == PROFILE_HIGH_PERFORMANCE) {
259 return HINT_HANDLED;
260 }
261
Michael Bestas47636f62018-05-25 21:30:28 +0300262 switch (hint) {
263 case POWER_HINT_VSYNC:
264 break;
265 case POWER_HINT_VIDEO_ENCODE:
266 process_video_encode_hint(data);
267 return HINT_HANDLED;
268 default:
269 break;
270 }
271 return HINT_NONE;
272}
273
274int set_interactive_override(int on)
275{
276 char governor[80];
277 int resource_values[20];
278 int num_resources;
279
280 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU0) == -1) {
281 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU1) == -1) {
282 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU2) == -1) {
283 if (get_scaling_governor_check_cores(governor, sizeof(governor), CPU3) == -1) {
284 ALOGE("Can't obtain scaling governor.");
285 return HINT_NONE;
286 }
287 }
288 }
289 }
290
291 if (!on) {
292 /* Display off. */
293 if (is_interactive_governor(governor)) {
294 if (is_target_SDM630()) {
295 /*
296 1. CPUfreq params
297 - hispeed freq for big - 1113Mhz
298 - go hispeed load for big - 95
299 - above_hispeed_delay for big - 40ms
300 2. BusDCVS V2 params
301 - Sample_ms of 10ms
302 */
303 int res[] = {
304 HISPEED_FREQ_BIG, 0x459,
305 GO_HISPEED_LOAD_BIG, 0x5F,
306 ABOVE_HISPEED_DELAY_BIG, 0x4,
307 CPUBW_HWMON_SAMPLE_MS, 0xA
308 };
309 memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
310 num_resources = ARRAY_SIZE(res);
311 } else {
312 /*
313 1. CPUfreq params
314 - hispeed freq for little - 902Mhz
315 - go hispeed load for little - 95
316 - above_hispeed_delay for little - 40ms
317 2. BusDCVS V2 params
318 - Sample_ms of 10ms
319 3. Sched group upmigrate - 500
320 */
321 int res[] = {
322 HISPEED_FREQ_LITTLE, 0x386,
323 GO_HISPEED_LOAD_LITTLE, 0x5F,
324 ABOVE_HISPEED_DELAY_LITTLE, 0x4,
325 CPUBW_HWMON_SAMPLE_MS, 0xA,
326 SCHED_GROUP_UP_MIGRATE, 0x1F4
327 };
328 memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
329 num_resources = ARRAY_SIZE(res);
330
331 }
332 perform_hint_action(DISPLAY_STATE_HINT_ID,
333 resource_values, num_resources);
334 }
335 } else {
336 /* Display on. */
337 if (is_interactive_governor(governor)) {
338 undo_hint_action(DISPLAY_STATE_HINT_ID);
339 }
340 }
341 return HINT_HANDLED;
Vara Prasad A V S G9b7a7582017-04-07 17:32:37 +0530342}