Jetson sensor frame row mismatch

Hello,

During owr development of V4L sensor drivers (10 sensors for Jetson Nano A02, Nano B01, TX2, Xavier, Xavier NX - L4T 32.3.1/32.4.3), we had cases when the sensor outputs some more or less frame rows than defined in the driver. All Jetson models by default require exact match of the number of frame rows.

Is it possible to change this default behavior of the kernel? If for example, the sensor outputs 1081 rows, and the driver expects 1080, the streaming goes without errors and the last excess row is discarded.

Another case: the sensor outputs some less rows. The kernel fills zero excess rows in the output frames and the streaming works fine,

Greetings,
Plamen

Please try to modify the REG CSI_CSI_PIXEL_PARSER_A_INTERRUPT_MASK_0 to mask the short frame event to try. Check the TX1 TRM for detail information.

For the more frame should be fine without any modify for Nnao.

Hi ShaneCCC,

I found description of the register CSI_CSI_PIXEL_PARSER_A_INTERRUPT_MASK_0 in the manual Tegra_X1_TRM_DP07225001_v1.3p.pdf:
Chapter “29.16.7 CSI_CSI_PIXEL_PARSER_A_INTERRUPT_MASK_0”.

Do you have in mind:
bit 7 : PPA_SHORT_FRAME_INT_MASK: Interrupt Mask for PPA_SHORT_FRAME.
0 = DISABLED: Do not generate an interrupt when PPA_SHORT_FRAME is set.
1 = ENABLED: Generate an interrupt when PPA_SHORT_FRAME is set.
What is the respective register name in the kernel source files?

Concerning the long frame, we receive FRAME_HEIGHT_LONG_ERROR error on Nano/32.3.1 in
the TEGRA_VI_CSI_ERROR_STATUS register (seem to correspond to VI_CSI_0_ERROR_STATUS_0 in the manual), for example:
[ 356.564780] vi 54080000.vi: tegra_channel_error_status(): TEGRA_VI_CSI_ERROR_STATUS=0x00000008
How to mask this “frame height long” interrupt ?

It’s define in the …/kernel/nvidia/include/media/vi2_registers.h
Also may try VI_CSI_[0…5]_ERROR_INT_MASK

#define	TEGRA_VI_CSI_ERROR_INT_MASK			                0x088
#define TEGRA_CSI_PIXEL_PARSER_INTERRUPT_MASK           0x018

Hi ShaneCCC,

The register TEGRA_VI_CSI_ERROR_INT_MASK seems to fit our needs, because it masks all possible events: short/long frame height, short/long frame width.

We did not found any Nano B01/32.3.1 kernel file, where this register is used.
We tested it in vi2_fops.c by the following code:

