From 1fc0f88577e197771b27161f2941918f0838da5c Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Thu, 13 Apr 2023 21:36:54 +0800 Subject: [PATCH 1/4] 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 Change-Id: I62d0dda18dbde45c7a161fdf7a85fd6219c90a31 --- drivers/media/platform/rockchip/cif/capture.c | 409 +++++++++++++++++- drivers/media/platform/rockchip/cif/dev.c | 100 +++++ drivers/media/platform/rockchip/cif/dev.h | 5 + 3 files changed, 502 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 74b2e09cb35e..2e5e72ad880a 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -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; } diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index c6988c76e38a..d5fe2010c6b4 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -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, }; diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 912e41abb48a..56df9877b985 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -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 { From 661fb29e155da8ebec12314242420f72cbac9205 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Fri, 26 Jan 2024 10:20:58 +0800 Subject: [PATCH 2/4] media: rockchip: vicap distinguish different interlace mode Signed-off-by: Zefa Chen Change-Id: I38ed270d9b063df3c5f572f2fba268c8f7d84091 --- drivers/media/platform/rockchip/cif/capture.c | 116 ++++++++++-------- drivers/media/platform/rockchip/cif/dev.c | 5 + drivers/media/platform/rockchip/cif/dev.h | 8 ++ 3 files changed, 76 insertions(+), 53 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 2e5e72ad880a..781028938897 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -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); diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index d5fe2010c6b4..3bb4cd737ad0 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -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); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 56df9877b985..9f2113408f96 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -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; From d611ab7d4022d30e5645445b8461b7259dfea3c5 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Thu, 1 Feb 2024 18:28:37 +0800 Subject: [PATCH 3/4] mtd: spinand: skyhigh: Fix devices information 1.The wrong QE bits will make a redundant write in status register. 2.The EBH dummy is 8 bytes, but we use 6BH cmd only. Change-Id: I6a19500340ab299f22f6e394e59a28430c6493a5 Signed-off-by: Jon Lin --- drivers/mtd/nand/spi/skyhigh.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/spi/skyhigh.c b/drivers/mtd/nand/spi/skyhigh.c index 3d075f12ed82..ae5a2d5c8b5f 100644 --- a/drivers/mtd/nand/spi/skyhigh.c +++ b/drivers/mtd/nand/spi/skyhigh.c @@ -14,7 +14,7 @@ #define SKYHIGH_STATUS_ECC_UNCOR_ERROR (3 << 4) static SPINAND_OP_VARIANTS(read_cache_variants, - SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 8, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), @@ -83,7 +83,7 @@ static const struct spinand_info skyhigh_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - SPINAND_HAS_QE_BIT, + 0, SPINAND_ECCINFO(&s35ml04g3_ooblayout, s35ml0xg3_ecc_get_status)), SPINAND_INFO("S35ML02G3", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25), @@ -92,7 +92,7 @@ static const struct spinand_info skyhigh_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - SPINAND_HAS_QE_BIT, + 0, SPINAND_ECCINFO(&s35ml04g3_ooblayout, s35ml0xg3_ecc_get_status)), SPINAND_INFO("S35ML04G3", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), @@ -101,7 +101,7 @@ static const struct spinand_info skyhigh_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - SPINAND_HAS_QE_BIT, + 0, SPINAND_ECCINFO(&s35ml04g3_ooblayout, s35ml0xg3_ecc_get_status)), }; From f4895714f4a155afc89647e4852c5c69c40b8e34 Mon Sep 17 00:00:00 2001 From: Wu Liangqing Date: Sun, 4 Feb 2024 01:40:29 +0000 Subject: [PATCH 4/4] arm64: dts: rockchip: rk3588-evb7-v11-imx415: remove cam_ircut0 cam_ircut0 ircut-open-gpios reused by typec Change-Id: Iac2f8f104175df7ff5c12b31c8215df837ce1aa2 Signed-off-by: Wu Liangqing --- arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-imx415.dtsi | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-imx415.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-imx415.dtsi index d5772ebb9d49..8a45e1b81b75 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-imx415.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-imx415.dtsi @@ -5,14 +5,6 @@ */ / { - cam_ircut0: cam_ircut { - status = "okay"; - compatible = "rockchip,ircut"; - ircut-open-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_HIGH>; - ircut-close-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_HIGH>; - rockchip,camera-module-index = <0>; - rockchip,camera-module-facing = "back"; - }; vcc_mipidphy0: vcc-mipidcphy0-regulator { compatible = "regulator-fixed"; gpio = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>; @@ -74,7 +66,6 @@ rockchip,camera-module-facing = "back"; rockchip,camera-module-name = "CMK-OT2022-PX1"; rockchip,camera-module-lens-name = "IR0147-50IRC-8M-F20"; - lens-focus = <&cam_ircut0>; port { imx415_out0: endpoint { remote-endpoint = <&mipidphy0_in_ucam0>;