2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.tizenopensource.org/license
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include "ss_device_plugin.h"
22 #include "include/ss_data.h"
25 #define DEFAULT_MAX_CPU_FREQ 1200000
26 #define DEFAULT_MIN_CPU_FREQ 100000
27 #define POWER_SAVING_CPUFREQ 800000
29 static int max_cpu_freq_limit = -1;
30 static int min_cpu_freq_limit = -1;
31 static int cur_max_cpu_freq = INT_MAX;
32 static int cur_min_cpu_freq = INT_MIN;
34 static Eina_List *max_cpu_freq_list;
35 static Eina_List *min_cpu_freq_list;
37 struct cpu_freq_entry {
42 static void __set_freq_limit();
43 static int __is_entry_enble(int pid);
44 static int __remove_entry_from_max_cpu_freq_list(int pid);
45 static int __remove_entry_from_min_cpu_freq_list(int pid);
46 static int __add_entry_to_max_cpu_freq_list(int pid, int freq);
47 static int __add_entry_to_min_cpu_freq_list(int pid, int freq);
48 static int __write_max_cpu_freq(int freq);
49 static int __write_min_cpu_freq(int freq);
51 int set_max_frequency_action(int argc, char **argv)
58 r = __add_entry_to_max_cpu_freq_list(atoi(argv[0]), atoi(argv[1]));
60 PRT_TRACE_ERR("Add entry failed");
64 r = __write_max_cpu_freq(cur_max_cpu_freq);
66 PRT_TRACE_ERR("Write entry failed");
73 int set_min_frequency_action(int argc, char **argv)
80 r = __add_entry_to_min_cpu_freq_list(atoi(argv[0]), atoi(argv[1]));
82 PRT_TRACE_ERR("Add entry failed");
86 r = __write_min_cpu_freq(cur_min_cpu_freq);
88 PRT_TRACE_ERR("Write entry failed");
95 int release_max_frequency_action(int argc, char **argv)
101 r = __remove_entry_from_max_cpu_freq_list(atoi(argv[0]));
103 PRT_TRACE_ERR("Remove entry failed");
107 if (cur_max_cpu_freq == INT_MAX)
108 cur_max_cpu_freq = max_cpu_freq_limit;
110 r = __write_max_cpu_freq(cur_max_cpu_freq);
112 PRT_TRACE_ERR("Write freq failed");
119 int release_min_frequency_action(int argc, char **argv)
126 r = __remove_entry_from_min_cpu_freq_list(atoi(argv[0]));
128 PRT_TRACE_ERR("Remove entry failed");
132 if (cur_min_cpu_freq == INT_MIN)
133 cur_min_cpu_freq = min_cpu_freq_limit;
135 r = __write_min_cpu_freq(cur_min_cpu_freq);
137 PRT_TRACE_ERR("Write entry failed");
144 static int power_saving_cb(keynode_t *key_nodes, void *data)
147 int power_saving_stat = -1;
148 int power_saving_cpu_stat = -1;
150 power_saving_stat = vconf_keynode_get_bool(key_nodes);
151 if (power_saving_stat == 1) {
152 vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_CPU, &power_saving_cpu_stat);
153 if (power_saving_cpu_stat == 1) {
154 ret = __add_entry_to_max_cpu_freq_list(getpid(), POWER_SAVING_CPUFREQ);
156 PRT_TRACE_ERR("Add entry failed");
161 ret = __remove_entry_from_max_cpu_freq_list(getpid());
163 PRT_TRACE_ERR("Remove entry failed");
166 if (cur_max_cpu_freq == INT_MIN)
167 cur_max_cpu_freq = max_cpu_freq_limit;
169 ret = __write_max_cpu_freq(cur_max_cpu_freq);
171 PRT_TRACE_ERR("Write failed");
178 static int power_saving_cpu_cb(keynode_t *key_nodes, void *data)
181 int power_saving_stat = -1;
182 int power_saving_cpu_stat = -1;
184 vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, &power_saving_stat);
185 if (power_saving_stat == 1) {
186 power_saving_cpu_stat = vconf_keynode_get_bool(key_nodes);
187 if (power_saving_cpu_stat == 1) {
188 ret = __add_entry_to_max_cpu_freq_list(getpid(), POWER_SAVING_CPUFREQ);
190 PRT_TRACE_ERR("Add entry failed");
194 ret = __remove_entry_from_max_cpu_freq_list(getpid());
196 PRT_TRACE_ERR("Remove entry failed");
199 if (cur_max_cpu_freq == INT_MAX)
200 cur_max_cpu_freq = max_cpu_freq_limit;
202 ret = __write_max_cpu_freq(cur_max_cpu_freq);
204 PRT_TRACE_ERR("Write failed");
212 int ss_cpu_handler_init(void)
216 ss_action_entry_add_internal(PREDEF_SET_MAX_FREQUENCY, set_max_frequency_action, NULL, NULL);
217 ss_action_entry_add_internal(PREDEF_SET_MIN_FREQUENCY, set_min_frequency_action, NULL, NULL);
218 ss_action_entry_add_internal(PREDEF_RELEASE_MAX_FREQUENCY, release_max_frequency_action, NULL, NULL);
219 ss_action_entry_add_internal(PREDEF_RELEASE_MIN_FREQUENCY, release_min_frequency_action, NULL, NULL);
221 vconf_notify_key_changed(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, (void *)power_saving_cb, NULL);
222 vconf_notify_key_changed(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_CPU, (void *)power_saving_cpu_cb, NULL);
227 static void __set_freq_limit()
231 ret = plugin_intf->OEM_sys_get_cpufreq_cpuinfo_max_freq(&max_cpu_freq_limit);
233 PRT_TRACE_ERR("get cpufreq cpuinfo max readerror: %s", strerror(errno));
234 max_cpu_freq_limit = DEFAULT_MAX_CPU_FREQ;
237 ret = plugin_intf->OEM_sys_get_cpufreq_cpuinfo_min_freq(&min_cpu_freq_limit);
239 PRT_TRACE_ERR("get cpufreq cpuinfo min readerror: %s", strerror(errno));
240 min_cpu_freq_limit = DEFAULT_MIN_CPU_FREQ;
243 /* check power saving */
244 int power_saving_stat = -1;
245 int power_saving_cpu_stat = -1;
246 vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, &power_saving_stat);
247 if (power_saving_stat == 1)
248 vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_CPU, &power_saving_cpu_stat);
249 if (power_saving_cpu_stat == 1) {
250 ret = __add_entry_to_max_cpu_freq_list(getpid(), POWER_SAVING_CPUFREQ);
252 PRT_TRACE_ERR("Add entry failed");
255 ret = __write_max_cpu_freq(cur_max_cpu_freq);
257 PRT_TRACE_ERR("Write entry failed");
263 static int __is_entry_enable(int pid)
265 char pid_path[PATH_MAX];
267 snprintf(pid_path, PATH_MAX, "/proc/%d", pid);
268 if (access(pid_path, F_OK) < 0) {
275 static int __remove_entry_from_max_cpu_freq_list(int pid)
279 struct cpu_freq_entry *entry;
281 cur_max_cpu_freq = INT_MAX;
283 EINA_LIST_FOREACH_SAFE(max_cpu_freq_list, tmp, tmp_next, entry) {
285 if ((!__is_entry_enable(entry->pid)) || (entry->pid == pid)) {
286 max_cpu_freq_list = eina_list_remove(max_cpu_freq_list, entry);
291 if (entry->freq < cur_max_cpu_freq) {
292 cur_max_cpu_freq = entry->freq;
300 static int __remove_entry_from_min_cpu_freq_list(int pid)
304 struct cpu_freq_entry *entry;
306 cur_min_cpu_freq = INT_MIN;
308 EINA_LIST_FOREACH_SAFE(min_cpu_freq_list, tmp, tmp_next, entry) {
310 if ((!__is_entry_enable(entry->pid)) || (entry->pid == pid)) {
311 min_cpu_freq_list = eina_list_remove(min_cpu_freq_list, entry);
316 if (entry->freq > cur_min_cpu_freq) {
317 cur_min_cpu_freq = entry->freq;
326 static int __add_entry_to_max_cpu_freq_list(int pid, int freq)
329 struct cpu_freq_entry *entry;
331 r = __remove_entry_from_max_cpu_freq_list(pid);
333 PRT_TRACE_ERR("Remove duplicated entry failed");
336 if (freq < cur_max_cpu_freq) {
337 cur_max_cpu_freq = freq;
340 entry = malloc(sizeof(struct cpu_freq_entry));
342 PRT_TRACE_ERR("Malloc failed");
349 max_cpu_freq_list = eina_list_prepend(max_cpu_freq_list, entry);
350 if (!max_cpu_freq_list) {
351 PRT_TRACE_ERR("eina_list_prepend failed");
358 static int __add_entry_to_min_cpu_freq_list(int pid, int freq)
361 struct cpu_freq_entry *entry;
363 r = __remove_entry_from_min_cpu_freq_list(pid);
365 PRT_TRACE_ERR("Remove duplicated entry failed");
368 if (freq > cur_min_cpu_freq) {
369 cur_min_cpu_freq = freq;
372 entry = malloc(sizeof(struct cpu_freq_entry));
374 PRT_TRACE_ERR("Malloc failed");
381 min_cpu_freq_list = eina_list_prepend(min_cpu_freq_list, entry);
382 if (!min_cpu_freq_list) {
383 PRT_TRACE_ERR("eina_list_prepend failed");
390 static int __write_max_cpu_freq(int freq)
394 ret = plugin_intf->OEM_sys_set_cpufreq_scaling_max_freq(freq);
396 PRT_TRACE_ERR("set cpufreq max freq write error: %s", strerror(errno));
403 static int __write_min_cpu_freq(int freq)
407 ret = plugin_intf->OEM_sys_set_cpufreq_scaling_min_freq(freq);
409 PRT_TRACE_ERR("set cpufreq min freq write error: %s", strerror(errno));