From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Thu, 19 Dec 2024 01:47:39 +0000 Subject: [PATCH] add wifi6 8852be driver --- kernel/drivers/video/rockchip/mpp/mpp_rkvdec.c | 166 ++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 128 insertions(+), 38 deletions(-) diff --git a/kernel/drivers/video/rockchip/mpp/mpp_rkvdec.c b/kernel/drivers/video/rockchip/mpp/mpp_rkvdec.c index 09bea1e..4310a09 100644 --- a/kernel/drivers/video/rockchip/mpp/mpp_rkvdec.c +++ b/kernel/drivers/video/rockchip/mpp/mpp_rkvdec.c @@ -36,6 +36,7 @@ #include "mpp_debug.h" #include "mpp_common.h" #include "mpp_iommu.h" +#include <soc/rockchip/rockchip_iommu.h> #include "hack/mpp_hack_px30.h" @@ -593,6 +594,7 @@ mem_region = mpp_task_attach_fd(&task->mpp_task, scaling_fd); if (IS_ERR(mem_region)) { + mpp_err("scaling list fd %d attach failed\n", scaling_fd); ret = PTR_ERR(mem_region); goto done; } @@ -727,8 +729,11 @@ offset = task->reg[idx] >> 10 << 4; } mem_region = mpp_task_attach_fd(&task->mpp_task, fd); - if (IS_ERR(mem_region)) + if (IS_ERR(mem_region)) { + mpp_err("reg[%03d]: %08x fd %d attach failed\n", + idx, task->reg[idx], fd); return -EFAULT; + } iova = mem_region->iova; task->reg[idx] = iova + offset; @@ -887,6 +892,7 @@ int i; u32 reg_en; struct rkvdec_task *task = NULL; + u32 timing_en = mpp->srv->timing_en; mpp_debug_enter(); @@ -918,10 +924,13 @@ } /* init current task */ mpp->cur_task = mpp_task; + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); /* Flush the register before the start the device */ wmb(); mpp_write(mpp, RKVDEC_REG_INT_EN, task->reg[reg_en] | RKVDEC_DEC_START); + + mpp_task_run_end(mpp_task, timing_en); } break; default: break; @@ -944,11 +953,11 @@ task = to_rkvdec_task(mpp_task); /* - * HW defeat workaround: VP9 power save optimization cause decoding + * HW defeat workaround: VP9 and H.265 power save optimization cause decoding * corruption, disable optimization here. */ fmt = RKVDEC_GET_FORMAT(task->reg[RKVDEC_REG_SYS_CTRL_INDEX]); - if (fmt == RKVDEC_FMT_VP9D) { + if (fmt == RKVDEC_FMT_VP9D || fmt == RKVDEC_FMT_H265D) { cfg = task->reg[RKVDEC_POWER_CTL_INDEX] | 0xFFFF; task->reg[RKVDEC_POWER_CTL_INDEX] = cfg & (~(1 << 12)); mpp_write_relaxed(mpp, RKVDEC_POWER_CTL_BASE, @@ -969,6 +978,13 @@ if (task->link_mode == RKVDEC_MODE_ONEFRAME) mpp_iommu_flush_tlb(mpp->iommu_info); + return rkvdec_run(mpp, mpp_task); +} + +static int rkvdec_px30_run(struct mpp_dev *mpp, + struct mpp_task *mpp_task) +{ + mpp_iommu_flush_tlb(mpp->iommu_info); return rkvdec_run(mpp, mpp_task); } @@ -1171,6 +1187,10 @@ dec->procfs = NULL; return -EIO; } + + /* for common mpp_dev options */ + mpp_procfs_create_common(dec->procfs, mpp); + mpp_procfs_create_u32("aclk", 0644, dec->procfs, &dec->aclk_info.debug_rate_hz); mpp_procfs_create_u32("clk_core", 0644, @@ -1261,6 +1281,13 @@ return px30_workaround_combo_init(mpp); } +static int rkvdec_3036_init(struct mpp_dev *mpp) +{ + rkvdec_init(mpp); + set_bit(mpp->var->device_type, &mpp->queue->dev_active_flags); + return 0; +} + static int rkvdec_3328_iommu_hdl(struct iommu_domain *iommu, struct device *iommu_dev, unsigned long iova, @@ -1311,7 +1338,7 @@ struct rkvdec_dev *dec = to_rkvdec_dev(mpp); mutex_init(&dec->set_clk_lock); - dec->parent_devfreq = devfreq_get_devfreq_by_phandle(mpp->dev, 0); + dec->parent_devfreq = devfreq_get_devfreq_by_phandle(mpp->dev, "rkvdec_devfreq", 0); if (IS_ERR_OR_NULL(dec->parent_devfreq)) { if (PTR_ERR(dec->parent_devfreq) == -EPROBE_DEFER) { dev_warn(mpp->dev, "parent devfreq is not ready, retry\n"); @@ -1402,7 +1429,7 @@ goto done; } dec->aux_iova = -1; - mpp->iommu_info->hdl = rkvdec_3328_iommu_hdl; + mpp->fault_handler = rkvdec_3328_iommu_hdl; ret = rkvdec_devfreq_init(mpp); done: @@ -1510,6 +1537,52 @@ dec->grf_changed = mpp_grf_is_changed(mpp->grf_info); mpp_set_grf(mpp->grf_info); + + return 0; +} + +static int rkvdec_3036_set_grf(struct mpp_dev *mpp) +{ + int grf_changed; + struct mpp_dev *loop = NULL, *n; + struct mpp_taskqueue *queue = mpp->queue; + bool pd_is_on; + + grf_changed = mpp_grf_is_changed(mpp->grf_info); + if (grf_changed) { + + /* + * in this case, devices share the queue also share the same pd&clk, + * so use mpp->dev's pd to control all the process is okay + */ + pd_is_on = rockchip_pmu_pd_is_on(mpp->dev); + if (!pd_is_on) + rockchip_pmu_pd_on(mpp->dev); + mpp->hw_ops->clk_on(mpp); + + list_for_each_entry_safe(loop, n, &queue->dev_list, queue_link) { + if (test_bit(loop->var->device_type, &queue->dev_active_flags)) { + mpp_set_grf(loop->grf_info); + if (loop->hw_ops->clk_on) + loop->hw_ops->clk_on(loop); + if (loop->hw_ops->reset) + loop->hw_ops->reset(loop); + rockchip_iommu_disable(loop->dev); + if (loop->hw_ops->clk_off) + loop->hw_ops->clk_off(loop); + clear_bit(loop->var->device_type, &queue->dev_active_flags); + } + } + + mpp_set_grf(mpp->grf_info); + rockchip_iommu_enable(mpp->dev); + set_bit(mpp->var->device_type, &queue->dev_active_flags); + + mpp->hw_ops->clk_off(mpp); + if (!pd_is_on) + rockchip_pmu_pd_off(mpp->dev); + } + return 0; } @@ -1629,7 +1702,7 @@ mpp_debug_enter(); if (dec->rst_a && dec->rst_h) { - rockchip_pmu_idle_request(mpp->dev, true); + mpp_pmu_idle_request(mpp, true); mpp_safe_reset(dec->rst_niu_a); mpp_safe_reset(dec->rst_niu_h); mpp_safe_reset(dec->rst_a); @@ -1645,7 +1718,7 @@ mpp_safe_unreset(dec->rst_core); mpp_safe_unreset(dec->rst_cabac); mpp_safe_unreset(dec->rst_hevc_cabac); - rockchip_pmu_idle_request(mpp->dev, false); + mpp_pmu_idle_request(mpp, false); } mpp_debug_leave(); @@ -1654,18 +1727,18 @@ static int rkvdec_sip_reset(struct mpp_dev *mpp) { - struct rkvdec_dev *dec = to_rkvdec_dev(mpp); + if (IS_REACHABLE(CONFIG_ROCKCHIP_SIP)) { + /* The reset flow in arm trustzone firmware */ + struct rkvdec_dev *dec = to_rkvdec_dev(mpp); -/* The reset flow in arm trustzone firmware */ -#if IS_ENABLED(CONFIG_ROCKCHIP_SIP) - mutex_lock(&dec->sip_reset_lock); - sip_smc_vpu_reset(0, 0, 0); - mutex_unlock(&dec->sip_reset_lock); + mutex_lock(&dec->sip_reset_lock); + sip_smc_vpu_reset(0, 0, 0); + mutex_unlock(&dec->sip_reset_lock); - return 0; -#else - return rkvdec_reset(mpp); -#endif + return 0; + } else { + return rkvdec_reset(mpp); + } } static struct mpp_hw_ops rkvdec_v1_hw_ops = { @@ -1687,6 +1760,17 @@ .reduce_freq = rkvdec_reduce_freq, .reset = rkvdec_reset, .set_grf = px30_workaround_combo_switch_grf, +}; + +static struct mpp_hw_ops rkvdec_3036_hw_ops = { + .init = rkvdec_3036_init, + .clk_on = rkvdec_clk_on, + .clk_off = rkvdec_clk_off, + .get_freq = rkvdec_get_freq, + .set_freq = rkvdec_set_freq, + .reduce_freq = rkvdec_reduce_freq, + .reset = rkvdec_reset, + .set_grf = rkvdec_3036_set_grf, }; static struct mpp_hw_ops rkvdec_3399_hw_ops = { @@ -1713,6 +1797,16 @@ static struct mpp_dev_ops rkvdec_v1_dev_ops = { .alloc_task = rkvdec_alloc_task, .run = rkvdec_run, + .irq = rkvdec_irq, + .isr = rkvdec_isr, + .finish = rkvdec_finish, + .result = rkvdec_result, + .free_task = rkvdec_free_task, +}; + +static struct mpp_dev_ops rkvdec_px30_dev_ops = { + .alloc_task = rkvdec_alloc_task, + .run = rkvdec_px30_run, .irq = rkvdec_irq, .isr = rkvdec_isr, .finish = rkvdec_finish, @@ -1769,6 +1863,14 @@ .dev_ops = &rkvdec_v1_dev_ops, }; +static const struct mpp_dev_var rk_hevcdec_3036_data = { + .device_type = MPP_DEVICE_HEVC_DEC, + .hw_info = &rk_hevcdec_hw_info, + .trans_info = rk_hevcdec_trans, + .hw_ops = &rkvdec_3036_hw_ops, + .dev_ops = &rkvdec_v1_dev_ops, +}; + static const struct mpp_dev_var rk_hevcdec_3368_data = { .device_type = MPP_DEVICE_HEVC_DEC, .hw_info = &rk_hevcdec_hw_info, @@ -1782,7 +1884,7 @@ .hw_info = &rk_hevcdec_hw_info, .trans_info = rk_hevcdec_trans, .hw_ops = &rkvdec_px30_hw_ops, - .dev_ops = &rkvdec_v1_dev_ops, + .dev_ops = &rkvdec_px30_dev_ops, }; static const struct mpp_dev_var rkvdec_v1_data = { @@ -1826,6 +1928,12 @@ { .compatible = "rockchip,hevc-decoder-px30", .data = &rk_hevcdec_px30_data, + }, +#endif +#ifdef CONFIG_CPU_RK3036 + { + .compatible = "rockchip,hevc-decoder-rk3036", + .data = &rk_hevcdec_3036_data, }, #endif #ifdef CONFIG_CPU_RK3368 @@ -1873,7 +1981,7 @@ return -ENOMEM; mpp = &dec->mpp; - platform_set_drvdata(pdev, dec); + platform_set_drvdata(pdev, mpp); if (pdev->dev.of_node) { match = of_match_node(mpp_rkvdec_dt_match, @@ -1919,28 +2027,10 @@ return 0; } -static void rkvdec_shutdown(struct platform_device *pdev) -{ - int ret; - int val; - struct device *dev = &pdev->dev; - struct rkvdec_dev *dec = platform_get_drvdata(pdev); - struct mpp_dev *mpp = &dec->mpp; - - dev_info(dev, "shutdown device\n"); - - atomic_inc(&mpp->srv->shutdown_request); - ret = readx_poll_timeout(atomic_read, - &mpp->task_count, - val, val == 0, 20000, 200000); - if (ret == -ETIMEDOUT) - dev_err(dev, "wait total running time out\n"); -} - struct platform_driver rockchip_rkvdec_driver = { .probe = rkvdec_probe, .remove = rkvdec_remove, - .shutdown = rkvdec_shutdown, + .shutdown = mpp_dev_shutdown, .driver = { .name = RKVDEC_DRIVER_NAME, .of_match_table = of_match_ptr(mpp_rkvdec_dt_match), -- Gitblit v1.6.2