ccp用户态驱动

本文详细解析了Linux内核Git仓库中的一次提交,ID为aa017ab97a223d55f4955e2864daf7a05ba1f8a2,由Linus Torvalds发起。这次提交可能涉及内核的多个方面,包括但不限于文件系统优化、设备驱动更新或网络协议改进。

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=aa017ab97a223d55f4955e2864daf7a05ba1f8a2

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; }
最新发布
12-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值