From e3e12f52b214121840b44c91de5b3e5af5d3eb84 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 06 Nov 2023 03:04:41 +0000
Subject: [PATCH] rk3568 rt init

---
 kernel/drivers/video/rockchip/mpp/mpp_iep2.c |  105 +++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 91 insertions(+), 14 deletions(-)

diff --git a/kernel/drivers/video/rockchip/mpp/mpp_iep2.c b/kernel/drivers/video/rockchip/mpp/mpp_iep2.c
index 92ec40e..e8e2183 100644
--- a/kernel/drivers/video/rockchip/mpp/mpp_iep2.c
+++ b/kernel/drivers/video/rockchip/mpp/mpp_iep2.c
@@ -20,6 +20,8 @@
 #include <linux/regmap.h>
 #include <linux/pm_runtime.h>
 #include <linux/proc_fs.h>
+#include <linux/mfd/syscon.h>
+#include <linux/rockchip/cpu.h>
 #include <soc/rockchip/pm_domains.h>
 
 #include "rockchip_iep2_regs.h"
@@ -389,12 +391,13 @@
 		| IEP2_REG_DIL_OSD_EN
 		| IEP2_REG_DIL_PD_EN
 		| IEP2_REG_DIL_FF_EN
-		| IEP2_REG_DIL_MD_PRE_EN
 		| IEP2_REG_DIL_FIELD_ORDER(cfg->dil_field_order)
 		| IEP2_REG_DIL_OUT_MODE(cfg->dil_out_mode)
 		| IEP2_REG_DIL_MODE(cfg->dil_mode);
 	if (cfg->roi_en)
 		reg |= IEP2_REG_DIL_ROI_EN;
+	if (cfg->md_lambda < 8)
+		reg |= IEP2_REG_DIL_MD_PRE_EN;
 	mpp_write_relaxed(mpp, IEP2_REG_DIL_CONFIG0, reg);
 
 	if (cfg->dil_mode != ROCKCHIP_IEP2_DIL_MODE_PD) {
@@ -437,6 +440,9 @@
 		mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_NXTUV, bot->cbcr);
 		mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_NXTV, bot->cr);
 	}
+
+	reg = IEP2_REG_TIMEOUT_CFG_EN | 0x3ffffff;
+	mpp_write_relaxed(mpp, IEP2_REG_TIMEOUT_CFG, reg);
 
 	mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_PREY, cfg->src[2].y);
 	mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_PREUV, cfg->src[2].cbcr);
@@ -580,6 +586,7 @@
 		    struct mpp_task *mpp_task)
 {
 	struct iep_task *task = NULL;
+	u32 timing_en = mpp->srv->timing_en;
 
 	mpp_debug_enter();
 
@@ -598,12 +605,20 @@
 	mpp_write_relaxed(mpp, IEP2_REG_INT_EN,
 			  IEP2_REG_FRM_DONE_EN
 			  | IEP2_REG_OSD_MAX_EN
-			  | IEP2_REG_BUS_ERROR_EN);
+			  | IEP2_REG_BUS_ERROR_EN
+			  | IEP2_REG_TIMEOUT_EN);
+
+	/* flush tlb before starting hardware */
+	mpp_iommu_flush_tlb(mpp->iommu_info);
+
+	mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY);
 
 	/* Last, flush the registers */
 	wmb();
 	/* start iep2 */
 	mpp_write(mpp, IEP2_REG_FRM_START, 1);
+
+	mpp_task_run_end(mpp_task, timing_en);
 
 	mpp_debug_leave();
 
@@ -612,6 +627,10 @@
 
 static int iep2_irq(struct mpp_dev *mpp)
 {
+	u32 work_mode = mpp_read(mpp, IEP2_REG_WORK_MODE);
+
+	if (work_mode && !(work_mode & IEP2_REG_IEP2_MODE))
+		return IRQ_NONE;
 	mpp->irq_status = mpp_read(mpp, IEP2_REG_INT_STS);
 	mpp_write(mpp, IEP2_REG_INT_CLR, 0xffffffff);
 
@@ -640,7 +659,8 @@
 	mpp_debug(DEBUG_IRQ_STATUS, "irq_status: %08x\n",
 		  task->irq_status);
 
-	if (IEP2_REG_RO_BUS_ERROR_STS(task->irq_status))
+	if (IEP2_REG_RO_BUS_ERROR_STS(task->irq_status) ||
+	    IEP2_REG_RO_TIMEOUT_STS(task->irq_status))
 		atomic_inc(&mpp->reset_request);
 
 	mpp_task_finish(mpp_task->session, mpp_task);
@@ -769,6 +789,10 @@
 		iep->procfs = NULL;
 		return -EIO;
 	}
