mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
video: rockchip: rga3: Add drv_shutdown callback
Need to reset hardware when driver exits. Update driver version to 1.3.6 Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com> Change-Id: I4c6cb394a1339cf689d2d0d011d5df3fb24f0425
This commit is contained in:
@@ -88,7 +88,7 @@
|
||||
|
||||
#define DRIVER_MAJOR_VERISON 1
|
||||
#define DRIVER_MINOR_VERSION 3
|
||||
#define DRIVER_REVISION_VERSION 5
|
||||
#define DRIVER_REVISION_VERSION 6
|
||||
#define DRIVER_PATCH_VERSION
|
||||
|
||||
#define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_VERSION) \
|
||||
@@ -450,6 +450,9 @@ struct rga_drvdata_t {
|
||||
#ifdef CONFIG_ROCKCHIP_RGA_DEBUGGER
|
||||
struct rga_debugger *debugger;
|
||||
#endif
|
||||
|
||||
bool shutdown;
|
||||
struct rw_semaphore rwsem;
|
||||
};
|
||||
|
||||
struct rga_irqs_data_t {
|
||||
|
||||
@@ -38,6 +38,7 @@ struct rga_request *rga_request_lookup(struct rga_pending_request_manager *reque
|
||||
uint32_t id);
|
||||
|
||||
int rga_request_commit(struct rga_request *user_request);
|
||||
void rga_request_scheduler_shutdown(struct rga_scheduler_t *scheduler);
|
||||
void rga_request_scheduler_abort(struct rga_scheduler_t *scheduler);
|
||||
void rga_request_session_destroy_abort(struct rga_session *session);
|
||||
int rga_request_put(struct rga_request *request);
|
||||
|
||||
@@ -927,6 +927,15 @@ static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
|
||||
if (DEBUGGER_EN(NONUSE))
|
||||
return 0;
|
||||
|
||||
down_read(&rga_drvdata->rwsem);
|
||||
|
||||
if (rga_drvdata->shutdown) {
|
||||
rga_log("driver has been shutdown\n");
|
||||
up_read(&rga_drvdata->rwsem);
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case RGA_BLIT_SYNC:
|
||||
case RGA_BLIT_ASYNC:
|
||||
@@ -1053,6 +1062,8 @@ static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
up_read(&rga_drvdata->rwsem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1442,17 +1453,38 @@ pm_disable:
|
||||
|
||||
static int rga_drv_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rga_scheduler_t *scheduler = NULL;
|
||||
|
||||
down_write(&rga_drvdata->rwsem);
|
||||
rga_drvdata->shutdown = true;
|
||||
|
||||
scheduler = (struct rga_scheduler_t *)platform_get_drvdata(pdev);
|
||||
if (scheduler)
|
||||
rga_request_scheduler_shutdown(scheduler);
|
||||
|
||||
#ifndef RGA_DISABLE_PM
|
||||
device_init_wakeup(&pdev->dev, false);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
#endif /* #ifndef RGA_DISABLE_PM */
|
||||
|
||||
up_write(&rga_drvdata->rwsem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rga_drv_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
rga_drv_remove(pdev);
|
||||
|
||||
dev_info(dev, "shutdown success\n");
|
||||
}
|
||||
|
||||
static struct platform_driver rga3_driver = {
|
||||
.probe = rga_drv_probe,
|
||||
.remove = rga_drv_remove,
|
||||
.shutdown = rga_drv_shutdown,
|
||||
.driver = {
|
||||
.name = "rga3",
|
||||
.of_match_table = of_match_ptr(rga3_dt_ids),
|
||||
@@ -1462,6 +1494,7 @@ static struct platform_driver rga3_driver = {
|
||||
static struct platform_driver rga2_driver = {
|
||||
.probe = rga_drv_probe,
|
||||
.remove = rga_drv_remove,
|
||||
.shutdown = rga_drv_shutdown,
|
||||
.driver = {
|
||||
.name = "rga2",
|
||||
.of_match_table = of_match_ptr(rga2_dt_ids),
|
||||
@@ -1479,6 +1512,8 @@ static int __init rga_init(void)
|
||||
}
|
||||
|
||||
mutex_init(&rga_drvdata->lock);
|
||||
init_rwsem(&rga_drvdata->rwsem);
|
||||
rga_drvdata->shutdown = false;
|
||||
|
||||
ret = platform_driver_register(&rga3_driver);
|
||||
if (ret != 0) {
|
||||
|
||||
@@ -633,6 +633,56 @@ struct rga_request *rga_request_lookup(struct rga_pending_request_manager *manag
|
||||
return request;
|
||||
}
|
||||
|
||||
void rga_request_scheduler_shutdown(struct rga_scheduler_t *scheduler)
|
||||
{
|
||||
struct rga_job *job, *job_q;
|
||||
unsigned long flags;
|
||||
|
||||
rga_power_enable(scheduler);
|
||||
|
||||
spin_lock_irqsave(&scheduler->irq_lock, flags);
|
||||
|
||||
job = scheduler->running_job;
|
||||
if (job) {
|
||||
if (test_bit(RGA_JOB_STATE_INTR_ERR, &job->state) ||
|
||||
test_bit(RGA_JOB_STATE_FINISH, &job->state)) {
|
||||
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
scheduler->running_job = NULL;
|
||||
scheduler->status = RGA_SCHEDULER_ABORT;
|
||||
scheduler->ops->soft_reset(scheduler);
|
||||
|
||||
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
|
||||
|
||||
rga_mm_unmap_job_info(job);
|
||||
|
||||
job->ret = -EBUSY;
|
||||
rga_request_release_signal(scheduler, job);
|
||||
|
||||
/*
|
||||
* Since the running job was abort, turn off the power here that
|
||||
* should have been turned off after job done (corresponds to
|
||||
* power_enable in rga_job_run()).
|
||||
*/
|
||||
rga_power_disable(scheduler);
|
||||
} else {
|
||||
/* Clean up the jobs in the todo list that need to be free. */
|
||||
list_for_each_entry_safe(job, job_q, &scheduler->todo_list, head) {
|
||||
rga_mm_unmap_job_info(job);
|
||||
|
||||
job->ret = -EBUSY;
|
||||
rga_request_release_signal(scheduler, job);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
|
||||
}
|
||||
|
||||
finish:
|
||||
rga_power_disable(scheduler);
|
||||
}
|
||||
|
||||
void rga_request_scheduler_abort(struct rga_scheduler_t *scheduler)
|
||||
{
|
||||
struct rga_job *job;
|
||||
|
||||
Reference in New Issue
Block a user