diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index f6acbb941dbd..4cd1b0505e49 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -4742,6 +4742,7 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream, unsigned long flags; int frame_phase = 0; bool is_dual_update_buf = false; + int on = 1; if (stream->state != RKCIF_STATE_STREAMING || rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT || @@ -4903,8 +4904,19 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream, __func__, __LINE__, stream->state, stream->curr_buf, stream->next_buf); } spin_unlock_irqrestore(&stream->vbq_lock, flags); - if (stream->to_en_dma) + if (stream->to_en_dma) { rkcif_enable_dma_capture(stream, true); + spin_lock_irqsave(&dev->hdr_lock, flags); + if (dev->is_sensor_off) { + dev->is_sensor_off = false; + spin_unlock_irqrestore(&dev->hdr_lock, flags); + rkcif_dphy_quick_stream(dev, on); + v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, + RKMODULE_SET_QUICK_STREAM, &on); + } else { + spin_unlock_irqrestore(&dev->hdr_lock, flags); + } + } } /* @@ -11109,6 +11121,9 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, stream->cifdev->sensor_work.on = 0; schedule_work(&stream->cifdev->sensor_work.work); stream->is_single_cap = false; + spin_lock_irqsave(&stream->cifdev->hdr_lock, flags); + stream->cifdev->is_sensor_off = true; + spin_unlock_irqrestore(&stream->cifdev->hdr_lock, flags); } if (stream->cur_skip_frame && (stream->cifdev->hdr.hdr_mode == NO_HDR || @@ -12291,8 +12306,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) stream->dma_en); rkcif_update_stream_rockit(cif_dev, stream, mipi_id); } - if ((stream->is_single_cap || stream->lack_buf_cnt == 2) && - !stream->cur_skip_frame) { + if (stream->is_single_cap && !stream->cur_skip_frame) { if (stream->dma_en & RKCIF_DMAEN_BY_ISP) stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; else if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) @@ -12307,7 +12321,18 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) rkcif_dphy_quick_stream(stream->cifdev, on); cif_dev->sensor_work.on = 0; schedule_work(&cif_dev->sensor_work.work); + spin_lock_irqsave(&cif_dev->hdr_lock, flags); + cif_dev->is_sensor_off = true; + spin_unlock_irqrestore(&cif_dev->hdr_lock, flags); } + } else if (stream->lack_buf_cnt == 2 && !stream->cur_skip_frame) { + if (stream->dma_en & RKCIF_DMAEN_BY_ISP) + stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; + else if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) + stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP; + else if (stream->dma_en & RKCIF_DMAEN_BY_ROCKIT) + stream->to_stop_dma = RKCIF_DMAEN_BY_ROCKIT; + rkcif_stop_dma_capture(stream); } if (cif_dev->chip_id >= CHIP_RV1106_CIF) diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index a71af5ba5fc1..417f44c9ec2f 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -2298,6 +2298,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int cif_dev->is_thunderboot = false; cif_dev->rdbk_debug = 0; cif_dev->is_stop_skip = false; + cif_dev->is_sensor_off = false; cif_dev->resume_mode = 0; memset(&cif_dev->channels[0].capture_info, 0, sizeof(cif_dev->channels[0].capture_info)); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 0a93cc34f96b..792a1c6b9091 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -933,6 +933,7 @@ struct rkcif_device { bool is_toisp_reset; bool use_hw_interlace; bool is_stop_skip; + bool is_sensor_off; int rdbk_debug; struct rkcif_sync_cfg sync_cfg; int sditf_cnt; diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 9b2e39f992a2..a900e25c3de0 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -839,7 +839,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, struct rkcif_stream *stream = NULL; struct rkisp_rx_buf *dbufs; struct rkcif_rx_buffer *rx_buf = NULL; - unsigned long flags, buffree_flags; + unsigned long flags, buffree_flags, hdr_lock_flags; u32 diff_time = 1000000; u32 early_time = 0; bool is_free = false; @@ -914,9 +914,16 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, if (!stream->dma_en) { stream->to_en_dma = RKCIF_DMAEN_BY_ISP; rkcif_enable_dma_capture(stream, true); - cif_dev->sensor_work.on = 1; - rkcif_dphy_quick_stream(stream->cifdev, cif_dev->sensor_work.on); - schedule_work(&cif_dev->sensor_work.work); + spin_lock_irqsave(&cif_dev->hdr_lock, hdr_lock_flags); + if (cif_dev->is_sensor_off) { + cif_dev->is_sensor_off = false; + spin_unlock_irqrestore(&cif_dev->hdr_lock, hdr_lock_flags); + cif_dev->sensor_work.on = 1; + rkcif_dphy_quick_stream(stream->cifdev, cif_dev->sensor_work.on); + schedule_work(&cif_dev->sensor_work.work); + } else { + spin_unlock_irqrestore(&cif_dev->hdr_lock, hdr_lock_flags); + } } } if (cif_dev->rdbk_debug) {