PM / devfreq: rockchip_dmc: Add bandwidth level table support

Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
Change-Id: I3fcc4b9454c599f7a5946a61893153171509de42
This commit is contained in:
Finley Xiao
2024-05-15 14:46:19 +08:00
committed by Tao Huang
parent 682affbb83
commit 7ee4b8fe83

View File

@@ -58,10 +58,11 @@
#define input_hd_to_dmcfreq(hd) container_of(hd, struct rockchip_dmcfreq, \
input_handler)
#define VIDEO_1080P_SIZE (1920 * 1080)
#define DTS_PAR_OFFSET (4096)
#define VIDEO_1080P_SIZE (1920 * 1080)
#define DTS_PAR_OFFSET (4096)
#define FALLBACK_STATIC_TEMPERATURE 55000
#define FALLBACK_STATIC_TEMPERATURE 55000
#define MAX_FREQ_COUNT 6
struct dmc_freq_table {
unsigned long freq;
@@ -90,7 +91,7 @@ struct share_params {
u32 update_deskew_cfg;
u32 freq_count;
u32 freq_info_mhz[6];
u32 freq_info_mhz[MAX_FREQ_COUNT];
u32 wait_mode;
u32 vop_scan_line_time_ns;
/* if need, add parameter after */
@@ -145,7 +146,7 @@ struct rockchip_dmcfreq {
unsigned long low_power_rate;
unsigned long freq_count;
unsigned long freq_info_rate[6];
unsigned long freq_info_rate[MAX_FREQ_COUNT];
unsigned long rate_low;
unsigned long rate_mid_low;
unsigned long rate_mid_high;
@@ -1200,7 +1201,7 @@ static __maybe_unused int rockchip_get_freq_info(struct rockchip_dmcfreq *dmcfre
return -ENOMEM;
}
if (ddr_psci_param->freq_count == 0 || ddr_psci_param->freq_count > 6) {
if (ddr_psci_param->freq_count == 0 || ddr_psci_param->freq_count > MAX_FREQ_COUNT) {
dev_err(dmcfreq->dev, "it is no available frequencies!\n");
return -EPERM;
}
@@ -1281,7 +1282,7 @@ rockchip_dmcfreq_adjust_opp_table(struct rockchip_dmcfreq *dmcfreq)
return -ENOMEM;
}
if (ddr_psci_param->freq_count == 0 || ddr_psci_param->freq_count > 6) {
if (ddr_psci_param->freq_count == 0 || ddr_psci_param->freq_count > MAX_FREQ_COUNT) {
dev_err(dev, "there is no available frequencies!\n");
return -EPERM;
}
@@ -2348,6 +2349,55 @@ static unsigned long rockchip_freq_level_2_rate(struct rockchip_dmcfreq *dmcfreq
return rate;
}
static int rockchip_get_level_map_talbe(struct device_node *np, char *porp_name,
struct rockchip_dmcfreq *dmcfreq,
struct freq_map_table **table)
{
struct freq_map_table *tbl;
const struct property *prop;
unsigned int level = 0;
int count, i;
if (dmcfreq->rate_low == 0)
return -EINVAL;
prop = of_find_property(np, porp_name, NULL);
if (!prop)
return -EINVAL;
if (!prop->value)
return -ENODATA;
count = of_property_count_u32_elems(np, porp_name);
if (count < 0)
return -EINVAL;
if (count % 3)
return -EINVAL;
tbl = kzalloc(sizeof(*tbl) * (count / 3 + 1), GFP_KERNEL);
if (!tbl)
return -ENOMEM;
for (i = 0; i < count / 3; i++) {
of_property_read_u32_index(np, porp_name, 3 * i, &tbl[i].min);
of_property_read_u32_index(np, porp_name, 3 * i + 1,
&tbl[i].max);
of_property_read_u32_index(np, porp_name, 3 * i + 2,
&level);
tbl[i].freq = rockchip_freq_level_2_rate(dmcfreq, level);
}
tbl[i].min = 0;
tbl[i].max = 0;
tbl[i].freq = DMCFREQ_TABLE_END;
*table = tbl;
return 0;
}
static int rockchip_get_system_status_level(struct device_node *np,
char *porp_name,
struct rockchip_dmcfreq *dmcfreq)
@@ -2357,6 +2407,9 @@ static int rockchip_get_system_status_level(struct device_node *np,
unsigned long temp_rate = 0;
int count, i;
if (dmcfreq->rate_low == 0)
return -EINVAL;
prop = of_find_property(np, porp_name, NULL);
if (!prop)
return -ENODEV;
@@ -2371,37 +2424,6 @@ static int rockchip_get_system_status_level(struct device_node *np,
if (count % 2)
return -EINVAL;
if (dmcfreq->freq_count == 1) {
dmcfreq->rate_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_high = dmcfreq->freq_info_rate[0];
dmcfreq->rate_high = dmcfreq->freq_info_rate[0];
} else if (dmcfreq->freq_count == 2) {
dmcfreq->rate_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_high = dmcfreq->freq_info_rate[1];
dmcfreq->rate_high = dmcfreq->freq_info_rate[1];
} else if (dmcfreq->freq_count == 3) {
dmcfreq->rate_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_low = dmcfreq->freq_info_rate[1];
dmcfreq->rate_mid_high = dmcfreq->freq_info_rate[1];
dmcfreq->rate_high = dmcfreq->freq_info_rate[2];
} else if (dmcfreq->freq_count == 4) {
dmcfreq->rate_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_low = dmcfreq->freq_info_rate[1];
dmcfreq->rate_mid_high = dmcfreq->freq_info_rate[2];
dmcfreq->rate_high = dmcfreq->freq_info_rate[3];
} else if (dmcfreq->freq_count == 5 || dmcfreq->freq_count == 6) {
dmcfreq->rate_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_low = dmcfreq->freq_info_rate[1];
dmcfreq->rate_mid_high = dmcfreq->freq_info_rate[dmcfreq->freq_count - 2];
dmcfreq->rate_high = dmcfreq->freq_info_rate[dmcfreq->freq_count - 1];
} else {
return -EINVAL;
}
dmcfreq->auto_min_rate = dmcfreq->rate_low;
for (i = 0; i < count / 2; i++) {
of_property_read_u32_index(np, porp_name, 2 * i,
&status);
@@ -2986,6 +3008,41 @@ static int rockchip_dmcfreq_dmc_init(struct platform_device *pdev,
return 0;
}
static void rockchip_dmcfreq_level_rate_init(struct rockchip_dmcfreq *dmcfreq)
{
if (dmcfreq->freq_count == 0 || dmcfreq->freq_count > MAX_FREQ_COUNT)
return;
if (dmcfreq->freq_count == 1) {
dmcfreq->rate_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_high = dmcfreq->freq_info_rate[0];
dmcfreq->rate_high = dmcfreq->freq_info_rate[0];
} else if (dmcfreq->freq_count == 2) {
dmcfreq->rate_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_high = dmcfreq->freq_info_rate[1];
dmcfreq->rate_high = dmcfreq->freq_info_rate[1];
} else if (dmcfreq->freq_count == 3) {
dmcfreq->rate_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_low = dmcfreq->freq_info_rate[1];
dmcfreq->rate_mid_high = dmcfreq->freq_info_rate[1];
dmcfreq->rate_high = dmcfreq->freq_info_rate[2];
} else if (dmcfreq->freq_count == 4) {
dmcfreq->rate_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_low = dmcfreq->freq_info_rate[1];
dmcfreq->rate_mid_high = dmcfreq->freq_info_rate[2];
dmcfreq->rate_high = dmcfreq->freq_info_rate[3];
} else if (dmcfreq->freq_count == 5 || dmcfreq->freq_count == 6) {
dmcfreq->rate_low = dmcfreq->freq_info_rate[0];
dmcfreq->rate_mid_low = dmcfreq->freq_info_rate[1];
dmcfreq->rate_mid_high = dmcfreq->freq_info_rate[dmcfreq->freq_count - 2];
dmcfreq->rate_high = dmcfreq->freq_info_rate[dmcfreq->freq_count - 1];
}
dmcfreq->auto_min_rate = dmcfreq->rate_low;
}
static void rockchip_dmcfreq_parse_dt(struct rockchip_dmcfreq *dmcfreq)
{
struct device *dev = dmcfreq->dev;
@@ -3011,15 +3068,25 @@ static void rockchip_dmcfreq_parse_dt(struct rockchip_dmcfreq *dmcfreq)
dmcfreq->auto_min_rate *= 1000;
}
if (rockchip_get_freq_map_talbe(np, "cpu-bw-dmc-freq",
&dmcfreq->cpu_bw_tbl))
dev_dbg(dev, "failed to get cpu bandwidth to dmc rate\n");
if (rockchip_get_freq_map_talbe(np, "vop-frame-bw-dmc-freq",
&dmcfreq->info.vop_frame_bw_tbl))
dev_dbg(dev, "failed to get vop frame bandwidth to dmc rate\n");
if (rockchip_get_freq_map_talbe(np, "vop-bw-dmc-freq",
&dmcfreq->info.vop_bw_tbl))
dev_err(dev, "failed to get vop bandwidth to dmc rate\n");
if (rockchip_get_level_map_talbe(np, "cpu-bw-dmc-level", dmcfreq,
&dmcfreq->cpu_bw_tbl)) {
if (rockchip_get_freq_map_talbe(np, "cpu-bw-dmc-freq",
&dmcfreq->cpu_bw_tbl))
dev_dbg(dev, "failed to get cpu bandwidth to dmc rate\n");
}
if (rockchip_get_level_map_talbe(np, "vop-frame-bw-dmc-level", dmcfreq,
&dmcfreq->info.vop_frame_bw_tbl)) {
if (rockchip_get_freq_map_talbe(np, "vop-frame-bw-dmc-freq",
&dmcfreq->info.vop_frame_bw_tbl))
dev_dbg(dev, "failed to get vop frame bandwidth to dmc rate\n");
}
if (rockchip_get_level_map_talbe(np, "vop-bw-dmc-level", dmcfreq,
&dmcfreq->info.vop_bw_tbl)) {
if (rockchip_get_freq_map_talbe(np, "vop-bw-dmc-freq",
&dmcfreq->info.vop_bw_tbl))
dev_err(dev, "failed to get vop bandwidth to dmc rate\n");
}
if (rockchip_get_rl_map_talbe(np, "vop-pn-msch-readlatency",
&dmcfreq->info.vop_pn_rl_tbl))
dev_err(dev, "failed to get vop pn to msch rl\n");
@@ -3257,6 +3324,7 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev)
if (ret)
return ret;
rockchip_dmcfreq_level_rate_init(data);
rockchip_dmcfreq_parse_dt(data);
platform_set_drvdata(pdev, data);