diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index b1f72357e802..e75b932a10e7 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -847,11 +847,13 @@ static int get_csi_crop_align(const struct cif_input_fmt *fmt_in) } const struct -cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd, struct v4l2_rect *rect, +cif_input_fmt *rkcif_get_input_fmt(struct rkcif_device *dev, struct v4l2_rect *rect, u32 pad_id, struct csi_channel_info *csi_info) { struct v4l2_subdev_format fmt; + struct v4l2_subdev *sd = dev->terminal_sensor.sd; struct rkmodule_channel_info ch_info = {0}; + struct rkmodule_capture_info capture_info; int ret; u32 i; @@ -897,7 +899,26 @@ cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd, struct v4l2_rect *rect, rect->top = 0; rect->width = fmt.format.width; rect->height = fmt.format.height; - + ret = v4l2_subdev_call(sd, + core, ioctl, + RKMODULE_GET_CAPTURE_MODE, + &capture_info); + if (!ret) { + if (capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE && + dev->hw_dev->is_rk3588s2) { + for (i = 0; i < capture_info.multi_dev.dev_num; i++) { + if (capture_info.multi_dev.dev_idx[i] == 0) + capture_info.multi_dev.dev_idx[i] = 2; + else if (capture_info.multi_dev.dev_idx[i] == 2) + capture_info.multi_dev.dev_idx[i] = 4; + else if (capture_info.multi_dev.dev_idx[i] == 3) + capture_info.multi_dev.dev_idx[i] = 5; + } + } + csi_info->capture_info = capture_info; + } else { + csi_info->capture_info.mode = RKMODULE_CAPTURE_MODE_NONE; + } for (i = 0; i < ARRAY_SIZE(in_fmts); i++) if (fmt.format.code == in_fmts[i].mbus_code && fmt.format.field == in_fmts[i].field) @@ -1795,14 +1816,51 @@ RDBK_TOISP_UNMATCH: spin_unlock_irqrestore(&dev->hdr_lock, flags); } +static void rkcif_write_buff_addr_multi_dev_combine(struct rkcif_stream *stream, + u32 frm_addr_y, u32 frm_addr_uv, + u32 buff_addr_y, u32 buff_addr_cbcr, + bool is_dummy_buf) +{ + struct rkcif_device *dev = stream->cifdev; + struct rkmodule_capture_info *capture_info = &dev->channels[stream->id].capture_info; + u32 addr_y, addr_cbcr; + int addr_offset = 0; + int i = 0; + int tmp_host_index = dev->csi_host_idx; + + for (i = 0; i < capture_info->multi_dev.dev_num; i++) { + if (is_dummy_buf) { + addr_y = buff_addr_y; + } else { + addr_offset = dev->channels[stream->id].left_virtual_width; + addr_y = buff_addr_y + addr_offset * i; + } + dev->csi_host_idx = capture_info->multi_dev.dev_idx[i]; + rkcif_write_register(dev, frm_addr_y, addr_y); + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW && + frm_addr_uv && buff_addr_cbcr) { + if (is_dummy_buf) { + addr_cbcr = buff_addr_cbcr; + } else { + addr_offset = dev->channels[stream->id].left_virtual_width; + addr_cbcr = buff_addr_cbcr + addr_offset * i; + } + rkcif_write_register(dev, frm_addr_uv, addr_cbcr); + } + } + dev->csi_host_idx = tmp_host_index; +} + static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, int channel_id) { struct rkcif_device *dev = stream->cifdev; struct rkcif_rx_buffer *rx_buf; struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; + struct rkmodule_capture_info *capture_info = &dev->channels[channel_id].capture_info; u32 frm0_addr_y; u32 frm1_addr_y; + u32 buff_addr_y; unsigned long flags; if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || @@ -1829,9 +1887,15 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, } } - if (stream->curr_buf_toisp) - rkcif_write_register(dev, frm0_addr_y, - stream->curr_buf_toisp->dummy.dma_addr); + if (stream->curr_buf_toisp) { + buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, frm0_addr_y, 0, + buff_addr_y, 0, false); + } else { + rkcif_write_register(dev, frm0_addr_y, buff_addr_y); + } + } if (!stream->next_buf_toisp) { if (!list_empty(&stream->rx_buf_head)) { @@ -1848,9 +1912,15 @@ static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream, } } - if (stream->next_buf_toisp) - rkcif_write_register(dev, frm1_addr_y, - stream->next_buf_toisp->dummy.dma_addr); + if (stream->next_buf_toisp) { + buff_addr_y = stream->next_buf_toisp->dummy.dma_addr; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, frm1_addr_y, 0, + buff_addr_y, 0, false); + } else { + rkcif_write_register(dev, frm1_addr_y, buff_addr_y); + } + } spin_unlock_irqrestore(&stream->vbq_lock, flags); stream->buf_owner = RKCIF_DMAEN_BY_ISP; @@ -1861,10 +1931,11 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, { struct rkcif_device *dev = stream->cifdev; struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; + struct rkmodule_capture_info *capture_info = &dev->channels[channel_id].capture_info; struct rkcif_rx_buffer *buffer = NULL; struct rkcif_rx_buffer *active_buf = NULL; struct sditf_priv *priv = dev->sditf[0]; - u32 frm_addr_y; + u32 frm_addr_y, buff_addr_y; unsigned long flags; if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || @@ -2009,8 +2080,13 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, out_get_buf: stream->frame_phase_cache = stream->frame_phase; if (buffer) { - rkcif_write_register(dev, frm_addr_y, - buffer->dummy.dma_addr); + buff_addr_y = buffer->dummy.dma_addr; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, 0, + buff_addr_y, 0, false); + } else { + rkcif_write_register(dev, frm_addr_y, buff_addr_y); + } if (dev->rdbk_debug > 1 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, @@ -2020,8 +2096,13 @@ out_get_buf: frm_addr_y, (u32)buffer->dummy.dma_addr); } else if (dev->hw_dev->dummy_buf.vaddr && priv && priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { - rkcif_write_register(dev, frm_addr_y, - dev->hw_dev->dummy_buf.dma_addr); + buff_addr_y = dev->hw_dev->dummy_buf.dma_addr; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, 0, + buff_addr_y, 0, true); + } else { + rkcif_write_register(dev, frm_addr_y, buff_addr_y); + } } spin_unlock_irqrestore(&stream->vbq_lock, flags); return 0; @@ -2044,8 +2125,9 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) struct rkcif_device *dev = stream->cifdev; struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; struct rkcif_rx_buffer *buffer = NULL; + struct rkmodule_capture_info *capture_info = &dev->channels[stream->id].capture_info; struct rkcif_rx_buffer *active_buf = NULL; - u32 frm_addr_y; + u32 frm_addr_y, buff_addr_y; u32 vblank = 0; u32 vblank_ns = 0; u64 cur_time = 0; @@ -2108,8 +2190,15 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) if (buffer) { list_del(&buffer->list); stream->curr_buf_toisp = buffer; - rkcif_write_register(dev, frm_addr_y, - stream->curr_buf_toisp->dummy.dma_addr); + buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm_addr_y, 0, + buff_addr_y, 0, + false); + } else { + rkcif_write_register(dev, frm_addr_y, buff_addr_y); + } if (dev->rdbk_debug > 1 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, @@ -2125,8 +2214,15 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) if (buffer) { list_del(&buffer->list); stream->next_buf_toisp = buffer; - rkcif_write_register(dev, frm_addr_y, - stream->next_buf_toisp->dummy.dma_addr); + buff_addr_y = stream->next_buf_toisp->dummy.dma_addr; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm_addr_y, 0, + buff_addr_y, 0, + false); + } else { + rkcif_write_register(dev, frm_addr_y, buff_addr_y); + } if (dev->rdbk_debug > 1 && stream->frame_idx < 15) v4l2_info(&dev->v4l2_dev, @@ -2174,8 +2270,13 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) stream->next_buf_toisp = stream->curr_buf_toisp; else stream->curr_buf_toisp = stream->next_buf_toisp; - rkcif_write_register(dev, frm_addr_y, - stream->curr_buf_toisp->dummy.dma_addr); + buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, 0, + buff_addr_y, 0, false); + } else { + rkcif_write_register(dev, frm_addr_y, buff_addr_y); + } } } @@ -2186,6 +2287,7 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream, struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; u32 frm0_addr_y, frm0_addr_uv; u32 frm1_addr_y, frm1_addr_uv; + u32 buff_addr_y, buff_addr_cbcr; unsigned long flags; struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf; struct csi_channel_info *channel = &dev->channels[channel_id]; @@ -2216,16 +2318,38 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream, } if (stream->curr_buf) { - rkcif_write_register(dev, frm0_addr_y, - stream->curr_buf->buff_addr[RKCIF_PLANE_Y]); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm0_addr_uv, - stream->curr_buf->buff_addr[RKCIF_PLANE_CBCR]); + buff_addr_y = stream->curr_buf->buff_addr[RKCIF_PLANE_Y]; + buff_addr_cbcr = stream->curr_buf->buff_addr[RKCIF_PLANE_CBCR]; + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm0_addr_y, + frm0_addr_uv, + buff_addr_y, + buff_addr_cbcr, + false); + } else { + rkcif_write_register(dev, frm0_addr_y, + stream->curr_buf->buff_addr[RKCIF_PLANE_Y]); + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) + rkcif_write_register(dev, frm0_addr_uv, + stream->curr_buf->buff_addr[RKCIF_PLANE_CBCR]); + } } else { if (dummy_buf->vaddr) { - rkcif_write_register(dev, frm0_addr_y, dummy_buf->dma_addr); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm0_addr_uv, dummy_buf->dma_addr); + buff_addr_y = dummy_buf->dma_addr; + buff_addr_cbcr = dummy_buf->dma_addr; + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm0_addr_y, + frm0_addr_uv, + buff_addr_y, + buff_addr_cbcr, + true); + } else { + 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); + } } else { if (stream->lack_buf_cnt < 2) stream->lack_buf_cnt++; @@ -2235,11 +2359,22 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream, if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) { stream->next_buf = stream->curr_buf; if (stream->next_buf) { - rkcif_write_register(dev, frm1_addr_y, - stream->next_buf->buff_addr[RKCIF_PLANE_Y] + (channel->virtual_width / 2)); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm1_addr_uv, - stream->next_buf->buff_addr[RKCIF_PLANE_CBCR] + (channel->virtual_width / 2)); + buff_addr_y = stream->next_buf->buff_addr[RKCIF_PLANE_Y]; + buff_addr_cbcr = stream->next_buf->buff_addr[RKCIF_PLANE_CBCR]; + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm1_addr_y, + frm1_addr_uv, + buff_addr_y, + buff_addr_cbcr, + false); + } else { + rkcif_write_register(dev, frm1_addr_y, + buff_addr_y + (channel->virtual_width / 2)); + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) + rkcif_write_register(dev, frm1_addr_uv, + buff_addr_cbcr + (channel->virtual_width / 2)); + } } } else { if (!stream->next_buf) { @@ -2250,28 +2385,41 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream, } } - if (stream->next_buf) { - rkcif_write_register(dev, frm1_addr_y, - stream->next_buf->buff_addr[RKCIF_PLANE_Y]); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm1_addr_uv, - stream->next_buf->buff_addr[RKCIF_PLANE_CBCR]); - } else { - if (dummy_buf->vaddr) { + if (!stream->next_buf && dummy_buf->vaddr) { + buff_addr_y = dummy_buf->dma_addr; + buff_addr_cbcr = dummy_buf->dma_addr; + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm1_addr_y, + frm1_addr_uv, + buff_addr_y, + buff_addr_cbcr, + true); + } else { rkcif_write_register(dev, frm1_addr_y, dummy_buf->dma_addr); if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) rkcif_write_register(dev, frm1_addr_uv, dummy_buf->dma_addr); + } + + } else if (!stream->next_buf && stream->curr_buf) { + stream->next_buf = stream->curr_buf; + if (stream->lack_buf_cnt < 2) + stream->lack_buf_cnt++; + } + if (stream->next_buf) { + buff_addr_y = stream->next_buf->buff_addr[RKCIF_PLANE_Y]; + buff_addr_cbcr = stream->next_buf->buff_addr[RKCIF_PLANE_CBCR]; + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm1_addr_y, + frm1_addr_uv, + buff_addr_y, + buff_addr_cbcr, + false); } else { - if (stream->curr_buf) { - stream->next_buf = stream->curr_buf; - rkcif_write_register(dev, frm1_addr_y, - stream->next_buf->buff_addr[RKCIF_PLANE_Y]); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm1_addr_uv, - stream->next_buf->buff_addr[RKCIF_PLANE_CBCR]); - } - if (stream->lack_buf_cnt < 2) - stream->lack_buf_cnt++; + 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); } } } @@ -2319,6 +2467,7 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, struct rkisp_rx_buf *dbufs = NULL; struct dma_buf *dbuf = NULL; int ret = 0; + u32 buff_addr_y, buff_addr_cbcr; unsigned long flags; if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || @@ -2431,19 +2580,37 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, stream->frame_phase_cache = stream->frame_phase; if (buffer) { + buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y]; + buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR]; if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED && stream->frame_phase == CIF_CSI_FRAME1_READY) { - rkcif_write_register(dev, frm_addr_y, - buffer->buff_addr[RKCIF_PLANE_Y] + (channel->virtual_width / 2)); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm_addr_uv, - buffer->buff_addr[RKCIF_PLANE_CBCR] + (channel->virtual_width / 2)); + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm_addr_y, + frm_addr_uv, + buff_addr_y, + buff_addr_cbcr, + false); + } else { + rkcif_write_register(dev, frm_addr_y, + buff_addr_y + (channel->virtual_width / 2)); + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) + rkcif_write_register(dev, frm_addr_uv, + buff_addr_cbcr + (channel->virtual_width / 2)); + } } else { - rkcif_write_register(dev, frm_addr_y, - buffer->buff_addr[RKCIF_PLANE_Y]); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm_addr_uv, - buffer->buff_addr[RKCIF_PLANE_CBCR]); + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm_addr_y, + frm_addr_uv, + buff_addr_y, + buff_addr_cbcr, + false); + } else { + 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); + } } if (stream->dma_en & RKCIF_DMAEN_BY_ISP) { if (stream->buf_replace_cnt < 2) @@ -2466,8 +2633,13 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, } } else { if (stream->dma_en & RKCIF_DMAEN_BY_ISP) { - rkcif_write_register(dev, frm_addr_y, - stream->curr_buf_toisp->dummy.dma_addr); + buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr; + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) + rkcif_write_buff_addr_multi_dev_combine(stream, + frm_addr_y, 0, + buff_addr_y, 0, false); + else + rkcif_write_register(dev, frm_addr_y, buff_addr_y); if (stream->frame_phase == CIF_CSI_FRAME0_READY && stream->next_buf) dbuf = stream->next_buf->dbuf; @@ -2493,11 +2665,24 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, stream->buf_replace_cnt--; } } else if (dummy_buf->vaddr) { - rkcif_write_register(dev, frm_addr_y, dummy_buf->dma_addr); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm_addr_uv, dummy_buf->dma_addr); + + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + buff_addr_y = dummy_buf->dma_addr; + buff_addr_cbcr = dummy_buf->dma_addr; + rkcif_write_buff_addr_multi_dev_combine(stream, + frm_addr_y, + frm_addr_uv, + buff_addr_y, + buff_addr_cbcr, + true); + } else { + rkcif_write_register(dev, frm_addr_y, dummy_buf->dma_addr); + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) + rkcif_write_register(dev, frm_addr_uv, dummy_buf->dma_addr); + } dev->err_state |= (RKCIF_ERR_ID0_NOT_BUF << stream->id); dev->irq_stats.not_active_buf_cnt[stream->id]++; + } else { ret = -EINVAL; stream->curr_buf = NULL; @@ -2511,8 +2696,13 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, stop_dma: if (stream->buf_replace_cnt) { spin_lock_irqsave(&stream->vbq_lock, flags); - rkcif_write_register(dev, frm_addr_y, - stream->curr_buf_toisp->dummy.dma_addr); + buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr; + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) + rkcif_write_buff_addr_multi_dev_combine(stream, + frm_addr_y, 0, + buff_addr_y, 0, false); + else + rkcif_write_register(dev, frm_addr_y, buff_addr_y); if (stream->frame_phase == CIF_CSI_FRAME0_READY && stream->next_buf) dbuf = stream->next_buf->dbuf; @@ -2608,8 +2798,10 @@ static int rkcif_update_new_buffer_wake_up_mode(struct rkcif_stream *stream) struct rkcif_device *dev = stream->cifdev; struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf; struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus; + struct rkmodule_capture_info *capture_info = &dev->channels[stream->id].capture_info; struct rkcif_buffer *buffer = NULL; u32 frm_addr_y, frm_addr_uv; + u32 buff_addr_y, buff_addr_cbcr; int channel_id = stream->id; int ret = 0; unsigned long flags; @@ -2640,16 +2832,35 @@ static int rkcif_update_new_buffer_wake_up_mode(struct rkcif_stream *stream) } spin_unlock_irqrestore(&stream->vbq_lock, flags); if (buffer) { - rkcif_write_register(dev, frm_addr_y, - buffer->buff_addr[RKCIF_PLANE_Y]); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm_addr_uv, - buffer->buff_addr[RKCIF_PLANE_CBCR]); + buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y]; + buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR]; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, + frm_addr_uv, + buff_addr_y, + buff_addr_cbcr, + false); + } else { + 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 { if (dummy_buf->vaddr) { - rkcif_write_register(dev, frm_addr_y, dummy_buf->dma_addr); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm_addr_uv, dummy_buf->dma_addr); + buff_addr_y = dummy_buf->dma_addr; + buff_addr_cbcr = dummy_buf->dma_addr; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm_addr_y, + frm_addr_uv, + buff_addr_y, + buff_addr_cbcr, + true); + } else { + 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 { if (dev->chip_id < CHIP_RK3588_CIF) ret = -EINVAL; @@ -3145,6 +3356,7 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, struct csi_channel_info *channel) { struct rkcif_device *dev = stream->cifdev; + struct sditf_priv *priv = dev->sditf[0]; const struct cif_output_fmt *fmt; u32 fourcc; int vc = dev->channels[stream->id].vc; @@ -3169,7 +3381,7 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, channel->crop_st_x = stream->crop[CROP_SRC_ACT].left; channel->crop_st_y = stream->crop[CROP_SRC_ACT].top; - if (dev->sditf_cnt > 1 && dev->sditf_cnt <= RKCIF_MAX_SDITF) + if (priv && priv->is_combine_mode && dev->sditf_cnt <= RKCIF_MAX_SDITF) channel->crop_st_y *= dev->sditf_cnt; channel->width = stream->crop[CROP_SRC_ACT].width; channel->height = stream->crop[CROP_SRC_ACT].height; @@ -3179,7 +3391,7 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, channel->crop_en = 0; } - if (dev->sditf_cnt > 1 && dev->sditf_cnt <= RKCIF_MAX_SDITF) + if (priv && priv->is_combine_mode && dev->sditf_cnt <= RKCIF_MAX_SDITF) channel->height *= dev->sditf_cnt; fmt = rkcif_find_output_fmt(stream, stream->pixm.pixelformat); @@ -3189,6 +3401,8 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, return -EINVAL; } + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) + channel->width /= channel->capture_info.multi_dev.dev_num; /* * 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 @@ -3198,9 +3412,19 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, if (fmt->fmt_type == CIF_FMT_TYPE_RAW && stream->is_compact && fmt->csi_fmt_val != CSI_WRDDR_TYPE_RGB888 && fmt->csi_fmt_val != CSI_WRDDR_TYPE_RGB565) { - channel->virtual_width = ALIGN(channel->width * fmt->raw_bpp / 8, 256); + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + channel->virtual_width = ALIGN(channel->width * 2 * fmt->raw_bpp / 8, 256); + channel->left_virtual_width = channel->width * fmt->raw_bpp / 8; + } else { + channel->virtual_width = ALIGN(channel->width * fmt->raw_bpp / 8, 256); + } } else { - channel->virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8); + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + channel->virtual_width = ALIGN(channel->width * 2 * fmt->bpp[0] / 8, 8); + channel->left_virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8); + } else { + channel->virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8); + } } if (channel->fmt_val == CSI_WRDDR_TYPE_RGB888 || channel->fmt_val == CSI_WRDDR_TYPE_RGB565) @@ -3219,6 +3443,8 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, channel->width *= 2; } channel->virtual_width *= 2; + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) + channel->left_virtual_width *= 2; } if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) { channel->virtual_width *= 2; @@ -3567,15 +3793,18 @@ static void rkcif_modify_frame_skip_config(struct rkcif_stream *stream) /*config reg for rk3588*/ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, - struct csi_channel_info *channel, - enum v4l2_mbus_type mbus_type, unsigned int mode) + struct csi_channel_info *channel, + enum v4l2_mbus_type mbus_type, unsigned int mode, + int index) { 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; unsigned int dma_en = 0; + int offset = 0; if (channel->id >= 4) return -EINVAL; @@ -3591,21 +3820,28 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, CSI_DMA_END_INTSTAT(channel->id) | CSI_LINE_INTSTAT_V1(channel->id))); - rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, - CSI_START_INTEN(channel->id)); + if (!(capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE && + index < capture_info->multi_dev.dev_num - 1)) { - if (priv && priv->mode.rdbk_mode && 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; - } - rkcif_write_register(dev, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1, - wait_line << 16 | wait_line); - rkcif_write_register(dev, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3, - wait_line << 16 | wait_line); + CSI_START_INTEN(channel->id)); - rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, - CSI_DMA_END_INTEN(channel->id)); + if (priv && priv->mode.rdbk_mode && 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; + } + rkcif_write_register(dev, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1, + wait_line << 16 | wait_line); + rkcif_write_register(dev, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3, + wait_line << 16 | wait_line); + + rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, + CSI_DMA_END_INTEN(channel->id)); + + rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, + CSI_ALL_ERROR_INTEN_V1); + } if (stream->cifdev->id_use_cnt == 0) { val = CIF_MIPI_LVDS_SW_PRESS_VALUE_RK3588(0x3) | CIF_MIPI_LVDS_SW_PRESS_ENABLE | @@ -3619,25 +3855,26 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, else val |= CIF_MIPI_LVDS_SW_SEL_LVDS_RV1106; rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val); - - rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN, - CSI_ALL_ERROR_INTEN_V1); } #if IS_ENABLED(CONFIG_CPU_RV1106) if (channel->id == 1) rv1106_sdmmc_get_lock(); #endif + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE && + priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && + (dev->hdr.hdr_mode == NO_HDR || + (dev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || + (dev->hdr.hdr_mode == HDR_X3 && stream->id == 2))) + offset = channel->capture_info.multi_dev.pixel_offset; + rkcif_write_register(dev, get_reg_index_of_id_ctrl1(channel->id), - channel->width | (channel->height << 16)); + (channel->width + offset) | (channel->height << 16)); #if IS_ENABLED(CONFIG_CPU_RV1106) if (channel->id == 1) rv1106_sdmmc_put_lock(); #endif - rkcif_write_register(dev, get_reg_index_of_frm0_y_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); @@ -3655,6 +3892,17 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, rkcif_assign_new_buffer_pingpong_rockit(stream, RKCIF_YUV_ADDR_STATE_INIT, channel->id); + + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE && + index == (capture_info->multi_dev.dev_num - 1) && + priv && priv->mode.rdbk_mode != RKISP_VICAP_ONLINE) + rkcif_write_register(dev, get_reg_index_of_id_crop_start(channel->id), + 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); + if (stream->lack_buf_cnt == 2) stream->dma_en = 0; @@ -3717,7 +3965,24 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, } if (dev->chip_id >= CHIP_RV1106_CIF) rkcif_modify_frame_skip_config(stream); - stream->cifdev->id_use_cnt++; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + if (index == (capture_info->multi_dev.dev_num - 1)) + stream->cifdev->id_use_cnt++; + } else { + stream->cifdev->id_use_cnt++; + } + if (!(capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE && + index < capture_info->multi_dev.dev_num - 1)) { + if (mode == RKCIF_STREAM_MODE_CAPTURE) + rkcif_assign_new_buffer_pingpong(stream, + RKCIF_YUV_ADDR_STATE_INIT, + channel->id); + else if (mode == RKCIF_STREAM_MODE_TOISP || + mode == RKCIF_STREAM_MODE_TOISP_RDBK) + rkcif_assign_new_buffer_pingpong_toisp(stream, + RKCIF_YUV_ADDR_STATE_INIT, + channel->id); + } return 0; } @@ -3728,6 +3993,7 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode enum v4l2_mbus_type mbus_type = active_sensor->mbus.type; struct csi_channel_info *channel; u32 ret = 0; + int i; if (stream->state < RKCIF_STATE_STREAMING) { stream->frame_idx = 0; @@ -3764,10 +4030,18 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode } else if (mode == RKCIF_STREAM_MODE_ROCKIT) { stream->dma_en |= RKCIF_DMAEN_BY_ROCKIT; } - if (stream->cifdev->chip_id < CHIP_RK3588_CIF) + if (stream->cifdev->chip_id < CHIP_RK3588_CIF) { rkcif_csi_channel_set(stream, channel, mbus_type); - else - rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode); + } else { + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + 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_csi_channel_set_v1(stream, channel, mbus_type, mode, i); + } + } else { + rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode, 0); + } + } } else { if (stream->cifdev->chip_id >= CHIP_RK3588_CIF) { if (mode == RKCIF_STREAM_MODE_CAPTURE) { @@ -3807,7 +4081,9 @@ static void rkcif_stream_stop(struct rkcif_stream *stream) struct v4l2_mbus_config *mbus_cfg = &cif_dev->active_sensor->mbus; u32 val; int id; + int i = 0; + stream->cifdev->id_use_cnt--; if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || mbus_cfg->type == V4L2_MBUS_CSI2_CPHY || mbus_cfg->type == V4L2_MBUS_CCP2) { @@ -3819,7 +4095,14 @@ static void rkcif_stream_stop(struct rkcif_stream *stream) else val &= ~LVDS_ENABLE_CAPTURE; - rkcif_write_register(cif_dev, get_reg_index_of_id_ctrl0(id), val); + if (cif_dev->channels[id].capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + for (i = 0; i < cif_dev->channels[id].capture_info.multi_dev.dev_num; i++) { + cif_dev->csi_host_idx = cif_dev->channels[id].capture_info.multi_dev.dev_idx[i]; + rkcif_write_register(cif_dev, get_reg_index_of_id_ctrl0(id), val); + } + } else { + rkcif_write_register(cif_dev, get_reg_index_of_id_ctrl0(id), val); + } rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_INTSTAT, CSI_START_INTSTAT(id) | @@ -3838,8 +4121,16 @@ static void rkcif_stream_stop(struct rkcif_stream *stream) if (stream->cifdev->id_use_cnt == 0) { rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_INTEN, ~CSI_ALL_ERROR_INTEN_V1); - rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL, - ~CSI_ENABLE_CAPTURE); + if (cif_dev->channels[id].capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + for (i = 0; i < cif_dev->channels[id].capture_info.multi_dev.dev_num; i++) { + cif_dev->csi_host_idx = cif_dev->channels[id].capture_info.multi_dev.dev_idx[i]; + rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL, + ~CSI_ENABLE_CAPTURE); + } + } else { + rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL, + ~CSI_ENABLE_CAPTURE); + } } } @@ -3855,7 +4146,6 @@ static void rkcif_stream_stop(struct rkcif_stream *stream) rkcif_config_dvp_pin(cif_dev, false); } } - stream->cifdev->id_use_cnt--; stream->state = RKCIF_STATE_READY; stream->dma_en = 0; } @@ -3952,6 +4242,8 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream, 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; + struct rkmodule_capture_info *capture_info = &dev->channels[channel_id].capture_info; unsigned long flags; int frame_phase = 0; bool is_dual_update_buf = false; @@ -4018,22 +4310,51 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream, } if (buffer) { if (is_dual_update_buf) { - rkcif_write_register(dev, frm0_addr_y, - buffer->buff_addr[RKCIF_PLANE_Y]); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm0_addr_uv, - buffer->buff_addr[RKCIF_PLANE_CBCR]); - rkcif_write_register(dev, frm1_addr_y, - buffer->buff_addr[RKCIF_PLANE_Y]); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm1_addr_uv, - buffer->buff_addr[RKCIF_PLANE_CBCR]); + buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y]; + buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR]; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm0_addr_y, + frm0_addr_uv, + buff_addr_y, + buff_addr_cbcr, + false); + rkcif_write_buff_addr_multi_dev_combine(stream, + frm1_addr_y, + frm1_addr_uv, + buff_addr_y, + buff_addr_cbcr, + false); + } else { + 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 { - rkcif_write_register(dev, frm_addr_y, - buffer->buff_addr[RKCIF_PLANE_Y]); - if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) - rkcif_write_register(dev, frm_addr_uv, - buffer->buff_addr[RKCIF_PLANE_CBCR]); + + buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y]; + buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR]; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + rkcif_write_buff_addr_multi_dev_combine(stream, + frm_addr_y, + frm_addr_uv, + buff_addr_y, + buff_addr_cbcr, + false); + } else { + 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 { @@ -5002,9 +5323,9 @@ static int rkcif_sanity_check_fmt(struct rkcif_stream *stream, struct v4l2_rect input, *crop; if (dev->terminal_sensor.sd) { - stream->cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd, - &input, stream->id, - &dev->channels[stream->id]); + stream->cif_fmt_in = rkcif_get_input_fmt(dev, + &input, stream->id, + &dev->channels[stream->id]); if (!stream->cif_fmt_in) { v4l2_err(v4l2_dev, "Input fmt is invalid\n"); return -EINVAL; @@ -5527,6 +5848,7 @@ static void rkcif_attach_sync_mode(struct rkcif_device *cifdev) { struct rkcif_hw *hw = cifdev->hw_dev; struct rkcif_device *dev; + struct sditf_priv *priv; int i = 0, j = 0; int ret = 0; int count = 0; @@ -5604,26 +5926,31 @@ static void rkcif_attach_sync_mode(struct rkcif_device *cifdev) else sync_cfg.group = 0; } else { - for (j = 0; j < dev->sditf_cnt; j++) { - ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd, - core, ioctl, - RKMODULE_GET_SYNC_MODE, - &sync_type); - if (!ret && sync_type) - break; + priv = dev->sditf[0]; + if (priv && priv->is_combine_mode && dev->sditf_cnt <= RKCIF_MAX_SDITF) { + for (j = 0; j < dev->sditf_cnt; j++) { + ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd, + core, ioctl, + RKMODULE_GET_SYNC_MODE, + &sync_type); + if (!ret && sync_type) { + priv = dev->sditf[j]; + break; + } + } + if (!ret) + sync_cfg.type = sync_type; + else + sync_cfg.type = NO_SYNC_MODE; + ret = v4l2_subdev_call(priv->sensor_sd, + core, ioctl, + RKMODULE_GET_GROUP_ID, + &sync_group); + if (!ret && sync_group < RKCIF_MAX_GROUP) + sync_cfg.group = sync_group; + else + sync_cfg.group = 0; } - if (!ret) - sync_cfg.type = sync_type; - else - sync_cfg.type = NO_SYNC_MODE; - ret = v4l2_subdev_call(dev->sditf[j]->sensor_sd, - core, ioctl, - RKMODULE_GET_GROUP_ID, - &sync_group); - if (!ret && sync_group < RKCIF_MAX_GROUP) - sync_cfg.group = sync_group; - else - sync_cfg.group = 0; } if (sync_cfg.group == cifdev->sync_cfg.group) { if (sync_cfg.type == EXTERNAL_MASTER_MODE) { @@ -5646,6 +5973,11 @@ static void rkcif_attach_sync_mode(struct rkcif_device *cifdev) sync_config->sync_mask |= BIT(dev->csi_host_idx); } dev->sync_cfg = sync_cfg; + } else { + ret = v4l2_subdev_call(dev->terminal_sensor.sd, + core, ioctl, + RKMODULE_GET_SYNC_MODE, + &sync_type); } } if (sync_config->int_master.count == 1) { @@ -5679,15 +6011,18 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode) struct rkcif_hw *hw_dev = dev->hw_dev; struct v4l2_device *v4l2_dev = &dev->v4l2_dev; struct rkcif_sensor_info *sensor_info = dev->active_sensor; - struct rkcif_sensor_info *terminal_sensor = &dev->terminal_sensor; + struct rkcif_sensor_info *terminal_sensor = NULL; struct rkmodule_hdr_cfg hdr_cfg; + struct rkcif_csi_info csi_info = {0}; int rkmodule_stream_seq = RKMODULE_START_STREAM_DEFAULT; int ret; + int i = 0; v4l2_info(&dev->v4l2_dev, "stream[%d] start streaming\n", stream->id); rkcif_attach_sync_mode(dev); mutex_lock(&dev->stream_lock); + if ((stream->cur_stream_mode & RKCIF_STREAM_MODE_CAPTURE) == mode) { ret = -EBUSY; v4l2_err(v4l2_dev, "stream in busy state\n"); @@ -5700,7 +6035,7 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode) else stream->is_line_inten = false; - if (dev->active_sensor) { + if (!dev->active_sensor) { ret = rkcif_update_sensor_info(stream); if (ret < 0) { v4l2_err(v4l2_dev, @@ -5709,7 +6044,7 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode) goto out; } } - + terminal_sensor = &dev->terminal_sensor; if (terminal_sensor->sd) { ret = v4l2_subdev_call(terminal_sensor->sd, core, ioctl, @@ -5740,6 +6075,39 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode) goto destroy_buf; mutex_lock(&hw_dev->dev_lock); + if (atomic_read(&dev->pipe.stream_cnt) == 0 && + dev->active_sensor && + (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || + dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY || + dev->active_sensor->mbus.type == V4L2_MBUS_CCP2)) { + if (dev->channels[0].capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + csi_info.csi_num = dev->channels[0].capture_info.multi_dev.dev_num; + if (csi_info.csi_num > RKCIF_MAX_CSI_NUM) { + v4l2_err(v4l2_dev, + "csi num %d, max %d\n", + csi_info.csi_num, RKCIF_MAX_CSI_NUM); + goto out; + } + for (i = 0; i < csi_info.csi_num; i++) { + csi_info.csi_idx[i] = dev->channels[0].capture_info.multi_dev.dev_idx[i]; + if (dev->hw_dev->is_rk3588s2) + v4l2_info(v4l2_dev, "rk3588s2 combine mode attach to mipi%d\n", + csi_info.csi_idx[i]); + } + } else { + csi_info.csi_num = 1; + dev->csi_host_idx = dev->csi_host_idx_def; + csi_info.csi_idx[0] = dev->csi_host_idx; + } + ret = v4l2_subdev_call(dev->active_sensor->sd, + core, ioctl, + RKCIF_CMD_SET_CSI_IDX, + &csi_info); + if (ret) + v4l2_err(&dev->v4l2_dev, "set csi idx %d fail\n", dev->csi_host_idx); + + } + if (((dev->active_sensor && dev->active_sensor->mbus.type == V4L2_MBUS_BT656) || dev->is_use_dummybuf) && (!dev->hw_dev->dummy_buf.vaddr) && @@ -5907,6 +6275,7 @@ int rkcif_set_fmt(struct rkcif_stream *stream, bool try) { struct rkcif_device *dev = stream->cifdev; + struct sditf_priv *priv = dev->sditf[0]; const struct cif_output_fmt *fmt; const struct cif_input_fmt *cif_fmt_in = NULL; struct v4l2_rect input_rect; @@ -5914,6 +6283,7 @@ int rkcif_set_fmt(struct rkcif_stream *stream, u32 xsubs = 1, ysubs = 1, i; struct rkmodule_hdr_cfg hdr_cfg; struct rkcif_extend_info *extend_line = &stream->extend_line; + struct csi_channel_info *channel_info = &dev->channels[stream->id]; int ret; for (i = 0; i < RKCIF_MAX_PLANE; i++) @@ -5927,9 +6297,9 @@ int rkcif_set_fmt(struct rkcif_stream *stream, input_rect.height = RKCIF_DEFAULT_HEIGHT; if (dev->terminal_sensor.sd) { - cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd, - &input_rect, stream->id, - &dev->channels[stream->id]); + cif_fmt_in = rkcif_get_input_fmt(dev, + &input_rect, stream->id, + channel_info); stream->cif_fmt_in = cif_fmt_in; } else { v4l2_err(&stream->cifdev->v4l2_dev, @@ -5971,8 +6341,9 @@ int rkcif_set_fmt(struct rkcif_stream *stream, planes = fmt->cplanes ? fmt->cplanes : fmt->mplanes; - if (cif_fmt_in && (cif_fmt_in->mbus_code == MEDIA_BUS_FMT_SPD_2X8 || - cif_fmt_in->mbus_code == MEDIA_BUS_FMT_EBD_1X8)) + if (cif_fmt_in && + (cif_fmt_in->mbus_code == MEDIA_BUS_FMT_SPD_2X8 || + cif_fmt_in->mbus_code == MEDIA_BUS_FMT_EBD_1X8)) stream->crop_enable = false; for (i = 0; i < planes; i++) { @@ -5997,7 +6368,7 @@ int rkcif_set_fmt(struct rkcif_stream *stream, } } - if (dev->sditf_cnt > 1 && dev->sditf_cnt <= RKCIF_MAX_SDITF) + if (priv && priv->is_combine_mode && dev->sditf_cnt <= RKCIF_MAX_SDITF) height *= dev->sditf_cnt; extend_line->pixm.height = height + RKMODULE_EXTEND_LINE; @@ -6007,8 +6378,9 @@ int rkcif_set_fmt(struct rkcif_stream *stream, * to optimize reading and writing of ddr, aliged with 256. */ if (fmt->fmt_type == CIF_FMT_TYPE_RAW && - (stream->cif_fmt_in->mbus_code == MEDIA_BUS_FMT_EBD_1X8 || - stream->cif_fmt_in->mbus_code == MEDIA_BUS_FMT_SPD_2X8)) { + cif_fmt_in && + (cif_fmt_in->mbus_code == MEDIA_BUS_FMT_EBD_1X8 || + cif_fmt_in->mbus_code == MEDIA_BUS_FMT_SPD_2X8)) { stream->is_compact = false; } @@ -6295,9 +6667,9 @@ static int rkcif_enum_framesizes(struct file *file, void *prov, input_rect.height = RKCIF_DEFAULT_HEIGHT; if (dev->terminal_sensor.sd) - get_input_fmt(dev->terminal_sensor.sd, - &input_rect, stream->id, - &csi_info); + rkcif_get_input_fmt(dev, + &input_rect, stream->id, + &csi_info); if (dev->hw_dev->adapt_to_usbcamerahal) { fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; @@ -6376,7 +6748,7 @@ static int rkcif_enum_fmt_vid_cap_mplane(struct file *file, void *priv, return -EINVAL; if (dev->terminal_sensor.sd) { - cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd, + cif_fmt_in = rkcif_get_input_fmt(dev, &input_rect, stream->id, &dev->channels[stream->id]); stream->cif_fmt_in = cif_fmt_in; @@ -6762,8 +7134,8 @@ static long rkcif_ioctl_default(struct file *file, void *fh, break; case RKCIF_CMD_SET_CSI_MEMORY_MODE: if (dev->terminal_sensor.sd) { - in_fmt = get_input_fmt(dev->terminal_sensor.sd, - &rect, 0, &csi_info); + in_fmt = rkcif_get_input_fmt(dev, + &rect, 0, &csi_info); if (in_fmt == NULL) { v4l2_err(&dev->v4l2_dev, "can't get sensor input format\n"); return -EINVAL; @@ -8426,8 +8798,8 @@ static void rkcif_update_stream(struct rkcif_device *cif_dev, if (!stream->is_line_wake_up) { ret = rkcif_assign_new_buffer_pingpong(stream, - RKCIF_YUV_ADDR_STATE_UPDATE, - mipi_id); + RKCIF_YUV_ADDR_STATE_UPDATE, + mipi_id); if (ret && cif_dev->chip_id < CHIP_RK3588_CIF) return; } else { @@ -8561,6 +8933,7 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev, 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; @@ -8629,10 +9002,12 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev, __func__, on ? "on" : "off", p->subdevs[i]->name); } - for (i = 0; i < cif_dev->sditf_cnt; i++) { - if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd) - ret = v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, core, ioctl, - RKMODULE_SET_QUICK_STREAM, &on); + if (priv && priv->is_combine_mode && cif_dev->sditf_cnt <= RKCIF_MAX_SDITF) { + for (i = 0; i < cif_dev->sditf_cnt; i++) { + if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd) + ret = v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, core, ioctl, + RKMODULE_SET_QUICK_STREAM, &on); + } } rockchip_clear_system_status(SYS_STATUS_CIF0); @@ -8727,10 +9102,12 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev, p->subdevs[i]->name); } - for (i = 0; i < cif_dev->sditf_cnt; i++) { - if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd) - v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, core, ioctl, - RKMODULE_SET_QUICK_STREAM, &on); + if (priv && priv->is_combine_mode && cif_dev->sditf_cnt <= RKCIF_MAX_SDITF) { + for (i = 0; i < cif_dev->sditf_cnt; i++) { + if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd) + v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, core, ioctl, + RKMODULE_SET_QUICK_STREAM, &on); + } } if (cif_dev->chip_id < CHIP_RK3588_CIF) diff --git a/drivers/media/platform/rockchip/cif/cif-scale.c b/drivers/media/platform/rockchip/cif/cif-scale.c index 7ea3404258f0..3beede6ee93f 100644 --- a/drivers/media/platform/rockchip/cif/cif-scale.c +++ b/drivers/media/platform/rockchip/cif/cif-scale.c @@ -364,8 +364,8 @@ static int rkcif_scale_enum_framesizes(struct file *file, void *prov, input_rect.height = RKCIF_DEFAULT_HEIGHT; if (terminal_sensor && terminal_sensor->sd) - get_input_fmt(terminal_sensor->sd, - &input_rect, 0, &csi_info); + rkcif_get_input_fmt(dev, + &input_rect, 0, &csi_info); switch (fsize->index) { case SCALE_8TIMES: diff --git a/drivers/media/platform/rockchip/cif/cif-tools.c b/drivers/media/platform/rockchip/cif/cif-tools.c index e3a676c04b4b..60103bf71402 100644 --- a/drivers/media/platform/rockchip/cif/cif-tools.c +++ b/drivers/media/platform/rockchip/cif/cif-tools.c @@ -300,8 +300,8 @@ static int rkcif_tools_enum_framesizes(struct file *file, void *prov, input_rect.height = RKCIF_DEFAULT_HEIGHT; if (terminal_sensor && terminal_sensor->sd) - get_input_fmt(terminal_sensor->sd, - &input_rect, 0, &csi_info); + rkcif_get_input_fmt(dev, + &input_rect, 0, &csi_info); fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; s->width = input_rect.width; diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index bd1b444f709e..f6a581727f92 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -1556,16 +1556,6 @@ static int subdev_notifier_complete(struct v4l2_async_notifier *notifier) if (!completion_done(&dev->cmpl_ntf)) complete(&dev->cmpl_ntf); - if (dev->active_sensor && - (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || - dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY)) { - ret = v4l2_subdev_call(dev->active_sensor->sd, - core, ioctl, - RKCIF_CMD_SET_CSI_IDX, - &dev->csi_host_idx); - if (ret) - v4l2_err(&dev->v4l2_dev, "set csi idx %d fail\n", dev->csi_host_idx); - } v4l2_info(&dev->v4l2_dev, "Async subdev notifier completed\n"); return ret; @@ -1924,6 +1914,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int cif_dev->early_line = 0; cif_dev->is_thunderboot = false; cif_dev->rdbk_debug = 0; + memset(&cif_dev->channels[0].capture_info, 0, sizeof(cif_dev->channels[0].capture_info)); if (cif_dev->chip_id == CHIP_RV1126_CIF_LITE) cif_dev->isr_hdl = rkcif_irq_lite_handler; @@ -1981,6 +1972,17 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int cif_dev->csi_host_idx = of_alias_get_id(node, "rkcif_mipi_lvds"); if (cif_dev->csi_host_idx < 0 || cif_dev->csi_host_idx > 5) cif_dev->csi_host_idx = 0; + if (cif_dev->hw_dev->is_rk3588s2) { + if (cif_dev->csi_host_idx == 0) + cif_dev->csi_host_idx = 2; + else if (cif_dev->csi_host_idx == 2) + cif_dev->csi_host_idx = 4; + else if (cif_dev->csi_host_idx == 3) + cif_dev->csi_host_idx = 5; + v4l2_info(&cif_dev->v4l2_dev, "rk3588s2 attach to mipi%d\n", + cif_dev->csi_host_idx); + } + cif_dev->csi_host_idx_def = cif_dev->csi_host_idx; cif_dev->media_dev.dev = dev; v4l2_dev = &cif_dev->v4l2_dev; v4l2_dev->mdev = &cif_dev->media_dev; @@ -2143,7 +2145,9 @@ static int rkcif_plat_probe(struct platform_device *pdev) if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp)) return -ENODEV; - rkcif_attach_hw(cif_dev); + ret = rkcif_attach_hw(cif_dev); + if (ret) + return ret; rkcif_parse_dts(cif_dev); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 8cdfab14fd27..b5d4c0315e8c 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -280,10 +280,12 @@ struct csi_channel_info { unsigned int width; unsigned int height; unsigned int virtual_width; + unsigned int left_virtual_width; unsigned int crop_st_x; unsigned int crop_st_y; unsigned int dsi_input; struct rkmodule_lvds_cfg lvds_cfg; + struct rkmodule_capture_info capture_info; }; struct rkcif_vdev_node { @@ -843,6 +845,7 @@ struct rkcif_device { struct rkcif_work_struct reset_work; int id_use_cnt; unsigned int csi_host_idx; + unsigned int csi_host_idx_def; unsigned int dvp_sof_in_oneframe; unsigned int wait_line; unsigned int wait_line_bak; @@ -885,7 +888,7 @@ void rkcif_vb_done_tasklet(struct rkcif_stream *stream, struct rkcif_buffer *buf int rkcif_scale_start(struct rkcif_scale_vdev *scale_vdev); const struct -cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd, +cif_input_fmt *rkcif_get_input_fmt(struct rkcif_device *dev, struct v4l2_rect *rect, u32 pad_id, struct csi_channel_info *csi_info); diff --git a/drivers/media/platform/rockchip/cif/hw.c b/drivers/media/platform/rockchip/cif/hw.c index 126be56186fb..b84db30b78be 100644 --- a/drivers/media/platform/rockchip/cif/hw.c +++ b/drivers/media/platform/rockchip/cif/hw.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -1252,6 +1253,51 @@ void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu) rkcif_iommu_enable(cif_hw); } +static int rkcif_get_efuse_value(struct device_node *np, char *porp_name, + u8 *value) +{ + struct nvmem_cell *cell; + unsigned char *buf; + size_t len; + + cell = of_nvmem_cell_get(np, porp_name); + if (IS_ERR(cell)) + return PTR_ERR(cell); + + buf = (unsigned char *)nvmem_cell_read(cell, &len); + + nvmem_cell_put(cell); + + if (IS_ERR(buf)) + return PTR_ERR(buf); + + *value = buf[0]; + + kfree(buf); + + return 0; +} + +static int rkcif_get_speciand_package_number(struct device_node *np) +{ + u8 spec = 0, package = 0, low = 0, high = 0; + + if (rkcif_get_efuse_value(np, "specification", &spec)) + return -EINVAL; + if (rkcif_get_efuse_value(np, "package_low", &low)) + return -EINVAL; + if (rkcif_get_efuse_value(np, "package_high", &high)) + return -EINVAL; + + package = ((high & 0x1) << 3) | low; + + /* RK3588S */ + if (spec == 0x13) + return package; + + return -EINVAL; +} + static int rkcif_plat_hw_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -1265,6 +1311,7 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) int i, ret, irq; bool is_mem_reserved = false; struct notifier_block *notifier; + int package = 0; match = of_match_node(rkcif_plat_of_match, node); if (IS_ERR(match)) @@ -1278,6 +1325,13 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) dev_set_drvdata(dev, cif_hw); cif_hw->dev = dev; + package = rkcif_get_speciand_package_number(node); + if (package == 0x2) { + cif_hw->is_rk3588s2 = true; + dev_info(dev, "attach rk3588s2\n"); + } else { + cif_hw->is_rk3588s2 = false; + } irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -1506,6 +1560,7 @@ int rk_cif_plat_drv_init(void) ret = platform_driver_register(&rkcif_hw_plat_drv); if (ret) return ret; + rkcif_csi2_hw_plat_drv_init(); return rkcif_csi2_plat_drv_init(); } @@ -1513,6 +1568,7 @@ static void __exit rk_cif_plat_drv_exit(void) { platform_driver_unregister(&rkcif_hw_plat_drv); rkcif_csi2_plat_drv_exit(); + rkcif_csi2_hw_plat_drv_exit(); } #if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) diff --git a/drivers/media/platform/rockchip/cif/hw.h b/drivers/media/platform/rockchip/cif/hw.h index 763041a33829..06ca088c4ce5 100644 --- a/drivers/media/platform/rockchip/cif/hw.h +++ b/drivers/media/platform/rockchip/cif/hw.h @@ -152,6 +152,7 @@ struct rkcif_hw { bool is_dma_contig; bool adapt_to_usbcamerahal; u64 irq_time; + bool is_rk3588s2; }; 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 d8622abf9ded..8081566d8d43 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.c +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.c @@ -13,12 +13,12 @@ #include #include #include +#include #include #include #include #include #include "mipi-csi2.h" -#include #include static int csi2_debug; @@ -129,47 +129,55 @@ static void csi2_update_sensor_info(struct csi2_dev *csi2) } -static void csi2_hw_do_reset(struct csi2_dev *csi2) +static void csi2_hw_do_reset(struct csi2_hw *csi2_hw) { - reset_control_assert(csi2->rsts_bulk); + + if (!csi2_hw->rsts_bulk) + return; + + reset_control_assert(csi2_hw->rsts_bulk); udelay(5); - reset_control_deassert(csi2->rsts_bulk); + reset_control_deassert(csi2_hw->rsts_bulk); } -static int csi2_enable_clks(struct csi2_dev *csi2) +static int csi2_enable_clks(struct csi2_hw *csi2_hw) { int ret = 0; - ret = clk_bulk_prepare_enable(csi2->clks_num, csi2->clks_bulk); + if (!csi2_hw->clks_bulk) + return -EINVAL; + + ret = clk_bulk_prepare_enable(csi2_hw->clks_num, csi2_hw->clks_bulk); if (ret) - dev_err(csi2->dev, "failed to enable clks\n"); + dev_err(csi2_hw->dev, "failed to enable clks\n"); return ret; } -static void csi2_disable_clks(struct csi2_dev *csi2) +static void csi2_disable_clks(struct csi2_hw *csi2_hw) { - clk_bulk_disable_unprepare(csi2->clks_num, csi2->clks_bulk); + if (!csi2_hw->clks_bulk) + return; + clk_bulk_disable_unprepare(csi2_hw->clks_num, csi2_hw->clks_bulk); } -static void csi2_disable(struct csi2_dev *csi2) +static void csi2_disable(struct csi2_hw *csi2_hw) { - void __iomem *base = csi2->base; - - write_csihost_reg(base, CSIHOST_RESETN, 0); - write_csihost_reg(base, CSIHOST_MSK1, 0xffffffff); - write_csihost_reg(base, CSIHOST_MSK2, 0xffffffff); + write_csihost_reg(csi2_hw->base, CSIHOST_RESETN, 0); + write_csihost_reg(csi2_hw->base, CSIHOST_MSK1, 0xffffffff); + write_csihost_reg(csi2_hw->base, CSIHOST_MSK2, 0xffffffff); } static int csi2_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, struct v4l2_mbus_config *mbus); -static void csi2_enable(struct csi2_dev *csi2, +static void csi2_enable(struct csi2_hw *csi2_hw, enum host_type_t host_type) { - void __iomem *base = csi2->base; + void __iomem *base = csi2_hw->base; + struct csi2_dev *csi2 = csi2_hw->csi2; int lanes = csi2->bus.num_data_lanes; struct v4l2_mbus_config mbus; u32 val = 0; @@ -207,16 +215,10 @@ static int csi2_start(struct csi2_dev *csi2) { enum host_type_t host_type; int ret, i; + int csi_idx = 0; atomic_set(&csi2->frm_sync_seq, 0); - csi2_hw_do_reset(csi2); - ret = csi2_enable_clks(csi2); - if (ret) { - v4l2_err(&csi2->sd, "%s: enable clks failed\n", __func__); - return ret; - } - csi2_update_sensor_info(csi2); if (csi2->dsi_input_en == RKMODULE_DSI_INPUT) @@ -224,7 +226,16 @@ static int csi2_start(struct csi2_dev *csi2) else host_type = RK_CSI_RXHOST; - csi2_enable(csi2, host_type); + for (i = 0; i < csi2->csi_info.csi_num; i++) { + csi_idx = csi2->csi_info.csi_idx[i]; + csi2_hw_do_reset(csi2->csi2_hw[csi_idx]); + ret = csi2_enable_clks(csi2->csi2_hw[csi_idx]); + if (ret) { + v4l2_err(&csi2->sd, "%s: enable clks failed\n", __func__); + return ret; + } + csi2_enable(csi2->csi2_hw[csi_idx], host_type); + } pr_debug("stream sd: %s\n", csi2->src_sd->name); ret = v4l2_subdev_call(csi2->src_sd, video, s_stream, 1); @@ -238,20 +249,29 @@ static int csi2_start(struct csi2_dev *csi2) return 0; err_assert_reset: - csi2_disable(csi2); - csi2_disable_clks(csi2); + for (i = 0; i < csi2->csi_info.csi_num; i++) { + csi_idx = csi2->csi_info.csi_idx[i]; + csi2_disable(csi2->csi2_hw[csi_idx]); + csi2_disable_clks(csi2->csi2_hw[csi_idx]); + } return ret; } static void csi2_stop(struct csi2_dev *csi2) { + int i = 0; + int csi_idx = 0; + /* stop upstream */ v4l2_subdev_call(csi2->src_sd, video, s_stream, 0); - csi2_disable(csi2); - csi2_hw_do_reset(csi2); - csi2_disable_clks(csi2); + for (i = 0; i < csi2->csi_info.csi_num; i++) { + csi_idx = csi2->csi_info.csi_idx[i]; + csi2_disable(csi2->csi2_hw[csi_idx]); + csi2_hw_do_reset(csi2->csi2_hw[csi_idx]); + csi2_disable_clks(csi2->csi2_hw[csi_idx]); + } } /* @@ -361,7 +381,6 @@ static int csi2_media_init(struct v4l2_subdev *sd) csi2->crop.left = 0; csi2->crop.width = RKCIF_DEFAULT_WIDTH; csi2->crop.height = RKCIF_DEFAULT_HEIGHT; - csi2->csi_idx = 0; return media_entity_pads_init(&sd->entity, num_pads, csi2->pad); } @@ -549,11 +568,19 @@ static int rkcif_csi2_s_power(struct v4l2_subdev *sd, int on) static long rkcif_csi2_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct csi2_dev *csi2 = sd_to_dev(sd); + struct v4l2_subdev *sensor = get_remote_sensor(sd); long ret = 0; + int i = 0; switch (cmd) { case RKCIF_CMD_SET_CSI_IDX: - csi2->csi_idx = *((u32 *)arg); + csi2->csi_info = *((struct rkcif_csi_info *)arg); + for (i = 0; i < csi2->csi_info.csi_num; i++) + csi2->csi2_hw[csi2->csi_info.csi_idx[i]]->csi2 = csi2; + if (csi2->match_data->chip_id > CHIP_RV1126_CSI2) + ret = v4l2_subdev_call(sensor, core, ioctl, + RKCIF_CMD_SET_CSI_IDX, + arg); break; default: ret = -ENOIOCTLCMD; @@ -568,15 +595,15 @@ static long rkcif_csi2_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg) { void __user *up = compat_ptr(arg); - u32 csi_idx = 0; + struct rkcif_csi_info csi_info; long ret; switch (cmd) { case RKCIF_CMD_SET_CSI_IDX: - if (copy_from_user(&csi_idx, up, sizeof(u32))) + if (copy_from_user(&csi_info, up, sizeof(struct rkcif_csi_info))) return -EFAULT; - ret = rkcif_csi2_ioctl(sd, cmd, &csi_idx); + ret = rkcif_csi2_ioctl(sd, cmd, &csi_info); break; default: ret = -ENOIOCTLCMD; @@ -721,7 +748,8 @@ static void csi2_find_err_vc(int val, char *vc_info) static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) { struct device *dev = ctx; - struct csi2_dev *csi2 = sd_to_dev(dev_get_drvdata(dev)); + struct csi2_hw *csi2_hw = dev_get_drvdata(dev); + struct csi2_dev *csi2 = csi2_hw->csi2; struct csi2_err_stats *err_list = NULL; unsigned long err_stat = 0; u32 val; @@ -730,7 +758,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) char vc_info[CSI_VCINFO_LEN] = {0}; bool is_add_cnt = false; - val = read_csihost_reg(csi2->base, CSIHOST_ERR1); + val = read_csihost_reg(csi2_hw->base, CSIHOST_ERR1); if (val) { if (val & CSIHOST_ERR1_PHYERR_SPTSYNCHS) { err_list = &csi2->err_list[RK_CSI2_ERR_SOTSYN]; @@ -739,7 +767,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) if (err_list->cnt > 3 && csi2->err_list[RK_CSI2_ERR_ALL].cnt <= err_list->cnt) { csi2->is_check_sot_sync = false; - write_csihost_reg(csi2->base, CSIHOST_MSK1, 0xf); + write_csihost_reg(csi2_hw->base, CSIHOST_MSK1, 0xf); } if (csi2->is_check_sot_sync) { csi2_find_err_vc(val & 0xf, vc_info); @@ -804,7 +832,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->dev_name, val, err_str); + pr_err("%s ERR1:0x%x %s\n", csi2_hw->dev_name, val, err_str); if (is_add_cnt) { csi2->err_list[RK_CSI2_ERR_ALL].cnt++; @@ -813,7 +841,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) atomic_notifier_call_chain(&g_csi_host_chain, err_stat, - &csi2->csi_idx); + &csi2->csi_info.csi_idx[csi2->csi_info.csi_num - 1]); } } @@ -824,13 +852,13 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx) { struct device *dev = ctx; - struct csi2_dev *csi2 = sd_to_dev(dev_get_drvdata(dev)); + struct csi2_hw *csi2_hw = dev_get_drvdata(dev); u32 val; char cur_str[CSI_ERRSTR_LEN] = {0}; char err_str[CSI_ERRSTR_LEN] = {0}; char vc_info[CSI_VCINFO_LEN] = {0}; - val = read_csihost_reg(csi2->base, CSIHOST_ERR2); + val = read_csihost_reg(csi2_hw->base, CSIHOST_ERR2); if (val) { if (val & CSIHOST_ERR2_PHYERR_ESC) { csi2_find_err_vc(val & 0xf, vc_info); @@ -857,7 +885,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->dev_name, val, err_str); + pr_err("%s ERR2:0x%x %s\n", csi2_hw->dev_name, val, err_str); } return IRQ_HANDLED; @@ -896,31 +924,43 @@ static int csi2_notifier(struct csi2_dev *csi2) static const struct csi2_match_data rk1808_csi2_match_data = { .chip_id = CHIP_RK1808_CSI2, .num_pads = CSI2_NUM_PADS, + .num_hw = 1, }; static const struct csi2_match_data rk3288_csi2_match_data = { .chip_id = CHIP_RK3288_CSI2, .num_pads = CSI2_NUM_PADS_SINGLE_LINK, + .num_hw = 1, }; static const struct csi2_match_data rv1126_csi2_match_data = { .chip_id = CHIP_RV1126_CSI2, .num_pads = CSI2_NUM_PADS, + .num_hw = 1, }; static const struct csi2_match_data rk3568_csi2_match_data = { .chip_id = CHIP_RK3568_CSI2, .num_pads = CSI2_NUM_PADS, + .num_hw = 1, }; static const struct csi2_match_data rk3588_csi2_match_data = { .chip_id = CHIP_RK3588_CSI2, .num_pads = CSI2_NUM_PADS_MAX, + .num_hw = 6, +}; + +static const struct csi2_match_data rv1106_csi2_match_data = { + .chip_id = CHIP_RV1106_CSI2, + .num_pads = CSI2_NUM_PADS_MAX, + .num_hw = 2, }; static const struct csi2_match_data rk3562_csi2_match_data = { .chip_id = CHIP_RK3562_CSI2, .num_pads = CSI2_NUM_PADS_MAX, + .num_hw = 4, }; static const struct of_device_id csi2_dt_ids[] = { @@ -944,6 +984,10 @@ static const struct of_device_id csi2_dt_ids[] = { .compatible = "rockchip,rk3588-mipi-csi2", .data = &rk3588_csi2_match_data, }, + { + .compatible = "rockchip,rv1106-mipi-csi2", + .data = &rv1106_csi2_match_data, + }, { .compatible = "rockchip,rk3562-mipi-csi2", .data = &rk3562_csi2_match_data, @@ -952,15 +996,48 @@ static const struct of_device_id csi2_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, csi2_dt_ids); +static int csi2_attach_hw(struct csi2_dev *csi2) +{ + struct device_node *np; + struct platform_device *pdev; + struct csi2_hw *hw; + int i = 0; + + for (i = 0; i < csi2->match_data->num_hw; i++) { + np = of_parse_phandle(csi2->dev->of_node, "rockchip,hw", i); + if (!np || !of_device_is_available(np)) { + dev_err(csi2->dev, "failed to get csi2 hw node\n"); + return -ENODEV; + } + + pdev = of_find_device_by_node(np); + of_node_put(np); + if (!pdev) { + dev_err(csi2->dev, "failed to get csi2 hw from node\n"); + return -ENODEV; + } + + hw = platform_get_drvdata(pdev); + if (!hw) { + dev_err(csi2->dev, "failed attach csi2 hw\n"); + return -EINVAL; + } + + hw->csi2 = csi2; + csi2->csi2_hw[i] = hw; + } + dev_info(csi2->dev, "attach to csi2 hw node\n"); + + return 0; +} + static int csi2_probe(struct platform_device *pdev) { const struct of_device_id *match; - struct device *dev = &pdev->dev; struct device_node *node = pdev->dev.of_node; struct csi2_dev *csi2 = NULL; - struct resource *res; const struct csi2_match_data *data; - int ret, irq; + int ret; match = of_match_node(csi2_dt_ids, node); if (IS_ERR(match)) @@ -986,63 +1063,11 @@ static int csi2_probe(struct platform_device *pdev) v4l2_err(&csi2->sd, "failed to copy name\n"); platform_set_drvdata(pdev, &csi2->sd); - csi2->clks_num = devm_clk_bulk_get_all(dev, &csi2->clks_bulk); - if (csi2->clks_num < 0) { - csi2->clks_num = 0; - dev_err(dev, "failed to get csi2 clks\n"); + ret = csi2_attach_hw(csi2); + if (ret) { + v4l2_err(&csi2->sd, "must enable all mipi csi2 hw node\n"); + return -EINVAL; } - - csi2->rsts_bulk = devm_reset_control_array_get_optional_exclusive(dev); - if (IS_ERR(csi2->rsts_bulk)) { - if (PTR_ERR(csi2->rsts_bulk) != -EPROBE_DEFER) - dev_err(dev, "failed to get csi2 reset\n"); - csi2->rsts_bulk = NULL; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - csi2->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(csi2->base)) { - resource_size_t offset = res->start; - resource_size_t size = resource_size(res); - - dev_warn(&pdev->dev, "avoid secondary mipi resource check!\n"); - - csi2->base = devm_ioremap(&pdev->dev, offset, size); - if (IS_ERR(csi2->base)) { - dev_err(&pdev->dev, "Failed to ioremap resource\n"); - - return PTR_ERR(csi2->base); - } - } - - irq = platform_get_irq_byname(pdev, "csi-intr1"); - if (irq > 0) { - ret = devm_request_irq(&pdev->dev, irq, - rk_csirx_irq1_handler, 0, - dev_driver_string(&pdev->dev), - &pdev->dev); - if (ret < 0) - v4l2_err(&csi2->sd, "request csi-intr1 irq failed: %d\n", - ret); - csi2->irq1 = irq; - } else { - v4l2_err(&csi2->sd, "No found irq csi-intr1\n"); - } - - irq = platform_get_irq_byname(pdev, "csi-intr2"); - if (irq > 0) { - ret = devm_request_irq(&pdev->dev, irq, - rk_csirx_irq2_handler, 0, - dev_driver_string(&pdev->dev), - &pdev->dev); - if (ret < 0) - v4l2_err(&csi2->sd, "request csi-intr2 failed: %d\n", - ret); - csi2->irq2 = irq; - } else { - v4l2_err(&csi2->sd, "No found irq csi-intr2\n"); - } - mutex_init(&csi2->lock); ret = csi2_media_init(&csi2->sd); @@ -1087,11 +1112,183 @@ int rkcif_csi2_plat_drv_init(void) return platform_driver_register(&csi2_driver); } -void __exit rkcif_csi2_plat_drv_exit(void) +void rkcif_csi2_plat_drv_exit(void) { platform_driver_unregister(&csi2_driver); } +static const struct csi2_hw_match_data rk1808_csi2_hw_match_data = { + .chip_id = CHIP_RK1808_CSI2, +}; + +static const struct csi2_hw_match_data rk3288_csi2_hw_match_data = { + .chip_id = CHIP_RK3288_CSI2, +}; + +static const struct csi2_hw_match_data rv1126_csi2_hw_match_data = { + .chip_id = CHIP_RV1126_CSI2, +}; + +static const struct csi2_hw_match_data rk3568_csi2_hw_match_data = { + .chip_id = CHIP_RK3568_CSI2, +}; + +static const struct csi2_hw_match_data rk3588_csi2_hw_match_data = { + .chip_id = CHIP_RK3588_CSI2, +}; + +static const struct csi2_hw_match_data rv1106_csi2_hw_match_data = { + .chip_id = CHIP_RV1106_CSI2, +}; + +static const struct csi2_hw_match_data rk3562_csi2_hw_match_data = { + .chip_id = CHIP_RK3562_CSI2, +}; + +static const struct of_device_id csi2_hw_ids[] = { + { + .compatible = "rockchip,rk1808-mipi-csi2-hw", + .data = &rk1808_csi2_hw_match_data, + }, + { + .compatible = "rockchip,rk3288-mipi-csi2-hw", + .data = &rk3288_csi2_hw_match_data, + }, + { + .compatible = "rockchip,rk3568-mipi-csi2-hw", + .data = &rk3568_csi2_hw_match_data, + }, + { + .compatible = "rockchip,rv1126-mipi-csi2-hw", + .data = &rv1126_csi2_hw_match_data, + }, + { + .compatible = "rockchip,rk3588-mipi-csi2-hw", + .data = &rk3588_csi2_hw_match_data, + }, + { + .compatible = "rockchip,rv1106-mipi-csi2-hw", + .data = &rv1106_csi2_hw_match_data, + }, + { + .compatible = "rockchip,rk3562-mipi-csi2-hw", + .data = &rk3588_csi2_hw_match_data, + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, csi2_hw_ids); + +static int csi2_hw_probe(struct platform_device *pdev) +{ + const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct device_node *node = pdev->dev.of_node; + struct csi2_hw *csi2_hw = NULL; + struct resource *res; + const struct csi2_hw_match_data *data; + int ret, irq; + + dev_info(&pdev->dev, "enter mipi csi2 hw probe!\n"); + match = of_match_node(csi2_hw_ids, node); + if (IS_ERR(match)) + return PTR_ERR(match); + data = match->data; + + csi2_hw = devm_kzalloc(&pdev->dev, sizeof(*csi2_hw), GFP_KERNEL); + if (!csi2_hw) + return -ENOMEM; + + csi2_hw->dev = &pdev->dev; + csi2_hw->match_data = data; + + csi2_hw->dev_name = node->name; + + csi2_hw->clks_num = devm_clk_bulk_get_all(dev, &csi2_hw->clks_bulk); + if (csi2_hw->clks_num < 0) { + csi2_hw->clks_num = 0; + dev_err(dev, "failed to get csi2 clks\n"); + } + + csi2_hw->rsts_bulk = devm_reset_control_array_get_optional_exclusive(dev); + if (IS_ERR(csi2_hw->rsts_bulk)) { + if (PTR_ERR(csi2_hw->rsts_bulk) != -EPROBE_DEFER) + dev_err(dev, "failed to get csi2 reset\n"); + csi2_hw->rsts_bulk = NULL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + csi2_hw->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(csi2_hw->base)) { + resource_size_t offset = res->start; + resource_size_t size = resource_size(res); + + dev_warn(&pdev->dev, "avoid secondary mipi resource check!\n"); + + csi2_hw->base = devm_ioremap(&pdev->dev, offset, size); + if (IS_ERR(csi2_hw->base)) { + dev_err(&pdev->dev, "Failed to ioremap resource\n"); + + return PTR_ERR(csi2_hw->base); + } + } + + irq = platform_get_irq_byname(pdev, "csi-intr1"); + if (irq > 0) { + ret = devm_request_irq(&pdev->dev, irq, + rk_csirx_irq1_handler, 0, + dev_driver_string(&pdev->dev), + &pdev->dev); + if (ret < 0) + dev_err(&pdev->dev, "request csi-intr1 irq failed: %d\n", + ret); + csi2_hw->irq1 = irq; + } else { + dev_err(&pdev->dev, "No found irq csi-intr1\n"); + } + + irq = platform_get_irq_byname(pdev, "csi-intr2"); + if (irq > 0) { + ret = devm_request_irq(&pdev->dev, irq, + rk_csirx_irq2_handler, 0, + dev_driver_string(&pdev->dev), + &pdev->dev); + if (ret < 0) + dev_err(&pdev->dev, "request csi-intr2 failed: %d\n", + ret); + csi2_hw->irq2 = irq; + } else { + dev_err(&pdev->dev, "No found irq csi-intr2\n"); + } + platform_set_drvdata(pdev, csi2_hw); + dev_info(&pdev->dev, "probe success, v4l2_dev:%s!\n", csi2_hw->dev_name); + + return 0; +} + +static int csi2_hw_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver csi2_hw_driver = { + .driver = { + .name = DEVICE_NAME_HW, + .of_match_table = csi2_hw_ids, + }, + .probe = csi2_hw_probe, + .remove = csi2_hw_remove, +}; + +int rkcif_csi2_hw_plat_drv_init(void) +{ + return platform_driver_register(&csi2_hw_driver); +} + +void rkcif_csi2_hw_plat_drv_exit(void) +{ + platform_driver_unregister(&csi2_hw_driver); +} + MODULE_DESCRIPTION("Rockchip MIPI CSI2 driver"); MODULE_AUTHOR("Macrofly.xu "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.h b/drivers/media/platform/rockchip/cif/mipi-csi2.h index 944e683623f7..3306c53d1336 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.h +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.h @@ -8,6 +8,7 @@ #include #include #include +#include #define CSI2_ERR_FSFE_MASK (0xff << 8) #define CSI2_ERR_COUNT_ALL_MASK (0xff) @@ -42,6 +43,7 @@ #define CSIHOST_MAX_ERRINT_COUNT 10 #define DEVICE_NAME "rockchip-mipi-csi2" +#define DEVICE_NAME_HW "rockchip-mipi-csi2-hw" /* CSI Host Registers Define */ #define CSIHOST_N_LANES 0x04 @@ -76,6 +78,8 @@ #define SW_DATATYPE_LS(x) ((x) << 20) #define SW_DATATYPE_LE(x) ((x) << 26) +#define RK_MAX_CSI_HW (6) + /* * add new chip id in tail in time order * by increasing to distinguish csi2 host version @@ -88,6 +92,7 @@ enum rkcsi2_chip_id { CHIP_RV1126_CSI2, CHIP_RK3568_CSI2, CHIP_RK3588_CSI2, + CHIP_RV1106_CSI2, CHIP_RK3562_CSI2, }; @@ -117,6 +122,11 @@ enum host_type_t { struct csi2_match_data { int chip_id; int num_pads; + int num_hw; +}; + +struct csi2_hw_match_data { + int chip_id; }; struct csi2_sensor_info { @@ -155,10 +165,29 @@ struct csi2_dev { int num_sensors; atomic_t frm_sync_seq; struct csi2_err_stats err_list[RK_CSI2_ERR_MAX]; + struct csi2_hw *csi2_hw[RK_MAX_CSI_HW]; int irq1; int irq2; int dsi_input_en; - u32 csi_idx; + struct rkcif_csi_info csi_info; + const char *dev_name; +}; + +struct csi2_hw { + struct device *dev; + struct clk_bulk_data *clks_bulk; + int clks_num; + struct reset_control *rsts_bulk; + struct csi2_dev *csi2; + const struct csi2_hw_match_data *match_data; + + void __iomem *base; + + /* lock to protect all members below */ + struct mutex lock; + + int irq1; + int irq2; const char *dev_name; }; @@ -166,7 +195,9 @@ u32 rkcif_csi2_get_sof(struct csi2_dev *csi2_dev); void rkcif_csi2_set_sof(struct csi2_dev *csi2_dev, u32 seq); void rkcif_csi2_event_inc_sof(struct csi2_dev *csi2_dev); int rkcif_csi2_plat_drv_init(void); -void __exit rkcif_csi2_plat_drv_exit(void); +void rkcif_csi2_plat_drv_exit(void); +int rkcif_csi2_hw_plat_drv_init(void); +void rkcif_csi2_hw_plat_drv_exit(void); int rkcif_csi2_register_notifier(struct notifier_block *nb); int rkcif_csi2_unregister_notifier(struct notifier_block *nb); void rkcif_csi2_event_reset_pipe(struct csi2_dev *csi2_dev, int reset_src); diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 5c1d8cbd0ede..16a8acb659d5 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -337,7 +337,10 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) mode = (struct rkisp_vicap_mode *)arg; memcpy(&priv->mode, mode, sizeof(*mode)); sditf_reinit_mode(priv, &priv->mode); - mode->input.merge_num = cif_dev->sditf_cnt; + if (priv->is_combine_mode) + mode->input.merge_num = cif_dev->sditf_cnt; + else + mode->input.merge_num = 1; mode->input.index = priv->combine_index; return 0; case RKISP_VICAP_CMD_INIT_BUF: @@ -425,6 +428,7 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd, static int sditf_channel_enable(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_val = 0; unsigned int int_en = 0; @@ -432,11 +436,25 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) 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; + + 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 = cif_dev->csi_host_idx * 4; + ch0 = csi_idx * 4; else ch0 = 24;//dvp ctrl_val = (ch0 << 3) | 0x1; @@ -491,7 +509,10 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) } } else { if (priv->toisp_inf.link_mode == TOISP_UNITE) { - offset_x = priv->cap_info.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL; + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) + offset_x = 0; + else + offset_x = priv->cap_info.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL; width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; } rkcif_write_register(cif_dev, CIF_REG_TOISP1_CTRL, ctrl_val); diff --git a/drivers/media/platform/rockchip/cif/version.h b/drivers/media/platform/rockchip/cif/version.h index 627b4a3a11e5..dbebed0ca0ef 100644 --- a/drivers/media/platform/rockchip/cif/version.h +++ b/drivers/media/platform/rockchip/cif/version.h @@ -67,6 +67,8 @@ *7. add keepint time to csi2 err for resetting *8. mipi supports pdaf/embedded data *9. mipi supports interlaced capture + *v0.2.0 + *1. vicap support combine multi mipi dev to one dev, this function is mainly used for rk3588 */ #define RKCIF_DRIVER_VERSION RKCIF_API_VERSION