mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
media: rockchip: vicap add dma_fence to support low latency
Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com> Change-Id: I2dc5b7956e5b89f1d03d8276cd5732fcdcfbc69c
This commit is contained in:
@@ -20,6 +20,9 @@
|
||||
#include <soc/rockchip/rockchip-system-status.h>
|
||||
#include <soc/rockchip/rockchip_iommu.h>
|
||||
#include <linux/rk-isp32-config.h>
|
||||
#include <linux/dma-fence.h>
|
||||
#include <linux/sync_file.h>
|
||||
#include <linux/fdtable.h>
|
||||
|
||||
#include "dev.h"
|
||||
#include "mipi-csi2.h"
|
||||
@@ -4234,7 +4237,6 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
|
||||
{
|
||||
unsigned int val = 0x0;
|
||||
struct rkcif_device *dev = stream->cifdev;
|
||||
struct rkcif_stream *detect_stream = &dev->stream[0];
|
||||
struct sditf_priv *priv = dev->sditf[0];
|
||||
struct rkmodule_capture_info *capture_info = &channel->capture_info;
|
||||
unsigned int wait_line = 0x3fff;
|
||||
@@ -4293,7 +4295,7 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
|
||||
CSI_START_INTEN(channel->id) :
|
||||
CSI_START_INTEN_RK3576(channel->id));
|
||||
|
||||
if (priv && priv->mode.rdbk_mode && detect_stream->is_line_wake_up) {
|
||||
if (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;
|
||||
@@ -4983,6 +4985,235 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream,
|
||||
}
|
||||
}
|
||||
|
||||
static void rkcif_add_fence_to_vb_done(struct rkcif_stream *stream,
|
||||
struct vb2_v4l2_buffer *vb_done)
|
||||
{
|
||||
unsigned long lock_flags = 0;
|
||||
struct rkcif_fence *vb_fence;
|
||||
struct rkcif_device *cif_dev = stream->cifdev;
|
||||
struct v4l2_device *v4l2_dev = &cif_dev->v4l2_dev;
|
||||
|
||||
spin_lock_irqsave(&stream->fence_lock, lock_flags);
|
||||
if (!list_empty(&stream->qbuf_fence_list_head)) {
|
||||
vb_fence = list_first_entry(&stream->qbuf_fence_list_head,
|
||||
struct rkcif_fence, fence_list);
|
||||
list_del(&vb_fence->fence_list);
|
||||
} else {
|
||||
vb_fence = NULL;
|
||||
}
|
||||
|
||||
if (vb_fence)
|
||||
list_add_tail(&vb_fence->fence_list, &stream->done_fence_list_head);
|
||||
spin_unlock_irqrestore(&stream->fence_lock, lock_flags);
|
||||
|
||||
if (vb_fence) {
|
||||
/* pass the fence_fd to userspace through timecode.userbits */
|
||||
vb_done->timecode.userbits[0] = vb_fence->fence_fd & 0xff;
|
||||
vb_done->timecode.userbits[1] = (vb_fence->fence_fd & 0xff00) >> 8;
|
||||
vb_done->timecode.userbits[2] = (vb_fence->fence_fd & 0xff0000) >> 16;
|
||||
vb_done->timecode.userbits[3] = (vb_fence->fence_fd & 0xff000000) >> 24;
|
||||
v4l2_dbg(3, rkcif_debug, v4l2_dev, "%s: fence:%p, fence_fd:%d\n",
|
||||
__func__, vb_fence->fence, vb_fence->fence_fd);
|
||||
} else {
|
||||
/* config userbits 0 or 0xffffffff as invalid fence_fd*/
|
||||
memset(vb_done->timecode.userbits, 0xff, sizeof(vb_done->timecode.userbits));
|
||||
v4l2_err(v4l2_dev, "%s: failed to get fence fd!\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static void rkcif_dqbuf_get_done_fence(struct rkcif_stream *stream)
|
||||
{
|
||||
unsigned long lock_flags = 0;
|
||||
struct rkcif_fence *done_fence;
|
||||
struct v4l2_device *v4l2_dev = &stream->cifdev->v4l2_dev;
|
||||
|
||||
spin_lock_irqsave(&stream->fence_lock, lock_flags);
|
||||
if (!list_empty(&stream->done_fence_list_head)) {
|
||||
done_fence = list_first_entry(&stream->done_fence_list_head,
|
||||
struct rkcif_fence, fence_list);
|
||||
list_del(&done_fence->fence_list);
|
||||
} else {
|
||||
done_fence = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->fence_lock, lock_flags);
|
||||
|
||||
if (done_fence) {
|
||||
spin_lock_irqsave(&stream->fence_lock, lock_flags);
|
||||
if (stream->rkcif_fence) {
|
||||
dma_fence_signal(stream->rkcif_fence->fence);
|
||||
dma_fence_put(stream->rkcif_fence->fence);
|
||||
v4l2_dbg(2, rkcif_debug, v4l2_dev, "%s: signal fence:%p, old_fd:%d\n",
|
||||
__func__,
|
||||
stream->rkcif_fence->fence,
|
||||
stream->rkcif_fence->fence_fd);
|
||||
kfree(stream->rkcif_fence);
|
||||
stream->rkcif_fence = NULL;
|
||||
}
|
||||
stream->rkcif_fence = done_fence;
|
||||
spin_unlock_irqrestore(&stream->fence_lock, lock_flags);
|
||||
v4l2_dbg(3, rkcif_debug, v4l2_dev, "%s: fence:%p, fence_fd:%d\n",
|
||||
__func__, done_fence->fence, done_fence->fence_fd);
|
||||
}
|
||||
}
|
||||
|
||||
static void rkcif_fence_signal(struct rkcif_stream *stream)
|
||||
{
|
||||
unsigned long lock_flags = 0;
|
||||
struct v4l2_device *v4l2_dev = &stream->cifdev->v4l2_dev;
|
||||
|
||||
spin_lock_irqsave(&stream->fence_lock, lock_flags);
|
||||
if (stream->rkcif_fence) {
|
||||
dma_fence_signal(stream->rkcif_fence->fence);
|
||||
dma_fence_put(stream->rkcif_fence->fence);
|
||||
v4l2_dbg(2, rkcif_debug, v4l2_dev, "%s: signal fence:%p, old_fd:%d\n",
|
||||
__func__,
|
||||
stream->rkcif_fence->fence,
|
||||
stream->rkcif_fence->fence_fd);
|
||||
kfree(stream->rkcif_fence);
|
||||
stream->rkcif_fence = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->fence_lock, lock_flags);
|
||||
}
|
||||
|
||||
static void rkcif_free_fence(struct rkcif_stream *stream)
|
||||
{
|
||||
unsigned long lock_flags = 0;
|
||||
struct rkcif_fence *vb_fence, *done_fence;
|
||||
struct v4l2_device *v4l2_dev = &stream->cifdev->v4l2_dev;
|
||||
LIST_HEAD(local_list);
|
||||
|
||||
spin_lock_irqsave(&stream->fence_lock, lock_flags);
|
||||
if (stream->rkcif_fence) {
|
||||
v4l2_dbg(2, rkcif_debug, v4l2_dev, "%s: signal rkcif_fence fd:%d\n",
|
||||
__func__, stream->rkcif_fence->fence_fd);
|
||||
dma_fence_signal(stream->rkcif_fence->fence);
|
||||
dma_fence_put(stream->rkcif_fence->fence);
|
||||
kfree(stream->rkcif_fence);
|
||||
stream->rkcif_fence = NULL;
|
||||
}
|
||||
list_replace_init(&stream->qbuf_fence_list_head, &local_list);
|
||||
spin_unlock_irqrestore(&stream->fence_lock, lock_flags);
|
||||
|
||||
while (!list_empty(&local_list)) {
|
||||
vb_fence = list_first_entry(&local_list, struct rkcif_fence, fence_list);
|
||||
list_del(&vb_fence->fence_list);
|
||||
v4l2_dbg(2, rkcif_debug, v4l2_dev, "%s: free qbuf_fence fd:%d\n",
|
||||
__func__, vb_fence->fence_fd);
|
||||
dma_fence_put(vb_fence->fence);
|
||||
put_unused_fd(vb_fence->fence_fd);
|
||||
close_fd(vb_fence->fence_fd);
|
||||
kfree(vb_fence);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&stream->fence_lock, lock_flags);
|
||||
list_replace_init(&stream->done_fence_list_head, &local_list);
|
||||
spin_unlock_irqrestore(&stream->fence_lock, lock_flags);
|
||||
|
||||
while (!list_empty(&local_list)) {
|
||||
done_fence = list_first_entry(&local_list, struct rkcif_fence, fence_list);
|
||||
list_del(&done_fence->fence_list);
|
||||
v4l2_dbg(2, rkcif_debug, v4l2_dev, "%s: free done_fence fd:%d\n",
|
||||
__func__, done_fence->fence_fd);
|
||||
dma_fence_put(done_fence->fence);
|
||||
put_unused_fd(done_fence->fence_fd);
|
||||
close_fd(done_fence->fence_fd);
|
||||
kfree(done_fence);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *rkcif_fence_get_name(struct dma_fence *fence)
|
||||
{
|
||||
return CIF_DRIVER_NAME;
|
||||
}
|
||||
|
||||
static const struct dma_fence_ops rkcif_fence_ops = {
|
||||
.get_driver_name = rkcif_fence_get_name,
|
||||
.get_timeline_name = rkcif_fence_get_name,
|
||||
};
|
||||
|
||||
static void rkcif_fence_context_init(struct rkcif_fence_context *fence_ctx)
|
||||
{
|
||||
fence_ctx->context = dma_fence_context_alloc(1);
|
||||
spin_lock_init(&fence_ctx->spinlock);
|
||||
}
|
||||
|
||||
static struct dma_fence *rkcif_dma_fence_alloc(struct rkcif_fence_context *fence_ctx)
|
||||
{
|
||||
struct dma_fence *fence = NULL;
|
||||
|
||||
if (fence_ctx == NULL) {
|
||||
pr_err("fence_context is NULL!\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
|
||||
if (!fence)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
dma_fence_init(fence, &rkcif_fence_ops, &fence_ctx->spinlock,
|
||||
fence_ctx->context, ++fence_ctx->seqno);
|
||||
|
||||
return fence;
|
||||
}
|
||||
|
||||
static int rkcif_dma_fence_get_fd(struct dma_fence *fence)
|
||||
{
|
||||
struct sync_file *sync_file = NULL;
|
||||
int fence_fd = -1;
|
||||
|
||||
if (!fence)
|
||||
return -EINVAL;
|
||||
|
||||
fence_fd = get_unused_fd_flags(O_CLOEXEC);
|
||||
if (fence_fd < 0)
|
||||
return fence_fd;
|
||||
|
||||
sync_file = sync_file_create(fence);
|
||||
if (!sync_file) {
|
||||
put_unused_fd(fence_fd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
fd_install(fence_fd, sync_file->file);
|
||||
|
||||
return fence_fd;
|
||||
}
|
||||
|
||||
static void rkcif_qbuf_alloc_fence(struct rkcif_stream *stream)
|
||||
{
|
||||
struct dma_fence *fence;
|
||||
int fence_fd;
|
||||
struct rkcif_fence *rkcif_fence;
|
||||
unsigned long lock_flags = 0;
|
||||
struct v4l2_device *v4l2_dev = &stream->cifdev->v4l2_dev;
|
||||
|
||||
fence = rkcif_dma_fence_alloc(&stream->fence_ctx);
|
||||
if (!IS_ERR(fence)) {
|
||||
rkcif_fence = kzalloc(sizeof(struct rkcif_fence), GFP_KERNEL);
|
||||
if (!rkcif_fence) {
|
||||
kfree(fence);
|
||||
v4l2_err(v4l2_dev, "%s: failed to alloc rkcif_fence!\n", __func__);
|
||||
return;
|
||||
}
|
||||
fence_fd = rkcif_dma_fence_get_fd(fence);
|
||||
if (fence_fd >= 0) {
|
||||
rkcif_fence->fence = fence;
|
||||
rkcif_fence->fence_fd = fence_fd;
|
||||
spin_lock_irqsave(&stream->fence_lock, lock_flags);
|
||||
list_add_tail(&rkcif_fence->fence_list, &stream->qbuf_fence_list_head);
|
||||
spin_unlock_irqrestore(&stream->fence_lock, lock_flags);
|
||||
v4l2_dbg(3, rkcif_debug, v4l2_dev, "%s: fence:%p, fence_fd:%d\n",
|
||||
__func__, fence, fence_fd);
|
||||
} else {
|
||||
dma_fence_put(fence);
|
||||
kfree(rkcif_fence);
|
||||
v4l2_err(v4l2_dev, "%s: failed to get fence fd!\n", __func__);
|
||||
}
|
||||
} else {
|
||||
v4l2_err(v4l2_dev, "%s: alloc fence failed!\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The vb2_buffer are stored in rkcif_buffer, in order to unify
|
||||
* mplane buffer and none-mplane buffer.
|
||||
@@ -5080,6 +5311,8 @@ void rkcif_buf_queue(struct vb2_buffer *vb)
|
||||
stream->cifdev->channels[0].capture_info.mode != RKMODULE_ONE_CH_TO_MULTI_ISP)
|
||||
rkcif_check_buffer_update_pingpong(stream, stream->id);
|
||||
atomic_inc(&stream->buf_cnt);
|
||||
if (stream->low_latency)
|
||||
rkcif_qbuf_alloc_fence(stream);
|
||||
v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev,
|
||||
"stream[%d] buf queue, index: %d, dma_addr 0x%x, dbuf %p, mem_priv %p\n",
|
||||
stream->id, vb->index, cifbuf->buff_addr[0], cifbuf->vb.vb2_buf.planes[0].dbuf,
|
||||
@@ -5800,8 +6033,6 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
|
||||
dev->reset_work_cancel = true;
|
||||
dev->early_line = 0;
|
||||
dev->sensor_linetime = 0;
|
||||
dev->wait_line = 0;
|
||||
stream->is_line_wake_up = false;
|
||||
}
|
||||
if (atomic_read(&dev->pipe.stream_cnt) == 0)
|
||||
atomic_set(&stream->sub_stream_buf_cnt, 0);
|
||||
@@ -5817,6 +6048,7 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
|
||||
rkcif_detach_sync_mode(dev);
|
||||
if (!atomic_read(&dev->pipe.stream_cnt) && dev->is_alloc_buf_user)
|
||||
rkcif_free_buf_by_user_require(dev);
|
||||
rkcif_free_fence(stream);
|
||||
stream->cur_stream_mode &= ~mode;
|
||||
v4l2_info(&dev->v4l2_dev, "stream[%d] stopping finished, dma_en 0x%x\n", stream->id, stream->dma_en);
|
||||
mutex_unlock(&dev->stream_lock);
|
||||
@@ -7054,6 +7286,12 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, enum rkcif_stream_mode mo
|
||||
}
|
||||
if (stream->dma_en == 0)
|
||||
stream->fs_cnt_in_single_frame = 0;
|
||||
|
||||
if (dev->wait_line_cache != 0) {
|
||||
dev->wait_line = dev->wait_line_cache;
|
||||
stream->is_line_wake_up = true;
|
||||
}
|
||||
|
||||
if (stream->is_line_wake_up)
|
||||
stream->is_line_inten = true;
|
||||
else
|
||||
@@ -7585,6 +7823,12 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id)
|
||||
stream->is_wait_stop_complete = false;
|
||||
stream->thunderboot_skip_interval = get_rk_cam_skip_frame_interval();
|
||||
atomic_set(&stream->sub_stream_buf_cnt, 0);
|
||||
spin_lock_init(&stream->fence_lock);
|
||||
rkcif_fence_context_init(&stream->fence_ctx);
|
||||
INIT_LIST_HEAD(&stream->qbuf_fence_list_head);
|
||||
INIT_LIST_HEAD(&stream->done_fence_list_head);
|
||||
stream->low_latency = false;
|
||||
stream->rkcif_fence = NULL;
|
||||
}
|
||||
|
||||
static int rkcif_sensor_set_power(struct rkcif_stream *stream, int on)
|
||||
@@ -8497,13 +8741,25 @@ static long rkcif_ioctl_default(struct file *file, void *fh,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rkcif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
|
||||
{
|
||||
int ret;
|
||||
struct rkcif_stream *stream = video_drvdata(file);
|
||||
|
||||
ret = vb2_ioctl_dqbuf(file, priv, p);
|
||||
if (stream->low_latency)
|
||||
rkcif_dqbuf_get_done_fence(stream);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct v4l2_ioctl_ops rkcif_v4l2_ioctl_ops = {
|
||||
.vidioc_reqbufs = vb2_ioctl_reqbufs,
|
||||
.vidioc_querybuf = vb2_ioctl_querybuf,
|
||||
.vidioc_create_bufs = vb2_ioctl_create_bufs,
|
||||
.vidioc_qbuf = vb2_ioctl_qbuf,
|
||||
.vidioc_expbuf = vb2_ioctl_expbuf,
|
||||
.vidioc_dqbuf = vb2_ioctl_dqbuf,
|
||||
.vidioc_dqbuf = rkcif_dqbuf,
|
||||
.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
|
||||
.vidioc_streamon = vb2_ioctl_streamon,
|
||||
.vidioc_streamoff = vb2_ioctl_streamoff,
|
||||
@@ -10007,6 +10263,10 @@ static void rkcif_line_wake_up(struct rkcif_stream *stream, int mipi_id)
|
||||
ret = rkcif_get_new_buffer_wake_up_mode(stream);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (active_buf && stream->low_latency)
|
||||
rkcif_add_fence_to_vb_done(stream, &active_buf->vb);
|
||||
|
||||
rkcif_buf_done_prepare(stream, active_buf, mipi_id, mode);
|
||||
}
|
||||
|
||||
@@ -11048,7 +11308,7 @@ static void rkcif_detect_wake_up_mode_change(struct rkcif_stream *stream)
|
||||
int ch = 0;
|
||||
int i = 0;
|
||||
|
||||
if (!priv || priv->mode.rdbk_mode == RKISP_VICAP_ONLINE)
|
||||
if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE)
|
||||
return;
|
||||
|
||||
if ((cif_dev->hdr.hdr_mode == NO_HDR || cif_dev->hdr.hdr_mode == HDR_COMPR) &&
|
||||
@@ -12653,6 +12913,8 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
|
||||
intstat &= ~CSI_FRAME_END_ID3;
|
||||
break;
|
||||
}
|
||||
if (stream->low_latency)
|
||||
rkcif_fence_signal(stream);
|
||||
if (stream->cifdev->rdbk_debug &&
|
||||
stream->frame_idx < 15 &&
|
||||
(!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode))
|
||||
@@ -13027,6 +13289,9 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream->low_latency)
|
||||
rkcif_fence_signal(stream);
|
||||
|
||||
if (stream->crop_dyn_en)
|
||||
rkcif_dynamic_crop(stream);
|
||||
|
||||
|
||||
@@ -923,6 +923,56 @@ static ssize_t rkcif_store_odd_frame_fisrt(struct device *dev,
|
||||
static DEVICE_ATTR(odd_frame_first, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_odd_frame_fisrt, rkcif_store_odd_frame_fisrt);
|
||||
|
||||
static ssize_t rkcif_show_low_latency(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 %d %d %d\n",
|
||||
cif_dev->stream[0].low_latency ? 1 : 0,
|
||||
cif_dev->stream[1].low_latency ? 1 : 0,
|
||||
cif_dev->stream[2].low_latency ? 1 : 0,
|
||||
cif_dev->stream[3].low_latency ? 1 : 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rkcif_store_low_latency(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 i, index;
|
||||
char val[4];
|
||||
|
||||
if (buf) {
|
||||
index = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i] == ' ')
|
||||
continue;
|
||||
else if (buf[i] == '\0')
|
||||
break;
|
||||
val[index] = buf[i];
|
||||
index++;
|
||||
if (index == 4)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < index; i++) {
|
||||
if (val[i] - '0' == 0)
|
||||
cif_dev->stream[i].low_latency = false;
|
||||
else
|
||||
cif_dev->stream[i].low_latency = true;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(low_latency, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_low_latency, rkcif_store_low_latency);
|
||||
|
||||
static struct attribute *dev_attrs[] = {
|
||||
&dev_attr_compact_test.attr,
|
||||
&dev_attr_wait_line.attr,
|
||||
@@ -940,6 +990,7 @@ static struct attribute *dev_attrs[] = {
|
||||
&dev_attr_extraction_pattern.attr,
|
||||
&dev_attr_sw_dbg_en.attr,
|
||||
&dev_attr_use_hw_interlace.attr,
|
||||
&dev_attr_low_latency.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
@@ -495,6 +495,18 @@ struct rkcif_toisp_buf_state {
|
||||
bool is_early_update;
|
||||
};
|
||||
|
||||
struct rkcif_fence_context {
|
||||
u64 context;
|
||||
u64 seqno;
|
||||
spinlock_t spinlock;
|
||||
};
|
||||
|
||||
struct rkcif_fence {
|
||||
struct list_head fence_list;
|
||||
struct dma_fence *fence;
|
||||
int fence_fd;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct rkcif_stream - Stream states TODO
|
||||
*
|
||||
@@ -578,6 +590,11 @@ struct rkcif_stream {
|
||||
int thunderboot_skip_interval;
|
||||
int sequence;
|
||||
atomic_t sub_stream_buf_cnt;
|
||||
struct rkcif_fence_context fence_ctx;
|
||||
struct rkcif_fence *rkcif_fence;
|
||||
struct list_head qbuf_fence_list_head;
|
||||
struct list_head done_fence_list_head;
|
||||
spinlock_t fence_lock;
|
||||
bool stopping;
|
||||
bool crop_enable;
|
||||
bool crop_dyn_en;
|
||||
@@ -598,6 +615,7 @@ struct rkcif_stream {
|
||||
bool is_single_cap;
|
||||
bool is_wait_stop_complete;
|
||||
bool interlaced_bad_frame;
|
||||
bool low_latency;
|
||||
};
|
||||
|
||||
struct rkcif_lvds_subdev {
|
||||
|
||||
Reference in New Issue
Block a user