video: rockchip: rga3: disable memory when RGA power off to save power

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: I6499783fff415dcf62b03f44d1736157ae04eedf
This commit is contained in:
Yu Qiaowei
2022-12-26 17:47:16 +08:00
committed by Tao Huang
parent e647074c1c
commit 0a7cd35e38
2 changed files with 79 additions and 3 deletions

View File

@@ -319,10 +319,18 @@ struct rga_timer {
u32 busy_time_record;
};
struct rga_grf_info {
uint32_t offset;
uint32_t open_val;
uint32_t close_val;
struct regmap *grf;
};
struct rga_scheduler_t {
struct device *dev;
void __iomem *rga_base;
struct rga_iommu_info *iommu_info;
struct rga_grf_info grf_info;
struct clk *clks[RGA_MAX_BUS_CLK];
int num_clks;

View File

@@ -7,6 +7,9 @@
#define pr_fmt(fmt) "rga: " fmt
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include "rga2_reg_info.h"
#include "rga3_reg_info.h"
#include "rga_dma_buf.h"
@@ -372,6 +375,62 @@ static void rga_cancel_timer(void)
}
#ifndef RGA_DISABLE_PM
static int rga_grf_open(struct rga_scheduler_t *scheduler)
{
if (scheduler->grf_info.grf && scheduler->grf_info.open_val)
regmap_write(scheduler->grf_info.grf,
scheduler->grf_info.offset,
scheduler->grf_info.open_val);
return 0;
}
static int rga_grf_close(struct rga_scheduler_t *scheduler)
{
if (scheduler->grf_info.grf && scheduler->grf_info.close_val)
regmap_write(scheduler->grf_info.grf,
scheduler->grf_info.offset,
scheduler->grf_info.close_val);
return 0;
}
static int rga_grf_init(struct rga_scheduler_t *scheduler)
{
int ret;
uint32_t grf_offset = 0;
uint32_t grf_open_value = 0, grf_close_value = 0;
struct device_node *np = scheduler->dev->of_node;
struct regmap *grf;
grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
if (IS_ERR_OR_NULL(grf))
return -EINVAL;
ret = of_property_read_u32(np, "rockchip,grf-offset", &grf_offset);
if (ret)
return -ENODATA;
ret = of_property_read_u32_index(np, "rockchip,grf-values",
0, &grf_open_value);
if (ret)
return -ENODATA;
ret = of_property_read_u32_index(np, "rockchip,grf-values",
1, &grf_close_value);
if (ret)
return -ENODATA;
scheduler->grf_info.grf = grf;
scheduler->grf_info.offset = grf_offset;
scheduler->grf_info.open_val = grf_open_value;
scheduler->grf_info.close_val = grf_close_value;
pr_info("%s grf init successfully.\n", dev_driver_string(scheduler->dev));
return 0;
}
int rga_power_enable(struct rga_scheduler_t *scheduler)
{
int ret = -EINVAL;
@@ -392,8 +451,10 @@ int rga_power_enable(struct rga_scheduler_t *scheduler)
spin_lock_irqsave(&scheduler->irq_lock, flags);
scheduler->pd_refcount++;
if (scheduler->status == RGA_SCHEDULER_IDLE)
if (scheduler->status == RGA_SCHEDULER_IDLE) {
scheduler->status = RGA_SCHEDULER_WORKING;
rga_grf_open(scheduler);
}
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
@@ -425,8 +486,10 @@ int rga_power_disable(struct rga_scheduler_t *scheduler)
}
scheduler->pd_refcount--;
if (scheduler->pd_refcount == 0)
if (scheduler->pd_refcount == 0) {
scheduler->status = RGA_SCHEDULER_IDLE;
rga_grf_close(scheduler);
}
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
@@ -1362,8 +1425,9 @@ static int rga_drv_probe(struct platform_device *pdev)
return ret;
}
#ifndef RGA_DISABLE_PM
rga_grf_init(scheduler);
/* clk init */
for (i = 0; i < match_data->num_clks; i++) {
struct clk *clk = devm_clk_get(dev, match_data->clks[i]);
@@ -1394,6 +1458,8 @@ static int rga_drv_probe(struct platform_device *pdev)
}
}
}
rga_grf_open(scheduler);
#endif /* #ifndef RGA_DISABLE_PM */
scheduler->ops->get_version(scheduler);
@@ -1419,6 +1485,8 @@ static int rga_drv_probe(struct platform_device *pdev)
data->num_of_scheduler++;
#ifndef RGA_DISABLE_PM
rga_grf_close(scheduler);
for (i = scheduler->num_clks - 1; i >= 0; i--)
if (!IS_ERR(scheduler->clks[i]))
clk_disable_unprepare(scheduler->clks[i]);