media: rockchip: vicap distinguish different interlace mode

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: I38ed270d9b063df3c5f572f2fba268c8f7d84091
This commit is contained in:
Zefa Chen
2024-01-26 10:20:58 +08:00
committed by Tao Huang
parent 1fc0f88577
commit 661fb29e15
3 changed files with 76 additions and 53 deletions

View File

@@ -555,6 +555,19 @@ static const struct cif_input_fmt in_fmts[] = {
}
};
static inline int rkcif_get_interlace_mode(struct rkcif_stream *stream)
{
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (stream->cifdev->use_hw_interlace)
return RKCIF_INTERLACE_HW;
else if (stream->cifdev->chip_id >= CHIP_RK3568_CIF)
return RKCIF_INTERLACE_SOFT_AUTO;
else
return RKCIF_INTERLACE_SOFT;
}
return RKCIF_INTERLACE_NONE;
}
static int rkcif_output_fmt_check(struct rkcif_stream *stream,
const struct cif_output_fmt *output_fmt)
{
@@ -2423,7 +2436,7 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream,
}
}
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT) {
stream->next_buf = stream->curr_buf;
if (stream->next_buf) {
buff_addr_y = stream->next_buf->buff_addr[RKCIF_PLANE_Y];
@@ -2569,7 +2582,7 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
if (!dummy_buf->vaddr &&
stream->curr_buf == stream->next_buf &&
stream->cif_fmt_in->field != V4L2_FIELD_INTERLACED)
rkcif_get_interlace_mode(stream) != RKCIF_INTERLACE_SOFT)
ret = -EINVAL;
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
@@ -2587,7 +2600,7 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (!stream->next_buf)
ret = -EINVAL;
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT) {
if (stream->next_buf != stream->curr_buf) {
stream->next_buf = stream->curr_buf;
buffer = stream->next_buf;
@@ -2613,7 +2626,7 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf = NULL;
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT) {
stream->next_buf = stream->curr_buf;
buffer = stream->next_buf;
} else {
@@ -2642,7 +2655,7 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
if (buffer) {
buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y];
buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR];
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED &&
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT &&
stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
rkcif_write_buff_addr_multi_dev_combine(stream,
@@ -3054,7 +3067,8 @@ static void rkcif_assign_new_buffer_init_rockit(struct rkcif_stream *stream,
}
}
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) {
stream->next_buf_rockit = stream->curr_buf_rockit;
if (stream->next_buf_rockit) {
rkcif_write_register(dev, frm1_addr_y,
@@ -3164,7 +3178,8 @@ static int rkcif_assign_new_buffer_update_rockit(struct rkcif_stream *stream,
if (!dummy_buf->vaddr &&
stream->curr_buf_rockit == stream->next_buf_rockit &&
stream->cif_fmt_in->field != V4L2_FIELD_INTERLACED)
(rkcif_get_interlace_mode(stream) != RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO))
ret = -EINVAL;
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
@@ -3179,7 +3194,8 @@ static int rkcif_assign_new_buffer_update_rockit(struct rkcif_stream *stream,
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (!stream->next_buf_rockit)
ret = -EINVAL;
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) {
if (stream->next_buf_rockit != stream->curr_buf_rockit) {
stream->next_buf_rockit = stream->curr_buf_rockit;
buffer = stream->next_buf_rockit;
@@ -3202,7 +3218,8 @@ static int rkcif_assign_new_buffer_update_rockit(struct rkcif_stream *stream,
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf_rockit = NULL;
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) {
stream->next_buf_rockit = stream->curr_buf_rockit;
buffer = stream->next_buf_rockit;
} else {
@@ -3228,7 +3245,8 @@ static int rkcif_assign_new_buffer_update_rockit(struct rkcif_stream *stream,
stream->frame_phase_cache = stream->frame_phase;
if (buffer) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED &&
if ((rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) &&
stream->frame_phase == CIF_CSI_FRAME1_READY) {
rkcif_write_register(dev, frm_addr_y,
buffer->buff_addr[RKCIF_PLANE_Y] + (channel->virtual_width / 2));
@@ -3492,7 +3510,8 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream,
if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE)
channel->left_virtual_width *= 2;
}
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) {
channel->virtual_width *= 2;
channel->height /= 2;
}
@@ -3675,8 +3694,7 @@ static int rkcif_csi_channel_set(struct rkcif_stream *stream,
channel->crop_st_y << 16 | channel->crop_st_x);
/* Set up an buffer for the next frame */
if (dev->chip_id >= CHIP_RK3568_CIF &&
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO)
rkcif_buf_init_interlace(stream, channel->id);
else
rkcif_assign_new_buffer_pingpong(stream,
@@ -3998,8 +4016,7 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
channel->crop_st_y << 16 | channel->crop_st_x);
if (mode == RKCIF_STREAM_MODE_CAPTURE) {
if (dev->chip_id >= CHIP_RK3568_CIF &&
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO)
rkcif_buf_init_interlace(stream, channel->id);
else
rkcif_assign_new_buffer_pingpong(stream,
@@ -4368,7 +4385,6 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream,
struct rkcif_device *dev = stream->cifdev;
struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
struct rkcif_buffer *buffer = NULL;
struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf;
u32 frm_addr_y = 0, frm_addr_uv = 0;
u32 frm0_addr_y = 0, frm0_addr_uv = 0;
u32 frm1_addr_y = 0, frm1_addr_uv = 0;
@@ -4378,13 +4394,15 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream,
int frame_phase = 0;
bool is_dual_update_buf = false;
if (stream->state != RKCIF_STATE_STREAMING ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO)
return;
spin_lock_irqsave(&stream->vbq_lock, flags);
if (stream->state == RKCIF_STATE_STREAMING &&
((stream->curr_buf == stream->next_buf &&
stream->cif_fmt_in->field != V4L2_FIELD_INTERLACED &&
(!dummy_buf->vaddr)) ||
stream->curr_buf == NULL ||
stream->next_buf == NULL)) {
if (stream->curr_buf == stream->next_buf ||
stream->curr_buf == NULL ||
stream->next_buf == NULL) {
frame_phase = stream->frame_phase_cache;
if (!stream->is_line_wake_up ||
(stream->is_line_wake_up && stream->frame_idx < 2)) {
@@ -4421,19 +4439,14 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream,
if (buffer && is_dual_update_buf)
stream->next_buf = buffer;
} else if (frame_phase == CIF_CSI_FRAME1_READY) {
if (stream->next_buf == NULL &&
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
stream->next_buf = stream->curr_buf;
} else {
stream->next_buf = list_first_entry(&stream->buf_head,
struct rkcif_buffer, queue);
if (stream->next_buf) {
list_del(&stream->next_buf->queue);
buffer = stream->next_buf;
}
if (buffer && is_dual_update_buf)
stream->curr_buf = buffer;
stream->next_buf = list_first_entry(&stream->buf_head,
struct rkcif_buffer, queue);
if (stream->next_buf) {
list_del(&stream->next_buf->queue);
buffer = stream->next_buf;
}
if (buffer && is_dual_update_buf)
stream->curr_buf = buffer;
}
} else {
v4l2_info(&dev->v4l2_dev, "%s %d\n", __func__, __LINE__);
@@ -8855,7 +8868,8 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream,
stream->readout.wk_timestamp = vb_done->vb2_buf.timestamp;
spin_unlock_irqrestore(&stream->fps_lock, flags);
}
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO)
vb_done->sequence /= 2;
if (stream->cur_skip_frame) {
rkcif_buf_queue(&active_buf->vb.vb2_buf);
@@ -8873,9 +8887,9 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream,
}
if (cif_dev->hdr.hdr_mode == NO_HDR || cif_dev->hdr.hdr_mode == HDR_COMPR) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) {
if (stream->frame_phase == CIF_CSI_FRAME1_READY && active_buf) {
if (cif_dev->is_support_tools && stream->tools_vdev)
rkcif_buf_done_with_tools(stream, active_buf);
else
@@ -9200,8 +9214,8 @@ static void rkcif_deal_readout_time(struct rkcif_stream *stream)
}
static void rkcif_update_stream_interlace(struct rkcif_device *cif_dev,
struct rkcif_stream *stream,
int mipi_id)
struct rkcif_stream *stream,
int mipi_id)
{
struct rkcif_buffer *active_buf = NULL;
struct rkcif_dummy_buffer *dummy_buf = &cif_dev->hw_dev->dummy_buf;
@@ -9558,7 +9572,8 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev,
for (i = 0; i < j; i++) {
stream = resume_stream[i];
stream->fs_cnt_in_single_frame = 0;
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) {
if (stream->curr_buf == stream->next_buf) {
if (stream->curr_buf)
list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
@@ -11000,7 +11015,8 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode)
stream->is_single_cap = true;
spin_lock_irqsave(&stream->vbq_lock, flags);
if (!priv || priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT ||
rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) {
if (stream->curr_buf == stream->next_buf) {
if (stream->curr_buf)
list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
@@ -11505,8 +11521,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
"dma capture by vicap, is_updata %d, group mode %d, dma_en %d\n",
is_update, cif_dev->sync_cfg.type, stream->dma_en);
if (is_update) {
if (cif_dev->chip_id >= CHIP_RK3568_CIF &&
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO)
rkcif_update_stream_interlace(cif_dev, stream, mipi_id);
else
rkcif_update_stream(cif_dev, stream, mipi_id);
@@ -11614,8 +11629,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
if (stream->to_en_dma)
rkcif_enable_dma_capture(stream, false);
spin_unlock_irqrestore(&stream->vbq_lock, flags);
if (cif_dev->chip_id >= CHIP_RK3568_CIF &&
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO)
rkcif_check_mipi_interlaced_frame_id(stream);
}
if (intstat & CSI_LINE_INTSTAT_V1(i)) {
@@ -11630,8 +11644,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
if (cif_dev->sditf[0] && (cif_dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO ||
cif_dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME))
rkcif_line_wake_up_rdbk(stream, stream->id);
else if (cif_dev->chip_id >= CHIP_RK3568_CIF &&
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
else if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO)
rkcif_line_wake_up_interlace(stream, stream->id);
else
rkcif_line_wake_up(stream, stream->id);
@@ -11835,8 +11848,7 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev)
if (stream->crop_dyn_en)
rkcif_dynamic_crop(stream);
if (cif_dev->chip_id >= CHIP_RK3568_CIF &&
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO)
rkcif_update_stream_interlace(cif_dev, stream, mipi_id);
else
rkcif_update_stream(cif_dev, stream, mipi_id);
@@ -11867,16 +11879,14 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev)
spin_unlock_irqrestore(&stream->fps_lock, flags);
}
stream->is_in_vblank = false;
if (cif_dev->chip_id >= CHIP_RK3568_CIF &&
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO)
rkcif_check_mipi_interlaced_frame_id(stream);
}
if (intstat & CSI_LINE_INTSTAT(i)) {
stream = &cif_dev->stream[i];
if (stream->is_line_inten) {
stream->line_int_cnt++;
if (cif_dev->chip_id >= CHIP_RK3568_CIF &&
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO)
rkcif_line_wake_up_interlace(stream, stream->id);
else
rkcif_line_wake_up(stream, stream->id);

View File

@@ -2078,6 +2078,11 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
INIT_WORK(&cif_dev->sensor_work.work, rkcif_set_sensor_stream);
INIT_DELAYED_WORK(&cif_dev->work_deal_err, rkcif_deal_err_intr);
if (cif_dev->inf_id == RKCIF_MIPI_LVDS && cif_dev->chip_id <= CHIP_RK3562_CIF)
cif_dev->use_hw_interlace = false;
else
cif_dev->use_hw_interlace = true;
if (cif_dev->chip_id < CHIP_RV1126_CIF) {
if (cif_dev->inf_id == RKCIF_MIPI_LVDS) {
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID0);

View File

@@ -839,6 +839,13 @@ struct rkcif_sensor_work {
int on;
};
enum rkcif_interlace_mode {
RKCIF_INTERLACE_NONE,
RKCIF_INTERLACE_SOFT,
RKCIF_INTERLACE_SOFT_AUTO,
RKCIF_INTERLACE_HW,
};
/*
* struct rkcif_device - ISP platform device
* @base_addr: base register address
@@ -915,6 +922,7 @@ struct rkcif_device {
bool is_aov_reserved;
bool sensor_state_change;
bool is_toisp_reset;
bool use_hw_interlace;
int rdbk_debug;
struct rkcif_sync_cfg sync_cfg;
int sditf_cnt;