(tx2)the camera delay N+2 frame

Hi, all:

Our camera supports trigger mode(sync mode),We found that only after two trigger signals can we get the image.
In function “tegra_channel_ring_buffer()” at code “kernel/nvidia/drivers/media/platform/tegra/camera/vi/channel.c”

/* release buffer N at N+2 frame start event */
if (chan->num_buffers >= (chan->capture_queue_depth -1)) {
free_ring_buffers(chan, 1);
}

we can konw, we will get the image at “sof” after two trigger signals.
But , I want get the image at “eof” of buffer N, not buffer N+2.

Can you tell me how should I do?

Thanks.

Did you try add --set-ctrl low_latency_mode=1 to the v4l2-ctl command line?

Hi. shaneccc:

thanks for you reply.

I add --set-ctrl low_latency_mode=1 to the v4l2-ctl command line.
I get the image at “eof” of buffer N+2, not buffer N.

I want get the image at “eof” of buffer N, not buffer N+2.

Thanks.

It’s could be a large work to revert this ring buffer logic.
Please use the source_sync.sh to get the source code. And find the below change and try to revert it.

commit be2cc397bf47414522def4f54360daab5bd43e23
Author: Bhanu Murthy V bmurthyv@nvidia.com
Date: Fri Apr 15 19:54:08 2016 -0700

drivers: media: camera: Ring buffer management

Implement ring buffer which holds two buffers
before delivering frames from VI. This is to
ensure there is no performance impact using
single thread and memory write of the buffer
is complete.

Add logic to store buffers at the start,
release one buffer every frame once the queue
has only one free slot left.

Free all buffers once the stop streaming
is signalled.
Clean up for two thread implementation and
improve state mechanism in single thread

Bug 200092604
Bug 1736471

Change-Id: Ia9784ee0c7925b5ec4dd6ca5f0b3354af8323662
Signed-off-by: Bhanu Murthy V <bmurthyv@nvidia.com>
Reviewed-on: http://git-master/r/1127760
(cherry picked from commit 39a3d10573140a98aea3b67044f056772fa2be9f)
Reviewed-on: http://git-master/r/1161371

diff --git a/drivers/media/platform/tegra/camera/channel.c b/drivers/media/platform/tegra/camera/channel.c
index d9a7a5f50…25397380b 100644
— a/drivers/media/platform/tegra/camera/channel.c
+++ b/drivers/media/platform/tegra/camera/channel.c
@@ -44,6 +44,9 @@
#define BPP_MEM 2

extern int _vb2_fop_release(struct file *file, struct mutex *lock);
+static void tegra_channel_queued_buf_done(struct tegra_channel *chan,

  •                                     enum vb2_buffer_state state);
    

+static void tegra_channel_stop_kthreads(struct tegra_channel *chan);

static void tegra_channel_write(struct tegra_channel *chan,
unsigned int addr, u32 val)
@@ -258,15 +261,51 @@ static void tegra_channel_capture_error(struct tegra_channel *chan)
}
}

+static void free_ring_buffers(struct tegra_channel *chan, int frames)
+{

  •   struct vb2_buffer *vb;
    
  •   while (frames--) {
    
  •           vb = chan->buffers[chan->free_index];
    
  •           /* release one frame */
    
  •           vb->v4l2_buf.sequence = chan->sequence++;
    
  •           vb->v4l2_buf.field = V4L2_FIELD_NONE;
    
  •           vb2_set_plane_payload(vb, 0, chan->format.sizeimage);
    
  •           vb2_buffer_done(vb, chan->buffer_state[chan->free_index++]);
    
  •           if (chan->free_index >= QUEUED_BUFFERS)
    
  •                   chan->free_index = 0;
    
  •           chan->num_buffers--;
    
  •   }
    

+}
+
+static void tegra_channel_ring_buffer(struct tegra_channel *chan,

  •                           struct vb2_buffer *vb, int state)
    

+{

  •   /* save the buffer to the ring first */
    
  •   chan->buffer_state[chan->save_index] = state;
    
  •   chan->buffers[chan->save_index++] = vb;
    
  •   if (chan->save_index >= QUEUED_BUFFERS)
    
  •           chan->save_index = 0;
    
  •   chan->num_buffers++;
    
  •   /* release one buffer when only one free slot is present */
    
  •   if (chan->num_buffers >= (QUEUED_BUFFERS - 1))
    
  •           free_ring_buffers(chan, 1);
    

+}
+
static void tegra_channel_capture_frame(struct tegra_channel *chan,
struct tegra_channel_buffer *buf)
{

