blob: 051cd5a9e42935ffda5f1c7eeae9933853ea2513 [file] [log] [blame]
David Ngee7c4c52018-03-22 23:49:12 -07001/*
2 * Copyright (c) 2012-2017, 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
30#define LOG_NIDEBUG 0
31
32#include <errno.h>
33#include <string.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <fcntl.h>
37#include <dlfcn.h>
38#include <stdlib.h>
Vinay Verma2fd9c122018-04-29 14:08:30 +053039#include <unistd.h>
David Ngee7c4c52018-03-22 23:49:12 -070040
41#define LOG_TAG "QTI PowerHAL"
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
52static int saved_dcvs_cpu0_slack_max = -1;
53static int saved_dcvs_cpu0_slack_min = -1;
54static int saved_mpdecision_slack_max = -1;
55static int saved_mpdecision_slack_min = -1;
56static int saved_interactive_mode = -1;
57static int slack_node_rw_failed = 0;
58static int display_hint_sent;
59int display_boost;
60
61static int power_device_open(const hw_module_t* module, const char* name,
62 hw_device_t** device);
63
64static struct hw_module_methods_t power_module_methods = {
65 .open = power_device_open,
66};
67
68static void power_init(struct power_module *module)
69{
70 ALOGI("QTI power HAL initing.");
71
72 int fd;
73 char buf[10] = {0};
74
75 fd = open("/sys/devices/soc0/soc_id", O_RDONLY);
76 if (fd >= 0) {
77 if (read(fd, buf, sizeof(buf) - 1) == -1) {
78 ALOGW("Unable to read soc_id");
79 } else {
80 int soc_id = atoi(buf);
81 if (soc_id == 194 || (soc_id >= 208 && soc_id <= 218) || soc_id == 178) {
82 display_boost = 1;
83 }
84 }
85 close(fd);
86 }
87}
88
89static void process_video_decode_hint(void *metadata)
90{
91 char governor[80];
92 struct video_decode_metadata_t video_decode_metadata;
93
94 if (get_scaling_governor(governor, sizeof(governor)) == -1) {
95 ALOGE("Can't obtain scaling governor.");
96
97 return;
98 }
99
100 if (metadata) {
101 ALOGI("Processing video decode hint. Metadata: %s", (char *)metadata);
102 }
103
104 /* Initialize encode metadata struct fields. */
105 memset(&video_decode_metadata, 0, sizeof(struct video_decode_metadata_t));
106 video_decode_metadata.state = -1;
107 video_decode_metadata.hint_id = DEFAULT_VIDEO_DECODE_HINT_ID;
108
109 if (metadata) {
110 if (parse_video_decode_metadata((char *)metadata, &video_decode_metadata) ==
111 -1) {
112 ALOGE("Error occurred while parsing metadata.");
113 return;
114 }
115 } else {
116 return;
117 }
118
119 if (video_decode_metadata.state == 1) {
120 if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
121 (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
122 int resource_values[] = {THREAD_MIGRATION_SYNC_OFF};
123
124 perform_hint_action(video_decode_metadata.hint_id,
125 resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
126 } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
127 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
128 int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026, THREAD_MIGRATION_SYNC_OFF};
129
130 perform_hint_action(video_decode_metadata.hint_id,
131 resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
132 }
133 } else if (video_decode_metadata.state == 0) {
134 if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
135 (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
136 } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
137 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
138 undo_hint_action(video_decode_metadata.hint_id);
139 }
140 }
141}
142
143static void process_video_encode_hint(void *metadata)
144{
145 char governor[80];
146 struct video_encode_metadata_t video_encode_metadata;
147
148 if (get_scaling_governor(governor, sizeof(governor)) == -1) {
149 ALOGE("Can't obtain scaling governor.");
150
151 return;
152 }
153
154 /* Initialize encode metadata struct fields. */
155 memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
156 video_encode_metadata.state = -1;
157 video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
158
159 if (metadata) {
160 if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) ==
161 -1) {
162 ALOGE("Error occurred while parsing metadata.");
163 return;
164 }
165 } else {
166 return;
167 }
168
169 if (video_encode_metadata.state == 1) {
170 if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
171 (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
172 int resource_values[] = {IO_BUSY_OFF, SAMPLING_DOWN_FACTOR_1, THREAD_MIGRATION_SYNC_OFF};
173
174 perform_hint_action(video_encode_metadata.hint_id,
175 resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
176 } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
177 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
178 int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026, THREAD_MIGRATION_SYNC_OFF,
179 INTERACTIVE_IO_BUSY_OFF};
180
181 perform_hint_action(video_encode_metadata.hint_id,
182 resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
183 }
184 } else if (video_encode_metadata.state == 0) {
185 if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
186 (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
187 undo_hint_action(video_encode_metadata.hint_id);
188 } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
189 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
190 undo_hint_action(video_encode_metadata.hint_id);
191 }
192 }
193}
194
195int __attribute__ ((weak)) power_hint_override(struct power_module *module, power_hint_t hint,
196 void *data)
197{
198 return HINT_NONE;
199}
200
201/* Declare function before use */
202void interaction(int duration, int num_args, int opt_list[]);
203
204static void power_hint(struct power_module *module, power_hint_t hint,
205 void *data)
206{
207 /* Check if this hint has been overridden. */
208 if (power_hint_override(module, hint, data) == HINT_HANDLED) {
209 /* The power_hint has been handled. We can skip the rest. */
210 return;
211 }
212
213 switch(hint) {
214 case POWER_HINT_VSYNC:
215 break;
216 case POWER_HINT_SUSTAINED_PERFORMANCE:
217 ALOGI("Sustained perf power hint not handled in power_hint_override");
218 break;
219 case POWER_HINT_VR_MODE:
220 ALOGI("VR mode power hint not handled in power_hint_override");
221 break;
222 case POWER_HINT_INTERACTION:
223 {
224 int resources[] = {0x702, 0x20F, 0x30F};
225 int duration = 3000;
226
227 interaction(duration, sizeof(resources)/sizeof(resources[0]), resources);
228 }
229 break;
230 case POWER_HINT_VIDEO_ENCODE:
231 process_video_encode_hint(data);
232 break;
233 case POWER_HINT_VIDEO_DECODE:
234 process_video_decode_hint(data);
235 break;
236 }
237}
238
239int __attribute__ ((weak)) set_interactive_override(struct power_module *module, int on)
240{
241 return HINT_NONE;
242}
243
244void set_interactive(struct power_module *module, int on)
245{
246 char governor[80];
247 char tmp_str[NODE_MAX];
248 struct video_encode_metadata_t video_encode_metadata;
249 int rc = 0;
250
251 if (!on) {
252 /* Send Display OFF hint to perf HAL */
253 perf_hint_enable(VENDOR_HINT_DISPLAY_OFF, 0);
254 } else {
255 /* Send Display ON hint to perf HAL */
256 perf_hint_enable(VENDOR_HINT_DISPLAY_ON, 0);
257 }
258
259 if (set_interactive_override(module, on) == HINT_HANDLED) {
260 return;
261 }
262
263 ALOGI("Got set_interactive hint");
264
265 if (get_scaling_governor(governor, sizeof(governor)) == -1) {
266 ALOGE("Can't obtain scaling governor.");
267
268 return;
269 }
270
271 if (!on) {
272 /* Display off. */
273 if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
274 (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
275 int resource_values[] = {DISPLAY_OFF, MS_500, THREAD_MIGRATION_SYNC_OFF};
276
277 if (!display_hint_sent) {
278 perform_hint_action(DISPLAY_STATE_HINT_ID,
279 resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
280 display_hint_sent = 1;
281 }
282 } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
283 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
284 int resource_values[] = {TR_MS_50, THREAD_MIGRATION_SYNC_OFF};
285
286 if (!display_hint_sent) {
287 perform_hint_action(DISPLAY_STATE_HINT_ID,
288 resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
289 display_hint_sent = 1;
290 }
291 } else if ((strncmp(governor, MSMDCVS_GOVERNOR, strlen(MSMDCVS_GOVERNOR)) == 0) &&
292 (strlen(governor) == strlen(MSMDCVS_GOVERNOR))) {
293 if (saved_interactive_mode == 1){
294 /* Display turned off. */
295 if (sysfs_read(DCVS_CPU0_SLACK_MAX_NODE, tmp_str, NODE_MAX - 1)) {
296 if (!slack_node_rw_failed) {
297 ALOGE("Failed to read from %s", DCVS_CPU0_SLACK_MAX_NODE);
298 }
299
300 rc = 1;
301 } else {
302 saved_dcvs_cpu0_slack_max = atoi(tmp_str);
303 }
304
305 if (sysfs_read(DCVS_CPU0_SLACK_MIN_NODE, tmp_str, NODE_MAX - 1)) {
306 if (!slack_node_rw_failed) {
307 ALOGE("Failed to read from %s", DCVS_CPU0_SLACK_MIN_NODE);
308 }
309
310 rc = 1;
311 } else {
312 saved_dcvs_cpu0_slack_min = atoi(tmp_str);
313 }
314
315 if (sysfs_read(MPDECISION_SLACK_MAX_NODE, tmp_str, NODE_MAX - 1)) {
316 if (!slack_node_rw_failed) {
317 ALOGE("Failed to read from %s", MPDECISION_SLACK_MAX_NODE);
318 }
319
320 rc = 1;
321 } else {
322 saved_mpdecision_slack_max = atoi(tmp_str);
323 }
324
325 if (sysfs_read(MPDECISION_SLACK_MIN_NODE, tmp_str, NODE_MAX - 1)) {
326 if(!slack_node_rw_failed) {
327 ALOGE("Failed to read from %s", MPDECISION_SLACK_MIN_NODE);
328 }
329
330 rc = 1;
331 } else {
332 saved_mpdecision_slack_min = atoi(tmp_str);
333 }
334
335 /* Write new values. */
336 if (saved_dcvs_cpu0_slack_max != -1) {
337 snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_dcvs_cpu0_slack_max);
338
339 if (sysfs_write(DCVS_CPU0_SLACK_MAX_NODE, tmp_str) != 0) {
340 if (!slack_node_rw_failed) {
341 ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MAX_NODE);
342 }
343
344 rc = 1;
345 }
346 }
347
348 if (saved_dcvs_cpu0_slack_min != -1) {
349 snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_dcvs_cpu0_slack_min);
350
351 if (sysfs_write(DCVS_CPU0_SLACK_MIN_NODE, tmp_str) != 0) {
352 if(!slack_node_rw_failed) {
353 ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MIN_NODE);
354 }
355
356 rc = 1;
357 }
358 }
359
360 if (saved_mpdecision_slack_max != -1) {
361 snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_mpdecision_slack_max);
362
363 if (sysfs_write(MPDECISION_SLACK_MAX_NODE, tmp_str) != 0) {
364 if(!slack_node_rw_failed) {
365 ALOGE("Failed to write to %s", MPDECISION_SLACK_MAX_NODE);
366 }
367
368 rc = 1;
369 }
370 }
371
372 if (saved_mpdecision_slack_min != -1) {
373 snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_mpdecision_slack_min);
374
375 if (sysfs_write(MPDECISION_SLACK_MIN_NODE, tmp_str) != 0) {
376 if(!slack_node_rw_failed) {
377 ALOGE("Failed to write to %s", MPDECISION_SLACK_MIN_NODE);
378 }
379
380 rc = 1;
381 }
382 }
383 }
384
385 slack_node_rw_failed = rc;
386 }
387 } else {
388 /* Display on. */
389 if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
390 (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
391 undo_hint_action(DISPLAY_STATE_HINT_ID);
392 display_hint_sent = 0;
393 } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
394 (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
395 undo_hint_action(DISPLAY_STATE_HINT_ID);
396 display_hint_sent = 0;
397 } else if ((strncmp(governor, MSMDCVS_GOVERNOR, strlen(MSMDCVS_GOVERNOR)) == 0) &&
398 (strlen(governor) == strlen(MSMDCVS_GOVERNOR))) {
399 if (saved_interactive_mode == -1 || saved_interactive_mode == 0) {
400 /* Display turned on. Restore if possible. */
401 if (saved_dcvs_cpu0_slack_max != -1) {
402 snprintf(tmp_str, NODE_MAX, "%d", saved_dcvs_cpu0_slack_max);
403
404 if (sysfs_write(DCVS_CPU0_SLACK_MAX_NODE, tmp_str) != 0) {
405 if (!slack_node_rw_failed) {
406 ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MAX_NODE);
407 }
408
409 rc = 1;
410 }
411 }
412
413 if (saved_dcvs_cpu0_slack_min != -1) {
414 snprintf(tmp_str, NODE_MAX, "%d", saved_dcvs_cpu0_slack_min);
415
416 if (sysfs_write(DCVS_CPU0_SLACK_MIN_NODE, tmp_str) != 0) {
417 if (!slack_node_rw_failed) {
418 ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MIN_NODE);
419 }
420
421 rc = 1;
422 }
423 }
424
425 if (saved_mpdecision_slack_max != -1) {
426 snprintf(tmp_str, NODE_MAX, "%d", saved_mpdecision_slack_max);
427
428 if (sysfs_write(MPDECISION_SLACK_MAX_NODE, tmp_str) != 0) {
429 if (!slack_node_rw_failed) {
430 ALOGE("Failed to write to %s", MPDECISION_SLACK_MAX_NODE);
431 }
432
433 rc = 1;
434 }
435 }
436
437 if (saved_mpdecision_slack_min != -1) {
438 snprintf(tmp_str, NODE_MAX, "%d", saved_mpdecision_slack_min);
439
440 if (sysfs_write(MPDECISION_SLACK_MIN_NODE, tmp_str) != 0) {
441 if (!slack_node_rw_failed) {
442 ALOGE("Failed to write to %s", MPDECISION_SLACK_MIN_NODE);
443 }
444
445 rc = 1;
446 }
447 }
448 }
449
450 slack_node_rw_failed = rc;
451 }
452 }
453
454 saved_interactive_mode = !!on;
455}
456
457static int power_device_open(const hw_module_t* module, const char* name,
458 hw_device_t** device)
459{
460 int status = -EINVAL;
461 if (module && name && device) {
462 if (!strcmp(name, POWER_HARDWARE_MODULE_ID)) {
463 power_module_t *dev = (power_module_t *)malloc(sizeof(*dev));
464
465 if(dev) {
466 memset(dev, 0, sizeof(*dev));
467
468 if(dev) {
469 /* initialize the fields */
470 dev->common.module_api_version = POWER_MODULE_API_VERSION_0_2;
471 dev->common.tag = HARDWARE_DEVICE_TAG;
472 dev->init = power_init;
473 dev->powerHint = power_hint;
474 dev->setInteractive = set_interactive;
475 /* At the moment we support 0.2 APIs */
476 dev->setFeature = NULL,
477 dev->get_number_of_platform_modes = NULL,
478 dev->get_platform_low_power_stats = NULL,
479 dev->get_voter_list = NULL,
480 *device = (hw_device_t*)dev;
481 status = 0;
482 } else {
483 status = -ENOMEM;
484 }
485 }
486 else {
487 status = -ENOMEM;
488 }
489 }
490 }
491
492 return status;
493}
494
495struct power_module HAL_MODULE_INFO_SYM = {
496 .common = {
497 .tag = HARDWARE_MODULE_TAG,
498 .module_api_version = POWER_MODULE_API_VERSION_0_2,
499 .hal_api_version = HARDWARE_HAL_API_VERSION,
500 .id = POWER_HARDWARE_MODULE_ID,
501 .name = "QTI Power HAL",
502 .author = "QTI",
503 .methods = &power_module_methods,
504 },
505
506 .init = power_init,
507 .powerHint = power_hint,
508 .setInteractive = set_interactive,
509};