From febc2c13b579a5c9cabb4a95055d48a2bb794dd7 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Fri, 1 Nov 2024 10:08:30 +0800 Subject: [PATCH] media: rockchip: vicap: sync with kernel-5.10 Merge from kernel-5.10 media: rockchip: vicap skip fs/fe match detect when use smartsens sensor and work with hdr mode media: vicap: fixed the sequence not increasing in one frame mode media: rockchip: vicap support soft sync mode media: rockchip: vicap support get timestamp for rtt_stream_on buffer media: rockchip: vicap support mipi/dvp reset together below rk3588 media: rockchip: vicap fixes error of frame interval info media: rockchip: vicap remove interrupt flags of IRQF_SHARED for rv1106/rv1103b media: rockchip: vicap fixes error of buf update seconds in one frame interval media: rockchip: vicap fixes lack_buf_cnt error media: rockchip: vicap clean to_stop_dma state before start stream media: rockchip: vicap fixes error of rtt stream on media: rockchip: vicap add pipe stop stream to function of shutdown media: rockchip: vicap skip direct reset when size err occurs and work in online mode media: rockchip: vicap proc node add group info media: rockchip: vicap: error print of mipi csi2 add base address to distinguish device media: rockchip: vicap fixes error of wake up time in thundboot mode media: rockchip: vicap support rtt stream on media: rockchip: vicap make sure sequence of first frame send to isp is zero media: rockchip: vicap rdbk_auto mode support group sync media: rockchip: vicap add register debug info to proc node media: rockchip: vicap support online_unite with thunderboot media: rockchip: vicap support set csi2 quick stream on/off media: rockchip: vicap fixes logic of thunderboot skip media: rockchip: vicap clean fs intr state before set fs intr enable media: rockchip: vicap use addr force update to replace dma reset for chip after rk3562 media: rockchip: vicap add complete for restart stream with aov media: rockchip: vicap fixes soft reset error of chips after rv1103b media: rockchip: vicap set capture mode to isp when resume one frame mode media: rockchip: vicap remove line intr disable each frame after rk3588 media: rockchip: vicap wait fe to stop stream when stream suspend media: rockchip: vicap remove cif-rockit init limit media: rockchip: vicap add vblank check media: rockchip: vicap: fastboot reserved buffer count according to isp media: rockchip: vicap: single dev need to config toisp when resume media: rockchip: vicap fixes null point of cur_stream media: rockchip: vicap disable fs inf intr when stop dma capture to reduce unnecessary intr consume media: rockchip: vicap fixes error of common dual camera aov media: rockchip: vicap add frame skipping to ensure frame integrity when using sensor flip media: rockchip: vicap remove limit of x_offset/y_offset media: rockchip: vicap support rounding 2/4bit for rv1103b media: rockchip: vicap support online hdr wrap for rv1103b media: rockchip: vicap fixes cru rst sequence of rv1103b media: rockchip: vicap fixes stream off issue when restart to multi frame mode media: rockchip: rv1103b vicap support online unite media: rockchip: vicap move toisp stop operation to toisp fs for more secure media: rockchip: vicap fixes same error with more toisp mode media: rockchip: vicap change work mode according to isp media: rockchip: vicap support rv1103b media: rockchip: vicap fixes isp timeout error media: rockchip: vicap fixes error of multi frame mode to singgle frame media: rockchip: vicap: rv1106 isp_unite not support change to online media: rockchip: vicap: rv1106 unite fixes error of write toisp register media: rockchip: vicap: rv1106 unite fix loss stream frame one frame to multi frame mode media: rockchip: vicap support distinguish toisp on/off media: rockchip: vicap check dev cnt acording to rkisp sd cxonnect state media: rockchip: vicap fixes error call soft reset below rk3588 media: rockchip: vicap support change to multi frame mode during capture in one frame mode media: rockchip: vicap add limit of rdbk_mode from app for aov media: rockchip: vicap fixes stream loss with rockit media: rockchip: vicap wait thunderboot ready when open video Signed-off-by: Zefa Chen Change-Id: Icc7c03e5d15bd4ea789deaa785a4534eafd53ce9 --- drivers/media/platform/rockchip/cif/capture.c | 1771 +++++++++++++---- .../media/platform/rockchip/cif/cif-rockit.c | 2 + drivers/media/platform/rockchip/cif/common.c | 5 +- drivers/media/platform/rockchip/cif/dev.c | 151 +- drivers/media/platform/rockchip/cif/dev.h | 49 +- drivers/media/platform/rockchip/cif/hw.c | 131 +- drivers/media/platform/rockchip/cif/hw.h | 7 +- .../media/platform/rockchip/cif/mipi-csi2.c | 77 +- .../media/platform/rockchip/cif/mipi-csi2.h | 3 + drivers/media/platform/rockchip/cif/procfs.c | 292 ++- drivers/media/platform/rockchip/cif/regs.h | 22 + .../media/platform/rockchip/cif/subdev-itf.c | 485 +++-- .../media/platform/rockchip/cif/subdev-itf.h | 4 + 13 files changed, 2406 insertions(+), 593 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index a891fe6d0343..1bbf0a98968d 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "dev.h" #include "mipi-csi2.h" @@ -669,8 +671,17 @@ static int rkcif_output_fmt_check(struct rkcif_stream *stream, output_fmt->fourcc == V4L2_PIX_FMT_SGRBG10 || output_fmt->fourcc == V4L2_PIX_FMT_SGBRG10 || output_fmt->fourcc == V4L2_PIX_FMT_SBGGR10 || - output_fmt->fourcc == V4L2_PIX_FMT_Y10) + output_fmt->fourcc == V4L2_PIX_FMT_Y10) { ret = 0; + } else if (stream->cifdev->chip_id == CHIP_RV1103B_CIF && + (output_fmt->fourcc == V4L2_PIX_FMT_SRGGB8 || + output_fmt->fourcc == V4L2_PIX_FMT_SGRBG8 || + output_fmt->fourcc == V4L2_PIX_FMT_SGBRG8 || + output_fmt->fourcc == V4L2_PIX_FMT_SBGGR8 || + output_fmt->fourcc == V4L2_PIX_FMT_GREY)) { + ret = 0; + stream->rounding_bit = ROUNDING_2BIT_RV1103B; + } break; case MEDIA_BUS_FMT_SBGGR12_1X12: case MEDIA_BUS_FMT_SGBRG12_1X12: @@ -681,8 +692,25 @@ static int rkcif_output_fmt_check(struct rkcif_stream *stream, output_fmt->fourcc == V4L2_PIX_FMT_SGRBG12 || output_fmt->fourcc == V4L2_PIX_FMT_SGBRG12 || output_fmt->fourcc == V4L2_PIX_FMT_SBGGR12 || - output_fmt->fourcc == V4L2_PIX_FMT_Y12) + output_fmt->fourcc == V4L2_PIX_FMT_Y12) { ret = 0; + } else if (stream->cifdev->chip_id == CHIP_RV1103B_CIF && + (output_fmt->fourcc == V4L2_PIX_FMT_SRGGB10 || + output_fmt->fourcc == V4L2_PIX_FMT_SGRBG10 || + output_fmt->fourcc == V4L2_PIX_FMT_SGBRG10 || + output_fmt->fourcc == V4L2_PIX_FMT_SBGGR10 || + output_fmt->fourcc == V4L2_PIX_FMT_Y10)) { + ret = 0; + stream->rounding_bit = ROUNDING_2BIT_RV1103B; + } else if (stream->cifdev->chip_id == CHIP_RV1103B_CIF && + (output_fmt->fourcc == V4L2_PIX_FMT_SRGGB8 || + output_fmt->fourcc == V4L2_PIX_FMT_SGRBG8 || + output_fmt->fourcc == V4L2_PIX_FMT_SGBRG8 || + output_fmt->fourcc == V4L2_PIX_FMT_SBGGR8 || + output_fmt->fourcc == V4L2_PIX_FMT_GREY)) { + ret = 0; + stream->rounding_bit = ROUNDING_4BIT_RV1103B; + } break; case MEDIA_BUS_FMT_RGB888_1X24: case MEDIA_BUS_FMT_BGR888_1X24: @@ -1554,6 +1582,20 @@ static enum cif_reg_index get_dvp_reg_index_of_frm1_uv_addr(int channel_id) return index; } +static void rkcif_enable_capture(struct rkcif_stream *stream) +{ + rkcif_write_register_or(stream->cifdev, + get_reg_index_of_id_ctrl0(stream->id), + ENABLE_CAPTURE); +} + +static void rkcif_disable_capture(struct rkcif_stream *stream) +{ + rkcif_write_register_and(stream->cifdev, + get_reg_index_of_id_ctrl0(stream->id), + ~ENABLE_CAPTURE); +} + int rkcif_get_linetime(struct rkcif_stream *stream) { struct rkcif_device *cif_dev = stream->cifdev; @@ -1564,8 +1606,8 @@ int rkcif_get_linetime(struct rkcif_stream *stream) int vblank_def = 0; int vblank_curr = 0; - numerator = sensor->fi.interval.numerator; - denominator = sensor->fi.interval.denominator; + numerator = sensor->src_fi.interval.numerator; + denominator = sensor->src_fi.interval.denominator; if (!numerator || !denominator) { v4l2_err(&cif_dev->v4l2_dev, "get frame interval fail, numerator %d, denominator %d\n", @@ -1589,6 +1631,9 @@ int rkcif_get_linetime(struct rkcif_stream *stream) } line_time = div_u64(1000000000, def_fps); line_time = div_u64(line_time, vblank_def + sensor->raw_rect.height); + v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, + "line_time %d, numerator %d, denominator %d, vblank_def %d\n", + line_time, numerator, denominator, vblank_def); return line_time; } @@ -1745,15 +1790,15 @@ static void rkcif_s_rx_buffer(struct rkcif_stream *stream, struct rkisp_rx_buf * sd = get_rkisp_sd(dev->sditf[0]); if (!sd) return; + rx_buf = to_cif_rx_buf(dbufs); + stream->last_buf_toisp = rx_buf; if ((dev->rdbk_debug && dbufs->sequence < 15) || - rkcif_debug == 3) { - rx_buf = to_cif_rx_buf(dbufs); + rkcif_debug == 3) v4l2_info(&dev->v4l2_dev, "s_buf seq %d type %d, dma addr %x, %lld\n", dbufs->sequence, dbufs->type, (u32)rx_buf->dummy.dma_addr, rkcif_time_get_ns(dev)); - } v4l2_subdev_call(sd, video, s_rx_buffer, dbufs, NULL); } @@ -2066,6 +2111,7 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, } else { if (stream->lack_buf_cnt < 2) stream->lack_buf_cnt++; + stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS; } if (!stream->next_buf_toisp) { @@ -2078,8 +2124,9 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, } else { stream->next_buf_toisp = stream->curr_buf_toisp; } - } else { + } else if (stream->curr_buf_toisp) { stream->next_buf_toisp = stream->curr_buf_toisp; + stream->toisp_buf_state.state = RKCIF_TOISP_BUF_THESAME; if (stream->lack_buf_cnt < 2) stream->lack_buf_cnt++; } @@ -2119,6 +2166,8 @@ void rkcif_dphy_quick_stream(struct rkcif_device *dev, int on) break; } } + v4l2_subdev_call(dev->active_sensor->sd, core, ioctl, + RKMODULE_SET_QUICK_STREAM, &on); } } @@ -2201,11 +2250,19 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, list_del(&buffer->list); stream->curr_buf_toisp = buffer; } - if (priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { + if (priv && (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO || + priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)) { if (!active_buf) goto out_get_buf; - if (stream->frame_idx == 1) + if (stream->is_fb_first_frame) { + stream->sequence = 0; active_buf->dbufs.is_first = true; + stream->is_fb_first_frame = false; + if (stream->frame_idx != 1) + v4l2_info(&dev->v4l2_dev, + "stream[%d],the first frame may be incomplete, fs cnt %d\n", + stream->id, stream->frame_idx); + } active_buf->dbufs.sequence = stream->sequence; active_buf->dbufs.timestamp = stream->readout.fs_timestamp; active_buf->fe_timestamp = rkcif_time_get_ns(dev); @@ -2232,11 +2289,19 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, list_del(&buffer->list); stream->next_buf_toisp = buffer; } - if (priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { + if (priv && (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO || + priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)) { if (!active_buf) goto out_get_buf; - if (stream->frame_idx == 1) + if (stream->is_fb_first_frame) { + stream->sequence = 0; active_buf->dbufs.is_first = true; + stream->is_fb_first_frame = false; + if (stream->frame_idx != 1) + v4l2_info(&dev->v4l2_dev, + "stream[%d],the first frame may be incomplete, fs cnt %d\n", + stream->id, stream->frame_idx); + } active_buf->dbufs.sequence = stream->sequence; active_buf->dbufs.timestamp = stream->readout.fs_timestamp; active_buf->fe_timestamp = rkcif_time_get_ns(dev); @@ -2259,7 +2324,7 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, if (stream->lack_buf_cnt) stream->lack_buf_cnt--; } else { - if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) + if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) goto out_get_buf; if (stream->lack_buf_cnt < 2) stream->lack_buf_cnt++; @@ -2296,8 +2361,15 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, } if (active_buf) { - if (stream->frame_idx == 1) + if (stream->is_fb_first_frame) { + stream->sequence = 0; active_buf->dbufs.is_first = true; + stream->is_fb_first_frame = false; + if (stream->frame_idx != 1) + v4l2_info(&dev->v4l2_dev, + "stream[%d],the first frame may be incomplete, fs cnt %d\n", + stream->id, stream->frame_idx); + } active_buf->dbufs.sequence = stream->sequence; active_buf->dbufs.timestamp = stream->readout.fs_timestamp; active_buf->fe_timestamp = rkcif_time_get_ns(dev); @@ -2371,6 +2443,7 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) int frame_phase = 0; int frame_phase_next = 0; bool is_dual_update = false; + uint32_t cur_dma_addr = 0, next_dma_addr = 0; if (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_ROTATE || (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_THESAME && @@ -2379,15 +2452,28 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) stream->toisp_buf_state.check_cnt >= 2)) { if ((dev->rdbk_debug > 2 && stream->frame_idx < 15) || - rkcif_debug == 3) + rkcif_debug == 3) { + if (stream->curr_buf_toisp) + cur_dma_addr = stream->curr_buf_toisp->dummy.dma_addr; + if (stream->next_buf_toisp) + next_dma_addr = stream->next_buf_toisp->dummy.dma_addr; v4l2_info(&dev->v4l2_dev, - "stream[%d] addr check not equal 0x%x 0x%x\n", + "stream[%d] addr check not equal 0x%x 0x%x state %d chech_cnt %d\n", stream->id, - (u32)stream->curr_buf_toisp->dummy.dma_addr, - (u32)stream->next_buf_toisp->dummy.dma_addr); + cur_dma_addr, + next_dma_addr, stream->toisp_buf_state.state, stream->toisp_buf_state.check_cnt); + } return; } + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, + "stream[%d] addr check 0x%x 0x%x state %d chech_cnt %d\n", + stream->id, + cur_dma_addr, + next_dma_addr, stream->toisp_buf_state.state, stream->toisp_buf_state.check_cnt); + if (stream->frame_phase == 0) + stream->frame_phase = CIF_CSI_FRAME0_READY; frame_phase = stream->frame_phase; + if (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_LOSS && stream->toisp_buf_state.check_cnt == 0) is_dual_update = true; @@ -2608,6 +2694,8 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream, __func__, __LINE__, stream->id, stream->next_buf->vb.vb2_buf.index); list_del(&stream->next_buf->queue); atomic_inc(&buf_stream->sub_stream_buf_cnt); + } else if (stream->curr_buf) { + stream->next_buf = stream->curr_buf; } } @@ -3118,10 +3206,13 @@ static int rkcif_get_new_buffer_wake_up_mode_rdbk(struct rkcif_stream *stream) stream->lack_buf_cnt++; if (stream->curr_buf_toisp && stream->next_buf_toisp && stream->curr_buf_toisp != stream->next_buf_toisp) { - if (stream->line_int_cnt % 2) + if (stream->line_int_cnt % 2) { stream->curr_buf_toisp = stream->next_buf_toisp; - else + frame_phase = CIF_CSI_FRAME0_READY; + } else { stream->next_buf_toisp = stream->curr_buf_toisp; + frame_phase = CIF_CSI_FRAME1_READY; + } buffer = stream->curr_buf_toisp; ret = 0; if (stream->cifdev->rdbk_debug) @@ -3479,6 +3570,172 @@ static int rkcif_assign_new_buffer_pingpong_rockit(struct rkcif_stream *stream, return ret; } +void rkcif_check_buffer_update_pingpong_rockit(struct rkcif_stream *stream, + int channel_id) +{ + struct rkcif_device *dev = stream->cifdev; + struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; + struct rkcif_buffer *buffer = NULL; + 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; + u32 buff_addr_y = 0, buff_addr_cbcr = 0; + unsigned long flags; + int frame_phase = 0; + bool is_dual_update_buf = false; + int on = 1; + + 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->curr_buf_rockit == stream->next_buf_rockit || + stream->curr_buf_rockit == NULL || + stream->next_buf_rockit == NULL) { + frame_phase = stream->frame_phase_cache; + if (!stream->is_line_wake_up || + (stream->is_line_wake_up && stream->frame_idx < 2)) { + if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || + mbus_cfg->type == V4L2_MBUS_CSI2_CPHY || + mbus_cfg->type == V4L2_MBUS_CCP2) { + frm0_addr_y = get_reg_index_of_frm0_y_addr(channel_id); + frm1_addr_y = get_reg_index_of_frm1_y_addr(channel_id); + frm0_addr_uv = get_reg_index_of_frm0_uv_addr(channel_id); + frm1_addr_uv = get_reg_index_of_frm1_uv_addr(channel_id); + } else { + frm0_addr_y = get_dvp_reg_index_of_frm0_y_addr(channel_id); + frm1_addr_y = get_dvp_reg_index_of_frm1_y_addr(channel_id); + frm0_addr_uv = get_dvp_reg_index_of_frm0_uv_addr(channel_id); + frm1_addr_uv = get_dvp_reg_index_of_frm1_uv_addr(channel_id); + } + if (frame_phase & CIF_CSI_FRAME0_READY) { + frm_addr_y = frm0_addr_y; + frm_addr_uv = frm0_addr_uv; + } else { + frm_addr_y = frm1_addr_y; + frm_addr_uv = frm1_addr_uv; + } + if (!stream->dma_en && stream->curr_buf_rockit == NULL && stream->next_buf_rockit == NULL) + is_dual_update_buf = true; + if (!list_empty(&stream->rockit_buf_head)) { + if (frame_phase == CIF_CSI_FRAME0_READY) { + stream->curr_buf_rockit = list_first_entry(&stream->rockit_buf_head, + struct rkcif_buffer, queue); + if (stream->curr_buf_rockit) { + list_del(&stream->curr_buf_rockit->queue); + buffer = stream->curr_buf_rockit; + } + if (buffer && is_dual_update_buf) + stream->next_buf_rockit = buffer; + } else if (frame_phase == CIF_CSI_FRAME1_READY) { + stream->next_buf_rockit = list_first_entry(&stream->rockit_buf_head, + struct rkcif_buffer, queue); + if (stream->next_buf_rockit) { + list_del(&stream->next_buf_rockit->queue); + buffer = stream->next_buf_rockit; + } + if (buffer && is_dual_update_buf) + stream->curr_buf_rockit = buffer; + } + } else { + v4l2_info(&dev->v4l2_dev, "%s %d\n", __func__, __LINE__); + } + if (buffer) { + if (is_dual_update_buf) { + buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y]; + buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR]; + + rkcif_write_register(dev, frm0_addr_y, buff_addr_y); + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) + rkcif_write_register(dev, + frm0_addr_uv, + buff_addr_cbcr); + rkcif_write_register(dev, frm1_addr_y, buff_addr_y); + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) + rkcif_write_register(dev, + frm1_addr_uv, + buff_addr_cbcr); + } else { + + buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y]; + buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR]; + + rkcif_write_register(dev, frm_addr_y, buff_addr_y); + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) + rkcif_write_register(dev, + frm_addr_uv, + buff_addr_cbcr); + } + } + } else { + v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev, + "%s %d, is_wake_up %d, frame_idx %d\n", + __func__, __LINE__, stream->is_line_wake_up, stream->frame_idx); + if (stream->curr_buf_rockit == stream->next_buf_rockit) { + if (stream->frame_phase_cache == CIF_CSI_FRAME0_READY) { + stream->curr_buf_rockit = list_first_entry(&stream->rockit_buf_head, + struct rkcif_buffer, queue); + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, + "%s %d, stream[%d] buf idx %d\n", + __func__, __LINE__, stream->id, stream->curr_buf_rockit->vb.vb2_buf.index); + if (stream->curr_buf_rockit) + list_del(&stream->curr_buf_rockit->queue); + } else if (stream->frame_phase_cache == CIF_CSI_FRAME1_READY) { + stream->next_buf_rockit = list_first_entry(&stream->rockit_buf_head, + struct rkcif_buffer, queue); + v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, + "%s %d, stream[%d] buf idx %d\n", + __func__, __LINE__, stream->id, stream->next_buf_rockit->vb.vb2_buf.index); + if (stream->next_buf_rockit) + list_del(&stream->next_buf_rockit->queue); + } + stream->is_buf_active = true; + } + } + v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev, + "%s, stream[%d] update buffer, frame_phase %d, is_stop %s, lack_buf_cnt %d\n", + __func__, stream->id, frame_phase, + (stream->dma_en ? "false" : "true"), + stream->lack_buf_cnt); + if (!stream->dma_en) { + if (stream->to_stop_dma) { + stream->to_stop_dma = 0; + wake_up(&stream->wq_stopped); + } else { + if (stream->cifdev->resume_mode != RKISP_RTT_MODE_ONE_FRAME) + stream->to_en_dma = RKCIF_DMAEN_BY_ROCKIT; + v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev, + "%s stream[%d] start dma capture, frame cnt %d\n", + __func__, stream->id, stream->frame_idx); + } + } else { + v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev, + "%s %d, dma_en 0x%x, frame cnt %d\n", + __func__, __LINE__, stream->dma_en, stream->frame_idx); + } + if (stream->lack_buf_cnt) + stream->lack_buf_cnt--; + + } else { + v4l2_info(&dev->v4l2_dev, "%s %d, state %d, curr_buf_rockit %p, next_buf_rockit %p\n", + __func__, __LINE__, stream->state, stream->curr_buf_rockit, stream->next_buf_rockit); + } + spin_unlock_irqrestore(&stream->vbq_lock, flags); + if (stream->to_en_dma) { + rkcif_enable_dma_capture(stream, true); + mutex_lock(&dev->stream_lock); + if (atomic_read(&dev->sensor_off)) { + atomic_set(&dev->sensor_off, 0); + rkcif_dphy_quick_stream(dev, on); + v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, + RKMODULE_SET_QUICK_STREAM, &on); + } + mutex_unlock(&dev->stream_lock); + } +} + static void rkcif_csi_set_lvds_sav_eav(struct rkcif_stream *stream, struct csi_channel_info *channel) { @@ -3601,6 +3858,8 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, channel->width = stream->crop[CROP_SRC_ACT].width; channel->height = stream->crop[CROP_SRC_ACT].height; } else { + channel->crop_st_x = 0; + channel->crop_st_y = 0; channel->width = stream->pixm.width; channel->height = stream->pixm.height; channel->crop_en = 0; @@ -3618,6 +3877,17 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) channel->width /= channel->capture_info.multi_dev.dev_num; + + if (dev->sditf[0] && dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE && + (dev->hdr.hdr_mode == NO_HDR || + dev->hdr.hdr_mode == HDR_COMPR || + (dev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || + (dev->hdr.hdr_mode == HDR_X3 && stream->id == 2))) { + channel->crop_st_x += channel->width / 2; + channel->crop_st_x -= RKMOUDLE_UNITE_EXTEND_PIXEL; + channel->width /= 2; + channel->width += RKMOUDLE_UNITE_EXTEND_PIXEL; + } /* * for mipi or lvds, when enable compact, the virtual width of raw10/raw12 * needs aligned with :ALIGN(bits_per_pixel * width / 8, 8), if enable 16bit mode @@ -3843,9 +4113,8 @@ static int rkcif_csi_channel_set(struct rkcif_stream *stream, rkcif_write_register(dev, get_reg_index_of_frm1_uv_vlw(channel->id), channel->virtual_width); - if (channel->crop_en) - rkcif_write_register(dev, get_reg_index_of_id_crop_start(channel->id), - channel->crop_st_y << 16 | channel->crop_st_x); + rkcif_write_register(dev, get_reg_index_of_id_crop_start(channel->id), + channel->crop_st_y << 16 | channel->crop_st_x); /* Set up an buffer for the next frame */ if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) @@ -4229,6 +4498,15 @@ static u32 rkcif_get_split_dphy_mask_rk3576(struct rkcif_device *dev) return val; } +static u32 rkcif_get_split_dphy_mask_rv1103b(struct rkcif_device *dev) +{ + u32 val = 0; + + if (dev->hw_dev->dev_num == 2) + val = SW_DPHY_SPLIT_EN_RV1103B; + return val; +} + /*config reg for rk3588*/ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, struct csi_channel_info *channel, @@ -4237,6 +4515,7 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, { unsigned int val = 0x0; struct rkcif_device *dev = stream->cifdev; + struct rkcif_stream *detect_stream = &dev->stream[0]; struct sditf_priv *priv = dev->sditf[0]; struct rkmodule_capture_info *capture_info = &channel->capture_info; unsigned int wait_line = 0x3fff; @@ -4273,6 +4552,8 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, } else if (dev->chip_id == CHIP_RK3576_CIF) { val = GLB_RESET_IDI_EN_RK3576; val |= rkcif_get_split_dphy_mask_rk3576(dev); + } else if (dev->chip_id == CHIP_RV1103B_CIF) { + val = rkcif_get_split_dphy_mask_rv1103b(dev); } rkcif_write_register_or(dev, CIF_REG_GLB_CTRL, val); @@ -4295,7 +4576,7 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, CSI_START_INTEN(channel->id) : CSI_START_INTEN_RK3576(channel->id)); - if (stream->is_line_wake_up) { + if (priv && priv->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ && detect_stream->is_line_wake_up) { rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, CSI_LINE_INTEN_RK3588(channel->id)); wait_line = dev->wait_line; @@ -4359,9 +4640,8 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, rv1106_sdmmc_put_lock(); #endif - if (channel->crop_en) - rkcif_write_register(dev, get_reg_index_of_id_crop_start(channel->id), - channel->crop_st_y << 16 | channel->crop_st_x); + 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) { if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) @@ -4388,8 +4668,11 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, channel->crop_st_y << 16 | (channel->crop_st_x + capture_info->multi_dev.pixel_offset)); - rkcif_write_register(dev, get_reg_index_of_frm0_y_vlw(channel->id), - channel->virtual_width); + val = channel->virtual_width; + if (dev->chip_id >= CHIP_RV1103B_CIF && dev->sditf[0] && + dev->sditf[0]->hdr_wrap_line) + val |= dev->sditf[0]->hdr_wrap_line << 20; + rkcif_write_register(dev, get_reg_index_of_frm0_y_vlw(channel->id), val); if (stream->lack_buf_cnt == 2) stream->dma_en = 0; @@ -4404,6 +4687,11 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, } else { dma_en = LVDS_DMAEN_RV1106; } + } else { + rkcif_write_register_and(dev, CIF_REG_MIPI_LVDS_INTEN, + dev->chip_id < CHIP_RK3576_CIF ? + ~(CSI_START_INTEN(channel->id)) : + ~(CSI_START_INTEN_RK3576(channel->id))); } if (mbus_type == V4L2_MBUS_CSI2_DPHY || mbus_type == V4L2_MBUS_CSI2_CPHY) { @@ -4425,6 +4713,13 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, if (stream->id == 0 && (stream->cif_fmt_out->fourcc == V4L2_PIX_FMT_NV12 || stream->cif_fmt_out->fourcc == V4L2_PIX_FMT_NV21)) val |= CSI_UVDS_EN; + + if (dev->chip_id >= CHIP_RV1103B_CIF && dev->sditf[0] && + dev->sditf[0]->hdr_wrap_line) + val |= (0x2 << 20); + if (dev->chip_id >= CHIP_RV1103B_CIF && stream->rounding_bit) + val |= stream->rounding_bit; + rkcif_write_register(dev, get_reg_index_of_id_ctrl0(channel->id), val); val = channel->vc | channel->data_type << 2; @@ -4525,6 +4820,37 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, return 0; } +void rkcif_reinit_right_half_config(struct rkcif_stream *stream) +{ + struct rkcif_device *cif_dev = stream->cifdev; + struct csi_channel_info *channel = &cif_dev->channels[0]; + const struct cif_output_fmt *fmt; + + fmt = rkcif_find_output_fmt(&cif_dev->stream[0], cif_dev->stream[0].pixm.pixelformat); + if (!fmt) { + v4l2_err(&cif_dev->v4l2_dev, "can not find output format: 0x%x", + cif_dev->stream[0].pixm.pixelformat); + return; + } + channel->crop_st_x += channel->width / 2; + channel->crop_st_x -= RKMOUDLE_UNITE_EXTEND_PIXEL; + channel->width /= 2; + channel->width += RKMOUDLE_UNITE_EXTEND_PIXEL; + channel->virtual_width = ALIGN(channel->width * fmt->raw_bpp / 8, 256); + if (cif_dev->chip_id < CHIP_RK3576_CIF) + rkcif_write_register(cif_dev, get_reg_index_of_id_ctrl1(channel->id), + channel->width | (channel->height << 16)); + else + rkcif_write_register(cif_dev, CIF_REG_MIPI_SET_SIZE_ID0 + channel->id, + channel->width | (channel->height << 16)); + rkcif_write_register(cif_dev, get_reg_index_of_id_crop_start(channel->id), + channel->crop_st_y << 16 | channel->crop_st_x); + rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_INTEN, + ~(CSI_DMA_END_INTEN(stream->id))); + stream->to_en_dma = RKCIF_DMAEN_BY_ISP; + rkcif_enable_dma_capture(stream, false); +} + static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode) { struct rkcif_device *dev = stream->cifdev; @@ -4537,16 +4863,20 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode int i; if (stream->state < RKCIF_STATE_STREAMING) { - stream->frame_idx = 0; + if (!dev->is_thunderboot) + stream->frame_idx = 0; stream->buf_wake_up_cnt = 0; stream->frame_phase = 0; stream->lack_buf_cnt = 0; stream->is_in_vblank = false; stream->is_change_toisp = false; + stream->is_finish_single_cap = true; + stream->is_wait_single_cap = false; } stream->interlaced_bad_frame = false; stream->last_fs_interlaced_phase = 0; stream->last_fe_interlaced_phase = 0; + stream->to_stop_dma = 0; channel = &dev->channels[stream->id]; channel->id = stream->id; @@ -4579,6 +4909,8 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode stream->dma_en |= RKCIF_DMAEN_BY_ISP; else if (dev->hdr.hdr_mode == HDR_X3 && (stream->id == 0 || stream->id == 1)) stream->dma_en |= RKCIF_DMAEN_BY_ISP; + else if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) + stream->dma_en |= RKCIF_DMAEN_BY_ISP; } else if (mode == RKCIF_STREAM_MODE_ROCKIT) { stream->dma_en |= RKCIF_DMAEN_BY_ROCKIT; } @@ -4982,18 +5314,17 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream, __func__, __LINE__, stream->state, stream->curr_buf, stream->next_buf); } spin_unlock_irqrestore(&stream->vbq_lock, flags); + if (stream->to_en_dma) { rkcif_enable_dma_capture(stream, true); - spin_lock_irqsave(&dev->hdr_lock, flags); - if (dev->is_sensor_off) { - dev->is_sensor_off = false; - spin_unlock_irqrestore(&dev->hdr_lock, flags); + mutex_lock(&dev->stream_lock); + if (atomic_read(&dev->sensor_off)) { + atomic_set(&dev->sensor_off, 0); rkcif_dphy_quick_stream(dev, on); v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, RKMODULE_SET_QUICK_STREAM, &on); - } else { - spin_unlock_irqrestore(&dev->hdr_lock, flags); } + mutex_unlock(&dev->stream_lock); } } @@ -5308,19 +5639,25 @@ void rkcif_buf_queue(struct vb2_buffer *vb) if (stream->dma_en & RKCIF_DMAEN_BY_ISP && (!cifbuf->dbuf)) { struct rkisp_rx_buf *dbufs = NULL; - dbufs = kzalloc(sizeof(struct rkisp_rx_buf), GFP_KERNEL); + dbufs = kzalloc(sizeof(struct rkisp_rx_buf), GFP_ATOMIC); - memset(dbufs, 0, sizeof(struct rkisp_rx_buf)); - if (stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 0) - dbufs->type = BUF_MIDDLE; - else if (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 0) - dbufs->type = BUF_LONG; - else if (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 1) - dbufs->type = BUF_MIDDLE; - cifbuf->dbuf = hw_dev->mem_ops->get_dmabuf(vb, vb->planes[0].mem_priv, O_RDWR); - if (cifbuf->dbuf) - dbufs->dbuf = cifbuf->dbuf; - list_add_tail(&dbufs->list, &stream->rx_buf_head_vicap); + if (dbufs) { + memset(dbufs, 0, sizeof(struct rkisp_rx_buf)); + if (stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 0) + dbufs->type = BUF_MIDDLE; + else if (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 0) + dbufs->type = BUF_LONG; + else if (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 1) + dbufs->type = BUF_MIDDLE; + cifbuf->dbuf = hw_dev->mem_ops->get_dmabuf(vb, vb->planes[0].mem_priv, O_RDWR); + if (cifbuf->dbuf) + dbufs->dbuf = cifbuf->dbuf; + list_add_tail(&dbufs->list, &stream->rx_buf_head_vicap); + } else { + v4l2_err(&stream->cifdev->v4l2_dev, + "stream[%d] buf queue, index: %d, dma_addr 0x%x, malloc dbufs fail\n", + stream->id, vb->index, cifbuf->buff_addr[0]); + } } if (stream->cifdev->workmode == RKCIF_WORKMODE_PINGPONG && stream->lack_buf_cnt && @@ -5328,8 +5665,23 @@ void rkcif_buf_queue(struct vb2_buffer *vb) stream->cifdev->channels[0].capture_info.mode != RKMODULE_ONE_CH_TO_MULTI_ISP) rkcif_check_buffer_update_pingpong(stream, stream->id); atomic_inc(&stream->buf_cnt); + if (stream->low_latency) rkcif_qbuf_alloc_fence(stream); + + spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags); + stream->is_finish_single_cap = true; + if (stream->is_wait_single_cap && + (stream->cifdev->hdr.hdr_mode == NO_HDR || + (stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || + (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 2))) { + stream->is_wait_single_cap = false; + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); + rkcif_quick_stream_on(stream->cifdev, false); + complete(&stream->start_complete); + } else { + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); + } v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev, "stream[%d] buf queue, index: %d, dma_addr 0x%x, dbuf %p, mem_priv %p\n", stream->id, vb->index, cifbuf->buff_addr[0], cifbuf->vb.vb2_buf.planes[0].dbuf, @@ -5408,12 +5760,17 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num) INIT_LIST_HEAD(&stream->rx_buf_head); spin_unlock_irqrestore(&stream->vbq_lock, flags); - if (dev->is_thunderboot) - spin_lock_irqsave(&dev->buffree_lock, flags); + spin_lock_irqsave(&dev->buffree_lock, flags); for (i = 0; i < buf_num; i++) { buf = &stream->rx_buf[i]; if (buf->dummy.is_free) continue; + if (stream->is_m_online_fb_res && buf == stream->last_buf_toisp) { + /* todo, release left buf*/ + stream->is_m_online_fb_res = false; + list_add_tail(&buf->list, &stream->rx_buf_head); + continue; + } if (buf->dbufs.is_init) v4l2_subdev_call(sd, core, ioctl, RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs); @@ -5426,15 +5783,40 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num) } stream->rx_buf_num = 0; - if (dev->is_thunderboot) { - spin_unlock_irqrestore(&dev->buffree_lock, flags); + spin_unlock_irqrestore(&dev->buffree_lock, flags); + + if (buf_num) schedule_work(&priv->buffree_work.work); - } + stream->dma_en &= ~RKCIF_DMAEN_BY_ISP; v4l2_dbg(1, rkcif_debug, &stream->cifdev->v4l2_dev, "free rx_buf, buf_num %d\n", buf_num); } +static void rkcif_sync_crop_info(struct rkcif_stream *stream); +static u32 rkcif_get_right_half_buf_size(struct rkcif_stream *stream) +{ + u32 width, height, virtual_width; + + rkcif_sync_crop_info(stream); + if (stream->crop_enable) { + width = stream->crop[CROP_SRC_ACT].width; + height = stream->crop[CROP_SRC_ACT].height; + } else { + width = stream->pixm.width; + height = stream->pixm.height; + } + width /= 2; + width += RKMOUDLE_UNITE_EXTEND_PIXEL; + if (stream->is_compact) + virtual_width = ALIGN(width * stream->cif_fmt_out->raw_bpp / 8, 256); + else + virtual_width = ALIGN(width * stream->cif_fmt_out->bpp[0] / 8, 8); + if (stream->cifdev->chip_id > CHIP_RK3562_CIF && stream->sw_dbg_en) + virtual_width = (virtual_width + 23) / 24 * 24; + return virtual_width * height; +} + static void rkcif_get_resmem_head(struct rkcif_device *cif_dev); int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) { @@ -5445,7 +5827,9 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) struct sditf_priv *priv = dev->sditf[0]; int frm_type = 0; int i = 0; + int j = 0; int ret = 0; + bool is_match_pre = false; if (!priv) return -EINVAL; @@ -5479,7 +5863,15 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) buf = &stream->rx_buf[i]; memset(buf, 0, sizeof(*buf)); dummy = &buf->dummy; - dummy->size = pixm->plane_fmt[0].sizeimage; + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE && + (priv->hdr_cfg.hdr_mode == NO_HDR || priv->hdr_cfg.hdr_mode == HDR_COMPR || + (priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 1) || + (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id == 2))) + dummy->size = rkcif_get_right_half_buf_size(stream); + else if (dev->chip_id >= CHIP_RV1103B_CIF && priv->hdr_wrap_line) + dummy->size = pixm->plane_fmt[0].bytesperline * priv->hdr_wrap_line; + else + dummy->size = pixm->plane_fmt[0].sizeimage; dummy->is_need_vaddr = true; dummy->is_need_dbuf = true; if (dev->is_thunderboot || dev->is_rtt_suspend || dev->is_aov_reserved) { @@ -5511,17 +5903,37 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) } buf->dbufs.is_init = false; buf->dbufs.type = frm_type; - list_add_tail(&buf->list, &stream->rx_buf_head); + is_match_pre = false; + if (dev->pre_buf_num) { + for (j = 0; j < dev->pre_buf_num; j++) { + if (dev->pre_buf_addr[i] == buf->dbufs.dma) { + if (i == 0) + buf->dbufs.is_first = true; + stream->is_fb_first_frame = false; + buf->dbufs.sequence = stream->frame_idx; + buf->dbufs.timestamp = dev->pre_buf_timestamp[i]; + rkcif_s_rx_buffer(stream, &buf->dbufs); + stream->frame_idx++; + is_match_pre = true; + break; + } + } + } + if (!is_match_pre) + list_add_tail(&buf->list, &stream->rx_buf_head); dummy->is_free = false; if (stream->is_compact) buf->dbufs.is_uncompact = false; else buf->dbufs.is_uncompact = true; - if (priv && i == 0) { + if (priv && i == 0 && dev->pre_buf_num == 0) { buf->dbufs.is_first = true; - if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) + if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) rkcif_s_rx_buffer(stream, &buf->dbufs); } + v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, + "init rx_buf,dma_addr 0x%llx size: 0x%x\n", + (u64)dummy->dma_addr, dummy->size); i++; if (!dev->is_thunderboot && i >= buf_num) { stream->rx_buf_num = buf_num; @@ -5532,9 +5944,6 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) "reserved mem alloc buf num %d\n", i); break; } - v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, - "init rx_buf,dma_addr 0x%llx size: 0x%x\n", - (u64)dummy->dma_addr, pixm->plane_fmt[0].sizeimage); } if (stream->rx_buf_num) { stream->total_buf_num = stream->rx_buf_num; @@ -5643,18 +6052,19 @@ static void rkcif_do_cru_reset(struct rkcif_device *dev) if (dev->luma_vdev.enable) rkcif_stop_luma(&dev->luma_vdev); - if (dev->hdr.hdr_mode != NO_HDR) { - if (dev->chip_id == CHIP_RK1808_CIF) { - val = rkcif_read_register(dev, CIF_REG_MIPI_WATER_LINE); - val |= CIF_MIPI_LVDS_SW_DMA_IDLE_RK1808; - rkcif_write_register(dev, CIF_REG_MIPI_WATER_LINE, val); - } else { - val = rkcif_read_register(dev, CIF_REG_MIPI_LVDS_CTRL); - val |= CIF_MIPI_LVDS_SW_DMA_IDLE; - rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val); - } - udelay(5); + if (dev->chip_id == CHIP_RK1808_CIF) { + val = rkcif_read_register(dev, CIF_REG_MIPI_WATER_LINE); + val |= CIF_MIPI_LVDS_SW_DMA_IDLE_RK1808; + rkcif_write_register(dev, CIF_REG_MIPI_WATER_LINE, val); + } else { + val = rkcif_read_register(dev, CIF_REG_MIPI_LVDS_CTRL); + val |= CIF_MIPI_LVDS_SW_DMA_IDLE; + rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val); + val = rkcif_read_register(dev, CIF_REG_DVP_CTRL); + val |= DVP_SW_DMA_IDLE; + rkcif_write_register(dev, CIF_REG_DVP_CTRL, val); } + udelay(5); for (i = 0; i < ARRAY_SIZE(cif_hw->cif_rst); i++) if (cif_hw->cif_rst[i]) @@ -5687,12 +6097,23 @@ void rkcif_do_soft_reset(struct rkcif_device *dev) dev->csi_host_idx = channel->capture_info.multi_dev.dev_idx[i]; rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); } + if (dev->chip_id >= CHIP_RV1103B_CIF) { + for (i = 0; i < channel->capture_info.multi_dev.dev_num; i++) { + dev->csi_host_idx = channel->capture_info.multi_dev.dev_idx[i]; + rkcif_write_register_and(dev, CIF_REG_MIPI_LVDS_CTRL, ~0x000f0000); + } + } dev->csi_host_idx = tmp_csi_host_idx; } else { rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); + if (dev->chip_id >= CHIP_RV1103B_CIF) + rkcif_write_register_and(dev, CIF_REG_MIPI_LVDS_CTRL, ~0x000f0000); } } else { rkcif_write_register_or(dev, CIF_REG_DVP_CTRL, 0x000A0000); + if (dev->chip_id >= CHIP_RV1103B_CIF) + rkcif_write_register_and(dev, CIF_REG_DVP_CTRL, ~0x000f0000); + } usleep_range(10, 20); v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, @@ -5905,9 +6326,12 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, stream->stopping = true; } if (stream->stopping == true) { - ret = wait_event_timeout(stream->wq_stopped, - stream->state != RKCIF_STATE_STREAMING, - msecs_to_jiffies(500)); + if (mode == RKCIF_STREAM_MODE_TOISP && dev->sditf[0]->is_toisp_off) + ret = 0; + else + ret = wait_event_timeout(stream->wq_stopped, + stream->state != RKCIF_STATE_STREAMING, + msecs_to_jiffies(500)); if (!ret) { rkcif_stream_stop(stream); stream->stopping = false; @@ -6044,11 +6468,17 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, dev->reset_work_cancel = true; dev->early_line = 0; dev->sensor_linetime = 0; + dev->wait_line = 0; + stream->is_line_wake_up = false; + dev->is_in_flip = false; + dev->pre_buf_num = 0; + dev->hw_dev->is_in_reset = false; } if (atomic_read(&dev->pipe.stream_cnt) == 0) atomic_set(&stream->sub_stream_buf_cnt, 0); if (can_reset && hw_dev->dummy_buf.vaddr) rkcif_destroy_dummy_buf(stream); + stream->rounding_bit = 0; } if (mode == RKCIF_STREAM_MODE_CAPTURE) { tasklet_disable(&stream->vb_done_tasklet); @@ -6477,6 +6907,9 @@ static int rkcif_sanity_check_fmt(struct rkcif_stream *stream, return -EINVAL; } } + if (atomic_read(&dev->pipe.stream_cnt) == 0) + v4l2_subdev_call(dev->terminal_sensor.sd, video, + g_frame_interval, &dev->terminal_sensor.src_fi); return 0; } @@ -7236,6 +7669,12 @@ static void rkcif_attach_sync_mode(struct rkcif_device *cifdev) sync_config->slave.count++; sync_config->dev_cnt++; sync_config->sync_mask |= BIT(dev->csi_host_idx); + } else if (sync_cfg.type == SOFT_SYNC_MODE) { + count = sync_config->soft_sync.count; + sync_config->soft_sync.cif_dev[count] = dev; + sync_config->soft_sync.count++; + sync_config->dev_cnt++; + sync_config->sync_mask |= BIT(dev->csi_host_idx); } dev->sync_cfg = sync_cfg; } else { @@ -7263,6 +7702,10 @@ static void rkcif_attach_sync_mode(struct rkcif_device *cifdev) sync_config->int_master.count, sync_config->ext_master.count, sync_config->slave.count); + } else if (sync_config->soft_sync.count > 1) { + sync_config->mode = RKCIF_SOFT_SYNC; + sync_config->is_attach = true; + dev_info(hw->dev, "group used soft sync mode\n"); } mutex_unlock(&hw->dev_lock); } @@ -7372,6 +7815,7 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, enum rkcif_stream_mode mo dev->csi_host_idx = dev->csi_host_idx_def; csi_info.csi_idx[0] = dev->csi_host_idx; } + dev->csi_info = csi_info; ret = v4l2_subdev_call(dev->active_sensor->sd, core, ioctl, RKCIF_CMD_SET_CSI_IDX, @@ -7625,6 +8069,16 @@ int rkcif_set_fmt(struct rkcif_stream *stream, dev->hdr.hdr_mode = NO_HDR; dev->terminal_sensor.raw_rect = input_rect; + if (atomic_read(&dev->pipe.stream_cnt) == 0) { + ret = v4l2_subdev_call(dev->terminal_sensor.sd, video, + g_frame_interval, &dev->terminal_sensor.src_fi); + if (ret) { + v4l2_err(&stream->cifdev->v4l2_dev, + "%s: get terminal %s g_frame_interval failed!\n", + __func__, dev->terminal_sensor.sd->name); + return ret; + } + } } /* CIF has not scale function, @@ -7832,6 +8286,7 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id) atomic_set(&stream->buf_cnt, 0); stream->rx_buf_num = 0; init_completion(&stream->stop_complete); + init_completion(&stream->start_complete); stream->is_wait_stop_complete = false; stream->thunderboot_skip_interval = get_rk_cam_skip_frame_interval(); atomic_set(&stream->sub_stream_buf_cnt, 0); @@ -7841,6 +8296,10 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id) INIT_LIST_HEAD(&stream->done_fence_list_head); stream->low_latency = false; stream->rkcif_fence = NULL; + stream->rounding_bit = 0; + stream->is_m_online_fb_res = false; + stream->is_fb_first_frame = true; + stream->frame_idx = 0; } static int rkcif_sensor_set_power(struct rkcif_stream *stream, int on) @@ -7881,6 +8340,16 @@ static int rkcif_fh_open(struct file *filp) if (ret) return ret; + if (cifdev->is_thunderboot) { + ret = rkisp_cond_poll_timeout(cifdev->is_thunderboot_start, + 2000, 5000 * USEC_PER_MSEC); + if (ret) { + mutex_lock(&cifdev->stream_lock); + cifdev->is_thunderboot = false; + mutex_unlock(&cifdev->stream_lock); + return -EINVAL; + } + } /* Make sure active sensor is valid before .set_fmt() */ ret = rkcif_update_sensor_info(stream); if (ret < 0) { @@ -8361,8 +8830,13 @@ void rkcif_set_fps(struct rkcif_stream *stream, struct rkcif_fps *fps) } if (!stream->cifdev->terminal_sensor.sd) return; - numerator = sensor->fi.interval.numerator; - denominator = sensor->fi.interval.denominator; + if (atomic_read(&cif_dev->pipe.stream_cnt) == 0) { + numerator = sensor->fi.interval.numerator; + denominator = sensor->fi.interval.denominator; + } else { + numerator = sensor->src_fi.interval.numerator; + denominator = sensor->src_fi.interval.denominator; + } def_fps = denominator / numerator; vblank_def = rkcif_get_sensor_vblank_def(cif_dev); @@ -8438,15 +8912,6 @@ void rkcif_set_fps(struct rkcif_stream *stream, struct rkcif_fps *fps) skip_n); } -static bool rkcif_check_can_be_online(struct rkcif_device *cif_dev) -{ - if (cif_dev->sditf[0] == NULL || cif_dev->sditf[0]->mode.name == NULL || - (cif_dev->chip_id == CHIP_RV1106_CIF && - strstr(cif_dev->sditf[0]->mode.name, "unite"))) - return false; - return true; -} - static void rkcif_alloc_buf_by_user_require(struct rkcif_device *dev, struct rkcif_buffer_info *buf_info) { @@ -8518,13 +8983,149 @@ void rkcif_free_buf_by_user_require(struct rkcif_device *dev) dev->is_alloc_buf_user = false; } +int rkcif_quick_stream_on(struct rkcif_device *dev, bool is_intr) +{ + struct v4l2_subdev *sd; + struct rkcif_stream *stream = NULL; + int i = 0; + int stream_num = 0; + int ret = 0; + int on = 1; + + if (dev->hdr.hdr_mode == HDR_X2) + stream_num = 2; + else if (dev->hdr.hdr_mode == HDR_X3) + stream_num = 3; + else + stream_num = 1; + + for (i = 0; i < stream_num; i++) + dev->stream[i].cur_skip_frame = dev->stream[i].skip_frame; + dev->sditf[0]->mode.rdbk_mode = dev->sditf[0]->mode_src.rdbk_mode; + if (dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { + for (i = 0; i < stream_num; i++) { + stream = &dev->stream[i]; + if (stream->cifdev->hdr.hdr_mode == NO_HDR || + (stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || + (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 2)) { + rkcif_enable_capture(stream); + } else { + dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP; + rkcif_enable_dma_capture(&dev->stream[i], true); + } + } + if (dev->chip_id == CHIP_RV1106_CIF) { + sditf_change_to_online(dev->sditf[0]); + sd = get_rkisp_sd(dev->sditf[0]); + if (sd) + ret = v4l2_subdev_call(sd, core, ioctl, + RKISP_VICAP_CMD_MODE, &dev->sditf[0]->mode); + if (ret) { + v4l2_err(&dev->v4l2_dev, "set isp work mode online fail\n"); + return -EINVAL; + } + } + } else { + if (dev->chip_id == CHIP_RV1106_CIF) { + sditf_disable_immediately(dev->sditf[0]); + sd = get_rkisp_sd(dev->sditf[0]); + if (sd) + ret = v4l2_subdev_call(sd, core, ioctl, + RKISP_VICAP_CMD_MODE, &dev->sditf[0]->mode); + } + for (i = 0; i < stream_num; i++) { + if (dev->sditf[0]->mode.rdbk_mode != RKISP_VICAP_RDBK_AIQ) + dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP; + else + dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_VICAP; + rkcif_enable_dma_capture(&dev->stream[i], true); + } + } + if (is_intr) { + if (atomic_read(&dev->sensor_off)) { + atomic_set(&dev->sensor_off, 0); + rkcif_dphy_quick_stream(dev, on); + dev->sensor_work.on = 1; + schedule_work(&dev->sensor_work.work); + } + + } else { + mutex_lock(&dev->stream_lock); + rkcif_dphy_quick_stream(dev, on); + if (atomic_read(&dev->sensor_off)) { + v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, + RKMODULE_SET_QUICK_STREAM, &on); + atomic_set(&dev->sensor_off, 0); + } + mutex_unlock(&dev->stream_lock); + } + dev->resume_mode = RKISP_RTT_MODE_MULTI_FRAME; + return ret; +} + +void rkcif_flip_end_wait_work(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct rkcif_device *dev = container_of(dwork, + struct rkcif_device, + work_flip); + int stream_num = 0; + int i = 0; + struct rkcif_stream *cur_stream = NULL; + unsigned long flags; + + mutex_lock(&dev->stream_lock); + if (dev->hdr.hdr_mode == HDR_X2) + stream_num = 2; + else if (dev->hdr.hdr_mode == HDR_X3) + stream_num = 3; + else + stream_num = 1; + if (dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { + for (i = 0; i < stream_num; i++) { + cur_stream = &dev->stream[i]; + if (dev->hdr.hdr_mode == NO_HDR || + (dev->hdr.hdr_mode == HDR_X2 && cur_stream->id == 1) || + (dev->hdr.hdr_mode == HDR_X3 && cur_stream->id == 2)) { + rkcif_enable_capture(cur_stream); + } else { + cur_stream->to_en_dma = RKCIF_DMAEN_BY_ISP; + rkcif_enable_dma_capture(cur_stream, true); + } + if (i == 0) { + spin_lock_irqsave(&cur_stream->vbq_lock, flags); + dev->is_in_flip = false; + spin_unlock_irqrestore(&cur_stream->vbq_lock, flags); + } + } + } else { + for (i = 0; i < stream_num; i++) { + cur_stream = &dev->stream[i]; + if (dev->sditf[0]->mode.rdbk_mode != RKISP_VICAP_RDBK_AIQ) + cur_stream->to_en_dma = RKCIF_DMAEN_BY_ISP; + else + cur_stream->to_en_dma = RKCIF_DMAEN_BY_VICAP; + rkcif_enable_dma_capture(cur_stream, true); + if (i == 0) { + spin_lock_irqsave(&cur_stream->vbq_lock, flags); + dev->is_in_flip = false; + spin_unlock_irqrestore(&cur_stream->vbq_lock, flags); + } + } + } + mutex_unlock(&dev->stream_lock); +} + static int rkcif_do_reset_work(struct rkcif_device *cif_dev, enum rkmodule_reset_src reset_src); + static long rkcif_ioctl_default(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) { struct rkcif_stream *stream = video_drvdata(file); struct rkcif_device *dev = stream->cifdev; + struct sditf_priv *priv = dev->sditf[0]; + struct rkcif_stream *cur_stream = NULL; const struct cif_input_fmt *in_fmt; struct v4l2_rect rect; struct csi_channel_info csi_info; @@ -8533,13 +9134,18 @@ static long rkcif_ioctl_default(struct file *file, void *fh, struct rkmodule_capture_info *capture_info; int reset_src; struct rkcif_quick_stream_param *stream_param; - bool is_single_dev = false; - struct v4l2_subdev *sd; int ret = 0; int i = 0; int stream_num = 0; - bool is_can_be_online = false; int on = 0; + struct rkcif_stream *last_stream = NULL; + unsigned long flags; + int flip_skip = 0; + u32 tline = 0; + u32 delay_ms = 0; + u32 vblank = 0; + struct rkisp_vicap_mode vicap_mode; + struct v4l2_subdev *sd = NULL; switch (cmd) { case RKCIF_CMD_GET_CSI_MEMORY_MODE: @@ -8587,87 +9193,68 @@ static long rkcif_ioctl_default(struct file *file, void *fh, break; case RKCIF_CMD_SET_RESET: reset_src = *(int *)arg; + if (dev->hw_dev->is_in_reset) + return 0; return rkcif_do_reset_work(dev, reset_src); case RKCIF_CMD_SET_QUICK_STREAM: stream_param = (struct rkcif_quick_stream_param *)arg; if (!dev->sditf[0]) return -EINVAL; - if (dev->hdr.hdr_mode == HDR_X2) + if (dev->hdr.hdr_mode == HDR_X2) { stream_num = 2; - else if (dev->hdr.hdr_mode == HDR_X3) + last_stream = &dev->stream[1]; + } else if (dev->hdr.hdr_mode == HDR_X3) { stream_num = 3; - else - stream_num = 1; - if (stream_param->on) { - for (i = 0; i < stream_num; i++) - dev->stream[i].cur_skip_frame = dev->stream[i].skip_frame; - is_single_dev = rkcif_check_single_dev_stream_on(dev->hw_dev); - is_can_be_online = rkcif_check_can_be_online(dev); - if (is_single_dev && is_can_be_online) { - for (i = 0; i < stream_num - 1; i++) { - dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP; - rkcif_enable_dma_capture(&dev->stream[i], true); - } - dev->sditf[0]->mode.rdbk_mode = RKISP_VICAP_ONLINE; - sditf_change_to_online(dev->sditf[0]); - sd = get_rkisp_sd(dev->sditf[0]); - if (sd) - ret = v4l2_subdev_call(sd, core, ioctl, - RKISP_VICAP_CMD_MODE, &dev->sditf[0]->mode); - if (ret) { - v4l2_err(&dev->v4l2_dev, "set isp work mode online fail\n"); - return -EINVAL; - } - } else { - sditf_disable_immediately(dev->sditf[0]); - if (dev->is_thunderboot) - dev->sditf[0]->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO; - else - dev->sditf[0]->mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ; - sd = get_rkisp_sd(dev->sditf[0]); - if (sd) - ret = v4l2_subdev_call(sd, core, ioctl, - RKISP_VICAP_CMD_MODE, &dev->sditf[0]->mode); - for (i = 0; i < stream_num; i++) { - if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) - dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP; - else - dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_VICAP; - rkcif_enable_dma_capture(&dev->stream[i], true); - } - } - rkcif_dphy_quick_stream(dev, stream_param->on); - v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, - RKMODULE_SET_QUICK_STREAM, &stream_param->on); - dev->resume_mode = RKISP_RTT_MODE_MULTI_FRAME; + last_stream = &dev->stream[2]; } else { - if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_ONLINE) { - for (i = 0; i < stream_num - 1; i++) { - reinit_completion(&dev->stream[i].stop_complete); - dev->stream[i].is_wait_stop_complete = true; - dev->stream[i].to_stop_dma = RKCIF_DMAEN_BY_ISP; - wait_for_completion_timeout(&dev->stream[i].stop_complete, - msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS)); - } + stream_num = 1; + last_stream = &dev->stream[0]; + } + if (stream_param->on) { + spin_lock_irqsave(&dev->stream_spinlock, flags); + if (last_stream->is_finish_single_cap) { + spin_unlock_irqrestore(&dev->stream_spinlock, flags); + ret = rkcif_quick_stream_on(dev, false); + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, + "%s %d, finish single capture, restart now\n", __func__, __LINE__); + } else { + last_stream->is_wait_single_cap = true; + spin_unlock_irqrestore(&dev->stream_spinlock, flags); + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, + "%s %d, wait for single capture finish, and than to restart\n", __func__, __LINE__); + reinit_completion(&last_stream->start_complete); + wait_for_completion_timeout(&last_stream->start_complete, + msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS)); + } + } else { + if (dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { stream->cifdev->sensor_state = stream_param->on; stream->cifdev->sensor_state_change = true; - dev->stream[i].is_wait_stop_complete = true; - wait_for_completion_timeout(&dev->stream[i].stop_complete, - msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS)); - } else { for (i = 0; i < stream_num; i++) { - dev->stream[i].is_wait_stop_complete = true; - reinit_completion(&dev->stream[i].stop_complete); - if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) - dev->stream[i].to_stop_dma = RKCIF_DMAEN_BY_ISP; - else - dev->stream[i].to_stop_dma = RKCIF_DMAEN_BY_VICAP; - wait_for_completion_timeout(&dev->stream[i].stop_complete, + cur_stream = &dev->stream[i]; + reinit_completion(&cur_stream->stop_complete); + cur_stream->is_wait_stop_complete = true; + wait_for_completion_timeout(&cur_stream->stop_complete, msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS)); } + } else { + for (i = 0; i < stream_num; i++) { + cur_stream = &dev->stream[i]; + cur_stream->is_wait_stop_complete = true; + reinit_completion(&cur_stream->stop_complete); + if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) + cur_stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; + else + cur_stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP; + wait_for_completion_timeout(&cur_stream->stop_complete, + msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS)); + } + mutex_lock(&stream->cifdev->stream_lock); rkcif_dphy_quick_stream(dev, stream_param->on); v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, RKMODULE_SET_QUICK_STREAM, &stream_param->on); + atomic_inc(&stream->cifdev->sensor_off); + mutex_unlock(&stream->cifdev->stream_lock); } stream_param->frame_num = dev->stream[0].frame_idx - 1; if (!dev->is_rtt_suspend) { @@ -8689,25 +9276,62 @@ static long rkcif_ioctl_default(struct file *file, void *fh, for (i = 0; i < stream_num; i++) { dev->stream[i].cur_skip_frame = dev->stream[i].skip_frame; dev->stream[i].is_single_cap = true; + stream->is_finish_single_cap = false; + stream->is_wait_single_cap = false; } - if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_ONLINE) { - for (i = 0; i < stream_num - 1; i++) { - dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP; - rkcif_enable_dma_capture(&dev->stream[i], true); + vicap_mode = priv->mode_src; + if (vicap_mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { + if (dev->chip_id == CHIP_RV1106_CIF) + vicap_mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO_ONE_FRAME; + else + vicap_mode.rdbk_mode = RKISP_VICAP_ONLINE_ONE_FRAME; + } else if (vicap_mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ) { + vicap_mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ; + } else { + vicap_mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO_ONE_FRAME; + } + + sd = get_rkisp_sd(priv); + if (sd) { + ret = v4l2_subdev_call(sd, core, ioctl, + RKISP_VICAP_CMD_MODE, &vicap_mode); + if (ret) + v4l2_err(&dev->v4l2_dev, + "set isp work mode %d failed\n", vicap_mode.rdbk_mode); + else + v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, + "set isp work mode %d", vicap_mode.rdbk_mode); + } + + if (dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { + for (i = 0; i < stream_num; i++) { + cur_stream = &dev->stream[i]; + if (dev->hdr.hdr_mode == NO_HDR || + (dev->hdr.hdr_mode == HDR_X2 && cur_stream->id == 1) || + (dev->hdr.hdr_mode == HDR_X3 && cur_stream->id == 2)) { + rkcif_enable_capture(cur_stream); + } else { + cur_stream->to_en_dma = RKCIF_DMAEN_BY_ISP; + rkcif_enable_dma_capture(cur_stream, true); + } } } else { for (i = 0; i < stream_num; i++) { - if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) - dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP; + cur_stream = &dev->stream[i]; + if (dev->sditf[0]->mode.rdbk_mode != RKISP_VICAP_RDBK_AIQ) + cur_stream->to_en_dma = RKCIF_DMAEN_BY_ISP; else - dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_VICAP; - rkcif_enable_dma_capture(&dev->stream[i], true); + cur_stream->to_en_dma = RKCIF_DMAEN_BY_VICAP; + rkcif_enable_dma_capture(cur_stream, true); } } + mutex_lock(&stream->cifdev->stream_lock); on = 1; rkcif_dphy_quick_stream(dev, on); v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, RKMODULE_SET_QUICK_STREAM, &on); + atomic_set(&stream->cifdev->sensor_off, 0); + mutex_unlock(&stream->cifdev->stream_lock); break; case RKCIF_CMD_ALLOC_BUF: buf_info = (struct rkcif_buffer_info *)arg; @@ -8746,6 +9370,76 @@ static long rkcif_ioctl_default(struct file *file, void *fh, v4l2_info(&dev->v4l2_dev, "set capture mode %d\n", dev->channels[0].capture_info.mode); break; + case RKCIF_CMD_SET_SENSOR_FLIP_START: + mutex_lock(&dev->stream_lock); + if (atomic_read(&dev->sensor_off)) { + mutex_unlock(&dev->stream_lock); + return 0; + } + if (dev->is_in_flip) { + v4l2_err(&dev->v4l2_dev, "last flip ops not finish\n"); + mutex_unlock(&dev->stream_lock); + return -EBUSY; + } + if (dev->hdr.hdr_mode == HDR_X2) + stream_num = 2; + else if (dev->hdr.hdr_mode == HDR_X3) + stream_num = 3; + else + stream_num = 1; + if (dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { + for (i = 0; i < stream_num; i++) { + cur_stream = &dev->stream[i]; + reinit_completion(&cur_stream->stop_complete); + cur_stream->is_wait_stop_complete = true; + wait_for_completion_timeout(&cur_stream->stop_complete, + msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS)); + if (i == 0) { + spin_lock_irqsave(&cur_stream->vbq_lock, flags); + dev->is_in_flip = true; + spin_unlock_irqrestore(&cur_stream->vbq_lock, flags); + } + } + } else { + for (i = 0; i < stream_num; i++) { + cur_stream = &dev->stream[i]; + cur_stream->is_wait_stop_complete = true; + reinit_completion(&cur_stream->stop_complete); + if (dev->sditf[0]->mode.rdbk_mode != RKISP_VICAP_RDBK_AIQ) + cur_stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; + else + cur_stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP; + wait_for_completion_timeout(&cur_stream->stop_complete, + msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS)); + if (i == 0) { + spin_lock_irqsave(&cur_stream->vbq_lock, flags); + dev->is_in_flip = true; + spin_unlock_irqrestore(&cur_stream->vbq_lock, flags); + } + } + } + mutex_unlock(&dev->stream_lock); + break; + case RKCIF_CMD_SET_SENSOR_FLIP_END: + mutex_lock(&dev->stream_lock); + if (atomic_read(&dev->sensor_off)) { + mutex_unlock(&dev->stream_lock); + return 0; + } + flip_skip = *(int *)arg; + if (flip_skip) { + tline = rkcif_get_linetime(stream); + tline = div_u64(tline, 1000); + vblank = rkcif_get_sensor_vblank(dev); + delay_ms = tline * ((flip_skip - 1) * (vblank + stream->pixm.height) + vblank); + delay_ms = div_u64(delay_ms, 1000); + } else { + delay_ms = 1; + } + schedule_delayed_work(&dev->work_flip, msecs_to_jiffies(delay_ms)); + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, "flip delay_ms %d\n", delay_ms); + mutex_unlock(&dev->stream_lock); + break; default: return -EINVAL; } @@ -9844,8 +10538,8 @@ static void rkcif_monitor_reset_event(struct rkcif_device *dev) timestamp0 - timestamp1 : timestamp1 - timestamp0; fps = div_u64(fps, 1000); } else { - numerator = dev->terminal_sensor.fi.interval.numerator; - denominator = dev->terminal_sensor.fi.interval.denominator; + numerator = dev->terminal_sensor.src_fi.interval.numerator; + denominator = dev->terminal_sensor.src_fi.interval.denominator; fps = div_u64(1000000 * numerator, denominator); } spin_lock_irqsave(&timer->timer_lock, flags); @@ -10377,47 +11071,47 @@ static void rkcif_line_wake_up_rdbk(struct rkcif_stream *stream, int mipi_id) } ret = rkcif_get_new_buffer_wake_up_mode_rdbk(stream); v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev, - "%d frame_idx %d, last_rx_buf_idx %d cur dma buf %x\n", + "%d frame_idx %d, last_rx_buf_idx %d cur dma buf %x, ret %d\n", __LINE__, stream->frame_idx, stream->last_rx_buf_idx, - (u32)active_buf->dummy.dma_addr); - if (!ret) { - priv = stream->cifdev->sditf[0]; - if (stream->cur_stream_mode & RKCIF_STREAM_MODE_TOISP_RDBK) { - spin_lock_irqsave(&stream->vbq_lock, flags); - if (stream->cifdev->is_thunderboot && - (stream->frame_idx - 1) == stream->last_rx_buf_idx && - stream->cifdev->is_rdbk_to_online) { - stream->cur_stream_mode &= ~RKCIF_STREAM_MODE_TOISP_RDBK; - stream->cur_stream_mode |= RKCIF_STREAM_MODE_TOISP; - stream->cifdev->wait_line = 0; - stream->is_line_wake_up = false; - if (stream->cifdev->hdr.hdr_mode == NO_HDR || - (priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 1) || - (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id == 2)) { - stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; - rkcif_stop_dma_capture(stream); - } - active_buf->dbufs.is_switch = true; - if ((priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id != 1) || - (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id != 2)) { - rkcif_store_last_buf_for_online(stream, active_buf); - stream->is_change_toisp = true; - } + (u32)active_buf->dummy.dma_addr, ret); + + priv = stream->cifdev->sditf[0]; + if (stream->cur_stream_mode & RKCIF_STREAM_MODE_TOISP_RDBK) { + spin_lock_irqsave(&stream->vbq_lock, flags); + if (stream->cifdev->is_thunderboot && + (stream->frame_idx - 1) == stream->last_rx_buf_idx && + stream->cifdev->is_rdbk_to_online) { + stream->cur_stream_mode &= ~RKCIF_STREAM_MODE_TOISP_RDBK; + stream->cur_stream_mode |= RKCIF_STREAM_MODE_TOISP; + stream->cifdev->wait_line = 0; + stream->is_line_wake_up = false; + if (stream->cifdev->hdr.hdr_mode == NO_HDR || + (priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 1) || + (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id == 2)) { + stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; + rkcif_stop_dma_capture(stream); } - spin_unlock_irqrestore(&stream->vbq_lock, flags); - active_buf->dbufs.sequence = stream->sequence; - active_buf->dbufs.timestamp = stream->readout.fs_timestamp; - active_buf->fe_timestamp = rkcif_time_get_ns(stream->cifdev); - stream->last_frame_idx = stream->frame_idx; - if (stream->cifdev->hdr.hdr_mode == NO_HDR) { - rkcif_s_rx_buffer(stream, &active_buf->dbufs); - if (stream->cifdev->is_support_tools && stream->tools_vdev) - rkcif_rdbk_with_tools(stream, active_buf); - } else { - rkcif_rdbk_frame_end_toisp(stream, active_buf); + active_buf->dbufs.is_switch = true; + if ((priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id != 1) || + (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id != 2)) { + rkcif_store_last_buf_for_online(stream, active_buf); + stream->is_change_toisp = true; } } + spin_unlock_irqrestore(&stream->vbq_lock, flags); + active_buf->dbufs.sequence = stream->sequence; + active_buf->dbufs.timestamp = stream->readout.fs_timestamp; + active_buf->fe_timestamp = rkcif_time_get_ns(stream->cifdev); + stream->last_frame_idx = stream->frame_idx; + if (stream->cifdev->hdr.hdr_mode == NO_HDR) { + rkcif_s_rx_buffer(stream, &active_buf->dbufs); + if (stream->cifdev->is_support_tools && stream->tools_vdev) + rkcif_rdbk_with_tools(stream, active_buf); + } else { + rkcif_rdbk_frame_end_toisp(stream, active_buf); + } } + } static void rkcif_deal_readout_time(struct rkcif_stream *stream) @@ -10618,7 +11312,6 @@ static void rkcif_update_stream_rockit(struct rkcif_device *cif_dev, { struct rkcif_buffer *active_buf = NULL; unsigned long flags; - int ret = 0; if (stream->frame_phase == (CIF_CSI_FRAME0_READY | CIF_CSI_FRAME1_READY)) { @@ -10644,11 +11337,9 @@ static void rkcif_update_stream_rockit(struct rkcif_device *cif_dev, if (cif_dev->inf_id == RKCIF_MIPI_LVDS) rkcif_deal_readout_time(stream); - ret = rkcif_assign_new_buffer_pingpong_rockit(stream, - RKCIF_YUV_ADDR_STATE_UPDATE, - mipi_id); - if (ret) - return; + rkcif_assign_new_buffer_pingpong_rockit(stream, + RKCIF_YUV_ADDR_STATE_UPDATE, + mipi_id); if (active_buf) { active_buf->vb.vb2_buf.timestamp = stream->readout.fs_timestamp; @@ -10676,7 +11367,7 @@ static u32 rkcif_get_sof(struct rkcif_device *cif_dev) return val; } -static void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq) +void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq) { struct rkcif_sensor_info *sensor = cif_dev->active_sensor; struct csi2_dev *csi; @@ -10702,26 +11393,17 @@ static void rkcif_toisp_set_stream(struct rkcif_device *dev, int on) RKISP_VICAP_CMD_SET_STREAM, &on); } -static int rkcif_do_reset_work(struct rkcif_device *cif_dev, - enum rkmodule_reset_src reset_src) +static int rkcif_streamoff_in_reset(struct rkcif_device *cif_dev, + struct rkcif_stream *resume_stream[], + struct rkcif_resume_info *resume_info, + enum rkmodule_reset_src reset_src) { - struct rkcif_pipeline *p = &cif_dev->pipe; struct rkcif_stream *stream = NULL; - struct rkcif_stream *resume_stream[RKCIF_MAX_STREAM_MIPI] = { NULL }; + struct rkcif_pipeline *p = &cif_dev->pipe; struct rkcif_sensor_info *terminal_sensor = &cif_dev->terminal_sensor; - struct rkcif_resume_info *resume_info = &cif_dev->reset_work.resume_info; - struct rkcif_timer *timer = &cif_dev->reset_watchdog_timer; struct sditf_priv *priv = cif_dev->sditf[0]; - int i, j, ret = 0; u32 on, sof_cnt; - int capture_mode = 0; - - mutex_lock(&cif_dev->stream_lock); - if (cif_dev->reset_work_cancel) { - ret = 0; - goto unlock_stream; - } - v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "do rkcif reset\n"); + int i, j, ret = 0; for (i = 0, j = 0; i < RKCIF_MAX_STREAM_MIPI; i++) { stream = &cif_dev->stream[i]; @@ -10746,8 +11428,6 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev, } stream->state = RKCIF_STATE_RESET_IN_STREAMING; - stream->is_fs_fe_not_paired = false; - stream->fs_cnt_in_single_frame = 0; resume_stream[j] = stream; j += 1; @@ -10797,32 +11477,27 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev, } } } + return ret; +} - rockchip_clear_system_status(SYS_STATUS_CIF0); +static int rkcif_streamon_in_reset(struct rkcif_device *cif_dev, + struct rkcif_stream *resume_stream[], + struct rkcif_resume_info *resume_info, + enum rkmodule_reset_src reset_src) +{ + struct rkcif_stream *stream = NULL; + struct rkcif_pipeline *p = &cif_dev->pipe; + struct rkcif_sensor_info *terminal_sensor = &cif_dev->terminal_sensor; + struct sditf_priv *priv = cif_dev->sditf[0]; + int i = 0; + int ret = 0; + int on = 0; + int capture_mode = 0; - if (cif_dev->chip_id >= CHIP_RK3588_CIF) { - rkcif_do_soft_reset(cif_dev); - } else { - - rkcif_do_cru_reset(cif_dev); - - rkcif_disable_sys_clk(cif_dev->hw_dev); - - udelay(5); - - ret = rkcif_enable_sys_clk(cif_dev->hw_dev); - - if (ret < 0) { - v4l2_err(&cif_dev->v4l2_dev, "%s:resume cif clk failed\n", __func__); - goto unlock_stream; - } - } - - if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) - rkcif_toisp_set_stream(cif_dev, 1); - - for (i = 0; i < j; i++) { + for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) { stream = resume_stream[i]; + if (stream == NULL || stream->state != RKCIF_STATE_RESET_IN_STREAMING) + break; stream->fs_cnt_in_single_frame = 0; if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT || rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT_AUTO) { @@ -10841,11 +11516,13 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev, if (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ) capture_mode = RKCIF_STREAM_MODE_CAPTURE; else { - if (cif_dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_ONLINE) + if (cif_dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) capture_mode = RKCIF_STREAM_MODE_TOISP; else capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; } + stream->is_fs_fe_not_paired = false; + stream->fs_cnt_in_single_frame = 0; if (cif_dev->active_sensor && (cif_dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || cif_dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY || @@ -10856,7 +11533,7 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev, if (ret) { v4l2_err(&cif_dev->v4l2_dev, "%s:resume stream[%d] failed\n", __func__, stream->id); - goto unlock_stream; + return ret; } v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, @@ -10865,8 +11542,6 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev, rkcif_get_sof(cif_dev)); } - rockchip_set_system_status(SYS_STATUS_CIF0); - on = 1; for (i = 0; i < p->num_subdevs; i++) { @@ -10911,10 +11586,97 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev, } } } + return ret; +} + +static int rkcif_do_reset_work_below_rk3588(struct rkcif_device *cif_dev, + enum rkmodule_reset_src reset_src) +{ + struct rkcif_stream *resume_stream[2][RKCIF_MAX_STREAM_MIPI] = {0}; + struct rkcif_resume_info *resume_info[2]; + struct rkcif_timer *timer = &cif_dev->reset_watchdog_timer; + struct rkcif_hw *hw = cif_dev->hw_dev; + struct rkcif_device *cifdev = NULL; + int i, ret = 0; + + mutex_lock(&hw->dev_lock); + if (cif_dev->reset_work_cancel) { + ret = 0; + goto unlock_stream; + } + + hw->is_in_reset = true; + v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "do rkcif reset\n"); + + for (i = 0; i < hw->dev_num; i++) { + cifdev = hw->cif_dev[i]; + resume_info[i] = &cifdev->reset_work.resume_info; + ret |= rkcif_streamoff_in_reset(cifdev, + resume_stream[i], + resume_info[i], + reset_src); + } + + rkcif_do_cru_reset(cif_dev); + + for (i = 0; i < hw->dev_num; i++) { + cifdev = hw->cif_dev[i]; + resume_info[i] = &cifdev->reset_work.resume_info; + ret |= rkcif_streamon_in_reset(cifdev, + resume_stream[i], + resume_info[i], + reset_src); + } + rkcif_start_luma(&cif_dev->luma_vdev, + cif_dev->stream[RKCIF_STREAM_MIPI_ID0].cif_fmt_in); + + timer->csi2_err_triggered_cnt = 0; + for (i = 0; i < hw->dev_num; i++) + rkcif_monitor_reset_event(cif_dev); + + v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "do rkcif reset successfully!\n"); + hw->is_in_reset = false; + mutex_unlock(&hw->dev_lock); + return 0; + +unlock_stream: + mutex_unlock(&hw->dev_lock); + return ret; +} + +static int rkcif_do_reset_work(struct rkcif_device *cif_dev, + enum rkmodule_reset_src reset_src) +{ + struct rkcif_stream *resume_stream[RKCIF_MAX_STREAM_MIPI] = { NULL }; + struct rkcif_resume_info *resume_info = &cif_dev->reset_work.resume_info; + struct rkcif_timer *timer = &cif_dev->reset_watchdog_timer; + struct sditf_priv *priv = cif_dev->sditf[0]; + int ret = 0; if (cif_dev->chip_id < CHIP_RK3588_CIF) - rkcif_start_luma(&cif_dev->luma_vdev, - cif_dev->stream[RKCIF_STREAM_MIPI_ID0].cif_fmt_in); + return rkcif_do_reset_work_below_rk3588(cif_dev, reset_src); + + mutex_lock(&cif_dev->stream_lock); + if (cif_dev->reset_work_cancel) { + ret = 0; + goto unlock_stream; + } + v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "do rkcif reset\n"); + + rkcif_streamoff_in_reset(cif_dev, + resume_stream, + resume_info, + reset_src); + + rkcif_do_soft_reset(cif_dev); + + if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) + rkcif_toisp_set_stream(cif_dev, 1); + + rkcif_streamon_in_reset(cif_dev, + resume_stream, + resume_info, + reset_src); timer->csi2_err_triggered_cnt = 0; rkcif_monitor_reset_event(cif_dev); @@ -11086,13 +11848,26 @@ static void rkcif_init_reset_work(struct rkcif_timer *timer) timer->last_buf_wakeup_cnt[stream->id] = stream->buf_wake_up_cnt; } spin_unlock_irqrestore(&timer->timer_lock, flags); - if (timer->is_ctrl_by_user) { - rkcif_send_reset_event(dev, timer->reset_src); + if (dev->chip_id >= CHIP_RK3588_CIF) { + if (timer->is_ctrl_by_user) { + rkcif_send_reset_event(dev, timer->reset_src); + } else { + dev->reset_work.reset_src = timer->reset_src; + if (!schedule_work(&dev->reset_work.work)) + v4l2_info(&dev->v4l2_dev, + "schedule reset work failed\n"); + } } else { - dev->reset_work.reset_src = timer->reset_src; - if (!schedule_work(&dev->reset_work.work)) - v4l2_info(&dev->v4l2_dev, - "schedule reset work failed\n"); + if (!dev->hw_dev->is_in_reset) { + if (timer->is_ctrl_by_user) { + rkcif_send_reset_event(dev, timer->reset_src); + } else { + dev->reset_work.reset_src = timer->reset_src; + if (!schedule_work(&dev->reset_work.work)) + v4l2_info(&dev->v4l2_dev, + "schedule reset work failed\n"); + } + } } } @@ -11286,7 +12061,7 @@ int rkcif_reset_notifier(struct notifier_block *nb, return 0; } -static void rkcif_modify_line_int(struct rkcif_stream *stream, bool en) +void rkcif_modify_line_int(struct rkcif_stream *stream, bool en) { struct rkcif_device *cif_dev = stream->cifdev; u32 line_intr_en = 0; @@ -11320,7 +12095,7 @@ static void rkcif_detect_wake_up_mode_change(struct rkcif_stream *stream) int ch = 0; int i = 0; - if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) + if (!priv || priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) return; if ((cif_dev->hdr.hdr_mode == NO_HDR || cif_dev->hdr.hdr_mode == HDR_COMPR) && @@ -11509,23 +12284,29 @@ void rkcif_enable_dma_capture(struct rkcif_stream *stream, bool is_only_enable) stream->dma_en |= stream->to_en_dma; if (!is_only_enable) { - if (stream->to_en_dma == RKCIF_DMAEN_BY_VICAP) { + if (stream->to_en_dma == RKCIF_DMAEN_BY_VICAP) rkcif_assign_new_buffer_pingpong(stream, RKCIF_YUV_ADDR_STATE_INIT, stream->id); - rkcif_write_register(cif_dev, get_reg_index_of_frm0_y_vlw(stream->id), - channel->virtual_width); - } else if (stream->to_en_dma == RKCIF_DMAEN_BY_ISP) { + else if (stream->to_en_dma == RKCIF_DMAEN_BY_ISP) rkcif_assign_new_buffer_pingpong_toisp(stream, RKCIF_YUV_ADDR_STATE_INIT, stream->id); - } + rkcif_write_register(cif_dev, get_reg_index_of_frm0_y_vlw(stream->id), + channel->virtual_width); } if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || - mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) - rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x00010000); - else - rkcif_write_register_or(cif_dev, CIF_REG_DVP_CTRL, 0x00010000); + mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) { + if (cif_dev->chip_id < CHIP_RK3562_CIF) + rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x00010000); + else + rkcif_write_register_or(cif_dev, get_reg_index_of_frm0_y_vlw(stream->id), BIT(31)); + } else { + if (cif_dev->chip_id < CHIP_RK3562_CIF) + rkcif_write_register_or(cif_dev, CIF_REG_DVP_CTRL, 0x00010000); + else + rkcif_write_register_or(cif_dev, CIF_REG_DVP_VIR_LINE_WIDTH, BIT(28) << stream->id); + } if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) { val = rkcif_read_register(cif_dev, get_reg_index_of_id_ctrl0(stream->id)); @@ -11697,6 +12478,60 @@ static int rkcif_g_toisp_ch_rk3576(unsigned int intstat_glb, int index) return -EINVAL; } +static u32 rkcif_toisp_get_src_id(struct sditf_priv *priv, int index, int ch) +{ + u32 reg_index = 0; + u32 val = 0; + u32 id = 0; + + if (priv->cif_dev->chip_id < CHIP_RV1103B_CIF) { + if (index == 0) + reg_index = CIF_REG_TOISP0_CTRL; + else + reg_index = CIF_REG_TOISP1_CTRL; + val = rkcif_read_register(priv->cif_dev, reg_index); + id = (val >> (ch * 8 + 3)) & 0x1f; + } else { + switch (ch) { + case 0: + reg_index = CIF_REG_TOISP0_CTRL; + break; + case 1: + reg_index = CIF_REG_TOISP0_CH1_CTRL; + break; + case 2: + reg_index = CIF_REG_TOISP0_CH2_CTRL; + break; + default: + v4l2_err(&priv->cif_dev->v4l2_dev, + "get error toisp ch %d\n", + ch); + break; + } + val = rkcif_read_register(priv->cif_dev, reg_index); + id = (val >> 3) & 0x1f; + } + return id; +} + +static void rkcif_check_vblank_value(struct rkcif_device *dev) +{ + u32 tline = 0; + u32 vblank_us = 0; + u32 vblank = 0; + + tline = rkcif_get_linetime(&dev->stream[0]); + vblank = rkcif_get_sensor_vblank(dev); + vblank_us = tline * vblank; + vblank_us = div_u64(vblank_us, 1000); + if (vblank_us < 1000) + v4l2_warn(&dev->v4l2_dev, + "Warning: vblank need >= 1000us if isp work in online, cur %u us\n", + vblank_us); + else + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, "vblank time %u us\n", vblank_us); +} + static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, unsigned int intstat_glb, int index) @@ -11717,6 +12552,8 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, ch = rkcif_g_toisp_ch_rk3576(intstat_glb, index); if (ch >= 0) { src_id = priv->toisp_inf.ch_info[ch].id; + if (src_id != rkcif_toisp_get_src_id(priv, index, ch)) + continue; if (src_id == 24) stream = &priv->cif_dev->stream[0]; else @@ -11729,27 +12566,53 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, stream->stopping = false; wake_up(&stream->wq_stopped); } - if (stream->cifdev->sensor_state_change) { + + spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags); + if (stream->is_wait_stop_complete) { + if (stream->cifdev->hdr.hdr_mode == NO_HDR || + (stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || + (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 2)) { + rkcif_disable_capture(stream); + } else { + stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; + rkcif_stop_dma_capture(stream); + } + stream->is_wait_stop_complete = false; + complete(&stream->stop_complete); + } + if (stream->cifdev->sensor_state_change && + (stream->cifdev->hdr.hdr_mode == NO_HDR || + (stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || + (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 2))) { + stream->cifdev->sensor_state_change = false; + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); rkcif_dphy_quick_stream(stream->cifdev, on); + atomic_inc(&stream->cifdev->sensor_off); stream->cifdev->sensor_work.on = stream->cifdev->sensor_state; schedule_work(&stream->cifdev->sensor_work.work); - stream->cifdev->sensor_state_change = false; - if (stream->is_wait_stop_complete) { - stream->is_wait_stop_complete = false; - complete(&stream->stop_complete); - } + } else { + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); } + spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags); if (stream->is_single_cap && (!stream->cur_skip_frame) && (stream->cifdev->hdr.hdr_mode == NO_HDR || (stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 2))) { - rkcif_dphy_quick_stream(stream->cifdev, on); - stream->cifdev->sensor_work.on = 0; - schedule_work(&stream->cifdev->sensor_work.work); - stream->is_single_cap = false; - spin_lock_irqsave(&stream->cifdev->hdr_lock, flags); - stream->cifdev->is_sensor_off = true; - spin_unlock_irqrestore(&stream->cifdev->hdr_lock, flags); + stream->is_finish_single_cap = true; + if (!stream->is_wait_single_cap) { + stream->is_single_cap = false; + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); + rkcif_dphy_quick_stream(stream->cifdev, on); + stream->cifdev->sensor_work.on = 0; + atomic_inc(&stream->cifdev->sensor_off); + schedule_work(&stream->cifdev->sensor_work.work); + } else { + stream->is_wait_single_cap = false; + complete(&stream->start_complete); + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); + } + } else { + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); } if (stream->cur_skip_frame && (stream->cifdev->hdr.hdr_mode == NO_HDR || @@ -11795,23 +12658,35 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, ch = rkcif_g_toisp_fs(intstat_glb, index); else ch = rkcif_g_toisp_fs_rk3576(intstat_glb, index); - if (ch >= 0) { + if (ch >= 0 && (!priv->is_toisp_off)) { src_id = priv->toisp_inf.ch_info[ch].id; + if (src_id != rkcif_toisp_get_src_id(priv, index, ch)) + continue; if (src_id == 24) stream = &priv->cif_dev->stream[0]; else stream = &priv->cif_dev->stream[src_id % 4]; if (stream->id == 0) { spin_lock_irqsave(&stream->vbq_lock, flags); - if (!stream->thunderboot_skip_interval || - (stream->thunderboot_skip_interval && - (stream->frame_idx % stream->thunderboot_skip_interval) == 0)) + if ((!stream->thunderboot_skip_interval || + (stream->thunderboot_skip_interval && + (stream->frame_idx % stream->thunderboot_skip_interval) == 0)) && + (!stream->cifdev->is_in_flip)) { rkcif_send_sof(stream->cifdev); + } stream->frame_idx++; + v4l2_dbg(3, rkcif_debug, &priv->cif_dev->v4l2_dev, + "stream[%d] toisp sof seq %d\n", + stream->id, + stream->frame_idx - 1); spin_unlock_irqrestore(&stream->vbq_lock, flags); + if (stream->frame_idx < 3) + rkcif_check_vblank_value(stream->cifdev); } else { stream->frame_idx++; } + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_MULTI) + sditf_disable_immediately(priv); cur_time = rkcif_time_get_ns(stream->cifdev); stream->readout.readout_time = cur_time - stream->readout.fs_timestamp; stream->readout.fs_timestamp = cur_time; @@ -11867,7 +12742,7 @@ void rkcif_irq_handle_toisp(struct rkcif_device *cif_dev, unsigned int intstat_g bool to_check = false; struct sditf_priv *priv = cif_dev->sditf[0]; - if (!priv || priv->mode.rdbk_mode != RKISP_VICAP_ONLINE) + if (!priv || priv->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ) return; for (i = 0; i < 2; i++) { @@ -11878,9 +12753,10 @@ void rkcif_irq_handle_toisp(struct rkcif_device *cif_dev, unsigned int intstat_g } else if (priv->toisp_inf.link_mode == TOISP1 && i == 1) { to_check = true; - } else if (priv->toisp_inf.link_mode == TOISP_UNITE && - i == 1) { - to_check = true; + } else if (priv->toisp_inf.link_mode == TOISP_UNITE) { + if ((cif_dev->chip_id == CHIP_RK3588_CIF && i == 1) || + (cif_dev->chip_id != CHIP_RK3588_CIF && i == 0)) + to_check = true; } if (to_check) rkcif_toisp_check_stop_status(priv, intstat_glb, i); @@ -11960,7 +12836,8 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) detect_stream->readout.fs_timestamp = rkcif_time_get_ns(cif_dev); spin_unlock_irqrestore(&detect_stream->fps_lock, flags); - if (cif_dev->sync_cfg.type != RKCIF_NOSYNC_MODE) { + if (cif_dev->sync_cfg.type != NO_SYNC_MODE && + cif_dev->sync_cfg.type != SOFT_SYNC_MODE) { struct rkcif_multi_sync_config *sync_config; sync_config = &hw->sync_config[cif_dev->sync_cfg.group]; @@ -11997,7 +12874,7 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) } } } else { - if (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode) { + if (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ) { spin_lock_irqsave(&detect_stream->vbq_lock, flags); if (!detect_stream->thunderboot_skip_interval || (detect_stream->thunderboot_skip_interval && @@ -12022,13 +12899,15 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) } if (detect_stream->cifdev->rdbk_debug && detect_stream->frame_idx < 15 && - (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode)) + (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ)) v4l2_info(&cif_dev->v4l2_dev, "stream[%d] real sof %d %lld\n", detect_stream->id, detect_stream->frame_idx - 1, rkcif_time_get_ns(cif_dev)); } + if (detect_stream->frame_idx < 3 && cif_dev->sditf[0]) + rkcif_check_vblank_value(cif_dev); } unsigned int rkcif_irq_global(struct rkcif_device *cif_dev) @@ -12088,72 +12967,89 @@ static bool rkcif_check_buffer_prepare(struct rkcif_stream *stream) bool rkcif_check_single_dev_stream_on(struct rkcif_hw *hw) { struct rkcif_device *cif_dev = NULL; - struct rkcif_stream *stream = NULL; - int i = 0, j = 0; + struct v4l2_subdev *sd = NULL; + int i = 0; int stream_cnt = 0; if (hw->dev_num == 1) return true; for (i = 0; i < hw->dev_num; i++) { cif_dev = hw->cif_dev[i]; - for (j = 0; j < RKCIF_MAX_STREAM_MIPI; j++) { - stream = &cif_dev->stream[j]; - if (stream->state == RKCIF_STATE_STREAMING || - stream->state == RKCIF_STATE_RESET_IN_STREAMING) { - stream_cnt++; - break; - } - } + sd = get_rkisp_sd(cif_dev->sditf[0]); + if (sd) + stream_cnt++; } if (stream_cnt > 1) return false; return true; } +static u64 rkcif_get_boot_time_ns_from_arch_timer(void) +{ + u64 ns; + + ns = arch_timer_read_counter() * 1000; + do_div(ns, 24); + + return ns; +} + +static u64 rkcif_get_rtt_time_offset(struct rkcif_device *cif_dev) +{ + u64 offset = 0; + u64 arch_time = 0; + + arch_time = rkcif_get_boot_time_ns_from_arch_timer(); + offset = arch_time - rkcif_time_get_ns(cif_dev); + return offset; +} + static void rkcif_get_resmem_head(struct rkcif_device *cif_dev) { void *resmem_va = phys_to_virt(cif_dev->resmem_pa); struct rkisp_thunderboot_resmem_head *head = NULL; + struct rkisp32_thunderboot_resmem_head *tmp = NULL; int size = 0; int offset = 0; - int ret = 0; - int cam_idx = 0; - char cam_idx_str[3] = {0}; + int i = 0; + int dev_id = 0; + u64 rtt_offset_time = 0; - if (!cif_dev->is_rtt_suspend) - return; - strscpy(cam_idx_str, cif_dev->terminal_sensor.sd->name + 1, 2); - cam_idx_str[2] = '\0'; - ret = kstrtoint(cam_idx_str, 0, &cam_idx); - if (ret) { - v4l2_err(&cif_dev->v4l2_dev, - "get camera index fail\n"); + if (cif_dev->resmem_pa == 0 || cif_dev->resmem_size == 0) return; + + size = sizeof(struct rkisp32_thunderboot_resmem_head); + if (cif_dev->sditf[0]) + dev_id = cif_dev->sditf[0]->mode.dev_id; + offset = size * dev_id; + + tmp = resmem_va + offset; + + dma_sync_single_for_cpu(cif_dev->dev, cif_dev->resmem_addr + offset, + size, DMA_FROM_DEVICE); + head = &tmp->head; + if (cif_dev->is_rtt_suspend) { + cif_dev->resume_mode = head->rtt_mode; + cif_dev->nr_buf_size = head->nr_buf_size; } - - if (cif_dev->chip_id == CHIP_RV1106_CIF) { - size = sizeof(struct rkisp32_thunderboot_resmem_head); - offset = size * cam_idx; - } - /* currently, thunderboot with mcu only run one camera */ - offset = 0; - - if (size && size < cif_dev->resmem_size) { - dma_sync_single_for_cpu(cif_dev->dev, cif_dev->resmem_addr + offset, - size, DMA_FROM_DEVICE); - if (cif_dev->chip_id == CHIP_RV1106_CIF) { - struct rkisp32_thunderboot_resmem_head *tmp = resmem_va + offset; - - head = &tmp->head; - cif_dev->resume_mode = head->rtt_mode; - cif_dev->nr_buf_size = head->nr_buf_size; - cif_dev->share_mem_size = head->share_mem_size; - cif_dev->thunderboot_sensor_num = head->camera_num; + cif_dev->share_mem_size = head->share_mem_size; + cif_dev->thunderboot_sensor_num = head->camera_num; + if (head->pre_buf_num && head->pre_buf_num < MAX_PRE_BUF_NUM) { + cif_dev->pre_buf_num = head->pre_buf_num; + rtt_offset_time = rkcif_get_rtt_time_offset(cif_dev); + for (i = 0; i < head->pre_buf_num; i++) { + cif_dev->pre_buf_addr[i] = head->pre_buf_addr[i]; + cif_dev->pre_buf_timestamp[i] = head->pre_buf_timestamp[i] * 1000000; + if (cif_dev->pre_buf_timestamp[i] < rtt_offset_time) + cif_dev->pre_buf_timestamp[i] = 0; + else + cif_dev->pre_buf_timestamp[i] -= rtt_offset_time; } } + v4l2_err(&cif_dev->v4l2_dev, - "get camera index %02x, resume_mode 0x%x, nr_buf_size %d\n", - cam_idx, cif_dev->resume_mode, cif_dev->nr_buf_size); + "get isp_dev %02x, resume_mode 0x%x, nr_buf_size %d\n", + dev_id, cif_dev->resume_mode, cif_dev->nr_buf_size); } static int rkcif_subdevs_set_power(struct rkcif_device *cif_dev, int on) @@ -12205,7 +13101,8 @@ static int rkcif_terminal_sensor_set_stream(struct rkcif_device *cif_dev, int on if (p->subdevs[i] == terminal_sensor->sd && on) rkcif_set_sof(cif_dev, cif_dev->stream[0].frame_idx); if (p->subdevs[i] == terminal_sensor->sd && - cif_dev->chip_id == CHIP_RV1106_CIF) { + (cif_dev->chip_id == CHIP_RV1106_CIF || + cif_dev->chip_id == CHIP_RV1103B_CIF)) { if (!rk_tb_mcu_is_done() && on) { cif_dev->tb_client.data = p->subdevs[i]; cif_dev->tb_client.cb = rkcif_sensor_quick_streaming_cb; @@ -12296,7 +13193,7 @@ int rkcif_stream_suspend(struct rkcif_device *cif_dev, int mode) mutex_lock(&cif_dev->stream_lock); - if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && mode == RKCIF_RESUME_CIF) + if (priv && priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ && mode == RKCIF_RESUME_CIF) goto out_suspend; for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) { @@ -12306,7 +13203,7 @@ int rkcif_stream_suspend(struct rkcif_device *cif_dev, int mode) suspend_cnt++; v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "stream[%d] stopping\n", stream->id); - if (!cif_dev->is_sensor_off) { + if (atomic_read(&cif_dev->sensor_off) == 0) { stream->stopping = true; ret = wait_event_timeout(stream->wq_stopped, stream->state != RKCIF_STATE_STREAMING, @@ -12366,61 +13263,60 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) int on = 1; int resume_cnt = 0; unsigned long flags; - bool is_single_dev = false; - bool is_can_be_online = false; struct rkisp_vicap_mode vicap_mode; + bool is_single_dev = false; mutex_lock(&cif_dev->stream_lock); rkcif_get_resmem_head(cif_dev); - is_single_dev = rkcif_check_single_dev_stream_on(cif_dev->hw_dev); - is_can_be_online = rkcif_check_can_be_online(cif_dev); if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME) { if (cif_dev->is_rtt_suspend) { capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; if (priv) priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO; } else { - if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) { - if (cif_dev->chip_id == CHIP_RV1106_CIF) { - capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; - priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO; + if (priv) { + priv->mode.rdbk_mode = priv->mode_src.rdbk_mode; + if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { + if (cif_dev->chip_id == CHIP_RV1106_CIF) { + capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; + priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO_ONE_FRAME; + } else { + capture_mode = RKCIF_STREAM_MODE_TOISP; + priv->mode.rdbk_mode = RKISP_VICAP_ONLINE_ONE_FRAME; + } } else { - capture_mode = RKCIF_STREAM_MODE_TOISP; + priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO_ONE_FRAME; + capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; } - } else if (priv && - (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO || - priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)) { - capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; } else { capture_mode = RKCIF_STREAM_MODE_CAPTURE; } } } else if (cif_dev->resume_mode == RKISP_RTT_MODE_MULTI_FRAME) { - if (is_single_dev && is_can_be_online) { - capture_mode = RKCIF_STREAM_MODE_TOISP; - if (priv) - priv->mode.rdbk_mode = RKISP_VICAP_ONLINE; - } else { - if (cif_dev->is_thunderboot) { - capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; - if (priv) - priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO; - } else { + if (priv) { + priv->mode.rdbk_mode = priv->mode_src.rdbk_mode; + if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) + capture_mode = RKCIF_STREAM_MODE_TOISP; + else if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ) capture_mode = RKCIF_STREAM_MODE_CAPTURE; - if (priv) - priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ; - } + else + capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; + } else { + capture_mode = RKCIF_STREAM_MODE_CAPTURE; } } else { - if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) - capture_mode = RKCIF_STREAM_MODE_TOISP; - else if (priv && - (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO || - priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)) - capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; - else + if (priv) { + if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) + capture_mode = RKCIF_STREAM_MODE_TOISP; + else if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO || + priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME) + capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK; + else + capture_mode = RKCIF_STREAM_MODE_CAPTURE; + } else { capture_mode = RKCIF_STREAM_MODE_CAPTURE; + } } if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && mode == RKCIF_RESUME_CIF) goto out_resume; @@ -12431,8 +13327,13 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) continue; stream->fs_cnt_in_single_frame = 0; - if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME) + if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME) { + spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags); stream->is_single_cap = true; + stream->is_finish_single_cap = false; + stream->is_wait_single_cap = false; + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); + } spin_lock_irqsave(&stream->vbq_lock, flags); if (!priv || priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ) { if (rkcif_get_interlace_mode(stream) == RKCIF_INTERLACE_SOFT || @@ -12450,7 +13351,7 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) stream->next_buf = NULL; } } else { - if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) { + if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { if (stream->curr_buf_toisp == stream->next_buf_toisp) { if (stream->curr_buf_toisp) list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head); @@ -12479,9 +13380,26 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) spin_unlock_irqrestore(&stream->vbq_lock, flags); + is_single_dev = rkcif_check_single_dev_stream_on(cif_dev->hw_dev); if (priv) { - if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) { - sditf_change_to_online(priv); + if (stream->is_single_cap && stream->id == 0) { + vicap_mode = priv->mode; + sd = get_rkisp_sd(priv); + if (sd) { + ret = v4l2_subdev_call(sd, core, ioctl, + RKISP_VICAP_CMD_MODE, &vicap_mode); + if (ret) + v4l2_err(&cif_dev->v4l2_dev, + "set isp work mode %d failed\n", vicap_mode.rdbk_mode); + else + v4l2_dbg(1, rkcif_debug, &stream->cifdev->v4l2_dev, + "set isp work mode %d", vicap_mode.rdbk_mode); + } + } + + if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { + if (cif_dev->chip_id == CHIP_RV1106_CIF || is_single_dev) + sditf_change_to_online(priv); if (cif_dev->resume_mode == RKISP_RTT_MODE_MULTI_FRAME && stream->rx_buf_num && (priv->hdr_cfg.hdr_mode == NO_HDR || @@ -12493,20 +13411,8 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) (priv->hdr_cfg.hdr_mode == HDR_X3 && (stream->id == 0 || stream->id == 1)))) rkcif_init_rx_buf(stream, 1); } else { - if (stream->is_single_cap && stream->id == 0) { - vicap_mode = priv->mode; - vicap_mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO_ONE_FRAME; - sd = get_rkisp_sd(priv); - if (sd) { - ret = v4l2_subdev_call(sd, core, ioctl, - RKISP_VICAP_CMD_MODE, &vicap_mode); - if (ret) - v4l2_err(&cif_dev->v4l2_dev, - "set isp work mode rdbk aotu oneframe fail\n"); - - } - } - sditf_disable_immediately(priv); + if (cif_dev->chip_id == CHIP_RV1106_CIF || is_single_dev) + sditf_disable_immediately(priv); if (!stream->rx_buf_num && capture_mode == RKCIF_STREAM_MODE_TOISP_RDBK) { if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME) @@ -12515,6 +13421,8 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) rkcif_init_rx_buf(stream, priv->buf_num); } } + v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev, + "toisp work mode %d, capture mode %d\n", priv->mode.rdbk_mode, capture_mode); } stream->lack_buf_cnt = 0; @@ -12844,6 +13752,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) int ret = 0; int on = 0; int tmp_csi_host_idx = 0; + struct rkcif_stream *last_stream = NULL; if (!cif_dev->active_sensor) return; @@ -12883,15 +13792,25 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) } cif_dev->irq_stats.csi_size_err_cnt++; cif_dev->err_state |= RKCIF_ERR_SIZE; + if (cif_dev->sditf[0] && cif_dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) + return; if (cif_dev->channels[0].capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { tmp_csi_host_idx = cif_dev->csi_host_idx; for (i = 0; i < channel->capture_info.multi_dev.dev_num; i++) { cif_dev->csi_host_idx = channel->capture_info.multi_dev.dev_idx[i]; rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); } + if (cif_dev->chip_id >= CHIP_RV1103B_CIF) { + for (i = 0; i < channel->capture_info.multi_dev.dev_num; i++) { + cif_dev->csi_host_idx = channel->capture_info.multi_dev.dev_idx[i]; + rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL, ~0x000f0000); + } + } cif_dev->csi_host_idx = tmp_csi_host_idx; } else { rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); + if (cif_dev->chip_id >= CHIP_RV1103B_CIF) + rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL, ~0x000f0000); } return; } @@ -12926,7 +13845,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) stream = &cif_dev->stream[mipi_id]; if (!cif_dev->sditf[0] || - cif_dev->sditf[0]->mode.rdbk_mode) + cif_dev->sditf[0]->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ) stream->buf_wake_up_cnt++; if (stream->stopping && (!stream->dma_en)) { @@ -12961,7 +13880,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) rkcif_fence_signal(stream); if (stream->cifdev->rdbk_debug && stream->frame_idx < 15 && - (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode)) + (!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ)) v4l2_info(&cif_dev->v4l2_dev, "stream[%d] fe %d, phase %d, %lld\n", stream->id, @@ -12976,16 +13895,19 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) } if (stream->is_finish_stop_dma && stream->is_wait_stop_complete) { - stream->is_finish_stop_dma = false; stream->is_wait_stop_complete = false; complete(&stream->stop_complete); } + if (stream->is_finish_stop_dma) + stream->is_finish_stop_dma = false; + if (stream->crop_dyn_en) rkcif_dynamic_crop(stream); if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) { - if (cif_dev->sync_cfg.type == RKCIF_NOSYNC_MODE) + if (cif_dev->sync_cfg.type == NO_SYNC_MODE || + cif_dev->sync_cfg.type == SOFT_SYNC_MODE) is_update = true; else is_update = rkcif_check_buffer_prepare(stream); @@ -13002,14 +13924,23 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_dev, "dma capture by isp, dma_en 0x%x\n", stream->dma_en); - rkcif_update_stream_toisp(cif_dev, stream, mipi_id); + if (cif_dev->sync_cfg.type == NO_SYNC_MODE || + cif_dev->sync_cfg.type == SOFT_SYNC_MODE) + is_update = true; + else + is_update = rkcif_check_buffer_prepare(stream); + if (is_update) + rkcif_update_stream_toisp(cif_dev, stream, mipi_id); } else if (stream->dma_en & RKCIF_DMAEN_BY_ROCKIT) { v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_dev, "dma capture by rockit, dma_en 0x%x\n", stream->dma_en); rkcif_update_stream_rockit(cif_dev, stream, mipi_id); } + spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags); if (stream->is_single_cap && !stream->cur_skip_frame) { + stream->is_single_cap = false; + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); if (stream->dma_en & RKCIF_DMAEN_BY_ISP) stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; else if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) @@ -13017,18 +13948,30 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) else if (stream->dma_en & RKCIF_DMAEN_BY_ROCKIT) stream->to_stop_dma = RKCIF_DMAEN_BY_ROCKIT; rkcif_stop_dma_capture(stream); - stream->is_single_cap = false; - if ((cif_dev->hdr.hdr_mode == NO_HDR && atomic_read(&cif_dev->streamoff_cnt) == 1) || - (cif_dev->hdr.hdr_mode == HDR_X2 && atomic_read(&cif_dev->streamoff_cnt) == 2) || - (cif_dev->hdr.hdr_mode == HDR_X3 && atomic_read(&cif_dev->streamoff_cnt) == 3)) { - rkcif_dphy_quick_stream(stream->cifdev, on); - cif_dev->sensor_work.on = 0; - schedule_work(&cif_dev->sensor_work.work); - spin_lock_irqsave(&cif_dev->hdr_lock, flags); - cif_dev->is_sensor_off = true; - spin_unlock_irqrestore(&cif_dev->hdr_lock, flags); + if (cif_dev->hdr.hdr_mode == HDR_X2) + last_stream = &cif_dev->stream[1]; + else if (cif_dev->hdr.hdr_mode == HDR_X3) + last_stream = &cif_dev->stream[2]; + else + last_stream = stream; + spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags); + if (!last_stream->is_wait_single_cap) { + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); + if ((cif_dev->hdr.hdr_mode == NO_HDR && atomic_read(&cif_dev->streamoff_cnt) == 1) || + (cif_dev->hdr.hdr_mode == HDR_X2 && atomic_read(&cif_dev->streamoff_cnt) == 2) || + (cif_dev->hdr.hdr_mode == HDR_X3 && atomic_read(&cif_dev->streamoff_cnt) == 3)) { + rkcif_dphy_quick_stream(stream->cifdev, on); + cif_dev->sensor_work.on = 0; + atomic_inc(&stream->cifdev->sensor_off); + schedule_work(&cif_dev->sensor_work.work); + } + } else { + last_stream->is_wait_single_cap = false; + complete(&stream->start_complete); + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); } } else if (stream->lack_buf_cnt == 2 && !stream->cur_skip_frame) { + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); if (stream->dma_en & RKCIF_DMAEN_BY_ISP) stream->to_stop_dma = RKCIF_DMAEN_BY_ISP; else if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) @@ -13036,6 +13979,8 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) else if (stream->dma_en & RKCIF_DMAEN_BY_ROCKIT) stream->to_stop_dma = RKCIF_DMAEN_BY_ROCKIT; rkcif_stop_dma_capture(stream); + } else { + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); } if (cif_dev->chip_id >= CHIP_RV1106_CIF) @@ -13048,6 +13993,8 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) stream->curr_buf_toisp); else sditf_change_to_online(cif_dev->sditf[0]); + rkcif_modify_line_int(stream, false); + stream->is_line_inten = false; } if (stream->cur_skip_frame) @@ -13078,8 +14025,13 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) CSI_START_INTSTAT(i) : CSI_START_INTSTAT_RK3576(i))) { stream = &cif_dev->stream[i]; if (i == 0) { - if (!stream->cur_skip_frame) + spin_lock_irqsave(&stream->vbq_lock, flags); + if (!stream->cur_skip_frame && (!cif_dev->is_in_flip)) { + spin_unlock_irqrestore(&stream->vbq_lock, flags); rkcif_deal_sof(cif_dev); + } else { + spin_unlock_irqrestore(&stream->vbq_lock, flags); + } } else { spin_lock_irqsave(&stream->fps_lock, flags); stream->readout.fs_timestamp = rkcif_time_get_ns(cif_dev); @@ -13125,8 +14077,6 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) 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; } v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "%s: id0 cur line:%d\n", __func__, lastline & 0x3fff); @@ -13150,6 +14100,8 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) if (intstat & DVP_SIZE_ERR) { cif_dev->irq_stats.dvp_size_err_cnt++; rkcif_write_register_or(cif_dev, CIF_REG_DVP_CTRL, 0x000A0000); + if (cif_dev->chip_id >= CHIP_RV1103B_CIF) + rkcif_write_register_and(cif_dev, CIF_REG_DVP_CTRL, ~0x000f0000); cif_dev->err_state |= RKCIF_ERR_SIZE; } @@ -13175,7 +14127,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) stream = &cif_dev->stream[ch_id]; if (!cif_dev->sditf[0] || - cif_dev->sditf[0]->mode.rdbk_mode) + cif_dev->sditf[0]->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ) stream->buf_wake_up_cnt++; if (stream->stopping) { @@ -13207,7 +14159,8 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) break; } if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) { - if (cif_dev->sync_cfg.type == RKCIF_NOSYNC_MODE) + if (cif_dev->sync_cfg.type == NO_SYNC_MODE || + cif_dev->sync_cfg.type == SOFT_SYNC_MODE) is_update = true; else is_update = rkcif_check_buffer_prepare(stream); diff --git a/drivers/media/platform/rockchip/cif/cif-rockit.c b/drivers/media/platform/rockchip/cif/cif-rockit.c index adeeab707296..6ab7120d8dd7 100644 --- a/drivers/media/platform/rockchip/cif/cif-rockit.c +++ b/drivers/media/platform/rockchip/cif/cif-rockit.c @@ -201,6 +201,8 @@ int rkcif_rockit_buf_queue(struct rockit_rkcif_cfg *input_rockit_cfg) list_add_tail(&rkcif_buf->cif_buf.queue, &stream->rockit_buf_head); spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + if (stream->lack_buf_cnt) + rkcif_check_buffer_update_pingpong_rockit(stream, stream->id); return 0; } diff --git a/drivers/media/platform/rockchip/cif/common.c b/drivers/media/platform/rockchip/cif/common.c index 27f2c1425b19..f1996a17ba8d 100644 --- a/drivers/media/platform/rockchip/cif/common.c +++ b/drivers/media/platform/rockchip/cif/common.c @@ -342,8 +342,11 @@ static struct dma_buf *rkcif_shm_alloc(struct rkisp_thunderboot_shmem *shmem) int rkcif_alloc_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffer *buf) { struct rkcif_dummy_buffer *dummy = &buf->dummy; + u32 reserved_mem = 0; - dummy->dma_addr = dev->resmem_pa + dummy->size * buf->buf_idx; + if (dev->pre_buf_num) + reserved_mem = SHARED_MEM_RESERVED_HEAD_SIZE; + dummy->dma_addr = reserved_mem + dev->resmem_pa + dummy->size * buf->buf_idx; if (dummy->dma_addr + dummy->size > dev->resmem_pa + dev->resmem_size) return -EINVAL; buf->dbufs.dma = dummy->dma_addr; diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index 211092b49324..172b1b21af3d 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -95,7 +95,7 @@ static ssize_t rkcif_store_compact_mode(struct device *dev, return len; } -static DEVICE_ATTR(compact_test, S_IWUSR | S_IRUSR, +static DEVICE_ATTR(compact_test, 0600, rkcif_show_compact_mode, rkcif_store_compact_mode); static ssize_t rkcif_show_line_int_num(struct device *dev, @@ -132,7 +132,7 @@ static ssize_t rkcif_store_line_int_num(struct device *dev, return len; } -static DEVICE_ATTR(wait_line, S_IWUSR | S_IRUSR, +static DEVICE_ATTR(wait_line, 0600, rkcif_show_line_int_num, rkcif_store_line_int_num); static ssize_t rkcif_show_dummybuf_mode(struct device *dev, @@ -167,7 +167,7 @@ static ssize_t rkcif_store_dummybuf_mode(struct device *dev, return len; } -static DEVICE_ATTR(is_use_dummybuf, S_IWUSR | S_IRUSR, +static DEVICE_ATTR(is_use_dummybuf, 0600, rkcif_show_dummybuf_mode, rkcif_store_dummybuf_mode); /* show the memory mode of each stream in stream index order, @@ -228,7 +228,7 @@ static ssize_t rkcif_store_memory_mode(struct device *dev, return len; } -static DEVICE_ATTR(is_high_align, S_IWUSR | S_IRUSR, +static DEVICE_ATTR(is_high_align, 0600, rkcif_show_memory_mode, rkcif_store_memory_mode); static ssize_t rkcif_show_scale_ch0_blc(struct device *dev, @@ -298,7 +298,7 @@ static ssize_t rkcif_store_scale_ch0_blc(struct device *dev, return len; } -static DEVICE_ATTR(scale_ch0_blc, S_IWUSR | S_IRUSR, +static DEVICE_ATTR(scale_ch0_blc, 0600, rkcif_show_scale_ch0_blc, rkcif_store_scale_ch0_blc); static ssize_t rkcif_show_scale_ch1_blc(struct device *dev, @@ -370,7 +370,7 @@ static ssize_t rkcif_store_scale_ch1_blc(struct device *dev, return len; } -static DEVICE_ATTR(scale_ch1_blc, S_IWUSR | S_IRUSR, +static DEVICE_ATTR(scale_ch1_blc, 0600, rkcif_show_scale_ch1_blc, rkcif_store_scale_ch1_blc); static ssize_t rkcif_show_scale_ch2_blc(struct device *dev, @@ -441,7 +441,7 @@ static ssize_t rkcif_store_scale_ch2_blc(struct device *dev, return len; } -static DEVICE_ATTR(scale_ch2_blc, S_IWUSR | S_IRUSR, +static DEVICE_ATTR(scale_ch2_blc, 0600, rkcif_show_scale_ch2_blc, rkcif_store_scale_ch2_blc); static ssize_t rkcif_show_scale_ch3_blc(struct device *dev, @@ -513,7 +513,7 @@ static ssize_t rkcif_store_scale_ch3_blc(struct device *dev, return len; } -static DEVICE_ATTR(scale_ch3_blc, S_IWUSR | S_IRUSR, +static DEVICE_ATTR(scale_ch3_blc, 0600, rkcif_show_scale_ch3_blc, rkcif_store_scale_ch3_blc); static ssize_t rkcif_store_capture_fps(struct device *dev, @@ -871,7 +871,7 @@ static ssize_t rkcif_store_odd_frame_id(struct device *dev, return len; } -static DEVICE_ATTR(odd_frame_id, S_IWUSR | S_IRUSR, +static DEVICE_ATTR(odd_frame_id, 0600, rkcif_show_odd_frame_id, rkcif_store_odd_frame_id); static ssize_t rkcif_show_odd_frame_fisrt(struct device *dev, @@ -920,7 +920,7 @@ static ssize_t rkcif_store_odd_frame_fisrt(struct device *dev, return len; } -static DEVICE_ATTR(odd_frame_first, S_IWUSR | S_IRUSR, +static DEVICE_ATTR(odd_frame_first, 0600, rkcif_show_odd_frame_fisrt, rkcif_store_odd_frame_fisrt); static ssize_t rkcif_show_low_latency(struct device *dev, @@ -973,6 +973,37 @@ static ssize_t rkcif_store_low_latency(struct device *dev, static DEVICE_ATTR(low_latency, S_IWUSR | S_IRUSR, rkcif_show_low_latency, rkcif_store_low_latency); +static ssize_t rkcif_show_reg_dbg(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\n", + cif_dev->reg_dbg); + return ret; +} + +static ssize_t rkcif_store_reg_dbg(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 val = 0; + int ret = 0; + + ret = kstrtoint(buf, 0, &val); + if (!ret && val >= 0 && val <= 0x3) + cif_dev->reg_dbg = val; + else + dev_info(cif_dev->dev, "set reg_dbg failed\n"); + return len; +} + +static DEVICE_ATTR(reg_dbg, 0600, + rkcif_show_reg_dbg, rkcif_store_reg_dbg); + static struct attribute *dev_attrs[] = { &dev_attr_compact_test.attr, &dev_attr_wait_line.attr, @@ -991,6 +1022,7 @@ static struct attribute *dev_attrs[] = { &dev_attr_sw_dbg_en.attr, &dev_attr_use_hw_interlace.attr, &dev_attr_low_latency.attr, + &dev_attr_reg_dbg.attr, NULL, }; @@ -1014,7 +1046,8 @@ void rkcif_write_register(struct rkcif_device *dev, index <= CIF_REG_MIPI_ON_PAD) { if (dev->chip_id == CHIP_RK3588_CIF) { csi_offset = dev->csi_host_idx * 0x100; - } else if (dev->chip_id == CHIP_RV1106_CIF) { + } else if (dev->chip_id == CHIP_RV1106_CIF || + dev->chip_id == CHIP_RV1103B_CIF) { csi_offset = dev->csi_host_idx * 0x200; } else if (dev->chip_id == CHIP_RK3562_CIF) { if (dev->csi_host_idx < 3) @@ -1055,7 +1088,8 @@ void rkcif_write_register_or(struct rkcif_device *dev, index <= CIF_REG_MIPI_ON_PAD) { if (dev->chip_id == CHIP_RK3588_CIF) { csi_offset = dev->csi_host_idx * 0x100; - } else if (dev->chip_id == CHIP_RV1106_CIF) { + } else if (dev->chip_id == CHIP_RV1106_CIF || + dev->chip_id == CHIP_RV1103B_CIF) { csi_offset = dev->csi_host_idx * 0x200; } else if (dev->chip_id == CHIP_RK3562_CIF) { if (dev->csi_host_idx < 3) @@ -1099,7 +1133,8 @@ void rkcif_write_register_and(struct rkcif_device *dev, index <= CIF_REG_MIPI_ON_PAD) { if (dev->chip_id == CHIP_RK3588_CIF) { csi_offset = dev->csi_host_idx * 0x100; - } else if (dev->chip_id == CHIP_RV1106_CIF) { + } else if (dev->chip_id == CHIP_RV1106_CIF || + dev->chip_id == CHIP_RV1103B_CIF) { csi_offset = dev->csi_host_idx * 0x200; } else if (dev->chip_id == CHIP_RK3562_CIF) { if (dev->csi_host_idx < 3) @@ -1144,7 +1179,8 @@ unsigned int rkcif_read_register(struct rkcif_device *dev, index <= CIF_REG_MIPI_ON_PAD) { if (dev->chip_id == CHIP_RK3588_CIF) { csi_offset = dev->csi_host_idx * 0x100; - } else if (dev->chip_id == CHIP_RV1106_CIF) { + } else if (dev->chip_id == CHIP_RV1106_CIF || + dev->chip_id == CHIP_RV1103B_CIF) { csi_offset = dev->csi_host_idx * 0x200; } else if (dev->chip_id == CHIP_RK3562_CIF) { if (dev->csi_host_idx < 3) @@ -1408,7 +1444,8 @@ static void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev) } if (sync_config->mode == RKCIF_MASTER_MASTER || - sync_config->mode == RKCIF_MASTER_SLAVE) { + sync_config->mode == RKCIF_MASTER_SLAVE || + sync_config->mode == RKCIF_SOFT_SYNC) { for (i = 0; i < sync_config->slave.count; i++) { dev = sync_config->slave.cif_dev[i]; is_streaming = sync_config->slave.is_streaming[i]; @@ -1488,6 +1525,32 @@ static void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev) v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, "quick stream in sync mode, int_master_dev[%d]\n", i); } + for (i = 0; i < sync_config->soft_sync.count; i++) { + dev = sync_config->soft_sync.cif_dev[i]; + is_streaming = sync_config->soft_sync.is_streaming[i]; + if (!is_streaming) { + if (dev->sditf_cnt == 1) { + ret = v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, + RKMODULE_SET_QUICK_STREAM, &on); + if (ret) + dev_info(hw->dev, + "set RKMODULE_SET_QUICK_STREAM failed\n"); + } else { + for (j = 0; j < dev->sditf_cnt; j++) + ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd, + core, + ioctl, + RKMODULE_SET_QUICK_STREAM, + &on); + if (ret) + dev_info(dev->dev, + "set RKMODULE_SET_QUICK_STREAM failed\n"); + } + sync_config->soft_sync.is_streaming[i] = true; + } + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, + "quick stream in sync mode, soft_sync[%d]\n", i); + } } mutex_unlock(&hw->dev_lock); } @@ -1552,9 +1615,12 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on) cif_dev->reset_watchdog_timer.is_running = false; cif_dev->err_state_work.last_timestamp = 0; cif_dev->is_toisp_reset = false; + atomic_set(&cif_dev->sensor_off, 0); for (i = 0; i < cif_dev->num_channels; i++) cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0; cif_dev->reset_watchdog_timer.run_cnt = 0; + } else { + atomic_set(&cif_dev->sensor_off, 1); } /* phy -> sensor */ @@ -1609,6 +1675,9 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on) for (i = 0; i < cif_dev->num_channels; i++) cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0; cif_dev->reset_watchdog_timer.run_cnt = 0; + atomic_set(&cif_dev->sensor_off, 0); + } else { + atomic_set(&cif_dev->sensor_off, 1); } /* phy -> sensor */ @@ -1623,6 +1692,8 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on) } else { ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on); } + if (on && i == 0 && cif_dev->is_thunderboot && cif_dev->pre_buf_num) + rkcif_set_sof(cif_dev, cif_dev->pre_buf_num); if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) goto err_stream_off; } @@ -1694,6 +1765,9 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on) for (i = 0; i < cif_dev->num_channels; i++) cif_dev->reset_watchdog_timer.last_buf_wakeup_cnt[i] = 0; cif_dev->reset_watchdog_timer.run_cnt = 0; + atomic_set(&cif_dev->sensor_off, 0); + } else { + atomic_set(&cif_dev->sensor_off, 1); } /* phy -> sensor */ @@ -1750,7 +1824,8 @@ static int rkcif_create_link(struct rkcif_device *dev, u32 flags, pad, id; int pad_offset = 0; - if (dev->chip_id >= CHIP_RK3588_CIF) + if (dev->chip_id >= CHIP_RK3588_CIF && + dev->chip_id != CHIP_RV1103B_CIF) pad_offset = 4; linked_sensor.lanes = sensor->lanes; @@ -1835,7 +1910,8 @@ static int rkcif_create_link(struct rkcif_device *dev, break; } } - if (dev->chip_id >= CHIP_RK3588_CIF) { + if (dev->chip_id >= CHIP_RK3588_CIF && + dev->chip_id != CHIP_RV1103B_CIF) { for (id = 0; id < stream_num; id++) { source_entity = &linked_sensor.sd->entity; sink_entity = &dev->scale_vdev[id].vnode.vdev.entity; @@ -2167,7 +2243,8 @@ static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev) return -EINVAL; } - if (cif_dev->chip_id >= CHIP_RK3588_CIF) { + if (cif_dev->chip_id >= CHIP_RK3588_CIF && + cif_dev->chip_id != CHIP_RV1103B_CIF) { ret = rkcif_register_scale_vdevs(cif_dev, RKCIF_MAX_SCALE_CH, true); if (ret < 0) { @@ -2200,7 +2277,8 @@ static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev) return 0; err_unreg_stream_vdev: rkcif_unregister_stream_vdevs(cif_dev, stream_num); - if (cif_dev->chip_id >= CHIP_RK3588_CIF) + if (cif_dev->chip_id >= CHIP_RK3588_CIF && + cif_dev->chip_id != CHIP_RV1103B_CIF) rkcif_unregister_scale_vdevs(cif_dev, RKCIF_MAX_SCALE_CH); if (cif_dev->chip_id > CHIP_RK1808_CIF) @@ -2369,10 +2447,16 @@ void rkcif_set_sensor_stream(struct work_struct *work) struct rkcif_device, sensor_work); - v4l2_subdev_call(cif_dev->terminal_sensor.sd, - core, ioctl, - RKMODULE_SET_QUICK_STREAM, - &sensor_work->on); + mutex_lock(&cif_dev->stream_lock); + if ((atomic_read(&cif_dev->sensor_off) && sensor_work->on == 0) || + (!atomic_read(&cif_dev->sensor_off) && sensor_work->on == 1)) { + v4l2_subdev_call(cif_dev->terminal_sensor.sd, + core, ioctl, + RKMODULE_SET_QUICK_STREAM, + &sensor_work->on); + } + mutex_unlock(&cif_dev->stream_lock); + } static void rkcif_deal_err_intr(struct work_struct *work) @@ -2716,10 +2800,12 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int spin_lock_init(&cif_dev->buffree_lock); spin_lock_init(&cif_dev->reset_watchdog_timer.timer_lock); spin_lock_init(&cif_dev->reset_watchdog_timer.csi2_err_lock); + spin_lock_init(&cif_dev->stream_spinlock); atomic_set(&cif_dev->pipe.power_cnt, 0); atomic_set(&cif_dev->pipe.stream_cnt, 0); atomic_set(&cif_dev->power_cnt, 0); atomic_set(&cif_dev->streamoff_cnt, 0); + atomic_set(&cif_dev->sensor_off, 1); cif_dev->is_start_hdr = false; cif_dev->pipe.open = rkcif_pipeline_open; cif_dev->pipe.close = rkcif_pipeline_close; @@ -2734,8 +2820,11 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int cif_dev->is_thunderboot = false; cif_dev->rdbk_debug = 0; cif_dev->is_stop_skip = false; - cif_dev->is_sensor_off = false; cif_dev->exp_dbg = 0; + cif_dev->is_thunderboot_start = false; + cif_dev->is_in_flip = false; + cif_dev->sw_reg = devm_kzalloc(cif_dev->dev, RKCIF_REG_MAX, GFP_KERNEL); + cif_dev->reg_dbg = 0; cif_dev->resume_mode = 0; memset(&cif_dev->channels[0].capture_info, 0, sizeof(cif_dev->channels[0].capture_info)); @@ -2746,6 +2835,7 @@ 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); INIT_WORK(&cif_dev->exp_work, rkcif_exp_work); + INIT_DELAYED_WORK(&cif_dev->work_flip, rkcif_flip_end_wait_work); cif_dev->exp_delay.time_delay = 2; cif_dev->exp_delay.gain_delay = 2; cif_dev->is_alloc_buf_user = false; @@ -2774,7 +2864,8 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID3); } - if (cif_dev->chip_id >= CHIP_RK3588_CIF) { + if (cif_dev->chip_id >= CHIP_RK3588_CIF && + cif_dev->chip_id != CHIP_RV1103B_CIF) { rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH0); rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH1); rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH2); @@ -2851,6 +2942,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int list_add_tail(&cif_dev->list, &rkcif_device_list); mutex_unlock(&rkcif_dev_mutex); + cif_dev->pre_buf_num = 0; return 0; err_unreg_media_dev: @@ -2884,8 +2976,7 @@ int rkcif_plat_uninit(struct rkcif_device *cif_dev) } rkcif_unregister_stream_vdevs(cif_dev, stream_num); - if (cif_dev->chip_id == CHIP_RV1106_CIF) - rkcif_rockit_dev_deinit(); + rkcif_rockit_dev_deinit(); return 0; } @@ -3024,8 +3115,7 @@ static int rkcif_plat_probe(struct platform_device *pdev) dev_warn(dev, "dev:%s create proc failed\n", dev_name(dev)); rkcif_init_reset_monitor(cif_dev); - if (cif_dev->chip_id == CHIP_RV1106_CIF) - rkcif_rockit_dev_init(cif_dev); + rkcif_rockit_dev_init(cif_dev); pm_runtime_enable(&pdev->dev); return 0; @@ -3085,7 +3175,8 @@ static int __maybe_unused rkcif_runtime_resume(struct device *dev) mutex_lock(&cif_dev->hw_dev->dev_lock); ret = pm_runtime_resume_and_get(cif_dev->hw_dev->dev); mutex_unlock(&cif_dev->hw_dev->dev_lock); - rkcif_do_soft_reset(cif_dev); + if (cif_dev->chip_id >= CHIP_RK3588_CIF) + rkcif_do_soft_reset(cif_dev); return (ret > 0) ? 0 : ret; } diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 43ed275a76b3..49ff16441cfa 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -40,6 +40,7 @@ #define CIF_MONITOR_PARA_NUM (5) +#define RKCIF_REG_MAX (0x900) #define RKCIF_SINGLE_STREAM 1 #define RKCIF_STREAM_CIF 0 #define CIF_DVP_VDEV_NAME CIF_VIDEODEVICE_NAME "_dvp" @@ -102,6 +103,16 @@ #define RKCIF_SKIP_FRAME_MAX (16) +#ifdef CONFIG_CPU_RV1106 +#define SHARED_MEM_RESERVED_HEAD_SIZE (0x6000) +#endif +#ifdef CONFIG_CPU_RV1103B +#define SHARED_MEM_RESERVED_HEAD_SIZE (0x9000) +#endif +#ifndef SHARED_MEM_RESERVED_HEAD_SIZE +#define SHARED_MEM_RESERVED_HEAD_SIZE (0) +#endif + enum rkcif_workmode { RKCIF_WORKMODE_ONEFRAME = 0x00, RKCIF_WORKMODE_PINGPONG = 0x01, @@ -167,6 +178,11 @@ enum rkcif_crop_src { CROP_SRC_MAX }; +enum rkcif_reg_dbg_level { + RKCIF_REG_DBG_PART = 1, /* print current device */ + RKCIF_REG_DBG_ALL = 2, /* print all register */ +}; + /* * struct rkcif_pipeline - An CIF hardware pipeline * @@ -224,6 +240,7 @@ struct rkcif_sensor_info { struct v4l2_subdev *sd; struct v4l2_mbus_config mbus; struct v4l2_subdev_frame_interval fi; + struct v4l2_subdev_frame_interval src_fi; int lanes; struct v4l2_rect raw_rect; struct v4l2_subdev_selection selection; @@ -541,6 +558,7 @@ struct rkcif_stream { struct rkcif_buffer *next_buf; struct rkcif_rx_buffer *curr_buf_toisp; struct rkcif_rx_buffer *next_buf_toisp; + struct rkcif_rx_buffer *last_buf_toisp; struct list_head rockit_buf_head; struct rkcif_buffer *curr_buf_rockit; struct rkcif_buffer *next_buf_rockit; @@ -584,6 +602,7 @@ struct rkcif_stream { int sw_dbg_en; atomic_t buf_cnt; struct completion stop_complete; + struct completion start_complete; struct rkcif_toisp_buf_state toisp_buf_state; u32 skip_frame; u32 cur_skip_frame; @@ -595,6 +614,7 @@ struct rkcif_stream { struct list_head qbuf_fence_list_head; struct list_head done_fence_list_head; spinlock_t fence_lock; + u32 rounding_bit; bool stopping; bool crop_enable; bool crop_dyn_en; @@ -616,6 +636,10 @@ struct rkcif_stream { bool is_wait_stop_complete; bool interlaced_bad_frame; bool low_latency; + bool is_finish_single_cap; + bool is_wait_single_cap; + bool is_m_online_fb_res; + bool is_fb_first_frame; }; struct rkcif_lvds_subdev { @@ -911,6 +935,7 @@ struct rkcif_device { atomic_t stream_cnt; atomic_t power_cnt; atomic_t streamoff_cnt; + atomic_t sensor_off; struct mutex stream_lock; /* lock between streams */ struct mutex scale_lock; /* lock between scale dev */ struct mutex tools_lock; /* lock between tools dev */ @@ -931,6 +956,7 @@ struct rkcif_device { struct rkcif_irq_stats irq_stats; spinlock_t hdr_lock; /* lock for hdr buf sync */ spinlock_t buffree_lock; + spinlock_t stream_spinlock; struct rkcif_timer reset_watchdog_timer; struct rkcif_work_struct reset_work; int id_use_cnt; @@ -966,9 +992,10 @@ struct rkcif_device { bool is_toisp_reset; bool use_hw_interlace; bool is_stop_skip; - bool is_sensor_off; bool is_alloc_buf_user; bool is_camera_over_bridge; + bool is_thunderboot_start; + bool is_in_flip; int rdbk_debug; struct rkcif_sync_cfg sync_cfg; int sditf_cnt; @@ -988,6 +1015,13 @@ struct rkcif_device { u32 other_intstat[RKMODULE_MULTI_DEV_NUM]; u32 fb_res_bufs; int exp_dbg; + struct delayed_work work_flip; + void *sw_reg; + int reg_dbg; + struct rkcif_csi_info csi_info; + u32 pre_buf_num; + u32 pre_buf_addr[MAX_PRE_BUF_NUM]; + u64 pre_buf_timestamp[MAX_PRE_BUF_NUM]; }; extern struct platform_driver rkcif_plat_drv; @@ -1090,7 +1124,8 @@ void rkcif_free_buf_by_user_require(struct rkcif_device *dev); static inline u64 rkcif_time_get_ns(struct rkcif_device *dev) { - if (dev->chip_id == CHIP_RV1106_CIF) + if (dev->chip_id == CHIP_RV1106_CIF || + dev->chip_id == CHIP_RV1103B_CIF) return ktime_get_boottime_ns(); else return ktime_get_ns(); @@ -1099,4 +1134,14 @@ static inline u64 rkcif_time_get_ns(struct rkcif_device *dev) bool rkcif_check_single_dev_stream_on(struct rkcif_hw *hw); void rkcif_dphy_quick_stream(struct rkcif_device *dev, int on); +void rkcif_check_buffer_update_pingpong_rockit(struct rkcif_stream *stream, + int channel_id); + +int rkcif_quick_stream_on(struct rkcif_device *dev, bool is_intr); + +void rkcif_flip_end_wait_work(struct work_struct *work); +void rkcif_reinit_right_half_config(struct rkcif_stream *stream); +void rkcif_modify_line_int(struct rkcif_stream *stream, bool en); + +void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq); #endif diff --git a/drivers/media/platform/rockchip/cif/hw.c b/drivers/media/platform/rockchip/cif/hw.c index 5b895e0d197b..13a4a6fc10e7 100644 --- a/drivers/media/platform/rockchip/cif/hw.c +++ b/drivers/media/platform/rockchip/cif/hw.c @@ -1080,6 +1080,86 @@ static const struct cif_reg rk3576_cif_regs[] = { [CIF_REG_GRF_CIFIO_CON] = CIF_REG(CIF_GRF_IOC_MISC_CON1_RK3576), }; +static const char * const rv1103b_cif_clks[] = { + "aclk_cif", + "hclk_cif", + "dclk_cif", + "isp0clk_cif", +}; + +static const char * const rv1103b_cif_rsts[] = { + "rst_cif_a", + "rst_cif_isp0", + "rst_cif_h", + "rst_cif_d", +}; + +static const struct cif_reg rv1103b_cif_regs[] = { + [CIF_REG_MIPI_LVDS_ID0_CTRL0] = CIF_REG(CSI_MIPI0_ID0_CTRL0), + [CIF_REG_MIPI_LVDS_ID0_CTRL1] = CIF_REG(CSI_MIPI0_ID0_CTRL1), + [CIF_REG_MIPI_LVDS_ID1_CTRL0] = CIF_REG(CSI_MIPI0_ID1_CTRL0), + [CIF_REG_MIPI_LVDS_ID1_CTRL1] = CIF_REG(CSI_MIPI0_ID1_CTRL1), + [CIF_REG_MIPI_LVDS_ID2_CTRL0] = CIF_REG(CSI_MIPI0_ID2_CTRL0), + [CIF_REG_MIPI_LVDS_ID2_CTRL1] = CIF_REG(CSI_MIPI0_ID2_CTRL1), + [CIF_REG_MIPI_LVDS_ID3_CTRL0] = CIF_REG(CSI_MIPI0_ID3_CTRL0), + [CIF_REG_MIPI_LVDS_ID3_CTRL1] = CIF_REG(CSI_MIPI0_ID3_CTRL1), + [CIF_REG_MIPI_LVDS_CTRL] = CIF_REG(CSI_MIPI0_CTRL), + [CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID0), + [CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID0), + [CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID0), + [CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID0), + [CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0] = CIF_REG(CSI_MIPI0_VLW_ID0), + [CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID1), + [CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID1), + [CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID1), + [CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID1), + [CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1] = CIF_REG(CSI_MIPI0_VLW_ID1), + [CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID2), + [CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID2), + [CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID2), + [CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID2), + [CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2] = CIF_REG(CSI_MIPI0_VLW_ID2), + [CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID3), + [CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID3), + [CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID3), + [CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID3), + [CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3] = CIF_REG(CSI_MIPI0_VLW_ID3), + [CIF_REG_MIPI_LVDS_INTEN] = CIF_REG(CSI_MIPI0_INTEN), + [CIF_REG_MIPI_LVDS_INTSTAT] = CIF_REG(CSI_MIPI0_INTSTAT), + [CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1] = CIF_REG(CSI_MIPI0_LINE_INT_NUM_ID0_1_RK3576), + [CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3] = CIF_REG(CSI_MIPI0_LINE_INT_NUM_ID2_3_RK3576), + [CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1] = CIF_REG(CSI_MIPI0_LINE_CNT_ID0_1_RK3576), + [CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3] = CIF_REG(CSI_MIPI0_LINE_CNT_ID2_3_RK3576), + [CIF_REG_MIPI_LVDS_ID0_CROP_START] = CIF_REG(CSI_MIPI0_ID0_CROP_START_RK3576), + [CIF_REG_MIPI_LVDS_ID1_CROP_START] = CIF_REG(CSI_MIPI0_ID1_CROP_START_RK3576), + [CIF_REG_MIPI_LVDS_ID2_CROP_START] = CIF_REG(CSI_MIPI0_ID2_CROP_START_RK3576), + [CIF_REG_MIPI_LVDS_ID3_CROP_START] = CIF_REG(CSI_MIPI0_ID3_CROP_START_RK3576), + [CIF_REG_MIPI_FRAME_NUM_VC0] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC0_RK3576), + [CIF_REG_MIPI_FRAME_NUM_VC1] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC1_RK3576), + [CIF_REG_MIPI_FRAME_NUM_VC2] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC2_RK3576), + [CIF_REG_MIPI_FRAME_NUM_VC3] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC3_RK3576), + [CIF_REG_MIPI_EFFECT_CODE_ID0] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID0_RK3576), + [CIF_REG_MIPI_EFFECT_CODE_ID1] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID1_RK3576), + [CIF_REG_MIPI_EFFECT_CODE_ID2] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID2_RK3576), + [CIF_REG_MIPI_EFFECT_CODE_ID3] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID3_RK3576), + [CIF_REG_MIPI_ON_PAD] = CIF_REG(CSI_MIPI0_ON_PAD_RK3576), + [CIF_REG_MIPI_SET_SIZE_ID0] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID0_RK3576), + [CIF_REG_MIPI_SET_SIZE_ID1] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID1_RK3576), + [CIF_REG_MIPI_SET_SIZE_ID2] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID2_RK3576), + [CIF_REG_MIPI_SET_SIZE_ID3] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID3_RK3576), + + [CIF_REG_GLB_CTRL] = CIF_REG(GLB_CTRL), + [CIF_REG_GLB_INTEN] = CIF_REG(GLB_INTEN), + [CIF_REG_GLB_INTST] = CIF_REG(GLB_INTST), + + [CIF_REG_TOISP0_CTRL] = CIF_REG(TOISP0_CH_CTRL), + [CIF_REG_TOISP0_SIZE] = CIF_REG(TOISP0_CROP_SIZE), + [CIF_REG_TOISP0_CROP] = CIF_REG(TOISP0_CROP), + [CIF_REG_TOISP0_CH1_CTRL] = CIF_REG(TOISP0_CH1_CTRL), + [CIF_REG_TOISP0_CH1_SIZE] = CIF_REG(TOISP0_CH1_CROP_SIZE), + [CIF_REG_TOISP0_CH1_CROP] = CIF_REG(TOISP0_CH1_CROP), +}; + static const struct rkcif_hw_match_data px30_cif_match_data = { .chip_id = CHIP_PX30_CIF, .clks = px30_cif_clks, @@ -1197,6 +1277,15 @@ static const struct rkcif_hw_match_data rk3576_cif_match_data = { .cif_regs = rk3576_cif_regs, }; +static const struct rkcif_hw_match_data rv1103b_cif_match_data = { + .chip_id = CHIP_RV1103B_CIF, + .clks = rv1103b_cif_clks, + .clks_num = ARRAY_SIZE(rv1103b_cif_clks), + .rsts = rv1103b_cif_rsts, + .rsts_num = ARRAY_SIZE(rv1103b_cif_rsts), + .cif_regs = rv1103b_cif_regs, +}; + static const struct of_device_id rkcif_plat_of_match[] = { #ifdef CONFIG_CPU_PX30 { @@ -1273,6 +1362,12 @@ static const struct of_device_id rkcif_plat_of_match[] = { .compatible = "rockchip,rk3576-cif", .data = &rk3576_cif_match_data, }, +#endif +#ifdef CONFIG_CPU_RV1103B + { + .compatible = "rockchip,rv1103b-cif", + .data = &rv1103b_cif_match_data, + }, #endif {}, }; @@ -1473,9 +1568,17 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) if (irq < 0) return irq; - ret = devm_request_irq(dev, irq, rkcif_irq_handler, - IRQF_SHARED, - dev_driver_string(dev), dev); + if (cif_hw->chip_id == CHIP_RV1106_CIF || + cif_hw->chip_id == CHIP_RV1103B_CIF) { + irq_set_status_flags(irq, IRQ_NOAUTOEN); + ret = devm_request_irq(dev, irq, rkcif_irq_handler, + 0, + dev_driver_string(dev), dev); + } else { + ret = devm_request_irq(dev, irq, rkcif_irq_handler, + IRQF_SHARED, + dev_driver_string(dev), dev); + } if (ret < 0) { dev_err(dev, "request irq failed: %d\n", ret); return ret; @@ -1505,6 +1608,7 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) if (IS_ERR(cif_hw->base_addr)) return PTR_ERR(cif_hw->base_addr); } + cif_hw->res = res; if (of_property_read_bool(np, "rockchip,android-usb-camerahal-enable")) { dev_info(dev, "config cif adapt to android usb camera hal!\n"); @@ -1553,7 +1657,9 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) cif_hw->is_dma_contig = true; mutex_init(&cif_hw->dev_lock); spin_lock_init(&cif_hw->group_lock); + spin_lock_init(&cif_hw->reset_lock); atomic_set(&cif_hw->power_cnt, 0); + cif_hw->is_in_reset = false; cif_hw->iommu_en = is_iommu_enable(dev); ret = of_reserved_mem_device_init(dev); @@ -1624,10 +1730,14 @@ static void rkcif_hw_shutdown(struct platform_device *pdev) if (pm_runtime_get_if_in_use(&pdev->dev) <= 0) return; - if (cif_hw->chip_id == CHIP_RK3588_CIF || - cif_hw->chip_id == CHIP_RV1106_CIF || - cif_hw->chip_id == CHIP_RK3562_CIF) { + if (cif_hw->chip_id >= CHIP_RK3588_CIF) { write_cif_reg(cif_hw->base_addr, 0, 0); + for (i = 0; i < cif_hw->dev_num; i++) { + cif_dev = cif_hw->cif_dev[i]; + if (atomic_read(&cif_dev->pipe.stream_cnt)) + cif_dev->pipe.set_stream(&cif_dev->pipe, false); + + } } else { for (i = 0; i < cif_hw->dev_num; i++) { cif_dev = cif_hw->cif_dev[i]; @@ -1640,6 +1750,7 @@ static void rkcif_hw_shutdown(struct platform_device *pdev) rkcif_write_register(cif_dev, CIF_REG_DVP_CTRL, 0); + cif_dev->pipe.set_stream(&cif_dev->pipe, false); } } } @@ -1656,6 +1767,10 @@ static int __maybe_unused rkcif_runtime_suspend(struct device *dev) return 0; rkcif_disable_sys_clk(cif_hw); + if (cif_hw->chip_id == CHIP_RV1106_CIF || + cif_hw->chip_id == CHIP_RV1103B_CIF) + disable_irq(cif_hw->irq); + return pinctrl_pm_select_sleep_state(dev); } @@ -1672,6 +1787,10 @@ static int __maybe_unused rkcif_runtime_resume(struct device *dev) rkcif_enable_sys_clk(cif_hw); rkcif_hw_soft_reset(cif_hw, true); + if (cif_hw->chip_id == CHIP_RV1106_CIF || + cif_hw->chip_id == CHIP_RV1103B_CIF) + enable_irq(cif_hw->irq); + return 0; } diff --git a/drivers/media/platform/rockchip/cif/hw.h b/drivers/media/platform/rockchip/cif/hw.h index 7521f4239c11..4645dd3f46ce 100644 --- a/drivers/media/platform/rockchip/cif/hw.h +++ b/drivers/media/platform/rockchip/cif/hw.h @@ -50,6 +50,7 @@ enum rkcif_sync_mode { RKCIF_MASTER_SLAVE, RKCIF_EXT_MASTER, RKCIF_EXT_SLAVE, + RKCIF_SOFT_SYNC, }; struct rkcif_sync_dev { @@ -62,6 +63,7 @@ struct rkcif_multi_sync_config { struct rkcif_sync_dev int_master; struct rkcif_sync_dev ext_master; struct rkcif_sync_dev slave; + struct rkcif_sync_dev soft_sync; enum rkcif_sync_mode mode; int dev_cnt; int streaming_cnt; @@ -108,6 +110,7 @@ enum rkcif_chip_id { CHIP_RV1106_CIF, CHIP_RK3562_CIF, CHIP_RK3576_CIF, + CHIP_RV1103B_CIF, }; struct rkcif_hw_match_data { @@ -129,7 +132,7 @@ struct rkcif_hw { struct device *dev; int irq; void __iomem *base_addr; - void __iomem *csi_base; + struct resource *res; struct regmap *grf; struct clk *clks[RKCIF_MAX_BUS_CLK]; int clk_size; @@ -145,6 +148,7 @@ struct rkcif_hw { struct mutex dev_lock; struct rkcif_multi_sync_config sync_config[RKCIF_MAX_GROUP]; spinlock_t group_lock; + spinlock_t reset_lock; struct notifier_block reset_notifier; /* reset for mipi csi crc err */ struct rkcif_dummy_buffer dummy_buf; bool iommu_en; @@ -154,6 +158,7 @@ struct rkcif_hw { bool adapt_to_usbcamerahal; u64 irq_time; bool is_rk3588s2; + bool is_in_reset; }; void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu); diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.c b/drivers/media/platform/rockchip/cif/mipi-csi2.c index 0c2326fb0389..3fb0ce847176 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.c +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.c @@ -183,6 +183,10 @@ static void csi2_enable(struct csi2_hw *csi2_hw, int lanes = csi2->bus.num_data_lanes; struct v4l2_mbus_config mbus; u32 val = 0; + u32 mask1 = 0; + struct v4l2_subdev *terminal_sensor_sd = NULL; + struct rkmodule_hdr_cfg hdr_cfg = {0}; + int ret = 0; csi2_g_mbus_config(&csi2->sd, 0, &mbus); if (mbus.type == V4L2_MBUS_CSI2_DPHY) @@ -195,6 +199,24 @@ static void csi2_enable(struct csi2_hw *csi2_hw, if (csi2->sw_dbg) val |= BIT(6); + get_remote_terminal_sensor(&csi2->sd, &terminal_sensor_sd); + if (terminal_sensor_sd) { + ret = v4l2_subdev_call(terminal_sensor_sd, + core, ioctl, + RKMODULE_GET_HDR_CFG, + &hdr_cfg); + if (ret != 0) + hdr_cfg.hdr_mode = NO_HDR; + if (strstr(terminal_sensor_sd->name, "sc") && + (hdr_cfg.hdr_mode == HDR_X2 || hdr_cfg.hdr_mode == HDR_X3)) { + mask1 = CSIHOST_ERR1_ERR_BNDRY_MATCH; + csi2->is_detect_fs_fe = false; + } else { + csi2->is_detect_fs_fe = true; + } + } else { + csi2->is_detect_fs_fe = true; + } if (host_type == RK_DSI_RXHOST) { val |= SW_DSI_EN(1) | SW_DATATYPE_FS(0x01) | SW_DATATYPE_FE(0x11) | SW_DATATYPE_LS(0x21) | @@ -208,7 +230,7 @@ static void csi2_enable(struct csi2_hw *csi2_hw, SW_DATATYPE_FE(0x01) | SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03); write_csihost_reg(base, CSIHOST_CONTROL, val); - write_csihost_reg(base, CSIHOST_MSK1, 0x0); + write_csihost_reg(base, CSIHOST_MSK1, mask1); write_csihost_reg(base, CSIHOST_MSK2, 0xf000); csi2->is_check_sot_sync = true; } @@ -578,6 +600,28 @@ static int rkcif_csi2_s_power(struct v4l2_subdev *sd, int on) return 0; } +static void csi2_quick_stream_on(struct csi2_dev *csi2) +{ + int csi_idx = 0; + int i = 0; + + for (i = 0; i < csi2->csi_info.csi_num; i++) { + csi_idx = csi2->csi_info.csi_idx[i]; + write_csihost_reg(csi2->csi2_hw[csi_idx]->base, CSIHOST_RESETN, 1); + } +} + +static void csi2_quick_stream_off(struct csi2_dev *csi2) +{ + int csi_idx = 0; + int i = 0; + + for (i = 0; i < csi2->csi_info.csi_num; i++) { + csi_idx = csi2->csi_info.csi_idx[i]; + write_csihost_reg(csi2->csi2_hw[csi_idx]->base, CSIHOST_RESETN, 0); + } +} + static long rkcif_csi2_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct csi2_dev *csi2 = sd_to_dev(sd); @@ -598,6 +642,12 @@ static long rkcif_csi2_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg case RKCIF_CMD_SET_PPI_DATA_DEBUG: csi2->sw_dbg = *((u32 *)arg); break; + case RKMODULE_SET_QUICK_STREAM: + if (*(int *)arg) + csi2_quick_stream_on(csi2); + else + csi2_quick_stream_off(csi2); + break; default: ret = -ENOIOCTLCMD; break; @@ -808,7 +858,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) } } - if (val & CSIHOST_ERR1_ERR_BNDRY_MATCH) { + if (val & CSIHOST_ERR1_ERR_BNDRY_MATCH && csi2->is_detect_fs_fe) { err_list = &csi2->err_list[RK_CSI2_ERR_FS_FE_MIS]; err_list->cnt++; csi2_find_err_vc((val >> 4) & 0xf, vc_info); @@ -858,7 +908,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) csi2_err_strncat(err_str, cur_str); } - pr_err("%s ERR1:0x%x %s\n", csi2_hw->dev_name, val, err_str); + pr_err("(0x%x)MIPI_CSI2 ERR1:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str); if (is_add_cnt) { csi2->err_list[RK_CSI2_ERR_ALL].cnt++; @@ -916,7 +966,7 @@ static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx) csi2_err_strncat(err_str, cur_str); } - pr_err("%s ERR2:0x%x %s\n", csi2_hw->dev_name, val, err_str); + pr_err("(0x%x)MIPI_CSI2 ERR2:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str); } return IRQ_HANDLED; @@ -1044,6 +1094,12 @@ static const struct csi2_match_data rk3576_csi2_match_data = { .num_hw = 5, }; +static const struct csi2_match_data rv1103b_csi2_match_data = { + .chip_id = CHIP_RV1103B_CSI2, + .num_pads = CSI2_NUM_PADS_MAX, + .num_hw = 2, +}; + static const struct of_device_id csi2_dt_ids[] = { { .compatible = "rockchip,rk1808-mipi-csi2", @@ -1077,6 +1133,10 @@ static const struct of_device_id csi2_dt_ids[] = { .compatible = "rockchip,rk3576-mipi-csi2", .data = &rk3576_csi2_match_data, }, + { + .compatible = "rockchip,rv1103b-mipi-csi2", + .data = &rv1103b_csi2_match_data, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, csi2_dt_ids); @@ -1234,6 +1294,10 @@ static const struct csi2_hw_match_data rk3576_csi2_hw_match_data = { .chip_id = CHIP_RK3576_CSI2, }; +static const struct csi2_hw_match_data rv1103b_csi2_hw_match_data = { + .chip_id = CHIP_RV1103B_CSI2, +}; + static const struct of_device_id csi2_hw_ids[] = { { .compatible = "rockchip,rk1808-mipi-csi2-hw", @@ -1267,6 +1331,10 @@ static const struct of_device_id csi2_hw_ids[] = { .compatible = "rockchip,rk3576-mipi-csi2-hw", .data = &rk3576_csi2_hw_match_data, }, + { + .compatible = "rockchip,rv1103b-mipi-csi2-hw", + .data = &rv1103b_csi2_hw_match_data, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, csi2_hw_ids); @@ -1311,6 +1379,7 @@ static int csi2_hw_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); csi2_hw->base = devm_ioremap_resource(&pdev->dev, res); + csi2_hw->res = res; if (IS_ERR(csi2_hw->base)) { resource_size_t offset = res->start; resource_size_t size = resource_size(res); diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.h b/drivers/media/platform/rockchip/cif/mipi-csi2.h index 5997abe3cfe6..1fbcc88fcbbc 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.h +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.h @@ -95,6 +95,7 @@ enum rkcsi2_chip_id { CHIP_RV1106_CSI2, CHIP_RK3562_CSI2, CHIP_RK3576_CSI2, + CHIP_RV1103B_CSI2, }; enum csi2_pads { @@ -161,6 +162,7 @@ struct csi2_dev { struct v4l2_subdev *src_sd; bool sink_linked[CSI2_NUM_SRC_PADS]; bool is_check_sot_sync; + bool is_detect_fs_fe; struct csi2_sensor_info sensors[MAX_CSI2_SENSORS]; const struct csi2_match_data *match_data; int num_sensors; @@ -184,6 +186,7 @@ struct csi2_hw { const struct csi2_hw_match_data *match_data; void __iomem *base; + struct resource *res; /* lock to protect all members below */ struct mutex lock; diff --git a/drivers/media/platform/rockchip/cif/procfs.c b/drivers/media/platform/rockchip/cif/procfs.c index ef229fa2a3a4..a8022ff7b9cf 100644 --- a/drivers/media/platform/rockchip/cif/procfs.c +++ b/drivers/media/platform/rockchip/cif/procfs.c @@ -7,9 +7,13 @@ #include #include #include +#include #include "dev.h" #include "procfs.h" +#include "mipi-csi2.h" +#include "../../../../phy/rockchip/phy-rockchip-csi2-dphy-common.h" +#include "../../../../phy/rockchip/phy-rockchip-samsung-dcphy.h" #ifdef CONFIG_PROC_FS @@ -211,6 +215,24 @@ static const char *rkcif_get_monitor_mode(enum rkcif_monitor_mode monitor_mode) } } +static const char *rkcif_get_sync_mode(enum rkmodule_sync_mode sync_mode) +{ + switch (sync_mode) { + case NO_SYNC_MODE: + return "no sync"; + case EXTERNAL_MASTER_MODE: + return "external master"; + case INTERNAL_MASTER_MODE: + return "internal master"; + case SLAVE_MODE: + return "slave"; + case SOFT_SYNC_MODE: + return "soft sync"; + default: + return "unknown"; + } +} + static void rkcif_show_mixed_info(struct rkcif_device *dev, struct seq_file *f) { enum rkcif_monitor_mode monitor_mode; @@ -240,13 +262,267 @@ static void rkcif_show_clks(struct rkcif_device *dev, struct seq_file *f) } } +static void rkcif_show_toisp_info(struct rkcif_device *dev, struct seq_file *f) +{ + struct sditf_priv *priv = dev->sditf[0]; + char name_strings[32] = {0}; + + seq_puts(f, "\nToisp Info:\n"); + seq_printf(f, "\tisp_name: %s\n", priv->mode.name); + switch (priv->mode.rdbk_mode) { + case RKISP_VICAP_ONLINE: + sprintf(name_strings, "%s", "online"); + break; + case RKISP_VICAP_ONLINE_ONE_FRAME: + sprintf(name_strings, "%s", "online_one_frame"); + break; + case RKISP_VICAP_ONLINE_MULTI: + sprintf(name_strings, "%s", "online_multi"); + break; + case RKISP_VICAP_ONLINE_UNITE: + sprintf(name_strings, "%s", "online_unite"); + break; + case RKISP_VICAP_RDBK_AIQ: + sprintf(name_strings, "%s", "rdbk_aiq"); + break; + case RKISP_VICAP_RDBK_AUTO: + sprintf(name_strings, "%s", "rdbk_auto"); + break; + case RKISP_VICAP_RDBK_AUTO_ONE_FRAME: + sprintf(name_strings, "%s", "rdbk_one_frame"); + break; + default: + sprintf(name_strings, "%s", "error"); + break; + } + seq_printf(f, "\trdbk_mode: %s\n", name_strings); + if (priv->mode.rdbk_mode > RKISP_VICAP_RDBK_AIQ) + seq_printf(f, "\treserved buf: %d\n", priv->cif_dev->fb_res_bufs); + if (priv->hdr_wrap_line) + seq_printf(f, "\twrap line: %d\n", priv->hdr_wrap_line); + if (priv->is_combine_mode) + seq_printf(f, "\tcombine num: %d\n", dev->sditf_cnt); +} + +static int rkcif_get_csi_offset(struct rkcif_device *dev, int csi_host_idx) +{ + int csi_offset = 0; + + if (dev->chip_id == CHIP_RK3588_CIF) { + csi_offset = csi_host_idx * 0x100; + } else if (dev->chip_id == CHIP_RV1106_CIF || + dev->chip_id == CHIP_RV1103B_CIF) { + csi_offset = csi_host_idx * 0x200; + } else if (dev->chip_id == CHIP_RK3562_CIF) { + if (csi_host_idx < 3) + csi_offset = csi_host_idx * 0x200; + else + csi_offset = 0x500; + } else if (dev->chip_id == CHIP_RK3576_CIF) { + if (csi_host_idx < 2) + csi_offset = csi_host_idx * 0x200; + else + csi_offset = 0x100 + csi_host_idx * 0x100; + } + csi_offset += 0x100; + return csi_offset; +} + +static void rkcif_show_reg_vicap(struct rkcif_device *dev, struct seq_file *f) +{ + void *buf = dev->sw_reg; + struct sditf_priv *priv = dev->sditf[0]; + u32 *reg = NULL; + int i, j; + int csi_offset = 0; + + seq_puts(f, "\nVicap reg:\n"); + memcpy_fromio(buf, dev->hw_dev->base_addr, RKCIF_REG_MAX); + if (dev->reg_dbg == RKCIF_REG_DBG_PART) { + if (dev->inf_id == RKCIF_MIPI_LVDS) { + for (j = 0; j < dev->csi_info.csi_num; j++) { + seq_printf(f, "\nmipi%d reg:\n", dev->csi_info.csi_idx[j]); + csi_offset = rkcif_get_csi_offset(dev, dev->csi_info.csi_idx[j]); + reg = buf + csi_offset; + for (i = 0; i < 0x100 / 16; i++) + seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + (u32)(dev->hw_dev->res->start + csi_offset + i * 16), + *(reg + i * 4), *(reg + i * 4 + 1), + *(reg + i * 4 + 2), *(reg + i * 4 + 3)); + } + } else { + reg = buf; + for (i = 0; i < 0x100 / 16; i++) + seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + (u32)(dev->hw_dev->res->start + i * 16), + *(reg + i * 4), *(reg + i * 4 + 1), + *(reg + i * 4 + 2), *(reg + i * 4 + 3)); + } + if (priv && priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { + seq_puts(f, "\ntoisp reg:\n"); + reg = buf + 0x780; + for (i = 0; i < 0x30 / 16; i++) + seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + (u32)(dev->hw_dev->res->start + 0x780 + i * 16), + *(reg + i * 4), *(reg + i * 4 + 1), + *(reg + i * 4 + 2), *(reg + i * 4 + 3)); + reg = buf; + seq_puts(f, "\nglobal reg:\n"); + for (i = 0; i < 0x10 / 16; i++) + seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + (u32)(dev->hw_dev->res->start + i * 16), + *(reg + i * 4), *(reg + i * 4 + 1), + *(reg + i * 4 + 2), *(reg + i * 4 + 3)); + } + } else { + reg = buf; + for (i = 0; i < RKCIF_REG_MAX / 16; i++) + seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + (u32)(dev->hw_dev->res->start + i * 16), + *(reg + i * 4), *(reg + i * 4 + 1), + *(reg + i * 4 + 2), *(reg + i * 4 + 3)); + } +} + +static void rkcif_show_reg_csi2(struct rkcif_device *dev, struct seq_file *f) +{ + struct csi2_dev *csi2 = container_of(dev->active_sensor->sd, struct csi2_dev, sd); + struct csi2_hw *csi2_hw = NULL; + int i, j; + int csi_idx = 0; + u32 buf[20]; + + for (j = 0; j < csi2->csi_info.csi_num; j++) { + csi_idx = csi2->csi_info.csi_idx[j]; + csi2_hw = csi2->csi2_hw[csi_idx]; + seq_printf(f, "\nmipi%d csi2 reg:\n", csi_idx); + memcpy_fromio(buf, csi2_hw->base, 0x50); + for (i = 0; i < 0x50 / 16; i++) + seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + (u32)(csi2_hw->res->start + i * 16), + *(buf + i * 4), *(buf + i * 4 + 1), + *(buf + i * 4 + 2), *(buf + i * 4 + 3)); + } +} + +static void rkcif_show_reg_dcphy(struct samsung_mipi_dcphy *dcphy, int index, struct seq_file *f) +{ + u32 bias_reg[4]; + char *dcphy_reg = NULL; + u32 *buf = NULL; + int i = 0; + + seq_printf(f, "\ndcphy%d reg:\n", index); + regmap_bulk_read(dcphy->regmap, 0, bias_reg, 4); + seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + (u32)dcphy->res->start, + bias_reg[0], bias_reg[1], + bias_reg[2], bias_reg[3]); + + dcphy_reg = kzalloc(0x500, GFP_KERNEL); + if (!dcphy_reg) + return; + regmap_bulk_read(dcphy->regmap, 0xb00, dcphy_reg, 0x500 / 4); + buf = (u32 *)dcphy_reg; + for (i = 0; i < 0x500 / 16; i++) + seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + (u32)(dcphy->res->start + 0xb00 + i * 16), + *(buf + i * 4), *(buf + i * 4 + 1), + *(buf + i * 4 + 2), *(buf + i * 4 + 3)); + kfree(dcphy_reg); +} + +static void rkcif_show_reg_dphy(struct csi2_dphy_hw *dphy_hw, int index, struct seq_file *f) +{ + char *dphy_reg = NULL; + u32 *buf = NULL; + int i = 0; + + seq_printf(f, "\ndphy%d reg:\n", index); + dphy_reg = kzalloc(0x900, GFP_KERNEL); + if (!dphy_reg) + return; + memcpy_fromio(dphy_reg, dphy_hw->hw_base_addr, 0x900); + buf = (u32 *)dphy_reg; + for (i = 0; i < 0x900 / 16; i++) + seq_printf(f, "0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + (u32)(dphy_hw->res->start + i * 16), + *(buf + i * 4), *(buf + i * 4 + 1), + *(buf + i * 4 + 2), *(buf + i * 4 + 3)); + kfree(dphy_reg); +} + +static void rkcif_show_reg_dphys(struct rkcif_device *dev, struct seq_file *f) +{ + struct csi2_dphy *dphy = NULL; + struct csi2_dphy_hw *dphy_hw = NULL; + struct samsung_mipi_dcphy *dcphy_hw = NULL; + struct rkcif_pipeline *p = NULL; + struct v4l2_subdev *sd = NULL; + int j; + int csi_idx = 0; + + p = &dev->pipe; + for (j = 0; j < p->num_subdevs; j++) { + if (p->subdevs[j] != dev->terminal_sensor.sd && + p->subdevs[j] != dev->active_sensor->sd) { + sd = p->subdevs[j]; + break; + } + } + if (!sd) + return; + dphy = container_of(sd, struct csi2_dphy, sd); + + for (j = 0; j < dev->csi_info.csi_num; j++) { + csi_idx = dev->csi_info.csi_idx[j]; + if (dphy->drv_data->chip_id == CHIP_ID_RK3568 || + dphy->drv_data->chip_id == CHIP_ID_RV1106) { + dphy_hw = dphy->dphy_hw_group[0]; + if (dphy_hw) + rkcif_show_reg_dphy(dphy_hw, 0, f); + } else if (dphy->drv_data->chip_id == CHIP_ID_RK3588) { + if (csi_idx < 2) { + dcphy_hw = dphy->samsung_phy_group[csi_idx]; + if (dcphy_hw) + rkcif_show_reg_dcphy(dcphy_hw, csi_idx, f); + } else { + dphy_hw = dphy->dphy_hw_group[(csi_idx - 2) / 2]; + if (dphy_hw) + rkcif_show_reg_dphy(dphy_hw, (csi_idx - 2) / 2, f); + } + } else { + dphy_hw = dphy->dphy_hw_group[csi_idx / 2]; + if (dphy_hw) + rkcif_show_reg_dphy(dphy_hw, csi_idx / 2, f); + } + } +} + +static void rkcif_show_reg_dbg(struct rkcif_device *dev, struct seq_file *f) +{ + int i; + + rkcif_show_reg_vicap(dev, f); + if (dev->inf_id == RKCIF_MIPI_LVDS) { + if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || + dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) { + for (i = 0; i < 5; i++) { + rkcif_show_reg_csi2(dev, f); + usleep_range(2000, 4000); + } + } + rkcif_show_reg_dphys(dev, f); + } +} + static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) { struct rkcif_stream *stream = &dev->stream[0]; struct rkcif_pipeline *pipe = &dev->pipe; struct rkcif_sensor_info *sensor = &dev->terminal_sensor; struct v4l2_rect *rect = &sensor->raw_rect; - struct v4l2_subdev_frame_interval *interval = &sensor->fi; + struct v4l2_subdev_frame_interval *interval = &sensor->src_fi; struct v4l2_subdev_selection *sel = &sensor->selection; u32 mbus_flags; u64 fps, timestamp0, timestamp1; @@ -371,9 +647,22 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) dev->stream[1].total_buf_num, dev->stream[2].total_buf_num, dev->stream[3].total_buf_num); + if (dev->sditf[0]) + rkcif_show_toisp_info(dev, f); + if (dev->reg_dbg) + rkcif_show_reg_dbg(dev, f); } } +static void rkcif_show_group_info(struct rkcif_device *dev, struct seq_file *f) +{ + seq_puts(f, "\nGroup Info:\n"); + seq_printf(f, "\tSync Mode:%s\n", + rkcif_get_sync_mode(dev->sync_cfg.type)); + if (dev->sync_cfg.type != NO_SYNC_MODE) + seq_printf(f, "\tGroup Id:%d\n", dev->sync_cfg.group); +} + static int rkcif_proc_show(struct seq_file *f, void *v) { struct rkcif_device *dev = f->private; @@ -382,6 +671,7 @@ static int rkcif_proc_show(struct seq_file *f, void *v) rkcif_show_mixed_info(dev, f); rkcif_show_clks(dev, f); rkcif_show_format(dev, f); + rkcif_show_group_info(dev, f); } else { seq_puts(f, "dev null\n"); } diff --git a/drivers/media/platform/rockchip/cif/regs.h b/drivers/media/platform/rockchip/cif/regs.h index d35ea807d5c7..15e77b4c04ad 100644 --- a/drivers/media/platform/rockchip/cif/regs.h +++ b/drivers/media/platform/rockchip/cif/regs.h @@ -199,6 +199,18 @@ enum cif_reg_index { CIF_REG_TOISP1_CTRL, CIF_REG_TOISP1_SIZE, CIF_REG_TOISP1_CROP, + CIF_REG_TOISP0_CH1_CTRL, + CIF_REG_TOISP0_CH1_SIZE, + CIF_REG_TOISP0_CH1_CROP, + CIF_REG_TOISP1_CH1_CTRL, + CIF_REG_TOISP1_CH1_SIZE, + CIF_REG_TOISP1_CH1_CROP, + CIF_REG_TOISP0_CH2_CTRL, + CIF_REG_TOISP0_CH2_SIZE, + CIF_REG_TOISP0_CH2_CROP, + CIF_REG_TOISP1_CH2_CTRL, + CIF_REG_TOISP1_CH2_SIZE, + CIF_REG_TOISP1_CH2_CROP, CIF_REG_INDEX_MAX }; @@ -506,6 +518,9 @@ enum cif_reg_index { #define TOISP1_CH_CTRL 0x78C #define TOISP1_CROP_SIZE 0x790 #define TOISP1_CROP 0x794 +#define TOISP0_CH1_CTRL 0x7A0 +#define TOISP0_CH1_CROP_SIZE 0x7A4 +#define TOISP0_CH1_CROP 0x7A8 /* The key register bit description */ @@ -527,6 +542,7 @@ enum cif_reg_index { #define DVP_SW_WATER_LINE_50_RK3576 (0x1 << 20) #define DVP_SW_WATER_LINE_25_RK3576 (0x2 << 20) #define DVP_SW_WATER_LINE_00_RK3576 (0x3 << 20) +#define DVP_SW_DMA_IDLE (0x1 << 4) /* CIF_INTEN */ #define INTEN_DISABLE (0x0 << 0) @@ -1149,4 +1165,10 @@ enum cif_reg_index { #define GLB_RESET_IDI_EN_RK3576 (BIT(30)) #define SW_DPHY1_SPLIT_EN_RK3576 (BIT(25)) #define SW_DPHY2_SPLIT_EN_RK3576 (BIT(26)) +#define SW_DPHY_SPLIT_EN_RV1103B (BIT(24)) + +/*mask for rv1103b*/ +#define ROUNDING_2BIT_RV1103B (1 << 18) +#define ROUNDING_4BIT_RV1103B (2 << 18) + #endif diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 0be6c7cef65a..0620e60c0784 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -296,6 +296,8 @@ static int sditf_init_buf(struct sditf_priv *priv) ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num); } else { ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num); + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) + ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num); } } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { @@ -311,13 +313,17 @@ static int sditf_init_buf(struct sditf_priv *priv) } else { ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num); ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num); + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) + ret |= rkcif_init_rx_buf(&cif_dev->stream[2], priv->buf_num); } } else { - if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) + if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO || + priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num); else ret = -EINVAL; } + priv->is_buf_init = true; return ret; } @@ -341,6 +347,7 @@ static void sditf_free_buf(struct sditf_priv *priv) cif_dev->wait_line_bak = 0; cif_dev->is_thunderboot = false; } + priv->is_buf_init = false; } static int sditf_get_selection(struct v4l2_subdev *sd, @@ -370,7 +377,7 @@ static void sditf_reinit_mode(struct sditf_priv *priv, struct rkisp_vicap_mode * __func__, mode->rdbk_mode, mode->name, priv->toisp_inf.link_mode); } -static void sditf_channel_disable(struct sditf_priv *priv, int user); +static void sditf_enable_immediately(struct sditf_priv *priv); static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct sditf_priv *priv = to_sditf_priv(sd); @@ -383,14 +390,27 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) struct sditf_time *time; struct sditf_gain *gain; struct sditf_effect_exp *effect_exp; - int *pbuf_num = NULL; + struct rkisp_init_buf *pisp_buf_info = NULL; int ret = 0; int *on = NULL; int *connect_id = NULL; + int sync_type = NO_SYNC_MODE; switch (cmd) { case RKISP_VICAP_CMD_MODE: mode = (struct rkisp_vicap_mode *)arg; + if (mode->rdbk_mode == RKISP_VICAP_ONLINE_UNITE && + priv->cif_dev->chip_id < CHIP_RV1103B_CIF) + return -EINVAL; + memcpy(&priv->mode_src, mode, sizeof(*mode)); + if (cif_dev->is_thunderboot && + cif_dev->is_thunderboot_start) { + if (mode->rdbk_mode < RKISP_VICAP_RDBK_AIQ) + cif_dev->is_rdbk_to_online = true; + else + cif_dev->is_rdbk_to_online = false; + return 0; + } mutex_lock(&cif_dev->stream_lock); memcpy(&priv->mode, mode, sizeof(*mode)); mutex_unlock(&cif_dev->stream_lock); @@ -400,12 +420,31 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) else mode->input.merge_num = 1; mode->input.index = priv->combine_index; + + ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd, + core, ioctl, + RKMODULE_GET_SYNC_MODE, + &sync_type); + if (ret || sync_type == NO_SYNC_MODE) + mode->input.multi_sync = 0; + else + mode->input.multi_sync = 1; return 0; case RKISP_VICAP_CMD_INIT_BUF: - pbuf_num = (int *)arg; - priv->buf_num = *pbuf_num; + pisp_buf_info = (struct rkisp_init_buf *)arg; + priv->buf_num = pisp_buf_info->buf_cnt; + priv->cif_dev->fb_res_bufs = pisp_buf_info->buf_cnt; sditf_get_set_fmt(&priv->sd, NULL, &fmt); - ret = sditf_init_buf(priv); + if (pisp_buf_info->hdr_wrap_line <= priv->cap_info.height) { + priv->hdr_wrap_line = pisp_buf_info->hdr_wrap_line; + v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "hdr_wrap_line %d\n", + priv->hdr_wrap_line); + } else { + dev_info(priv->dev, "set hdr_wap_line failed, val %d, max %d\n", + pisp_buf_info->hdr_wrap_line, priv->cap_info.height); + } + if (!priv->is_buf_init) + ret = sditf_init_buf(priv); return ret; case RKMODULE_GET_HDR_CFG: if (!cif_dev->terminal_sensor.sd) @@ -421,20 +460,13 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) if (*on) { rkcif_stream_resume(cif_dev, RKCIF_RESUME_ISP); } else { - if (priv->toisp_inf.link_mode == TOISP0) { - sditf_channel_disable(priv, 0); - } else if (priv->toisp_inf.link_mode == TOISP1) { - sditf_channel_disable(priv, 1); - } else if (priv->toisp_inf.link_mode == TOISP_UNITE) { - sditf_channel_disable(priv, 0); - if (cif_dev->chip_id == CHIP_RK3588_CIF) - sditf_channel_disable(priv, 1); - } rkcif_stream_suspend(cif_dev, RKCIF_RESUME_ISP); + if (cif_dev->chip_id == CHIP_RV1106_CIF) + sditf_disable_immediately(priv); } break; case RKISP_VICAP_CMD_SET_RESET: - if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) { + if (priv->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) { cif_dev->is_toisp_reset = true; return 0; } @@ -486,6 +518,15 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) connect_id = (int *)arg; *connect_id = priv->connect_id; return ret; + case RKISP_VICAP_CMD_HW_LINK: + on = (int *)arg; + if (*on) { + sditf_enable_immediately(priv); + } else { + if (priv->mode.rdbk_mode != RKISP_VICAP_ONLINE_MULTI) + sditf_disable_immediately(priv); + } + return 0; default: break; } @@ -586,6 +627,11 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd, case RKISP_VICAP_CMD_SET_RESET: ret = sditf_ioctl(sd, cmd, NULL); return ret; + case RKISP_VICAP_CMD_HW_LINK: + if (copy_from_user(&on, up, sizeof(int))) + return -EFAULT; + ret = sditf_ioctl(sd, cmd, &on); + return ret; default: break; } @@ -602,6 +648,141 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd, } #endif +static int sditf_channel_enable_rv1103b(struct sditf_priv *priv, int user) +{ + struct rkcif_device *cif_dev = priv->cif_dev; + struct rkmodule_capture_info *capture_info = &cif_dev->channels[0].capture_info; + unsigned int ch0 = 0, ch1 = 0, ch2 = 0; + unsigned int ctrl_ch0 = 0; + unsigned int ctrl_ch1 = 0; + unsigned int ctrl_ch2 = 0; + unsigned int int_en = 0; + unsigned int offset_x = 0; + unsigned int offset_y = 0; + unsigned int width = priv->cap_info.width; + unsigned int height = priv->cap_info.height; + int csi_idx = cif_dev->csi_host_idx; + unsigned int read_ctrl_ch0 = 0; + unsigned int read_ctrl_ch1 = 0; + unsigned int read_ctrl_ch2 = 0; + + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE && + priv->toisp_inf.link_mode == TOISP_UNITE) { + if (capture_info->multi_dev.dev_num != 2 || + capture_info->multi_dev.pixel_offset != RKMOUDLE_UNITE_EXTEND_PIXEL) { + v4l2_err(&cif_dev->v4l2_dev, + "param error of online mode, combine dev num %d, offset %d\n", + capture_info->multi_dev.dev_num, + capture_info->multi_dev.pixel_offset); + return -EINVAL; + } + csi_idx = capture_info->multi_dev.dev_idx[user]; + } + + if (priv->hdr_cfg.hdr_mode == NO_HDR || + priv->hdr_cfg.hdr_mode == HDR_COMPR) { + if (cif_dev->inf_id == RKCIF_MIPI_LVDS) + ch0 = csi_idx * 4; + else + ch0 = 24;//dvp + ctrl_ch0 = (ch0 << 3) | 0x1; + if (user == 0) + int_en = CIF_TOISP0_FS_RK3576(0) | CIF_TOISP0_FE_RK3576(0); + priv->toisp_inf.ch_info[0].is_valid = true; + priv->toisp_inf.ch_info[0].id = ch0; + } else if (priv->hdr_cfg.hdr_mode == HDR_X2) { + ch0 = cif_dev->csi_host_idx * 4 + 1; + ch1 = cif_dev->csi_host_idx * 4; + ctrl_ch0 = (ch0 << 3) | 0x1; + ctrl_ch1 = (ch1 << 3) | 0x1; + if (cif_dev->chip_id < CHIP_RK3576_CIF) { + if (user == 0) + int_en = CIF_TOISP0_FS(0) | CIF_TOISP0_FS(1) | + CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1); + else + int_en = CIF_TOISP1_FS(0) | CIF_TOISP1_FS(1) | + CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1); + } else { + if (user == 0) + int_en = CIF_TOISP0_FS_RK3576(0) | CIF_TOISP0_FS_RK3576(1) | + CIF_TOISP0_FE_RK3576(0) | CIF_TOISP0_FE_RK3576(1); + } + priv->toisp_inf.ch_info[0].is_valid = true; + priv->toisp_inf.ch_info[0].id = ch0; + priv->toisp_inf.ch_info[1].is_valid = true; + priv->toisp_inf.ch_info[1].id = ch1; + } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { + ch0 = cif_dev->csi_host_idx * 4 + 2; + ch1 = cif_dev->csi_host_idx * 4 + 1; + ch2 = cif_dev->csi_host_idx * 4; + ctrl_ch0 = (ch0 << 3) | 0x1; + ctrl_ch1 = (ch1 << 3) | 0x1; + ctrl_ch2 = (ch2 << 3) | 0x1; + + if (user == 0) + int_en = CIF_TOISP0_FS_RK3576(0) | CIF_TOISP0_FS_RK3576(1) | + CIF_TOISP0_FS_RK3576(2) | CIF_TOISP0_FE_RK3576(0) | + CIF_TOISP0_FE_RK3576(1) | CIF_TOISP0_FE_RK3576(2); + + priv->toisp_inf.ch_info[0].is_valid = true; + priv->toisp_inf.ch_info[0].id = ch0; + priv->toisp_inf.ch_info[1].is_valid = true; + priv->toisp_inf.ch_info[1].id = ch1; + priv->toisp_inf.ch_info[2].is_valid = true; + priv->toisp_inf.ch_info[2].id = ch2; + } + + if (!width || !height) + return -EINVAL; + + rkcif_write_register_or(cif_dev, CIF_REG_GLB_INTEN, int_en); + + if (user == 0) { + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) { + width /= 2; + width += RKMOUDLE_UNITE_EXTEND_PIXEL; + } else if (priv->toisp_inf.link_mode == TOISP_UNITE) { + width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + } + rkcif_write_register(cif_dev, CIF_REG_TOISP0_CTRL, ctrl_ch0); + rkcif_write_register(cif_dev, CIF_REG_TOISP0_CROP, + offset_x | (offset_y << 16)); + rkcif_write_register(cif_dev, CIF_REG_TOISP0_SIZE, + width | (height << 16)); + if (priv->hdr_cfg.hdr_mode != NO_HDR && + priv->hdr_cfg.hdr_mode != HDR_COMPR) { + rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH1_CTRL, ctrl_ch1); + rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH1_CROP, + offset_x | (offset_y << 16)); + rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH1_SIZE, + width | (height << 16)); + } + if (priv->hdr_cfg.hdr_mode == HDR_X3) { + rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH2_CTRL, ctrl_ch2); + rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH2_CROP, + offset_x | (offset_y << 16)); + rkcif_write_register(cif_dev, CIF_REG_TOISP0_CH2_SIZE, + width | (height << 16)); + } + } + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_MULTI) + rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, CSI_ENABLE_CAPTURE); + read_ctrl_ch0 = rkcif_read_register(cif_dev, CIF_REG_TOISP0_CTRL); + v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "isp%d, toisp ch0 %d, width %d, height %d, reg w:0x%x r:0x%x\n", + user, ch0, width, height, ctrl_ch0, read_ctrl_ch0); + if (priv->hdr_cfg.hdr_mode != NO_HDR) { + read_ctrl_ch1 = rkcif_read_register(cif_dev, CIF_REG_TOISP0_CH1_CTRL); + v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "isp%d, toisp ch1 %d, width %d, height %d, reg w:0x%x r:0x%x\n", + user, ch1, width, height, ctrl_ch1, read_ctrl_ch1); + } + if (priv->hdr_cfg.hdr_mode == HDR_X3) { + read_ctrl_ch2 = rkcif_read_register(cif_dev, CIF_REG_TOISP0_CH2_CTRL); + v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "isp%d, toisp ch2 %d, width %d, height %d, reg w:0x%x r:0x%x\n", + user, ch2, width, height, ctrl_ch2, read_ctrl_ch2); + } + return 0; +} + static int sditf_channel_enable(struct sditf_priv *priv, int user) { struct rkcif_device *cif_dev = priv->cif_dev; @@ -665,7 +846,6 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) } priv->toisp_inf.ch_info[0].is_valid = true; priv->toisp_inf.ch_info[0].id = ch0; - priv->toisp_inf.ch_info[1].is_valid = true; priv->toisp_inf.ch_info[1].id = ch1; } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { ch0 = cif_dev->csi_host_idx * 4 + 2; @@ -689,9 +869,7 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) } priv->toisp_inf.ch_info[0].is_valid = true; priv->toisp_inf.ch_info[0].id = ch0; - priv->toisp_inf.ch_info[1].is_valid = true; priv->toisp_inf.ch_info[1].id = ch1; - priv->toisp_inf.ch_info[2].is_valid = true; priv->toisp_inf.ch_info[2].id = ch2; } if (cif_dev->chip_id > CHIP_RK3562_CIF) @@ -726,6 +904,8 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) return -EINVAL; } } + v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "isp%d, toisp ch0 %d, width %d, height %d, reg 0x%x\n", + user, ch0, width, height, ctrl_val); #if IS_ENABLED(CONFIG_CPU_RV1106) rv1106_sdmmc_get_lock(); #endif @@ -739,104 +919,118 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) static void sditf_channel_disable(struct sditf_priv *priv, int user) { struct rkcif_device *cif_dev = priv->cif_dev; - unsigned int ctrl_val = 0; + u32 ctrl_val = 0x10101; - if (priv->hdr_cfg.hdr_mode == NO_HDR || - priv->hdr_cfg.hdr_mode == HDR_COMPR) { - if (user == 0) - ctrl_val = CIF_TOISP0_FE(0); - else - ctrl_val = CIF_TOISP1_FE(0); - } else if (priv->hdr_cfg.hdr_mode == HDR_X2) { - if (user == 0) - ctrl_val = CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1); - else - ctrl_val = CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1); - } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { - if (user == 0) - ctrl_val = CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1) | CIF_TOISP0_FE(2); - else - ctrl_val = CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1) | CIF_TOISP1_FE(2); - } -#if IS_ENABLED(CONFIG_CPU_RV1106) - rv1106_sdmmc_get_lock(); -#endif - rkcif_write_register_or(cif_dev, CIF_REG_GLB_INTEN, ctrl_val); -#if IS_ENABLED(CONFIG_CPU_RV1106) - rv1106_sdmmc_put_lock(); -#endif - priv->toisp_inf.ch_info[0].is_valid = false; - priv->toisp_inf.ch_info[1].is_valid = false; - priv->toisp_inf.ch_info[2].is_valid = false; + if (user == 0) + rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val); + else + rkcif_write_register_and(cif_dev, CIF_REG_TOISP1_CTRL, ~ctrl_val); +} + +static void sditf_channel_disable_rv1103b(struct sditf_priv *priv, int user) +{ + struct rkcif_device *cif_dev = priv->cif_dev; + u32 ctrl_val = 0x1; + u32 read_ctrl_ch0 = 0; + + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_MULTI) + rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL, ~CSI_ENABLE_CAPTURE); + + rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val); + read_ctrl_ch0 = rkcif_read_register(cif_dev, CIF_REG_TOISP0_CTRL); + v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "isp%d, toisp disable reg w_and:0x%x r:0x%x\n", + user, ~ctrl_val, read_ctrl_ch0); + if (priv->hdr_cfg.hdr_mode != NO_HDR) + rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CH1_CTRL, ~ctrl_val); + if (priv->hdr_cfg.hdr_mode == HDR_X3) + rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CH2_CTRL, ~ctrl_val); } void sditf_change_to_online(struct sditf_priv *priv) { struct rkcif_device *cif_dev = priv->cif_dev; + struct rkcif_stream *cur_stream = NULL; - priv->mode.rdbk_mode = RKISP_VICAP_ONLINE; - if (priv->toisp_inf.link_mode == TOISP0) { - sditf_channel_enable(priv, 0); - } else if (priv->toisp_inf.link_mode == TOISP1) { - sditf_channel_enable(priv, 1); - } else if (priv->toisp_inf.link_mode == TOISP_UNITE) { - sditf_channel_enable(priv, 0); - if (cif_dev->chip_id == CHIP_RK3588_CIF) - sditf_channel_enable(priv, 1); - } + priv->mode = priv->mode_src; + if (priv->mode.rdbk_mode != RKISP_VICAP_ONLINE_UNITE && + priv->mode.rdbk_mode != RKISP_VICAP_ONLINE_MULTI) + sditf_enable_immediately(priv); if (cif_dev->is_thunderboot) { if (priv->hdr_cfg.hdr_mode == NO_HDR) { - rkcif_free_rx_buf(&cif_dev->stream[0], cif_dev->stream[0].rx_buf_num); + cur_stream = &cif_dev->stream[0]; cif_dev->stream[0].is_line_wake_up = false; } else if (priv->hdr_cfg.hdr_mode == HDR_X2) { - rkcif_free_rx_buf(&cif_dev->stream[1], cif_dev->stream[1].rx_buf_num); + cur_stream = &cif_dev->stream[1]; cif_dev->stream[0].is_line_wake_up = false; cif_dev->stream[1].is_line_wake_up = false; } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { - rkcif_free_rx_buf(&cif_dev->stream[2], cif_dev->stream[2].rx_buf_num); + cur_stream = &cif_dev->stream[2]; cif_dev->stream[0].is_line_wake_up = false; cif_dev->stream[1].is_line_wake_up = false; cif_dev->stream[2].is_line_wake_up = false; } + + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) + cur_stream->is_m_online_fb_res = true; + rkcif_free_rx_buf(cur_stream, cur_stream->rx_buf_num); + cif_dev->wait_line_cache = 0; cif_dev->wait_line = 0; cif_dev->wait_line_bak = 0; cif_dev->is_thunderboot = false; + + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) + rkcif_reinit_right_half_config(cur_stream); } } void sditf_disable_immediately(struct sditf_priv *priv) { - struct rkcif_device *cif_dev = priv->cif_dev; - u32 ctrl_val = 0x10101; - if (priv->toisp_inf.link_mode == TOISP0) { - rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val); + if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF) + sditf_channel_disable_rv1103b(priv, 0); + else + sditf_channel_disable(priv, 0); } else if (priv->toisp_inf.link_mode == TOISP1) { - rkcif_write_register_and(cif_dev, CIF_REG_TOISP1_CTRL, ~ctrl_val); + if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF) + sditf_channel_disable_rv1103b(priv, 1); + else + sditf_channel_disable(priv, 1); } else if (priv->toisp_inf.link_mode == TOISP_UNITE) { - rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val); - if (cif_dev->chip_id == CHIP_RK3588_CIF) - rkcif_write_register_and(cif_dev, CIF_REG_TOISP1_CTRL, ~ctrl_val); + if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF) { + sditf_channel_disable_rv1103b(priv, 0); + } else { + sditf_channel_disable(priv, 0); + if (priv->cif_dev->chip_id == CHIP_RK3588_CIF) + sditf_channel_disable(priv, 1); + } } + priv->is_toisp_off = true; } -static void sditf_check_capture_mode(struct rkcif_device *cif_dev) +static void sditf_enable_immediately(struct sditf_priv *priv) { - struct rkcif_device *dev = NULL; - int i = 0; - int toisp_cnt = 0; - - for (i = 0; i < cif_dev->hw_dev->dev_num; i++) { - dev = cif_dev->hw_dev->cif_dev[i]; - if (dev && dev->sditf_cnt) - toisp_cnt++; + if (priv->toisp_inf.link_mode == TOISP0) { + if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF) + sditf_channel_enable_rv1103b(priv, 0); + else + sditf_channel_enable(priv, 0); + } else if (priv->toisp_inf.link_mode == TOISP1) { + if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF) + sditf_channel_enable_rv1103b(priv, 1); + else + sditf_channel_enable(priv, 1); + } else if (priv->toisp_inf.link_mode == TOISP_UNITE) { + if (priv->cif_dev->chip_id == CHIP_RV1103B_CIF) { + sditf_channel_enable_rv1103b(priv, 0); + } else { + sditf_channel_enable(priv, 0); + if (priv->cif_dev->chip_id == CHIP_RK3588_CIF) + sditf_channel_enable(priv, 1); + } } - if (cif_dev->is_thunderboot && toisp_cnt == 1) - cif_dev->is_rdbk_to_online = true; - else - cif_dev->is_rdbk_to_online = false; + priv->is_toisp_off = false; } static int sditf_start_stream(struct sditf_priv *priv) @@ -844,35 +1038,28 @@ static int sditf_start_stream(struct sditf_priv *priv) struct rkcif_device *cif_dev = priv->cif_dev; struct v4l2_subdev_format fmt; unsigned int mode = RKCIF_STREAM_MODE_TOISP; + int stream_cnt = 0; + int i = 0; - sditf_check_capture_mode(cif_dev); sditf_get_set_fmt(&priv->sd, NULL, &fmt); if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) { - if (priv->toisp_inf.link_mode == TOISP0) { - sditf_channel_enable(priv, 0); - } else if (priv->toisp_inf.link_mode == TOISP1) { - sditf_channel_enable(priv, 1); - } else if (priv->toisp_inf.link_mode == TOISP_UNITE) { - sditf_channel_enable(priv, 0); - if (cif_dev->chip_id == CHIP_RK3588_CIF) - sditf_channel_enable(priv, 1); - } + sditf_enable_immediately(priv); mode = RKCIF_STREAM_MODE_TOISP; } else if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { mode = RKCIF_STREAM_MODE_TOISP_RDBK; } if (priv->hdr_cfg.hdr_mode == NO_HDR || - priv->hdr_cfg.hdr_mode == HDR_COMPR) { - rkcif_do_start_stream(&cif_dev->stream[0], mode); - } else if (priv->hdr_cfg.hdr_mode == HDR_X2) { - rkcif_do_start_stream(&cif_dev->stream[0], mode); - rkcif_do_start_stream(&cif_dev->stream[1], mode); - } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { - rkcif_do_start_stream(&cif_dev->stream[0], mode); - rkcif_do_start_stream(&cif_dev->stream[1], mode); - rkcif_do_start_stream(&cif_dev->stream[2], mode); - } + priv->hdr_cfg.hdr_mode == HDR_COMPR) + stream_cnt = 1; + else if (priv->hdr_cfg.hdr_mode == HDR_X2) + stream_cnt = 2; + else if (priv->hdr_cfg.hdr_mode == HDR_X3) + stream_cnt = 3; + + cif_dev->is_thunderboot_start = true; + for (i = 0; i < stream_cnt; i++) + rkcif_do_start_stream(&cif_dev->stream[i], mode); INIT_LIST_HEAD(&priv->buf_free_list); return 0; } @@ -881,16 +1068,10 @@ static int sditf_stop_stream(struct sditf_priv *priv) { struct rkcif_device *cif_dev = priv->cif_dev; unsigned int mode = RKCIF_STREAM_MODE_TOISP; - - if (priv->toisp_inf.link_mode == TOISP0) { - sditf_channel_disable(priv, 0); - } else if (priv->toisp_inf.link_mode == TOISP1) { - sditf_channel_disable(priv, 1); - } else if (priv->toisp_inf.link_mode == TOISP_UNITE) { - sditf_channel_disable(priv, 0); - if (cif_dev->chip_id == CHIP_RK3588_CIF) - sditf_channel_disable(priv, 1); - } + struct rkcif_hw *hw_dev = cif_dev->hw_dev; + int stream_cnt = 0; + int i = 0; + bool toisp_off = true; if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) mode = RKCIF_STREAM_MODE_TOISP; @@ -898,16 +1079,29 @@ static int sditf_stop_stream(struct sditf_priv *priv) mode = RKCIF_STREAM_MODE_TOISP_RDBK; if (priv->hdr_cfg.hdr_mode == NO_HDR || - priv->hdr_cfg.hdr_mode == HDR_COMPR) { - rkcif_do_stop_stream(&cif_dev->stream[0], mode); - } else if (priv->hdr_cfg.hdr_mode == HDR_X2) { - rkcif_do_stop_stream(&cif_dev->stream[0], mode); - rkcif_do_stop_stream(&cif_dev->stream[1], mode); - } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { - rkcif_do_stop_stream(&cif_dev->stream[0], mode); - rkcif_do_stop_stream(&cif_dev->stream[1], mode); - rkcif_do_stop_stream(&cif_dev->stream[2], mode); + priv->hdr_cfg.hdr_mode == HDR_COMPR) + stream_cnt = 1; + else if (priv->hdr_cfg.hdr_mode == HDR_X2) + stream_cnt = 2; + else if (priv->hdr_cfg.hdr_mode == HDR_X3) + stream_cnt = 3; + + for (i = 0; i < stream_cnt; i++) + rkcif_do_stop_stream(&cif_dev->stream[i], mode); + + mutex_lock(&hw_dev->dev_lock); + for (i = 0; i < hw_dev->dev_num; i++) { + if (atomic_read(&hw_dev->cif_dev[i]->pipe.stream_cnt) != 0) { + toisp_off = false; + break; + } } + mutex_unlock(&hw_dev->dev_lock); + if (toisp_off) + sditf_disable_immediately(priv); + priv->toisp_inf.ch_info[0].is_valid = false; + priv->toisp_inf.ch_info[1].is_valid = false; + priv->toisp_inf.ch_info[2].is_valid = false; return 0; } @@ -985,11 +1179,10 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, struct rkcif_stream *stream = NULL; struct rkisp_rx_buf *dbufs; struct rkcif_rx_buffer *rx_buf = NULL; - unsigned long flags, buffree_flags, hdr_lock_flags; + unsigned long flags, buffree_flags; u32 diff_time = 1000000; u32 early_time = 0; bool is_free = false; - bool is_single_dev = false; if (!buf) { v4l2_err(&cif_dev->v4l2_dev, "buf is NULL\n"); @@ -1023,7 +1216,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, if (!stream) return -EINVAL; - if (dbufs->sequence == 0) { + if (dbufs->sequence == 0 && + stream->thunderboot_skip_interval) { spin_lock_irqsave(&stream->vbq_lock, flags); cif_dev->is_stop_skip = true; spin_unlock_irqrestore(&stream->vbq_lock, flags); @@ -1036,14 +1230,10 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, stream->last_rx_buf_idx = dbufs->sequence + 1; atomic_inc(&stream->buf_cnt); - is_single_dev = rkcif_check_single_dev_stream_on(cif_dev->hw_dev); if (stream->total_buf_num > cif_dev->fb_res_bufs && cif_dev->is_thunderboot && - ((!cif_dev->is_rtt_suspend && - !cif_dev->is_aov_reserved) || - !is_single_dev) && - (dbufs->type == BUF_SHORT || - (dbufs->type != BUF_SHORT && (!dbufs->is_switch)))) { + (dbufs->sequence > 2) && + (!dbufs->is_switch)) { spin_lock_irqsave(&cif_dev->buffree_lock, buffree_flags); list_add_tail(&rx_buf->list_free, &priv->buf_free_list); spin_unlock_irqrestore(&cif_dev->buffree_lock, buffree_flags); @@ -1060,15 +1250,11 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, if (!stream->dma_en) { stream->to_en_dma = RKCIF_DMAEN_BY_ISP; rkcif_enable_dma_capture(stream, true); - spin_lock_irqsave(&cif_dev->hdr_lock, hdr_lock_flags); - if (cif_dev->is_sensor_off) { - cif_dev->is_sensor_off = false; - spin_unlock_irqrestore(&cif_dev->hdr_lock, hdr_lock_flags); + if (atomic_read(&cif_dev->sensor_off)) { + atomic_set(&cif_dev->sensor_off, 0); cif_dev->sensor_work.on = 1; rkcif_dphy_quick_stream(stream->cifdev, cif_dev->sensor_work.on); schedule_work(&cif_dev->sensor_work.work); - } else { - spin_unlock_irqrestore(&cif_dev->hdr_lock, hdr_lock_flags); } } } @@ -1092,15 +1278,31 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, } if (dbufs->is_switch && dbufs->type == BUF_SHORT) { - if (stream->is_in_vblank) + if (stream->is_in_vblank) { sditf_change_to_online(priv); - else + rkcif_modify_line_int(stream, false); + stream->is_line_inten = false; + } else { stream->is_change_toisp = true; + } v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "switch to online mode\n"); } spin_unlock_irqrestore(&stream->vbq_lock, flags); + spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags); + stream->is_finish_single_cap = true; + if (stream->is_wait_single_cap && + (cif_dev->hdr.hdr_mode == NO_HDR || + (cif_dev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || + (cif_dev->hdr.hdr_mode == HDR_X3 && stream->id == 2))) { + stream->is_wait_single_cap = false; + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); + rkcif_quick_stream_on(cif_dev, true); + } else { + spin_unlock_irqrestore(&stream->cifdev->stream_spinlock, flags); + } + if (!cif_dev->is_thunderboot || cif_dev->is_rdbk_to_online == false) return 0; @@ -1113,7 +1315,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, diff_time = 200000; else diff_time = 1000000; - if (dbufs->runtime_us * 1000 + cif_dev->sensor_linetime > diff_time) + if (dbufs->runtime_us * 1000 < cif_dev->sensor_linetime * sensor->raw_rect.height && + dbufs->runtime_us * 1000 + cif_dev->sensor_linetime > diff_time) early_time = dbufs->runtime_us * 1000 - diff_time; else early_time = diff_time; @@ -1133,7 +1336,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, diff_time = 200000; else diff_time = 1000000; - if (dbufs->runtime_us * 1000 + cif_dev->sensor_linetime > diff_time) + if (dbufs->runtime_us * 1000 < cif_dev->sensor_linetime * sensor->raw_rect.height && + dbufs->runtime_us * 1000 + cif_dev->sensor_linetime > diff_time) early_time = dbufs->runtime_us * 1000 - diff_time; else early_time = diff_time; @@ -1447,6 +1651,7 @@ static int rkcif_subdev_media_init(struct sditf_priv *priv) priv->toisp_inf.ch_info[0].is_valid = false; priv->toisp_inf.ch_info[1].is_valid = false; priv->toisp_inf.ch_info[2].is_valid = false; + priv->is_toisp_off = true; if (priv->port_count > 1) sditf_subdev_notifier(priv); atomic_set(&priv->power_cnt, 0); @@ -1459,6 +1664,8 @@ static int rkcif_subdev_media_init(struct sditf_priv *priv) priv->frame_idx.cur_frame_idx = 0; atomic_set(&priv->frm_sync_seq, 0); mutex_init(&priv->mutex); + priv->hdr_wrap_line = 0; + priv->is_buf_init = false; return 0; } diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.h b/drivers/media/platform/rockchip/cif/subdev-itf.h index 6fff43d28576..59852f6b8a18 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.h +++ b/drivers/media/platform/rockchip/cif/subdev-itf.h @@ -100,6 +100,7 @@ struct sditf_priv { struct rkmodule_hdr_cfg hdr_cfg; struct capture_info cap_info; struct rkisp_vicap_mode mode; + struct rkisp_vicap_mode mode_src; struct toisp_info toisp_inf; struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl_handler ctrl_handler; @@ -123,6 +124,9 @@ struct sditf_priv { u32 cur_time; u32 cur_gain; int one_to_multi_id; + u32 hdr_wrap_line; + bool is_toisp_off; + bool is_buf_init; }; extern struct platform_driver rkcif_subdev_driver;