soc: rockchip: system_monitor: Add support limit rate when 4k video

Change-Id: I15b443df1e7b24df03e986e401e6032f307aa376
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
This commit is contained in:
Finley Xiao 2019-03-26 09:24:11 +08:00 committed by Tao Huang
parent f23062aa03
commit ce28fbc8a6
2 changed files with 73 additions and 15 deletions

View File

@ -516,10 +516,10 @@ static int rockchip_init_temp_opp_table(struct monitor_dev_info *info)
return ret;
}
static int monitor_device_parse_dt(struct device *dev,
struct monitor_dev_info *info)
static int monitor_device_parse_wide_temp_config(struct device_node *np,
struct monitor_dev_info *info)
{
struct device_node *np;
struct device *dev = info->dev;
unsigned long high_temp_max_freq;
int ret = 0;
u32 value;
@ -565,22 +565,49 @@ static int monitor_device_parse_dt(struct device *dev,
info->low_temp, info->high_temp,
info->temp_hysteresis);
ret = -EINVAL;
goto out;
goto err;
}
if (!info->low_temp_adjust_table && !info->low_temp_min_volt &&
!info->low_limit && !info->high_limit) {
ret = -EINVAL;
goto out;
goto err;
}
if (info->low_temp_adjust_table || info->low_temp_min_volt)
info->is_low_temp_enabled = true;
out:
return 0;
err:
kfree(info->low_temp_adjust_table);
info->low_temp_adjust_table = NULL;
kfree(info->opp_table);
info->opp_table = NULL;
return ret;
}
static int monitor_device_parse_dt(struct device *dev,
struct monitor_dev_info *info)
{
struct device_node *np;
int ret = 0;
bool is_wide_temp_en = false;
bool is_4k_limit_en = false;
np = of_parse_phandle(dev->of_node, "operating-points-v2", 0);
if (!np)
return -EINVAL;
if (!monitor_device_parse_wide_temp_config(np, info))
is_wide_temp_en = true;
if (!of_property_read_u32(np, "rockchip,video-4k-freq",
&info->video_4k_freq))
is_4k_limit_en = true;
if (is_wide_temp_en || is_4k_limit_en)
ret = 0;
else
ret = -EINVAL;
of_node_put(np);
if (ret) {
kfree(info->low_temp_adjust_table);
kfree(info->opp_table);
}
return ret;
}
@ -1018,6 +1045,28 @@ static void rockchip_system_monitor_thermal_check(struct work_struct *work)
rockchip_system_monitor_thermal_update();
}
static void rockchip_system_status_limit_freq(unsigned long status)
{
struct monitor_dev_info *info;
unsigned int target_freq, cpu;
down_read(&mdev_list_sem);
list_for_each_entry(info, &monitor_dev_list, node) {
if (info->devp->type != MONITOR_TPYE_CPU)
continue;
if (status & SYS_STATUS_VIDEO_4K)
target_freq = info->video_4k_freq;
else
target_freq = 0;
if (target_freq != info->status_limit) {
info->status_limit = target_freq;
cpu = cpumask_any(&info->devp->allowed_cpus);
cpufreq_update_policy(cpu);
}
}
up_read(&mdev_list_sem);
}
static void rockchip_system_status_cpu_on_off(unsigned long status)
{
struct cpumask offline_cpus;
@ -1039,6 +1088,8 @@ static int rockchip_system_status_notifier(struct notifier_block *nb,
unsigned long status,
void *ptr)
{
rockchip_system_status_limit_freq(status);
rockchip_system_status_cpu_on_off(status);
return NOTIFY_OK;
@ -1077,7 +1128,7 @@ static int rockchip_monitor_cpufreq_policy_notifier(struct notifier_block *nb,
struct monitor_dev_info *info;
struct cpufreq_policy *policy = data;
int cpu = policy->cpu;
unsigned int target_freq;
unsigned int limit_freq = UINT_MAX;
if (event != CPUFREQ_ADJUST)
return NOTIFY_OK;
@ -1088,12 +1139,15 @@ static int rockchip_monitor_cpufreq_policy_notifier(struct notifier_block *nb,
continue;
if (!cpumask_test_cpu(cpu, &info->devp->allowed_cpus))
continue;
if (info->wide_temp_limit) {
target_freq = info->wide_temp_limit / 1000;
if (target_freq < policy->max)
cpufreq_verify_within_limits(policy, 0,
target_freq);
if (limit_freq > info->wide_temp_limit / 1000)
limit_freq = info->wide_temp_limit / 1000;
}
if (info->status_limit && limit_freq > info->status_limit)
limit_freq = info->status_limit;
if (limit_freq < policy->max)
cpufreq_verify_within_limits(policy, 0, limit_freq);
}
up_read(&mdev_list_sem);

View File

@ -49,6 +49,8 @@ struct temp_opp_table {
* @high_temp_max_volt: Maximum voltage when high temperature, in microvolt
* @wide_temp_limit: Target maximum frequency when low or high temperature,
* in Hz
* @video_4k_freq: Maximum frequency when paly 4k video, in KHz
* @status_limit: Minimum frequency of all status frequency, in KHz
* @low_temp: Low temperature trip point, in millicelsius
* @high_temp: High temperature trip point, in millicelsius
* @temp_hysteresis: A low hysteresis value on low_temp, in millicelsius
@ -70,6 +72,8 @@ struct monitor_dev_info {
unsigned long low_temp_min_volt;
unsigned long high_temp_max_volt;
unsigned long wide_temp_limit;
unsigned int video_4k_freq;
unsigned int status_limit;
int low_temp;
int high_temp;
int temp_hysteresis;