  •   struct vb2_buffer *vb = &buf->buf;
      int err = 0;
    
  •   u32 val, frame_start;
    
  •   u32 val, frame_start, mw_ack_done;
      int bytes_per_line = chan->format.bytesperline;
      int index = 0;
      u32 thresh[TEGRA_CSI_BLOCKS] = { 0 };
      int valid_ports = chan->valid_ports;
    
  •   int state = VB2_BUF_STATE_DONE;
    
      for (index = 0; index < valid_ports; index++) {
              /* Program buffer address by using surface 0 */
    

@@ -285,6 +324,15 @@ static void tegra_channel_capture_frame(struct tegra_channel *chan,
chan->syncpt[index];
tegra_channel_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, val);

  •           /* Program syncpoint */
    
  •           chan->thresh[index] = nvhost_syncpt_incr_max_ext(chan->vi->ndev,
    
  •                           chan->syncpt[index], 1);
    
  •           mw_ack_done = VI_CSI_MW_ACK_DONE(chan->port[index]);
    
  •           val = VI_CFG_VI_INCR_SYNCPT_COND(mw_ack_done) |
    
  •                           chan->syncpt[index];
    
  •           tegra_channel_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, val);
    
  •           csi_write(chan, index,
                      TEGRA_VI_CSI_SINGLE_SHOT, SINGLE_SHOT_CAPTURE);
      }
    

@@ -299,47 +347,28 @@ static void tegra_channel_capture_frame(struct tegra_channel *chan,
dev_err(&chan->video.dev,
“frame start syncpt timeout!%d\n”, index);
tegra_channel_capture_error(chan);

  •                   state = VB2_BUF_STATE_ERROR;
              }
      }
    
  •   if (atomic_read(&chan->is_hdmiin_unplug)) {
    
  •           vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
    
  •           complete(&chan->capture_comp);
    
  •   } else {
    
  •           /* Move buffer to capture done queue */
    
  •           spin_lock(&chan->done_lock);
    
  •           list_add_tail(&buf->queue, &chan->done);
    
  •           spin_unlock(&chan->done_lock);
    
  •   if (atomic_read(&chan->is_hdmiin_unplug))
    
  •           state = VB2_BUF_STATE_ERROR;
    
  •           /* Wait up kthread for capture done */
    
  •           wake_up_interruptible(&chan->done_wait);
    
  •   }
    
  •   /* update time stamp and add buffer to queue */
    
  •   v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
    
  •   tegra_channel_ring_buffer(chan, vb, state);
    

}

-static void tegra_channel_capture_done(struct tegra_channel *chan,

  •                                  struct tegra_channel_buffer *buf)
    

