mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
media: rockchip: vicap: mipi interlaced capture support correct frame sequence
correct by frame num witch get from mipi fs/fe short packet, this function need rk356x and later chips to support Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com> Change-Id: I62d0dda18dbde45c7a161fdf7a85fd6219c90a31
This commit is contained in:
@@ -3525,6 +3525,73 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rkcif_write_buffer(struct rkcif_stream *stream, struct rkcif_buffer *buffer,
|
||||
int frame_phase, int even_offset)
|
||||
{
|
||||
struct rkcif_device *dev = stream->cifdev;
|
||||
struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf;
|
||||
u32 frm_addr_y, frm_addr_uv;
|
||||
struct csi_channel_info *channel = &dev->channels[stream->id];
|
||||
|
||||
if (frame_phase == CIF_CSI_FRAME0_READY) {
|
||||
frm_addr_y = get_reg_index_of_frm0_y_addr(stream->id);
|
||||
frm_addr_uv = get_reg_index_of_frm0_uv_addr(stream->id);
|
||||
} else {
|
||||
frm_addr_y = get_reg_index_of_frm1_y_addr(stream->id);
|
||||
frm_addr_uv = get_reg_index_of_frm1_uv_addr(stream->id);
|
||||
}
|
||||
if (buffer) {
|
||||
rkcif_write_register(dev, frm_addr_y,
|
||||
buffer->buff_addr[RKCIF_PLANE_Y] + even_offset *
|
||||
(channel->virtual_width / 2));
|
||||
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
|
||||
rkcif_write_register(dev, frm_addr_uv,
|
||||
buffer->buff_addr[RKCIF_PLANE_CBCR] +
|
||||
even_offset * (channel->virtual_width / 2));
|
||||
} else if (dummy_buf->vaddr) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void rkcif_buf_init_interlace(struct rkcif_stream *stream, int channel_id)
|
||||
{
|
||||
struct rkcif_device *dev = stream->cifdev;
|
||||
unsigned long flags;
|
||||
struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf;
|
||||
int buf_offset = 0;
|
||||
|
||||
spin_lock_irqsave(&stream->vbq_lock, flags);
|
||||
if (!stream->curr_buf) {
|
||||
if (!list_empty(&stream->buf_head)) {
|
||||
stream->curr_buf = list_first_entry(&stream->buf_head,
|
||||
struct rkcif_buffer,
|
||||
queue);
|
||||
list_del(&stream->curr_buf->queue);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
|
||||
if (!stream->odd_frame_first)
|
||||
buf_offset = 1;
|
||||
|
||||
if (stream->curr_buf) {
|
||||
rkcif_write_buffer(stream, stream->curr_buf, CIF_CSI_FRAME0_READY, buf_offset);
|
||||
rkcif_write_buffer(stream, stream->curr_buf, CIF_CSI_FRAME1_READY, buf_offset);
|
||||
} else {
|
||||
if (dummy_buf->vaddr) {
|
||||
rkcif_write_buffer(stream, NULL, CIF_CSI_FRAME0_READY, 0);
|
||||
rkcif_write_buffer(stream, NULL, CIF_CSI_FRAME1_READY, 0);
|
||||
} else {
|
||||
v4l2_err(&dev->v4l2_dev,
|
||||
"stream[%d] mipi interlace not buf, if cap_en, may cause system death\n",
|
||||
stream->id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int rkcif_csi_channel_set(struct rkcif_stream *stream,
|
||||
struct csi_channel_info *channel,
|
||||
enum v4l2_mbus_type mbus_type)
|
||||
@@ -3608,7 +3675,11 @@ 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 */
|
||||
rkcif_assign_new_buffer_pingpong(stream,
|
||||
if (dev->chip_id >= CHIP_RK3568_CIF &&
|
||||
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
|
||||
rkcif_buf_init_interlace(stream, channel->id);
|
||||
else
|
||||
rkcif_assign_new_buffer_pingpong(stream,
|
||||
RKCIF_YUV_ADDR_STATE_INIT,
|
||||
channel->id);
|
||||
|
||||
@@ -3926,19 +3997,24 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
|
||||
rkcif_write_register(dev, get_reg_index_of_id_crop_start(channel->id),
|
||||
channel->crop_st_y << 16 | channel->crop_st_x);
|
||||
|
||||
if (mode == RKCIF_STREAM_MODE_CAPTURE)
|
||||
rkcif_assign_new_buffer_pingpong(stream,
|
||||
RKCIF_YUV_ADDR_STATE_INIT,
|
||||
channel->id);
|
||||
else if (mode == RKCIF_STREAM_MODE_TOISP ||
|
||||
mode == RKCIF_STREAM_MODE_TOISP_RDBK)
|
||||
if (mode == RKCIF_STREAM_MODE_CAPTURE) {
|
||||
if (dev->chip_id >= CHIP_RK3568_CIF &&
|
||||
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
|
||||
rkcif_buf_init_interlace(stream, channel->id);
|
||||
else
|
||||
rkcif_assign_new_buffer_pingpong(stream,
|
||||
RKCIF_YUV_ADDR_STATE_INIT,
|
||||
channel->id);
|
||||
} else if (mode == RKCIF_STREAM_MODE_TOISP ||
|
||||
mode == RKCIF_STREAM_MODE_TOISP_RDBK) {
|
||||
rkcif_assign_new_buffer_pingpong_toisp(stream,
|
||||
RKCIF_YUV_ADDR_STATE_INIT,
|
||||
channel->id);
|
||||
else if (mode == RKCIF_STREAM_MODE_ROCKIT)
|
||||
} else if (mode == RKCIF_STREAM_MODE_ROCKIT) {
|
||||
rkcif_assign_new_buffer_pingpong_rockit(stream,
|
||||
RKCIF_YUV_ADDR_STATE_INIT,
|
||||
channel->id);
|
||||
}
|
||||
|
||||
if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE &&
|
||||
index == (capture_info->multi_dev.dev_num - 1) &&
|
||||
@@ -4052,6 +4128,9 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode
|
||||
stream->is_in_vblank = false;
|
||||
stream->is_change_toisp = false;
|
||||
}
|
||||
stream->interlaced_bad_frame = false;
|
||||
stream->last_fs_interlaced_phase = 0;
|
||||
stream->last_fe_interlaced_phase = 0;
|
||||
|
||||
rkcif_csi_get_vc_num(dev, flags);
|
||||
|
||||
@@ -8876,6 +8955,69 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream,
|
||||
|
||||
}
|
||||
|
||||
static void rkcif_line_wake_up_interlace(struct rkcif_stream *stream,
|
||||
int mipi_id)
|
||||
{
|
||||
struct rkcif_device *cif_dev = stream->cifdev;
|
||||
struct rkcif_buffer *active_buf = NULL;
|
||||
struct rkcif_dummy_buffer *dummy_buf = &cif_dev->hw_dev->dummy_buf;
|
||||
int frame_id = 0;
|
||||
int fe_interlaced_phase = 0;
|
||||
|
||||
if (stream->id == 0)
|
||||
frame_id = rkcif_read_register(cif_dev, CIF_REG_MIPI_FRAME_NUM_VC0);
|
||||
else if (stream->id == 1)
|
||||
frame_id = rkcif_read_register(cif_dev, CIF_REG_MIPI_FRAME_NUM_VC1);
|
||||
else if (stream->id == 2)
|
||||
frame_id = rkcif_read_register(cif_dev, CIF_REG_MIPI_FRAME_NUM_VC2);
|
||||
else if (stream->id == 3)
|
||||
frame_id = rkcif_read_register(cif_dev, CIF_REG_MIPI_FRAME_NUM_VC3);
|
||||
|
||||
if ((frame_id & 0xffff) % 2 == stream->odd_frame_id) {
|
||||
//odd frame
|
||||
if (stream->odd_frame_first)
|
||||
fe_interlaced_phase = CIF_CSI_FRAME0_READY;
|
||||
else
|
||||
fe_interlaced_phase = CIF_CSI_FRAME1_READY;
|
||||
} else {
|
||||
//even frame
|
||||
if (stream->odd_frame_first)
|
||||
fe_interlaced_phase = CIF_CSI_FRAME1_READY;
|
||||
else
|
||||
fe_interlaced_phase = CIF_CSI_FRAME0_READY;
|
||||
}
|
||||
|
||||
v4l2_dbg(rkcif_debug, 3, &cif_dev->v4l2_dev,
|
||||
"stream[%d] mipi fe interlace phase %d, frame num 0x%x\n",
|
||||
stream->id, fe_interlaced_phase, frame_id);
|
||||
|
||||
if (fe_interlaced_phase == CIF_CSI_FRAME1_READY &&
|
||||
stream->last_fe_interlaced_phase == CIF_CSI_FRAME0_READY) {
|
||||
if (dummy_buf->vaddr || stream->next_buf) {
|
||||
active_buf = stream->curr_buf;
|
||||
if (active_buf) {
|
||||
active_buf->vb.vb2_buf.timestamp = stream->readout.fs_timestamp;
|
||||
active_buf->vb.sequence = (stream->frame_idx - 1) / 2;
|
||||
if (stream->interlaced_bad_frame) {
|
||||
stream->interlaced_bad_frame = false;
|
||||
rkcif_buf_queue(&active_buf->vb.vb2_buf);
|
||||
v4l2_dbg(rkcif_debug, 3, &cif_dev->v4l2_dev,
|
||||
"stream[%d] mipi fe interlace bad frame queue, phase %d, line %d\n",
|
||||
stream->id, fe_interlaced_phase, __LINE__);
|
||||
} else {
|
||||
rkcif_vb_done_tasklet(stream, active_buf);
|
||||
}
|
||||
stream->curr_buf = stream->next_buf;
|
||||
stream->next_buf = NULL;
|
||||
} else {
|
||||
stream->curr_buf = stream->next_buf;
|
||||
stream->next_buf = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
stream->last_fe_interlaced_phase = fe_interlaced_phase;
|
||||
}
|
||||
|
||||
static void rkcif_line_wake_up(struct rkcif_stream *stream, int mipi_id)
|
||||
{
|
||||
u32 mode;
|
||||
@@ -9057,6 +9199,82 @@ static void rkcif_deal_readout_time(struct rkcif_stream *stream)
|
||||
spin_unlock_irqrestore(&stream->fps_lock, flags);
|
||||
}
|
||||
|
||||
static void rkcif_update_stream_interlace(struct rkcif_device *cif_dev,
|
||||
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;
|
||||
unsigned long flags;
|
||||
int frame_id = 0;
|
||||
int fe_interlaced_phase = 0;
|
||||
|
||||
if (stream->id == 0)
|
||||
frame_id = rkcif_read_register(cif_dev, CIF_REG_MIPI_FRAME_NUM_VC0);
|
||||
else if (stream->id == 1)
|
||||
frame_id = rkcif_read_register(cif_dev, CIF_REG_MIPI_FRAME_NUM_VC1);
|
||||
else if (stream->id == 2)
|
||||
frame_id = rkcif_read_register(cif_dev, CIF_REG_MIPI_FRAME_NUM_VC2);
|
||||
else if (stream->id == 3)
|
||||
frame_id = rkcif_read_register(cif_dev, CIF_REG_MIPI_FRAME_NUM_VC3);
|
||||
|
||||
if ((frame_id & 0xffff) % 2 == stream->odd_frame_id) {
|
||||
//odd frame
|
||||
if (stream->odd_frame_first)
|
||||
fe_interlaced_phase = CIF_CSI_FRAME0_READY;
|
||||
else
|
||||
fe_interlaced_phase = CIF_CSI_FRAME1_READY;
|
||||
} else {
|
||||
//even frame
|
||||
if (stream->odd_frame_first)
|
||||
fe_interlaced_phase = CIF_CSI_FRAME1_READY;
|
||||
else
|
||||
fe_interlaced_phase = CIF_CSI_FRAME0_READY;
|
||||
}
|
||||
|
||||
v4l2_dbg(rkcif_debug, 3, &cif_dev->v4l2_dev,
|
||||
"stream[%d] mipi fe interlace phase %d, frame num 0x%x\n",
|
||||
stream->id, fe_interlaced_phase, frame_id);
|
||||
|
||||
if (!stream->is_line_wake_up) {
|
||||
spin_lock_irqsave(&stream->fps_lock, flags);
|
||||
if (stream->frame_phase & CIF_CSI_FRAME0_READY)
|
||||
stream->fps_stats.frm0_timestamp = ktime_get_ns();
|
||||
else if (stream->frame_phase & CIF_CSI_FRAME1_READY)
|
||||
stream->fps_stats.frm1_timestamp = ktime_get_ns();
|
||||
spin_unlock_irqrestore(&stream->fps_lock, flags);
|
||||
}
|
||||
|
||||
if (!stream->is_line_wake_up) {
|
||||
if (fe_interlaced_phase == CIF_CSI_FRAME1_READY &&
|
||||
stream->last_fe_interlaced_phase == CIF_CSI_FRAME0_READY) {
|
||||
if (dummy_buf->vaddr || stream->next_buf) {
|
||||
active_buf = stream->curr_buf;
|
||||
if (active_buf) {
|
||||
active_buf->vb.vb2_buf.timestamp = stream->readout.fs_timestamp;
|
||||
active_buf->vb.sequence = (stream->frame_idx - 1) / 2;
|
||||
if (stream->interlaced_bad_frame) {
|
||||
stream->interlaced_bad_frame = false;
|
||||
rkcif_buf_queue(&active_buf->vb.vb2_buf);
|
||||
v4l2_dbg(rkcif_debug, 3, &cif_dev->v4l2_dev,
|
||||
"stream[%d] mipi fe interlace bad frame queue, phase %d, line %d\n",
|
||||
stream->id, fe_interlaced_phase, __LINE__);
|
||||
} else {
|
||||
rkcif_vb_done_tasklet(stream, active_buf);
|
||||
}
|
||||
stream->curr_buf = stream->next_buf;
|
||||
stream->next_buf = NULL;
|
||||
} else {
|
||||
stream->curr_buf = stream->next_buf;
|
||||
stream->next_buf = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rkcif_deal_readout_time(stream);
|
||||
stream->last_fe_interlaced_phase = fe_interlaced_phase;
|
||||
}
|
||||
|
||||
static void rkcif_update_stream(struct rkcif_device *cif_dev,
|
||||
struct rkcif_stream *stream,
|
||||
int mipi_id)
|
||||
@@ -10994,6 +11212,151 @@ void rkcif_err_print_work(struct work_struct *work)
|
||||
intstat, lastline);
|
||||
}
|
||||
|
||||
static void rkcif_check_mipi_interlaced_frame_id(struct rkcif_stream *stream)
|
||||
{
|
||||
struct rkcif_device *dev = stream->cifdev;
|
||||
struct rkcif_buffer *buffer = NULL;
|
||||
struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf;
|
||||
int frame_id = 0;
|
||||
int fs_interlaced_phase = 0;
|
||||
unsigned long flags;
|
||||
int buf_offset = 0;
|
||||
|
||||
if (stream->id == 0)
|
||||
frame_id = rkcif_read_register(dev, CIF_REG_MIPI_FRAME_NUM_VC0);
|
||||
else if (stream->id == 1)
|
||||
frame_id = rkcif_read_register(dev, CIF_REG_MIPI_FRAME_NUM_VC1);
|
||||
else if (stream->id == 2)
|
||||
frame_id = rkcif_read_register(dev, CIF_REG_MIPI_FRAME_NUM_VC2);
|
||||
else if (stream->id == 3)
|
||||
frame_id = rkcif_read_register(dev, CIF_REG_MIPI_FRAME_NUM_VC3);
|
||||
|
||||
if ((frame_id & 0xffff) % 2 == stream->odd_frame_id) {
|
||||
//odd frame
|
||||
if (stream->odd_frame_first) {
|
||||
fs_interlaced_phase = CIF_CSI_FRAME0_READY;
|
||||
buf_offset = 1;
|
||||
} else {
|
||||
fs_interlaced_phase = CIF_CSI_FRAME1_READY;
|
||||
buf_offset = 1;
|
||||
}
|
||||
} else {
|
||||
//even frame
|
||||
if (stream->odd_frame_first) {
|
||||
fs_interlaced_phase = CIF_CSI_FRAME1_READY;
|
||||
buf_offset = 0;
|
||||
} else {
|
||||
fs_interlaced_phase = CIF_CSI_FRAME0_READY;
|
||||
buf_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
v4l2_dbg(rkcif_debug, 3, &dev->v4l2_dev,
|
||||
"stream[%d] mipi fs interlace phase %d, frame num 0x%x\n",
|
||||
stream->id, fs_interlaced_phase, frame_id);
|
||||
if (stream->last_fs_interlaced_phase == 0) {
|
||||
buffer = stream->curr_buf;
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME0_READY, buf_offset);
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME1_READY, buf_offset);
|
||||
} else {
|
||||
if (fs_interlaced_phase == CIF_CSI_FRAME0_READY) {
|
||||
buffer = stream->curr_buf;
|
||||
if (stream->last_fs_interlaced_phase == CIF_CSI_FRAME1_READY) {
|
||||
if (stream->last_fe_interlaced_phase == CIF_CSI_FRAME0_READY) {
|
||||
if (buffer)
|
||||
rkcif_buf_queue(&buffer->vb.vb2_buf);
|
||||
stream->curr_buf = stream->next_buf;
|
||||
stream->next_buf = NULL;
|
||||
buffer = stream->curr_buf;
|
||||
stream->last_fe_interlaced_phase = CIF_CSI_FRAME1_READY;
|
||||
v4l2_dbg(rkcif_debug, 3, &dev->v4l2_dev,
|
||||
"stream[%d] mipi fs interlace bad frame queue, phase %d, line %d\n",
|
||||
stream->id, fs_interlaced_phase, __LINE__);
|
||||
}
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME0_READY, buf_offset);
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME1_READY, buf_offset);
|
||||
} else if (stream->last_fs_interlaced_phase == CIF_CSI_FRAME0_READY) {
|
||||
stream->interlaced_bad_frame = true;
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME0_READY, buf_offset);
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME1_READY, buf_offset);
|
||||
v4l2_dbg(rkcif_debug, 3, &dev->v4l2_dev,
|
||||
"stream[%d] mipi fs interlace bad frame, phase %d, line %d\n",
|
||||
stream->id, fs_interlaced_phase, __LINE__);
|
||||
}
|
||||
} else {
|
||||
if (stream->last_fs_interlaced_phase == CIF_CSI_FRAME0_READY) {
|
||||
if (stream->next_buf) {
|
||||
if (stream->curr_buf) {
|
||||
rkcif_buf_queue(&stream->curr_buf->vb.vb2_buf);
|
||||
stream->curr_buf = stream->next_buf;
|
||||
stream->next_buf = NULL;
|
||||
}
|
||||
stream->interlaced_bad_frame = true;
|
||||
v4l2_dbg(rkcif_debug, 3, &dev->v4l2_dev,
|
||||
"stream[%d] mipi fs interlace bad frame, phase %d\n",
|
||||
stream->id, fs_interlaced_phase);
|
||||
}
|
||||
spin_lock_irqsave(&stream->vbq_lock, flags);
|
||||
if (!list_empty(&stream->buf_head)) {
|
||||
buffer = list_first_entry(&stream->buf_head,
|
||||
struct rkcif_buffer, queue);
|
||||
list_del(&buffer->queue);
|
||||
stream->next_buf = buffer;
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, flags);
|
||||
if (buffer) {
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME0_READY, buf_offset);
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME1_READY, buf_offset);
|
||||
} else if (dummy_buf->vaddr) {
|
||||
stream->interlaced_bad_frame = true;
|
||||
rkcif_write_buffer(stream, NULL, CIF_CSI_FRAME0_READY, buf_offset);
|
||||
rkcif_write_buffer(stream, NULL, CIF_CSI_FRAME1_READY, buf_offset);
|
||||
v4l2_dbg(rkcif_debug, 3, &dev->v4l2_dev,
|
||||
"stream[%d] mipi interlace not buf, use dummy buf, line %d\n",
|
||||
stream->id, __LINE__);
|
||||
} else {
|
||||
v4l2_dbg(rkcif_debug, 3, &dev->v4l2_dev,
|
||||
"stream[%d] mipi interlace not buf, may overwrite buf, line %d\n",
|
||||
stream->id, __LINE__);
|
||||
}
|
||||
} else {
|
||||
if (stream->last_fe_interlaced_phase != CIF_CSI_FRAME1_READY) {
|
||||
buffer = stream->curr_buf;
|
||||
if (buffer)
|
||||
rkcif_buf_queue(&buffer->vb.vb2_buf);
|
||||
stream->curr_buf = stream->next_buf;
|
||||
stream->next_buf = NULL;
|
||||
stream->last_fe_interlaced_phase = CIF_CSI_FRAME1_READY;
|
||||
v4l2_dbg(rkcif_debug, 3, &dev->v4l2_dev,
|
||||
"stream[%d] mipi fs interlace bad frame queue, phase %d, line %d\n",
|
||||
stream->id, fs_interlaced_phase, __LINE__);
|
||||
}
|
||||
if (stream->next_buf) {
|
||||
buffer = stream->next_buf;
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME0_READY, buf_offset);
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME1_READY, buf_offset);
|
||||
} else if (stream->curr_buf) {
|
||||
buffer = stream->curr_buf;
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME0_READY, buf_offset);
|
||||
rkcif_write_buffer(stream, buffer, CIF_CSI_FRAME1_READY, buf_offset);
|
||||
} else if (dummy_buf->vaddr) {
|
||||
rkcif_write_buffer(stream, NULL, CIF_CSI_FRAME0_READY, buf_offset);
|
||||
rkcif_write_buffer(stream, NULL, CIF_CSI_FRAME1_READY, buf_offset);
|
||||
stream->interlaced_bad_frame = true;
|
||||
v4l2_dbg(rkcif_debug, 3, &dev->v4l2_dev,
|
||||
"stream[%d] mipi interlace not buf, use dummy buf, line %d\n",
|
||||
stream->id, __LINE__);
|
||||
} else {
|
||||
v4l2_dbg(rkcif_debug, 3, &dev->v4l2_dev,
|
||||
"stream[%d] mipi interlace not buf, may overwrite buf, line %d\n",
|
||||
stream->id, __LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stream->last_fs_interlaced_phase = fs_interlaced_phase;
|
||||
}
|
||||
|
||||
/* pingpong irq for rk3588 and next */
|
||||
void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
|
||||
{
|
||||
@@ -11141,8 +11504,13 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
|
||||
v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_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)
|
||||
rkcif_update_stream(cif_dev, stream, mipi_id);
|
||||
if (is_update) {
|
||||
if (cif_dev->chip_id >= CHIP_RK3568_CIF &&
|
||||
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
|
||||
rkcif_update_stream_interlace(cif_dev, stream, mipi_id);
|
||||
else
|
||||
rkcif_update_stream(cif_dev, stream, mipi_id);
|
||||
}
|
||||
} else if (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
|
||||
v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_dev,
|
||||
"dma capture by isp, dma_en 0x%x\n",
|
||||
@@ -11246,6 +11614,9 @@ 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)
|
||||
rkcif_check_mipi_interlaced_frame_id(stream);
|
||||
}
|
||||
if (intstat & CSI_LINE_INTSTAT_V1(i)) {
|
||||
stream = &cif_dev->stream[i];
|
||||
@@ -11259,6 +11630,9 @@ 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)
|
||||
rkcif_line_wake_up_interlace(stream, stream->id);
|
||||
else
|
||||
rkcif_line_wake_up(stream, stream->id);
|
||||
rkcif_modify_line_int(stream, false);
|
||||
@@ -11461,7 +11835,11 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev)
|
||||
if (stream->crop_dyn_en)
|
||||
rkcif_dynamic_crop(stream);
|
||||
|
||||
rkcif_update_stream(cif_dev, stream, mipi_id);
|
||||
if (cif_dev->chip_id >= CHIP_RK3568_CIF &&
|
||||
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
|
||||
rkcif_update_stream_interlace(cif_dev, stream, mipi_id);
|
||||
else
|
||||
rkcif_update_stream(cif_dev, stream, mipi_id);
|
||||
rkcif_detect_wake_up_mode_change(stream);
|
||||
rkcif_monitor_reset_event(cif_dev);
|
||||
if (mipi_id == RKCIF_STREAM_MIPI_ID0) {
|
||||
@@ -11489,12 +11867,19 @@ 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)
|
||||
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++;
|
||||
rkcif_line_wake_up(stream, stream->id);
|
||||
if (cif_dev->chip_id >= CHIP_RK3568_CIF &&
|
||||
stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
|
||||
rkcif_line_wake_up_interlace(stream, stream->id);
|
||||
else
|
||||
rkcif_line_wake_up(stream, stream->id);
|
||||
rkcif_modify_line_int(stream, false);
|
||||
stream->is_line_inten = false;
|
||||
}
|
||||
|
||||
@@ -599,6 +599,104 @@ static ssize_t rkcif_store_rdbk_debug(struct device *dev,
|
||||
}
|
||||
static DEVICE_ATTR(rdbk_debug, 0200, rkcif_show_rdbk_debug, rkcif_store_rdbk_debug);
|
||||
|
||||
static ssize_t rkcif_show_odd_frame_id(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
|
||||
cif_dev->stream[0].odd_frame_id ? 1 : 0,
|
||||
cif_dev->stream[1].odd_frame_id ? 1 : 0,
|
||||
cif_dev->stream[2].odd_frame_id ? 1 : 0,
|
||||
cif_dev->stream[3].odd_frame_id ? 1 : 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rkcif_store_odd_frame_id(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int i, index;
|
||||
char val[4];
|
||||
|
||||
if (buf) {
|
||||
index = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i] == ' ')
|
||||
continue;
|
||||
else if (buf[i] == '\0')
|
||||
break;
|
||||
val[index] = buf[i];
|
||||
index++;
|
||||
if (index == 4)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < index; i++) {
|
||||
if (val[i] - '0' == 0)
|
||||
cif_dev->stream[i].odd_frame_id = 0;
|
||||
else
|
||||
cif_dev->stream[i].odd_frame_id = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
static DEVICE_ATTR(odd_frame_id, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_odd_frame_id, rkcif_store_odd_frame_id);
|
||||
|
||||
static ssize_t rkcif_show_odd_frame_fisrt(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
|
||||
cif_dev->stream[0].odd_frame_first ? 1 : 0,
|
||||
cif_dev->stream[1].odd_frame_first ? 1 : 0,
|
||||
cif_dev->stream[2].odd_frame_first ? 1 : 0,
|
||||
cif_dev->stream[3].odd_frame_first ? 1 : 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rkcif_store_odd_frame_fisrt(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int i, index;
|
||||
char val[4];
|
||||
|
||||
if (buf) {
|
||||
index = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i] == ' ')
|
||||
continue;
|
||||
else if (buf[i] == '\0')
|
||||
break;
|
||||
val[index] = buf[i];
|
||||
index++;
|
||||
if (index == 4)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < index; i++) {
|
||||
if (val[i] - '0' == 0)
|
||||
cif_dev->stream[i].odd_frame_first = 0;
|
||||
else
|
||||
cif_dev->stream[i].odd_frame_first = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
static DEVICE_ATTR(odd_frame_first, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_odd_frame_fisrt, rkcif_store_odd_frame_fisrt);
|
||||
|
||||
static struct attribute *dev_attrs[] = {
|
||||
&dev_attr_compact_test.attr,
|
||||
&dev_attr_wait_line.attr,
|
||||
@@ -610,6 +708,8 @@ static struct attribute *dev_attrs[] = {
|
||||
&dev_attr_scale_ch3_blc.attr,
|
||||
&dev_attr_fps.attr,
|
||||
&dev_attr_rdbk_debug.attr,
|
||||
&dev_attr_odd_frame_id.attr,
|
||||
&dev_attr_odd_frame_first.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
@@ -512,6 +512,10 @@ struct rkcif_stream {
|
||||
unsigned int frame_idx;
|
||||
int frame_phase;
|
||||
int frame_phase_cache;
|
||||
int last_fs_interlaced_phase;
|
||||
int last_fe_interlaced_phase;
|
||||
int odd_frame_id;
|
||||
int odd_frame_first;
|
||||
unsigned int crop_mask;
|
||||
/* lock between irq and buf_queue */
|
||||
struct list_head buf_head;
|
||||
@@ -583,6 +587,7 @@ struct rkcif_stream {
|
||||
bool is_wait_dma_stop;
|
||||
bool is_single_cap;
|
||||
bool is_wait_stop_complete;
|
||||
bool interlaced_bad_frame;
|
||||
};
|
||||
|
||||
struct rkcif_lvds_subdev {
|
||||
|
||||
Reference in New Issue
Block a user