diff --git a/drivers/video/rockchip/rga3/include/rga_drv.h b/drivers/video/rockchip/rga3/include/rga_drv.h index 6fa89f9fc23f..320710466013 100644 --- a/drivers/video/rockchip/rga3/include/rga_drv.h +++ b/drivers/video/rockchip/rga3/include/rga_drv.h @@ -42,6 +42,7 @@ #include #include #include +#include #include @@ -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_ */ diff --git a/drivers/video/rockchip/rga3/include/rga_job.h b/drivers/video/rockchip/rga3/include/rga_job.h index 72728860cd64..b97db5efaa81 100644 --- a/drivers/video/rockchip/rga3/include/rga_job.h +++ b/drivers/video/rockchip/rga3/include/rga_job.h @@ -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_ */ diff --git a/drivers/video/rockchip/rga3/rga_drv.c b/drivers/video/rockchip/rga3/rga_drv.c index 979dd453be1e..21e375a030b9 100644 --- a/drivers/video/rockchip/rga3/rga_drv.c +++ b/drivers/video/rockchip/rga3/rga_drv.c @@ -15,11 +15,6 @@ #include "rga_fence.h" #include "rga_hw_config.h" -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) -#include -#include -#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"); diff --git a/drivers/video/rockchip/rga3/rga_job.c b/drivers/video/rockchip/rga3/rga_job.c index 9d2d34816e73..b6956e6a98e6 100644 --- a/drivers/video/rockchip/rga3/rga_job.c +++ b/drivers/video/rockchip/rga3/rga_job.c @@ -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",