Explorar o código

Merge pull request #24 from SFxingyuwu/JH7100_starlight_multimedia_td

soft_3rdpart:wave511:driver:Amend Vdec module platform driver
andyhu-stf %!s(int64=2) %!d(string=hai) anos
pai
achega
0275c9e959

+ 301 - 0
soft_3rdpart/wave511/code/vdi/linux/driver/vdec-starfive.h

@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 StarFive Technology Co., Ltd.
+ */
+#ifndef __VDEC_STARFIVE_H__
+#define __VDEC_STARFIVE_H__
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/reset-controller.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/clk-provider.h>
+
+#define VDEC_ID_NUM 5
+
+struct starfive_vdec_data {
+	struct device *dev;
+	struct clk *clk_vdec_axi;
+	struct clk *clk_vdecbrg_main;
+	struct clk *clk_vdec_bclk;
+	struct clk *clk_vdec_cclk;
+	struct clk *clk_vdec_apb;
+
+    struct reset_control *rst_vdecbrg_main;
+    struct reset_control *rst_vdec_axi;
+    struct reset_control *rst_vdec_bclk;
+    struct reset_control *rst_vdec_cclk;
+    struct reset_control *rst_vdec_apb;
+
+	struct clk *clk_vdec_id[VDEC_ID_NUM];
+	struct reset_control *rst_vdec_id[VDEC_ID_NUM];
+
+};
+
+static struct starfive_vdec_data *sf_vdec = NULL;
+
+const char vdec_data_id[VDEC_ID_NUM][15] = {
+	"vdec_axi",
+	"vdecbrg_main",
+	"vdec_bclk",
+	"vdec_cclk",
+	"vdec_apb",
+};
+
+void starfive_vdec_rst_status(void)
+{
+	int i;
+	int rst_state;
+	for (i = 0; i < VDEC_ID_NUM; i++) {		
+		rst_state = reset_control_status(sf_vdec->rst_vdec_id[i]);
+	}
+	return;
+}
+
+void starfive_vdec_clk_status(void)
+{
+	int i;
+	int clk_state;
+	for (i = 0; i < VDEC_ID_NUM; i++) {		
+		clk_state = __clk_is_enabled(sf_vdec->clk_vdec_id[i]);
+	}
+	return;
+}
+
+void starfive_vdec_rst_exit(void)
+{
+	int i;
+	int ret;
+	for (i = 0; i < VDEC_ID_NUM; i++) {
+		ret = reset_control_assert(sf_vdec->rst_vdec_id[i]);
+		if (ret) {
+			dev_err(sf_vdec->dev, "reset assert failed\n");
+		}
+	}
+	return;
+}
+
+void starfive_vdec_clk_exit(void)
+{
+	int i;
+	for (i = 0; i < VDEC_ID_NUM; i++) {
+		clk_disable_unprepare(sf_vdec->clk_vdec_id[i]);
+	}
+	return;
+}
+
+static int starfive_vdec_clk_init(void)
+{
+	int ret = 0;
+	int i;
+	for (i = 0; i < VDEC_ID_NUM; i++) {
+		ret = clk_prepare_enable(sf_vdec->clk_vdec_id[i]);
+		if (ret) {
+			dev_err(sf_vdec->dev, vdec_data_id[i]);
+			goto init_clk_failed;
+		}
+	}
+
+	return 0;
+
+init_clk_failed:
+	for(; i > 0 ; i--) {
+		clk_disable_unprepare(sf_vdec->clk_vdec_id[i-1]);
+	}
+
+	return ret;
+
+}
+
+static int starfive_vdec_get_clk(void)
+{
+	int ret = 0;
+	int i;
+	for ( i = 0; i < VDEC_ID_NUM ; i++) {
+		sf_vdec->clk_vdec_id[i] = devm_clk_get(sf_vdec->dev, vdec_data_id[i]);
+		if (IS_ERR(sf_vdec->clk_vdec_id[i])) {
+			dev_err(sf_vdec->dev,  vdec_data_id[i]);
+			ret = PTR_ERR(sf_vdec->clk_vdec_id[i]);
+			goto get_clk_failed;
+		}
+	}
+
+	return 0;
+
+get_clk_failed:
+	for( ; i > 0 ; i--) {
+		devm_clk_put(sf_vdec->dev, sf_vdec->clk_vdec_id[i-1]);
+	}
+
+	return ret;
+}
+
+static int starfive_vdec_reset_init(void)
+{
+    int ret = 0;
+	int i;
+	for (i = 0; i < VDEC_ID_NUM ; i++) {
+		ret = reset_control_deassert(sf_vdec->rst_vdec_id[i]);
+    	if (ret) {
+			dev_err(sf_vdec->dev, vdec_data_id[i]);
+       	 	goto init_reset_failed;
+		}
+	}
+
+	return 0;
+
+init_reset_failed:
+	for (; i > 0 ; i--) {
+		reset_control_assert(sf_vdec->rst_vdec_id[i-1]);
+	}
+
+	return ret;
+}
+
+static int starfive_vdec_get_resets(void)
+{	
+    int ret = 0;
+	int i;
+	for (i = 0; i < VDEC_ID_NUM ; i++) {
+		sf_vdec->rst_vdec_id[i] = devm_reset_control_get_exclusive(sf_vdec->dev, vdec_data_id[i]);
+		if (IS_ERR(sf_vdec->rst_vdec_id[i])) {
+			dev_err(sf_vdec->dev,  vdec_data_id[i]);
+			ret = PTR_ERR(sf_vdec->rst_vdec_id[i]);
+			goto get_resets_failed;
+		}
+	}
+
+	return 0;
+
+get_resets_failed:
+	for (; i > 0; i--) {
+		reset_control_put(sf_vdec->rst_vdec_id[i-1]);
+	}
+
+	return ret;
+}
+
+
+int starfive_vdec_data_init(struct device *dev)
+{
+	int ret = 0;
+
+	if (sf_vdec == NULL){
+		sf_vdec = devm_kzalloc(dev, sizeof(*sf_vdec), GFP_KERNEL);
+		if (!sf_vdec)
+			return -ENOMEM;
+		sf_vdec->dev = dev;
+
+		ret = starfive_vdec_get_clk();
+		if (ret) {
+			dev_err(sf_vdec->dev, "failed to get vdec clock\n");
+			return ret;
+		}
+
+		ret = starfive_vdec_get_resets();
+		if (ret) {
+			dev_err(sf_vdec->dev, "failed to get vdec resets\n");
+			return ret;
+		}		
+	}
+
+	return 0;
+}
+
+int starfive_vdec_clk_enable(struct device *dev)
+{
+    int ret = 0;
+
+	ret = starfive_vdec_data_init(dev);
+	if (ret)
+		return ret;
+
+	ret = starfive_vdec_clk_init();
+	if (ret) {
+		dev_err(sf_vdec->dev, "failed to enable vdec clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+int starfive_vdec_clk_disable(struct device *dev)
+{
+    int ret = 0;
+
+	ret = starfive_vdec_data_init(dev);
+	if (ret)
+		return ret;
+
+	starfive_vdec_clk_exit();
+
+	return 0;
+	
+}
+
+int starfive_vdec_rst_deassert(struct device *dev)
+{
+    int ret = 0;
+
+	ret = starfive_vdec_data_init(dev);
+	if (ret)
+		return ret;
+
+	ret = starfive_vdec_reset_init();
+	if (ret) {
+		dev_err(sf_vdec->dev, "failed to deassert vdec resets\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+int starfive_vdec_rst_assert(struct device *dev)
+{
+    int ret = 0;
+	ret = starfive_vdec_data_init(dev);
+	if (ret)
+		return ret;
+    
+	starfive_vdec_rst_exit();
+
+	return 0;
+	
+}
+
+
+int starfive_vdec_clk_rst_init(struct platform_device *pdev)
+{
+    int ret = 0;
+
+	ret = starfive_vdec_data_init(&pdev->dev);
+	if (ret)
+		return ret;
+
+	ret = starfive_vdec_clk_init();
+	if (ret) {
+		dev_err(sf_vdec->dev, "failed to enable vdec clock\n");
+		return ret;
+	} 
+
+	starfive_vdec_rst_exit();
+	mdelay(1);
+	ret = starfive_vdec_reset_init();
+	if (ret) {
+		dev_err(sf_vdec->dev, "failed to set vdec reset\n");
+		goto init_failed;
+	}
+
+	printk("starfive vdec clock & reset init success.");
+    return 0;
+
+init_failed:
+    starfive_vdec_clk_exit();
+    return ret;
+
+}
+
+#endif

+ 61 - 11
soft_3rdpart/wave511/code/vdi/linux/driver/vdec.c

@@ -20,10 +20,14 @@
 #include <linux/kfifo.h>
 #include <linux/kthread.h>
 #include <asm/io.h>
-#include <soc/starfive/vic7100.h>
+#include <soc/sifive/sifive_l2_cache.h>
 #include "../../../vpuapi/vpuconfig.h"
 
 #include "vpu.h"
+#include "vdec-starfive.h"
+
+#define starfive_flush_dcache(start, len) \
+	sifive_l2_flush64_range(start, len)
 
 //#define ENABLE_DEBUG_MSG
 #ifdef ENABLE_DEBUG_MSG
@@ -33,8 +37,10 @@
 #endif
 
 /* definitions to be changed as customer  configuration */
-/* if you want to have clock gating scheme frame by frame */
-/* #define VPU_SUPPORT_CLOCK_CONTROL */
+/* if linux version is 5.15 or later, then can use clock and reset framework */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(5,15,0)
+#define VPU_SUPPORT_CLOCK_CONTROL
+#endif
 
 /* if the driver want to use interrupt service from kernel ISR */
 #define VPU_SUPPORT_ISR
@@ -888,19 +894,20 @@ INTERRUPT_REMAIN_IN_QUEUE:
 
     case VDI_IOCTL_SET_CLOCK_GATE:
         {
+#ifndef VPU_SUPPORT_CLOCK_CONTROL
             u32 clkgate;
 
             DPRINTK("[VPUDRV][+]VDI_IOCTL_SET_CLOCK_GATE\n");
             if (get_user(clkgate, (u32 __user *) arg))
                 return -EFAULT;
-#ifdef VPU_SUPPORT_CLOCK_CONTROL
+
             if (clkgate)
                 vpu_clk_enable(s_vpu_clk);
             else
                 vpu_clk_disable(s_vpu_clk);
-#endif
-            DPRINTK("[VPUDRV][-]VDI_IOCTL_SET_CLOCK_GATE\n");
 
+            DPRINTK("[VPUDRV][-]VDI_IOCTL_SET_CLOCK_GATE\n");
+#endif
         }
         break;
     case VDI_IOCTL_GET_INSTANCE_POOL:
@@ -1081,7 +1088,9 @@ INTERRUPT_REMAIN_IN_QUEUE:
         break;
     case VDI_IOCTL_RESET:
         {
+#ifndef VPU_SUPPORT_CLOCK_CONTROL
             vpu_hw_reset();
+#endif
         }
         break;
     case VDI_IOCTL_GET_REGISTER_INFO:
@@ -1307,11 +1316,13 @@ static int vpu_probe(struct platform_device *pdev)
 {
     int err = 0;
     struct resource *res = NULL;
+
 #ifdef VPU_SUPPORT_RESERVED_VIDEO_MEMORY
 	struct resource res_cma;
 	struct device_node *node;
 #endif
     DPRINTK("[VPUDRV] vpu_probe\n");
+
 	if(pdev){
 		vpu_dev = &pdev->dev;
 		vpu_dev->coherent_dma_mask = 0xffffffff;;
@@ -1350,6 +1361,7 @@ static int vpu_probe(struct platform_device *pdev)
         goto ERROR_PROVE_DEVICE;
     }
 
+#ifndef VPU_SUPPORT_CLOCK_CONTROL
     if (pdev)
         s_vpu_clk = vpu_clk_get(&pdev->dev);
     else
@@ -1359,8 +1371,13 @@ static int vpu_probe(struct platform_device *pdev)
         printk(KERN_ERR "[VPUDRV] : not support clock controller.\n");
     else
         DPRINTK("[VPUDRV] : get clock controller s_vpu_clk=%p\n", s_vpu_clk);
+#endif
 
 #ifdef VPU_SUPPORT_CLOCK_CONTROL
+    err = starfive_vdec_clk_rst_init(pdev);
+    if (err){
+        goto ERROR_PROVE_DEVICE; 
+    }
 #else
     vpu_clk_enable(s_vpu_clk);
     vpu_hw_reset();
@@ -1467,7 +1484,9 @@ static int vpu_remove(struct platform_device *pdev)
     if (s_vpu_register.virt_addr)
         iounmap((void *)s_vpu_register.virt_addr);
 
+#ifndef VPU_SUPPORT_CLOCK_CONTROL
     vpu_clk_put(s_vpu_clk);
+#endif
 
     return 0;
 }
@@ -1497,7 +1516,11 @@ static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
 
     DPRINTK("[VPUDRV] vpu_suspend\n");
 
+#ifdef VPU_SUPPORT_CLOCK_CONTROL
+    starfive_vdec_clk_enable(&pdev->dev);
+#else
     vpu_clk_enable(s_vpu_clk);
+#endif
 
     if (s_vpu_open_ref_count > 0) {
         for (core = 0; core < MAX_NUM_VPU_CORE; core++) {
@@ -1542,12 +1565,20 @@ static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
         }
     }
 
+ #ifdef VPU_SUPPORT_CLOCK_CONTROL
+    starfive_vdec_clk_disable(&pdev->dev);
+#else
     vpu_clk_disable(s_vpu_clk);
+#endif
     return 0;
 
 DONE_SUSPEND:
 
+#ifdef VPU_SUPPORT_CLOCK_CONTROL
+    starfive_vdec_clk_disable(&pdev->dev);
+#else
     vpu_clk_disable(s_vpu_clk);
+#endif
 
     return -EAGAIN;
 
@@ -1569,7 +1600,11 @@ static int vpu_resume(struct platform_device *pdev)
 
     DPRINTK("[VPUDRV] vpu_resume\n");
 
+#ifdef VPU_SUPPORT_CLOCK_CONTROL
+    starfive_vdec_clk_enable(&pdev->dev);
+#else
     vpu_clk_enable(s_vpu_clk);
+#endif
 
     for (core = 0; core < MAX_NUM_VPU_CORE; core++) {
 
@@ -1672,13 +1707,23 @@ static int vpu_resume(struct platform_device *pdev)
         }
     }
 
-    if (s_vpu_open_ref_count == 0)
+    if (s_vpu_open_ref_count == 0){
+#ifdef VPU_SUPPORT_CLOCK_CONTROL
+        starfive_vdec_clk_disable(&pdev->dev);
+#else
         vpu_clk_disable(s_vpu_clk);
+#endif
+    }
 
 DONE_WAKEUP:
 
-    if (s_vpu_open_ref_count > 0)
+    if (s_vpu_open_ref_count > 0){
+#ifdef VPU_SUPPORT_CLOCK_CONTROL
+        starfive_vdec_clk_enable(&pdev->dev);
+#else
         vpu_clk_enable(s_vpu_clk);
+#endif
+    }
 
     return 0;
 }
@@ -1746,6 +1791,12 @@ static int __init vpu_init(void)
 
 static void __exit vpu_exit(void)
 {
+
+#ifdef VPU_SUPPORT_CLOCK_CONTROL
+    starfive_vdec_clk_disable(vpu_dev);
+    starfive_vdec_rst_assert(vpu_dev);
+#endif
+
 #ifdef VPU_SUPPORT_PLATFORM_DRIVER_REGISTER
     DPRINTK("[VPUDRV] vpu_exit\n");
 
@@ -1753,11 +1804,10 @@ static void __exit vpu_exit(void)
 
 #else /* VPU_SUPPORT_PLATFORM_DRIVER_REGISTER */
 
-#ifdef VPU_SUPPORT_CLOCK_CONTROL
-#else
+#ifndef VPU_SUPPORT_CLOCK_CONTROL
     vpu_clk_disable(s_vpu_clk);
-#endif
     vpu_clk_put(s_vpu_clk);
+#endif
 
     if (s_instance_pool.base) {
 #ifdef USE_VMALLOC_FOR_INSTANCE_POOL_MEMORY