+
+	/* for common mpp_dev options */
+	mpp_procfs_create_common(iep->procfs, mpp);
+
 	mpp_procfs_create_u32("aclk", 0644,
 			      iep->procfs, &iep->aclk_info.debug_rate_hz);
 	mpp_procfs_create_u32("session_buffers", 0644,
@@ -870,17 +894,29 @@
 {
 	struct iep2_dev *iep = to_iep2_dev(mpp);
 
-	if (iep->rst_a && iep->rst_h && iep->rst_s) {
-		/* Don't skip this or iommu won't work after reset */
-		rockchip_pmu_idle_request(mpp->dev, true);
-		mpp_safe_reset(iep->rst_a);
-		mpp_safe_reset(iep->rst_h);
-		mpp_safe_reset(iep->rst_s);
-		udelay(5);
-		mpp_safe_unreset(iep->rst_a);
-		mpp_safe_unreset(iep->rst_h);
-		mpp_safe_unreset(iep->rst_s);
-		rockchip_pmu_idle_request(mpp->dev, false);
+	int ret = 0;
+	u32 rst_status = 0;
+
+	/* soft rest first */
+	mpp_write(mpp, IEP2_REG_IEP_CONFIG0, IEP2_REG_ACLK_SRESET_P);
+	ret = readl_relaxed_poll_timeout(mpp->reg_base + IEP2_REG_STATUS,
+					 rst_status,
+					 rst_status & IEP2_REG_ARST_FINISH_DONE,
+					 0, 5);
+	if (ret) {
+		mpp_err("soft reset timeout, use cru reset\n");
+		if (iep->rst_a && iep->rst_h && iep->rst_s) {
+			/* Don't skip this or iommu won't work after reset */
+			mpp_pmu_idle_request(mpp, true);
+			mpp_safe_reset(iep->rst_a);
+			mpp_safe_reset(iep->rst_h);
+			mpp_safe_reset(iep->rst_s);
+			udelay(5);
+			mpp_safe_unreset(iep->rst_a);
+			mpp_safe_unreset(iep->rst_h);
+			mpp_safe_unreset(iep->rst_s);
+			mpp_pmu_idle_request(mpp, false);
+		}
 	}
 
 	return 0;
@@ -1008,12 +1044,53 @@
 		dev_err(dev, "wait total running time out\n");
 }
 
+static int iep2_runtime_suspend(struct device *dev)
+{
+	struct mpp_dev *mpp = dev_get_drvdata(dev);
+	struct mpp_grf_info *info = mpp->grf_info;
+	struct mpp_taskqueue *queue = mpp->queue;
+
+	if (cpu_is_rk3528() && info && info->mem_offset) {
+		mutex_lock(&queue->ref_lock);
+		if (!atomic_dec_if_positive(&queue->runtime_cnt)) {
+			regmap_write(info->grf, info->mem_offset,
+				     info->val_mem_off);
+		}
+		mutex_unlock(&queue->ref_lock);
+	}
+
+	return 0;
+}
+
+static int iep2_runtime_resume(struct device *dev)
+{
+	struct mpp_dev *mpp = dev_get_drvdata(dev);
+	struct mpp_grf_info *info = mpp->grf_info;
+	struct mpp_taskqueue *queue = mpp->queue;
+
+	if (cpu_is_rk3528() && info && info->mem_offset) {
+		mutex_lock(&queue->ref_lock);
+		regmap_write(info->grf, info->mem_offset,
+			     info->val_mem_on);
+		atomic_inc(&queue->runtime_cnt);
+		mutex_unlock(&queue->ref_lock);
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops iep2_pm_ops = {
+	.runtime_suspend		= iep2_runtime_suspend,
+	.runtime_resume			= iep2_runtime_resume,
+};
+
 struct platform_driver rockchip_iep2_driver = {
 	.probe = iep2_probe,
 	.remove = iep2_remove,
 	.shutdown = iep2_shutdown,
 	.driver = {
 		.name = IEP2_DRIVER_NAME,
+		.pm = &iep2_pm_ops,
 		.of_match_table = of_match_ptr(mpp_iep2_match),
 	},
 };

--
Gitblit v1.6.2