blob: d3d81c9a578c90aa868751811b62ff12fe7c6e65 [file] [log] [blame]
David Ngee7c4c52018-03-22 23:49:12 -07001/*
2 * Copyright (c) 2016-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#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>
Bharat Pawar2cda3f72018-06-26 13:06:17 +053038#include <pthread.h>
39#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#include "powerhintparser.h"
52
53#define CHECK_HANDLE(x) ((x)>0)
54#define NUM_PERF_MODES 3
55
56typedef enum {
57 NORMAL_MODE = 0,
58 SUSTAINED_MODE = 1,
59 VR_MODE = 2,
60 VR_SUSTAINED_MODE = (SUSTAINED_MODE|VR_MODE),
61 INVALID_MODE = 0xFF
62}perf_mode_type_t;
63
64typedef struct perf_mode {
65 perf_mode_type_t type;
66 int perf_hint_id;
67}perf_mode_t;
68
69perf_mode_t perf_modes[NUM_PERF_MODES] = { { SUSTAINED_MODE, SUSTAINED_PERF_HINT },
70 { VR_MODE, VR_MODE_HINT },
71 { VR_SUSTAINED_MODE, VR_MODE_SUSTAINED_PERF_HINT } };
72
73static pthread_mutex_t perf_mode_switch_lock = PTHREAD_MUTEX_INITIALIZER;
74static int current_mode = NORMAL_MODE;
75
76static inline int get_perfd_hint_id(perf_mode_type_t type) {
77 int i;
78 for(i=0; i<NUM_PERF_MODES; i++) {
79 if (perf_modes[i].type == type) {
80 ALOGD("Hint id is 0x%x for mode 0x%x", perf_modes[i].perf_hint_id, type);
81 return perf_modes[i].perf_hint_id;
82 }
83 }
84 ALOGD("Couldn't find the hint for mode 0x%x", type);
85 return 0;
86}
87
88static int switch_mode(perf_mode_type_t mode) {
89
90 int hint_id = 0;
91 static int perfd_mode_handle = -1;
92
93 // release existing mode if any
94 if (CHECK_HANDLE(perfd_mode_handle)) {
95 ALOGD("Releasing handle 0x%x", perfd_mode_handle);
96 release_request(perfd_mode_handle);
97 perfd_mode_handle = -1;
98 }
99 // switch to a perf mode
100 hint_id = get_perfd_hint_id(mode);
101 if(hint_id != 0) {
102 perfd_mode_handle = perf_hint_enable(hint_id, 0);
103 if (!CHECK_HANDLE(perfd_mode_handle)) {
104 ALOGE("Failed perf_hint_interaction for mode: 0x%x", mode);
105 return -1;
106 }
107 ALOGD("Acquired handle 0x%x", perfd_mode_handle);
108 }
109 return 0;
110}
111
112static int process_perf_hint(void *data, perf_mode_type_t mode) {
113
114 pthread_mutex_lock(&perf_mode_switch_lock);
115
116 // enable
117 if (data){
118 ALOGI("Enable request for mode: 0x%x", mode);
119 // check if mode is current mode
120 if ( current_mode & mode ) {
121 pthread_mutex_unlock(&perf_mode_switch_lock);
122 ALOGD("Mode 0x%x already enabled", mode);
123 return HINT_HANDLED;
124 }
125 // enable requested mode
126 if ( 0 != switch_mode(current_mode | mode)) {
127 pthread_mutex_unlock(&perf_mode_switch_lock);
128 ALOGE("Couldn't enable mode 0x%x", mode);
129 return HINT_NONE;
130 }
131 current_mode |= mode;
132 ALOGI("Current mode is 0x%x", current_mode);
133 // disable
134 } else {
135 ALOGI("Disable request for mode: 0x%x", mode);
136 // check if mode is enabled
137 if ( !(current_mode & mode) ) {
138 pthread_mutex_unlock(&perf_mode_switch_lock);
139 ALOGD("Mode 0x%x already disabled", mode);
140 return HINT_HANDLED;
141 }
142 //disable requested mode
143 if ( 0 != switch_mode(current_mode & ~mode)) {
144 pthread_mutex_unlock(&perf_mode_switch_lock);
145 ALOGE("Couldn't disable mode 0x%x", mode);
146 return HINT_NONE;
147 }
148 current_mode &= ~mode;
149 ALOGI("Current mode is 0x%x", current_mode);
150 }
151
152 pthread_mutex_unlock(&perf_mode_switch_lock);
153 return HINT_HANDLED;
154}
155
156static int process_video_encode_hint(void *metadata)
157{
158 char governor[80];
159 struct video_encode_metadata_t video_encode_metadata;
160 static int video_encode_handle = 0;
161
162 if(!metadata)
163 return HINT_NONE;
164
165 if (get_scaling_governor(governor, sizeof(governor)) == -1) {
166 ALOGE("Can't obtain scaling governor.");
167
168 return HINT_NONE;
169 }
170
171 /* Initialize encode metadata struct fields */
172 memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
173 video_encode_metadata.state = -1;
174
175 if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) ==
176 -1) {
177 ALOGE("Error occurred while parsing metadata.");
178 return HINT_NONE;
179 }
180
181 if (video_encode_metadata.state == 1) {
182 if (is_interactive_governor(governor)) {
183 video_encode_handle = perf_hint_enable(
184 VIDEO_ENCODE_HINT, 0);
185 return HINT_HANDLED;
186 }
187 } else if (video_encode_metadata.state == 0) {
188 if (is_interactive_governor(governor)) {
189 release_request(video_encode_handle);
190 ALOGI("Video Encode hint stop");
191 return HINT_HANDLED;
192 }
193 }
194 return HINT_NONE;
195}
196
197int power_hint_override(struct power_module *module, power_hint_t hint, void *data)
198{
199 int ret_val = HINT_NONE;
200 switch(hint) {
201 case POWER_HINT_VIDEO_ENCODE:
202 ret_val = process_video_encode_hint(data);
203 break;
204 case POWER_HINT_SUSTAINED_PERFORMANCE:
205 ret_val = process_perf_hint(data, SUSTAINED_MODE);
206 break;
207 case POWER_HINT_VR_MODE:
208 ret_val = process_perf_hint(data, VR_MODE);
209 break;
210 case POWER_HINT_INTERACTION:
211 pthread_mutex_lock(&perf_mode_switch_lock);
212 if (current_mode != NORMAL_MODE) {
213 ret_val = HINT_HANDLED;
214 }
215 pthread_mutex_unlock(&perf_mode_switch_lock);
216 break;
217 default:
218 break;
219 }
220 return ret_val;
221}
222
223int set_interactive_override(struct power_module *module, int on)
224{
225 return HINT_HANDLED; /* Don't excecute this code path, not in use */
226}