Parcourir la source

soft_3rdpart:wave511:driver:Amend Vdec module platform driver

Modified Vdec module driver and Add Vdec module clocks and resets driver file.
And if linux version is 5.15 or later, then the driver can use clock and reset framework.

Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
xingyu.wu il y a 2 ans
Parent
commit
1d83ac3dde

+ 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