gaming_control, mali: more controls, optimizations
This commit is contained in:
parent
850830b157
commit
71e430b7c9
9 changed files with 289 additions and 93 deletions
|
@ -20,6 +20,8 @@
|
||||||
#include <linux/sti/abc_common.h>
|
#include <linux/sti/abc_common.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <linux/gaming_control.h>
|
||||||
|
|
||||||
bool sleep_mode = false;
|
bool sleep_mode = false;
|
||||||
|
|
||||||
static enum power_supply_property sec_battery_props[] = {
|
static enum power_supply_property sec_battery_props[] = {
|
||||||
|
@ -3502,6 +3504,9 @@ static void sec_bat_check_full_capacity(struct sec_battery_info *battery)
|
||||||
{
|
{
|
||||||
int rechg_capacity = battery->batt_full_capacity - 2;
|
int rechg_capacity = battery->batt_full_capacity - 2;
|
||||||
|
|
||||||
|
if(battery_idle_gaming() && battery->capacity >= 20)
|
||||||
|
goto warn;
|
||||||
|
|
||||||
if (battery->batt_full_capacity >= 100 || battery->batt_full_capacity <= 0 ||
|
if (battery->batt_full_capacity >= 100 || battery->batt_full_capacity <= 0 ||
|
||||||
battery->status == POWER_SUPPLY_STATUS_DISCHARGING) {
|
battery->status == POWER_SUPPLY_STATUS_DISCHARGING) {
|
||||||
if (battery->misc_event & BATT_MISC_EVENT_FULL_CAPACITY) {
|
if (battery->misc_event & BATT_MISC_EVENT_FULL_CAPACITY) {
|
||||||
|
@ -3518,6 +3523,7 @@ static void sec_bat_check_full_capacity(struct sec_battery_info *battery)
|
||||||
sec_bat_recov_full_capacity(battery);
|
sec_bat_recov_full_capacity(battery);
|
||||||
}
|
}
|
||||||
} else if (battery->capacity >= battery->batt_full_capacity) {
|
} else if (battery->capacity >= battery->batt_full_capacity) {
|
||||||
|
warn:
|
||||||
pr_info("%s : stop charging(%d, %d)\n", __func__, battery->capacity, battery->batt_full_capacity);
|
pr_info("%s : stop charging(%d, %d)\n", __func__, battery->capacity, battery->batt_full_capacity);
|
||||||
|
|
||||||
sec_bat_set_misc_event(battery, BATT_MISC_EVENT_FULL_CAPACITY,
|
sec_bat_set_misc_event(battery, BATT_MISC_EVENT_FULL_CAPACITY,
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
#include <linux/pm_opp.h>
|
#include <linux/pm_opp.h>
|
||||||
#include <linux/exynos-ucc.h>
|
#include <linux/exynos-ucc.h>
|
||||||
|
#include <linux/gaming_control.h>
|
||||||
#include <linux/sysfs_helpers.h>
|
#include <linux/sysfs_helpers.h>
|
||||||
#include <linux/ems_service.h>
|
#include <linux/ems_service.h>
|
||||||
|
|
||||||
|
@ -41,6 +42,9 @@ static bool unlock_freqs_switch = false;
|
||||||
|
|
||||||
bool exynos_cpufreq_get_unlock_freqs_status()
|
bool exynos_cpufreq_get_unlock_freqs_status()
|
||||||
{
|
{
|
||||||
|
if (gaming_mode)
|
||||||
|
return true;
|
||||||
|
|
||||||
return unlock_freqs_switch;
|
return unlock_freqs_switch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,6 +637,11 @@ static void cpufreq_max_limit_update(int input_freq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void exynos_cpufreq_set_gaming_mode(void) {
|
||||||
|
last_max_limit = -1;
|
||||||
|
cpufreq_max_limit_update(last_max_limit);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t store_cpufreq_max_limit(struct kobject *kobj, struct kobj_attribute *attr,
|
static ssize_t store_cpufreq_max_limit(struct kobject *kobj, struct kobj_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,10 +31,29 @@
|
||||||
#include <gpexbe_utilization.h>
|
#include <gpexbe_utilization.h>
|
||||||
#include <gpexbe_debug.h>
|
#include <gpexbe_debug.h>
|
||||||
|
|
||||||
|
#include <linux/gaming_control.h>
|
||||||
|
|
||||||
#include "gpex_clock_internal.h"
|
#include "gpex_clock_internal.h"
|
||||||
|
|
||||||
#define CPU_MAX INT_MAX
|
#define CPU_MAX INT_MAX
|
||||||
|
|
||||||
|
int gpu_min_clock_custom = 0;
|
||||||
|
int gpu_custom_min_clock(int gpu_min_clock)
|
||||||
|
{
|
||||||
|
gpu_min_clock_custom = gpu_min_clock;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gpu_max_clock_custom = 0;
|
||||||
|
int gpu_custom_max_clock(int gpu_max_clock)
|
||||||
|
{
|
||||||
|
gpu_max_clock_custom = gpu_max_clock;
|
||||||
|
|
||||||
|
gpex_clock_set(gpu_max_clock_custom);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct _clock_info clk_info;
|
static struct _clock_info clk_info;
|
||||||
|
|
||||||
int gpex_clock_get_boot_clock()
|
int gpex_clock_get_boot_clock()
|
||||||
|
@ -43,14 +62,23 @@ int gpex_clock_get_boot_clock()
|
||||||
}
|
}
|
||||||
int gpex_clock_get_max_clock()
|
int gpex_clock_get_max_clock()
|
||||||
{
|
{
|
||||||
|
if (gpu_max_clock_custom > 0)
|
||||||
|
return gpu_max_clock_custom;
|
||||||
|
|
||||||
return clk_info.gpu_max_clock;
|
return clk_info.gpu_max_clock;
|
||||||
}
|
}
|
||||||
int gpex_clock_get_max_clock_limit()
|
int gpex_clock_get_max_clock_limit()
|
||||||
{
|
{
|
||||||
|
if (gpu_max_clock_custom > 0)
|
||||||
|
return gpu_max_clock_custom;
|
||||||
|
|
||||||
return clk_info.gpu_max_clock_limit;
|
return clk_info.gpu_max_clock_limit;
|
||||||
}
|
}
|
||||||
int gpex_clock_get_min_clock()
|
int gpex_clock_get_min_clock()
|
||||||
{
|
{
|
||||||
|
if (gpu_min_clock_custom > 0)
|
||||||
|
return gpu_min_clock_custom;
|
||||||
|
|
||||||
return clk_info.gpu_min_clock;
|
return clk_info.gpu_min_clock;
|
||||||
}
|
}
|
||||||
int gpex_clock_get_cur_clock()
|
int gpex_clock_get_cur_clock()
|
||||||
|
@ -59,10 +87,16 @@ int gpex_clock_get_cur_clock()
|
||||||
}
|
}
|
||||||
int gpex_clock_get_max_lock()
|
int gpex_clock_get_max_lock()
|
||||||
{
|
{
|
||||||
|
if (gpu_max_clock_custom > 0)
|
||||||
|
return gpu_max_clock_custom;
|
||||||
|
|
||||||
return clk_info.max_lock;
|
return clk_info.max_lock;
|
||||||
}
|
}
|
||||||
int gpex_clock_get_min_lock()
|
int gpex_clock_get_min_lock()
|
||||||
{
|
{
|
||||||
|
if (gpu_min_clock_custom > 0)
|
||||||
|
return gpu_min_clock_custom;
|
||||||
|
|
||||||
return clk_info.min_lock;
|
return clk_info.min_lock;
|
||||||
}
|
}
|
||||||
int gpex_clock_get_clock(int level)
|
int gpex_clock_get_clock(int level)
|
||||||
|
@ -75,6 +109,9 @@ u64 gpex_clock_get_time_busy(int level)
|
||||||
}
|
}
|
||||||
bool gpex_clock_get_unlock_freqs_status()
|
bool gpex_clock_get_unlock_freqs_status()
|
||||||
{
|
{
|
||||||
|
if (gaming_mode)
|
||||||
|
return false;
|
||||||
|
|
||||||
return clk_info.unlock_freqs;
|
return clk_info.unlock_freqs;
|
||||||
}
|
}
|
||||||
int gpex_clock_update_config_data_from_dt()
|
int gpex_clock_update_config_data_from_dt()
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <soc/samsung/cal-if.h>
|
#include <soc/samsung/cal-if.h>
|
||||||
#include <linux/sysfs_helpers.h>
|
#include <linux/sysfs_helpers.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <linux/gaming_control.h>
|
||||||
|
|
||||||
#include "gpex_clock_internal.h"
|
#include "gpex_clock_internal.h"
|
||||||
|
|
||||||
|
@ -162,6 +163,9 @@ GPEX_STATIC ssize_t set_max_lock_dvfs(const char *buf, size_t count)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gaming_mode)
|
||||||
|
clock = gpex_clock_get_max_clock();
|
||||||
|
|
||||||
clk_info->user_max_lock_input = clock;
|
clk_info->user_max_lock_input = clock;
|
||||||
|
|
||||||
clock = gpex_get_valid_gpu_clock(clock, false);
|
clock = gpex_get_valid_gpu_clock(clock, false);
|
||||||
|
@ -256,6 +260,9 @@ GPEX_STATIC ssize_t set_min_lock_dvfs(const char *buf, size_t count)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gaming_mode)
|
||||||
|
clock = gpex_clock_get_min_clock();
|
||||||
|
|
||||||
clk_info->user_min_lock_input = clock;
|
clk_info->user_min_lock_input = clock;
|
||||||
|
|
||||||
clock = gpex_get_valid_gpu_clock(clock, true);
|
clock = gpex_get_valid_gpu_clock(clock, true);
|
||||||
|
@ -352,6 +359,9 @@ GPEX_STATIC ssize_t set_mm_min_lock_dvfs(const char *buf, size_t count)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gaming_mode)
|
||||||
|
clock = gpex_clock_get_min_clock();
|
||||||
|
|
||||||
clock = gpex_get_valid_gpu_clock(clock, true);
|
clock = gpex_get_valid_gpu_clock(clock, true);
|
||||||
|
|
||||||
ret = gpex_clock_get_table_idx(clock);
|
ret = gpex_clock_get_table_idx(clock);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2019
|
* Copyright (C) 2019
|
||||||
* Diep Quynh Nguyen <remilia.1505@gmail.com>
|
* Diep Quynh Nguyen <remilia.1505@gmail.com>
|
||||||
|
* Mustafa Gökmen <mustafa.gokmen2004@gmail.com>
|
||||||
*
|
*
|
||||||
* This software is licensed under the terms of the GNU General Public
|
* This software is licensed under the terms of the GNU General Public
|
||||||
* License version 2, as published by the Free Software Foundation, and
|
* License version 2, as published by the Free Software Foundation, and
|
||||||
|
@ -15,53 +16,74 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/binfmts.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
#include <linux/sysfs.h>
|
#include <linux/sysfs.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/gaming_control.h>
|
|
||||||
#include <linux/pm_qos.h>
|
#include <linux/pm_qos.h>
|
||||||
|
#include <linux/gaming_control.h>
|
||||||
|
|
||||||
#define GAME_LIST_LENGTH 1024
|
extern void exynos_cpufreq_set_gaming_mode(void);
|
||||||
#define NUM_SUPPORTED_RUNNING_GAMES 20
|
|
||||||
#define GAMING_CONTROL_VERSION "0.2"
|
|
||||||
|
|
||||||
#define TASK_STARTED 1
|
|
||||||
|
|
||||||
/* PM QoS implementation */
|
/* PM QoS implementation */
|
||||||
struct pm_qos_request gaming_control_min_mif_qos;
|
static struct pm_qos_request gaming_control_min_int_qos;
|
||||||
struct pm_qos_request gaming_control_min_big_qos;
|
static struct pm_qos_request gaming_control_min_mif_qos;
|
||||||
struct pm_qos_request gaming_control_max_big_qos;
|
static struct pm_qos_request gaming_control_min_big_qos;
|
||||||
struct pm_qos_request gaming_control_max_little_qos;
|
static struct pm_qos_request gaming_control_max_big_qos;
|
||||||
|
static struct pm_qos_request gaming_control_min_little_qos;
|
||||||
|
static struct pm_qos_request gaming_control_max_little_qos;
|
||||||
|
static unsigned int min_int_freq = 534000;
|
||||||
static unsigned int min_mif_freq = 1794000;
|
static unsigned int min_mif_freq = 1794000;
|
||||||
static unsigned int max_little_freq = 1456000;
|
static unsigned int min_little_freq = 1456000;
|
||||||
static unsigned int min_big_freq = 1703000;
|
static unsigned int max_little_freq = 2002000;
|
||||||
static unsigned int max_big_freq = 2002000;
|
static unsigned int min_big_freq = 1469000;
|
||||||
|
static unsigned int max_big_freq = 2886000;
|
||||||
|
static unsigned int min_gpu_freq = 598000;
|
||||||
|
static unsigned int max_gpu_freq = 598000;
|
||||||
|
static int nr_running_games = 0;
|
||||||
|
static bool always_on = 0;
|
||||||
|
static bool battery_idle = 0;
|
||||||
|
bool gaming_mode;
|
||||||
|
|
||||||
char games_list[GAME_LIST_LENGTH] = {0};
|
char games_list[GAME_LIST_LENGTH] = {0};
|
||||||
int games_pid[NUM_SUPPORTED_RUNNING_GAMES] = {
|
pid_t games_pid[NUM_SUPPORTED_RUNNING_GAMES] = {
|
||||||
[0 ... (NUM_SUPPORTED_RUNNING_GAMES - 1)] = -1
|
[0 ... (NUM_SUPPORTED_RUNNING_GAMES - 1)] = -1
|
||||||
};
|
};
|
||||||
static int nr_running_games = 0;
|
|
||||||
|
|
||||||
static void set_gaming_mode(int mode)
|
static inline void set_gaming_mode(bool mode, bool force)
|
||||||
{
|
{
|
||||||
if (mode == 0) {
|
if (always_on)
|
||||||
pm_qos_update_request(&gaming_control_min_mif_qos, PM_QOS_BUS_THROUGHPUT_DEFAULT_VALUE);
|
mode = 1;
|
||||||
pm_qos_update_request(&gaming_control_max_little_qos, PM_QOS_CLUSTER0_FREQ_MAX_DEFAULT_VALUE);
|
|
||||||
pm_qos_update_request(&gaming_control_min_big_qos, PM_QOS_CLUSTER1_FREQ_MIN_DEFAULT_VALUE);
|
if (mode == gaming_mode && !force)
|
||||||
pm_qos_update_request(&gaming_control_max_big_qos, PM_QOS_CLUSTER1_FREQ_MAX_DEFAULT_VALUE);
|
return;
|
||||||
} else if (mode == 1) {
|
else
|
||||||
pm_qos_update_request(&gaming_control_min_mif_qos, min_mif_freq);
|
gaming_mode = mode;
|
||||||
pm_qos_update_request(&gaming_control_max_little_qos, max_little_freq);
|
|
||||||
pm_qos_update_request(&gaming_control_min_big_qos, min_big_freq);
|
exynos_cpufreq_set_gaming_mode();
|
||||||
pm_qos_update_request(&gaming_control_max_big_qos, max_big_freq);
|
|
||||||
}
|
pm_qos_update_request(&gaming_control_min_int_qos, mode && min_int_freq ? min_int_freq : PM_QOS_DEVICE_THROUGHPUT_DEFAULT_VALUE);
|
||||||
|
pm_qos_update_request(&gaming_control_min_mif_qos, mode && min_mif_freq ? min_mif_freq : PM_QOS_BUS_THROUGHPUT_DEFAULT_VALUE);
|
||||||
|
pm_qos_update_request(&gaming_control_min_little_qos, mode && min_little_freq ? min_little_freq : PM_QOS_CLUSTER0_FREQ_MIN_DEFAULT_VALUE);
|
||||||
|
pm_qos_update_request(&gaming_control_max_little_qos, mode && max_little_freq ? max_little_freq : PM_QOS_CLUSTER0_FREQ_MAX_DEFAULT_VALUE);
|
||||||
|
pm_qos_update_request(&gaming_control_min_big_qos, mode && min_big_freq ? min_big_freq : PM_QOS_CLUSTER1_FREQ_MIN_DEFAULT_VALUE);
|
||||||
|
pm_qos_update_request(&gaming_control_max_big_qos, mode && max_big_freq ? max_big_freq : PM_QOS_CLUSTER1_FREQ_MAX_DEFAULT_VALUE);
|
||||||
|
|
||||||
|
gpu_custom_max_clock(mode ? max_gpu_freq : 0);
|
||||||
|
gpu_custom_min_clock(mode ? min_gpu_freq : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void store_game_pid(int pid)
|
bool battery_idle_gaming(void) {
|
||||||
|
if (gaming_mode && battery_idle)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void store_game_pid(pid_t pid)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -69,25 +91,53 @@ static void store_game_pid(int pid)
|
||||||
if (games_pid[i] == -1) {
|
if (games_pid[i] == -1) {
|
||||||
games_pid[i] = pid;
|
games_pid[i] = pid;
|
||||||
nr_running_games++;
|
nr_running_games++;
|
||||||
} }
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_dead_pids(void)
|
static inline int check_game_pid(pid_t pid)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < NUM_SUPPORTED_RUNNING_GAMES; i++) {
|
for (i = 0; i < NUM_SUPPORTED_RUNNING_GAMES; i++) {
|
||||||
if (games_pid[i] != -1) {
|
if (games_pid[i] != -1) {
|
||||||
if (find_task_by_vpid(games_pid[i]) == NULL) {
|
if (games_pid[i] == pid)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clear_dead_pids(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_SUPPORTED_RUNNING_GAMES; i++) {
|
||||||
|
if (games_pid[i] != -1) {
|
||||||
|
rcu_read_lock();
|
||||||
|
if (!find_task_by_vpid(games_pid[i])) {
|
||||||
games_pid[i] = -1;
|
games_pid[i] = -1;
|
||||||
nr_running_games--;
|
nr_running_games--;
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there's no running games, turn off game mode */
|
/* If there's no running games, turn off game mode */
|
||||||
if (nr_running_games == 0)
|
if (nr_running_games == 0)
|
||||||
set_gaming_mode(0);
|
set_gaming_mode(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void removeSubstringAfterChar(char *str, char ch) {
|
||||||
|
char *ptr = str;
|
||||||
|
while (*ptr != '\0') {
|
||||||
|
if (*ptr == ch) {
|
||||||
|
*(ptr) = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_for_games(struct task_struct *tsk)
|
static int check_for_games(struct task_struct *tsk)
|
||||||
|
@ -105,8 +155,11 @@ static int check_for_games(struct task_struct *tsk)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clean extra process identifier */
|
||||||
|
removeSubstringAfterChar(cmdline, ':');
|
||||||
|
|
||||||
/* Invalid Android process name. Bail out */
|
/* Invalid Android process name. Bail out */
|
||||||
if (strlen(cmdline) < 7) {
|
if (!strcmp(cmdline, "android") || strlen(cmdline) < 7) {
|
||||||
kfree(cmdline);
|
kfree(cmdline);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -124,29 +177,36 @@ static int check_for_games(struct task_struct *tsk)
|
||||||
|
|
||||||
void game_option(struct task_struct *tsk, enum game_opts opts)
|
void game_option(struct task_struct *tsk, enum game_opts opts)
|
||||||
{
|
{
|
||||||
|
pid_t pid;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Remove all zombie tasks PIDs */
|
/* Remove all zombie tasks PIDs */
|
||||||
clear_dead_pids();
|
clear_dead_pids();
|
||||||
|
|
||||||
|
if(always_on) {
|
||||||
|
set_gaming_mode(true, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ret = check_for_games(tsk);
|
ret = check_for_games(tsk);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (opts) {
|
switch (opts) {
|
||||||
case GAME_START:
|
case GAME_START:
|
||||||
if (tsk->app_state == TASK_STARTED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
store_game_pid(tsk->pid);
|
|
||||||
tsk->app_state = TASK_STARTED;
|
|
||||||
set_gaming_mode(1);
|
|
||||||
break;
|
|
||||||
case GAME_RUNNING:
|
case GAME_RUNNING:
|
||||||
set_gaming_mode(1);
|
set_gaming_mode(true, false);
|
||||||
|
|
||||||
|
pid = task_pid_vnr(tsk);
|
||||||
|
|
||||||
|
if (tsk->app_state == TASK_STARTED || check_game_pid(pid))
|
||||||
|
break;
|
||||||
|
|
||||||
|
store_game_pid(pid);
|
||||||
|
tsk->app_state = TASK_STARTED;
|
||||||
break;
|
break;
|
||||||
case GAME_PAUSE:
|
case GAME_PAUSE:
|
||||||
set_gaming_mode(0);
|
set_gaming_mode(false, false);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -172,36 +232,58 @@ static ssize_t game_packages_store(struct kobject *kobj,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show maximum freq */
|
/* Show/Store value */
|
||||||
#define show_freq(type) \
|
#define attr_value(type) \
|
||||||
|
static ssize_t type##_store(struct kobject *kobj, \
|
||||||
|
struct kobj_attribute *attr, const char *buf, size_t count) \
|
||||||
|
{ \
|
||||||
|
unsigned int value; \
|
||||||
|
\
|
||||||
|
sscanf(buf, "%u\n", &value); \
|
||||||
|
type = value; \
|
||||||
|
\
|
||||||
|
set_gaming_mode(gaming_mode, gaming_mode); \
|
||||||
|
\
|
||||||
|
return count; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
static ssize_t type##_show(struct kobject *kobj, \
|
static ssize_t type##_show(struct kobject *kobj, \
|
||||||
struct kobj_attribute *attr, char *buf) \
|
struct kobj_attribute *attr, char *buf) \
|
||||||
{ \
|
{ \
|
||||||
return sprintf(buf, "%u\n", type); \
|
return sprintf(buf, "%u\n", type); \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
show_freq(min_mif_freq);
|
|
||||||
show_freq(max_little_freq);
|
|
||||||
show_freq(min_big_freq);
|
|
||||||
show_freq(max_big_freq);
|
|
||||||
|
|
||||||
/* Store maximum freq */
|
|
||||||
#define store_freq(type) \
|
|
||||||
static ssize_t type##_store(struct kobject *kobj, \
|
|
||||||
struct kobj_attribute *attr, const char *buf, size_t count) \
|
|
||||||
{ \
|
|
||||||
unsigned int freq; \
|
|
||||||
\
|
\
|
||||||
sscanf(buf, "%u\n", &freq); \
|
static struct kobj_attribute type##_attribute = \
|
||||||
type = freq; \
|
__ATTR(type, 0644, type##_show, type##_store);
|
||||||
\
|
|
||||||
return count; \
|
|
||||||
} \
|
|
||||||
|
|
||||||
store_freq(min_mif_freq);
|
attr_value(always_on);
|
||||||
store_freq(max_little_freq);
|
attr_value(battery_idle);
|
||||||
store_freq(min_big_freq);
|
attr_value(min_int_freq);
|
||||||
store_freq(max_big_freq);
|
attr_value(min_mif_freq);
|
||||||
|
attr_value(min_little_freq);
|
||||||
|
attr_value(max_little_freq);
|
||||||
|
attr_value(min_big_freq);
|
||||||
|
attr_value(max_big_freq);
|
||||||
|
attr_value(min_gpu_freq);
|
||||||
|
attr_value(max_gpu_freq);
|
||||||
|
|
||||||
|
static ssize_t status_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
ssize_t len = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
len += sprintf(buf + len, "%d\n\n", nr_running_games);
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_SUPPORTED_RUNNING_GAMES; i++) {
|
||||||
|
if (games_pid[i] != -1)
|
||||||
|
len += sprintf(buf + len, "%d\n", games_pid[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t version_show(struct kobject *kobj,
|
static ssize_t version_show(struct kobject *kobj,
|
||||||
struct kobj_attribute *attr, char *buf)
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
@ -209,31 +291,29 @@ static ssize_t version_show(struct kobject *kobj,
|
||||||
return sprintf(buf, "%s\n", GAMING_CONTROL_VERSION);
|
return sprintf(buf, "%s\n", GAMING_CONTROL_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kobj_attribute game_packages_attribute =
|
static struct kobj_attribute status_attribute =
|
||||||
__ATTR(game_packages, 0644, game_packages_show, game_packages_store);
|
__ATTR(status, 0444, status_show, NULL);
|
||||||
|
|
||||||
static struct kobj_attribute version_attribute =
|
static struct kobj_attribute version_attribute =
|
||||||
__ATTR(version, 0444, version_show, NULL);
|
__ATTR(version, 0444, version_show, NULL);
|
||||||
|
|
||||||
static struct kobj_attribute min_mif_freq_attribute =
|
static struct kobj_attribute game_packages_attribute =
|
||||||
__ATTR(min_mif, 0644, min_mif_freq_show, min_mif_freq_store);
|
__ATTR(game_packages, 0644, game_packages_show, game_packages_store);
|
||||||
|
|
||||||
static struct kobj_attribute max_little_freq_attribute =
|
|
||||||
__ATTR(little_freq_max, 0644, max_little_freq_show, max_little_freq_store);
|
|
||||||
|
|
||||||
static struct kobj_attribute min_big_freq_attribute =
|
|
||||||
__ATTR(big_freq_min, 0644, min_big_freq_show, min_big_freq_store);
|
|
||||||
|
|
||||||
static struct kobj_attribute max_big_freq_attribute =
|
|
||||||
__ATTR(big_freq_max, 0644, max_big_freq_show, max_big_freq_store);
|
|
||||||
|
|
||||||
static struct attribute *gaming_control_attributes[] = {
|
static struct attribute *gaming_control_attributes[] = {
|
||||||
&game_packages_attribute.attr,
|
&game_packages_attribute.attr,
|
||||||
|
&status_attribute.attr,
|
||||||
&version_attribute.attr,
|
&version_attribute.attr,
|
||||||
|
&always_on_attribute.attr,
|
||||||
|
&battery_idle_attribute.attr,
|
||||||
|
&min_int_freq_attribute.attr,
|
||||||
&min_mif_freq_attribute.attr,
|
&min_mif_freq_attribute.attr,
|
||||||
|
&min_little_freq_attribute.attr,
|
||||||
&max_little_freq_attribute.attr,
|
&max_little_freq_attribute.attr,
|
||||||
&min_big_freq_attribute.attr,
|
&min_big_freq_attribute.attr,
|
||||||
&max_big_freq_attribute.attr,
|
&max_big_freq_attribute.attr,
|
||||||
|
&min_gpu_freq_attribute.attr,
|
||||||
|
&max_gpu_freq_attribute.attr,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -247,7 +327,9 @@ static int gaming_control_init(void)
|
||||||
{
|
{
|
||||||
int sysfs_result;
|
int sysfs_result;
|
||||||
|
|
||||||
|
pm_qos_add_request(&gaming_control_min_int_qos, PM_QOS_DEVICE_THROUGHPUT, PM_QOS_DEVICE_THROUGHPUT_DEFAULT_VALUE);
|
||||||
pm_qos_add_request(&gaming_control_min_mif_qos, PM_QOS_BUS_THROUGHPUT, PM_QOS_BUS_THROUGHPUT_DEFAULT_VALUE);
|
pm_qos_add_request(&gaming_control_min_mif_qos, PM_QOS_BUS_THROUGHPUT, PM_QOS_BUS_THROUGHPUT_DEFAULT_VALUE);
|
||||||
|
pm_qos_add_request(&gaming_control_min_little_qos, PM_QOS_CLUSTER0_FREQ_MIN, PM_QOS_CLUSTER0_FREQ_MIN_DEFAULT_VALUE);
|
||||||
pm_qos_add_request(&gaming_control_max_little_qos, PM_QOS_CLUSTER0_FREQ_MAX, PM_QOS_CLUSTER0_FREQ_MAX_DEFAULT_VALUE);
|
pm_qos_add_request(&gaming_control_max_little_qos, PM_QOS_CLUSTER0_FREQ_MAX, PM_QOS_CLUSTER0_FREQ_MAX_DEFAULT_VALUE);
|
||||||
pm_qos_add_request(&gaming_control_min_big_qos, PM_QOS_CLUSTER1_FREQ_MIN, PM_QOS_CLUSTER1_FREQ_MIN_DEFAULT_VALUE);
|
pm_qos_add_request(&gaming_control_min_big_qos, PM_QOS_CLUSTER1_FREQ_MIN, PM_QOS_CLUSTER1_FREQ_MIN_DEFAULT_VALUE);
|
||||||
pm_qos_add_request(&gaming_control_max_big_qos, PM_QOS_CLUSTER1_FREQ_MAX, PM_QOS_CLUSTER1_FREQ_MAX_DEFAULT_VALUE);
|
pm_qos_add_request(&gaming_control_max_big_qos, PM_QOS_CLUSTER1_FREQ_MAX, PM_QOS_CLUSTER1_FREQ_MAX_DEFAULT_VALUE);
|
||||||
|
@ -272,7 +354,9 @@ static int gaming_control_init(void)
|
||||||
|
|
||||||
static void gaming_control_exit(void)
|
static void gaming_control_exit(void)
|
||||||
{
|
{
|
||||||
|
pm_qos_remove_request(&gaming_control_min_int_qos);
|
||||||
pm_qos_remove_request(&gaming_control_min_mif_qos);
|
pm_qos_remove_request(&gaming_control_min_mif_qos);
|
||||||
|
pm_qos_remove_request(&gaming_control_min_little_qos);
|
||||||
pm_qos_remove_request(&gaming_control_max_little_qos);
|
pm_qos_remove_request(&gaming_control_max_little_qos);
|
||||||
pm_qos_remove_request(&gaming_control_min_big_qos);
|
pm_qos_remove_request(&gaming_control_min_big_qos);
|
||||||
pm_qos_remove_request(&gaming_control_max_big_qos);
|
pm_qos_remove_request(&gaming_control_max_big_qos);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/sysfs.h>
|
#include <linux/sysfs.h>
|
||||||
|
#include <linux/gaming_control.h>
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* CPUFREQ INTERFACE *
|
* CPUFREQ INTERFACE *
|
||||||
|
@ -381,9 +382,11 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
|
||||||
const char *cpufreq_get_current_driver(void);
|
const char *cpufreq_get_current_driver(void);
|
||||||
void *cpufreq_get_driver_data(void);
|
void *cpufreq_get_driver_data(void);
|
||||||
|
|
||||||
static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
|
static inline void cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
|
||||||
unsigned int min, unsigned int max)
|
|
||||||
{
|
{
|
||||||
|
unsigned int min = policy->cpuinfo.min_freq;
|
||||||
|
unsigned int max = policy->cpuinfo.max_freq;
|
||||||
|
|
||||||
if (policy->min < min)
|
if (policy->min < min)
|
||||||
policy->min = min;
|
policy->min = min;
|
||||||
if (policy->max < min)
|
if (policy->max < min)
|
||||||
|
@ -397,11 +400,23 @@ static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
|
||||||
cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
|
unsigned int min, unsigned int max)
|
||||||
{
|
{
|
||||||
cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
if (gaming_mode)
|
||||||
policy->cpuinfo.max_freq);
|
cpufreq_verify_within_cpu_limits(policy);
|
||||||
|
|
||||||
|
if (policy->min < min)
|
||||||
|
policy->min = min;
|
||||||
|
if (policy->max < min)
|
||||||
|
policy->max = min;
|
||||||
|
if (policy->min > max)
|
||||||
|
policy->min = max;
|
||||||
|
if (policy->max > max)
|
||||||
|
policy->max = max;
|
||||||
|
if (policy->min > policy->max)
|
||||||
|
policy->min = policy->max;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_FREQ
|
#ifdef CONFIG_CPU_FREQ
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2019
|
* Copyright (C) 2019
|
||||||
* Diep Quynh Nguyen <remilia.1505@gmail.com>
|
* Diep Quynh Nguyen <remilia.1505@gmail.com>
|
||||||
|
* Mustafa Gökmen <mustafa.gokmen2004@gmail.com>
|
||||||
*
|
*
|
||||||
* This software is licensed under the terms of the GNU General Public
|
* This software is licensed under the terms of the GNU General Public
|
||||||
* License version 2, as published by the Free Software Foundation, and
|
* License version 2, as published by the Free Software Foundation, and
|
||||||
|
@ -18,16 +19,45 @@
|
||||||
#ifndef _GAMING_CONTROL_H_
|
#ifndef _GAMING_CONTROL_H_
|
||||||
#define _GAMING_CONTROL_H_
|
#define _GAMING_CONTROL_H_
|
||||||
|
|
||||||
|
#define GAME_LIST_LENGTH 1024
|
||||||
|
#define NUM_SUPPORTED_RUNNING_GAMES 20
|
||||||
|
#define GAMING_CONTROL_VERSION "0.4"
|
||||||
|
|
||||||
|
#define TASK_STARTED 1
|
||||||
|
|
||||||
enum game_opts {
|
enum game_opts {
|
||||||
GAME_START,
|
GAME_START,
|
||||||
GAME_RUNNING,
|
GAME_RUNNING,
|
||||||
GAME_PAUSE
|
GAME_PAUSE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum dvfs_id {
|
||||||
|
DVFS_MIF = 0,
|
||||||
|
DVFS_INT,
|
||||||
|
DVFS_CPUCL0,
|
||||||
|
DVFS_CPUCL1,
|
||||||
|
DVFS_G3D,
|
||||||
|
DVFS_INTCAM,
|
||||||
|
DVFS_FSYS0,
|
||||||
|
DVFS_CAM,
|
||||||
|
DVFS_DISP_EVT1,
|
||||||
|
DVFS_AUD,
|
||||||
|
DVFS_IVA,
|
||||||
|
DVFS_SCORE,
|
||||||
|
DVFS_CP,
|
||||||
|
};
|
||||||
|
|
||||||
|
int gpu_custom_min_clock(int gpu_min_clock);
|
||||||
|
int gpu_custom_max_clock(int gpu_max_clock);
|
||||||
|
|
||||||
#ifdef CONFIG_GAMING_CONTROL
|
#ifdef CONFIG_GAMING_CONTROL
|
||||||
|
extern bool gaming_mode;
|
||||||
extern void game_option(struct task_struct *tsk, enum game_opts opts);
|
extern void game_option(struct task_struct *tsk, enum game_opts opts);
|
||||||
|
extern bool battery_idle_gaming(void);
|
||||||
#else
|
#else
|
||||||
static void game_option(struct task_struct *tsk, enum game_opts opts) {}
|
static bool gaming_mode = 0;
|
||||||
|
static void game_option(struct task_struct *tsk, enum game_opts opts) {};
|
||||||
|
static bool battery_idle_gaming(void) {return false;};
|
||||||
#endif /* CONFIG_GAMING_CONTROL */
|
#endif /* CONFIG_GAMING_CONTROL */
|
||||||
|
|
||||||
#endif /* _GAMING_CONTROL_H_ */
|
#endif /* _GAMING_CONTROL_H_ */
|
|
@ -71,6 +71,15 @@
|
||||||
/* Gaming control */
|
/* Gaming control */
|
||||||
#include <linux/gaming_control.h>
|
#include <linux/gaming_control.h>
|
||||||
|
|
||||||
|
/* Check if the task is a game */
|
||||||
|
static void cgroup_game_check(struct task_struct *tsk, const char *name)
|
||||||
|
{
|
||||||
|
if (!strcmp(name, "top-app"))
|
||||||
|
game_option(tsk, GAME_RUNNING);
|
||||||
|
else if (!strcmp(name, "background"))
|
||||||
|
game_option(tsk, GAME_PAUSE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pidlists linger the following amount before being destroyed. The goal
|
* pidlists linger the following amount before being destroyed. The goal
|
||||||
* is avoiding frequent destruction in the middle of consecutive read calls
|
* is avoiding frequent destruction in the middle of consecutive read calls
|
||||||
|
@ -2925,12 +2934,8 @@ static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf,
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = cgroup_attach_task(cgrp, tsk, threadgroup);
|
ret = cgroup_attach_task(cgrp, tsk, threadgroup);
|
||||||
|
|
||||||
/* Check if the task is a game */
|
if (!ret)
|
||||||
if (!memcmp(cgrp->kn->name, "top-app", sizeof("top-app")) && !ret) {
|
cgroup_game_check(tsk, of->kn->parent->name);
|
||||||
game_option(tsk, GAME_RUNNING);
|
|
||||||
} else if (!memcmp(cgrp->kn->name, "background", sizeof("background")) && !ret) {
|
|
||||||
game_option(tsk, GAME_PAUSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
put_task_struct(tsk);
|
put_task_struct(tsk);
|
||||||
goto out_unlock_threadgroup;
|
goto out_unlock_threadgroup;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue