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