2025-01-03 03:30:57 +00:00
|
|
|
From a04b4317f04cddf1b1406b788f189a32609aa1d0 Mon Sep 17 00:00:00 2001
|
2024-12-15 18:29:23 +00:00
|
|
|
From: zouxiaojun <zouxiaojun@eswincomputing.com>
|
|
|
|
Date: Thu, 18 Jul 2024 16:24:24 +0800
|
2024-12-27 22:35:16 +00:00
|
|
|
Subject: [PATCH 126/222] feat(VE): VE support power management
|
2024-12-15 18:29:23 +00:00
|
|
|
|
|
|
|
Changelogs:
|
|
|
|
Add generic & runtime power management for VENC&JENC;
|
|
|
|
|
|
|
|
Signed-off-by: zouxiaojun <zouxiaojun@eswincomputing.com>
|
|
|
|
---
|
|
|
|
.../staging/media/eswin/venc/vc8000_driver.h | 11 +-
|
|
|
|
.../media/eswin/venc/vc8000_normal_driver.c | 68 +++--
|
|
|
|
.../media/eswin/venc/vc8000_vcmd_driver.c | 119 +++++---
|
|
|
|
.../staging/media/eswin/venc/vc8000e_driver.c | 257 +++++++++++++++++-
|
|
|
|
4 files changed, 381 insertions(+), 74 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/drivers/staging/media/eswin/venc/vc8000_driver.h b/drivers/staging/media/eswin/venc/vc8000_driver.h
|
|
|
|
index aadd259d1752..2863a47ff0ff 100644
|
|
|
|
--- a/drivers/staging/media/eswin/venc/vc8000_driver.h
|
|
|
|
+++ b/drivers/staging/media/eswin/venc/vc8000_driver.h
|
|
|
|
@@ -71,6 +71,9 @@
|
|
|
|
#include "vc8000_axife.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
+#define ENC_DEV_IDLEWAIT_TIME (msecs_to_jiffies(10000))
|
|
|
|
+
|
|
|
|
+#define ENC_CORE_NUM (4)
|
|
|
|
|
|
|
|
#undef ptr_t
|
|
|
|
#define ptr_t PTR_T_KERNEL
|
|
|
|
@@ -81,16 +84,18 @@ struct dmabuf_cfg {
|
|
|
|
int dmabuf_fd;
|
|
|
|
unsigned long iova;
|
|
|
|
};
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
-struct dmabuf_priv {
|
|
|
|
+struct filp_priv {
|
|
|
|
+#ifdef SUPPORT_DMA_HEAP
|
|
|
|
struct heap_root root;
|
|
|
|
struct heap_root root_d1;
|
|
|
|
+#endif
|
|
|
|
void *dev;
|
|
|
|
+ atomic_t core_tasks[ENC_CORE_NUM]; /** for task count of 4 cores*/
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
|
|
|
|
#define ENC_HW_ID1 0x48320100
|
|
|
|
#define ENC_HW_ID2 0x80006000
|
|
|
|
diff --git a/drivers/staging/media/eswin/venc/vc8000_normal_driver.c b/drivers/staging/media/eswin/venc/vc8000_normal_driver.c
|
|
|
|
index 6aae8a725c2d..7ef36c148f81 100644
|
|
|
|
--- a/drivers/staging/media/eswin/venc/vc8000_normal_driver.c
|
|
|
|
+++ b/drivers/staging/media/eswin/venc/vc8000_normal_driver.c
|
|
|
|
@@ -836,7 +836,7 @@ static long hantroenc_ioctl(struct file *filp, unsigned int cmd,
|
|
|
|
struct dmabuf_cfg dbcfg;
|
|
|
|
size_t buf_size = 0;
|
|
|
|
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;
|
|
|
|
@@ -844,14 +844,14 @@ static long hantroenc_ioctl(struct file *filp, unsigned int cmd,
|
|
|
|
LOG_DBG("import dmabuf_fd = %d\n", dbcfg.dmabuf_fd);
|
|
|
|
|
|
|
|
/* map the pha to dma addr(iova)*/
|
|
|
|
- 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 import from userspace failed\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (venc_pdev_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");
|
|
|
|
@@ -891,7 +891,7 @@ static long hantroenc_ioctl(struct file *filp, unsigned int cmd,
|
|
|
|
case HANTRO_IOCH_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;
|
|
|
|
@@ -899,14 +899,14 @@ static long hantroenc_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);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (venc_pdev_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;
|
|
|
|
@@ -929,27 +929,21 @@ static long hantroenc_ioctl(struct file *filp, unsigned int cmd,
|
|
|
|
static int hantroenc_open(struct inode *inode, struct file *filp)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
-#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, &venc_pdev->dev);
|
|
|
|
+#ifdef SUPPORT_DMA_HEAP
|
|
|
|
+ common_dmabuf_heap_import_init(&fp_priv->root, &venc_pdev->dev);
|
|
|
|
if (venc_pdev_d1) {
|
|
|
|
- common_dmabuf_heap_import_init(&db_priv->root_d1, &venc_pdev_d1->dev);
|
|
|
|
+ common_dmabuf_heap_import_init(&fp_priv->root_d1, &venc_pdev_d1->dev);
|
|
|
|
}
|
|
|
|
- db_priv->dev = (void *)hantroenc_data;
|
|
|
|
-
|
|
|
|
- filp->private_data = (void *)db_priv;
|
|
|
|
-#else
|
|
|
|
- hantroenc_t *dev = hantroenc_data;
|
|
|
|
-
|
|
|
|
- filp->private_data = (void *)dev;
|
|
|
|
#endif
|
|
|
|
+ fp_priv->dev = (void *)hantroenc_data;
|
|
|
|
+ filp->private_data = (void *)fp_priv;
|
|
|
|
|
|
|
|
LOG_DBG("dev opened\n");
|
|
|
|
return result;
|
|
|
|
@@ -957,12 +951,8 @@ static int hantroenc_open(struct inode *inode, struct file *filp)
|
|
|
|
|
|
|
|
static int hantroenc_release(struct inode *inode, struct file *filp)
|
|
|
|
{
|
|
|
|
-#ifdef SUPPORT_DMA_HEAP
|
|
|
|
- struct dmabuf_priv *db_priv= (struct dmabuf_priv *)filp->private_data;
|
|
|
|
- hantroenc_t *dev = (hantroenc_t *)db_priv->dev;
|
|
|
|
-#else
|
|
|
|
- hantroenc_t *dev = (hantroenc_t *)filp->private_data;
|
|
|
|
-#endif
|
|
|
|
+ struct filp_priv *fp_priv= (struct filp_priv *)filp->private_data;
|
|
|
|
+ hantroenc_t *dev = (hantroenc_t *)fp_priv->dev;
|
|
|
|
u32 core_id = 0, i = 0;
|
|
|
|
|
|
|
|
#ifdef hantroenc_DEBUG
|
|
|
|
@@ -993,11 +983,11 @@ static int hantroenc_release(struct inode *inode, struct file *filp)
|
|
|
|
up(&enc_core_sem);
|
|
|
|
|
|
|
|
#ifdef SUPPORT_DMA_HEAP
|
|
|
|
- common_dmabuf_heap_import_uninit(&db_priv->root);
|
|
|
|
+ common_dmabuf_heap_import_uninit(&fp_priv->root);
|
|
|
|
if (venc_pdev_d1) {
|
|
|
|
- common_dmabuf_heap_import_uninit(&db_priv->root_d1);
|
|
|
|
+ common_dmabuf_heap_import_uninit(&fp_priv->root_d1);
|
|
|
|
}
|
|
|
|
- kfree(db_priv);
|
|
|
|
+ kfree(fp_priv);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
@@ -1382,3 +1372,23 @@ static void dump_regs(unsigned long data)
|
|
|
|
LOG_DBG("Reg Dump End\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
+
|
|
|
|
+int hantroenc_wait_core_idle(u32 core_id)
|
|
|
|
+{
|
|
|
|
+#if 0
|
|
|
|
+ hantroenc_t *dev;
|
|
|
|
+ // u32 irq_status;
|
|
|
|
+ CORE_WAIT_OUT out;
|
|
|
|
+
|
|
|
|
+ if (core_id >= total_subsys_num) {
|
|
|
|
+ LOG_ERR("invalid core_id = %u, total_subsys_num = %u\n", core_id, total_subsys_num);
|
|
|
|
+ return -ERESTARTSYS;
|
|
|
|
+ }
|
|
|
|
+ dev = &hantroenc_data[core_id];
|
|
|
|
+
|
|
|
|
+ return wait_event_interruptible_timeout(enc_wait_queue
|
|
|
|
+ , CheckEncAnyIrq(dev, &out), ENC_DEV_IDLEWAIT_TIME);
|
|
|
|
+#else
|
|
|
|
+ return 0;
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
diff --git a/drivers/staging/media/eswin/venc/vc8000_vcmd_driver.c b/drivers/staging/media/eswin/venc/vc8000_vcmd_driver.c
|
|
|
|
index 6442cd2c0a54..9e5e388ef990 100644
|
|
|
|
--- a/drivers/staging/media/eswin/venc/vc8000_vcmd_driver.c
|
|
|
|
+++ b/drivers/staging/media/eswin/venc/vc8000_vcmd_driver.c
|
|
|
|
@@ -255,6 +255,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
|
|
|
|
@@ -281,6 +282,10 @@ static void create_kernel_process_manager(void);
|
|
|
|
|
|
|
|
static irqreturn_t hantrovcmd_isr(int irq, void *dev_id);
|
|
|
|
|
|
|
|
+/** pm runtime sync & put*/
|
|
|
|
+extern int venc_pm_runtime_sync(u32 core_id);
|
|
|
|
+extern int venc_pm_runtime_put(u32 core_id);
|
|
|
|
+
|
|
|
|
#ifdef VCMD_DEBUG_INTERNAL
|
|
|
|
static void printk_vcmd_register_debug(const void *hwregs, char *info);
|
|
|
|
#endif
|
|
|
|
@@ -1031,6 +1036,15 @@ static long release_cmdbuf(struct file *filp, u16 cmdbuf_id)
|
|
|
|
}
|
|
|
|
//spin_unlock_irqrestore(dev->spinlock, flags);
|
|
|
|
up(&vcmd_reserve_cmdbuf_sem[module_type]);
|
|
|
|
+ if (filp) {
|
|
|
|
+ struct filp_priv *fp_priv = (struct filp_priv *)filp->private_data;
|
|
|
|
+
|
|
|
|
+ /** release for the pm*/
|
|
|
|
+ if (atomic_dec_return(&(fp_priv->core_tasks[dev->core_id])) >= 0) {
|
|
|
|
+ venc_pm_runtime_put(dev->core_id);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1175,6 +1189,11 @@ 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("Venc 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;
|
|
|
|
+ venc_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.
|
|
|
|
@@ -1339,7 +1358,7 @@ static unsigned int wait_cmdbuf_ready(struct file *filp, u16 cmdbuf_id,
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (wait_event_interruptible(*dev->wait_queue, check_cmdbuf_irq(dev, cmdbuf_obj, irq_status_ret))) {
|
|
|
|
- LOG_DBG("vcmd_wait_queue_0 interrupted\n");
|
|
|
|
+ LOG_ERR("vcmd_wait_queue_0 interrupted\n");
|
|
|
|
//abort the vcmd
|
|
|
|
//vcmd_write_register_value((const void *)dev->hwregs,dev->reg_mirror,HWIF_VCMD_START_TRIGGER,0);
|
|
|
|
return -ERESTARTSYS;
|
|
|
|
@@ -1596,7 +1615,7 @@ static long hantrovcmd_ioctl(struct file *filp, unsigned int cmd,
|
|
|
|
struct dmabuf_cfg dbcfg;
|
|
|
|
size_t buf_size = 0;
|
|
|
|
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;
|
|
|
|
@@ -1604,14 +1623,14 @@ static long hantrovcmd_ioctl(struct file *filp, unsigned int cmd,
|
|
|
|
LOG_DBG("import dmabuf_fd = %d\n", dbcfg.dmabuf_fd);
|
|
|
|
|
|
|
|
/* map the pha to dma addr(iova)*/
|
|
|
|
- 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 import from userspace failed\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (venc_pdev_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");
|
|
|
|
@@ -1653,7 +1672,7 @@ static long hantrovcmd_ioctl(struct file *filp, unsigned int cmd,
|
|
|
|
case HANTRO_IOCH_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;
|
|
|
|
@@ -1661,14 +1680,14 @@ static long hantrovcmd_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);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (venc_pdev_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;
|
|
|
|
@@ -1944,25 +1963,24 @@ static 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 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, &venc_pdev->dev);
|
|
|
|
+#ifdef SUPPORT_DMA_HEAP
|
|
|
|
+ common_dmabuf_heap_import_init(&fp_priv->root, &venc_pdev->dev);
|
|
|
|
if (venc_pdev_d1) {
|
|
|
|
- common_dmabuf_heap_import_init(&db_priv->root_d1, &venc_pdev_d1->dev);
|
|
|
|
+ common_dmabuf_heap_import_init(&fp_priv->root_d1, &venc_pdev_d1->dev);
|
|
|
|
}
|
|
|
|
- db_priv->dev = (void *)dev;
|
|
|
|
-
|
|
|
|
- filp->private_data = (void *)db_priv;
|
|
|
|
-#else
|
|
|
|
- filp->private_data = (void *)dev;
|
|
|
|
#endif
|
|
|
|
+ fp_priv->dev = (void*)dev;
|
|
|
|
+ for (u32 core_id = 0; core_id < ENC_CORE_NUM; core_id ++) {
|
|
|
|
+ atomic_set(&(fp_priv->core_tasks[core_id]), 0);
|
|
|
|
+ }
|
|
|
|
+ filp->private_data = (void *)fp_priv;
|
|
|
|
process_manager_node = create_process_manager_node();
|
|
|
|
if (!process_manager_node)
|
|
|
|
return -1;
|
|
|
|
@@ -1972,20 +1990,14 @@ static int hantrovcmd_open(struct inode *inode, struct file *filp)
|
|
|
|
spin_lock_irqsave(&vcmd_process_manager_lock, flags);
|
|
|
|
bi_list_insert_node_tail(&global_process_manager, process_manager_node);
|
|
|
|
spin_unlock_irqrestore(&vcmd_process_manager_lock, flags);
|
|
|
|
-
|
|
|
|
LOG_DBG("dev opened\n");
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hantrovcmd_release(struct inode *inode, struct file *filp)
|
|
|
|
{
|
|
|
|
-#ifdef SUPPORT_DMA_HEAP
|
|
|
|
- struct dmabuf_priv *db_priv = (struct dmabuf_priv *)filp->private_data;
|
|
|
|
- struct hantrovcmd_dev *dev = (struct hantrovcmd_dev *)db_priv->dev;
|
|
|
|
-#else
|
|
|
|
- struct hantrovcmd_dev *dev =
|
|
|
|
- (struct hantrovcmd_dev *)filp->private_data;
|
|
|
|
-#endif
|
|
|
|
+ struct filp_priv *fp_priv = (struct filp_priv *)filp->private_data;
|
|
|
|
+ struct hantrovcmd_dev *dev = (struct hantrovcmd_dev *)fp_priv->dev;
|
|
|
|
u32 core_id = 0;
|
|
|
|
u32 release_cmdbuf_num = 0;
|
|
|
|
bi_list_node *new_cmdbuf_node = NULL;
|
|
|
|
@@ -2345,23 +2357,28 @@ static int hantrovcmd_release(struct inode *inode, struct file *filp)
|
|
|
|
free_process_manager_node(process_manager_node);
|
|
|
|
up(&vcmd_reserve_cmdbuf_sem[dev->vcmd_core_cfg.sub_module_type]);
|
|
|
|
|
|
|
|
+ for (u32 core_id = 0; core_id < ENC_CORE_NUM; core_id ++) {
|
|
|
|
+ /** clear the tasks for pm*/
|
|
|
|
+ while (atomic_dec_return(&(fp_priv->core_tasks[core_id])) >= 0) {
|
|
|
|
+ venc_pm_runtime_put(core_id);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
#ifdef SUPPORT_DMA_HEAP
|
|
|
|
- common_dmabuf_heap_import_uninit(&db_priv->root);
|
|
|
|
+ common_dmabuf_heap_import_uninit(&fp_priv->root);
|
|
|
|
if (venc_pdev_d1) {
|
|
|
|
- common_dmabuf_heap_import_uninit(&db_priv->root_d1);
|
|
|
|
+ common_dmabuf_heap_import_uninit(&fp_priv->root_d1);
|
|
|
|
}
|
|
|
|
- kfree(db_priv);
|
|
|
|
#endif
|
|
|
|
-
|
|
|
|
+ kfree(fp_priv);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
#ifdef SUPPORT_DMA_HEAP
|
|
|
|
- common_dmabuf_heap_import_uninit(&db_priv->root);
|
|
|
|
+ common_dmabuf_heap_import_uninit(&fp_priv->root);
|
|
|
|
if (venc_pdev_d1) {
|
|
|
|
- common_dmabuf_heap_import_uninit(&db_priv->root_d1);
|
|
|
|
+ common_dmabuf_heap_import_uninit(&fp_priv->root_d1);
|
|
|
|
}
|
|
|
|
- kfree(db_priv);
|
|
|
|
+ kfree(fp_priv);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return -ERESTARTSYS;
|
|
|
|
@@ -4045,3 +4062,37 @@ int vc8000e_vcmd_cleanup(void)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
+static int check_dev_idle(struct hantrovcmd_dev *dev)
|
|
|
|
+{
|
|
|
|
+ /** the devices must not be power down now.*/
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+ LOG_INFO("check_dev_idle, vcmd_state = %u\n", vcmd_state);
|
|
|
|
+
|
|
|
|
+ return idle;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int hantrovcmd_wait_core_idle(u32 core_id)
|
|
|
|
+{
|
|
|
|
+ struct hantrovcmd_dev *dev = NULL;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (core_id >= venc_vcmd_core_num) {
|
|
|
|
+ LOG_ERR("invalid core_id = %u, venc_vcmd_core_num = %u\n", core_id, venc_vcmd_core_num);
|
|
|
|
+ return -ERESTARTSYS;
|
|
|
|
+ }
|
|
|
|
+ dev = &hantrovcmd_data[core_id];
|
|
|
|
+ LOG_INFO("enc wait core idle, core_id = %u\n", core_id);
|
|
|
|
+
|
|
|
|
+ ret = wait_event_interruptible_timeout(*dev->wait_queue, check_dev_idle(dev), ENC_DEV_IDLEWAIT_TIME);
|
|
|
|
+
|
|
|
|
+ LOG_INFO("enc wait core idle exit, core_id = %u, ret = %d\n", core_id, ret);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
diff --git a/drivers/staging/media/eswin/venc/vc8000e_driver.c b/drivers/staging/media/eswin/venc/vc8000e_driver.c
|
|
|
|
index c85d919fe750..b66055e26c3b 100644
|
|
|
|
--- a/drivers/staging/media/eswin/venc/vc8000e_driver.c
|
|
|
|
+++ b/drivers/staging/media/eswin/venc/vc8000e_driver.c
|
|
|
|
@@ -7,6 +7,7 @@
|
|
|
|
#include <linux/of_platform.h>
|
|
|
|
#include <linux/of_irq.h>
|
|
|
|
#include <linux/clk.h>
|
|
|
|
+#include <linux/pm_runtime.h>
|
|
|
|
#include <linux/reset.h>
|
|
|
|
#include <linux/regmap.h>
|
|
|
|
#include <linux/mfd/syscon.h>
|
|
|
|
@@ -48,6 +49,15 @@ typedef struct _venc_clk_rst {
|
|
|
|
struct clk *mon_pclk;
|
|
|
|
} venc_clk_rst_t;
|
|
|
|
|
|
|
|
+typedef struct {
|
|
|
|
+ venc_clk_rst_t vcrt;
|
|
|
|
+
|
|
|
|
+ u8 numa_id;
|
|
|
|
+ atomic_t dev_close_gate;
|
|
|
|
+ atomic_t dev_open_gate;
|
|
|
|
+ u8 dev_closed;
|
|
|
|
+} venc_dev_prvdata;
|
|
|
|
+
|
|
|
|
SUBSYS_CONFIG vc8000e_subsys_array[4] = {0};
|
|
|
|
CORE_CONFIG vc8000e_core_array[8] = {0};
|
|
|
|
|
|
|
|
@@ -59,12 +69,71 @@ module_param(vcmd_supported, uint, 0);
|
|
|
|
|
|
|
|
extern int hantroenc_normal_init(void);
|
|
|
|
extern void hantroenc_normal_cleanup(void);
|
|
|
|
+extern int hantroenc_wait_core_idle(u32 core_id);
|
|
|
|
extern int vc8000e_vcmd_init(void);
|
|
|
|
extern int vc8000e_vcmd_cleanup(void);
|
|
|
|
+extern int hantrovcmd_wait_core_idle(u32 core_id);
|
|
|
|
+
|
|
|
|
+static int venc_dev_open(struct device *dev);
|
|
|
|
+static int venc_dev_close(struct device *dev);
|
|
|
|
+static int venc_pm_enable(struct platform_device *pdev);
|
|
|
|
|
|
|
|
extern VCMD_CONFIG vc8000e_vcmd_core_array[];
|
|
|
|
extern int venc_vcmd_core_num;
|
|
|
|
|
|
|
|
+/** <TODO> the je & ve should be seperated as two devices*/
|
|
|
|
+static u8 numa_id_array[4] = {0};
|
|
|
|
+struct platform_device *venc_get_platform_device(u32 core_id)
|
|
|
|
+{
|
|
|
|
+ struct platform_device *pdev = NULL;
|
|
|
|
+ u8 numa_id;
|
|
|
|
+
|
|
|
|
+ if (core_id >= venc_vcmd_core_num) {
|
|
|
|
+ LOG_ERR("invalid core_id = %u, venc_vcmd_core_num = %u\n", core_id, venc_vcmd_core_num);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+ numa_id = numa_id_array[core_id];
|
|
|
|
+
|
|
|
|
+ if (0 == numa_id)
|
|
|
|
+ pdev = venc_pdev;
|
|
|
|
+ else if (1 == numa_id)
|
|
|
|
+ pdev = venc_pdev_d1;
|
|
|
|
+
|
|
|
|
+ return pdev;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int venc_wait_core_idle(u32 core_id) {
|
|
|
|
+ if (0 == vcmd_supported) {
|
|
|
|
+ return hantroenc_wait_core_idle(core_id);
|
|
|
|
+ } else {
|
|
|
|
+ return hantrovcmd_wait_core_idle(core_id);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/** <TODO> the je & ve should be seperated as two devices*/
|
|
|
|
+int venc_wait_device_idle(struct platform_device *pdev)
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (pdev == venc_pdev) {
|
|
|
|
+ ret = venc_wait_core_idle(0);
|
|
|
|
+ if (ret <= 0)
|
|
|
|
+ return ret;
|
|
|
|
+ ret = venc_wait_core_idle(1);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+ else if (pdev == venc_pdev_d1) {
|
|
|
|
+ ret = venc_wait_core_idle(2);
|
|
|
|
+ if (ret <= 0)
|
|
|
|
+ return ret;
|
|
|
|
+ ret = venc_wait_core_idle(3);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ LOG_ERR("Unknown platform device = %p\n", pdev);
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static int venc_device_node_scan(unsigned char *compatible)
|
|
|
|
{
|
|
|
|
struct property *prop;
|
|
|
|
@@ -113,7 +182,7 @@ static int venc_device_nodes_check(void)
|
|
|
|
index++; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
-int venc_trans_device_nodes(struct platform_device *pdev)
|
|
|
|
+int venc_trans_device_nodes(struct platform_device *pdev, u8 numa_id)
|
|
|
|
{
|
|
|
|
static int subsys_id = 0;
|
|
|
|
static int core_index = 0;
|
|
|
|
@@ -171,6 +240,8 @@ int venc_trans_device_nodes(struct platform_device *pdev)
|
|
|
|
if (strstr(core_name, "jpeg"))
|
|
|
|
hw_type = CORE_VC8000EJ;
|
|
|
|
|
|
|
|
+ numa_id_array[subsys_id] = numa_id;
|
|
|
|
+
|
|
|
|
VENC_CORE_ARRAY_ASSIGN(core_index, subsys_id, hw_type, venc_addr[0], venc_addr[1], child_irq);
|
|
|
|
VENC_CORE_ARRAY_ASSIGN(core_index, subsys_id, CORE_AXIFE, axife_addr[0], axife_addr[1], -1);
|
|
|
|
subsys_id++;
|
|
|
|
@@ -537,7 +608,8 @@ static int hantro_venc_probe(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
static int pdev_count = 0;
|
|
|
|
int ret, numa_id, venc_dev_num = 0;
|
|
|
|
- venc_clk_rst_t *vcrt = devm_kzalloc(&pdev->dev, sizeof(venc_clk_rst_t), GFP_KERNEL);
|
|
|
|
+ venc_dev_prvdata *prvdata = devm_kzalloc(&pdev->dev, sizeof(venc_dev_prvdata), GFP_KERNEL);
|
|
|
|
+ venc_clk_rst_t *vcrt = &prvdata->vcrt;
|
|
|
|
|
|
|
|
venc_dev_num = venc_device_nodes_check();
|
|
|
|
if (venc_dev_num <= 0) {
|
|
|
|
@@ -581,7 +653,7 @@ static int hantro_venc_probe(struct platform_device *pdev)
|
|
|
|
venc_d1_clk_reset_init();
|
|
|
|
}
|
|
|
|
|
|
|
|
- ret = venc_trans_device_nodes(pdev);
|
|
|
|
+ ret = venc_trans_device_nodes(pdev, numa_id);
|
|
|
|
if (ret < 0) {
|
|
|
|
LOG_ERR("venc: dts parse failed");
|
|
|
|
return -1;
|
|
|
|
@@ -613,16 +685,31 @@ static int hantro_venc_probe(struct platform_device *pdev)
|
|
|
|
LOG_ERR("41bit esdma dev: No suitable DMA available\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
+ atomic_set(&prvdata->dev_open_gate, 1);
|
|
|
|
+ atomic_set(&prvdata->dev_close_gate, 1);
|
|
|
|
+ prvdata->dev_closed = 1;
|
|
|
|
+ prvdata->numa_id = numa_id;
|
|
|
|
+
|
|
|
|
pdev_count++;
|
|
|
|
if (venc_dev_num > pdev_count) {
|
|
|
|
LOG_INFO("VENC: The first core loaded, waiting for another...");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
-
|
|
|
|
if (vcmd_supported == 0)
|
|
|
|
- return hantroenc_normal_init();
|
|
|
|
+ ret = hantroenc_normal_init();
|
|
|
|
else
|
|
|
|
- return vc8000e_vcmd_init();
|
|
|
|
+ ret = vc8000e_vcmd_init();
|
|
|
|
+
|
|
|
|
+ if (0 == ret) {
|
|
|
|
+ if (venc_pdev && venc_pm_enable(venc_pdev) < 0) {
|
|
|
|
+ LOG_WARN("venc: enable pm for venc_pdev failed\n");
|
|
|
|
+ }
|
|
|
|
+ if (venc_pdev_d1 && venc_pm_enable(venc_pdev_d1) < 0) {
|
|
|
|
+ LOG_WARN("venc: enable pm for venc_pdev_d1 failed\n");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hantro_venc_remove(struct platform_device *pdev)
|
|
|
|
@@ -630,8 +717,12 @@ static int hantro_venc_remove(struct platform_device *pdev)
|
|
|
|
#ifdef SUPPORT_DMA_HEAP
|
|
|
|
int ret;
|
|
|
|
venc_clk_rst_t *vcrt;
|
|
|
|
+ venc_dev_prvdata *prvdata;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
|
|
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
|
|
+
|
|
|
|
if (vcmd_supported == 0)
|
|
|
|
hantroenc_normal_cleanup();
|
|
|
|
else
|
|
|
|
@@ -643,14 +734,163 @@ static int hantro_venc_remove(struct platform_device *pdev)
|
|
|
|
LOG_ERR("venc tbu power down failed\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
- vcrt = platform_get_drvdata(pdev);
|
|
|
|
+ prvdata = platform_get_drvdata(pdev);
|
|
|
|
+ vcrt = &prvdata->vcrt;
|
|
|
|
venc_hardware_reset(vcrt);
|
|
|
|
- venc_clk_disable(vcrt);
|
|
|
|
+ // venc_clk_disable(vcrt);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
+int venc_pm_runtime_sync(u32 core_id) {
|
|
|
|
+ struct platform_device *pdev = venc_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 venc_pm_runtime_put(u32 core_id) {
|
|
|
|
+ struct platform_device *pdev = venc_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);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int venc_pm_enable(struct platform_device *pdev) {
|
|
|
|
+ /** enable runtime PM */
|
|
|
|
+ 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 venc_dev_open(struct device *dev)
|
|
|
|
+{
|
|
|
|
+ venc_dev_prvdata *prvdata = dev_get_drvdata(dev);
|
|
|
|
+ venc_clk_rst_t *vcrt = &prvdata->vcrt;
|
|
|
|
+ int ret = -1;
|
|
|
|
+
|
|
|
|
+ if (atomic_dec_return(&prvdata->dev_open_gate) < 0) {
|
|
|
|
+ LOG_INFO("The device is opening\n");
|
|
|
|
+ atomic_inc(&prvdata->dev_open_gate);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ // if (prvdata->dev_closed == 0) {
|
|
|
|
+ // ret = 0;
|
|
|
|
+ // goto end;
|
|
|
|
+ // }
|
|
|
|
+ ret = venc_sys_clk_enable(vcrt);
|
|
|
|
+ if (ret) {
|
|
|
|
+ LOG_ERR("open device, venc enable clock failed\n");
|
|
|
|
+ goto end;
|
|
|
|
+ }
|
|
|
|
+ ret = win2030_tbu_power(dev, true);
|
|
|
|
+ if (ret) {
|
|
|
|
+ LOG_ERR("open device, tbu power on failed\n");
|
|
|
|
+ goto end;
|
|
|
|
+ }
|
|
|
|
+ prvdata->dev_closed = 0;
|
|
|
|
+
|
|
|
|
+end:
|
|
|
|
+ LOG_INFO("dev open, numa_id = %u, ret = %d\n", prvdata->numa_id, ret);
|
|
|
|
+ atomic_inc(&prvdata->dev_open_gate);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int venc_dev_close(struct device *dev)
|
|
|
|
+{
|
|
|
|
+ struct platform_device *pdev = container_of(dev, struct platform_device, dev);
|
|
|
|
+ venc_dev_prvdata *prvdata = dev_get_drvdata(dev);
|
|
|
|
+ venc_clk_rst_t *vcrt = &prvdata->vcrt;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (atomic_dec_return(&prvdata->dev_close_gate) < 0) {
|
|
|
|
+ LOG_INFO("The device is opening\n");
|
|
|
|
+ atomic_inc(&prvdata->dev_close_gate);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ // if (prvdata->dev_closed == 1) {
|
|
|
|
+ // ret = 0;
|
|
|
|
+ // goto end;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ /** check the device be idle*/
|
|
|
|
+ LOG_INFO("venc device closing, waiting device idle\n");
|
|
|
|
+ ret = venc_wait_device_idle(pdev);
|
|
|
|
+ LOG_INFO("enc device closing, waiting device idle ret=%d\n", ret);
|
|
|
|
+ if (0 == ret) {
|
|
|
|
+ /** timeout*/
|
|
|
|
+ LOG_ERR("Timeout for venc_suspend\n");
|
|
|
|
+ ret = -ETIMEDOUT;
|
|
|
|
+ goto end;
|
|
|
|
+ } else if (ret < 0) {
|
|
|
|
+ LOG_ERR("Interrupt triggered while venc_suspend\n");
|
|
|
|
+ ret = -ERESTARTSYS;
|
|
|
|
+ goto end;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /** close the venc device*/
|
|
|
|
+ ret = win2030_tbu_power(dev, false);
|
|
|
|
+ if (ret) {
|
|
|
|
+ LOG_ERR("close device, tbu power down failed\n");
|
|
|
|
+ goto end;
|
|
|
|
+ }
|
|
|
|
+ ret = venc_clk_disable(vcrt);
|
|
|
|
+ if (ret) {
|
|
|
|
+ LOG_ERR("close device, venc disable clock failed\n");
|
|
|
|
+ goto end;
|
|
|
|
+ }
|
|
|
|
+ prvdata->dev_closed = 1;
|
|
|
|
+
|
|
|
|
+end:
|
|
|
|
+ LOG_INFO("dev closed, numa_id = %u, ret = %d\n", prvdata->numa_id, ret);
|
|
|
|
+ atomic_inc(&prvdata->dev_close_gate);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int venc_runtime_suspend(struct device *dev) {
|
|
|
|
+ LOG_INFO("runtime suspend\n");
|
|
|
|
+ return venc_dev_close(dev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int venc_runtime_resume(struct device *dev) {
|
|
|
|
+ LOG_INFO("runtime resume\n");
|
|
|
|
+ return venc_dev_open(dev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int venc_suspend(struct device *dev) {
|
|
|
|
+ LOG_INFO("generic suspend\n");
|
|
|
|
+ if (pm_runtime_status_suspended(dev)) {
|
|
|
|
+ LOG_INFO("generic suspend, venc is suspended already\n");
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ return venc_dev_close(dev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int venc_resume(struct device *dev) {
|
|
|
|
+ LOG_INFO("generic resume\n");
|
|
|
|
+ if (pm_runtime_status_suspended(dev)) {
|
|
|
|
+ LOG_INFO("generic resume, venc is resumed already\n");
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ return venc_dev_open(dev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const struct dev_pm_ops venc_pm_ops = {
|
|
|
|
+ SET_RUNTIME_PM_OPS(venc_runtime_suspend, venc_runtime_resume, NULL)
|
|
|
|
+ SET_SYSTEM_SLEEP_PM_OPS(venc_suspend, venc_resume)
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
static const struct of_device_id eswin_venc_match[] = {
|
|
|
|
{ .compatible = "eswin,video-encoder0", },
|
|
|
|
{ .compatible = "eswin,video-encoder1", },
|
|
|
|
@@ -662,6 +902,7 @@ static struct platform_driver eswin_venc_driver = {
|
|
|
|
.driver = {
|
|
|
|
.name = "Eswinenc",
|
|
|
|
.of_match_table = eswin_venc_match,
|
|
|
|
+ .pm = &venc_pm_ops,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
--
|
|
|
|
2.47.0
|
|
|
|
|