From 584d1f62df4f6f2a1d7d71708a7b68b52d3fccca Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Wed, 4 Aug 2021 16:35:41 +0800 Subject: [PATCH] media: rockchip: ispp: fbc error handle Change-Id: I9c303ef76831ed45962991a8d7d6e8b67fce78f8 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/ispp/common.h | 1 + drivers/media/platform/rockchip/ispp/dev.c | 4 + drivers/media/platform/rockchip/ispp/stream.c | 115 +++++++++++++++++- drivers/media/platform/rockchip/ispp/stream.h | 1 + 4 files changed, 116 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/rockchip/ispp/common.h b/drivers/media/platform/rockchip/ispp/common.h index 94fc3bccf56d..716293976fa6 100644 --- a/drivers/media/platform/rockchip/ispp/common.h +++ b/drivers/media/platform/rockchip/ispp/common.h @@ -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); diff --git a/drivers/media/platform/rockchip/ispp/dev.c b/drivers/media/platform/rockchip/ispp/dev.c index 4eebe1f0d5e1..1182c83da912 100644 --- a/drivers/media/platform/rockchip/ispp/dev.c +++ b/drivers/media/platform/rockchip/ispp/dev.c @@ -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) diff --git a/drivers/media/platform/rockchip/ispp/stream.c b/drivers/media/platform/rockchip/ispp/stream.c index b3e4385e88f1..4c2fdecef968 100644 --- a/drivers/media/platform/rockchip/ispp/stream.c +++ b/drivers/media/platform/rockchip/ispp/stream.c @@ -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); diff --git a/drivers/media/platform/rockchip/ispp/stream.h b/drivers/media/platform/rockchip/ispp/stream.h index 07c981a5ef6e..728e55497d7d 100644 --- a/drivers/media/platform/rockchip/ispp/stream.h +++ b/drivers/media/platform/rockchip/ispp/stream.h @@ -184,6 +184,7 @@ struct module_monitor { struct completion cmpl; u16 time; u8 module; + bool is_err; }; struct rkispp_monitor {