video: rockchip: mpp: rkvenc2: add governor and device for devfreq

Change-Id: Ie92f2a0795359201a77fac4a3446a7c8e1b8e897
Signed-off-by: Liang Chen <cl@rock-chips.com>
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
This commit is contained in:
Liang Chen
2025-05-23 15:19:22 +08:00
committed by Tao Huang
parent c9478f44f8
commit 27e9662f0c

View File

@@ -33,6 +33,10 @@
#include <soc/rockchip/rockchip_system_monitor.h>
#include <soc/rockchip/rockchip_iommu.h>
#ifdef CONFIG_PM_DEVFREQ
#include "../../../devfreq/governor.h"
#endif
#include "mpp_debug.h"
#include "mpp_iommu.h"
#include "mpp_common.h"
@@ -53,6 +57,10 @@
#define to_rkvenc_dev(dev) \
container_of(dev, struct rkvenc_dev, mpp)
#ifdef CONFIG_PM_DEVFREQ
static DEFINE_MUTEX(venc_governor_mutex);
static int venc_governor_count;
#endif
enum RKVENC_FORMAT_TYPE {
RKVENC_FMT_BASE = 0x0000,
@@ -328,6 +336,9 @@ struct rkvenc_dev {
u32 bs_overflow;
#ifdef CONFIG_PM_DEVFREQ
struct devfreq *devfreq;
unsigned long core_rate_hz;
unsigned long core_current_rate_hz;
struct rockchip_opp_info opp_info;
struct monitor_dev_info *mdev_info;
#endif
@@ -2127,6 +2138,90 @@ static inline int rkvenc_procfs_ccu_init(struct mpp_dev *mpp)
#endif
#ifdef CONFIG_PM_DEVFREQ
static int rkvenc_devfreq_target(struct device *dev,
unsigned long *freq, u32 flags)
{
struct mpp_dev *mpp = dev_get_drvdata(dev);
struct rkvenc_dev *enc = to_rkvenc_dev(mpp);
struct devfreq *devfreq = enc->devfreq;
struct rockchip_opp_info *opp_info = &enc->opp_info;
struct dev_pm_opp *opp;
int ret = 0;
if (!opp_info->is_rate_volt_checked)
return -EINVAL;
opp = devfreq_recommended_opp(dev, freq, flags);
if (IS_ERR(opp))
return PTR_ERR(opp);
dev_pm_opp_put(opp);
if (*freq == enc->core_current_rate_hz)
return 0;
rockchip_opp_dvfs_lock(opp_info);
if (pm_runtime_active(dev))
opp_info->is_runtime_active = true;
else
opp_info->is_runtime_active = false;
ret = dev_pm_opp_set_rate(dev, *freq);
if (!ret) {
enc->core_current_rate_hz = *freq;
devfreq->last_status.current_frequency = *freq;
}
rockchip_opp_dvfs_unlock(opp_info);
return ret;
}
static int rkvenc_devfreq_get_dev_status(struct device *dev,
struct devfreq_dev_status *stat)
{
return 0;
}
static int rkvenc_devfreq_get_cur_freq(struct device *dev,
unsigned long *freq)
{
struct mpp_dev *mpp = dev_get_drvdata(dev);
struct rkvenc_dev *enc = to_rkvenc_dev(mpp);
*freq = enc->core_current_rate_hz;
return 0;
}
static struct devfreq_dev_profile rkvenc_devfreq_profile = {
.target = rkvenc_devfreq_target,
.get_dev_status = rkvenc_devfreq_get_dev_status,
.get_cur_freq = rkvenc_devfreq_get_cur_freq,
.is_cooling_device = true,
};
static int devfreq_venc_ondemand_func(struct devfreq *df, unsigned long *freq)
{
struct rkvenc_dev *enc = df->data;
if (enc)
*freq = enc->core_rate_hz;
else
*freq = df->previous_freq;
return 0;
}
static int devfreq_venc_ondemand_handler(struct devfreq *devfreq,
unsigned int event, void *data)
{
return 0;
}
static struct devfreq_governor devfreq_venc_ondemand = {
.name = "venc_ondemand",
.get_target_freq = devfreq_venc_ondemand_func,
.event_handler = devfreq_venc_ondemand_handler,
};
static int rk3588_venc_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
u32 rm)
@@ -2164,6 +2259,8 @@ static const struct of_device_id rockchip_rkvenc_of_match[] = {
static struct monitor_dev_profile venc_mdevp = {
.type = MONITOR_TYPE_DEV,
.check_rate_volt = rockchip_monitor_check_rate_volt,
.low_temp_adjust = rockchip_monitor_dev_low_temp_adjust,
.high_temp_adjust = rockchip_monitor_dev_high_temp_adjust,
};
static int rkvenc_devfreq_init(struct mpp_dev *mpp)
@@ -2183,6 +2280,33 @@ static int rkvenc_devfreq_init(struct mpp_dev *mpp)
dev_err(dev, "failed to init_opp_table\n");
return ret;
}
mutex_lock(&venc_governor_mutex);
if (!venc_governor_count) {
ret = devfreq_add_governor(&devfreq_venc_ondemand);
if (ret) {
dev_err(dev, "failed to add venc_ondemand governor\n");
mutex_unlock(&venc_governor_mutex);
goto governor_err;
}
}
venc_governor_count++;
mutex_unlock(&venc_governor_mutex);
rkvenc_devfreq_profile.initial_freq = clk_get_rate(clk_core);
enc->core_rate_hz = rkvenc_devfreq_profile.initial_freq;
enc->devfreq = devm_devfreq_add_device(dev,
&rkvenc_devfreq_profile,
"venc_ondemand", (void *)enc);
if (IS_ERR(enc->devfreq)) {
ret = PTR_ERR(enc->devfreq);
enc->devfreq = NULL;
goto devfreq_err;
}
devfreq_register_opp_notifier(dev, enc->devfreq);
venc_mdevp.data = enc->devfreq;
venc_mdevp.opp_info = opp_info;
enc->mdev_info = rockchip_system_monitor_register(dev, &venc_mdevp);
if (IS_ERR(enc->mdev_info)) {
@@ -2190,6 +2314,24 @@ static int rkvenc_devfreq_init(struct mpp_dev *mpp)
enc->mdev_info = NULL;
}
enc->core_current_rate_hz = clk_get_rate(clk_core);
enc->core_rate_hz = enc->core_current_rate_hz;
if (enc->devfreq->suspend_freq)
enc->devfreq->resume_freq = enc->core_current_rate_hz;
enc->devfreq->last_status.current_frequency = enc->core_current_rate_hz;
enc->devfreq->last_status.total_time = 1;
enc->devfreq->last_status.busy_time = 1;
return 0;
devfreq_err:
mutex_lock(&venc_governor_mutex);
if (--venc_governor_count == 0)
devfreq_remove_governor(&devfreq_venc_ondemand);
mutex_unlock(&venc_governor_mutex);
governor_err:
dev_pm_opp_of_remove_table(dev);
return ret;
}
@@ -2201,6 +2343,12 @@ static int rkvenc_devfreq_remove(struct mpp_dev *mpp)
rockchip_system_monitor_unregister(enc->mdev_info);
enc->mdev_info = NULL;
}
if (enc->devfreq)
devfreq_unregister_opp_notifier(mpp->dev, enc->devfreq);
mutex_lock(&venc_governor_mutex);
if (--venc_governor_count == 0)
devfreq_remove_governor(&devfreq_venc_ondemand);
mutex_unlock(&venc_governor_mutex);
rockchip_uninit_opp_table(mpp->dev, &enc->opp_info);
return 0;
@@ -2297,6 +2445,10 @@ static int rkvenc_reset(struct mpp_dev *mpp)
mpp_debug_enter();
#ifdef CONFIG_PM_DEVFREQ
if (enc->devfreq)
mutex_lock(&enc->devfreq->lock);
#endif
/* safe reset first*/
ret = rkvenc_soft_reset(mpp);
@@ -2325,6 +2477,11 @@ static int rkvenc_reset(struct mpp_dev *mpp)
mpp_dbg_core("core %d reset idle %lx\n", mpp->core_id, queue->core_idle);
#ifdef CONFIG_PM_DEVFREQ
if (enc->devfreq)
mutex_unlock(&enc->devfreq->lock);
#endif
mpp_debug_leave();
return 0;
@@ -2358,6 +2515,27 @@ static int rkvenc_set_freq(struct mpp_dev *mpp, struct mpp_task *mpp_task)
struct rkvenc_task *task = to_rkvenc_task(mpp_task);
mpp_clk_set_rate(&enc->aclk_info, task->clk_mode);
#ifdef CONFIG_PM_DEVFREQ
if (enc->devfreq) {
unsigned long core_rate_hz;
mutex_lock(&enc->devfreq->lock);
core_rate_hz = mpp_get_clk_info_rate_hz(&enc->core_clk_info, task->clk_mode);
if (enc->core_rate_hz != core_rate_hz) {
enc->core_rate_hz = core_rate_hz;
update_devfreq(enc->devfreq);
} else {
/*
* Restore frequency when frequency is changed by
* rkvenc_reduce_freq()
*/
clk_set_rate(enc->core_clk_info.clk, enc->core_current_rate_hz);
}
mutex_unlock(&enc->devfreq->lock);
return 0;
}
#endif
mpp_clk_set_rate(&enc->core_clk_info, task->clk_mode);
return 0;