media: rockchip: ispp: fbc error handle

Change-Id: I9c303ef76831ed45962991a8d7d6e8b67fce78f8
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2021-08-04 16:35:41 +08:00
committed by Tao Huang
parent 1427b10e9f
commit 4beac95035
4 changed files with 116 additions and 5 deletions

View File

@@ -107,6 +107,7 @@ extern bool rkispp_reg_withstream;
extern char rkispp_reg_withstream_video_name[RKISPP_VIDEO_NAME_LEN];
extern unsigned int rkispp_debug_reg;
extern struct platform_driver rkispp_plat_drv;
extern char rkispp_dump_path[128];
void rkispp_write(struct rkispp_device *dev, u32 reg, u32 val);
void rkispp_set_bits(struct rkispp_device *dev, u32 reg, u32 mask, u32 val);

View File

@@ -64,6 +64,10 @@ static unsigned int rkispp_wait_line;
module_param_named(wait_line, rkispp_wait_line, uint, 0644);
MODULE_PARM_DESC(wait_line, "rkispp wait line to buf done early");
char rkispp_dump_path[128];
module_param_string(dump_path, rkispp_dump_path, sizeof(rkispp_dump_path), 0644);
MODULE_PARM_DESC(dump_path, "rkispp dump debug file path");
void rkispp_set_clk_rate(struct clk *clk, unsigned long rate)
{
if (rkispp_clk_dbg)

View File

@@ -2269,6 +2269,89 @@ unreg:
return ret;
}
static void dump_file(struct rkispp_device *dev, u32 restart_module)
{
struct rkispp_stream_vdev *vdev = &dev->stream_vdev;
void __iomem *base = dev->hw_dev->base_addr;
struct rkispp_isp_buf_pool *buf;
struct rkispp_dummy_buffer *dummy;
struct file *fp = NULL;
char file[160], reg[48];
int i;
snprintf(file, sizeof(file), "%s/%s%d.reg",
rkispp_dump_path, DRIVER_NAME, dev->dev_id);
fp = filp_open(file, O_RDWR | O_CREAT, 0644);
if (IS_ERR(fp)) {
v4l2_err(&dev->v4l2_dev, "%s open %s fail\n", __func__, file);
return;
}
for (i = 0; i < 0x1000; i += 16) {
snprintf(reg, sizeof(reg), "ffb6%04x: %08x %08x %08x %08x\n",
i, readl(base + i), readl(base + i + 4),
readl(base + i + 8), readl(base + i + 12));
kernel_write(fp, reg, strlen(reg), &fp->f_pos);
}
filp_close(fp, NULL);
if (restart_module & MONITOR_TNR) {
if (vdev->tnr.cur_rd) {
snprintf(file, sizeof(file), "%s/%s%d_tnr_cur.fbc",
rkispp_dump_path, DRIVER_NAME, dev->dev_id);
fp = filp_open(file, O_RDWR | O_CREAT, 0644);
if (IS_ERR(fp)) {
v4l2_err(&dev->v4l2_dev,
"%s open %s fail\n", __func__, file);
return;
}
buf = get_pool_buf(dev, vdev->tnr.cur_rd);
kernel_write(fp, buf->vaddr[0], vdev->tnr.cur_rd->dbuf[0]->size, &fp->f_pos);
filp_close(fp, NULL);
v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev,
"dump tnr cur_rd dma:0x%x vaddr:%p\n",
buf->dma[0], buf->vaddr[0]);
}
if (vdev->tnr.nxt_rd && vdev->tnr.nxt_rd != vdev->tnr.cur_rd) {
snprintf(file, sizeof(file), "%s/%s%d_tnr_nxt.fbc",
rkispp_dump_path, DRIVER_NAME, dev->dev_id);
fp = filp_open(file, O_RDWR | O_CREAT, 0644);
if (IS_ERR(fp)) {
v4l2_err(&dev->v4l2_dev,
"%s open %s fail\n", __func__, file);
return;
}
buf = get_pool_buf(dev, vdev->tnr.nxt_rd);
kernel_write(fp, buf->vaddr[0], vdev->tnr.nxt_rd->dbuf[0]->size, &fp->f_pos);
filp_close(fp, NULL);
v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev,
"dump tnr nxt_rd dma:0x%x vaddr:%p\n",
buf->dma[0], buf->vaddr[0]);
}
}
if (!(restart_module & MONITOR_FEC)) {
for (i = 0; i < RKISPP_BUF_MAX; i++) {
dummy = &vdev->tnr.buf.wr[i][0];
if (!dummy->mem_priv)
break;
snprintf(file, sizeof(file), "%s/%s%d_iir%d.fbc",
rkispp_dump_path, DRIVER_NAME, dev->dev_id, i);
fp = filp_open(file, O_RDWR | O_CREAT, 0644);
if (IS_ERR(fp)) {
v4l2_err(&dev->v4l2_dev,
"%s open %s fail\n", __func__, file);
return;
}
kernel_write(fp, dummy->vaddr, dummy->size, &fp->f_pos);
filp_close(fp, NULL);
v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev,
"dump tnr wr dma:0x%x vaddr:%p\n",
dummy->dma_addr, dummy->vaddr);
}
}
}
static void restart_module(struct rkispp_device *dev)
{
struct rkispp_monitor *monitor = &dev->stream_vdev.monitor;
@@ -2291,6 +2374,21 @@ static void restart_module(struct rkispp_device *dev)
monitor->is_restart = false;
goto end;
}
if (rkispp_dump_path[0] == '/')
dump_file(dev, monitor->restart_module);
if (monitor->restart_module & MONITOR_TNR && monitor->tnr.is_err) {
rkispp_set_bits(dev, RKISPP_TNR_CTRL, 0, SW_TNR_1ST_FRM);
monitor->tnr.is_err = false;
}
if (monitor->restart_module & MONITOR_NR && monitor->nr.is_err) {
rkispp_write(dev, RKISPP_NR_ADDR_BASE_Y,
readl(base + RKISPP_NR_ADDR_BASE_Y_SHD));
rkispp_write(dev, RKISPP_NR_ADDR_BASE_UV,
readl(base + RKISPP_NR_ADDR_BASE_UV_SHD));
monitor->nr.is_err = false;
}
rkispp_soft_reset(dev->hw_dev);
rkispp_update_regs(dev, RKISPP_CTRL_QUICK, RKISPP_FEC_CROP);
writel(ALL_FORCE_UPD, base + RKISPP_CTRL_UPDATE);
@@ -2797,6 +2895,7 @@ static void nr_work_event(struct rkispp_device *dev,
if (monitor->is_en) {
monitor->nr.time = vdev->nr.dbg.interval / 1000 / 1000;
monitor->monitoring_module |= MONITOR_NR;
monitor->nr.is_err = false;
if (!completion_done(&monitor->nr.cmpl))
complete(&monitor->nr.cmpl);
}
@@ -3107,6 +3206,7 @@ static void tnr_work_event(struct rkispp_device *dev,
if (monitor->is_en) {
monitor->tnr.time = vdev->tnr.dbg.interval / 1000 / 1000;
monitor->monitoring_module |= MONITOR_TNR;
monitor->tnr.is_err = false;
if (!completion_done(&monitor->tnr.cmpl))
complete(&monitor->tnr.cmpl);
}
@@ -3302,9 +3402,10 @@ void rkispp_isr(u32 mis_val, struct rkispp_device *dev)
{
struct rkispp_stream_vdev *vdev;
struct rkispp_stream *stream;
u32 i, err_mask = NR_LOST_ERR | TNR_LOST_ERR |
FBCH_EMPTY_NR | FBCH_EMPTY_TNR | FBCD_DEC_ERR_NR |
FBCD_DEC_ERR_TNR | BUS_ERR_NR | BUS_ERR_TNR;
u32 i, nr_err = NR_LOST_ERR | FBCH_EMPTY_NR |
FBCD_DEC_ERR_NR | BUS_ERR_NR;
u32 tnr_err = TNR_LOST_ERR | FBCH_EMPTY_TNR |
FBCD_DEC_ERR_TNR | BUS_ERR_TNR;
u64 ns = ktime_get_ns();
v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev,
@@ -3312,7 +3413,11 @@ void rkispp_isr(u32 mis_val, struct rkispp_device *dev)
vdev = &dev->stream_vdev;
dev->isr_cnt++;
if (mis_val & err_mask) {
if (mis_val & (tnr_err | nr_err)) {
if (mis_val & tnr_err)
vdev->monitor.tnr.is_err = true;
if (mis_val & nr_err)
vdev->monitor.nr.is_err = true;
dev->isr_err_cnt++;
v4l2_err(&dev->v4l2_dev,
"ispp err:0x%x, seq:%d\n",
@@ -3348,7 +3453,7 @@ void rkispp_isr(u32 mis_val, struct rkispp_device *dev)
(dev->isp_mode & ISP_ISPP_QUICK))
++dev->ispp_sdev.frm_sync_seq;
if (mis_val & TNR_INT)
if (mis_val & TNR_INT && !dev->hw_dev->is_first)
if (rkispp_read(dev, RKISPP_TNR_CTRL) & SW_TNR_1ST_FRM)
rkispp_clear_bits(dev, RKISPP_TNR_CTRL, SW_TNR_1ST_FRM);

View File

@@ -184,6 +184,7 @@ struct module_monitor {
struct completion cmpl;
u16 time;
u8 module;
bool is_err;
};
struct rkispp_monitor {