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:
Zefa Chen
2023-04-13 21:36:54 +08:00
committed by Tao Huang
parent d12fe16c94
commit 1fc0f88577
3 changed files with 502 additions and 12 deletions

View File

@@ -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;
}

View File

@@ -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,
};

View File

@@ -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 {