From d05b0ddc69628548f431de87e17c9c61e40aa010 Mon Sep 17 00:00:00 2001 From: tangdaoyong Date: Thu, 18 Jul 2024 13:54:33 +0800 Subject: [PATCH 125/222] feat:vdec support power managemnt Changelogs: 1. Add generic & runtime power management for vdec & jdec. Signed-off-by: tangdaoyong --- 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 #include #include +#include #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; +} + +/** 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 +#include #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