diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 0f49a7c767df..321b53505a42 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -676,7 +676,7 @@ static int rkcif_output_fmt_check(struct rkcif_stream *stream, break; } if (ret) - v4l2_err(&stream->cifdev->v4l2_dev, + v4l2_dbg(4, rkcif_debug, &stream->cifdev->v4l2_dev, "input mbus_code 0x%x, can't transform to %c%c%c%c\n", input_fmt->mbus_code, output_fmt->fourcc & 0xff, @@ -6717,6 +6717,8 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id) stream->is_single_cap = false; atomic_set(&stream->buf_cnt, 0); stream->rx_buf_num = 0; + init_completion(&stream->stop_complete); + stream->is_wait_stop_complete = false; } static int rkcif_fh_open(struct file *filp) @@ -7316,10 +7318,12 @@ static long rkcif_ioctl_default(struct file *file, void *fh, struct csi_channel_info csi_info; struct rkcif_fps fps; int reset_src; - int on = 0; + struct rkcif_quick_stream_param *stream_param; bool is_single_dev = false; struct v4l2_subdev *sd; int ret = -EINVAL; + int i = 0; + int stream_num = 0; switch (cmd) { case RKCIF_CMD_GET_CSI_MEMORY_MODE: @@ -7369,12 +7373,22 @@ static long rkcif_ioctl_default(struct file *file, void *fh, reset_src = *(int *)arg; return rkcif_do_reset_work(dev, reset_src); case RKCIF_CMD_SET_QUICK_STREAM: - on = *(int *)arg; + stream_param = (struct rkcif_quick_stream_param *)arg; if (!dev->sditf[0]) return -EINVAL; - if (on) { + if (dev->hdr.hdr_mode == HDR_X2) + stream_num = 2; + else if (dev->hdr.hdr_mode == HDR_X3) + stream_num = 3; + else + stream_num = 1; + if (stream_param->on) { is_single_dev = rkcif_check_single_dev_stream_on(dev->hw_dev); if (is_single_dev) { + for (i = 0; i < stream_num - 1; i++) { + dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP; + rkcif_enable_dma_capture(&dev->stream[i], true); + } dev->sditf[0]->mode.rdbk_mode = RKISP_VICAP_ONLINE; sditf_change_to_online(dev->sditf[0]); sd = get_rkisp_sd(dev->sditf[0]); @@ -7386,23 +7400,47 @@ static long rkcif_ioctl_default(struct file *file, void *fh, return -EINVAL; } } else { - dev->sditf[0]->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO; sditf_disable_immediately(dev->sditf[0]); - stream->to_en_dma = RKCIF_DMAEN_BY_ISP; - rkcif_enable_dma_capture(stream, true); + for (i = 0; i < stream_num; i++) { + if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) + dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP; + else + dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_VICAP; + rkcif_enable_dma_capture(&dev->stream[i], true); + } } - rkcif_dphy_quick_stream(dev, on); + rkcif_dphy_quick_stream(dev, stream_param->on); v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, - RKMODULE_SET_QUICK_STREAM, &on); + RKMODULE_SET_QUICK_STREAM, &stream_param->on); } else { - if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { - stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; - } else if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ) { - stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP; - } else { - stream->cifdev->sensor_state = 0; + if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_ONLINE) { + for (i = 0; i < stream_num - 1; i++) { + reinit_completion(&dev->stream[i].stop_complete); + dev->stream[i].is_wait_stop_complete = true; + dev->stream[i].to_stop_dma = RKCIF_DMAEN_BY_ISP; + wait_for_completion_timeout(&dev->stream[i].stop_complete, + msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS)); + } + stream->cifdev->sensor_state = stream_param->on; stream->cifdev->sensor_state_change = true; + dev->stream[i].is_wait_stop_complete = true; + wait_for_completion_timeout(&dev->stream[i].stop_complete, + msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS)); + } else { + for (i = 0; i < stream_num; i++) { + dev->stream[i].is_wait_stop_complete = true; + reinit_completion(&dev->stream[i].stop_complete); + if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) + dev->stream[i].to_stop_dma = RKCIF_DMAEN_BY_ISP; + else + dev->stream[i].to_stop_dma = RKCIF_DMAEN_BY_VICAP; + wait_for_completion_timeout(&dev->stream[i].stop_complete, + msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS)); + } } + stream_param->frame_num = dev->stream[0].frame_idx - 1; + if (!dev->is_rtt_suspend) + dev->resume_mode = stream_param->resume_mode; } break; default: @@ -10124,6 +10162,10 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, stream->cifdev->sensor_work.on = stream->cifdev->sensor_state; schedule_work(&stream->cifdev->sensor_work.work); stream->cifdev->sensor_state_change = false; + if (stream->is_wait_stop_complete) { + stream->is_wait_stop_complete = false; + complete(&stream->stop_complete); + } } if (stream->is_single_cap) { rkcif_dphy_quick_stream(stream->cifdev, on); @@ -10444,7 +10486,6 @@ static void rkcif_get_resmem_head(struct rkcif_device *cif_dev) int cam_idx = 0; char cam_idx_str[3] = {0}; - cif_dev->resume_mode = RKISP_RTT_MODE_NORMAL; if (!cif_dev->is_thunderboot && !cif_dev->is_rtt_suspend) return; strscpy(cam_idx_str, cif_dev->terminal_sensor.sd->name + 1, 2); @@ -10518,7 +10559,7 @@ static int rkcif_subdevs_set_stream(struct rkcif_device *cif_dev, int on) for (i = 0; i < p->num_subdevs; i++) { if (p->subdevs[i] == terminal_sensor->sd && on) rkcif_set_sof(cif_dev, cif_dev->stream[0].frame_idx); - if (p->subdevs[i] == terminal_sensor->sd && cif_dev->is_rtt_suspend) { + if (p->subdevs[i] == terminal_sensor->sd) { if (!rk_tb_mcu_is_done() && on) { cif_dev->tb_client.data = p->subdevs[i]; cif_dev->tb_client.cb = rkcif_sensor_quick_streaming_cb; @@ -10632,6 +10673,7 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) { struct rkcif_stream *stream = NULL; struct sditf_priv *priv = cif_dev->sditf[0]; + struct v4l2_subdev *sd = NULL; int ret = 0; int i = 0; u32 capture_mode = 0; @@ -10643,7 +10685,6 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) mutex_lock(&cif_dev->stream_lock); rkcif_get_resmem_head(cif_dev); - cif_dev->resume_mode = RKISP_RTT_MODE_ONE_FRAME; is_single_dev = rkcif_check_single_dev_stream_on(cif_dev->hw_dev); if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME) { if (cif_dev->is_rtt_suspend) { @@ -10651,12 +10692,20 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) if (priv) priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO; } else { - if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) - capture_mode = RKCIF_STREAM_MODE_TOISP; - else if (priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) + if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) { + if (cif_dev->chip_id == CHIP_RV1106_CIF) { + capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; + priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO; + } else { + capture_mode = RKCIF_STREAM_MODE_TOISP; + } + } else if (priv && + (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO || + priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)) { capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; - else + } else { capture_mode = RKCIF_STREAM_MODE_CAPTURE; + } } } else if (cif_dev->resume_mode == RKISP_RTT_MODE_MULTI_FRAME) { if (is_single_dev) { @@ -10671,7 +10720,9 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) } else { if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) capture_mode = RKCIF_STREAM_MODE_TOISP; - else if (priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) + else if (priv && + (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO || + priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)) capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; else capture_mode = RKCIF_STREAM_MODE_CAPTURE; @@ -10746,6 +10797,18 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) (priv->hdr_cfg.hdr_mode == HDR_X3 && (stream->id == 0 || stream->id == 1)))) rkcif_init_rx_buf(stream, 1); } else { + if (stream->is_single_cap && stream->id == 0) { + priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO_ONE_FRAME; + sd = get_rkisp_sd(priv); + if (sd) { + ret = v4l2_subdev_call(sd, core, ioctl, + RKISP_VICAP_CMD_MODE, &priv->mode); + if (ret) + v4l2_err(&cif_dev->v4l2_dev, + "set isp work mode rdbk aotu oneframe fail\n"); + + } + } sditf_disable_immediately(priv); if (!stream->rx_buf_num && capture_mode == RKCIF_STREAM_MODE_TOISP_RDBK) { @@ -11009,6 +11072,13 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) stream->is_finish_stop_dma = false; continue; } + + if (stream->is_finish_stop_dma && stream->is_wait_stop_complete) { + stream->is_finish_stop_dma = false; + stream->is_wait_stop_complete = false; + complete(&stream->stop_complete); + } + if (stream->crop_dyn_en) rkcif_dynamic_crop(stream); @@ -11047,15 +11117,13 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) } spin_lock_irqsave(&stream->vbq_lock, flags); - if (stream->lack_buf_cnt == 2) { + if (!(stream->cur_stream_mode & RKCIF_STREAM_MODE_TOISP) && + stream->lack_buf_cnt == 2) { + stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP; + rkcif_stop_dma_capture(stream); v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_dev, "stream[%d] to stop dma, lack_buf_cnt %d\n", stream->id, stream->lack_buf_cnt); - if (stream->cur_stream_mode & RKCIF_STREAM_MODE_TOISP) - stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; - else - stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP; - rkcif_stop_dma_capture(stream); } spin_unlock_irqrestore(&stream->vbq_lock, flags); if (stream->to_en_scale) { diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 9fbd5bb7b6ef..a33277ea19b1 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -94,6 +94,11 @@ #define CROP_SRC_SENSOR_MASK (0x1 << 0) #define CROP_SRC_USR_MASK (0x1 << 1) +/* + * max wait time for stream stop + */ +#define RKCIF_STOP_MAX_WAIT_TIME_MS (500) + enum rkcif_workmode { RKCIF_WORKMODE_ONEFRAME = 0x00, RKCIF_WORKMODE_PINGPONG = 0x01, @@ -541,6 +546,7 @@ struct rkcif_stream { int last_frame_idx; int new_fource_idx; atomic_t buf_cnt; + struct completion stop_complete; bool stopping; bool crop_enable; bool crop_dyn_en; @@ -559,6 +565,7 @@ struct rkcif_stream { bool is_stop_capture; bool is_wait_dma_stop; bool is_single_cap; + bool is_wait_stop_complete; }; struct rkcif_lvds_subdev { diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index f0ab3e854032..b186ec857ef8 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -862,7 +862,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, return -EINVAL; rx_buf = to_cif_rx_buf(dbufs); - v4l2_dbg(rkcif_debug, 3, &cif_dev->v4l2_dev, "buf back to vicap 0x%x\n", + v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "buf back to vicap 0x%x\n", (u32)rx_buf->dummy.dma_addr); spin_lock_irqsave(&stream->vbq_lock, flags); stream->last_rx_buf_idx = dbufs->sequence + 1; diff --git a/include/uapi/linux/rkcif-config.h b/include/uapi/linux/rkcif-config.h index f9efbab06b08..c9b9bbf0d301 100644 --- a/include/uapi/linux/rkcif-config.h +++ b/include/uapi/linux/rkcif-config.h @@ -37,7 +37,7 @@ _IOW('V', BASE_VIDIOC_PRIVATE + 7, struct rkcif_csi_info) #define RKCIF_CMD_SET_QUICK_STREAM \ - _IOW('V', BASE_VIDIOC_PRIVATE + 8, int) + _IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct rkcif_quick_stream_param) /* cif memory mode * 0: raw12/raw10/raw8 8bit memory compact @@ -82,4 +82,10 @@ struct rkcif_csi_info { int dphy_vendor[RKCIF_MAX_CSI_NUM]; }; +struct rkcif_quick_stream_param { + int on; + __u32 frame_num; + int resume_mode; +}; + #endif