+static void tegra_channel_capture_done(struct tegra_channel *chan)
{

  •   struct vb2_v4l2_buffer *vb = &buf->buf;
    
  •   int err = 0;
    
  •   u32 val, mw_ack_done;
    
  •   int index = 0;
    
  •   u32 thresh[TEGRA_CSI_BLOCKS] = { 0 };
    
  •   int valid_ports = chan->valid_ports;
    
  •   for (index = 0; index < valid_ports; index++) {
    
  •           /* Program syncpoint */
    
  •           thresh[index] = nvhost_syncpt_incr_max_ext(chan->vi->ndev,
    
  •                           chan->syncpt[index], 1);
    
  •   int index;
    
  •           mw_ack_done = VI_CSI_MW_ACK_DONE(chan->port[index]);
    
  •           val = VI_CFG_VI_INCR_SYNCPT_COND(mw_ack_done) |
    
  •                           chan->syncpt[index];
    
  •           tegra_channel_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, val);
    
  •   }
    
  •   if (atomic_read(&chan->is_hdmiin_unplug))
    
  •           return;
    
  •   for (index = 0; index < valid_ports; index++) {
    
  •           err = nvhost_syncpt_wait_timeout_ext(chan->vi->ndev,
    
  •                   chan->syncpt[index], thresh[index],
    
  •   for (index = 0; index < chan->valid_ports; index++) {
    
  •           int err = nvhost_syncpt_wait_timeout_ext(chan->vi->ndev,
    
  •                   chan->syncpt[index], chan->thresh[index],
                      TEGRA_VI_SYNCPT_WAIT_TIMEOUT,
                      NULL,
                      NULL);
    

@@ -347,20 +376,6 @@ static void tegra_channel_capture_done(struct tegra_channel *chan,
dev_err(&chan->video.dev,
“MW_ACK_DONE syncpoint time out!%d\n”, index);
}

  •   if (atomic_read(&chan->is_hdmiin_unplug)) {
    
  •           vb2_buffer_done(&vb->vb2_buf, err < 0 ? VB2_BUF_STATE_ERROR :
    
  •                           VB2_BUF_STATE_DONE);
    
  •           complete(&chan->done_comp);
    
  •   } else {
    
  •           /* Captured one frame */
    
  •           vb->sequence = chan->sequence++;
    
  •           vb->field = V4L2_FIELD_NONE;
    
  •           v4l2_get_timestamp(&vb->timestamp);
    
  •           vb2_set_plane_payload(&vb->vb2_buf, 0, chan->format.sizeimage);
    
  •           vb2_buffer_done(&vb->vb2_buf, err < 0 ? VB2_BUF_STATE_ERROR
    
  •                           : VB2_BUF_STATE_DONE);
    
  •   }
    

}

static int tegra_channel_kthread_capture_start(void *data)
@@ -370,17 +385,17 @@ static int tegra_channel_kthread_capture_start(void *data)

    set_freezable();
  •   while (1) {
    
  •   while (!atomic_read(&chan->is_hdmiin_unplug)) {
    
  •           try_to_freeze();
    
  •           wait_event_interruptible(chan->start_wait,
                                       !list_empty(&chan->capture) ||
                                       kthread_should_stop() ||
                                       atomic_read(&chan->is_hdmiin_unplug));
              if (kthread_should_stop() ||
    
  •               atomic_read(&chan->is_hdmiin_unplug)) {
    
  •                   complete(&chan->capture_comp);
    
  •               atomic_read(&chan->is_hdmiin_unplug))
                      break;
    
  •           }
    
              spin_lock(&chan->start_lock);
              if (list_empty(&chan->capture)) {
    

@@ -396,58 +411,13 @@ static int tegra_channel_kthread_capture_start(void *data)
tegra_channel_capture_frame(chan, buf);
}

  •   return 0;
    

-}

-static int tegra_channel_kthread_capture_done(void *data)
-{

  •   struct tegra_channel *chan = data;
    
  •   struct tegra_channel_buffer *buf;
    
  •   set_freezable();
    
  •   while (1) {
    
  •           try_to_freeze();
    
  •           wait_event_interruptible(chan->done_wait,
    
  •                                    !list_empty(&chan->done) ||
    
  •                                    kthread_should_stop() ||
    
  •                                    atomic_read(&chan->is_hdmiin_unplug));
    
  •           if ((chan->vi->pg_mode &&
    
  •                   kthread_should_stop()) ||
    
  •                   atomic_read(&chan->is_hdmiin_unplug)) {
    
  •                   complete(&chan->done_comp);
    
  •                   break;
    
  •           } else if (kthread_should_stop() &&
    
  •                   list_empty(&chan->done)) {
    
  •                   complete(&chan->done_comp);
    
  •                   break;
    
  •           }
    
  •           spin_lock(&chan->done_lock);
    
  •           if (list_empty(&chan->done)) {
    
  •                   spin_unlock(&chan->done_lock);
    
  •                   continue;
    
  •           }
    
  •           buf = list_entry(chan->done.next,
    
  •                            struct tegra_channel_buffer, queue);
    
  •           list_del_init(&buf->queue);
    
  •           spin_unlock(&chan->done_lock);
    
  •           tegra_channel_capture_done(chan, buf);
    
  •   }
    
  •   complete(&chan->capture_comp);
    
      return 0;
    

}

-static void tegra_channel_queued_buf_done(struct tegra_channel *chan,

  •                                     enum vb2_buffer_state state,
    
  •                                     bool is_capture);
    

static void tegra_channel_stop_kthreads(struct tegra_channel *chan)
{

    mutex_lock(&chan->stop_kthread_lock);
    /* Stop the kthread for capture */
    if (chan->kthread_capture_start) {

@@ -455,13 +425,6 @@ static void tegra_channel_stop_kthreads(struct tegra_channel *chan)
wait_for_completion(&chan->capture_comp);
chan->kthread_capture_start = NULL;
}

  •   if (chan->kthread_capture_done) {
    
  •           kthread_stop(chan->kthread_capture_done);
    
  •           wait_for_completion(&chan->done_comp);
    
  •           chan->kthread_capture_done = NULL;
    
  •   }
    
  •   tegra_channel_queued_buf_done(chan, VB2_BUF_STATE_ERROR, 1);
    
  •   tegra_channel_queued_buf_done(chan, VB2_BUF_STATE_ERROR, 0);
      mutex_unlock(&chan->stop_kthread_lock);
    

}

@@ -504,14 +467,10 @@ void tegra_channel_query_hdmiin_unplug(struct tegra_channel *chan,
return;

                            atomic_set(&chan->is_hdmiin_unplug, 1);
  •                           for (index = 0; index < valid_ports; index++) {
    
  •                                   nvhost_syncpt_cpu_incr_ext(
    
  •                                                   chan->vi->ndev,
    
  •                                                   chan->syncpt[index]);
    
  •                           for (index = 0; index < valid_ports; index++)
                                      nvhost_syncpt_cpu_incr_ext(
                                                      chan->vi->ndev,
                                                      chan->syncpt[index]);
    
  •                           }
    
                              tegra_channel_stop_kthreads(chan);
                      }
    

@@ -583,12 +542,11 @@ static void tegra_channel_buffer_queue(struct vb2_buffer *vb)

/* Return all queued buffers back to videobuf2 */
static void tegra_channel_queued_buf_done(struct tegra_channel *chan,

  •                                     enum vb2_buffer_state state,
    
  •                                     bool is_capture)
    
  •                                     enum vb2_buffer_state state)
    

{
struct tegra_channel_buffer *buf, *nbuf;

  •   spinlock_t *lock = is_capture ? &chan->start_lock : &chan->done_lock;
    
  •   struct list_head *q = is_capture ? &chan->capture : &chan->done;
    
  •   spinlock_t *lock = &chan->start_lock;
    
  •   struct list_head *q = &chan->capture;
    
      spin_lock(lock);
      list_for_each_entry_safe(buf, nbuf, q, queue) {
    

@@ -675,6 +633,14 @@ static void tegra_channel_update_clknbw(struct tegra_channel *chan, u8 on)
mutex_unlock(&chan->vi->bw_update_lock);
}

+static void tegra_channel_init_ring_buffer(struct tegra_channel *chan)
+{

  •   chan->num_buffers = 0;
    
  •   chan->save_index = 0;
    
  •   chan->free_index = 0;
    
  •   chan->sequence = 0;
    

+}
+
static int tegra_channel_start_streaming(struct vb2_queue *vq, u32 count)
{
struct tegra_channel *chan = vb2_get_drv_priv(vq);
@@ -711,9 +677,13 @@ static int tegra_channel_start_streaming(struct vb2_queue *vq, u32 count)
if (ret < 0)
goto error_capture_setup;

  •   chan->sequence = 0;
    
  •   tegra_channel_init_ring_buffer(chan);
      atomic_set(&chan->is_hdmiin_unplug, 0);
    
  •   /* Update clock and bandwidth based on the format */
    
  •   /* perform calibration as sensor started streaming */
    
  •   tegra_channel_update_clknbw(chan, 1);
    
  •   /* Start kthread to capture data to buffer */
      chan->kthread_capture_start = kthread_run(
                                      tegra_channel_kthread_capture_start,
    

@@ -725,17 +695,6 @@ static int tegra_channel_start_streaming(struct vb2_queue *vq, u32 count)
goto error_capture_setup;
}

  •   chan->kthread_capture_done = kthread_run(
    
  •                                   tegra_channel_kthread_capture_done,
    
  •                                   chan, chan->video.name);
    
  •   if (IS_ERR(chan->kthread_capture_done)) {
    
  •           dev_err(&chan->video.dev,
    
  •                   "failed to run kthread for capture done\n");
    
  •           ret = PTR_ERR(chan->kthread_capture_done);
    
  •           goto error_capture_setup;
    
  •   }
    
  •   tegra_channel_update_clknbw(chan, 1);
    
  •   return 0;
    

error_capture_setup:
@@ -746,7 +705,7 @@ error_set_stream:
media_entity_pipeline_stop(&chan->video.entity);
error_pipeline_start:
vq->start_streaming_called = 0;

  •   tegra_channel_queued_buf_done(chan, VB2_BUF_STATE_QUEUED, 1);
    
  •   tegra_channel_queued_buf_done(chan, VB2_BUF_STATE_QUEUED);
    
      return ret;
    

}
@@ -758,6 +717,12 @@ static void tegra_channel_stop_streaming(struct vb2_queue *vq)

    if (!chan->bypass) {
            tegra_channel_stop_kthreads(chan);
  •           /* wait for last frame memory write ack */
    
  •           tegra_channel_capture_done(chan);
    
  •           /* free all the ring buffers */
    
  •           free_ring_buffers(chan, chan->num_buffers);
    
  •           /* dequeue buffers back to app which are in capture queue */
    
  •           tegra_channel_queued_buf_done(chan, VB2_BUF_STATE_ERROR);
    
              if (atomic_read(&chan->is_hdmiin_unplug)) {
                      tegra_channel_write(chan, TEGRA_VI_CFG_CG_CTRL, 0);
    

@@ -1626,14 +1591,10 @@ static int tegra_channel_init(struct tegra_mc_vi *vi, unsigned int index)
chan->num_subdevs = 0;
mutex_init(&chan->video_lock);
INIT_LIST_HEAD(&chan->capture);

  •   INIT_LIST_HEAD(&chan->done);
      init_waitqueue_head(&chan->start_wait);
    
  •   init_waitqueue_head(&chan->done_wait);
      spin_lock_init(&chan->start_lock);
    
  •   spin_lock_init(&chan->done_lock);
      mutex_init(&chan->stop_kthread_lock);
      init_completion(&chan->capture_comp);
    
  •   init_completion(&chan->done_comp);
      atomic_set(&chan->is_hdmiin_unplug, 0);
    
      /* Init video format */
    

diff --git a/drivers/media/platform/tegra/camera/mc_common.h b/drivers/media/platform/tegra/camera/mc_common.h
index 0bb8073b3…ecb3705f2 100644
— a/drivers/media/platform/tegra/camera/mc_common.h
+++ b/drivers/media/platform/tegra/camera/mc_common.h
@@ -34,6 +34,7 @@

#define MAX_FORMAT_NUM 64
#define MAX_SUBDEVICES 4
+#define QUEUED_BUFFERS 4

/**

  • struct tegra_channel_buffer - video channel buffer
    @@ -118,20 +119,21 @@ struct tegra_channel {

    unsigned char port[TEGRA_CSI_BLOCKS];
    unsigned int syncpt[TEGRA_CSI_BLOCKS];
    
  •   unsigned int thresh[TEGRA_CSI_BLOCKS];
      unsigned int buffer_offset[TEGRA_CSI_BLOCKS];
    
  •   unsigned int buffer_state[QUEUED_BUFFERS];
    
  •   struct vb2_buffer *buffers[QUEUED_BUFFERS];
    
  •   unsigned int save_index;
    
  •   unsigned int free_index;
    
  •   unsigned int num_buffers;
    
      struct task_struct *kthread_capture_start;
      wait_queue_head_t start_wait;
    
  •   struct task_struct *kthread_capture_done;
    
  •   wait_queue_head_t done_wait;
      struct vb2_queue queue;
      void *alloc_ctx;
      struct list_head capture;
      spinlock_t start_lock;
    
  •   struct list_head done;
    
  •   spinlock_t done_lock;
      struct completion capture_comp;
    
  •   struct completion done_comp;
    
      void __iomem *csibase[TEGRA_CSI_BLOCKS];
      unsigned int align;
    
1 Like

Hi,
Please have a try to reduce the QUEUED_BUFFERS to try.

kernel/nvidia/include/media/mc_common.h

Hi,
I have the same unresolved problem,I have a try to reduce the QUEUED_BUFFERS,
when #define QUEUED_BUFFERS 3 the camera delay 1 frame;
when #define QUEUED_BUFFERS 2 the camera can’t capture the image, the code select() timeout
Can you help me with this problem? Thanks!

Wating update.

1 Like

We are debugging it. Will update once get result.

Hi,
Please have a try this patch for modify QUEUED_BUFFERS 2

diff --git a/drivers/media/platform/tegra/camera/vi/channel.c b/drivers/media/platform/tegra/camera/vi/channel.c
index 0a07f9d..057678f 100644
--- a/drivers/media/platform/tegra/camera/vi/channel.c
+++ b/drivers/media/platform/tegra/camera/vi/channel.c
@@ -525,7 +525,7 @@ static void add_buffer_to_ring(struct tegra_channel *chan,
 
 static void update_state_to_buffer(struct tegra_channel *chan, int state)
 {
-       int save_index = (chan->save_index - PREVIOUS_BUFFER_DEC_INDEX);
+       int save_index = (chan->save_index - 1);
 
        /* save index decrements by 2 as 3 bufs are added in ring buffer */
        if (save_index < 0)
@@ -565,7 +565,7 @@ void tegra_channel_ring_buffer(struct tegra_channel *chan,
        }
 
        /* release buffer N at N+2 frame start event */
-       if (chan->num_buffers >= (chan->capture_queue_depth - 1))
+       //if (chan->num_buffers >= (chan->capture_queue_depth - 1))
                free_ring_buffers(chan, 1);
 }
2 Likes

We use this patch and found there are some camera shake issue.
Do you have any comments?

May need more information about the camera shake?

I have update two video files:
1)origin_version.mp4: test result with origin version don’t apply patch
origin_version

2)optimize_shake.mp4: est result with optimized version apply follow patch
optimize_shake

Our patch is below

diff --git a/drivers/media/platform/tegra/camera/vi/channel.c b/drivers/media/platform/tegra/camera/vi/channel.c
index 3ea2885..d34f4de 100644
--- a/drivers/media/platform/tegra/camera/vi/channel.c
+++ b/drivers/media/platform/tegra/camera/vi/channel.c
@@ -457,7 +457,11 @@ static void add_buffer_to_ring(struct tegra_channel *chan,
 
 static void update_state_to_buffer(struct tegra_channel *chan, int state)
 {
+#if 0
        int save_index = (chan->save_index - PREVIOUS_BUFFER_DEC_INDEX);
+#else
+       int save_index = (chan->save_index - 1);
+#endif
 
        /* save index decrements by 2 as 3 bufs are added in ring buffer */
        if (save_index < 0)
@@ -492,7 +496,10 @@ void tegra_channel_ring_buffer(struct tegra_channel *chan,
        vb->timestamp.tv_usec = ts->tv_nsec / NSEC_PER_USEC;
 
        /* release buffer N at N+2 frame start event */
+#if 0
        if (chan->num_buffers >= (QUEUED_BUFFERS - 1))
+#endif
+    /* release the the latest one buffer to user space */
                free_ring_buffers(chan, 1);
 }
 
diff --git a/drivers/media/platform/tegra/camera/vi/mc_common.h b/drivers/media/platform/tegra/camera/vi/mc_common.h
index d55837f..61eed58 100644
--- a/drivers/media/platform/tegra/camera/vi/mc_common.h
+++ b/drivers/media/platform/tegra/camera/vi/mc_common.h
@@ -37,7 +37,7 @@
 
 #define MAX_FORMAT_NUM 64
 #define        MAX_SUBDEVICES  4
-#define        QUEUED_BUFFERS  4
+#define        QUEUED_BUFFERS  2
 #define        ENABLE          1
 #define        DISABLE         0
 #define MAX_SYNCPT_PER_CHANNEL 3

We also revert QUEUED_BUFFERS back to 4, the shake is still there.

Try this patch for the shake problem.

diff --git a/drivers/media/platform/tegra/camera/vi/vi4_fops.c b/drivers/media/platform/tegra/camera/vi/vi4_fops.c
index 9bcae78..e481552 100644
--- a/drivers/media/platform/tegra/camera/vi/vi4_fops.c
+++ b/drivers/media/platform/tegra/camera/vi/vi4_fops.c
@@ -206,7 +206,7 @@ static bool vi_notify_wait(struct tegra_channel *chan,
         */
        for (i = 0; i < chan->valid_ports; i++) {
                err = nvhost_syncpt_wait_timeout_ext(chan->vi->ndev,
-                               chan->syncpt[i][SOF_SYNCPT_IDX], thresh[i],
+                               chan->syncpt[i][FE_SYNCPT_IDX], thresh[i],
                                chan->timeout, NULL, NULL);
                if (unlikely(err)) {
                        dev_err(chan->vi->dev,

1 Like

@ShaneCCC Seems shake issue disappeared.

Can you explain more why this fix will work?

Another question is do we have to set QUEUED_BUFFERS to 2? The default is 4.

Yes, set QUEUED_BUFFERS to 2,
You need to apply the ealy path and this one.

1 Like

@ShaneCCC Unfortunately we found another crack issue here.
optimize_crack
You can see when my hands up and down there is one crack line appear on screen.

Can you help me out again.
Thanks.

Could you try
v4l2-ctl --set-ctrl low_latency_mode=0/1

@ShaneCCC
It is screen display issue.
Sorry for your interference!

Would anyone here be able to share their code that achieved trigger mode capture? It seems like I would need to set QUEUED_BUFFERS = 2 and apply the two patches (one, and two), but is reverting the ring buffer logic (as outlined here) necessary? Also, a full example showing trigger capture via v4l2 would be greatly appreciated. Thanks!