From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 03 Jan 2024 09:43:39 +0000 Subject: [PATCH] update kernel to 5.10.198 --- kernel/drivers/video/rockchip/mpp/mpp_rkvenc2.c | 191 +++++++++++++++++++++++++++++++++-------------- 1 files changed, 135 insertions(+), 56 deletions(-) diff --git a/kernel/drivers/video/rockchip/mpp/mpp_rkvenc2.c b/kernel/drivers/video/rockchip/mpp/mpp_rkvenc2.c index 5bd7054..111c106 100644 --- a/kernel/drivers/video/rockchip/mpp/mpp_rkvenc2.c +++ b/kernel/drivers/video/rockchip/mpp/mpp_rkvenc2.c @@ -32,6 +32,7 @@ #include <soc/rockchip/rockchip_ipa.h> #include <soc/rockchip/rockchip_opp_select.h> #include <soc/rockchip/rockchip_system_monitor.h> +#include <soc/rockchip/rockchip_iommu.h> #include "mpp_debug.h" #include "mpp_iommu.h" @@ -44,6 +45,8 @@ #define RKVENC_MAX_DCHS_ID 4 #define RKVENC_MAX_SLICE_FIFO_LEN 256 #define RKVENC_SCLR_DONE_STA BIT(2) +#define RKVENC_WDG 0x38 +#define TIMEOUT_MS 100 #define to_rkvenc_info(info) \ container_of(info, struct rkvenc_hw_info, hw) @@ -127,6 +130,11 @@ #define INT_STA_WBUS_ERR_STA BIT(6) #define INT_STA_RBUS_ERR_STA BIT(7) #define INT_STA_WDG_STA BIT(8) + +#define INT_STA_ERROR (INT_STA_BRSP_OTSD_STA | \ + INT_STA_WBUS_ERR_STA | \ + INT_STA_RBUS_ERR_STA | \ + INT_STA_WDG_STA) #define DCHS_REG_OFFSET (0x304) #define DCHS_CLASS_OFFSET (33) @@ -294,6 +302,7 @@ #ifdef CONFIG_PM_DEVFREQ struct rockchip_opp_info opp_info; struct monitor_dev_info *mdev_info; + struct opp_table *opp_table; #endif }; @@ -1194,6 +1203,7 @@ struct rkvenc_task *task = to_rkvenc_task(mpp_task); struct rkvenc_hw_info *hw = enc->hw_info; u32 timing_en = mpp->srv->timing_en; + u32 timeout_thd; mpp_debug_enter(); @@ -1242,11 +1252,18 @@ /* init current task */ mpp->cur_task = mpp_task; + /* + * reconfig timeout threshold. + * bit0-bit23,x1024 core clk cycles + */ + timeout_thd = mpp_read(mpp, RKVENC_WDG) & 0xff000000; + timeout_thd |= TIMEOUT_MS * clk_get_rate(enc->core_clk_info.clk) / 1024000; + mpp_write(mpp, RKVENC_WDG, timeout_thd); + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); /* Flush the register before the start the device */ wmb(); - mpp_write(mpp, enc->hw_info->enc_start_base, start_val); mpp_task_run_end(mpp_task, timing_en); @@ -1256,9 +1273,9 @@ return 0; } -static void rkvenc2_read_slice_len(struct mpp_dev *mpp, struct rkvenc_task *task) +static void rkvenc2_read_slice_len(struct mpp_dev *mpp, struct rkvenc_task *task, + u32 last) { - u32 last = mpp_read_relaxed(mpp, 0x002c) & INT_STA_ENC_DONE_STA; u32 sli_num = mpp_read_relaxed(mpp, RKVENC2_REG_SLICE_NUM_BASE); union rkvenc2_slice_len_info slice_info; u32 task_id = task->mpp_task.task_id; @@ -1298,46 +1315,49 @@ struct rkvenc_hw_info *hw = enc->hw_info; struct mpp_task *mpp_task = NULL; struct rkvenc_task *task = NULL; - u32 int_clear = 1; - u32 irq_mask = 0; + u32 irq_status; int ret = IRQ_NONE; mpp_debug_enter(); - mpp->irq_status = mpp_read(mpp, hw->int_sta_base); - if (!mpp->irq_status) + irq_status = mpp_read(mpp, hw->int_sta_base); + + mpp_debug(DEBUG_IRQ_STATUS, "%s irq_status: %08x\n", + dev_name(mpp->dev), irq_status); + + if (!irq_status) return ret; + + /* clear int first */ + mpp_write(mpp, hw->int_clr_base, irq_status); + + /* + * prevent watch dog irq storm. + * The encoder did not stop working when watchdog interrupt is triggered, + * it still check timeout and trigger watch dog irq. + */ + if (irq_status & INT_STA_WDG_STA) + mpp_write(mpp, hw->int_mask_base, INT_STA_WDG_STA); if (mpp->cur_task) { mpp_task = mpp->cur_task; task = to_rkvenc_task(mpp_task); } - if (mpp->irq_status & INT_STA_ENC_DONE_STA) { - if (task) { - if (task->task_split) - rkvenc2_read_slice_len(mpp, task); + /* 1. read slice number and slice length */ + if (task && task->task_split && + (irq_status & (INT_STA_SLC_DONE_STA | INT_STA_ENC_DONE_STA))) { + mpp_time_part_diff(mpp_task); + rkvenc2_read_slice_len(mpp, task, irq_status & INT_STA_ENC_DONE_STA); + wake_up(&mpp_task->wait); + } - wake_up(&mpp_task->wait); - } + /* 2. process slice irq */ + if (irq_status & INT_STA_SLC_DONE_STA) + ret = IRQ_HANDLED; - irq_mask = INT_STA_ENC_DONE_STA; - ret = IRQ_WAKE_THREAD; - if (enc->bs_overflow) { - mpp->irq_status |= INT_STA_BSF_OFLW_STA; - enc->bs_overflow = 0; - } - } else if (mpp->irq_status & INT_STA_SLC_DONE_STA) { - if (task && task->task_split) { - mpp_time_part_diff(mpp_task); - - rkvenc2_read_slice_len(mpp, task); - wake_up(&mpp_task->wait); - } - - irq_mask = INT_STA_ENC_DONE_STA; - int_clear = 0; - } else if (mpp->irq_status & INT_STA_BSF_OFLW_STA) { + /* 3. process bitstream overflow */ + if (irq_status & INT_STA_BSF_OFLW_STA) { u32 bs_rd = mpp_read(mpp, RKVENC2_REG_ADR_BSBR); u32 bs_wr = mpp_read(mpp, RKVENC2_REG_ST_BSB); u32 bs_top = mpp_read(mpp, RKVENC2_REG_ADR_BSBT); @@ -1349,33 +1369,43 @@ bs_wr += 128; if (bs_wr >= bs_top) bs_wr = bs_bot; - /* clear int first */ - mpp_write(mpp, hw->int_clr_base, mpp->irq_status); + /* update write addr for enc continue */ mpp_write(mpp, RKVENC2_REG_ADR_BSBS, bs_wr); enc->bs_overflow = 1; - irq_mask = 0; - int_clear = 0; - ret = IRQ_HANDLED; - } else { - dev_err(mpp->dev, "found error status %08x\n", mpp->irq_status); - irq_mask = mpp->irq_status; + ret = IRQ_HANDLED; + } + + /* 4. process frame irq */ + if (irq_status & INT_STA_ENC_DONE_STA) { + mpp->irq_status = irq_status; + + if (enc->bs_overflow) { + mpp->irq_status |= INT_STA_BSF_OFLW_STA; + enc->bs_overflow = 0; + } + ret = IRQ_WAKE_THREAD; } - if (irq_mask) - mpp_write(mpp, hw->int_mask_base, irq_mask); + /* 5. process error irq */ + if (irq_status & INT_STA_ERROR) { + mpp->irq_status = irq_status; - if (int_clear) { - mpp_write(mpp, hw->int_clr_base, mpp->irq_status); - udelay(5); - mpp_write(mpp, hw->int_sta_base, 0); + dev_err(mpp->dev, "found error status %08x\n", irq_status); + + ret = IRQ_WAKE_THREAD; } mpp_debug_leave(); return ret; +} + +static int vepu540c_irq(struct mpp_dev *mpp) +{ + return rkvenc_irq(mpp); } static int rkvenc_isr(struct mpp_dev *mpp) @@ -1405,9 +1435,6 @@ task->irq_status = mpp->irq_status; rkvenc2_update_dchs(enc, task); - - mpp_debug(DEBUG_IRQ_STATUS, "%s irq_status: %08x\n", - dev_name(mpp->dev), task->irq_status); if (task->irq_status & enc->hw_info->err_mask) { atomic_inc(&mpp->reset_request); @@ -1458,7 +1485,7 @@ if (task->bs_buf) { u32 bs_size = mpp_read(mpp, 0x4064); - mpp_dma_buf_sync(task->bs_buf, 0, bs_size / 8 + task->offset_bs, + mpp_dma_buf_sync(task->bs_buf, 0, bs_size + task->offset_bs, DMA_FROM_DEVICE, true); } @@ -1785,16 +1812,19 @@ if (IS_ERR(reg_table)) return PTR_ERR(reg_table); } + enc->opp_table = reg_table; clk_table = dev_pm_opp_set_clkname(dev, "clk_core"); - if (IS_ERR(clk_table)) - return PTR_ERR(clk_table); + if (IS_ERR(clk_table)) { + ret = PTR_ERR(clk_table); + goto put_opp_reg; + } rockchip_get_opp_data(rockchip_rkvenc_of_match, &enc->opp_info); ret = rockchip_init_opp_table(dev, &enc->opp_info, "leakage", "venc"); if (ret) { dev_err(dev, "failed to init_opp_table\n"); - return ret; + goto put_opp_clk; } enc->mdev_info = rockchip_system_monitor_register(dev, &venc_mdevp); @@ -1803,6 +1833,14 @@ enc->mdev_info = NULL; } + return 0; + +put_opp_clk: + dev_pm_opp_put_clkname(enc->opp_table); +put_opp_reg: + dev_pm_opp_put_regulators(enc->opp_table); + enc->opp_table = NULL; + return ret; } @@ -1810,8 +1848,16 @@ { struct rkvenc_dev *enc = to_rkvenc_dev(mpp); - if (enc->mdev_info) + if (enc->mdev_info) { rockchip_system_monitor_unregister(enc->mdev_info); + enc->mdev_info = NULL; + } + if (enc->opp_table) { + rockchip_uninit_opp_table(mpp->dev, &enc->opp_info); + dev_pm_opp_put_clkname(enc->opp_table); + dev_pm_opp_put_regulators(enc->opp_table); + enc->opp_table = NULL; + } return 0; } @@ -1880,7 +1926,7 @@ /* safe reset */ mpp_write(mpp, hw->int_mask_base, 0x3FF); - mpp_write(mpp, hw->enc_clr_base, 0x1); + mpp_write(mpp, hw->enc_clr_base, 0x3); ret = readl_relaxed_poll_timeout(mpp->reg_base + hw->int_sta_base, rst_status, rst_status & RKVENC_SCLR_DONE_STA, @@ -2169,6 +2215,20 @@ .dump_session = rkvenc_dump_session, }; +static struct mpp_dev_ops vepu540c_dev_ops_v2 = { + .wait_result = rkvenc2_wait_result, + .alloc_task = rkvenc_alloc_task, + .run = rkvenc_run, + .irq = vepu540c_irq, + .isr = rkvenc_isr, + .finish = rkvenc_finish, + .result = rkvenc_result, + .free_task = rkvenc_free_task, + .ioctl = rkvenc_control, + .init_session = rkvenc_init_session, + .free_session = rkvenc_free_session, + .dump_session = rkvenc_dump_session, +}; static const struct mpp_dev_var rkvenc_v2_data = { .device_type = MPP_DEVICE_RKVENC, @@ -2183,7 +2243,7 @@ .hw_info = &rkvenc_540c_hw_info.hw, .trans_info = trans_rkvenc_540c, .hw_ops = &rkvenc_hw_ops, - .dev_ops = &rkvenc_dev_ops_v2, + .dev_ops = &vepu540c_dev_ops_v2, }; static const struct mpp_dev_var rkvenc_ccu_data = { @@ -2404,13 +2464,32 @@ { struct mpp_dev *mpp = (struct mpp_dev *)arg; struct rkvenc_dev *enc = to_rkvenc_dev(mpp); - struct mpp_task *mpp_task = mpp->cur_task; + struct mpp_task *mpp_task; + struct rkvenc_ccu *ccu = enc->ccu; + if (ccu) { + struct rkvenc_dev *core = NULL, *n; + + list_for_each_entry_safe(core, n, &ccu->core_list, core_link) { + if (core->mpp.iommu_info && + (&core->mpp.iommu_info->pdev->dev == iommu_dev)) { + mpp = &core->mpp; + break; + } + } + } + mpp_task = mpp->cur_task; dev_info(mpp->dev, "core %d page fault found dchs %08x\n", mpp->core_id, mpp_read_relaxed(&enc->mpp, DCHS_REG_OFFSET)); if (mpp_task) mpp_task_dump_mem_region(mpp, mpp_task); + + /* + * Mask iommu irq, in order for iommu not repeatedly trigger pagefault. + * Until the pagefault task finish by hw timeout. + */ + rockchip_iommu_mask_irq(mpp->dev); return 0; } @@ -2455,7 +2534,7 @@ ret = devm_request_threaded_irq(dev, mpp->irq, mpp_dev_irq, mpp_dev_isr_sched, - IRQF_SHARED, + IRQF_ONESHOT, dev_name(dev), mpp); if (ret) { dev_err(dev, "register interrupter runtime failed\n"); -- Gitblit v1.6.2