video: rockchip: rga3: Support pm_runtime

Add enable/disable pd on rga_job_schedule/done

Signed-off-by: Li Huang <putin.li@rock-chips.com>
Change-Id: Iaf3c19027c599ecc5f8ffdbd3ef7da44a4049381
This commit is contained in:
Li Huang
2021-11-26 15:07:03 +08:00
committed by Tao Huang
parent 096cbd86cf
commit 2ed162aef5
4 changed files with 122 additions and 30 deletions

View File

@@ -42,6 +42,7 @@
#include <linux/version.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/pm_runtime.h>
#include <asm/cacheflush.h>
@@ -212,6 +213,8 @@ struct rga_scheduler_t {
struct clk *clks[RGA_MAX_BUS_CLK];
int num_clks;
struct kref pd_refcount;
struct rga_job *running_job;
struct list_head todo_list;
spinlock_t irq_lock;
@@ -230,8 +233,6 @@ struct rga_drvdata_t {
struct rga_fence_context *fence_ctx;
struct mutex mutex; // mutex
/* used by rga2's mmu lock */
struct mutex lock;
@@ -271,4 +272,8 @@ static inline void rga_write(int value, int offset, struct rga_scheduler_t *rga_
writel(value, rga_scheduler->rga_base + offset);
}
int rga_power_enable(struct rga_scheduler_t *rga_scheduler);
int rga_power_disable(struct rga_scheduler_t *rga_scheduler);
void rga_kref_disable_power(struct kref *ref);
#endif /* __LINUX_RGA_FENCE_H_ */

View File

@@ -23,4 +23,10 @@ int rga_commit(struct rga_req *rga_command_base, int flags);
int rga_kernel_commit(struct rga_req *rga_command_base,
struct rga_mpi_job_t *mpi_job, int flags);
struct rga_job *
rga_scheduler_get_pending_job_list(struct rga_scheduler_t *scheduler);
struct rga_job *
rga_scheduler_get_running_job(struct rga_scheduler_t *scheduler);
#endif /* __LINUX_RKRGA_JOB_H_ */

View File

@@ -15,11 +15,6 @@
#include "rga_fence.h"
#include "rga_hw_config.h"
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
#include <linux/pm_runtime.h>
#include <linux/dma-buf.h>
#endif
#include "rga2_mmu_info.h"
#include "rga_debugger.h"
@@ -56,17 +51,13 @@ int rga_mpi_commit(struct rga_req *cmd, struct rga_mpi_job_t *mpi_job)
EXPORT_SYMBOL_GPL(rga_mpi_commit);
#ifndef CONFIG_ROCKCHIP_FPGA
static int rga_power_enable(struct rga_scheduler_t *rga_scheduler)
int rga_power_enable(struct rga_scheduler_t *rga_scheduler)
{
int ret = -EINVAL;
int i;
ret = pm_runtime_get_sync(rga_scheduler->dev);
if (ret < 0) {
pr_err("failed to get pm runtime, ret = %d\n",
ret);
return ret;
}
pm_runtime_get_sync(rga_scheduler->dev);
pm_stay_awake(rga_scheduler->dev);
for (i = 0; i < rga_scheduler->num_clks; i++) {
if (!IS_ERR(rga_scheduler->clks[i])) {
@@ -83,10 +74,13 @@ err_enable_clk:
if (!IS_ERR(rga_scheduler->clks[i]))
clk_disable_unprepare(rga_scheduler->clks[i]);
pm_relax(rga_scheduler->dev);
pm_runtime_put_sync_suspend(rga_scheduler->dev);
return ret;
}
static int rga_power_disable(struct rga_scheduler_t *rga_scheduler)
int rga_power_disable(struct rga_scheduler_t *rga_scheduler)
{
int i;
@@ -94,10 +88,21 @@ static int rga_power_disable(struct rga_scheduler_t *rga_scheduler)
if (!IS_ERR(rga_scheduler->clks[i]))
clk_disable_unprepare(rga_scheduler->clks[i]);
pm_runtime_put(rga_scheduler->dev);
pm_relax(rga_scheduler->dev);
pm_runtime_put_sync_suspend(rga_scheduler->dev);
return 0;
}
void rga_kref_disable_power(struct kref *ref)
{
struct rga_scheduler_t *rga_scheduler = NULL;
rga_scheduler = container_of(ref, struct rga_scheduler_t, pd_refcount);
rga_power_disable(rga_scheduler);
}
#endif //CONFIG_ROCKCHIP_FPGA
static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
@@ -562,13 +567,28 @@ static int rga_drv_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rga_scheduler);
device_init_wakeup(dev, true);
/* PM init */
#ifndef CONFIG_ROCKCHIP_FPGA
pm_runtime_enable(&pdev->dev);
ret = rga_power_enable(rga_scheduler);
if (ret)
return ret;
ret = pm_runtime_get_sync(rga_scheduler->dev);
if (ret < 0) {
pr_err("failed to get pm runtime, ret = %d\n",
ret);
goto failed;
}
for (i = 0; i < rga_scheduler->num_clks; i++) {
if (!IS_ERR(rga_scheduler->clks[i])) {
ret = clk_prepare_enable(rga_scheduler->clks[i]);
if (ret < 0) {
pr_err("failed to enable clk\n");
goto failed;
}
}
}
#endif //CONFIG_ROCKCHIP_FPGA
rga_scheduler->ops->get_version(rga_scheduler);
@@ -579,19 +599,27 @@ static int rga_drv_probe(struct platform_device *pdev)
data->num_of_scheduler++;
for (i = rga_scheduler->num_clks - 1; i >= 0; i--)
if (!IS_ERR(rga_scheduler->clks[i]))
clk_disable_unprepare(rga_scheduler->clks[i]);
pm_runtime_put_sync(&pdev->dev);
pr_err("probe successfully\n");
return 0;
failed:
device_init_wakeup(dev, false);
pm_runtime_disable(dev);
return ret;
}
static int rga_drv_remove(struct platform_device *pdev)
{
struct rga_scheduler_t *rga_scheduler =
platform_get_drvdata(pdev);
device_init_wakeup(&pdev->dev, false);
#ifndef CONFIG_ROCKCHIP_FPGA
rga_power_disable(rga_scheduler);
pm_runtime_disable(&pdev->dev);
#endif //CONFIG_ROCKCHIP_FPGA
@@ -673,7 +701,6 @@ static int __init rga_init(void)
return -ENOMEM;
}
mutex_init(&rga_drvdata->mutex);
mutex_init(&rga_drvdata->lock);
wake_lock_init(&rga_drvdata->wake_lock, WAKE_LOCK_SUSPEND, "rga");

View File

@@ -13,6 +13,37 @@
#include "rga_hw_config.h"
#include "rga2_mmu_info.h"
struct rga_job *
rga_scheduler_get_pending_job_list(struct rga_scheduler_t *scheduler)
{
unsigned long flags;
struct rga_job *job;
spin_lock_irqsave(&scheduler->irq_lock, flags);
job = list_first_entry_or_null(&scheduler->todo_list,
struct rga_job, head);
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
return job;
}
struct rga_job *
rga_scheduler_get_running_job(struct rga_scheduler_t *scheduler)
{
unsigned long flags;
struct rga_job *job;
spin_lock_irqsave(&scheduler->irq_lock, flags);
job = scheduler->running_job;
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
return job;
}
static struct rga_scheduler_t *get_scheduler(struct rga_job *job)
{
struct rga_scheduler_t *scheduler = NULL;
@@ -82,25 +113,26 @@ static int rga_job_run(struct rga_job *job, struct rga_scheduler_t *scheduler)
ret = rga_dma_get_info(job);
if (ret < 0) {
pr_err("dma buf get failed");
return ret;
goto failed;
}
ret = scheduler->ops->init_reg(job);
if (ret < 0) {
pr_err("init reg failed");
return ret;
goto failed;
}
ret = scheduler->ops->set_reg(job, scheduler);
if (ret < 0) {
pr_err("set reg failed");
return ret;
goto failed;
}
/* for debug */
if (RGA_DEBUG_MSG)
print_job_info(job);
failed:
return ret;
}
@@ -172,10 +204,14 @@ void rga_job_done(struct rga_scheduler_t *rga_scheduler, int ret)
pr_err("%s use time = %lld\n", __func__,
ktime_to_us(ktime_sub(now, job->timestamp)));
rga2_dma_flush_cache_for_virtual_address(&job->vir_page_table, rga_scheduler);
if (job->core == RGA2_SCHEDULER_CORE0)
rga2_dma_flush_cache_for_virtual_address(&job->vir_page_table,
rga_scheduler);
rga_dma_put_info(job);
kref_put(&rga_scheduler->pd_refcount, rga_kref_disable_power);
if (job->out_fence)
dma_fence_signal(job->out_fence);
@@ -496,6 +532,8 @@ static struct rga_scheduler_t *rga_job_schedule(struct rga_job *job)
struct rga_scheduler_t *scheduler = NULL;
struct rga_job *job_pos;
bool first_match = 0;
bool first_open_pd = false;
int ret = 0;
if (rga_drvdata->num_of_scheduler > 1) {
job->core = rga_job_assign(job);
@@ -515,6 +553,13 @@ static struct rga_scheduler_t *rga_job_schedule(struct rga_job *job)
spin_lock_irqsave(&scheduler->irq_lock, flags);
if (list_empty(&scheduler->todo_list) && !scheduler->running_job) {
kref_init(&scheduler->pd_refcount);
first_open_pd = true;
} else {
kref_get(&scheduler->pd_refcount);
}
/* priority policy set by userspace */
if (list_empty(&scheduler->todo_list)
|| (job->priority == RGA_SCHED_PRIORITY_DEFAULT)) {
@@ -543,6 +588,15 @@ static struct rga_scheduler_t *rga_job_schedule(struct rga_job *job)
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
/* enable power */
if (first_open_pd) {
ret = rga_power_enable(scheduler);
if (ret < 0) {
pr_err("power enable failed");
return NULL;
}
}
rga_job_next(scheduler);
return scheduler;
@@ -644,7 +698,7 @@ int rga_commit(struct rga_req *rga_command_base, int flags)
job->flags |= RGA_JOB_ASYNC;
rga_command_base->out_fence_fd = rga_out_fence_get_fd(job);
//TODO: job timeout clean
//TODO: job timeout clean, need add pd disable
if (RGA_DEBUG_MSG)
pr_err("in_fence_fd = %d",