From 0a7cd35e38a4e9449e6037757a85b59e46d521ed Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Mon, 26 Dec 2022 17:47:16 +0800 Subject: [PATCH] video: rockchip: rga3: disable memory when RGA power off to save power Signed-off-by: Yu Qiaowei Change-Id: I6499783fff415dcf62b03f44d1736157ae04eedf --- drivers/video/rockchip/rga3/include/rga_drv.h | 8 ++ drivers/video/rockchip/rga3/rga_drv.c | 74 ++++++++++++++++++- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/drivers/video/rockchip/rga3/include/rga_drv.h b/drivers/video/rockchip/rga3/include/rga_drv.h index a47ffbc25f97..f317cbcb02e0 100644 --- a/drivers/video/rockchip/rga3/include/rga_drv.h +++ b/drivers/video/rockchip/rga3/include/rga_drv.h @@ -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; diff --git a/drivers/video/rockchip/rga3/rga_drv.c b/drivers/video/rockchip/rga3/rga_drv.c index 226fb773760d..ae3b379a4e73 100644 --- a/drivers/video/rockchip/rga3/rga_drv.c +++ b/drivers/video/rockchip/rga3/rga_drv.c @@ -7,6 +7,9 @@ #define pr_fmt(fmt) "rga: " fmt +#include +#include + #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]);