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>
|
||||
#endif
|
||||
|
||||
#include <linux/gaming_control.h>
|
||||
|
||||
bool sleep_mode = false;
|
||||
|
||||
static enum power_supply_property sec_battery_props[] = {
|
||||
|
@ -3501,6 +3503,9 @@ static void sec_bat_recov_full_capacity(struct sec_battery_info *battery)
|
|||
static void sec_bat_check_full_capacity(struct sec_battery_info *battery)
|
||||
{
|
||||
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 ||
|
||||
battery->status == POWER_SUPPLY_STATUS_DISCHARGING) {
|
||||
|
@ -3518,6 +3523,7 @@ static void sec_bat_check_full_capacity(struct sec_battery_info *battery)
|
|||
sec_bat_recov_full_capacity(battery);
|
||||
}
|
||||
} else if (battery->capacity >= battery->batt_full_capacity) {
|
||||
warn:
|
||||
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,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/cpufreq.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/exynos-ucc.h>
|
||||
#include <linux/gaming_control.h>
|
||||
#include <linux/sysfs_helpers.h>
|
||||
#include <linux/ems_service.h>
|
||||
|
||||
|
@ -41,6 +42,9 @@ static bool unlock_freqs_switch = false;
|
|||
|
||||
bool exynos_cpufreq_get_unlock_freqs_status()
|
||||
{
|
||||
if (gaming_mode)
|
||||
return true;
|
||||
|
||||
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,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
|
|
|
@ -31,10 +31,29 @@
|
|||
#include <gpexbe_utilization.h>
|
||||
#include <gpexbe_debug.h>
|
||||
|
||||
#include <linux/gaming_control.h>
|
||||
|
||||
#include "gpex_clock_internal.h"
|
||||
|
||||
#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;
|
||||
|
||||
int gpex_clock_get_boot_clock()
|
||||
|
@ -43,14 +62,23 @@ int gpex_clock_get_boot_clock()
|
|||
}
|
||||
int gpex_clock_get_max_clock()
|
||||
{
|
||||
if (gpu_max_clock_custom > 0)
|
||||
return gpu_max_clock_custom;
|
||||
|
||||
return clk_info.gpu_max_clock;
|
||||
}
|
||||
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;
|
||||
}
|
||||
int gpex_clock_get_min_clock()
|
||||
{
|
||||
if (gpu_min_clock_custom > 0)
|
||||
return gpu_min_clock_custom;
|
||||
|
||||
return clk_info.gpu_min_clock;
|
||||
}
|
||||
int gpex_clock_get_cur_clock()
|
||||
|
@ -59,10 +87,16 @@ int gpex_clock_get_cur_clock()
|
|||
}
|
||||
int gpex_clock_get_max_lock()
|
||||
{
|
||||
if (gpu_max_clock_custom > 0)
|
||||
return gpu_max_clock_custom;
|
||||
|
||||
return clk_info.max_lock;
|
||||
}
|
||||
int gpex_clock_get_min_lock()
|
||||
{
|
||||
if (gpu_min_clock_custom > 0)
|
||||
return gpu_min_clock_custom;
|
||||
|
||||
return clk_info.min_lock;
|
||||
}
|
||||
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()
|
||||
{
|
||||
if (gaming_mode)
|
||||
return false;
|
||||
|
||||
return clk_info.unlock_freqs;
|
||||
}
|
||||
int gpex_clock_update_config_data_from_dt()
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <soc/samsung/cal-if.h>
|
||||
#include <linux/sysfs_helpers.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/gaming_control.h>
|
||||
|
||||
#include "gpex_clock_internal.h"
|
||||
|
||||
|
@ -161,6 +162,9 @@ GPEX_STATIC ssize_t set_max_lock_dvfs(const char *buf, size_t count)
|
|||
GPU_LOG(MALI_EXYNOS_WARNING, "%s: invalid value\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (gaming_mode)
|
||||
clock = gpex_clock_get_max_clock();
|
||||
|
||||
clk_info->user_max_lock_input = clock;
|
||||
|
||||
|
@ -255,6 +259,9 @@ GPEX_STATIC ssize_t set_min_lock_dvfs(const char *buf, size_t count)
|
|||
GPU_LOG(MALI_EXYNOS_WARNING, "%s: invalid value\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (gaming_mode)
|
||||
clock = gpex_clock_get_min_clock();
|
||||
|
||||
clk_info->user_min_lock_input = clock;
|
||||
|
||||
|
@ -351,6 +358,9 @@ GPEX_STATIC ssize_t set_mm_min_lock_dvfs(const char *buf, size_t count)
|
|||
GPU_LOG(MALI_EXYNOS_WARNING, "%s: invalid value\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (gaming_mode)
|
||||
clock = gpex_clock_get_min_clock();
|
||||
|
||||
clock = gpex_get_valid_gpu_clock(clock, true);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2019
|
||||
* 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
|
||||
* 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/kobject.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gaming_control.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/gaming_control.h>
|
||||
|
||||
#define GAME_LIST_LENGTH 1024
|
||||
#define NUM_SUPPORTED_RUNNING_GAMES 20
|
||||
#define GAMING_CONTROL_VERSION "0.2"
|
||||
|
||||
#define TASK_STARTED 1
|
||||
extern void exynos_cpufreq_set_gaming_mode(void);
|
||||
|
||||
/* PM QoS implementation */
|
||||
struct pm_qos_request gaming_control_min_mif_qos;
|
||||
struct pm_qos_request gaming_control_min_big_qos;
|
||||
struct pm_qos_request gaming_control_max_big_qos;
|
||||
struct pm_qos_request gaming_control_max_little_qos;
|
||||
static struct pm_qos_request gaming_control_min_int_qos;
|
||||
static struct pm_qos_request gaming_control_min_mif_qos;
|
||||
static struct pm_qos_request gaming_control_min_big_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 max_little_freq = 1456000;
|
||||
static unsigned int min_big_freq = 1703000;
|
||||
static unsigned int max_big_freq = 2002000;
|
||||
static unsigned int min_little_freq = 1456000;
|
||||
static unsigned int max_little_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};
|
||||
int games_pid[NUM_SUPPORTED_RUNNING_GAMES] = {
|
||||
pid_t games_pid[NUM_SUPPORTED_RUNNING_GAMES] = {
|
||||
[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) {
|
||||
pm_qos_update_request(&gaming_control_min_mif_qos, PM_QOS_BUS_THROUGHPUT_DEFAULT_VALUE);
|
||||
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);
|
||||
pm_qos_update_request(&gaming_control_max_big_qos, PM_QOS_CLUSTER1_FREQ_MAX_DEFAULT_VALUE);
|
||||
} else if (mode == 1) {
|
||||
pm_qos_update_request(&gaming_control_min_mif_qos, min_mif_freq);
|
||||
pm_qos_update_request(&gaming_control_max_little_qos, max_little_freq);
|
||||
pm_qos_update_request(&gaming_control_min_big_qos, min_big_freq);
|
||||
pm_qos_update_request(&gaming_control_max_big_qos, max_big_freq);
|
||||
}
|
||||
if (always_on)
|
||||
mode = 1;
|
||||
|
||||
if (mode == gaming_mode && !force)
|
||||
return;
|
||||
else
|
||||
gaming_mode = mode;
|
||||
|
||||
exynos_cpufreq_set_gaming_mode();
|
||||
|
||||
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;
|
||||
|
||||
|
@ -69,25 +91,53 @@ static void store_game_pid(int pid)
|
|||
if (games_pid[i] == -1) {
|
||||
games_pid[i] = pid;
|
||||
nr_running_games++;
|
||||
} }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_dead_pids(void)
|
||||
static inline int check_game_pid(pid_t pid)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_SUPPORTED_RUNNING_GAMES; i++) {
|
||||
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;
|
||||
nr_running_games--;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/* If there's no running games, turn off game mode */
|
||||
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)
|
||||
|
@ -105,8 +155,11 @@ static int check_for_games(struct task_struct *tsk)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* clean extra process identifier */
|
||||
removeSubstringAfterChar(cmdline, ':');
|
||||
|
||||
/* Invalid Android process name. Bail out */
|
||||
if (strlen(cmdline) < 7) {
|
||||
if (!strcmp(cmdline, "android") || strlen(cmdline) < 7) {
|
||||
kfree(cmdline);
|
||||
return 0;
|
||||
}
|
||||
|
@ -124,10 +177,16 @@ static int check_for_games(struct task_struct *tsk)
|
|||
|
||||
void game_option(struct task_struct *tsk, enum game_opts opts)
|
||||
{
|
||||
pid_t pid;
|
||||
int ret;
|
||||
|
||||
/* Remove all zombie tasks PIDs */
|
||||
clear_dead_pids();
|
||||
|
||||
if(always_on) {
|
||||
set_gaming_mode(true, false);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = check_for_games(tsk);
|
||||
if (!ret)
|
||||
|
@ -135,18 +194,19 @@ void game_option(struct task_struct *tsk, enum game_opts opts)
|
|||
|
||||
switch (opts) {
|
||||
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:
|
||||
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;
|
||||
case GAME_PAUSE:
|
||||
set_gaming_mode(0);
|
||||
set_gaming_mode(false, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -172,36 +232,58 @@ static ssize_t game_packages_store(struct kobject *kobj,
|
|||
return count;
|
||||
}
|
||||
|
||||
/* Show maximum freq */
|
||||
#define show_freq(type) \
|
||||
/* Show/Store value */
|
||||
#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, \
|
||||
struct kobj_attribute *attr, char *buf) \
|
||||
{ \
|
||||
return sprintf(buf, "%u\n", type); \
|
||||
} \
|
||||
\
|
||||
static struct kobj_attribute type##_attribute = \
|
||||
__ATTR(type, 0644, type##_show, type##_store);
|
||||
|
||||
show_freq(min_mif_freq);
|
||||
show_freq(max_little_freq);
|
||||
show_freq(min_big_freq);
|
||||
show_freq(max_big_freq);
|
||||
attr_value(always_on);
|
||||
attr_value(battery_idle);
|
||||
attr_value(min_int_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);
|
||||
|
||||
/* 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); \
|
||||
type = freq; \
|
||||
\
|
||||
return count; \
|
||||
} \
|
||||
static ssize_t status_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
int i;
|
||||
|
||||
store_freq(min_mif_freq);
|
||||
store_freq(max_little_freq);
|
||||
store_freq(min_big_freq);
|
||||
store_freq(max_big_freq);
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
static struct kobj_attribute game_packages_attribute =
|
||||
__ATTR(game_packages, 0644, game_packages_show, game_packages_store);
|
||||
static struct kobj_attribute status_attribute =
|
||||
__ATTR(status, 0444, status_show, NULL);
|
||||
|
||||
static struct kobj_attribute version_attribute =
|
||||
__ATTR(version, 0444, version_show, NULL);
|
||||
|
||||
static struct kobj_attribute min_mif_freq_attribute =
|
||||
__ATTR(min_mif, 0644, min_mif_freq_show, min_mif_freq_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 kobj_attribute game_packages_attribute =
|
||||
__ATTR(game_packages, 0644, game_packages_show, game_packages_store);
|
||||
|
||||
static struct attribute *gaming_control_attributes[] = {
|
||||
&game_packages_attribute.attr,
|
||||
&status_attribute.attr,
|
||||
&version_attribute.attr,
|
||||
&always_on_attribute.attr,
|
||||
&battery_idle_attribute.attr,
|
||||
&min_int_freq_attribute.attr,
|
||||
&min_mif_freq_attribute.attr,
|
||||
&min_little_freq_attribute.attr,
|
||||
&max_little_freq_attribute.attr,
|
||||
&min_big_freq_attribute.attr,
|
||||
&max_big_freq_attribute.attr,
|
||||
&min_gpu_freq_attribute.attr,
|
||||
&max_gpu_freq_attribute.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -247,7 +327,9 @@ static int gaming_control_init(void)
|
|||
{
|
||||
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_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_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);
|
||||
|
@ -272,7 +354,9 @@ static int gaming_control_init(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_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_max_big_qos);
|
||||
|
@ -282,4 +366,4 @@ static void gaming_control_exit(void)
|
|||
}
|
||||
|
||||
module_init(gaming_control_init);
|
||||
module_exit(gaming_control_exit);
|
||||
module_exit(gaming_control_exit);
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/notifier.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/gaming_control.h>
|
||||
|
||||
/*********************************************************************
|
||||
* CPUFREQ INTERFACE *
|
||||
|
@ -381,9 +382,11 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
|
|||
const char *cpufreq_get_current_driver(void);
|
||||
void *cpufreq_get_driver_data(void);
|
||||
|
||||
static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
|
||||
unsigned int min, unsigned int max)
|
||||
static inline void cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned int min = policy->cpuinfo.min_freq;
|
||||
unsigned int max = policy->cpuinfo.max_freq;
|
||||
|
||||
if (policy->min < min)
|
||||
policy->min = min;
|
||||
if (policy->max < min)
|
||||
|
@ -397,11 +400,23 @@ static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
|
|||
return;
|
||||
}
|
||||
|
||||
static inline void
|
||||
cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
|
||||
static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
|
||||
unsigned int min, unsigned int max)
|
||||
{
|
||||
cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
policy->cpuinfo.max_freq);
|
||||
if (gaming_mode)
|
||||
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
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2019
|
||||
* 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
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
|
@ -18,16 +19,45 @@
|
|||
#ifndef _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 {
|
||||
GAME_START,
|
||||
GAME_RUNNING,
|
||||
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
|
||||
extern bool gaming_mode;
|
||||
extern void game_option(struct task_struct *tsk, enum game_opts opts);
|
||||
extern bool battery_idle_gaming(void);
|
||||
#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 /* _GAMING_CONTROL_H_ */
|
||||
#endif /* _GAMING_CONTROL_H_ */
|
|
@ -71,6 +71,15 @@
|
|||
/* Gaming control */
|
||||
#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
|
||||
* 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)
|
||||
ret = cgroup_attach_task(cgrp, tsk, threadgroup);
|
||||
|
||||
/* Check if the task is a game */
|
||||
if (!memcmp(cgrp->kn->name, "top-app", sizeof("top-app")) && !ret) {
|
||||
game_option(tsk, GAME_RUNNING);
|
||||
} else if (!memcmp(cgrp->kn->name, "background", sizeof("background")) && !ret) {
|
||||
game_option(tsk, GAME_PAUSE);
|
||||
}
|
||||
if (!ret)
|
||||
cgroup_game_check(tsk, of->kn->parent->name);
|
||||
|
||||
put_task_struct(tsk);
|
||||
goto out_unlock_threadgroup;
|
||||
|
|
|
@ -2175,7 +2175,7 @@ long _do_fork(unsigned long clone_flags,
|
|||
struct task_struct *p;
|
||||
int trace = 0;
|
||||
long nr;
|
||||
|
||||
|
||||
game_option(current, GAME_START);
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue