media: rockchip: cif supports dummy buffer configurable

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: Icc62c1324affd65934872dfb7c1d29f15e28bb3b
This commit is contained in:
Zefa Chen
2021-08-12 19:51:17 +08:00
parent d3556d4c45
commit 95bfb5ca3a
5 changed files with 186 additions and 27 deletions

View File

@@ -24,3 +24,17 @@ config ROCKCHIP_CIF_WORKMODE_ONEFRAME
bool "interface works in oneframe mode"
endchoice
choice
prompt "rockchip rkcif device dummy buffer choice"
depends on VIDEO_ROCKCHIP_CIF
default ROCKCHIP_CIF_USE_DUMMY_BUF
config ROCKCHIP_CIF_USE_DUMMY_BUF
bool "rkcif use dummy buffer"
config ROCKCHIP_CIF_USE_NONE_DUMMY_BUF
bool "rkcif not use dummy buffer"
endchoice

View File

@@ -1162,6 +1162,7 @@ static int rkcif_assign_new_buffer_oneframe(struct rkcif_stream *stream,
enum rkcif_yuvaddr_state stat)
{
struct rkcif_device *dev = stream->cifdev;
struct rkcif_dummy_buffer *dummy_buf = &dev->dummy_buf;
struct rkcif_buffer *buffer = NULL;
u32 frm_addr_y = CIF_REG_DVP_FRM0_ADDR_Y;
u32 frm_addr_uv = CIF_REG_DVP_FRM0_ADDR_UV;
@@ -1184,6 +1185,13 @@ static int rkcif_assign_new_buffer_oneframe(struct rkcif_stream *stream,
stream->curr_buf->buff_addr[RKCIF_PLANE_Y]);
rkcif_write_register(dev, CIF_REG_DVP_FRM0_ADDR_UV,
stream->curr_buf->buff_addr[RKCIF_PLANE_CBCR]);
} else {
if (dummy_buf->vaddr) {
rkcif_write_register(dev, CIF_REG_DVP_FRM0_ADDR_Y,
dummy_buf->dma_addr);
rkcif_write_register(dev, CIF_REG_DVP_FRM0_ADDR_UV,
dummy_buf->dma_addr);
}
}
if (!stream->next_buf) {
@@ -1199,6 +1207,13 @@ static int rkcif_assign_new_buffer_oneframe(struct rkcif_stream *stream,
stream->next_buf->buff_addr[RKCIF_PLANE_Y]);
rkcif_write_register(dev, CIF_REG_DVP_FRM1_ADDR_UV,
stream->next_buf->buff_addr[RKCIF_PLANE_CBCR]);
} else {
if (dummy_buf->vaddr) {
rkcif_write_register(dev, CIF_REG_DVP_FRM1_ADDR_Y,
dummy_buf->dma_addr);
rkcif_write_register(dev, CIF_REG_DVP_FRM1_ADDR_UV,
dummy_buf->dma_addr);
}
}
} else if (stat == RKCIF_YUV_ADDR_STATE_UPDATE) {
if (!list_empty(&stream->buf_head)) {
@@ -1214,6 +1229,10 @@ static int rkcif_assign_new_buffer_oneframe(struct rkcif_stream *stream,
buffer = stream->next_buf;
}
} else {
if (dummy_buf->vaddr && stream->frame_phase == CIF_CSI_FRAME0_READY)
stream->curr_buf = NULL;
if (dummy_buf->vaddr && stream->frame_phase == CIF_CSI_FRAME1_READY)
stream->next_buf = NULL;
buffer = NULL;
}
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
@@ -1230,7 +1249,14 @@ static int rkcif_assign_new_buffer_oneframe(struct rkcif_stream *stream,
rkcif_write_register(dev, frm_addr_uv,
buffer->buff_addr[RKCIF_PLANE_CBCR]);
} else {
ret = -EINVAL;
if (dummy_buf->vaddr) {
rkcif_write_register(dev, frm_addr_y,
dummy_buf->dma_addr);
rkcif_write_register(dev, frm_addr_uv,
dummy_buf->dma_addr);
} else {
ret = -EINVAL;
}
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev,
"not active buffer, frame Drop\n");
}
@@ -1280,6 +1306,12 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream,
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);
}
}
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
@@ -1306,6 +1338,12 @@ static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream,
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) {
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);
}
}
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
@@ -1344,6 +1382,7 @@ 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;
@@ -1370,6 +1409,10 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
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);
@@ -1393,6 +1436,22 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
}
} 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)
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;
}
}
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
@@ -1412,7 +1471,13 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
buffer->buff_addr[RKCIF_PLANE_CBCR]);
}
} else {
ret = -EINVAL;
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 ||
@@ -1424,11 +1489,16 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream,
static int rkcif_get_new_buffer_wake_up_mode(struct rkcif_stream *stream)
{
struct rkcif_device *dev = stream->cifdev;
struct rkcif_dummy_buffer *dummy_buf = &dev->dummy_buf;
int ret = 0;
unsigned long flags;
spin_lock_irqsave(&stream->vbq_lock, flags);
if (!list_empty(&stream->buf_head)) {
if (!dummy_buf->vaddr &&
stream->curr_buf == stream->next_buf)
ret = -EINVAL;
if (stream->line_int_cnt % 2) {
stream->curr_buf = list_first_entry(&stream->buf_head,
struct rkcif_buffer, queue);
@@ -1442,8 +1512,21 @@ static int rkcif_get_new_buffer_wake_up_mode(struct rkcif_stream *stream)
}
stream->is_buf_active = true;
} else {
ret = -EINVAL;
stream->is_buf_active = false;
if (dummy_buf->vaddr) {
if (stream->line_int_cnt % 2)
stream->curr_buf = NULL;
else
stream->next_buf = NULL;
} else if (stream->curr_buf != stream->next_buf) {
if (stream->line_int_cnt % 2)
stream->curr_buf = stream->next_buf;
else
stream->next_buf = stream->curr_buf;
stream->is_buf_active = true;
} else {
ret = -EINVAL;
}
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
@@ -1453,6 +1536,7 @@ static int rkcif_get_new_buffer_wake_up_mode(struct rkcif_stream *stream)
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->dummy_buf;
struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
struct rkcif_buffer *buffer = NULL;
u32 frm_addr_y, frm_addr_uv;
@@ -1490,7 +1574,13 @@ static int rkcif_update_new_buffer_wake_up_mode(struct rkcif_stream *stream)
rkcif_write_register(dev, frm_addr_uv,
buffer->buff_addr[RKCIF_PLANE_CBCR]);
} else {
ret = -EINVAL;
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 ||
@@ -2894,8 +2984,8 @@ static int rkcif_start_streaming(struct vb2_queue *queue, unsigned int count)
if (ret < 0)
goto destroy_buf;
if (dev->active_sensor &&
dev->active_sensor->mbus.type == V4L2_MBUS_BT656 &&
if (((dev->active_sensor && dev->active_sensor->mbus.type == V4L2_MBUS_BT656) ||
dev->is_use_dummybuf) &&
(!dev->dummy_buf.vaddr)) {
ret = rkcif_create_dummy_buf(stream);
if (ret < 0) {
@@ -3034,7 +3124,10 @@ static int rkcif_init_vb2_queue(struct vb2_queue *q,
else
q->mem_ops = &vb2_dma_contig_memops;
q->buf_struct_size = sizeof(struct rkcif_buffer);
q->min_buffers_needed = CIF_REQ_BUFS_MIN;
if (stream->cifdev->is_use_dummybuf)
q->min_buffers_needed = 1;
else
q->min_buffers_needed = CIF_REQ_BUFS_MIN;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &stream->vnode.vlock;
q->dev = hw_dev->dev;
@@ -4920,7 +5013,8 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream,
cif_dev->rdbk_buf[RDBK_L]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
rkcif_buf_queue(&cif_dev->rdbk_buf[RDBK_L]->vb.vb2_buf);
}
cif_dev->rdbk_buf[RDBK_L] = active_buf;
if (active_buf)
cif_dev->rdbk_buf[RDBK_L] = active_buf;
} else if (mipi_id == RKCIF_STREAM_MIPI_ID1) {
if (cif_dev->rdbk_buf[RDBK_M]) {
v4l2_err(&cif_dev->v4l2_dev,
@@ -4931,8 +5025,8 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream,
cif_dev->rdbk_buf[RDBK_M]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
rkcif_buf_queue(&cif_dev->rdbk_buf[RDBK_M]->vb.vb2_buf);
}
cif_dev->rdbk_buf[RDBK_M] = active_buf;
if (active_buf)
cif_dev->rdbk_buf[RDBK_M] = active_buf;
if (cif_dev->hdr.mode == HDR_X2)
rkcif_rdbk_frame_end(stream);
} else if (mipi_id == RKCIF_STREAM_MIPI_ID2) {
@@ -4945,7 +5039,8 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream,
cif_dev->rdbk_buf[RDBK_S]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
rkcif_buf_queue(&cif_dev->rdbk_buf[RDBK_S]->vb.vb2_buf);
}
cif_dev->rdbk_buf[RDBK_S] = active_buf;
if (active_buf)
cif_dev->rdbk_buf[RDBK_S] = active_buf;
if (cif_dev->hdr.mode == HDR_X3)
rkcif_rdbk_frame_end(stream);
}
@@ -5016,10 +5111,12 @@ static void rkcif_deal_readout_time(struct rkcif_stream *stream)
} else if ((cif_dev->hdr.mode == HDR_X2) && (stream->id == RKCIF_STREAM_MIPI_ID1)) {
detect_stream->readout.early_time = stream->readout.fe_timestamp - stream->readout.wk_timestamp;
detect_stream->readout.total_time = stream->readout.fe_timestamp - detect_stream->readout.fs_timestamp;
detect_stream->readout.total_time = stream->readout.fe_timestamp - detect_stream->readout.fe_timestamp;
detect_stream->readout.total_time += detect_stream->readout.readout_time;
} else if ((cif_dev->hdr.mode == HDR_X3) && (stream->id == RKCIF_STREAM_MIPI_ID2)) {
detect_stream->readout.early_time = stream->readout.fe_timestamp - stream->readout.wk_timestamp;
detect_stream->readout.total_time = stream->readout.fe_timestamp - detect_stream->readout.fs_timestamp;
detect_stream->readout.total_time = stream->readout.fe_timestamp - detect_stream->readout.fe_timestamp;
detect_stream->readout.total_time += detect_stream->readout.readout_time;
}
if (!stream->is_line_wake_up)
detect_stream->readout.early_time = 0;
@@ -5059,7 +5156,8 @@ static void rkcif_update_stream(struct rkcif_device *cif_dev,
cif_dev->buf_wake_up_cnt += 1;
}
rkcif_deal_readout_time(stream);
if (cif_dev->inf_id == RKCIF_MIPI_LVDS)
rkcif_deal_readout_time(stream);
if (!stream->is_line_wake_up) {
ret = rkcif_assign_new_buffer_pingpong(stream,

View File

@@ -120,15 +120,52 @@ static ssize_t rkcif_store_line_int_num(struct device *dev,
return len;
}
static ssize_t rkcif_show_dummybuf_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int ret;
ret = snprintf(buf, PAGE_SIZE, "%d\n",
cif_dev->is_use_dummybuf);
return ret;
}
static ssize_t rkcif_store_dummybuf_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int val = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &val);
if (!ret) {
if (val)
cif_dev->is_use_dummybuf = true;
else
cif_dev->is_use_dummybuf = false;
} else {
dev_info(cif_dev->dev, "set dummy buf mode failed\n");
}
return len;
}
static DEVICE_ATTR(compact_test, S_IWUSR | S_IRUSR,
rkcif_show_compact_mode, rkcif_store_compact_mode);
static DEVICE_ATTR(wait_line, S_IWUSR | S_IRUSR,
rkcif_show_line_int_num, rkcif_store_line_int_num);
static DEVICE_ATTR(is_use_dummybuf, S_IWUSR | S_IRUSR,
rkcif_show_dummybuf_mode, rkcif_store_dummybuf_mode);
static struct attribute *dev_attrs[] = {
&dev_attr_compact_test.attr,
&dev_attr_wait_line.attr,
&dev_attr_is_use_dummybuf.attr,
NULL,
};
@@ -1096,6 +1133,12 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
cif_dev->workmode = RKCIF_WORKMODE_PINGPONG;
#endif
#if defined(CONFIG_ROCKCHIP_CIF_USE_DUMMY_BUF)
cif_dev->is_use_dummybuf = true;
#else
cif_dev->is_use_dummybuf = false;
#endif
strlcpy(cif_dev->media_dev.model, dev_name(dev),
sizeof(cif_dev->media_dev.model));
cif_dev->media_dev.dev = dev;
@@ -1226,9 +1269,6 @@ static int rkcif_plat_probe(struct platform_device *pdev)
dev_set_drvdata(dev, cif_dev);
cif_dev->dev = dev;
if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp))
return -ENODEV;
rkcif_attach_hw(cif_dev);
rkcif_parse_dts(cif_dev);
@@ -1239,6 +1279,9 @@ static int rkcif_plat_probe(struct platform_device *pdev)
return ret;
}
if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp))
return -ENODEV;
if (rkcif_proc_init(cif_dev))
dev_warn(dev, "dev:%s create proc failed\n", dev_name(dev));
@@ -1257,6 +1300,7 @@ static int rkcif_plat_remove(struct platform_device *pdev)
rkcif_detach_hw(cif_dev);
rkcif_proc_cleanup(cif_dev);
rkcif_csi2_unregister_notifier(&cif_dev->reset_notifier);
sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
del_timer_sync(&cif_dev->reset_watchdog_timer.timer);
return 0;

