mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
media: rockchip: vicap disables DMA capture when there is no active buffer
Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com> Change-Id: I38a705b8b495473acb1f3cfdf50eabda9e61330e
This commit is contained in:
@@ -1540,6 +1540,8 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream,
|
||||
rkcif_write_register(dev, frm0_addr_y, dummy_buf->dma_addr);
|
||||
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
|
||||
rkcif_write_register(dev, frm0_addr_uv, dummy_buf->dma_addr);
|
||||
} else {
|
||||
stream->lack_buf_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1572,6 +1574,16 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream,
|
||||
rkcif_write_register(dev, frm1_addr_y, dummy_buf->dma_addr);
|
||||
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
|
||||
rkcif_write_register(dev, frm1_addr_uv, dummy_buf->dma_addr);
|
||||
} else {
|
||||
if (stream->curr_buf) {
|
||||
stream->next_buf = stream->curr_buf;
|
||||
rkcif_write_register(dev, frm1_addr_y,
|
||||
stream->next_buf->buff_addr[RKCIF_PLANE_Y]);
|
||||
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
|
||||
rkcif_write_register(dev, frm1_addr_uv,
|
||||
stream->next_buf->buff_addr[RKCIF_PLANE_CBCR]);
|
||||
}
|
||||
stream->lack_buf_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1689,12 +1701,16 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
|
||||
stream->next_buf = stream->curr_buf;
|
||||
buffer = stream->curr_buf;
|
||||
}
|
||||
|
||||
stream->lack_buf_cnt++;
|
||||
} else {
|
||||
if (stream->frame_phase == CIF_CSI_FRAME0_READY)
|
||||
stream->curr_buf = NULL;
|
||||
else if (stream->frame_phase == CIF_CSI_FRAME1_READY)
|
||||
stream->next_buf = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
stream->frame_phase_cache = stream->frame_phase;
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
|
||||
if (buffer) {
|
||||
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED &&
|
||||
@@ -1716,16 +1732,29 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
|
||||
rkcif_write_register(dev, frm_addr_y, dummy_buf->dma_addr);
|
||||
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
|
||||
rkcif_write_register(dev, frm_addr_uv, dummy_buf->dma_addr);
|
||||
v4l2_info(&dev->v4l2_dev,
|
||||
"not active buffer, use dummy buffer, %s stream[%d]\n",
|
||||
(mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
|
||||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
|
||||
mbus_cfg->type == V4L2_MBUS_CCP2) ? "mipi/lvds" : "dvp",
|
||||
stream->id);
|
||||
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
stream->lack_buf_cnt++;
|
||||
if (dev->chip_id < CHIP_RK3588_CIF)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
ret = 0;
|
||||
v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev,
|
||||
"not active buffer, lack_buf_cnt %d, stop capture, %s stream[%d]\n",
|
||||
stream->lack_buf_cnt,
|
||||
(mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
|
||||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
|
||||
mbus_cfg->type == V4L2_MBUS_CCP2) ? "mipi/lvds" : "dvp",
|
||||
stream->id);
|
||||
}
|
||||
v4l2_info(&dev->v4l2_dev,
|
||||
"not active buffer, skip current frame, %s stream[%d]\n",
|
||||
(mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
|
||||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
|
||||
mbus_cfg->type == V4L2_MBUS_CCP2) ? "mipi/lvds" : "dvp",
|
||||
stream->id);
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1769,8 +1798,13 @@ static int rkcif_get_new_buffer_wake_up_mode(struct rkcif_stream *stream)
|
||||
stream->frame_phase_cache = CIF_CSI_FRAME1_READY;
|
||||
}
|
||||
stream->is_buf_active = true;
|
||||
stream->lack_buf_cnt++;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
if (dev->chip_id < CHIP_RK3588_CIF)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
ret = 0;
|
||||
stream->lack_buf_cnt++;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
@@ -1826,10 +1860,13 @@ static int rkcif_update_new_buffer_wake_up_mode(struct rkcif_stream *stream)
|
||||
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
|
||||
rkcif_write_register(dev, frm_addr_uv, dummy_buf->dma_addr);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
if (dev->chip_id < CHIP_RK3588_CIF)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
v4l2_info(&dev->v4l2_dev,
|
||||
"not active buffer, skip current frame, %s stream[%d]\n",
|
||||
"not active buffer, skip current frame in wake_up mode, %s stream[%d]\n",
|
||||
(mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
|
||||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
|
||||
mbus_cfg->type == V4L2_MBUS_CCP2) ? "mipi/lvds" : "dvp",
|
||||
@@ -2470,13 +2507,7 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
|
||||
if (channel->crop_en)
|
||||
rkcif_write_register(dev, get_reg_index_of_id_crop_start(channel->id),
|
||||
channel->crop_st_y << 16 | channel->crop_st_x);
|
||||
if (stream->dma_en) {
|
||||
if (mbus_type == V4L2_MBUS_CSI2_DPHY ||
|
||||
mbus_type == V4L2_MBUS_CSI2_CPHY)
|
||||
dma_en = CSI_DMA_ENABLE;
|
||||
else
|
||||
dma_en = LVDS_DMAEN_RV1106;
|
||||
}
|
||||
|
||||
if (stream->dma_en & RKCIF_DMAEN_BY_VICAP)
|
||||
rkcif_assign_new_buffer_pingpong(stream,
|
||||
RKCIF_YUV_ADDR_STATE_INIT,
|
||||
@@ -2485,6 +2516,17 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
|
||||
rkcif_assign_new_buffer_pingpong_toisp(stream,
|
||||
RKCIF_YUV_ADDR_STATE_INIT,
|
||||
channel->id);
|
||||
if (stream->lack_buf_cnt == 2) {
|
||||
stream->is_stop_dma = true;
|
||||
stream->dma_en = 0;
|
||||
}
|
||||
if (stream->dma_en) {
|
||||
if (mbus_type == V4L2_MBUS_CSI2_DPHY ||
|
||||
mbus_type == V4L2_MBUS_CSI2_CPHY)
|
||||
dma_en = CSI_DMA_ENABLE;
|
||||
else
|
||||
dma_en = LVDS_DMAEN_RV1106;
|
||||
}
|
||||
if (mbus_type == V4L2_MBUS_CSI2_DPHY ||
|
||||
mbus_type == V4L2_MBUS_CSI2_CPHY) {
|
||||
|
||||
@@ -2548,8 +2590,12 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode
|
||||
struct csi_channel_info *channel;
|
||||
u32 ret = 0;
|
||||
|
||||
if (stream->state < RKCIF_STATE_STREAMING)
|
||||
if (stream->state < RKCIF_STATE_STREAMING) {
|
||||
stream->frame_idx = 0;
|
||||
stream->frame_phase = 0;
|
||||
stream->lack_buf_cnt = 0;
|
||||
stream->is_stop_dma = false;
|
||||
}
|
||||
|
||||
rkcif_csi_get_vc_num(dev, flags);
|
||||
|
||||
@@ -2757,42 +2803,50 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream,
|
||||
struct rkcif_dummy_buffer *dummy_buf = &dev->dummy_buf;
|
||||
u32 frm_addr_y, frm_addr_uv;
|
||||
unsigned long flags;
|
||||
int frame_phase = 0;
|
||||
|
||||
if (stream->state == RKCIF_STATE_STREAMING &&
|
||||
stream->curr_buf == stream->next_buf &&
|
||||
((stream->curr_buf == stream->next_buf &&
|
||||
stream->cif_fmt_in->field != V4L2_FIELD_INTERLACED &&
|
||||
(!dummy_buf->vaddr)) {
|
||||
if (!stream->is_line_wake_up) {
|
||||
(!dummy_buf->vaddr)) ||
|
||||
stream->curr_buf == NULL ||
|
||||
stream->next_buf == NULL)) {
|
||||
if (stream->curr_buf == NULL)
|
||||
frame_phase = CIF_CSI_FRAME0_READY;
|
||||
else if (stream->next_buf == NULL)
|
||||
frame_phase = CIF_CSI_FRAME1_READY;
|
||||
else
|
||||
frame_phase = stream->frame_phase_cache;
|
||||
|
||||
spin_lock_irqsave(&stream->vbq_lock, flags);
|
||||
if (!stream->is_line_wake_up ||
|
||||
(stream->is_line_wake_up && stream->frame_idx < 2)) {
|
||||
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
|
||||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
|
||||
mbus_cfg->type == V4L2_MBUS_CCP2) {
|
||||
frm_addr_y = stream->frame_phase_cache & CIF_CSI_FRAME0_READY ?
|
||||
frm_addr_y = frame_phase & CIF_CSI_FRAME0_READY ?
|
||||
get_reg_index_of_frm0_y_addr(channel_id) :
|
||||
get_reg_index_of_frm1_y_addr(channel_id);
|
||||
frm_addr_uv = stream->frame_phase_cache & CIF_CSI_FRAME0_READY ?
|
||||
frm_addr_uv = frame_phase & CIF_CSI_FRAME0_READY ?
|
||||
get_reg_index_of_frm0_uv_addr(channel_id) :
|
||||
get_reg_index_of_frm1_uv_addr(channel_id);
|
||||
} else {
|
||||
frm_addr_y = stream->frame_phase_cache & CIF_CSI_FRAME0_READY ?
|
||||
frm_addr_y = frame_phase & CIF_CSI_FRAME0_READY ?
|
||||
get_dvp_reg_index_of_frm0_y_addr(channel_id) :
|
||||
get_dvp_reg_index_of_frm1_y_addr(channel_id);
|
||||
frm_addr_uv = stream->frame_phase_cache & CIF_CSI_FRAME0_READY ?
|
||||
frm_addr_uv = frame_phase & CIF_CSI_FRAME0_READY ?
|
||||
get_dvp_reg_index_of_frm0_uv_addr(channel_id) :
|
||||
get_dvp_reg_index_of_frm1_uv_addr(channel_id);
|
||||
}
|
||||
v4l2_dbg(2, rkcif_debug, &stream->cifdev->v4l2_dev,
|
||||
"stream[%d] update buf in %s, stream->frame_phase_cache %d\n",
|
||||
stream->id, __func__, stream->frame_phase_cache);
|
||||
spin_lock_irqsave(&stream->vbq_lock, flags);
|
||||
if (!list_empty(&stream->buf_head)) {
|
||||
if (stream->frame_phase_cache == CIF_CSI_FRAME0_READY) {
|
||||
if (frame_phase == CIF_CSI_FRAME0_READY) {
|
||||
stream->curr_buf = list_first_entry(&stream->buf_head,
|
||||
struct rkcif_buffer, queue);
|
||||
if (stream->curr_buf) {
|
||||
list_del(&stream->curr_buf->queue);
|
||||
buffer = stream->curr_buf;
|
||||
}
|
||||
} else if (stream->frame_phase_cache == CIF_CSI_FRAME1_READY) {
|
||||
} else if (frame_phase == CIF_CSI_FRAME1_READY) {
|
||||
stream->next_buf = list_first_entry(&stream->buf_head,
|
||||
struct rkcif_buffer, queue);
|
||||
if (stream->next_buf) {
|
||||
@@ -2801,7 +2855,6 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream,
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
if (buffer) {
|
||||
rkcif_write_register(dev, frm_addr_y,
|
||||
buffer->buff_addr[RKCIF_PLANE_Y]);
|
||||
@@ -2810,7 +2863,6 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream,
|
||||
buffer->buff_addr[RKCIF_PLANE_CBCR]);
|
||||
}
|
||||
} else {
|
||||
spin_lock_irqsave(&stream->vbq_lock, flags);
|
||||
if (stream->curr_buf == stream->next_buf) {
|
||||
if (stream->frame_phase_cache == CIF_CSI_FRAME0_READY) {
|
||||
stream->curr_buf = list_first_entry(&stream->buf_head,
|
||||
@@ -2825,8 +2877,20 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream,
|
||||
}
|
||||
stream->is_buf_active = true;
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
}
|
||||
v4l2_dbg(2, rkcif_debug, &stream->cifdev->v4l2_dev,
|
||||
"%s, stream[%d] update buffer, frame_phase %d, is_stop %s, lack_buf_cnt %d\n",
|
||||
__func__, stream->id, frame_phase,
|
||||
(stream->is_stop_dma ? "true" : "false"),
|
||||
stream->lack_buf_cnt);
|
||||
if (stream->is_stop_dma) {
|
||||
stream->to_en_dma = true;
|
||||
rkcif_enable_dma_capture(stream);
|
||||
stream->is_stop_dma = false;
|
||||
}
|
||||
if (stream->lack_buf_cnt)
|
||||
stream->lack_buf_cnt--;
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3781,8 +3845,12 @@ static int rkcif_stream_start(struct rkcif_stream *stream, unsigned int mode)
|
||||
int i = 0;
|
||||
u32 sav_detect = BT656_DETECT_SAV;
|
||||
|
||||
if (stream->state < RKCIF_STATE_STREAMING)
|
||||
if (stream->state < RKCIF_STATE_STREAMING) {
|
||||
stream->frame_idx = 0;
|
||||
stream->lack_buf_cnt = 0;
|
||||
stream->is_stop_dma = false;
|
||||
stream->frame_phase = 0;
|
||||
}
|
||||
|
||||
sensor_info = dev->active_sensor;
|
||||
mbus = &sensor_info->mbus;
|
||||
@@ -3998,6 +4066,10 @@ static int rkcif_stream_start(struct rkcif_stream *stream, unsigned int mode)
|
||||
|
||||
if (dev->chip_id == CHIP_RK3588_CIF) {
|
||||
dma_en = DVP_DMA_EN;
|
||||
if (stream->lack_buf_cnt == 2) {
|
||||
dma_en = 0;
|
||||
stream->is_stop_dma = true;
|
||||
}
|
||||
rkcif_write_register(dev, CIF_REG_DVP_CTRL,
|
||||
DVP_SW_WATER_LINE_25
|
||||
| dma_en
|
||||
@@ -4009,6 +4081,10 @@ static int rkcif_stream_start(struct rkcif_stream *stream, unsigned int mode)
|
||||
| ENABLE_CAPTURE);
|
||||
} else if (dev->chip_id == CHIP_RV1106_CIF) {
|
||||
dma_en = DVP_SW_DMA_EN(stream->id);
|
||||
if (stream->lack_buf_cnt == 2) {
|
||||
dma_en = 0;
|
||||
stream->is_stop_dma = true;
|
||||
}
|
||||
rkcif_write_register(dev, CIF_REG_DVP_CTRL,
|
||||
DVP_SW_WATER_LINE_25
|
||||
| DVP_PRESS_EN
|
||||
@@ -6476,11 +6552,11 @@ static void rkcif_update_stream(struct rkcif_device *cif_dev,
|
||||
ret = rkcif_assign_new_buffer_pingpong(stream,
|
||||
RKCIF_YUV_ADDR_STATE_UPDATE,
|
||||
mipi_id);
|
||||
if (ret)
|
||||
if (ret && cif_dev->chip_id < CHIP_RK3588_CIF)
|
||||
return;
|
||||
} else {
|
||||
ret = rkcif_update_new_buffer_wake_up_mode(stream);
|
||||
if (ret)
|
||||
if (ret && cif_dev->chip_id < CHIP_RK3588_CIF)
|
||||
return;
|
||||
}
|
||||
if (!stream->is_line_wake_up)
|
||||
@@ -7656,6 +7732,13 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
|
||||
rkcif_stop_dma_capture(stream);
|
||||
wake_up(&stream->wq_stopped);
|
||||
}
|
||||
spin_lock_irqsave(&stream->vbq_lock, flags);
|
||||
if (stream->lack_buf_cnt == 2) {
|
||||
stream->to_stop_dma = true;
|
||||
rkcif_stop_dma_capture(stream);
|
||||
stream->is_stop_dma = true;
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
if (stream->to_en_scale) {
|
||||
stream->to_en_scale = false;
|
||||
rkcif_scale_start(stream->scale_vdev);
|
||||
|
||||
@@ -490,6 +490,8 @@ struct rkcif_stream {
|
||||
struct list_head rx_buf_head;
|
||||
int buf_num_toisp;
|
||||
u64 line_int_cnt;
|
||||
int lack_buf_cnt;
|
||||
bool is_stop_dma;
|
||||
bool stopping;
|
||||
bool crop_enable;
|
||||
bool crop_dyn_en;
|
||||
|
||||
Reference in New Issue
Block a user