From fccdeb122756b59b9b88dbd4c0fa6625212bdb74 Mon Sep 17 00:00:00 2001 From: Hu Kejun Date: Tue, 15 Apr 2025 11:06:17 +0800 Subject: [PATCH 1/5] media: rockchip: aiisp: modify for airms algo Signed-off-by: Hu Kejun Change-Id: I68bf45d2d83cbd45ce2f955050ece955931ed6d1 --- drivers/media/platform/rockchip/aiisp/aiisp.c | 253 ++++++++++++++++-- drivers/media/platform/rockchip/aiisp/aiisp.h | 18 +- drivers/media/platform/rockchip/aiisp/hw.c | 4 +- .../media/platform/rockchip/aiisp/procfs.c | 27 +- include/uapi/linux/rk-aiisp-config.h | 44 ++- 5 files changed, 313 insertions(+), 33 deletions(-) diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.c b/drivers/media/platform/rockchip/aiisp/aiisp.c index 7c16cbd33e4e..8ae4ffbe429a 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.c +++ b/drivers/media/platform/rockchip/aiisp/aiisp.c @@ -102,6 +102,8 @@ static int mi_chns_tab[2][7] = { {15, 1, 1, 1, 1, 1, 1} }; +static int rkaiisp_free_airms_pool(struct rkaiisp_device *aidev); + static void rkaiisp_update_regs(struct rkaiisp_device *aidev, u32 start, u32 end) { struct rkaiisp_hw_dev *hw_dev = aidev->hw_dev; @@ -190,6 +192,40 @@ static void rkaiisp_dump_list_reg(struct rkaiisp_device *aidev) rkaiisp_dumpreg(aidev, AIISP_MI_WR_CTRL, AIISP_MI_CHN0_WR_STRIDE); } +static int rkaiisp_buf_get_fd(struct rkaiisp_device *aidev, + struct rkaiisp_dummy_buffer *buf, bool try_fd) +{ + const struct vb2_mem_ops *g_ops = aidev->hw_dev->mem_ops; + bool new_dbuf = false; + + if (!buf || !buf->mem_priv) + return -EINVAL; + if (try_fd) { + buf->is_need_dbuf = true; + buf->is_need_dmafd = true; + } + + if (buf->is_need_dbuf && !buf->dmabuf) { + buf->dmabuf = g_ops->get_dmabuf(&buf->vb, buf->mem_priv, O_RDWR); + new_dbuf = true; + } + + if (buf->is_need_dmafd) { + buf->dma_fd = dma_buf_fd(buf->dmabuf, O_CLOEXEC); + if (buf->dma_fd < 0) { + if (new_dbuf) { + dma_buf_put(buf->dmabuf); + buf->dmabuf = NULL; + buf->is_need_dbuf = false; + } + buf->is_need_dmafd = false; + return -EINVAL; + } + get_dma_buf(buf->dmabuf); + } + return 0; +} + #if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE static void rkaiisp_init_dummy_vb2(struct rkaiisp_device *dev, struct rkaiisp_dummy_buffer *buf) @@ -231,8 +267,16 @@ static int rkaiisp_allow_buffer(struct rkaiisp_device *aidev, sg_tbl = (struct sg_table *)mem_ops->cookie(&buf->vb, mem_priv); buf->dma_addr = sg_dma_address(sg_tbl->sgl); mem_ops->prepare(mem_priv); - - buf->vaddr = mem_ops->vaddr(&buf->vb, mem_priv); + if (buf->is_need_vaddr) + buf->vaddr = mem_ops->vaddr(&buf->vb, mem_priv); + ret = rkaiisp_buf_get_fd(aidev, buf, false); + if (ret < 0) { + mem_ops->put(buf->mem_priv); + buf->mem_priv = NULL; + buf->vaddr = NULL; + buf->size = 0; + goto err; + } v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "%s buf:%pad size:%d\n", __func__, &buf->dma_addr, buf->size); @@ -271,8 +315,8 @@ static int rkaiisp_allow_buffer(struct rkaiisp_device *aidev, sg_tbl = (struct sg_table *)mem_ops->cookie(mem_priv); buf->dma_addr = sg_dma_address(sg_tbl->sgl); mem_ops->prepare(mem_priv); - - buf->vaddr = mem_ops->vaddr(mem_priv); + if (buf->is_need_vaddr) + buf->vaddr = mem_ops->vaddr(mem_priv); v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "%s buf:%pad size:%d\n", __func__, &buf->dma_addr, buf->size); @@ -294,10 +338,15 @@ static void rkaiisp_free_buffer(struct rkaiisp_device *aidev, "%s buf:%pad size:%d\n", __func__, &buf->dma_addr, buf->size); + if (buf->dmabuf) + dma_buf_put(buf->dmabuf); mem_ops->put(buf->mem_priv); buf->size = 0; buf->vaddr = NULL; + buf->dmabuf = NULL; buf->mem_priv = NULL; + buf->is_need_dbuf = false; + buf->is_need_dmafd = false; } } @@ -327,6 +376,9 @@ static int rkaiisp_free_pool(struct rkaiisp_device *aidev) struct rkaiisp_ispbuf_info *ispbuf = &aidev->ispbuf; int i; + if (aidev->exealgo == AIRMS) + return rkaiisp_free_airms_pool(aidev); + if (!aidev->init_buf) return 0; @@ -391,6 +443,9 @@ static void rkaiisp_calc_outbuf_size(struct rkaiisp_device *aidev, u32 raw_hgt, { int i; + if (aidev->model_mode == REMOSAIC_MODE) + return; + if (aidev->model_mode == SINGLEX2_MODE) { for (i = 0; i < RKAIISP_PYRAMID_LAYER_NUM; i++) { if (i == 0) { @@ -485,6 +540,12 @@ static int rkaiisp_init_pool(struct rkaiisp_device *aidev, struct rkaiisp_ispbuf stride = ((ispbuf->iir_width + 1) / 2 * 15 * 11 + 7) >> 3; aidev->temp_buf[0].size = stride * (ispbuf->iir_height + 1) / 2; aidev->temp_buf[1].size = aidev->temp_buf[0].size; + aidev->temp_buf[0].is_need_vaddr = false; + aidev->temp_buf[0].is_need_dbuf = false; + aidev->temp_buf[0].is_need_dmafd = false; + aidev->temp_buf[1].is_need_vaddr = false; + aidev->temp_buf[1].is_need_dbuf = false; + aidev->temp_buf[1].is_need_dmafd = false; ret = rkaiisp_allow_buffer(aidev, &aidev->temp_buf[0]); ret |= rkaiisp_allow_buffer(aidev, &aidev->temp_buf[1]); if (ret) @@ -498,11 +559,88 @@ static int rkaiisp_init_pool(struct rkaiisp_device *aidev, struct rkaiisp_ispbuf return ret; } -int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, struct rkisp_aiisp_st *idxbuf) +static int rkaiisp_free_airms_pool(struct rkaiisp_device *aidev) +{ + int i; + + if (!aidev->init_buf) + return 0; + + for (i = 0; i < aidev->rmsbuf.inbuf_num; i++) + rkaiisp_free_buffer(aidev, &aidev->rms_inbuf[i]); + + for (i = 0; i < aidev->rmsbuf.outbuf_num; i++) + rkaiisp_free_buffer(aidev, &aidev->rms_outbuf[i]); + + rkaiisp_free_buffer(aidev, &aidev->sigma_buf); + rkaiisp_free_buffer(aidev, &aidev->narmap_buf); + + aidev->init_buf = false; + v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, + "free buf poll\n"); + return 0; +} + +static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_rmsbuf_info *rmsbuf) +{ + int i, ret = 0; + u32 size; + + size = rmsbuf->image_width * rmsbuf->image_height * 2; + rmsbuf->inbuf_num = RKAIISP_MIN(rmsbuf->inbuf_num, RKAIISP_AIRMS_BUF_MAXCNT); + for (i = 0; i < rmsbuf->inbuf_num; i++) { + aidev->rms_inbuf[i].size = size; + aidev->rms_inbuf[i].is_need_vaddr = false; + aidev->rms_inbuf[i].is_need_dbuf = true; + aidev->rms_inbuf[i].is_need_dmafd = true; + ret = rkaiisp_allow_buffer(aidev, &aidev->rms_inbuf[i]); + if (ret) { + rkaiisp_free_airms_pool(aidev); + v4l2_err(&aidev->v4l2_dev, "alloc buf failed: %d\n", ret); + return -EINVAL; + } + rmsbuf->inbuf_fd[i] = aidev->rms_inbuf[i].dma_fd; + } + + rmsbuf->outbuf_num = RKAIISP_MIN(rmsbuf->outbuf_num, RKAIISP_AIRMS_BUF_MAXCNT); + for (i = 0; i < rmsbuf->outbuf_num; i++) { + aidev->rms_outbuf[i].size = size; + aidev->rms_outbuf[i].is_need_vaddr = false; + aidev->rms_outbuf[i].is_need_dbuf = true; + aidev->rms_outbuf[i].is_need_dmafd = true; + ret = rkaiisp_allow_buffer(aidev, &aidev->rms_outbuf[i]); + if (ret) { + rkaiisp_free_airms_pool(aidev); + v4l2_err(&aidev->v4l2_dev, "alloc buf failed: %d\n", ret); + return -EINVAL; + } + rmsbuf->outbuf_fd[i] = aidev->rms_outbuf[i].dma_fd; + } + + aidev->sigma_buf.size = rmsbuf->sigma_width * rmsbuf->sigma_height; + aidev->sigma_buf.is_need_vaddr = false; + aidev->sigma_buf.is_need_dbuf = false; + aidev->sigma_buf.is_need_dmafd = false; + rkaiisp_allow_buffer(aidev, &aidev->sigma_buf); + aidev->narmap_buf.size = rmsbuf->narmap_width * rmsbuf->narmap_height; + aidev->narmap_buf.is_need_vaddr = false; + aidev->narmap_buf.is_need_dbuf = false; + aidev->narmap_buf.is_need_dmafd = false; + rkaiisp_allow_buffer(aidev, &aidev->narmap_buf); + + aidev->rmsbuf = *rmsbuf; + aidev->init_buf = true; + + v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "init buf poll\n"); + return ret; +} + +int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf *idxbuf) { struct kfifo *fifo = &aidev->idxbuf_kfifo; struct rkaiisp_hw_dev *hw_dev = aidev->hw_dev; unsigned long flags = 0; + int sequence = 0; int ret = 0; spin_lock_irqsave(&hw_dev->hw_lock, flags); @@ -514,12 +652,17 @@ int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, struct rkisp_aiisp_st *id } if (!kfifo_is_full(fifo)) - kfifo_in(fifo, idxbuf, sizeof(struct rkisp_aiisp_st)); + kfifo_in(fifo, idxbuf, sizeof(union rkaiisp_queue_buf)); else v4l2_err(&aidev->v4l2_dev, "fifo is full\n"); + if (aidev->exealgo == AIBNR) + sequence = idxbuf->aibnr_st.sequence; + else if (aidev->exealgo == AIRMS) + sequence = idxbuf->airms_st.sequence; + v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "idxbuf fifo in: %d\n", idxbuf->sequence); + "idxbuf fifo in: %d\n", sequence); if (hw_dev->is_idle) { hw_dev->cur_dev_id = aidev->dev_id; @@ -854,13 +997,15 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, struct rkaiisp_model_cfg *model_cfg, u32 run_idx) { struct rkaiisp_ispbuf_info *ispbuf = &aidev->ispbuf; + struct rkaiisp_rmsbuf_info *rmsbuf = &aidev->rmsbuf; struct rkaiisp_dummy_buffer *vpsl_buf; dma_addr_t dma_addr; u32 width, height; u32 sig_width = 0; + int buffer_index; int i; - vpsl_buf = &aidev->vpslbuf[aidev->curr_idxbuf.vpsl_index]; + vpsl_buf = &aidev->vpslbuf[aidev->curr_idxbuf.aibnr_st.vpsl_index]; for (i = 0; i < 7; i++) { if (model_cfg->sw_mi_chn_en[i] == 0) continue; @@ -871,7 +1016,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, width = CEIL_BY(width * 9 / 4, 16); width = width >> 1; height = ispbuf->iir_height; - dma_addr = aidev->iirbuf[aidev->curr_idxbuf.iir_index].dma_addr; + dma_addr = aidev->iirbuf[aidev->curr_idxbuf.aibnr_st.iir_index].dma_addr; break; case VPSL_YRAW_CHN0: width = ispbuf->raw_width[0]; @@ -936,7 +1081,8 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, case ISP_AIPRE_NARMAP: width = ispbuf->narmap_width; height = ispbuf->narmap_height; - dma_addr = aidev->aiprebuf[aidev->curr_idxbuf.aipre_gain_index].dma_addr; + buffer_index = aidev->curr_idxbuf.aibnr_st.aipre_gain_index; + dma_addr = aidev->aiprebuf[buffer_index].dma_addr; break; case AIISP_LAST_OUT: if (aidev->model_mode == COMBO_MODE) { @@ -948,6 +1094,22 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, } dma_addr = aidev->temp_buf[aidev->outbuf_idx].dma_addr; break; + case VICAP_BAYER_RAW: + width = rmsbuf->image_width; + height = rmsbuf->image_height; + dma_addr = aidev->rms_inbuf[aidev->curr_idxbuf.airms_st.inbuf_idx].dma_addr; + break; + case ALLZERO_SIGMA: + width = rmsbuf->sigma_width; + height = rmsbuf->sigma_height; + dma_addr = aidev->sigma_buf.dma_addr; + sig_width = width; + break; + case ALLZERO_NARMAP: + width = rmsbuf->narmap_width; + height = rmsbuf->narmap_height; + dma_addr = aidev->narmap_buf.dma_addr; + break; default: width = 0; height = 0; @@ -982,10 +1144,17 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) u32 iir_stride; u32 sig_width; dma_addr_t dma_addr; + int buffer_index; + int sequence = 0; + + if (aidev->exealgo == AIBNR) + sequence = aidev->curr_idxbuf.aibnr_st.sequence; + else if (aidev->exealgo == AIRMS) + sequence = aidev->curr_idxbuf.airms_st.sequence; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "run frame id: %d, run_idx: %d\n", - aidev->curr_idxbuf.sequence, run_idx); + sequence, run_idx); cur_params = (struct rkaiisp_params *)aidev->cur_params->vaddr[0]; model_cfg = &cur_params->model_cfg[run_idx]; @@ -993,7 +1162,15 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) lastlv = model_cfg->sw_aiisp_level_num - 1; lv_mode = model_cfg->sw_aiisp_lv_mode[lastlv]; out_chns = channels_lut[model_cfg->sw_aiisp_mode][lv_mode]; - if (aidev->model_mode == SINGLEX2_MODE) { + if (aidev->model_mode == REMOSAIC_MODE) { + sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); + + dma_addr = aidev->rms_outbuf[aidev->curr_idxbuf.airms_st.outbuf_idx].dma_addr; + rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, dma_addr, false); + + rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); + rkaiisp_determine_size(aidev, model_cfg); + } else if (aidev->model_mode == SINGLEX2_MODE) { if (run_idx == 0) { sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); @@ -1017,7 +1194,8 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) } else { sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); - dma_addr = aidev->aiispbuf[aidev->curr_idxbuf.aiisp_index].dma_addr; + buffer_index = aidev->curr_idxbuf.aibnr_st.aiisp_index; + dma_addr = aidev->aiispbuf[buffer_index].dma_addr; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, dma_addr, false); rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); @@ -1055,7 +1233,8 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) } else { rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); - dma_addr = aidev->aiispbuf[aidev->curr_idxbuf.aiisp_index].dma_addr; + buffer_index = aidev->curr_idxbuf.aibnr_st.aiisp_index; + dma_addr = aidev->aiispbuf[buffer_index].dma_addr; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, dma_addr, false); rkaiisp_gen_slice_param(aidev, model_cfg, ispbuf->sig_width[0]); @@ -1115,8 +1294,9 @@ static int rkaiisp_update_buf(struct rkaiisp_device *aidev) { struct kfifo *fifo = &aidev->idxbuf_kfifo; struct rkaiisp_hw_dev *hw_dev = aidev->hw_dev; - struct rkisp_aiisp_st idxbuf = {0}; + union rkaiisp_queue_buf idxbuf = {0}; unsigned long flags = 0; + int sequence = 0; int ret = 0; spin_lock_irqsave(&hw_dev->hw_lock, flags); @@ -1127,8 +1307,13 @@ static int rkaiisp_update_buf(struct rkaiisp_device *aidev) } else { ret = 0; aidev->curr_idxbuf = idxbuf; + if (aidev->exealgo == AIBNR) + sequence = aidev->curr_idxbuf.aibnr_st.sequence; + else if (aidev->exealgo == AIRMS) + sequence = aidev->curr_idxbuf.airms_st.sequence; + v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "idxbuf fifo out: %d\n", idxbuf.sequence); + "idxbuf fifo out: %d\n", sequence); } spin_unlock_irqrestore(&hw_dev->hw_lock, flags); @@ -1214,10 +1399,16 @@ static void rkaiisp_get_new_iqparam(struct rkaiisp_device *aidev) void rkaiisp_trigger(struct rkaiisp_device *aidev) { struct rkaiisp_ispbuf_info *ispbuf = &aidev->ispbuf; + int sequence = 0; + + if (aidev->exealgo == AIBNR) + sequence = aidev->curr_idxbuf.aibnr_st.sequence; + else if (aidev->exealgo == AIRMS) + sequence = aidev->curr_idxbuf.airms_st.sequence; if (!rkaiisp_update_buf(aidev)) { aidev->run_idx = 0; - aidev->frame_id = aidev->curr_idxbuf.sequence; + aidev->frame_id = sequence; aidev->pre_frm_st = aidev->frm_st; aidev->frm_st = ktime_get_ns(); rkaiisp_get_new_iqparam(aidev); @@ -1228,18 +1419,24 @@ void rkaiisp_trigger(struct rkaiisp_device *aidev) } } -static void rkaiisp_event_queue(struct rkaiisp_device *aidev, struct rkisp_aiisp_st *idxbuf) +static void rkaiisp_event_queue(struct rkaiisp_device *aidev, union rkaiisp_queue_buf *idxbuf) { - struct rkisp_aiisp_st *rundone; + union rkaiisp_queue_buf *rundone; struct v4l2_event event = {0}; + int sequence = 0; + + if (aidev->exealgo == AIBNR) + sequence = idxbuf->aibnr_st.sequence; + else if (aidev->exealgo == AIRMS) + sequence = idxbuf->airms_st.sequence; if (aidev->subdev.is_subs_evt && aidev->exemode != BOTHEVENT_IN_KERNEL) { event.type = RKAIISP_V4L2_EVENT_AIISP_DONE; - rundone = (struct rkisp_aiisp_st *)&event.u.data[0]; + rundone = (union rkaiisp_queue_buf *)&event.u.data[0]; *rundone = *idxbuf; v4l2_event_queue(aidev->subdev.sd.devnode, &event); v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "aiisp done: %d\n", rundone->sequence); + "aiisp done: %d\n", sequence); } else { // call isp api to inform } @@ -1250,13 +1447,13 @@ int rkaiisp_get_idxbuf_len(struct rkaiisp_device *aidev) struct kfifo *fifo = &aidev->idxbuf_kfifo; int len = 0; - len = kfifo_len(fifo) / sizeof(struct rkisp_aiisp_st); + len = kfifo_len(fifo) / sizeof(union rkaiisp_queue_buf); return len; } enum rkaiisp_irqhdl_ret rkaiisp_irq_hdl(struct rkaiisp_device *aidev, u32 mi_mis) { - struct rkisp_aiisp_st *idxbuf = NULL; + union rkaiisp_queue_buf *idxbuf = NULL; u64 frm_hdntim = 0; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, @@ -1266,11 +1463,13 @@ enum rkaiisp_irqhdl_ret rkaiisp_irq_hdl(struct rkaiisp_device *aidev, u32 mi_mis if (mi_mis & AIISP_MI_ISR_BUSERR) { v4l2_err(&aidev->v4l2_dev, "buserr 0x%x\n", mi_mis); rkaiisp_write(aidev, AIISP_MI_ICR, AIISP_MI_ISR_BUSERR, true); + aidev->isr_buserr_cnt++; } if (!(mi_mis & AIISP_MI_ISR_WREND)) return NOT_WREND; rkaiisp_write(aidev, AIISP_MI_ICR, AIISP_MI_ISR_WREND, true); + aidev->isr_wrend_cnt++; if (aidev->run_idx < aidev->model_runcnt - 1) { aidev->run_idx++; @@ -1427,6 +1626,7 @@ static long rkaiisp_ioctl_default(struct file *file, void *fh, if ((param_info->para_size > 0) && (param_info->max_runcnt > 0) && (param_info->max_runcnt <= RKAIISP_MAX_RUNCNT)) { + aidev->exealgo = param_info->exealgo; aidev->exemode = param_info->exemode; aidev->para_size = param_info->para_size; aidev->max_runcnt = param_info->max_runcnt; @@ -1446,6 +1646,9 @@ static long rkaiisp_ioctl_default(struct file *file, void *fh, case RKAIISP_CMD_QUEUE_BUF: ret = rkaiisp_queue_ispbuf(aidev, arg); break; + case RKAIISP_CMD_INIT_AIRMS_BUFPOOL: + ret = rkaiisp_init_airms_pool(aidev, arg); + break; default: ret = -EINVAL; } @@ -1584,6 +1787,8 @@ rkaiisp_vb2_start_streaming(struct vb2_queue *queue, unsigned int count) atomic_inc(&hw_dev->refcnt); aidev->frm_oversdtim_cnt = 0; + aidev->isr_buserr_cnt = 0; + aidev->isr_wrend_cnt = 0; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "start streaming %d\n", aidev->streamon); @@ -1685,7 +1890,7 @@ int rkaiisp_register_vdev(struct rkaiisp_device *aidev, struct v4l2_device *v4l2 aidev->mem_ops = aidev->hw_dev->mem_ops; ret = kfifo_alloc(&aidev->idxbuf_kfifo, - 16 * sizeof(struct rkisp_aiisp_st), GFP_KERNEL); + 16 * sizeof(union rkaiisp_queue_buf), GFP_KERNEL); if (ret < 0) { v4l2_err(v4l2_dev, "Failed to alloc kfifo %d", ret); return ret; diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.h b/drivers/media/platform/rockchip/aiisp/aiisp.h index d3eb8c1f30eb..8c3749b9916f 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.h +++ b/drivers/media/platform/rockchip/aiisp/aiisp.h @@ -35,6 +35,8 @@ #define RKAIISP_DEFAULT_PARASIZE (16 * 1024) #define RKAIISP_SW_REG_SIZE 0x3000 #define RKAIISP_SW_MAX_SIZE (RKAIISP_SW_REG_SIZE * 2) +#define RKAIISP_AIRMS_BUF_MAXCNT 8 +#define RKAIISP_MIN(a, b) ((a) < (b) ? (a) : (b)) enum rkaiisp_irqhdl_ret { NOT_WREND = (0 << 0), @@ -71,6 +73,9 @@ struct rkaiisp_dummy_buffer { void *vaddr; u32 size; void *mem_priv; + bool is_need_vaddr; + bool is_need_dbuf; + bool is_need_dmafd; }; struct rkaiisp_buffer_size { @@ -113,8 +118,14 @@ struct rkaiisp_device { struct rkaiisp_dummy_buffer temp_buf[RKAIISP_TMP_BUF_CNT]; u32 outbuf_idx; + struct rkaiisp_rmsbuf_info rmsbuf; + struct rkaiisp_dummy_buffer rms_inbuf[RKAIISP_AIRMS_BUF_MAXCNT]; + struct rkaiisp_dummy_buffer rms_outbuf[RKAIISP_AIRMS_BUF_MAXCNT]; + struct rkaiisp_dummy_buffer sigma_buf; + struct rkaiisp_dummy_buffer narmap_buf; + struct kfifo idxbuf_kfifo; - struct rkisp_aiisp_st curr_idxbuf; + union rkaiisp_queue_buf curr_idxbuf; struct rkaiisp_vdev_node vnode; struct list_head params; @@ -123,6 +134,7 @@ struct rkaiisp_device { struct rkaiisp_buffer_size outbuf_size[RKAIISP_MAX_RUNCNT]; struct rkaiisp_buffer_size chn_size[RKAIISP_MAX_CHANNEL]; + enum rkaiisp_exealgo exealgo; enum rkaiisp_exemode exemode; enum rkaiisp_model_mode model_mode; enum rkaiisp_hwstate hwstate; @@ -137,6 +149,8 @@ struct rkaiisp_device { u64 frm_ed; u32 frm_interval; u32 frm_oversdtim_cnt; + u32 isr_buserr_cnt; + u32 isr_wrend_cnt; bool streamon; bool showreg; @@ -178,7 +192,7 @@ static inline u32 rkaiisp_read(struct rkaiisp_device *aidev, u32 reg, bool is_di } extern struct platform_driver rkaiisp_plat_drv; -int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, struct rkisp_aiisp_st *idxbuf); +int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf *idxbuf); void rkaiisp_update_list_reg(struct rkaiisp_device *aidev); void rkaiisp_trigger(struct rkaiisp_device *aidev); int rkaiisp_get_idxbuf_len(struct rkaiisp_device *aidev); diff --git a/drivers/media/platform/rockchip/aiisp/hw.c b/drivers/media/platform/rockchip/aiisp/hw.c index 7c99a62f9d5b..dfe1675ac805 100644 --- a/drivers/media/platform/rockchip/aiisp/hw.c +++ b/drivers/media/platform/rockchip/aiisp/hw.c @@ -120,6 +120,7 @@ int rkaiisp_ispidx_queue(int dev_id, struct rkisp_aiisp_st *idxbuf) { struct rkaiisp_hw_dev *hw_dev = rkaiisp_hwdev; struct rkaiisp_device *aidev = NULL; + union rkaiisp_queue_buf queue_buf; int i; if (!hw_dev) { @@ -146,7 +147,8 @@ int rkaiisp_ispidx_queue(int dev_id, struct rkisp_aiisp_st *idxbuf) return -EINVAL; } - return rkaiisp_queue_ispbuf(aidev, idxbuf); + queue_buf.aibnr_st = *idxbuf; + return rkaiisp_queue_ispbuf(aidev, &queue_buf); } EXPORT_SYMBOL(rkaiisp_ispidx_queue); diff --git a/drivers/media/platform/rockchip/aiisp/procfs.c b/drivers/media/platform/rockchip/aiisp/procfs.c index 0f58541815c2..fa9c042b0723 100644 --- a/drivers/media/platform/rockchip/aiisp/procfs.c +++ b/drivers/media/platform/rockchip/aiisp/procfs.c @@ -16,14 +16,27 @@ static int rkaiisp_show(struct seq_file *p, void *v) struct rkaiisp_device *aidev = p->private; struct rkaiisp_hw_dev *hw_dev = aidev->hw_dev; unsigned long flags = 0; + u32 image_width; + u32 image_height; u32 frm_rate; - int idx_buf_len; + int i, idx_buf_len; seq_printf(p, "%-18s Version:v%02x.%02x.%02x\n", aidev->v4l2_dev.name, RKAIISP_DRIVER_VERSION >> 16, (RKAIISP_DRIVER_VERSION & 0xff00) >> 8, RKAIISP_DRIVER_VERSION & 0x00ff); + for (i = 0; i < hw_dev->num_clks; i++) { + seq_printf(p, "%-18s %ld\n", + hw_dev->match_data->clks[i], + clk_get_rate(hw_dev->clks[i])); + } + + seq_printf(p, "%-18s wrend cnt:%d buserr cnt:%d\n", + "interrupt", + aidev->isr_wrend_cnt, + aidev->isr_buserr_cnt); + seq_printf(p, "%-18s %d\n", "dev id", aidev->dev_id); seq_printf(p, "%-18s %d\n", "frame id", aidev->frame_id); seq_printf(p, "%-18s %d\n", "run idx", aidev->run_idx); @@ -31,13 +44,21 @@ static int rkaiisp_show(struct seq_file *p, void *v) seq_printf(p, "%-18s %d\n", "frm rate", frm_rate / 1000 / 1000); seq_printf(p, "%-18s %d\n", "frm hdltime", aidev->frm_interval / 1000 / 1000); seq_printf(p, "%-18s %d\n", "frm_oversdtim_cnt", aidev->frm_oversdtim_cnt); + seq_printf(p, "%-18s %d\n", "execute algo", aidev->exealgo); seq_printf(p, "%-18s %d\n", "model mode", aidev->model_mode); seq_printf(p, "%-18s %d\n", "model runcnt", aidev->model_runcnt); seq_printf(p, "%-18s %d\n", "max runcnt", aidev->max_runcnt); seq_printf(p, "%-18s %d\n", "para size", aidev->para_size); seq_printf(p, "%-18s %d\n", "hw state", aidev->hwstate); - seq_printf(p, "%-18s %d\n", "iir width", aidev->ispbuf.iir_width); - seq_printf(p, "%-18s %d\n", "iir height", aidev->ispbuf.iir_height); + if (aidev->exealgo == AIRMS) { + image_width = aidev->rmsbuf.image_width; + image_height = aidev->rmsbuf.image_height; + } else { + image_width = aidev->ispbuf.iir_width; + image_height = aidev->ispbuf.iir_height; + } + seq_printf(p, "%-18s %d\n", "image width", image_width); + seq_printf(p, "%-18s %d\n", "image height", image_height); spin_lock_irqsave(&hw_dev->hw_lock, flags); idx_buf_len = rkaiisp_get_idxbuf_len(aidev); diff --git a/include/uapi/linux/rk-aiisp-config.h b/include/uapi/linux/rk-aiisp-config.h index 35d22efa040d..54f51202a8c5 100644 --- a/include/uapi/linux/rk-aiisp-config.h +++ b/include/uapi/linux/rk-aiisp-config.h @@ -25,7 +25,10 @@ _IO('V', BASE_VIDIOC_PRIVATE + 2) #define RKAIISP_CMD_QUEUE_BUF \ - _IOW('V', BASE_VIDIOC_PRIVATE + 3, struct rkisp_aiisp_st) + _IOW('V', BASE_VIDIOC_PRIVATE + 3, union rkaiisp_queue_buf) + +#define RKAIISP_CMD_INIT_AIRMS_BUFPOOL \ + _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct rkaiisp_rmsbuf_info) /**********************EVENT_PRIVATE***************************/ #define RKAIISP_V4L2_EVENT_AIISP_DONE (V4L2_EVENT_PRIVATE_START + 1) @@ -44,13 +47,23 @@ enum rkaiisp_chn_src { VPSL_SIG_CHN3, VPSL_SIG_CHN4, ISP_AIPRE_NARMAP, - AIISP_LAST_OUT + AIISP_LAST_OUT, + VICAP_BAYER_RAW, + ALLZERO_SIGMA, + ALLZERO_NARMAP +}; + +enum rkaiisp_exealgo { + AIBNR, + AIRMS, + AIYNR }; enum rkaiisp_model_mode { SINGLE_MODE, COMBO_MODE, - SINGLEX2_MODE + SINGLEX2_MODE, + REMOSAIC_MODE }; enum rkaiisp_exemode { @@ -59,7 +72,19 @@ enum rkaiisp_exemode { BOTHEVENT_IN_KERNEL }; +struct rkaiisp_airms_st { + int sequence; + int inbuf_idx; + int outbuf_idx; +} __attribute__ ((packed)); + +union rkaiisp_queue_buf { + struct rkisp_aiisp_st aibnr_st; + struct rkaiisp_airms_st airms_st; +} __attribute__ ((packed)); + struct rkaiisp_param_info { + enum rkaiisp_exealgo exealgo; enum rkaiisp_exemode exemode; __u32 para_size; __u32 max_runcnt; @@ -77,6 +102,19 @@ struct rkaiisp_ispbuf_info { __u32 narmap_height; } __attribute__ ((packed)); +struct rkaiisp_rmsbuf_info { + __u32 image_width; + __u32 image_height; + __u32 sigma_width; + __u32 sigma_height; + __u32 narmap_width; + __u32 narmap_height; + __u32 inbuf_num; + __u32 outbuf_num; + int inbuf_fd[6]; + int outbuf_fd[6]; +} __attribute__ ((packed)); + struct rkaiisp_other_cfg { __u16 sw_neg_noiselimit; __u16 sw_pos_noiselimit; From 412920a44131989f0e9a7ccef9667e91ed4dad81 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Tue, 20 May 2025 10:40:03 +0800 Subject: [PATCH 2/5] media: rockchip: isp: add ioctl RKISP_VPSS_GET_ISP_WORKING ioctl for vpss to get isp working status Change-Id: Id9727440467a3796e8630e5440dc0069dacf70df Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/isp_sditf.c | 3 +++ drivers/media/platform/rockchip/isp/isp_vpss.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/media/platform/rockchip/isp/isp_sditf.c b/drivers/media/platform/rockchip/isp/isp_sditf.c index 0ed93ed228ba..9d64875995d5 100644 --- a/drivers/media/platform/rockchip/isp/isp_sditf.c +++ b/drivers/media/platform/rockchip/isp/isp_sditf.c @@ -189,6 +189,9 @@ static long rkisp_sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *ar else *(unsigned int *)arg = 0; break; + case RKISP_VPSS_GET_ISP_WORKING: + *(int *)arg = sditf->isp->hw_dev->is_runing; + break; default: ret = -ENOIOCTLCMD; } diff --git a/drivers/media/platform/rockchip/isp/isp_vpss.h b/drivers/media/platform/rockchip/isp/isp_vpss.h index 12774fe9bed1..686b61a20edc 100644 --- a/drivers/media/platform/rockchip/isp/isp_vpss.h +++ b/drivers/media/platform/rockchip/isp/isp_vpss.h @@ -19,6 +19,9 @@ #define RKISP_VPSS_CMD_FRAME_INFO \ _IOW('V', BASE_VIDIOC_PRIVATE + 4, struct rkisp_vpss_frame_info) +#define RKISP_VPSS_GET_ISP_WORKING \ + _IOR('V', BASE_VIDIOC_PRIVATE + 5, int) + struct rkisp_vpss_sof { u32 irq; u32 seq; From 635bb96ec03ec0b070996954101b9e0b65dd6d55 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Tue, 20 May 2025 10:42:29 +0800 Subject: [PATCH 3/5] media: rockchip: vpss: limit vpss start first if online Change-Id: I71acdf32ff4c2af9592320d38bd28ea53d8cd95f Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/vpss/dev.c | 13 ++++++++++++- drivers/media/platform/rockchip/vpss/stream_v10.c | 3 ++- drivers/media/platform/rockchip/vpss/stream_v20.c | 3 ++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/rockchip/vpss/dev.c b/drivers/media/platform/rockchip/vpss/dev.c index bf48377b9d96..3748a19909e8 100644 --- a/drivers/media/platform/rockchip/vpss/dev.c +++ b/drivers/media/platform/rockchip/vpss/dev.c @@ -78,9 +78,20 @@ void rkvpss_pipeline_default_fmt(struct rkvpss_device *dev) int rkvpss_pipeline_open(struct rkvpss_device *dev) { + int isp_working = 0; + if (atomic_inc_return(&dev->pipe_power_cnt) > 1) return 0; - + if (!atomic_read(&dev->hw_dev->refcnt)) { + v4l2_subdev_call(dev->remote_sd, core, ioctl, + RKISP_VPSS_GET_ISP_WORKING, &isp_working); + if (isp_working) { + atomic_dec(&dev->pipe_power_cnt); + v4l2_err(&dev->v4l2_dev, + "no support isp working then vpss start, make sure vpss stream on first\n"); + return -EINVAL; + } + } return 0; } diff --git a/drivers/media/platform/rockchip/vpss/stream_v10.c b/drivers/media/platform/rockchip/vpss/stream_v10.c index b0b35f26c661..6ac0a5a4e50c 100644 --- a/drivers/media/platform/rockchip/vpss/stream_v10.c +++ b/drivers/media/platform/rockchip/vpss/stream_v10.c @@ -1871,7 +1871,8 @@ static int rkvpss_start_streaming(struct vb2_queue *queue, unsigned int count) goto free_buf_queue; } - rkvpss_pipeline_open(dev); + if (rkvpss_pipeline_open(dev) < 0) + goto free_buf_queue; ret = rkvpss_stream_start(stream); if (ret < 0) { diff --git a/drivers/media/platform/rockchip/vpss/stream_v20.c b/drivers/media/platform/rockchip/vpss/stream_v20.c index 5038086c7ead..420e292c43ef 100644 --- a/drivers/media/platform/rockchip/vpss/stream_v20.c +++ b/drivers/media/platform/rockchip/vpss/stream_v20.c @@ -2094,7 +2094,8 @@ static int rkvpss_start_streaming(struct vb2_queue *queue, unsigned int count) goto free_buf_queue; } - rkvpss_pipeline_open(dev); + if (rkvpss_pipeline_open(dev) < 0) + goto free_buf_queue; ret = rkvpss_stream_start(stream); if (ret < 0) { From f6221ca70f488a367f3e92627dd8a71e457245d0 Mon Sep 17 00:00:00 2001 From: cww Date: Tue, 20 May 2025 10:52:44 +0800 Subject: [PATCH 4/5] ARM: configs: rv1126b-evb: enable exfat Signed-off-by: cww Change-Id: I49d3bbba5c653148b7693d2ad35d64df7ef7c82d --- arch/arm/configs/rv1126b-evb.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/rv1126b-evb.config b/arch/arm/configs/rv1126b-evb.config index 47d3fd0bec40..add7b901ba15 100644 --- a/arch/arm/configs/rv1126b-evb.config +++ b/arch/arm/configs/rv1126b-evb.config @@ -3,6 +3,7 @@ CONFIG_CRC16=y CONFIG_CRYPTO=y CONFIG_DEBUG_FS=y CONFIG_ELF_CORE=y +CONFIG_EXFAT_FS=y CONFIG_EXPORTFS_BLOCK_OPS=y CONFIG_EXT4_FS=y CONFIG_EXTCON=y @@ -300,6 +301,7 @@ CONFIG_DNS_RESOLVER=y # CONFIG_ENC28J60 is not set # CONFIG_ENCRYPTED_KEYS is not set # CONFIG_ENCX24J600 is not set +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" # CONFIG_EXT4_DEBUG is not set # CONFIG_EXT4_FS_POSIX_ACL is not set # CONFIG_EXT4_FS_SECURITY is not set From 1e7f98d23e872853a684414a6e0271393ec10193 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Mon, 19 May 2025 09:21:15 +0800 Subject: [PATCH 5/5] rockchp/drm: vop2: limit vrr work condition for active and mode change In the active change and mode change case, the refresh_rate_change should be set true to reconfig the reuqesut rate after active change or mode change. In some case, the active change or mode change is triggered, but a valid request refresh rate is not config, which will also cause the refresh_rate_change be set true. This is a wrong operation. So in the active change or mode change case, It's also need to check the whether request refresh rate is valid or not. Fix error log at system bootup: [drm:vop2_crtc_atomic_begin] *ERROR* invalid rate:0 Change-Id: I93f6f36a64302ddb0f38264377bb4659d8aaa5a2 Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index b9de39ca740a..6e31532f8856 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -10850,8 +10850,11 @@ static int vop2_crtc_atomic_check(struct drm_crtc *crtc, } } - if ((old_vcstate->request_refresh_rate != new_vcstate->request_refresh_rate) || - new_crtc_state->active_changed || new_crtc_state->mode_changed) + if (old_vcstate->request_refresh_rate != new_vcstate->request_refresh_rate) + vp->refresh_rate_change = true; + else if ((new_crtc_state->active_changed || new_crtc_state->mode_changed) && + (new_vcstate->request_refresh_rate >= new_vcstate->min_refresh_rate && + new_vcstate->request_refresh_rate <= new_vcstate->max_refresh_rate)) vp->refresh_rate_change = true; else vp->refresh_rate_change = false;