View File

@@ -551,6 +551,7 @@ struct rkcif_device {
bool is_start_hdr;
bool reset_work_cancel;
bool iommu_en;
bool is_use_dummybuf;
};
extern struct platform_driver rkcif_plat_drv;

View File

@@ -315,17 +315,19 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f)
dev->channels[0].crop_st_x, dev->channels[0].crop_st_y);
seq_printf(f, "\tcompact:%s\n", stream->is_compact ? "enable" : "disabled");
seq_printf(f, "\tframe amount:%d\n", stream->frame_idx);
time_val = div_u64(stream->readout.early_time, 1000000);
seq_printf(f, "\tearly:%u ms\n", time_val);
if (dev->hdr.mode == NO_HDR) {
time_val = div_u64(stream->readout.readout_time, 1000000);
seq_printf(f, "\treadout:%u ms\n", time_val);
} else {
time_val = div_u64(stream->readout.readout_time, 1000000);
seq_printf(f, "\tsingle readout:%u ms\n", time_val);
time_val = div_u64(stream->readout.total_time, 1000000);
seq_printf(f, "\ttotal readout:%u ms\n", time_val);
if (dev->inf_id == RKCIF_MIPI_LVDS) {
time_val = div_u64(stream->readout.early_time, 1000000);
seq_printf(f, "\tearly:%u ms\n", time_val);
if (dev->hdr.mode == NO_HDR) {
time_val = div_u64(stream->readout.readout_time, 1000000);
seq_printf(f, "\treadout:%u ms\n", time_val);
} else {
time_val = div_u64(stream->readout.readout_time, 1000000);
seq_printf(f, "\tsingle readout:%u ms\n", time_val);
time_val = div_u64(stream->readout.total_time, 1000000);
seq_printf(f, "\ttotal readout:%u ms\n", time_val);
}
}
seq_printf(f, "\trate:%llu ms\n", fps);
fps = div_u64(1000, fps);