From 8f9f8dc62df9bc8d7a9f4ec8ffbd78873eb3ee64 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Sun, 8 Oct 2023 16:06:38 +0800 Subject: [PATCH] media: rockchip: isp: suspend resume with rtt Change-Id: Ibc86e518c3c464950d41166401c5ba2d9ee6c613 Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/isp/dev.c | 68 ++++++++++++++++++- drivers/media/platform/rockchip/isp/dev.h | 4 ++ .../media/platform/rockchip/isp/isp_params.c | 22 ++++++ .../media/platform/rockchip/isp/isp_rockit.c | 5 ++ .../platform/rockchip/isp/isp_stats_v32.c | 3 + drivers/media/platform/rockchip/isp/rkisp.c | 27 +++++--- drivers/media/platform/rockchip/isp/rkisp.h | 2 + include/uapi/linux/rk-isp2-config.h | 8 +++ include/uapi/linux/rk-isp32-config.h | 3 +- 9 files changed, 130 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/dev.c b/drivers/media/platform/rockchip/isp/dev.c index b27522df25fe..69a2ba09a440 100644 --- a/drivers/media/platform/rockchip/isp/dev.c +++ b/drivers/media/platform/rockchip/isp/dev.c @@ -816,6 +816,15 @@ static int rkisp_get_reserved_mem(struct rkisp_device *isp_dev) DMA_BIDIRECTIONAL); ret = dma_mapping_error(dev, isp_dev->resmem_addr); isp_dev->is_thunderboot = true; + isp_dev->is_rtt_suspend = false; + isp_dev->is_rtt_first = true; + if (device_property_read_bool(dev, "rtt-suspend")) { + isp_dev->is_rtt_suspend = true; + if (!isp_dev->hw_dev->is_thunderboot) { + isp_dev->is_thunderboot = false; + isp_dev->is_rtt_first = false; + } + } dev_info(dev, "Allocated reserved memory, paddr: 0x%x\n", (u32)isp_dev->resmem_pa); return ret; } @@ -1065,7 +1074,7 @@ static void rkisp_pm_complete(struct device *dev) struct rkisp_hw_dev *hw = isp_dev->hw_dev; struct rkisp_pipeline *p = &isp_dev->pipe; struct rkisp_stream *stream; - int i, on = 1; + int i, on = 1, rd_mode = isp_dev->rd_mode; if (isp_dev->isp_state & ISP_STOP) { if (pm_runtime_active(dev) && @@ -1079,6 +1088,63 @@ static void rkisp_pm_complete(struct device *dev) return; } + if (isp_dev->is_rtt_suspend) { + rkisp_save_tb_info(isp_dev); + v4l2_info(&isp_dev->v4l2_dev, + "tb info en:%d comp:%d cnt:%d w:%d h:%d cam:%d idx:%d mode:%d\n", + isp_dev->tb_head.enable, isp_dev->tb_head.complete, + isp_dev->tb_head.frm_total, isp_dev->tb_head.width, + isp_dev->tb_head.height, isp_dev->tb_head.camera_num, + isp_dev->tb_head.camera_index, isp_dev->tb_head.rtt_mode); + isp_dev->is_first_double = false; + switch (isp_dev->tb_head.rtt_mode) { + case RKISP_RTT_MODE_ONE_FRAME: + isp_dev->is_first_double = true; + /* switch to readback mode */ + switch (rd_mode) { + case HDR_LINEX3_DDR: + isp_dev->rd_mode = HDR_RDBK_FRAME3; + break; + case HDR_LINEX2_DDR: + isp_dev->rd_mode = HDR_RDBK_FRAME2; + break; + default: + isp_dev->rd_mode = HDR_RDBK_FRAME1; + } + break; + case RKISP_RTT_MODE_MULTI_FRAME: + default: + if (isp_dev->tb_head.rtt_mode != RKISP_RTT_MODE_MULTI_FRAME) + v4l2_warn(&isp_dev->v4l2_dev, + "invalid rtt mode:%d, change to mode:%d\n", + isp_dev->tb_head.rtt_mode, RKISP_RTT_MODE_MULTI_FRAME); + if (!hw->is_single) + break; + /* switch to online mode for single sensor */ + switch (rd_mode) { + case HDR_RDBK_FRAME3: + isp_dev->rd_mode = HDR_LINEX3_DDR; + break; + case HDR_RDBK_FRAME2: + isp_dev->rd_mode = HDR_LINEX2_DDR; + break; + default: + isp_dev->rd_mode = HDR_NORMAL; + } + } + isp_dev->hdr.op_mode = isp_dev->rd_mode; + if (rd_mode != isp_dev->rd_mode && hw->cur_dev_id == isp_dev->dev_id) { + rkisp_unite_write(isp_dev, CSI2RX_CTRL0, + SW_IBUF_OP_MODE(isp_dev->rd_mode), true); + if (IS_HDR_RDBK(isp_dev->rd_mode)) + rkisp_unite_set_bits(isp_dev, CTRL_SWS_CFG, 0, + SW_MPIP_DROP_FRM_DIS, true); + else + rkisp_unite_clear_bits(isp_dev, CTRL_SWS_CFG, + SW_MPIP_DROP_FRM_DIS, true); + } + } + isp_dev->is_suspend = false; isp_dev->isp_state = ISP_START | ISP_FRAME_END; for (i = 0; i < RKISP_MAX_STREAM; i++) { diff --git a/drivers/media/platform/rockchip/isp/dev.h b/drivers/media/platform/rockchip/isp/dev.h index b5cd72d21bb9..89043eaba7b4 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -235,6 +235,10 @@ struct rkisp_device { size_t resmem_size; struct rkisp_thunderboot_resmem_head tb_head; bool is_thunderboot; + /* first frame for rtt */ + bool is_rtt_first; + /* suspend/resume with rtt */ + bool is_rtt_suspend; struct rkisp_tb_stream_info tb_stream_info; unsigned int tb_addr_idx; diff --git a/drivers/media/platform/rockchip/isp/isp_params.c b/drivers/media/platform/rockchip/isp/isp_params.c index 4b7bb64d65fa..cbfcf581424d 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.c +++ b/drivers/media/platform/rockchip/isp/isp_params.c @@ -185,6 +185,28 @@ static void rkisp_params_vb2_buf_queue(struct vb2_buffer *vb) spin_lock_irqsave(¶ms_vdev->config_lock, flags); list_add_tail(¶ms_buf->queue, ¶ms_vdev->params); spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); + + if (params_vdev->dev->is_first_double) { + struct isp32_isp_params_cfg *params = params_buf->vaddr[0]; + struct rkisp_buffer *buf; + + if (!(params->module_cfg_update & ISP32_MODULE_RTT_FST)) + return; + spin_lock_irqsave(¶ms_vdev->config_lock, flags); + while (!list_empty(¶ms_vdev->params)) { + buf = list_first_entry(¶ms_vdev->params, + struct rkisp_buffer, queue); + if (buf == params_buf) + break; + list_del(&buf->queue); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); + dev_info(params_vdev->dev->dev, + "first params:%d for rtt resume\n", params->frame_id); + params_vdev->dev->is_first_double = false; + rkisp_trigger_read_back(params_vdev->dev, false, false, false); + } } static void rkisp_params_vb2_stop_streaming(struct vb2_queue *vq) diff --git a/drivers/media/platform/rockchip/isp/isp_rockit.c b/drivers/media/platform/rockchip/isp/isp_rockit.c index d97cc27976ee..7aa1632ff8fc 100644 --- a/drivers/media/platform/rockchip/isp/isp_rockit.c +++ b/drivers/media/platform/rockchip/isp/isp_rockit.c @@ -240,6 +240,11 @@ int rkisp_rockit_buf_done(struct rkisp_stream *stream, int cmd) rockit_cfg->frame.u64PTS = stream->curr_buf->vb.vb2_buf.timestamp; rockit_cfg->frame.u32TimeRef = stream->curr_buf->vb.sequence; + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "%s stream:%d seq:%d buf:0x%x done\n", + __func__, stream->id, + stream->curr_buf->vb.sequence, + stream->curr_buf->buff_addr[0]); } else { if (stream->ispdev->cap_dev.wrap_line && stream->id == RKISP_STREAM_MP) { diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v32.c b/drivers/media/platform/rockchip/isp/isp_stats_v32.c index cd0a4907846d..79317e618620 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats_v32.c +++ b/drivers/media/platform/rockchip/isp/isp_stats_v32.c @@ -628,6 +628,9 @@ rkisp_stats_send_meas(struct rkisp_isp_stats_vdev *stats_vdev, ops->get_vsm_stats(stats_vdev, cur_stat_buf); } + if (cur_stat_buf && stats_vdev->dev->is_first_double) + cur_stat_buf->meas_type |= ISP32_STAT_RTT_FST; + if (is_dummy) { spin_lock_irqsave(&stats_vdev->rd_lock, flags); if (!list_empty(&stats_vdev->stat)) { diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 3fb64b3b6485..28fcad71b7ab 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -873,6 +873,9 @@ static void rkisp_fast_switch_rx_buf(struct rkisp_device *dev, bool is_current) struct rkisp_buffer *buf; u32 i, val; + if (!dev->is_rtt_first) + return; + for (i = RKISP_STREAM_RAWRD0; i < RKISP_MAX_DMARX_STREAM; i++) { stream = &dev->dmarx_dev.stream[i]; if (!stream->ops) @@ -956,7 +959,7 @@ static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd) } /* wait 2 frame to start isp for fast */ - if (dev->is_pre_on && max == 1 && !atomic_read(&dev->isp_sdev.frm_sync_seq)) + if (dev->is_rtt_first && max == 1 && !atomic_read(&dev->isp_sdev.frm_sync_seq)) goto end; if (max) { @@ -1002,7 +1005,7 @@ static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd) /* first frame handle twice for thunderboot * first output stats to AIQ and wait new params to run second */ - if (isp->is_pre_on && t.frame_id == 0) { + if (isp->is_rtt_first && t.frame_id == 0) { isp->is_first_double = true; isp->skip_frame = 1; if (hw->unite != ISP_UNITE_ONE) { @@ -1010,6 +1013,8 @@ static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd) isp->is_frame_double = false; } rkisp_fast_switch_rx_buf(isp, false); + } else { + isp->is_rtt_first = false; } isp->params_vdev.rdbk_times = isp->sw_rd_cnt + 1; } @@ -1088,6 +1093,7 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq) if (dev->is_first_double) { rkisp_fast_switch_rx_buf(dev, true); + dev->is_rtt_first = false; dev->skip_frame = 0; dev->irq_ends = 0; return; @@ -3024,7 +3030,8 @@ static int rkisp_rx_buf_pool_init(struct rkisp_device *dev, pool->dbufs = dbufs; v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, - "%s type:0x%x dbufs[%d]:%p", __func__, dbufs->type, i, dbufs); + "%s type:0x%x first:%d dbufs[%d]:%p", __func__, + dbufs->type, dbufs->is_first, i, dbufs); if (dbufs->is_resmem) { dma = dbufs->dma; @@ -3415,7 +3422,7 @@ static long rkisp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) rkisp_get_info(isp_dev, arg); break; case RKISP_CMD_GET_TB_HEAD_V32: - if (isp_dev->tb_head.complete != RKISP_TB_OK || !isp_dev->is_pre_on) { + if (isp_dev->tb_head.complete != RKISP_TB_OK) { ret = -EINVAL; break; } @@ -3775,8 +3782,7 @@ void rkisp_unregister_isp_subdev(struct rkisp_device *isp_dev) (cond) ? 0 : -ETIMEDOUT; \ }) -#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP -static void rkisp_save_tb_info(struct rkisp_device *isp_dev) +void rkisp_save_tb_info(struct rkisp_device *isp_dev) { struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev; void *resmem_va = phys_to_virt(isp_dev->resmem_pa); @@ -3796,7 +3802,8 @@ static void rkisp_save_tb_info(struct rkisp_device *isp_dev) if (size && size < isp_dev->resmem_size) { dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr + offset, size, DMA_FROM_DEVICE); - params_vdev->is_first_cfg = true; + if (isp_dev->is_rtt_first) + params_vdev->is_first_cfg = true; if (isp_dev->isp_ver == ISP_V32) { struct rkisp32_thunderboot_resmem_head *tmp = resmem_va + offset; @@ -3808,7 +3815,7 @@ static void rkisp_save_tb_info(struct rkisp_device *isp_dev) tmp->cfg.module_ens, tmp->cfg.module_cfg_update); } - if (param) + if (param && (isp_dev->isp_state & ISP_STOP)) params_vdev->ops->save_first_param(params_vdev, param); } else if (size > isp_dev->resmem_size) { v4l2_err(&isp_dev->v4l2_dev, @@ -3819,6 +3826,7 @@ static void rkisp_save_tb_info(struct rkisp_device *isp_dev) memcpy(&isp_dev->tb_head, head, sizeof(*head)); } +#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP void rkisp_chk_tb_over(struct rkisp_device *isp_dev) { struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev; @@ -3866,11 +3874,10 @@ void rkisp_chk_tb_over(struct rkisp_device *isp_dev) end: head = &isp_dev->tb_head; v4l2_info(&isp_dev->v4l2_dev, - "thunderboot info: %d, %d, %d, %d, %d, %d | %d %d\n", + "tb info en:%d comp:%d cnt:%d w:%d h:%d cam:%d idx:%d\n", head->enable, head->complete, head->frm_total, - head->hdr_mode, head->width, head->height, head->camera_num, diff --git a/drivers/media/platform/rockchip/isp/rkisp.h b/drivers/media/platform/rockchip/isp/rkisp.h index 54f32b9685c3..76f8ce05e424 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.h +++ b/drivers/media/platform/rockchip/isp/rkisp.h @@ -153,6 +153,8 @@ void rkisp_chk_tb_over(struct rkisp_device *isp_dev); static inline void rkisp_chk_tb_over(struct rkisp_device *isp_dev) {} #endif +void rkisp_save_tb_info(struct rkisp_device *isp_dev); + void rkisp_mipi_isr(unsigned int mipi_mis, struct rkisp_device *dev); void rkisp_mipi_v13_isr(unsigned int err1, unsigned int err2, diff --git a/include/uapi/linux/rk-isp2-config.h b/include/uapi/linux/rk-isp2-config.h index 9de8ac7d6e20..fb8254771d92 100644 --- a/include/uapi/linux/rk-isp2-config.h +++ b/include/uapi/linux/rk-isp2-config.h @@ -1968,6 +1968,12 @@ struct rkisp_isp2x_luma_buffer { struct rkisp_mipi_luma luma[ISP2X_MIPI_RAW_MAX]; } __attribute__ ((packed)); +enum { + RKISP_RTT_MODE_NORMAL = 0, + RKISP_RTT_MODE_MULTI_FRAME, + RKISP_RTT_MODE_ONE_FRAME, +}; + /** * struct rkisp_thunderboot_resmem_head */ @@ -1976,10 +1982,12 @@ struct rkisp_thunderboot_resmem_head { __u16 complete; __u16 frm_total; __u16 hdr_mode; + __u16 rtt_mode; __u16 width; __u16 height; __u16 camera_num; __u16 camera_index; + __u16 md_flag; __u32 exp_time[3]; __u32 exp_gain[3]; diff --git a/include/uapi/linux/rk-isp32-config.h b/include/uapi/linux/rk-isp32-config.h index cabd8c191c2d..ecd4eaef2cd3 100644 --- a/include/uapi/linux/rk-isp32-config.h +++ b/include/uapi/linux/rk-isp32-config.h @@ -52,7 +52,7 @@ #define ISP32_MODULE_CSM ISP3X_MODULE_CSM #define ISP32_MODULE_CGC ISP3X_MODULE_CGC #define ISP32_MODULE_VSM BIT_ULL(45) - +#define ISP32_MODULE_RTT_FST BIT_ULL(62) #define ISP32_MODULE_FORCE ISP3X_MODULE_FORCE /* Measurement types */ @@ -70,6 +70,7 @@ #define ISP32_STAT_DHAZ ISP3X_STAT_DHAZ #define ISP32_STAT_VSM BIT(18) #define ISP32_STAT_INFO2DDR BIT(19) +#define ISP32_STAT_RTT_FST BIT(31) #define ISP32_MESH_BUF_NUM ISP3X_MESH_BUF_NUM