mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user