static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
int channel_id)
{
struct rkcif_device *dev = stream->cifdev;
struct rkcif_dummy_buffer *dummy_buf = &dev->dummy_buf;
struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
struct rkcif_buffer *buffer = NULL;
u32 frm_addr_y, frm_addr_uv;
struct csi_channel_info *channel = &dev->channels[channel_id];
int ret = 0;
unsigned long flags;
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
mbus_cfg->type == V4L2_MBUS_CCP2) {
frm_addr_y = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_reg_index_of_frm0_y_addr(channel_id) :
get_reg_index_of_frm1_y_addr(channel_id);
frm_addr_uv = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_reg_index_of_frm0_uv_addr(channel_id) :
get_reg_index_of_frm1_uv_addr(channel_id);
} else {
frm_addr_y = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_dvp_reg_index_of_frm0_y_addr(channel_id) :
get_dvp_reg_index_of_frm1_y_addr(channel_id);
frm_addr_uv = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_dvp_reg_index_of_frm0_uv_addr(channel_id) :
get_dvp_reg_index_of_frm1_uv_addr(channel_id);
}
spin_lock_irqsave(&stream->vbq_lock, flags);
if (!list_empty(&stream->buf_head)) {
if (!dummy_buf->vaddr &&
stream->curr_buf == stream->next_buf &&
stream->cif_fmt_in->field != V4L2_FIELD_INTERLACED)
ret = -EINVAL;
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf = list_first_entry(&stream->buf_head,
struct rkcif_buffer, queue);
if (stream->curr_buf) {
list_del(&stream->curr_buf->queue);
buffer = stream->curr_buf;
}
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (stream->next_buf != stream->curr_buf) {
stream->next_buf = stream->curr_buf;
buffer = stream->next_buf;
} else {
buffer = NULL;
}
} else {
stream->next_buf = list_first_entry(&stream->buf_head,
struct rkcif_buffer, queue);
if (stream->next_buf) {
list_del(&stream->next_buf->queue);
buffer = stream->next_buf;
}
}
}
} else {
buffer = NULL;
if (dummy_buf->vaddr) {
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf = NULL;
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
stream->next_buf = stream->curr_buf;
buffer = stream->next_buf;
} else {
stream->next_buf = NULL;
}
}
} else if (stream->curr_buf != stream->next_buf) {
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf = stream->next_buf;
buffer = stream->next_buf;
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
stream->next_buf = stream->curr_buf;
buffer = stream->curr_buf;
}
}
}
stream->frame_phase_cache = stream->frame_phase;
spin_unlock_irqrestore(&stream->vbq_lock, flags);
if (buffer) {
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));
} 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]);
}
} 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);
} else {
ret = -EINVAL;
}
v4l2_info(&dev->v4l2_dev,
"not active buffer, skip current frame, %s stream[%d]\n",
(mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
mbus_cfg->type == V4L2_MBUS_CCP2) ? "mipi/lvds" : "dvp",
stream->id);
}
return ret;
}解读这两段代码区别static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
int channel_id)
{
struct rkcif_device *dev = stream->cifdev;
struct rkcif_dummy_buffer *dummy_buf = &dev->dummy_buf;
struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
struct rkcif_buffer *buffer = NULL;
u32 frm_addr_y, frm_addr_uv;
struct csi_channel_info *channel = &dev->channels[channel_id];
struct rkisp_rx_buf *dbufs = NULL;
struct dma_buf *dbuf = NULL;
int ret = 0;
unsigned long flags;
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
mbus_cfg->type == V4L2_MBUS_CCP2) {
frm_addr_y = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_reg_index_of_frm0_y_addr(channel_id) :
get_reg_index_of_frm1_y_addr(channel_id);
frm_addr_uv = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_reg_index_of_frm0_uv_addr(channel_id) :
get_reg_index_of_frm1_uv_addr(channel_id);
} else {
frm_addr_y = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_dvp_reg_index_of_frm0_y_addr(channel_id) :
get_dvp_reg_index_of_frm1_y_addr(channel_id);
frm_addr_uv = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_dvp_reg_index_of_frm0_uv_addr(channel_id) :
get_dvp_reg_index_of_frm1_uv_addr(channel_id);
}
if (dev->hdr.hdr_mode != NO_HDR && stream->id != 0 && (!dev->rdbk_buf[RDBK_L]))
return -EINVAL;
if (stream->to_stop_dma) {
if (stream->dma_en & RKCIF_DMAEN_BY_ISP)
goto stop_dma;
else
return -EINVAL;
}
spin_lock_irqsave(&stream->vbq_lock, flags);
if (!list_empty(&stream->buf_head)) {
if (!dummy_buf->vaddr &&
stream->curr_buf == stream->next_buf &&
stream->cif_fmt_in->field != V4L2_FIELD_INTERLACED)
ret = -EINVAL;
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
if (!stream->curr_buf)
ret = -EINVAL;
stream->curr_buf = list_first_entry(&stream->buf_head,
struct rkcif_buffer, queue);
if (stream->curr_buf) {
list_del(&stream->curr_buf->queue);
buffer = stream->curr_buf;
}
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (!stream->next_buf)
ret = -EINVAL;
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (stream->next_buf != stream->curr_buf) {
stream->next_buf = stream->curr_buf;
buffer = stream->next_buf;
} else {
buffer = NULL;
}
} else {
stream->next_buf = list_first_entry(&stream->buf_head,
struct rkcif_buffer, queue);
if (stream->next_buf) {
list_del(&stream->next_buf->queue);
buffer = stream->next_buf;
}
}
}
} else if (!(stream->dma_en & RKCIF_DMAEN_BY_ISP)) {
buffer = NULL;
if (dummy_buf->vaddr) {
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf = NULL;
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
stream->next_buf = stream->curr_buf;
buffer = stream->next_buf;
} else {
stream->next_buf = NULL;
}
}
} else if (stream->curr_buf && stream->next_buf &&
stream->curr_buf != stream->next_buf) {
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf = stream->next_buf;
buffer = stream->next_buf;
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
stream->next_buf = stream->curr_buf;
buffer = stream->curr_buf;
}
if (stream->lack_buf_cnt < 2)
stream->lack_buf_cnt++;
} else {
if (stream->lack_buf_cnt < 2)
stream->lack_buf_cnt++;
}
}
stream->frame_phase_cache = stream->frame_phase;
if (buffer) {
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));
} 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 (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
if (stream->buf_replace_cnt < 2)
stream->buf_replace_cnt++;
if (stream->frame_phase == CIF_CSI_FRAME0_READY &&
stream->next_buf)
dbuf = stream->next_buf->dbuf;
else if (stream->frame_phase == CIF_CSI_FRAME1_READY &&
stream->curr_buf)
dbuf = stream->curr_buf->dbuf;
if (dbuf) {
list_for_each_entry(dbufs, &stream->rx_buf_head_vicap, list)
if (dbufs->dbuf == dbuf)
break;
} else {
dbufs = &stream->curr_buf_toisp->dbufs;
}
rkcif_s_rx_buffer(dev, dbufs);
stream->buf_num_toisp--;
}
} else {
if (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
rkcif_write_register(dev, frm_addr_y,
stream->curr_buf_toisp->dummy.dma_addr);
if (stream->frame_phase == CIF_CSI_FRAME0_READY &&
stream->next_buf)
dbuf = stream->next_buf->dbuf;
else if (stream->frame_phase == CIF_CSI_FRAME1_READY &&
stream->curr_buf)
dbuf = stream->curr_buf->dbuf;
if (dbuf) {
list_for_each_entry(dbufs, &stream->rx_buf_head_vicap, list)
if (dbufs->dbuf == dbuf)
break;
} else {
dbufs = &stream->curr_buf_toisp->dbufs;
}
rkcif_s_rx_buffer(dev, dbufs);
stream->buf_num_toisp--;
if (stream->curr_buf && stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf = NULL;
if (stream->buf_replace_cnt)
stream->buf_replace_cnt--;
} else if (stream->next_buf && stream->frame_phase == CIF_CSI_FRAME1_READY) {
stream->next_buf = NULL;
if (stream->buf_replace_cnt)
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);
v4l2_info(&dev->v4l2_dev,
"not active buffer, use dummy buffer, %s stream[%d]\n",
(mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
mbus_cfg->type == V4L2_MBUS_CCP2) ? "mipi/lvds" : "dvp",
stream->id);
} else {
ret = -EINVAL;
v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev,
"not active buffer, lack_buf_cnt %d, stop capture, %s stream[%d]\n",
stream->lack_buf_cnt,
(mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
mbus_cfg->type == V4L2_MBUS_CCP2) ? "mipi/lvds" : "dvp",
stream->id);
}
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
return ret;
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);
if (stream->frame_phase == CIF_CSI_FRAME0_READY &&
stream->next_buf)
dbuf = stream->next_buf->dbuf;
else if (stream->frame_phase == CIF_CSI_FRAME1_READY &&
stream->curr_buf)
dbuf = stream->curr_buf->dbuf;
if (dbuf) {
list_for_each_entry(dbufs, &stream->rx_buf_head_vicap, list)
if (dbufs->dbuf == dbuf)
break;
} else {
dbufs = &stream->curr_buf_toisp->dbufs;
}
rkcif_s_rx_buffer(dev, dbufs);
stream->buf_num_toisp--;
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
stream->curr_buf = NULL;
} else {
list_add_tail(&stream->next_buf->queue, &stream->buf_head);
stream->next_buf = NULL;
}
stream->buf_replace_cnt--;
spin_unlock_irqrestore(&stream->vbq_lock, flags);
}
return -EINVAL;
}
最新发布