static int tegra_channel_capture_setup(struct tegra_channel *chan)
{
. . . . . . .
    for (index = 0; index < chan->valid_ports; index++) {
        csi_write(chan, index, TEGRA_VI_CSI_ERROR_STATUS, 0xFFFFFFFF);
//+++++++
{
        int val = csi_read(chan, index, TEGRA_VI_CSI_ERROR_INT_MASK);
        val |= 0xc;   // set bits 3,2: short/long frame height interrupt mask
        csi_write(chan, index, TEGRA_VI_CSI_ERROR_INT_MASK, val);
        val = csi_read(chan, index, TEGRA_VI_CSI_ERROR_INT_MASK);
        dev_err(&chan->video->dev, "%s(): index=%d TEGRA_VI_CSI_ERROR_INT_MASK=0x%x\n", __func__, index, val);
}
//-------
        csi_write(chan, index, TEGRA_VI_CSI_IMAGE_DEF,
          (bypass_pixel_transform << BYPASS_PXL_TRANSFORM_OFFSET) |
          (format << IMAGE_DEF_FORMAT_OFFSET));
        . . . . .

When the sensor outputs “long frame height”, the kernel crashes and reboots:

[  202.104967] vi 54080000.vi: tegra_channel_error_status(): i=0: TEGRA_VI_CSI_ERROR_STATUS=0x00000008 (Bits 3-0: h>,<, w>,<)
[  202.321150] video4linux video0: tegra_channel_capture_done: MW_ACK_DONE syncpoint time out!0
[  202.330179] vi 54080000.vi: TEGRA_CSI_PIXEL_PARSER_STATUS 0x00000000
[  202.339935] vi 54080000.vi: TEGRA_CSI_CIL_STATUS 0x00000000
[  202.346143] vi 54080000.vi: TEGRA_CSI_CILX_STATUS 0x00000000
[  202.352300] video4linux video0: tegra_channel_capture_setup(): valid_ports=1: width,height=1440,1080 word_count=1800
[  202.363107] video4linux video0: tegra_channel_capture_setup(): index=0 TEGRA_VI_CSI_ERROR_INT_MASK=0xc
[  203.385140] tegra-vii2c 546c0000.i2c: --- register dump for debugging ----
[  203.392667] tegra-vii2c 546c0000.i2c: I2C_CNFG - 0x22c00
[  203.403224] tegra-vii2c 546c0000.i2c: I2C_PACKET_TRANSFER_STATUS - 0x1010001
[  203.410908] tegra-vii2c 546c0000.i2c: I2C_FIFO_CONTROL - 0xe0
[  203.417112] tegra-vii2c 546c0000.i2c: I2C_FIFO_STATUS - 0x800080
[  203.423140] tegra-vii2c 546c0000.i2c: I2C_INT_MASK - 0xac
[  203.428548] tegra-vii2c 546c0000.i2c: I2C_INT_STATUS - 0xc2
[  203.434126] tegra-vii2c 546c0000.i2c: msg->len - 3
[  203.438923] tegra-vii2c 546c0000.i2c: is_msg_write - 1
[  203.444067] tegra-vii2c 546c0000.i2c: buf_remaining - 0
[  203.449300] tegra-vii2c 546c0000.i2c: i2c transfer timed out, addr 0x001a, data 0x30
[  203.457140] regmap_util_write_table_8:regmap_util_write_table:-110
[  203.463156] imx296_vgl 7-001a: imx296_stop_streaming(): imx296_write_table() err=-110
[  203.470982] imx296_vgl 7-001a: imx296_stop_streaming(): err=-110
[  203.470982]
[  203.478469] imx296_vgl 7-001a: Error turning off streaming
[  213.624858] tegra-i2c 7000d000.i2c: pio timed out addr: 0x3c tlen:28 rlen:4
[  213.631829] tegra-i2c 7000d000.i2c: --- register dump for debugging ----
[  213.639585] tegra-i2c 7000d000.i2c: I2C_CNFG - 0x22c00
[  213.645189] tegra-i2c 7000d000.i2c: I2C_PACKET_TRANSFER_STATUS - 0x1010001
[  213.652492] tegra-i2c 7000d000.i2c: I2C_FIFO_CONTROL - 0xe0
[  213.658489] tegra-i2c 7000d000.i2c: I2C_FIFO_STATUS - 0x800081
[  213.664739] tegra-i2c 7000d000.i2c: I2C_INT_MASK - 0x7d
[  213.670384] tegra-i2c 7000d000.i2c: I2C_INT_STATUS - 0xc3
[  213.675799] tegra-i2c 7000d000.i2c: i2c transfer timed out addr: 0x3c
[  222.701159] INFO: rcu_preempt detected stalls on CPUs/tasks:
[  222.706823]  0-...: (3 GPs behind) idle=f67/1/0 softirq=36455/36455 fqs=2509
[  222.713941]  (detected by 1, t=5252 jiffies, g=4837, c=4836, q=870)
[  223.865240] tegra-i2c 7000d000.i2c: pio timed out addr: 0x3c tlen:28 rlen:4
[  223.872208] tegra-i2c 7000d000.i2c: --- register dump for debugging ----
[  223.879856] tegra-i2c 7000d000.i2c: I2C_CNFG - 0x22c00
[  223.885461] tegra-i2c 7000d000.i2c: I2C_PACKET_TRANSFER_STATUS - 0x1010001
[  223.892764] tegra-i2c 7000d000.i2c: I2C_FIFO_CONTROL - 0xe0
[  223.898760] tegra-i2c 7000d000.i2c: I2C_FIFO_STATUS - 0x800081
[  223.905025] tegra-i2c 7000d000.i2c: I2C_INT_MASK - 0x7d
[  223.910671] tegra-i2c 7000d000.i2c: I2C_INT_STATUS - 0xc3
[  223.916088] tegra-i2c 7000d000.i2c: i2c transfer timed out addr: 0x3c
[  223.922577] Failed to set dvfs regulator vdd-core
[  227.277319] INFO: rcu_sched detected stalls on CPUs/tasks:
[  227.282810]  0-...: (1 GPs behind) idle=f67/1/0 softirq=36274/36455 fqs=2491
[  227.289930]  (detected by 1, t=5252 jiffies, g=1324, c=1323, q=20)
[  228.333359] Kernel panic - not syncing: Watchdog detected hard LOCKUP on cpu 0
[  228.340573] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 4.9.140-tegra #62
[  228.347171] Hardware name: NVIDIA Jetson Nano Developer Kit (DT)
[  228.353162] Call trace:
[  228.355605] [<ffffff800808bdb8>] dump_backtrace+0x0/0x198
[  228.360993] [<ffffff800808c37c>] show_stack+0x24/0x30
[  228.366033] [<ffffff800845d820>] dump_stack+0x98/0xc0
[  228.371073] [<ffffff80081c2198>] panic+0x11c/0x298
[  228.375853] [<ffffff8008183114>] watchdog_check_hardlockup_other_cpu+0x11c/0x120
[  228.383232] [<ffffff8008182288>] watchdog_timer_fn+0x98/0x2c0
[  228.388965] [<ffffff800813a738>] __hrtimer_run_queues+0xd8/0x360
[  228.394959] [<ffffff800813b088>] hrtimer_interrupt+0xa8/0x1e0
[  228.400693] [<ffffff8008c06600>] tegra210_timer_isr+0x38/0x48
[  228.406426] [<ffffff8008123260>] __handle_irq_event_percpu+0x68/0x288
[  228.412852] [<ffffff80081234a8>] handle_irq_event_percpu+0x28/0x60
[  228.419017] [<ffffff8008123530>] handle_irq_event+0x50/0x80
[  228.424576] [<ffffff80081272f8>] handle_fasteoi_irq+0xc8/0x1b8
[  228.430395] [<ffffff800812224c>] generic_handle_irq+0x34/0x50
[  228.436127] [<ffffff8008122930>] __handle_domain_irq+0x68/0xc0
[  228.441945] [<ffffff8008080d44>] gic_handle_irq+0x5c/0xb0
[  228.447331] [<ffffff8008082be8>] el1_irq+0xe8/0x18c
[  228.452197] [<ffffff8008bac930>] cpuidle_enter_state+0xb8/0x380
[  228.458103] [<ffffff8008bacc6c>] cpuidle_enter+0x34/0x48
[  228.463401] [<ffffff8008112a1c>] call_cpuidle+0x44/0x70
[  228.468612] [<ffffff8008112d98>] cpu_startup_entry+0x1b0/0x200
[  228.474432] [<ffffff8008092ce8>] secondary_start_kernel+0x190/0x1f8
[  228.480683] [<0000000080f6b1a4>] 0x80f6b1a4
[  228.484857] SMP: stopping secondary CPUs
[  229.547526] SMP: failed to stop secondary CPUs 0,3
[  229.552307] Kernel Offset: disabled
[  229.555787] Memory Limit: none
[  229.566533] Rebooting in 5 seconds..

Are you sure that using this register we can mask long/short frame height?
Where is the right place to set this register?

The code dump may cause by the i2c failed?

The system messages, shown before the start of the streaming are OK and the I2C transfer to sensor registers work fine. If the sensor outputs correct # of rows it’s OK - no kernel panic. When the sensor outputs 1 row more (long frame height), the streaming ends with status for long frame height (bit 3 = 1):

  vi 54080000.vi: tegra_channel_error_status(): i=0: TEGRA_VI_CSI_ERROR_STATUS=0x00000008

and next we see the kernel panic dump.

Obviously the problem is caused by the incorrect setting of register TEGRA_VI_CSI_ERROR_INT_MASK, shown in my previous post:

     csi_write(chan, index, TEGRA_VI_CSI_ERROR_INT_MASK, 0xc);

Without this setting, the streaming with long sensor frame height returns normally with
error status: TEGRA_VI_CSI_ERROR_STATUS=0x00000008

Please also configure the REG VI_CSI_0_ERROR_INT_MASK_0 to mask the frame height long to try.

I believe, that we have tested exactly the same register:

TRM: 31.7.28 VI_CSI_0_ERROR_INT_MASK_0
Offset: 0x62 | Byte Offset: 0x188 | Read/Write: R/W | Reset: 0x00000000 (0bxxxxxxxxxxxxxxxxxxxxxxxxxx000000)

vi2_registers.h:
#define TEGRA_VI_CSI_BASE(x) (0x100 + (x) * 0x100)
#define TEGRA_VI_CSI_ERROR_INT_MASK 0x088

The actual offset seems to be 0x188 ?
Maybe we set this register in the wrong place or time?

vi2_fops.c:

static int tegra_channel_capture_setup(struct tegra_channel *chan)
{
. . . . . . .
    for (index = 0; index < chan->valid_ports; index++) {
        csi_write(chan, index, TEGRA_VI_CSI_ERROR_STATUS, 0xFFFFFFFF);
        csi_write(chan, index, TEGRA_VI_CSI_ERROR_INT_MASK, 0xc);
        . . . . .
}

Could you write 0 to try. Looks like int_mask == 0 means masking error

csi_write(chan, index, TEGRA_VI_CSI_ERROR_INT_MASK, 0x0);

Does not help. 0x0 is the default state of the register after reboot.

Hi plamenk,

Sorry for the late response, is this still an issue to support?

Hi Kayccc,

Yes, we could not find solution of the problem.