kernel/0125-feat-vdec-support-power-managemnt.patch

730 lines
24 KiB
Diff
Raw Normal View History

2024-12-19 21:34:44 +00:00
From 84162c54f7eab78ae69bfb4a7d7453d44965913b Mon Sep 17 00:00:00 2001
2024-12-15 18:29:23 +00:00
From: tangdaoyong <tangdaoyong@eswincomputing.com>
Date: Thu, 18 Jul 2024 13:54:33 +0800
Subject: [PATCH 125/219] feat:vdec support power managemnt
Changelogs:
1. Add generic & runtime power management for vdec & jdec.
Signed-off-by: tangdaoyong <tangdaoyong@eswincomputing.com>
---
drivers/staging/media/eswin/vdec/dts_parser.c | 4 +-
drivers/staging/media/eswin/vdec/dts_parser.h | 3 +-
drivers/staging/media/eswin/vdec/hantro_dec.c | 194 +++++++++++++++---
.../staging/media/eswin/vdec/hantro_vcmd.c | 89 +++++---
drivers/staging/media/eswin/vdec/hantrodec.h | 10 +-
drivers/staging/media/eswin/vdec/subsys.c | 42 ++++
drivers/staging/media/eswin/vdec/subsys.h | 4 +
7 files changed, 283 insertions(+), 63 deletions(-)
diff --git a/drivers/staging/media/eswin/vdec/dts_parser.c b/drivers/staging/media/eswin/vdec/dts_parser.c
index a423612727d0..8d96a39bf1c5 100644
--- a/drivers/staging/media/eswin/vdec/dts_parser.c
+++ b/drivers/staging/media/eswin/vdec/dts_parser.c
@@ -11,6 +11,7 @@
struct SubsysDesc subsys_array[VDEC_MAX_SUBSYS] = {0};
struct CoreDesc core_array[VDEC_MAX_CORE] = {0};
+u8 numa_id_array[4] = {0};
static int vdec_device_node_scan(unsigned char *compatible)
{
@@ -60,7 +61,7 @@ int vdec_device_nodes_check(void)
index++; \
} while (0)
-int vdec_trans_device_nodes(struct platform_device *pdev)
+int vdec_trans_device_nodes(struct platform_device *pdev, u8 numa_id)
{
extern unsigned int vcmd;
int jpeg = 0;
@@ -125,6 +126,7 @@ int vdec_trans_device_nodes(struct platform_device *pdev)
if (jpeg && vcmd)
hw_type = HW_VC8000DJ;
+ numa_id_array[subsys_id] = numa_id;
VDEC_CORE_ARRAY_ASSIGN(core_index, subsys_id, hw_type, (base_addr + vdec_addr[0]), vdec_addr[1], child_irq);
subsys_id++;
}
diff --git a/drivers/staging/media/eswin/vdec/dts_parser.h b/drivers/staging/media/eswin/vdec/dts_parser.h
index 310cfcf8ccd1..d375b2e23cb9 100644
--- a/drivers/staging/media/eswin/vdec/dts_parser.h
+++ b/drivers/staging/media/eswin/vdec/dts_parser.h
@@ -8,6 +8,7 @@
int vdec_device_nodes_check(void);
extern struct SubsysDesc subsys_array[VDEC_MAX_SUBSYS];
extern struct CoreDesc core_array[VDEC_MAX_CORE];
-extern int vdec_trans_device_nodes(struct platform_device *pdev);
+extern u8 numa_id_array[4];
+extern int vdec_trans_device_nodes(struct platform_device *pdev, u8 numa_id);
#endif /* __DTS_PARSER_H__ */
diff --git a/drivers/staging/media/eswin/vdec/hantro_dec.c b/drivers/staging/media/eswin/vdec/hantro_dec.c
index 54b1fbe6ad6f..12d63a5ea985 100644
--- a/drivers/staging/media/eswin/vdec/hantro_dec.c
+++ b/drivers/staging/media/eswin/vdec/hantro_dec.c
@@ -98,6 +98,7 @@
#include <linux/mfd/syscon.h>
#include <linux/eswin-win2030-sid-cfg.h>
#include <dt-bindings/memory/eswin-win2030-sid.h>
+#include <linux/pm_runtime.h>
#include "subsys.h"
#include "hantroaxife.h"
@@ -410,6 +411,9 @@ static void ReleaseIO(void);
static void ResetAsic(hantrodec_t *dev);
+static int vdec_clk_enable(vdec_clk_rst_t *vcrt);
+static int vdec_pm_enable(struct platform_device *pdev);
+
#ifdef HANTRODEC_DEBUG
static void dump_regs(hantrodec_t *dev);
#endif
@@ -2380,7 +2384,7 @@ static long hantrodec_ioctl(struct file *filp, unsigned int cmd,
size_t buf_size = 0;
void *cpu_vaddr = NULL;
struct heap_mem *hmem, *hmem_d1;
- struct dmabuf_priv *db_priv = (struct dmabuf_priv *)filp->private_data;
+ struct filp_priv *fp_priv = (struct filp_priv *)filp->private_data;
if (copy_from_user(&dbcfg, (void __user *)arg, sizeof(struct dmabuf_cfg)) != 0)
return -EFAULT;
@@ -2389,14 +2393,16 @@ static long hantrodec_ioctl(struct file *filp, unsigned int cmd,
/* map the pha to dma addr(iova)*/
/* syscoherent <-> false, flush one time when import; sys,cma <-> true, no fush */
- hmem = common_dmabuf_heap_import_from_user(&db_priv->root, dbcfg.dmabuf_fd);
+ hmem = common_dmabuf_heap_import_from_user(&fp_priv->root, dbcfg.dmabuf_fd);
if(IS_ERR(hmem)) {
LOG_ERR("dmabuf-heap alloc from userspace failed\n");
return -ENOMEM;
}
+ //LOG_INFO("import dmabuf_fd = %d, hmem=%px, filp=%px, platformdev_d1=%px\n", dbcfg.dmabuf_fd, hmem, filp,
+ // platformdev_d1);
if (platformdev_d1) {
- hmem_d1 = common_dmabuf_heap_import_from_user(&db_priv->root_d1, dbcfg.dmabuf_fd);
+ hmem_d1 = common_dmabuf_heap_import_from_user(&fp_priv->root_d1, dbcfg.dmabuf_fd);
if(IS_ERR(hmem_d1)) {
common_dmabuf_heap_release(hmem);
LOG_ERR("dmabuf-heap alloc from userspace failed for d1\n");
@@ -2438,7 +2444,7 @@ static long hantrodec_ioctl(struct file *filp, unsigned int cmd,
common_dmabuf_heap_release(hmem);
if (platformdev_d1)
common_dmabuf_heap_release(hmem_d1);
- LOG_DBG("%s %d: copy_from_user failed, returned %li\n", __func__, __LINE__, tmp);
+ LOG_ERR("%s %d: copy_from_user failed, returned %li\n", __func__, __LINE__, tmp);
return -EFAULT;
}
@@ -2447,7 +2453,7 @@ static long hantrodec_ioctl(struct file *filp, unsigned int cmd,
case HANTRODEC_IOC_DMA_HEAP_PUT_IOVA: {
struct heap_mem *hmem, *hmem_d1;
unsigned int dmabuf_fd;
- struct dmabuf_priv *db_priv = (struct dmabuf_priv *)filp->private_data;
+ struct filp_priv *fp_priv = (struct filp_priv *)filp->private_data;
if (copy_from_user(&dmabuf_fd, (void __user *)arg, sizeof(int)) != 0)
return -EFAULT;
@@ -2455,20 +2461,22 @@ static long hantrodec_ioctl(struct file *filp, unsigned int cmd,
LOG_DBG("release dmabuf_fd = %d\n", dmabuf_fd);
/* find the heap_mem */
- hmem = common_dmabuf_lookup_heapobj_by_fd(&db_priv->root, dmabuf_fd);
+ hmem = common_dmabuf_lookup_heapobj_by_fd(&fp_priv->root, dmabuf_fd);
if (IS_ERR(hmem)) {
- LOG_ERR("cannot find dmabuf-heap for dmabuf_fd %d\n", dmabuf_fd);
+ LOG_ERR("cannot find dmabuf-heap for dmabuf_fd %d, %px\n", dmabuf_fd, hmem);
return -ENOMEM;
}
if (platformdev_d1) {
- hmem_d1 = common_dmabuf_lookup_heapobj_by_fd(&db_priv->root_d1, dmabuf_fd);
+ hmem_d1 = common_dmabuf_lookup_heapobj_by_fd(&fp_priv->root_d1, dmabuf_fd);
if (IS_ERR(hmem_d1)) {
LOG_ERR("cannot find dmabuf-heap for dmabuf_fd %d on d1\n", dmabuf_fd);
return -EFAULT;
}
common_dmabuf_heap_release(hmem_d1);
}
+ //LOG_INFO("release dmabuf_fd = %d, hmem=%px, filp=%px, platformdev_d1=%px\n", dmabuf_fd, hmem, filp,
+ // platformdev_d1);
common_dmabuf_heap_release(hmem);
return 0;
@@ -2535,22 +2543,24 @@ static int hantrodec_mmap(struct file *filp, struct vm_area_struct *vma)
*/
static int hantrodec_open(struct inode *inode, struct file *filp)
{
-#ifdef SUPPORT_DMA_HEAP
- struct dmabuf_priv *db_priv;
+ struct filp_priv *fp_priv;
- db_priv = kzalloc(sizeof(struct dmabuf_priv), GFP_KERNEL);
- if (!db_priv) {
+ fp_priv = kzalloc(sizeof(struct filp_priv), GFP_KERNEL);
+ if (!fp_priv) {
pr_err("%s: alloc failed\n", __func__);
return -ENOMEM;
}
- common_dmabuf_heap_import_init(&db_priv->root, &platformdev->dev);
+#ifdef SUPPORT_DMA_HEAP
+ common_dmabuf_heap_import_init(&fp_priv->root, &platformdev->dev);
if (platformdev_d1) {
- common_dmabuf_heap_import_init(&db_priv->root_d1, &platformdev_d1->dev);
+ common_dmabuf_heap_import_init(&fp_priv->root_d1, &platformdev_d1->dev);
}
-
- filp->private_data = (void *)db_priv;
#endif
+ for (u32 core_id = 0; core_id < DEC_CORE_NUM; core_id ++) {
+ atomic_set(&(fp_priv->core_tasks[core_id]), 0);
+ }
+ filp->private_data = (void *)fp_priv;
LOG_DBG("dev opened\n");
if (vcmd)
@@ -2571,9 +2581,7 @@ static int hantrodec_release(struct inode *inode,
{
int n;
hantrodec_t *dev = &hantrodec_data;
-#ifdef SUPPORT_DMA_HEAP
- struct dmabuf_priv *db_priv = (struct dmabuf_priv *)filp->private_data;
-#endif
+ struct filp_priv *fp_priv = (struct filp_priv *)filp->private_data;
LOG_DBG("closing ...\n");
@@ -2601,12 +2609,18 @@ static int hantrodec_release(struct inode *inode,
end:
#ifdef SUPPORT_DMA_HEAP
- common_dmabuf_heap_import_uninit(&db_priv->root);
+ common_dmabuf_heap_import_uninit(&fp_priv->root);
if (platformdev_d1) {
- common_dmabuf_heap_import_uninit(&db_priv->root_d1);
+ common_dmabuf_heap_import_uninit(&fp_priv->root_d1);
}
- kfree(db_priv);
#endif
+ for (u32 core_id = 0; core_id < DEC_CORE_NUM; core_id ++) {
+ /** clear the tasks for pm*/
+ while (atomic_dec_return(&(fp_priv->core_tasks[core_id])) >= 0) {
+ vdec_pm_runtime_put(core_id);
+ }
+ }
+ kfree(fp_priv);
LOG_DBG("closed\n");
return 0;
@@ -2810,8 +2824,8 @@ static int hantrodec_init(void)
hantrodec_data.async_queue_pp = NULL;
result = register_chrdev(hantrodec_major,
- DEC_DEV_NAME,
- &hantrodec_fops);
+ DEC_DEV_NAME,
+ &hantrodec_fops);
if (result < 0) {
LOG_ERR("unable to get major %d\n", hantrodec_major);
goto err;
@@ -3703,6 +3717,12 @@ static int vdec_sys_clk_enable(vdec_clk_rst_t *vcrt)
LOG_INFO("VD set vd_clk to %ldHZ\n", rate);
}
+ return vdec_clk_enable(vcrt);
+}
+
+static int vdec_clk_enable(vdec_clk_rst_t *vcrt) {
+ int ret;
+
ret = clk_prepare_enable(vcrt->aclk);
if (ret) {
LOG_ERR("Video Decoder: failed to enable aclk: %d\n", ret);
@@ -3873,6 +3893,10 @@ static int hantro_vdec_probe(struct platform_device *pdev)
int ret, vdec_dev_num = 0;
static int pdev_count = 0;
vdec_clk_rst_t *vcrt = devm_kzalloc(&pdev->dev, sizeof(vdec_clk_rst_t), GFP_KERNEL);
+ if (!vcrt) {
+ LOG_ERR("malloc drvdata failed\n");
+ return -ENOMEM;
+ }
// pr_info("[%s]build version: %s\n", DEC_DEV_NAME, ES_VDEC_GIT_VER);
vdec_dev_num = vdec_device_nodes_check();
@@ -3921,7 +3945,7 @@ static int hantro_vdec_probe(struct platform_device *pdev)
d1_clk_reset_init();
}
- if (vdec_trans_device_nodes(pdev)) {
+ if (vdec_trans_device_nodes(pdev, numa_id)) {
LOG_ERR("Translates video decoder dts to subsys failed");
return -1;
}
@@ -3951,17 +3975,36 @@ static int hantro_vdec_probe(struct platform_device *pdev)
LOG_NOTICE("load driver %s failed\n", DEC_DEV_NAME);
} else {
LOG_NOTICE("module inserted. Major = %d\n", hantrodec_major);
+
+ if (platformdev && vdec_pm_enable(platformdev) < 0) {
+ LOG_WARN("enable pm for vdec-die0 failed\n");
+ }
+ if (platformdev_d1 && vdec_pm_enable(platformdev_d1) < 0) {
+ LOG_WARN("enable pm for vdec-die1 failed\n");
+ }
}
return ret;
}
+static int vdec_pm_enable(struct platform_device *pdev) {
+ /* The code below assumes runtime PM to be disabled. */
+ WARN_ON(pm_runtime_enabled(&pdev->dev));
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
+}
+
static int hantro_vdec_remove(struct platform_device *pdev)
{
#ifdef SUPPORT_DMA_HEAP
int ret;
- vdec_clk_rst_t *vcrt;
#endif
+ vdec_clk_rst_t *vcrt;
+ pm_runtime_disable(&pdev->dev);
hantrodec_cleanup();
#ifdef SUPPORT_DMA_HEAP
ret = win2030_tbu_power(&pdev->dev, false);
@@ -3969,14 +4012,110 @@ static int hantro_vdec_remove(struct platform_device *pdev)
LOG_ERR("vdec tbu power down failed\n");
return -1;
}
+#endif
vcrt = platform_get_drvdata(pdev);
vdec_hardware_reset(vcrt);
vdec_clk_disable(vcrt);
-#endif
return 0;
}
+static int eswin_vdec_runtime_suspend(struct device *dev) {
+ vdec_clk_rst_t *vcrt = NULL;
+ int ret = -1;
+
+ vcrt = dev_get_drvdata(dev);
+ if (vcrt) {
+ ret = win2030_tbu_power(dev, false);
+ if (ret != 0) {
+ LOG_ERR("tbu power up failed, %d\n", __LINE__);
+ return -1;
+ }
+ ret = vdec_clk_disable(vcrt);
+ }
+ return ret;
+}
+
+static int eswin_vdec_runtime_resume(struct device *dev) {
+ vdec_clk_rst_t *vcrt = NULL;
+ int ret = -1;
+
+ vcrt = dev_get_drvdata(dev);
+ if (vcrt) {
+ ret = vdec_clk_enable(vcrt);
+ if (ret) {
+ LOG_ERR("enable sys clk failed, %d\n", __LINE__);
+ return ret;
+ }
+
+ ret = win2030_tbu_power(dev, true);
+ if (ret != 0) {
+ LOG_ERR("tbu power down failed, %d\n", __LINE__);
+ return -1;
+ }
+ }
+ return ret;
+}
+
+/** <TODO> the jd & vd should be seperated as two devices*/
+int vdec_wait_device_idle(struct platform_device *pdev) {
+ int ret;
+
+ if (pdev == platformdev) {
+ ret = hantrovcmd_wait_core_idle(0, msecs_to_jiffies(500));
+ if (ret <= 0) {
+ return ret;
+ }
+ ret = hantrovcmd_wait_core_idle(1, msecs_to_jiffies(500));
+ return ret;
+ }
+ else if (pdev == platformdev_d1) {
+ ret = hantrovcmd_wait_core_idle(2, msecs_to_jiffies(500));
+ if (ret <= 0) {
+ return ret;
+ }
+ ret = hantrovcmd_wait_core_idle(3, msecs_to_jiffies(500));
+ return ret;
+ }
+
+ LOG_ERR("Unknown platform device = %p\n", pdev);
+ return 1;
+}
+
+static int eswin_vdec_suspend(struct device *dev) {
+ int ret = 0;
+ struct platform_device *pdev = NULL;
+
+ if (!pm_runtime_status_suspended(dev)) {
+ pdev = container_of(dev, struct platform_device, dev);
+ ret = vdec_wait_device_idle(pdev);
+ if (!ret) {
+ LOG_ERR("Timeout for vdec_suspend\n");
+ return -ETIMEDOUT;
+ } else if (ret < 0) {
+ LOG_ERR("Interrupt triggered while vdec_suspend\n");
+ return -ERESTARTSYS;
+ }
+
+ ret = eswin_vdec_runtime_suspend(dev);
+ }
+ return ret;
+}
+
+static int eswin_vdec_resume(struct device *dev) {
+ int ret = 0;
+
+ if (!pm_runtime_status_suspended(dev)) {
+ ret = eswin_vdec_runtime_resume(dev);
+ }
+ return ret;
+}
+
+static const struct dev_pm_ops eswin_vdec_dev_pm_ops = {
+ LATE_SYSTEM_SLEEP_PM_OPS(eswin_vdec_suspend, eswin_vdec_resume)
+ RUNTIME_PM_OPS(eswin_vdec_runtime_suspend, eswin_vdec_runtime_resume, NULL)
+};
+
static const struct of_device_id eswin_vdec_match[] = {
{ .compatible = "eswin,video-decoder0", },
{ .compatible = "eswin,video-decoder1", },
@@ -3988,6 +4127,7 @@ static struct platform_driver eswin_vdec_driver = {
.driver = {
.name = DEC_DEV_NAME,
.of_match_table = eswin_vdec_match,
+ .pm = &eswin_vdec_dev_pm_ops,
},
};
diff --git a/drivers/staging/media/eswin/vdec/hantro_vcmd.c b/drivers/staging/media/eswin/vdec/hantro_vcmd.c
index 76a411fdbde2..3e07e4a1f5cb 100644
--- a/drivers/staging/media/eswin/vdec/hantro_vcmd.c
+++ b/drivers/staging/media/eswin/vdec/hantro_vcmd.c
@@ -781,6 +781,7 @@ static int vcmd_type_core_num[MAX_VCMD_TYPE];
#define WORKING_STATE_IDLE 0
#define WORKING_STATE_WORKING 1
+#define WORKING_STATE_STALL 2
#define CMDBUF_EXE_STATUS_OK 0
#define CMDBUF_EXE_STATUS_CMDERR 1
#define CMDBUF_EXE_STATUS_BUSERR 2
@@ -1583,14 +1584,13 @@ static long release_cmdbuf(struct file *filp, u16 cmdbuf_id)
unsigned long flags;
struct hantrovcmd_dev *dev = NULL;
-#ifdef SUPPORT_DMA_HEAP
- struct dmabuf_priv *db_priv = NULL;
+ struct filp_priv *fp_priv = NULL;
if (!filp || !filp->private_data) {
LOG_ERR("invalid filp\n");
return -1;
}
- db_priv = (struct dmabuf_priv *)filp->private_data;
-#endif
+ fp_priv = (struct filp_priv *)filp->private_data;
+
/*get cmdbuf object according to cmdbuf_id*/
new_cmdbuf_node = global_cmdbuf_node[cmdbuf_id];
if (!new_cmdbuf_node) {
@@ -1623,11 +1623,11 @@ static long release_cmdbuf(struct file *filp, u16 cmdbuf_id)
if (new_cmdbuf_node) {
//free node
#ifdef SUPPORT_DMA_HEAP
- spin_lock_irqsave(&db_priv->vcmdlock, flags);
+ spin_lock_irqsave(&fp_priv->vcmdlock, flags);
#endif
global_cmdbuf_node[cmdbuf_obj->cmdbuf_id] = NULL;
#ifdef SUPPORT_DMA_HEAP
- spin_unlock_irqrestore(&db_priv->vcmdlock, flags);
+ spin_unlock_irqrestore(&fp_priv->vcmdlock, flags);
#endif
if (cmdbuf_obj->process_manager_obj) {
spin_lock_irqsave(&cmdbuf_obj->process_manager_obj->spinlock,
@@ -1648,6 +1648,11 @@ static long release_cmdbuf(struct file *filp, u16 cmdbuf_id)
}
//spin_unlock_irqrestore(dev->spinlock, flags);
up(&vcmd_reserve_cmdbuf_sem[module_type]);
+ /** release for the pm*/
+ if (atomic_dec_return(&(fp_priv->core_tasks[dev->core_id])) >= 0) {
+ vdec_pm_runtime_put(dev->core_id);
+ }
+
return 0;
}
@@ -1797,8 +1802,12 @@ static long link_and_run_cmdbuf(struct file *filp,
dev = &hantrovcmd_data[cmdbuf_obj->core_id];
input_para->core_id = cmdbuf_obj->core_id;
- LOG_TRACE("Vdec Allocate cmd buffer [%d] to core [%d]\n", cmdbuf_id,
- input_para->core_id);
+ LOG_TRACE("Vdec Allocate cmd buffer [%d] to core [%d]\n", cmdbuf_id, input_para->core_id);
+ if (filp) {
+ struct filp_priv *fp_priv = (struct filp_priv *)filp->private_data;
+ vdec_pm_runtime_sync(dev->core_id);
+ atomic_inc(&(fp_priv->core_tasks[dev->core_id]));
+ }
//set ddr address for vcmd registers copy.
if (dev->hw_version_id > HW_ID_1_0_C) {
//read vcmd executing register into ddr memory.
@@ -1906,12 +1915,12 @@ static int check_mc_cmdbuf_irq(struct file *filp, struct cmdbuf_obj *cmdbuf_obj,
struct hantrovcmd_dev *dev = NULL;
#ifdef SUPPORT_DMA_HEAP
unsigned long flags = 0;
- struct dmabuf_priv *db_priv = NULL;
+ struct filp_priv *fp_priv = NULL;
if (!filp || !filp->private_data) {
LOG_ERR("check mc: invalid filp\n");
return 0;
}
- db_priv = (struct dmabuf_priv *)filp->private_data;
+ fp_priv = (struct filp_priv *)filp->private_data;
#endif
for (k = 0; k < TOTAL_DISCRETE_CMDBUF_NUM; k++) {
@@ -1921,12 +1930,12 @@ static int check_mc_cmdbuf_irq(struct file *filp, struct cmdbuf_obj *cmdbuf_obj,
}
#ifdef SUPPORT_DMA_HEAP
- spin_lock_irqsave(&db_priv->vcmdlock, flags);
+ spin_lock_irqsave(&fp_priv->vcmdlock, flags);
#endif
new_cmdbuf_node = global_cmdbuf_node[k];
if (!new_cmdbuf_node) {
#ifdef SUPPORT_DMA_HEAP
- spin_unlock_irqrestore(&db_priv->vcmdlock, flags);
+ spin_unlock_irqrestore(&fp_priv->vcmdlock, flags);
#endif
continue;
}
@@ -1934,7 +1943,7 @@ static int check_mc_cmdbuf_irq(struct file *filp, struct cmdbuf_obj *cmdbuf_obj,
cmdbuf_obj = (struct cmdbuf_obj *)new_cmdbuf_node->data;
if (!cmdbuf_obj || cmdbuf_obj->filp != filp) {
#ifdef SUPPORT_DMA_HEAP
- spin_unlock_irqrestore(&db_priv->vcmdlock, flags);
+ spin_unlock_irqrestore(&fp_priv->vcmdlock, flags);
#endif
continue;
}
@@ -1945,13 +1954,13 @@ static int check_mc_cmdbuf_irq(struct file *filp, struct cmdbuf_obj *cmdbuf_obj,
*irq_status_ret = cmdbuf_obj->cmdbuf_id;
cmdbuf_obj->waited = 1;
#ifdef SUPPORT_DMA_HEAP
- spin_unlock_irqrestore(&db_priv->vcmdlock, flags);
+ spin_unlock_irqrestore(&fp_priv->vcmdlock, flags);
#endif
return 1;
}
}
#ifdef SUPPORT_DMA_HEAP
- spin_unlock_irqrestore(&db_priv->vcmdlock, flags);
+ spin_unlock_irqrestore(&fp_priv->vcmdlock, flags);
#endif
}
@@ -2616,13 +2625,11 @@ int hantrovcmd_open(struct inode *inode, struct file *filp)
bi_list_node *process_manager_node;
unsigned long flags;
struct process_manager_obj *process_manager_obj = NULL;
-#ifdef SUPPORT_DMA_HEAP
- struct dmabuf_priv *db_priv = (struct dmabuf_priv *)filp->private_data;
- spin_lock_init(&db_priv->vcmdlock);
- db_priv->dev = (void *)dev;
-#else
- filp->private_data = (void *)dev;
-#endif
+ struct filp_priv *fp_priv = (struct filp_priv *)filp->private_data;
+
+ spin_lock_init(&fp_priv->vcmdlock);
+ fp_priv->dev = (void *)dev;
+
process_manager_node = create_process_manager_node();
if (!process_manager_node) {
pr_err("%d: create_process_manager_node failed\n", __LINE__);
@@ -2642,9 +2649,7 @@ int hantrovcmd_open(struct inode *inode, struct file *filp)
int hantrovcmd_release(struct inode *inode, struct file *filp)
{
-#ifdef SUPPORT_DMA_HEAP
- struct dmabuf_priv *db_priv = NULL;
-#endif
+ struct filp_priv *fp_priv = NULL;
struct hantrovcmd_dev *dev = NULL;
u32 core_id = 0;
u32 release_cmdbuf_num = 0;
@@ -2664,12 +2669,8 @@ int hantrovcmd_release(struct inode *inode, struct file *filp)
return EFAULT;
}
-#ifdef SUPPORT_DMA_HEAP
- db_priv = (struct dmabuf_priv *)filp->private_data;
- dev = (struct hantrovcmd_dev *)db_priv->dev;
-#else
- dev = (struct hantrovcmd_dev *)filp->private_data;
-#endif
+ fp_priv = (struct filp_priv *)filp->private_data;
+ dev = (struct hantrovcmd_dev *)fp_priv->dev;
if (down_interruptible(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]))
return -ERESTARTSYS;
@@ -4982,3 +4983,29 @@ static void printk_vcmd_register_debug(const void *hwregs, char *info)
}
#endif
}
+
+static int check_dev_idle(struct hantrovcmd_dev *dev) {
+ int idle = 0;
+
+ u8 vcmd_state = vcmd_get_register_value((const void *)dev->hwregs,
+ dev->reg_mirror, HWIF_VCMD_WORK_STATE);
+ if (WORKING_STATE_STALL != vcmd_state && WORKING_STATE_WORKING != vcmd_state) {
+ idle = 1;
+ } else {
+ // LOG_WARN("check_dev_idle, vcmd_state = %u\n", vcmd_state);
+ }
+ LOG_WARN("check_dev_idle, vcmd_state = %u\n", vcmd_state);
+ return idle;
+}
+
+int hantrovcmd_wait_core_idle(u32 core_id, long timeout) {
+ struct hantrovcmd_dev *dev = NULL;
+
+ if (core_id >= total_vcmd_core_num) {
+ LOG_ERR("invalid core_id = %u, vcmd_core_num = %u\n", core_id, total_vcmd_core_num);
+ return -ERESTARTSYS;
+ }
+
+ dev = &hantrovcmd_data[core_id];
+ return wait_event_interruptible_timeout(*dev->wait_queue, check_dev_idle(dev), timeout);
+}
diff --git a/drivers/staging/media/eswin/vdec/hantrodec.h b/drivers/staging/media/eswin/vdec/hantrodec.h
index e9f356be4f07..9991f4e2ed8e 100644
--- a/drivers/staging/media/eswin/vdec/hantrodec.h
+++ b/drivers/staging/media/eswin/vdec/hantrodec.h
@@ -153,18 +153,22 @@ struct dmabuf_split {
unsigned int offset; /* offset of the buffer corresponding to dmabuf_fd */
unsigned int length; /* size of the splitted buffer start from offset */
};
+#endif
+
+#define DEC_CORE_NUM (4)
#ifdef __KERNEL__
-struct dmabuf_priv {
+struct filp_priv {
+#ifdef SUPPORT_DMA_HEAP
struct heap_root root;
struct heap_root root_d1;
+#endif
void *dev;
spinlock_t vcmdlock;
+ atomic_t core_tasks[DEC_CORE_NUM]; /** for task count of 4 cores*/
};
#endif
-#endif
-
/* Use 'k' as magic number */
#define HANTRODEC_IOC_MAGIC 'k'
diff --git a/drivers/staging/media/eswin/vdec/subsys.c b/drivers/staging/media/eswin/vdec/subsys.c
index 0f68ed405bce..7b8b2a50975c 100644
--- a/drivers/staging/media/eswin/vdec/subsys.c
+++ b/drivers/staging/media/eswin/vdec/subsys.c
@@ -56,6 +56,8 @@
#include "subsys.h"
#include "dts_parser.h"
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
#define LOG_TAG DEC_DEV_NAME ":subs"
#include "vc_drv_log.h"
@@ -210,3 +212,43 @@ void CheckSubsysCoreArray(struct subsys_config *subsys, int *vcmd)
i, multicorebase[i], iosize[i]);
}
}
+
+struct platform_device *vdec_get_platform_device(u32 core_id)
+{
+ struct platform_device *pdev = NULL;
+ u32 core_num = 4;
+ u8 numa_id;
+
+ if (core_id >= core_num) {
+ LOG_ERR("invalid core_id = %u, core_num = %u\n", core_id, core_num);
+ return NULL;
+ }
+ numa_id = numa_id_array[core_id];
+
+ if (0 == numa_id)
+ pdev = platformdev;
+ else if (1 == numa_id)
+ pdev = platformdev_d1;
+
+ return pdev;
+}
+
+int vdec_pm_runtime_sync(u32 core_id) {
+ struct platform_device *pdev = vdec_get_platform_device(core_id);
+
+ if (!pdev) {
+ LOG_ERR("get platform device failed for pm sync, core_id = %u\n", core_id);
+ }
+
+ return pm_runtime_get_sync(&pdev->dev);
+}
+
+int vdec_pm_runtime_put(u32 core_id) {
+ struct platform_device *pdev = vdec_get_platform_device(core_id);
+
+ if (!pdev) {
+ LOG_ERR("get platform device failed for pm put, numa_id = %u\n", core_id);
+ }
+
+ return pm_runtime_put(&pdev->dev);
+}
diff --git a/drivers/staging/media/eswin/vdec/subsys.h b/drivers/staging/media/eswin/vdec/subsys.h
index 39b68c6c1bbd..17a82a6169b0 100644
--- a/drivers/staging/media/eswin/vdec/subsys.h
+++ b/drivers/staging/media/eswin/vdec/subsys.h
@@ -173,6 +173,10 @@ int hantrovcmd_mmap(struct file *filp, struct vm_area_struct *vma);
int hantrovcmd_init(void);
void hantrovcmd_cleanup(void);
+int hantrovcmd_wait_core_idle(u32 core_id, long timeout);
+struct platform_device *vdec_get_platform_device(u32 core_id);
+int vdec_pm_runtime_sync(u32 core_id);
+int vdec_pm_runtime_put(u32 core_id);
/******************************************************************************/
/* MMU */
/******************************************************************************/
--
2.47.0