From 6778948f9de86c3cfaf36725a7c87dcff9ba247f Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 08:20:59 +0000
Subject: [PATCH] kernel_5.10 no rt
---
kernel/drivers/video/rockchip/mpp/mpp_rkvenc2.c | 171 +++++++++++++++++++++++++++++++++++---------------------
1 files changed, 106 insertions(+), 65 deletions(-)
diff --git a/kernel/drivers/video/rockchip/mpp/mpp_rkvenc2.c b/kernel/drivers/video/rockchip/mpp/mpp_rkvenc2.c
index 2dc50bb..5bd7054 100644
--- a/kernel/drivers/video/rockchip/mpp/mpp_rkvenc2.c
+++ b/kernel/drivers/video/rockchip/mpp/mpp_rkvenc2.c
@@ -178,6 +178,12 @@
#define RKVENC2_REG_SLICE_NUM_BASE (0x4034)
#define RKVENC2_REG_SLICE_LEN_BASE (0x4038)
+#define RKVENC2_REG_ST_BSB (0x402c)
+#define RKVENC2_REG_ADR_BSBT (0x2b0)
+#define RKVENC2_REG_ADR_BSBB (0x2b4)
+#define RKVENC2_REG_ADR_BSBR (0x2b8)
+#define RKVENC2_REG_ADR_BSBS (0x2bc)
+
union rkvenc2_slice_len_info {
u32 val;
@@ -282,6 +288,8 @@
dma_addr_t sram_iova;
u32 sram_enabled;
struct page *rcb_page;
+
+ u32 bs_overflow;
#ifdef CONFIG_PM_DEVFREQ
struct rockchip_opp_info opp_info;
@@ -1290,6 +1298,8 @@
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;
int ret = IRQ_NONE;
mpp_debug_enter();
@@ -1311,12 +1321,12 @@
wake_up(&mpp_task->wait);
}
- mpp_write(mpp, hw->int_mask_base, 0x100);
- mpp_write(mpp, hw->int_clr_base, 0xffffffff);
- udelay(5);
- mpp_write(mpp, hw->int_sta_base, 0);
-
+ 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);
@@ -1325,7 +1335,42 @@
wake_up(&mpp_task->wait);
}
- mpp_write(mpp, hw->int_clr_base, INT_STA_SLC_DONE_STA);
+ irq_mask = INT_STA_ENC_DONE_STA;
+ int_clear = 0;
+ } else if (mpp->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);
+ u32 bs_bot = mpp_read(mpp, RKVENC2_REG_ADR_BSBB);
+
+ if (mpp_task)
+ dev_err(mpp->dev, "task %d found bitstream overflow [%#08x %#08x %#08x %#08x]\n",
+ mpp_task->task_index, bs_top, bs_bot, bs_wr, bs_rd);
+ 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_WAKE_THREAD;
+ }
+
+ if (irq_mask)
+ mpp_write(mpp, hw->int_mask_base, irq_mask);
+
+ if (int_clear) {
+ mpp_write(mpp, hw->int_clr_base, mpp->irq_status);
+ udelay(5);
+ mpp_write(mpp, hw->int_sta_base, 0);
}
mpp_debug_leave();
@@ -2004,38 +2049,31 @@
if (!enc_task->task_split || enc_task->task_split_done) {
task_done_ret:
- ret = wait_event_timeout(task->wait,
- test_bit(TASK_STATE_DONE, &task->state),
- msecs_to_jiffies(RKVENC2_WAIT_TIMEOUT_DELAY));
+ ret = wait_event_interruptible(task->wait, test_bit(TASK_STATE_DONE, &task->state));
+ if (ret == -ERESTARTSYS)
+ mpp_err("wait task break by signal in normal mode\n");
- if (ret > 0)
- return rkvenc2_task_default_process(mpp, task);
+ return rkvenc2_task_default_process(mpp, task);
- rkvenc2_task_timeout_process(session, task);
- return ret;
}
/* not slice return just wait all slice length */
if (!req) {
do {
- ret = wait_event_timeout(task->wait,
- kfifo_out(&enc_task->slice_info, &slice_info, 1),
- msecs_to_jiffies(RKVENC2_WORK_TIMEOUT_DELAY));
- if (ret > 0) {
- mpp_dbg_slice("task %d rd %3d len %d %s\n",
- task_id, enc_task->slice_rd_cnt, slice_info.slice_len,
- slice_info.last ? "last" : "");
-
- enc_task->slice_rd_cnt++;
-
- if (slice_info.last)
- goto task_done_ret;
-
- continue;
+ ret = wait_event_interruptible(task->wait, kfifo_out(&enc_task->slice_info,
+ &slice_info, 1));
+ if (ret == -ERESTARTSYS) {
+ mpp_err("wait task break by signal in slice all mode\n");
+ return 0;
}
+ mpp_dbg_slice("task %d rd %3d len %d %s\n",
+ task_id, enc_task->slice_rd_cnt, slice_info.slice_len,
+ slice_info.last ? "last" : "");
- rkvenc2_task_timeout_process(session, task);
- return ret;
+ enc_task->slice_rd_cnt++;
+
+ if (slice_info.last)
+ goto task_done_ret;
} while (1);
}
@@ -2050,40 +2088,41 @@
/* handle slice mode poll return */
do {
- ret = wait_event_timeout(task->wait,
- kfifo_out(&enc_task->slice_info, &slice_info, 1),
- msecs_to_jiffies(RKVENC2_WORK_TIMEOUT_DELAY));
- if (ret > 0) {
- mpp_dbg_slice("core %d task %d rd %3d len %d %s\n", task_id,
- mpp->core_id, enc_task->slice_rd_cnt, slice_info.slice_len,
- slice_info.last ? "last" : "");
- enc_task->slice_rd_cnt++;
- if (cfg.count_ret < cfg.count_max) {
- struct rkvenc_poll_slice_cfg __user *ucfg =
- (struct rkvenc_poll_slice_cfg __user *)(req->data);
- u32 __user *dst = (u32 __user *)(ucfg + 1);
-
- /* Do NOT return here when put_user error. Just continue */
- if (put_user(slice_info.val, dst + cfg.count_ret))
- ret = -EFAULT;
-
- cfg.count_ret++;
- if (put_user(cfg.count_ret, &ucfg->count_ret))
- ret = -EFAULT;
- }
-
- if (slice_info.last) {
- enc_task->task_split_done = 1;
- goto task_done_ret;
- }
-
- if (cfg.count_ret >= cfg.count_max)
- return 0;
-
- if (ret < 0)
- return ret;
+ ret = wait_event_interruptible(task->wait, kfifo_out(&enc_task->slice_info,
+ &slice_info, 1));
+ if (ret == -ERESTARTSYS) {
+ mpp_err("wait task break by signal in slice one mode\n");
+ return 0;
}
- } while (ret > 0);
+ mpp_dbg_slice("core %d task %d rd %3d len %d %s\n", task_id,
+ mpp->core_id, enc_task->slice_rd_cnt, slice_info.slice_len,
+ slice_info.last ? "last" : "");
+ enc_task->slice_rd_cnt++;
+ if (cfg.count_ret < cfg.count_max) {
+ struct rkvenc_poll_slice_cfg __user *ucfg =
+ (struct rkvenc_poll_slice_cfg __user *)(req->data);
+ u32 __user *dst = (u32 __user *)(ucfg + 1);
+
+ /* Do NOT return here when put_user error. Just continue */
+ if (put_user(slice_info.val, dst + cfg.count_ret))
+ ret = -EFAULT;
+
+ cfg.count_ret++;
+ if (put_user(cfg.count_ret, &ucfg->count_ret))
+ ret = -EFAULT;
+ }
+
+ if (slice_info.last) {
+ enc_task->task_split_done = 1;
+ goto task_done_ret;
+ }
+
+ if (cfg.count_ret >= cfg.count_max)
+ return 0;
+
+ if (ret < 0)
+ return ret;
+ } while (!ret);
rkvenc2_task_timeout_process(session, task);
@@ -2243,8 +2282,10 @@
ccu_info = ccu->main_core->iommu_info;
cur_info = enc->mpp.iommu_info;
- cur_info->domain = ccu_info->domain;
- cur_info->rw_sem = ccu_info->rw_sem;
+ if (cur_info) {
+ cur_info->domain = ccu_info->domain;
+ cur_info->rw_sem = ccu_info->rw_sem;
+ }
mpp_iommu_attach(cur_info);
/* increase main core message capacity */
@@ -2422,7 +2463,7 @@
}
mpp->session_max_buffers = RKVENC_SESSION_MAX_BUFFERS;
enc->hw_info = to_rkvenc_info(mpp->var->hw_info);
- mpp->iommu_info->hdl = rkvenc2_iommu_fault_handle;
+ mpp->fault_handler = rkvenc2_iommu_fault_handle;
rkvenc_procfs_init(mpp);
rkvenc_procfs_ccu_init(mpp);
--
Gitblit v1.6.2