blob: 9248f384c0ea79f1934bdb0709e2ca5b03756c26 [file] [log] [blame]
David Ngee7c4c52018-03-22 23:49:12 -07001/*
2 * Copyright (c) 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
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>
Vinay Verma2fd9c122018-04-29 14:08:30 +053040#include <pthread.h>
41#include <unistd.h>
David Ngee7c4c52018-03-22 23:49:12 -070042
43#define LOG_TAG "QTI PowerHAL"
44#include <utils/Log.h>
45#include <hardware/hardware.h>
46#include <hardware/power.h>
47
48#include "utils.h"
49#include "metadata-defs.h"
50#include "hint-data.h"
51#include "performance.h"
52#include "power-common.h"
53
54static int display_fd;
55#define SYS_DISPLAY_PWR "/sys/kernel/hbtp/display_pwr"
56
57#define CHECK_HANDLE(x) ((x)>0)
58#define NUM_PERF_MODES 3
59
60typedef enum {
61 NORMAL_MODE = 0,
62 SUSTAINED_MODE = 1,
63 VR_MODE = 2,
64 VR_SUSTAINED_MODE = (SUSTAINED_MODE|VR_MODE),
65 INVALID_MODE = 0xFF
66}perf_mode_type_t;
67
68typedef struct perf_mode {
69 perf_mode_type_t type;
70 int perf_hint_id;
71}perf_mode_t;
72
73perf_mode_t perf_modes[NUM_PERF_MODES] = { { SUSTAINED_MODE, SUSTAINED_PERF_HINT },
74 { VR_MODE, VR_MODE_HINT },
75 { VR_SUSTAINED_MODE, VR_MODE_SUSTAINED_PERF_HINT } };
76
77static pthread_mutex_t perf_mode_switch_lock = PTHREAD_MUTEX_INITIALIZER;
78static int current_mode = NORMAL_MODE;
79
80static inline int get_perfd_hint_id(perf_mode_type_t type) {
81 int i;
82 for(i=0; i<NUM_PERF_MODES; i++) {
83 if (perf_modes[i].type == type) {
84 ALOGD("Hint id is 0x%x for mode 0x%x", perf_modes[i].perf_hint_id, type);
85 return perf_modes[i].perf_hint_id;
86 }
87 }
88 ALOGD("Couldn't find the hint for mode 0x%x", type);
89 return 0;
90}
91
92static int switch_mode(perf_mode_type_t mode) {
93
94 int hint_id = 0;
95 static int perfd_mode_handle = -1;
96
97 // release existing mode if any
98 if (CHECK_HANDLE(perfd_mode_handle)) {
99 ALOGD("Releasing handle 0x%x", perfd_mode_handle);
100 release_request(perfd_mode_handle);
101 perfd_mode_handle = -1;
102 }
103 // switch to a perf mode
104 hint_id = get_perfd_hint_id(mode);
105 if(hint_id != 0) {
106 perfd_mode_handle = perf_hint_enable(hint_id, 0);
107 if (!CHECK_HANDLE(perfd_mode_handle)) {
108 ALOGE("Failed perf_hint_interaction for mode: 0x%x", mode);
109 return -1;
110 }
111 ALOGD("Acquired handle 0x%x", perfd_mode_handle);
112 }
113 return 0;
114}
115
116static int process_perf_hint(void *data, perf_mode_type_t mode) {
117
118 pthread_mutex_lock(&perf_mode_switch_lock);
119
120 // enable
121 if (data){
122 ALOGI("Enable request for mode: 0x%x", mode);
123 // check if mode is current mode
124 if ( current_mode & mode ) {
125 pthread_mutex_unlock(&perf_mode_switch_lock);
126 ALOGD("Mode 0x%x already enabled", mode);
127 return HINT_HANDLED;
128 }
129 // enable requested mode
130 if ( 0 != switch_mode(current_mode | mode)) {
131 pthread_mutex_unlock(&perf_mode_switch_lock);
132 ALOGE("Couldn't enable mode 0x%x", mode);
133 return HINT_NONE;
134 }
135 current_mode |= mode;
136 ALOGI("Current mode is 0x%x", current_mode);
137 // disable
138 } else {
139 ALOGI("Disable request for mode: 0x%x", mode);
140 // check if mode is enabled
141 if ( !(current_mode & mode) ) {
142 pthread_mutex_unlock(&perf_mode_switch_lock);
143 ALOGD("Mode 0x%x already disabled", mode);
144 return HINT_HANDLED;
145 }
146 //disable requested mode
147 if ( 0 != switch_mode(current_mode & ~mode)) {
148 pthread_mutex_unlock(&perf_mode_switch_lock);
149 ALOGE("Couldn't disable mode 0x%x", mode);
150 return HINT_NONE;
151 }
152 current_mode &= ~mode;
153 ALOGI("Current mode is 0x%x", current_mode);
154 }
155
156 pthread_mutex_unlock(&perf_mode_switch_lock);
157 return HINT_HANDLED;
158}
159
160static int process_video_encode_hint(void *metadata)
161{
162 char governor[80];
163 struct video_encode_metadata_t video_encode_metadata;
164 static int video_encode_handle = 0;
165
166 if(!metadata)
167 return HINT_NONE;
168
169 if (get_scaling_governor(governor, sizeof(governor)) == -1) {
170 ALOGE("Can't obtain scaling governor.");
171
172 return HINT_NONE;
173 }
174
175 /* Initialize encode metadata struct fields */
176 memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
177 video_encode_metadata.state = -1;
178
179 if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) ==
180 -1) {
181 ALOGE("Error occurred while parsing metadata.");
182 return HINT_NONE;
183 }
184
185 if (video_encode_metadata.state == 1) {
186 if (is_interactive_governor(governor)) {
187 video_encode_handle = perf_hint_enable(
188 VIDEO_ENCODE_HINT, 0);
189 ALOGI("Video encode hint start");
190 return HINT_HANDLED;
191 }
192 } else if (video_encode_metadata.state == 0) {
193 if (is_interactive_governor(governor)) {
194 release_request(video_encode_handle);
195 ALOGI("Video Encode hint stop");
196 return HINT_HANDLED;
197 }
198 }
199 return HINT_NONE;
200}
201
202/* Declare function before use */
203void interaction(int duration, int num_args, int opt_list[]);
204
205int power_hint_override(struct power_module *module, power_hint_t hint, void *data)
206{
207 int ret_val = HINT_NONE;
208 switch(hint) {
209 case POWER_HINT_VIDEO_ENCODE:
210 ret_val = process_video_encode_hint(data);
211 break;
212 case POWER_HINT_SUSTAINED_PERFORMANCE:
213 ret_val = process_perf_hint(data, SUSTAINED_MODE);
214 break;
215 case POWER_HINT_VR_MODE:
216 ret_val = process_perf_hint(data, VR_MODE);
217 break;
218 case POWER_HINT_INTERACTION:
219 {
220 int resources[] = {0x40800100, 0x514};
221 int duration = 100;
222 interaction(duration, sizeof(resources)/sizeof(resources[0]), resources);
223 ret_val = HINT_HANDLED;
224 }
225 break;
226 default:
227 break;
228 }
229 return ret_val;
230}
231
232int set_interactive_override(struct power_module *module, int on)
233{
234 static const char *display_on = "1";
235 static const char *display_off = "0";
236 char err_buf[80];
237 static int init_interactive_hint = 0;
238 static int set_i_count = 0;
239 int rc = 0;
240
241 set_i_count ++;
242 ALOGI("Got set_interactive hint on= %d, count= %d\n", on, set_i_count);
243
244 if (init_interactive_hint == 0)
245 {
246 //First time the display is turned off
247 display_fd = TEMP_FAILURE_RETRY(open(SYS_DISPLAY_PWR, O_RDWR));
248 if (display_fd < 0) {
249 strerror_r(errno,err_buf,sizeof(err_buf));
250 ALOGE("Error opening %s: %s\n", SYS_DISPLAY_PWR, err_buf);
251 }
252 else
253 init_interactive_hint = 1;
254 }
255 else
256 if (!on ) {
257 /* Display off. */
258 rc = TEMP_FAILURE_RETRY(write(display_fd, display_off, strlen(display_off)));
259 if (rc < 0) {
260 strerror_r(errno,err_buf,sizeof(err_buf));
261 ALOGE("Error writing %s to %s: %s\n", display_off, SYS_DISPLAY_PWR, err_buf);
262 }
263 }
264 else {
265 /* Display on */
266 rc = TEMP_FAILURE_RETRY(write(display_fd, display_on, strlen(display_on)));
267 if (rc < 0) {
268 strerror_r(errno,err_buf,sizeof(err_buf));
269 ALOGE("Error writing %s to %s: %s\n", display_on, SYS_DISPLAY_PWR, err_buf);
270 }
271 }
272
273 return HINT_HANDLED; /* Don't excecute this code path, not in use */
274}