This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VM: TDA4VM Problems capturing CSI from Lontium LT7911D

Part Number: TDA4VM

Dear Forum,

we are trying to capture DisplayPort Video with a BeagleBone AI-64 using a Lontium LT7911D DP-to-CSI bridge.

Sadly, this only works sometimes and only for one or a few frames, then the capture stalls.

For testing, we attached the same Test-PCB with the Lontium chip to a Raspberry Pi 5 and using the same driver, there the capture works as expected. So probably I (or the driver) am configuring something wrong.

As the vanilla Linux Kernel does not come with a driver for the LT7911D, I ported one found on the Internet (https://gitlabhost.argos-navy.ru/rockchip/rongpin/rk3588_android12/-/blob/master/kernel-5.10/drivers/media/i2c/lt7911d.c) and modified it a bit. The current version is attached, as well as the Device Tree used.

Originally, the driver did not start/stop the CSI stream. As I found multiple posts that said the output should only start after the capture is ready, I modified the driver to actually do something in s_stream. However, this did also not change the problem. Sadly, I have no description of the "inner workings" of the LT7911D (e.g. register description, firmware, ...) and the datasheet I have does not have sufficient detail. I do know that the firmware running had the filename "LT7911d_dp_to_1port-mipi-csi_1920x1080@60hz_YUV422_20250728_(CKS0x1D8C8E).hex" and this is also the resolution reported:

[   73.892942] m_LT7911D 7-002b: act:1920x1080, total:2200x1125, pixclk:148364000, fps:60
[   73.900861] m_LT7911D 7-002b: hfp:88, hs:44, hbp:148, vfp:4, vs:5, vbp:36
[   73.907639] m_LT7911D 7-002b: inerlaced:0,

I use the following commands to prepare and execute the capture (I added more debug print statements to some of the drivers involved):

# v4l2-ctl -d /dev/v4l-subdev1 --set-dv-bt-timings query
BT timings set
# media-ctl -d 0 --set-v4l2 '"cdns_csi2rx.4504000.csi-bridge":0[fmt:UYVY8_1X16/1920x1080 colorspace:srgb]'
# v4l2-ctl -v width=1920,height=1080,pixelformat=UYVY
# v4l2-ctl --device /dev/video0 --set-fmt-video width=1920,height=1080,pixelformat=UYVY --stream-mmap --stream-to=frame.raw --stream-count=10
[   59.778963] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dmaengine_prep_slave_single, addr = 0xfe600000, len = 0x3f4800
[   59.790337] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dma_async_issue_pending
[   59.799256] m_LT7911D 7-002b: enable_stream: enable

Here, the capture hung without recording anything. When it works, it looks like this:

# v4l2-ctl --device /dev/video0 --set-fmt-video width=1920,height=1080,pixelformat=UYVY --stream-mmap --stream-to=frame.raw --stream-count=1
[ 5523.619795] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dmaengine_prep_slave_single, addr = 0xfe600000, len = 0x3f4800
[ 5523.631169] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dma_async_issue_pending
[ 5523.639805] m_LT7911D 7-002b: enable_stream: enable
[ 5523.662342] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_dma_callback
[ 5523.668429] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dmaengine_prep_slave_single, addr = 0xfea00000, len = 0x3f4800
[ 5523.679807] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dma_async_issue_pending
[ 5523.687798] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dmaengine_prep_slave_single, addr = 0xfee00000, len = 0x3f4800
[ 5523.699163] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dma_async_issue_pending
[ 5523.707144] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dmaengine_prep_slave_single, addr = 0xff200000, len = 0x3f4800
[ 5523.718508] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dma_async_issue_pending
<[ 5523.726626] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_dma_callback
[ 5523.732795] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dmaengine_prep_slave_single, addr = 0xfe600000, len = 0x3f4800
[ 5523.744162] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_start_dma: dma_async_issue_pending
[ 5523.752267] m_LT7911D 7-002b: enable_stream: disable
[ 5523.757761] j721e-csi2rx 4500000.ticsi2rx: ti_csi2rx_stop_dma

I also examined lots of CSI/D-PHY related registers, while the capture was active and hung:

CSIRX:
CSI_RX_IF_VBUS2APB_ERROR_DEBUG               devmem 0x04504074    0x00000000
CSI_RX_IF_VBUS2APB_ERROR_IRQS                devmem 0x04504028    0x00000100
CSI_RX_IF_VBUS2APB_DPHY_STATUS               devmem 0x04504048    0x00222206 / 0x00333306 / 0x00333307
CSI_RX_IF_VBUS2APB_INTEGRATION_DEBUG         devmem 0x04504060    0x10000000
CSI_RX_IF_VBUS2APB_STREAM0_STATUS            devmem 0x04504104    0x80000113
CSI_RX_IF_VBUS2APB_STREAM0_DATA_CFG          devmem 0x04504108    0x00010000
CSI_RX_IF_VBUS2APB_STREAM0_CFG               devmem 0x0450410c    0x00000100

DPHY:
DPHY_RX_VBUS2APB_DL0_RX_DIG_TBIT33           devmem 0x04580290    0x0003D0B8
DPHY_RX_VBUS2APB_DL0_RX_DIG_TBIT34           devmem 0x04580294    0x00008000
DPHY_RX_VBUS2APB_DL0_RX_DIG_TBIT42           devmem 0x045802b4    0x00400800
DPHY_RX_VBUS2APB_DL0_RX_DIG_TBIT43           devmem 0x045802b8    0x00010020
DPHY_RX_VBUS2APB_PCS_TX_DIG_TBIT0            devmem 0x04580b00    0x0000016B
DPHY_RX_VBUS2APB_ISO_PHY_ISO_DL_HS_L0        devmem 0x04580c18    0x00000002 / 0x00000080 / 0x00000000 / 0x00000020 / 0x000000EC
DPHY_RX_VBUS2APB_ISO_PHY_ISO_DL_HS_L1        devmem 0x04580c24    0x000000FF
DPHY_RX_VBUS2APB_ISO_LDD_PHY_ISO_DL_HS_L2    devmem 0x04580c34    0x0000007F
DPHY_RX_VBUS2APB_ISO_LDD_PHY_ISO_DL_HS_L3    devmem 0x04580c40    0x000000D5

Rows with multiple values show where the value changed when calling devmem again.

I also attached a full kernel log of the board booting, then attaching a Display Port output and trying to capture (which hung), then cancelling the capture ~18 seconds later (Ctrl + C).

I hope you can guide me in a direction for further debugging, as I am getting out of ideas... Thank you!

lt7911d.c 

lt7911d.h 

k3-christmann-dra829.dts.txt 

lt7911d_dmesg.txt 

Kind regards,
Stefan Krupop

  • Hi ,

    For testing, we attached the same Test-PCB with the Lontium chip to a Raspberry Pi 5 and using the same driver, there the capture works as expected. So probably I (or the driver) am configuring something wrong.

    Does this mean the driver used when testing on the BeagleBone AI-64 is the same as the driver used with the Raspberry Pi 5?

    Can you send the Raspberry Pi device tree as well? I'd like to compare the two.

    One thing I noticed is that the link frequency output in the dmesg differs with the device tree:

    dmesg:

    [    2.595043] m_LT7911D 7-002b: lt7911d found @ 0x56 (OMAP I2C adapter), using link freq 312500000

    Device-tree:

    				link-frequencies = /bits/ 64 <192000000>;

    Best,
    Jared

  • Thank you for your reply!

    Does this mean the driver used when testing on the BeagleBone AI-64 is the same as the driver used with the Raspberry Pi 5?

    Except for one minor unrelated change to make it compile with a different Kernel: Yes.

    Can you send the Raspberry Pi device tree as well? I'd like to compare the two.

    For the Pi I used a DT overlay. Here it is: 

    /dts-v1/;
    /plugin/;
    
    / {
    	compatible = "brcm,bcm2712";
    
    	i2c_frag: fragment@0 {
    		target = <&i2c_csi_dsi>;
    		__overlay__ {
    			#address-cells = <1>;
    			#size-cells = <0>;
    			status = "okay";
    
    			lt7911d: lt7911d@2b {
    				compatible = "lontium,lt7911d";
    				reg = <0x2b>;
    				status = "okay";
    
    				clocks = <&cam1_clk>;
    				clock-names = "refclk";
    
    				port {
    					lt7911d_0: endpoint {
    						remote-endpoint = <&csi1_ep>;
    						clock-lanes = <0>;
    						clock-noncontinuous;
    						link-frequencies =
    							/bits/ 64 <486000000>;
    					};
    				};
    			};
    		};
    	};
    
    	csi_frag: fragment@1 {
    		target = <&csi1>;
    		csi: __overlay__ {
    			status = "okay";
    
    			port {
    				csi1_ep: endpoint {
    					remote-endpoint = <&lt7911d_0>;
    				};
    			};
    		};
    	};
    
    	fragment@2 {
    		target = <&lt7911d_0>;
    		__overlay__ {
    			data-lanes = <1 2>;
    		};
    	};
    
    	fragment@3 {
    		target = <&lt7911d_0>;
    		__dormant__ {
    			data-lanes = <1 2 3 4>;
    		};
    	};
    
    	fragment@4 {
    		target = <&i2c0if>;
    		__overlay__ {
    			status = "okay";
    		};
    	};
    
    	fragment@5 {
    		target = <&i2c0mux>;
    		__overlay__ {
    			status = "okay";
    		};
    	};
    
    	clk_frag: fragment@6 {
    		target = <&cam1_clk>;
    		__overlay__ {
    			status = "okay";
    			clock-frequency = <27000000>;
    		};
    	};
    
    	fragment@7 {
    		target = <&csi1_ep>;
    		__overlay__ {
    			data-lanes = <1 2>;
    		};
    	};
    
    	fragment@8 {
    		target = <&csi1_ep>;
    		__dormant__ {
    			data-lanes = <1 2 3 4>;
    		};
    	};
    
    	__overrides__ {
    		4lane = <0>, "-2+3-7+8";
    		link-frequency = <&lt7911d_0>,"link-frequencies#0";
    		cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>,
    		       <&csi_frag>, "target:0=",<&csi0>,
    		       <&clk_frag>, "target:0=",<&cam0_clk>,
    		       <&lt7911d>, "clocks:0=",<&cam0_clk>;
    	};
    };
    

    One thing I noticed is that the link frequency output in the dmesg differs with the device tree:

    You are right. The changed link speed in the driver was a later change, after we tried to measure the CSI clock. I did not update the DT then.
    I just tried it again with the same speed in the DT as in the driver, but the problem did not change. I am not even sure whether the link speed from the DT is actually used, I did not find a code path accessing it.

    Kind regards,
    Stefan

  • Hi ,

    Why does your device-tree not have clocks or clocks-names properties, and why do you have "clock-noncontinuous = <1>;" instead of "clock-noncontinuous;"?

    Best,
    Jared

  • Why does your device-tree not have clocks or clocks-names properties

    Which clocks do you mean? The LT7911D driver does not request any and the test PCB has a local oscillator for it.

    why do you have "clock-noncontinuous = <1>;" instead of "clock-noncontinuous;"?

    I got that syntax somewhere on the Internet, I guess. Tried changing it to "clock-noncontinuous;", did not change the behavior.

    Regards,
    Stefan

  • Hi ,

    Which clocks do you mean? The LT7911D driver does not request any and the test PCB has a local oscillator for it.

    clocks = <&cam1_clk>;
    clock-names = "refclk";

    I got that syntax somewhere on the Internet, I guess. Tried changing it to "clock-noncontinuous;", did not change the behavior.

    If the Raspberry Pi device-tree is working without issue, I would follow it as closely as possible. I will say, the link frequency doesn't look like it makes sense in the RPi device tree.


    Except for one minor unrelated change to make it compile with a different Kernel: Yes.

    Have you tested the driver on the original kernel version?

    Why is every instance of xvclk commented out in the driver?

    Best,
    Jared

  • Have you tested the driver on the original kernel version?

    What do you mean by "original"? The current Kernel on the Pi was a slightly different version that the current Kernel on the Beagle Bone, so I had to change the "timer_container_of" (new style) function call to "from_timer" (old style) - that's it.

    Why is every instance of xvclk commented out in the driver?

    Because there is no externally controllable clock that I could enable. The crystal is on the test PCB and always enabled.


    We have the feeling that the issue is already with the TDA4VM not correctly receiving the CSI data.

    In the meantime I ported this commit to our Kernel to print error interrupts that show up during capture: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/media/platform/cadence/cdns-csi2rx.c?h=v6.19-rc5&id=9f2d0da9b8c3477cd5ed4e1ed1e58bb44184561b (I just added a direct print in the interrupt handler, as to see the sequence of errors, not just a summary).

    When trying to capture, all sorts of errors get flagged (but not always all of them):

    [   84.189369] cdns-csi2rx 4514000.csi-bridge: Enabling error IRQs
    [   84.195301] cdns-mipi-dphy-rx 4590000.phy: In cdns_dphy_rx_configure
    [   84.201701] DPHY rate match 11
    [   84.229884] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x21100
    [   84.238389] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [   84.248630] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x1060
    [   84.257046] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [   84.267280] cdns-csi2rx 4514000.csi-bridge: Error interrupt: ECC error detected and corrected
    [   84.275782] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Unrecoverable ECC error
    [   84.283511] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x1040
    [   84.291927] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [   84.302160] cdns-csi2rx 4514000.csi-bridge: Error interrupt: ECC error detected and corrected
    [   84.310681] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x20
    [   84.318923] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Unrecoverable ECC error

    A colleague of mine thinks the problem could have something to to with the "HS-settle time". Do you agree? How could I test?

    Thank you!

    Kind regards,
    Stefan

  • Also, we saw "i2190 - CSI: CSI_RX_IF may enter unknown state following an incomplete frame" in the Errata.

    I did not see any mention of this in the Linux drivers, do you know wether this issue could explain the problem we are seeing (hanging) and what would be the recommended fix?

    Thank you!

    Kind regards,
    Stefan

  • Hi ,

    What do you mean by "original"? The current Kernel on the Pi was a slightly different version that the current Kernel on the Beagle Bone, so I had to change the "timer_container_of" (new style) function call to "from_timer" (old style) - that's it.

    I meant the Pi kernel version (not the exact kernel, but both would be based off the same Linux kernel).

    A colleague of mine thinks the problem could have something to to with the "HS-settle time". Do you agree? How could I test?

    If you had access to the datasheet, you could adjust the parameters in the device through I2C commands.

    I did not see any mention of this in the Linux drivers, do you know wether this issue could explain the problem we are seeing (hanging) and what would be the recommended fix?

    It could be explain the problem. I think your problem is more likely, the timing of the device does not line up with the TDA4, and it's causing issues with the header packets.


    Are there any loose connections in the cables?

    Best,
    Jared

  • I think your problem is more likely, the timing of the device does not line up with the TDA4, and it's causing issues with the header packets.

    Sadly, our contact at Lontium has fallen silent. It currently seems unlikely we will get more information than we already have, thus no specific timing information. Would it be possible to measure the necessary information off of an oscilloscope capture of the actual transmission? If yes, which parameters should we look for?

    Are there any loose connections in the cables?

    I hope not ;-) It is a standard "Raspberry camera" style FFC with FFC connectors at both ends. I also tried a different cable without change.

    Kind regards,
    Stefan

  • Hi ,

    Can you try adding the link-frequency to the csi2rx0_in_sensor node, so that the device tree resembles our current imx219 device trees?

    Best,
    Jared

  • Can you try adding the link-frequency to the csi2rx0_in_sensor node, so that the device tree resembles our current imx219 device trees?

    Could you please point me towards the DT you mean? I found this one https://github.com/TexasInstruments/ti-linux-kernel/blob/ti-linux-6.18.y/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-dual-imx219.dtso, but it also does not contain the link-frequency in the CSI endpoint.

    However, I updated the DT to try and match it with the one linked above plus adding the link-frequency. I also re-enabled the xvclk-code. Sadly, it did not change the result, capture still hangs:

    # dmesg|grep -i lt
    [    0.000000] alternatives: applying boot alternatives
    [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 1048576
    [    0.000324] pid_max: default: 32768 minimum: 301
    [    0.011048] alternatives: applying system-wide alternatives
    [    0.020229] 26656 pages in range for non-PLT usage
    [    0.020236] 518176 pages in range for PLT usage
    [    0.028074] /bus@100000/ticsi2rx@4510000/csi-bridge@4514000: Fixed dependency cycle(s) with /bus@100000/i2c@2010000/lt7911d@2b
    [    0.028323] /bus@100000/i2c@2010000/lt7911d@2b: Fixed dependency cycle(s) with /bus@100000/ticsi2rx@4510000/csi-bridge@4514000
    [    0.032396] /bus@100000/ticsi2rx@4510000/csi-bridge@4514000: Fixed dependency cycle(s) with /bus@100000/i2c@2010000/lt7911d@2b
    [    0.034684] /bus@100000/i2c@2010000/lt7911d@2b: Fixed dependency cycle(s) with /bus@100000/ticsi2rx@4510000/csi-bridge@4514000
    [    0.039076] iommu: Default domain type: Translated
    [    0.048388] PCI: CLS 0 bytes, default 64
    [    0.108965] Synopsys Designware Multimedia Card Interface Driver
    [    0.109306] sdhci-pltfm: SDHCI platform and OF driver helper
    [    0.279930] /bus@100000/ticsi2rx@4510000/csi-bridge@4514000: Fixed dependency cycle(s) with /bus@100000/i2c@2010000/lt7911d@2b
    [    0.279977] /bus@100000/i2c@2010000/lt7911d@2b: Fixed dependency cycle(s) with /bus@100000/ticsi2rx@4510000/csi-bridge@4514000
    [    2.672255] LT7911D 5-002b: driver version: 00.01.02
    [    2.693939] LT7911D 5-002b: check chipid ok, id:0x516
    [    2.699156] LT7911D 5-002b: failed to get plugin det irq, maybe no use
    [    2.713200] LT7911D 5-002b: failed to register plugin det irq (-22), maybe no use
    [    2.720723] m_LT7911D 5-002b: lt7911d found @ 0x56 (OMAP I2C adapter)
    [    4.214225] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 7: entity 'm_LT7911D 5-002b'
    [    4.214229] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 8: source pad 'm_LT7911D 5-002b':0
    [    4.214233] cdns-csi2rx 4514000.csi-bridge: Bound m_LT7911D 5-002b pad: 0
    # [  605.986261] m_LT7911D 5-002b: act:1920x1080, total:2200x1125, pixclk:148366000, fps:60
    [  605.994178] m_LT7911D 5-002b: hfp:88, hs:44, hbp:148, vfp:4, vs:5, vbp:36
    [  606.000957] m_LT7911D 5-002b: inerlaced:0,
    [  606.006102] m_LT7911D 5-002b: Format_change: New format: 1920x1080p59.94 (2200x1125)
    v4l2-ctl -d /dev/v4l-subdev1 --set-dv-bt-timings query
    BT timings set
    # media-ctl -d 1 --set-v4l2 '"cdns_csi2rx.4514000.csi-bridge":0[fmt:UYVY8_1X16/1
    920x1080 colorspace:srgb]'
    # v4l2-ctl -v width=1920,height=1080,pixelformat=UYVY
    # v4l2-ctl --device /dev/video0 --set-fmt-video width=1920,height=1080,pixelform
    at=UYVY --stream-mmap --stream-to=frame.raw --stream-count=10
    [  665.120709] cdns-csi2rx 4514000.csi-bridge: Enabling error IRQs
    [  665.126670] cdns-mipi-dphy-rx 4590000.phy: In cdns_dphy_rx_configure
    [  665.133023] DPHY rate match 11
    [  665.145521] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x21100
    [  665.154027] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  665.164272] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x1060
    [  665.172689] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  665.182924] cdns-csi2rx 4514000.csi-bridge: Error interrupt: ECC error detected and corrected
    [  665.191425] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Unrecoverable ECC error
    [  665.199155] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x20010
    [  665.207657] cdns-csi2rx 4514000.csi-bridge: Error interrupt: CRC error
    [  665.214168] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x1060
    [  665.222583] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  665.232818] cdns-csi2rx 4514000.csi-bridge: Error interrupt: ECC error detected and corrected
    [  665.241318] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Unrecoverable ECC error
    [  665.249043] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x20010
    [  665.257544] cdns-csi2rx 4514000.csi-bridge: Error interrupt: CRC error
    ^C[  668.323131] j721e-csi2rx 4510000.ticsi2rx: ti_csi2rx_stop_dma
    
    #

    To not loose track, here are the current versions of the driver and DT as well as a full dmesg of boot and the capture above:

    // SPDX-License-Identifier: GPL-2.0
    /*
     * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
     *
     * lt7911d type-c/DP to MIPI CSI-2 bridge driver.
     *
     * Author: Jianwei Fan <jianwei.fan@rock-chips.com>
     *
     * V0.0X01.0X00 first version.
     * V0.0X01.0X01 add 4K30 support.
     * V0.0X01.0X02 add poll resolution change.
     *
     */
    
    #include <linux/clk.h>
    #include <linux/delay.h>
    #include <linux/gpio/consumer.h>
    #include <linux/hdmi.h>
    #include <linux/i2c.h>
    #include <linux/interrupt.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/of_graph.h>
    #include <linux/slab.h>
    #include <linux/timer.h>
    #include <linux/v4l2-dv-timings.h>
    #include <linux/version.h>
    #include <linux/videodev2.h>
    #include <linux/workqueue.h>
    #include <linux/compat.h>
    #include <media/v4l2-ctrls.h>
    #include <media/v4l2-device.h>
    #include <media/v4l2-dv-timings.h>
    #include <media/v4l2-event.h>
    #include <media/v4l2-fwnode.h>
    #include "lt7911d.h"
    
    #define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x02)
    
    static int debug;
    module_param(debug, int, 0644);
    MODULE_PARM_DESC(debug, "debug level (0-3)");
    
    #define I2C_MAX_XFER_SIZE	128
    #define POLL_INTERVAL_MS	1000
    
    #define LT7911D_LINK_FREQ	312500000
    #define LT7911D_PIXEL_RATE	156250000
    
    #ifdef LT7911D_OUT_RGB
    #define LT7911D_MEDIA_BUS_FMT		MEDIA_BUS_FMT_BGR888_1X24
    #else
    #define LT7911D_MEDIA_BUS_FMT		MEDIA_BUS_FMT_UYVY8_1X16 //MEDIA_BUS_FMT_UYVY8_2X8
    #endif
    
    #define LT7911D_NAME			"LT7911D"
    
    static const s64 link_freq_menu_items[] = {
    	LT7911D_LINK_FREQ,
    };
    
    struct lt7911d_state {
    	struct v4l2_mbus_config_mipi_csi2 bus;
    	struct v4l2_subdev sd;
    	struct media_pad pad;
    	struct v4l2_ctrl_handler hdl;
    	struct i2c_client *i2c_client;
    	struct mutex confctl_mutex;
    	struct v4l2_ctrl *detect_tx_5v_ctrl;
    	struct v4l2_ctrl *audio_sampling_rate_ctrl;
    	struct v4l2_ctrl *audio_present_ctrl;
    	struct v4l2_ctrl *link_freq;
    	struct v4l2_ctrl *pixel_rate;
    	struct delayed_work delayed_work_enable_hotplug;
    	struct delayed_work delayed_work_res_change;
    	struct v4l2_dv_timings timings;
    	struct clk *xvclk;
    	struct gpio_desc *reset_gpio;
    	struct gpio_desc *plugin_det_gpio;
    	struct gpio_desc *power_gpio;
    	struct work_struct work_i2c_poll;
    	struct timer_list timer;
    	const struct lt7911d_mode *cur_mode;
    	bool nosignal;
    	bool enable_hdcp;
    	bool is_audio_present;
    	int plugin_irq;
    	u32 mbus_fmt_code;
    	u8 csi_lanes_in_use;
    	u32 audio_sampling_rate;
    };
    
    static const struct v4l2_dv_timings_cap lt7911d_timings_cap = {
    	.type = V4L2_DV_BT_656_1120,
    	.reserved = { 0 },
    	V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 400000000,
    			V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
    			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
    			V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED |
    			V4L2_DV_BT_CAP_REDUCED_BLANKING |
    			V4L2_DV_BT_CAP_CUSTOM)
    };
    
    struct lt7911d_mode {
    	u32 width;
    	u32 height;
    	struct v4l2_fract max_fps;
    	u32 hts_def;
    	u32 vts_def;
    	u32 exp_def;
    };
    
    static const struct lt7911d_mode supported_modes[] = {
    	{
    		.width = 3840,
    		.height = 2160,
    		.max_fps = {
    			.numerator = 10000,
    			.denominator = 300000,
    		},
    		.hts_def = 4400,
    		.vts_def = 2250,
    	}, {
    		.width = 1920,
    		.height = 1080,
    		.max_fps = {
    			.numerator = 10000,
    			.denominator = 600000,
    		},
    		.hts_def = 2200,
    		.vts_def = 1125,
    	}, {
    		.width = 1280,
    		.height = 720,
    		.max_fps = {
    			.numerator = 10000,
    			.denominator = 600000,
    		},
    		.hts_def = 1650,
    		.vts_def = 750,
    	}, {
    		.width = 720,
    		.height = 576,
    		.max_fps = {
    			.numerator = 10000,
    			.denominator = 500000,
    		},
    		.hts_def = 864,
    		.vts_def = 625,
    	}, {
    		.width = 720,
    		.height = 480,
    		.max_fps = {
    			.numerator = 10000,
    			.denominator = 600000,
    		},
    		.hts_def = 858,
    		.vts_def = 525,
    	},
    };
    
    static void lt7911d_format_change(struct v4l2_subdev *sd);
    static int lt7911d_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd);
    static int lt7911d_s_dv_timings(struct v4l2_subdev *sd, unsigned int pad,
    				struct v4l2_dv_timings *timings);
    
    static inline struct lt7911d_state *to_state(struct v4l2_subdev *sd)
    {
    	return container_of(sd, struct lt7911d_state, sd);
    }
    
    static void i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    	struct i2c_client *client = lt7911d->i2c_client;
    	int err;
    	u8 buf[2] = { 0xFF, reg >> 8};
    	u8 reg_addr = reg & 0xFF;
    	struct i2c_msg msgs[3];
    
    	msgs[0].addr = client->addr;
    	msgs[0].flags = 0;
    	msgs[0].len = 2;
    	msgs[0].buf = buf;
    
    	msgs[1].addr = client->addr;
    	msgs[1].flags = 0;
    	msgs[1].len = 1;
    	msgs[1].buf = &reg_addr;
    
    	msgs[2].addr = client->addr;
    	msgs[2].flags = I2C_M_RD;
    	msgs[2].len = n;
    	msgs[2].buf = values;
    
    	err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
    	if (err != ARRAY_SIZE(msgs)) {
    		v4l2_err(sd, "%s: reading register 0x%x from 0x%x failed\n",
    				__func__, reg, client->addr);
    	}
    
    	if (!debug)
    		return;
    
    	switch (n) {
    	case 1:
    		v4l2_info(sd, "I2C read 0x%04x = 0x%02x\n",
    			reg, values[0]);
    		break;
    	case 2:
    		v4l2_info(sd, "I2C read 0x%04x = 0x%02x%02x\n",
    			reg, values[1], values[0]);
    		break;
    	case 4:
    		v4l2_info(sd, "I2C read 0x%04x = 0x%02x%02x%02x%02x\n",
    			reg, values[3], values[2], values[1], values[0]);
    		break;
    	default:
    		v4l2_info(sd, "I2C read %d bytes from address 0x%04x\n",
    			n, reg);
    	}
    }
    
    static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    	struct i2c_client *client = lt7911d->i2c_client;
    	int err, i;
    	struct i2c_msg msgs[2];
    	u8 data[I2C_MAX_XFER_SIZE];
    	u8 buf[2] = { 0xFF, reg >> 8};
    
    	if ((1 + n) > I2C_MAX_XFER_SIZE) {
    		n = I2C_MAX_XFER_SIZE - 1;
    		v4l2_warn(sd, "i2c wr reg=%04x: len=%d is too big!\n",
    			  reg, 1 + n);
    	}
    
    	msgs[0].addr = client->addr;
    	msgs[0].flags = 0;
    	msgs[0].len = 2;
    	msgs[0].buf = buf;
    
    	msgs[1].addr = client->addr;
    	msgs[1].flags = 0;
    	msgs[1].len = 1 + n;
    	msgs[1].buf = data;
    
    	data[0] = reg & 0xff;
    	for (i = 0; i < n; i++)
    		data[1 + i] = values[i];
    
    	err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
    	if (err < 0) {
    		v4l2_err(sd, "%s: writing register 0x%x from 0x%x failed\n",
    				__func__, reg, client->addr);
    		return;
    	}
    
    	if (!debug)
    		return;
    
    	switch (n) {
    	case 1:
    		v4l2_info(sd, "I2C write 0x%04x = 0x%02x\n",
    				reg, data[1]);
    		break;
    	case 2:
    		v4l2_info(sd, "I2C write 0x%04x = 0x%02x%02x\n",
    				reg, data[2], data[1]);
    		break;
    	case 4:
    		v4l2_info(sd, "I2C write 0x%04x = 0x%02x%02x%02x%02x\n",
    				reg, data[4], data[3], data[2], data[1]);
    		break;
    	default:
    		v4l2_info(sd, "I2C write %d bytes from address 0x%04x\n",
    				n, reg);
    	}
    }
    
    static u8 i2c_rd8(struct v4l2_subdev *sd, u16 reg)
    {
    	u32 val;
    
    	i2c_rd(sd, reg, (u8 __force *)&val, 1);
    	return val;
    }
    
    static void i2c_wr8(struct v4l2_subdev *sd, u16 reg, u8 val)
    {
    	i2c_wr(sd, reg, &val, 1);
    }
    
    static void lt7911d_i2c_enable(struct v4l2_subdev *sd)
    {
    	i2c_wr8(sd, I2C_EN_REG, I2C_ENABLE);
    }
    
    static void lt7911d_i2c_disable(struct v4l2_subdev *sd)
    {
    	i2c_wr8(sd, I2C_EN_REG, I2C_DISABLE);
    }
    
    static inline bool tx_5v_power_present(struct v4l2_subdev *sd)
    {
    	bool ret;
    	int val, i, cnt;
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	/* if not use plugin det gpio */
    	if (!lt7911d->plugin_det_gpio)
    		return true;
    
    	cnt = 0;
    	for (i = 0; i < 5; i++) {
    		val = gpiod_get_value(lt7911d->plugin_det_gpio);
    		if (val > 0)
    			cnt++;
    		usleep_range(500, 600);
    	}
    
    	ret = (cnt >= 3) ? true : false;
    	v4l2_dbg(1, debug, sd, "%s: %d\n", __func__, ret);
    
    	return ret;
    }
    
    static inline bool no_signal(struct v4l2_subdev *sd)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	v4l2_dbg(1, debug, sd, "%s no signal:%d\n", __func__,
    			lt7911d->nosignal);
    
    	return lt7911d->nosignal;
    }
    
    static inline bool audio_present(struct v4l2_subdev *sd)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	return lt7911d->is_audio_present;
    }
    
    static int get_audio_sampling_rate(struct v4l2_subdev *sd)
    {
    	static const int code_to_rate[] = {
    		44100, 0, 48000, 32000, 22050, 384000, 24000, 352800,
    		88200, 768000, 96000, 705600, 176400, 0, 192000, 0
    	};
    
    	if (no_signal(sd))
    		return 0;
    
    	return code_to_rate[2];
    }
    
    static inline unsigned int fps_calc(const struct v4l2_bt_timings *t)
    {
    	if (!V4L2_DV_BT_FRAME_HEIGHT(t) || !V4L2_DV_BT_FRAME_WIDTH(t))
    		return 0;
    
    	return DIV_ROUND_CLOSEST((unsigned int)t->pixelclock,
    			V4L2_DV_BT_FRAME_HEIGHT(t) * V4L2_DV_BT_FRAME_WIDTH(t));
    }
    
    static bool lt7911d_rcv_supported_res(struct v4l2_subdev *sd, u32 width,
    		u32 height)
    {
    	u32 i;
    
    	for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
    		if ((supported_modes[i].width == width) &&
    		    (supported_modes[i].height == height)) {
    			break;
    		}
    	}
    
    	if (i == ARRAY_SIZE(supported_modes)) {
    		v4l2_err(sd, "%s do not support res wxh: %dx%d\n", __func__,
    				width, height);
    		return false;
    	} else {
    		return true;
    	}
    }
    
    static int lt7911d_get_detected_timings(struct v4l2_subdev *sd,
    				     struct v4l2_dv_timings *timings)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    	struct v4l2_bt_timings *bt = &timings->bt;
    	u32 hact, vact, htotal, vtotal;
    	u32 hbp, hs, hfp, vbp, vs, vfp;
    	u32 pixel_clock, fps, halt_pix_clk;
    	u8 clk_h, clk_m, clk_l;
    	u8 value, val_h, val_l;
    
    	memset(timings, 0, sizeof(struct v4l2_dv_timings));
    
    	lt7911d_i2c_enable(sd);
    	i2c_wr8(sd, FM_CLK_SEL, AD_HALF_PIX_CLK);
    	mdelay(10);
    	clk_h = i2c_rd8(sd, FREQ_METER_H);
    	clk_m = i2c_rd8(sd, FREQ_METER_M);
    	clk_l = i2c_rd8(sd, FREQ_METER_L);
    	halt_pix_clk = (((clk_h & 0xf) << 16) | (clk_m << 8) | clk_l);
    	pixel_clock = halt_pix_clk * 2 * 1000;
    
    	i2c_wr8(sd, RG_MK_PRESET_SEL, SOURCE_DP_RX);
    	mdelay(10);
    	val_h = i2c_rd8(sd, HTOTAL_H);
    	val_l = i2c_rd8(sd, HTOTAL_L);
    	htotal = ((val_h << 8) | val_l) * 2;
    	val_h = i2c_rd8(sd, VTOTAL_H);
    	val_l = i2c_rd8(sd, VTOTAL_L);
    	vtotal = (val_h << 8) | val_l;
    	val_h = i2c_rd8(sd, HACT_H);
    	val_l = i2c_rd8(sd, HACT_L);
    	hact = ((val_h << 8) | val_l) * 2;
    	val_h = i2c_rd8(sd, VACT_H);
    	val_l = i2c_rd8(sd, VACT_L);
    	vact = (val_h << 8) | val_l;
    	val_h = i2c_rd8(sd, HS_H);
    	val_l = i2c_rd8(sd, HS_L);
    	hs = ((val_h << 8) | val_l) * 2;
    	value = i2c_rd8(sd, VS);
    	vs = value;
    	val_h = i2c_rd8(sd, HFP_H);
    	val_l = i2c_rd8(sd, HFP_L);
    	hfp = ((val_h << 8) | val_l) * 2;
    	value = i2c_rd8(sd, VFP);
    	vfp = value;
    	val_h = i2c_rd8(sd, HBP_H);
    	val_l = i2c_rd8(sd, HBP_L);
    	hbp = ((val_h << 8) | val_l) * 2;
    	value = i2c_rd8(sd, VBP);
    	vbp = value;
    
    	lt7911d_i2c_disable(sd);
    
    	if (!lt7911d_rcv_supported_res(sd, hact, vact)) {
    		lt7911d->nosignal = true;
    		v4l2_err(sd, "%s: rcv err res, return no signal!\n", __func__);
    		return -EINVAL;
    	}
    
    	lt7911d->nosignal = false;
    	lt7911d->is_audio_present = true;
    	timings->type = V4L2_DV_BT_656_1120;
    	bt->interlaced = V4L2_DV_PROGRESSIVE;
    	bt->width = hact;
    	bt->height = vact;
    	bt->vsync = vs;
    	bt->hsync = hs;
    	bt->pixelclock = pixel_clock;
    	bt->hfrontporch = hfp;
    	bt->vfrontporch = vfp;
    	bt->hbackporch = hbp;
    	bt->vbackporch = vbp;
    	fps = fps_calc(bt);
    
    	v4l2_info(sd, "act:%dx%d, total:%dx%d, pixclk:%d, fps:%d\n",
    			hact, vact, htotal, vtotal, pixel_clock, fps);
    	v4l2_info(sd, "hfp:%d, hs:%d, hbp:%d, vfp:%d, vs:%d, vbp:%d\n",
    			bt->hfrontporch, bt->hsync, bt->hbackporch,
    			bt->vfrontporch, bt->vsync, bt->vbackporch);
    	v4l2_info(sd, "inerlaced:%d,\n", bt->interlaced);
    
    	return 0;
    }
    
    static void lt7911d_delayed_work_enable_hotplug(struct work_struct *work)
    {
    	struct delayed_work *dwork = to_delayed_work(work);
    	struct lt7911d_state *lt7911d = container_of(dwork,
    			struct lt7911d_state, delayed_work_enable_hotplug);
    	struct v4l2_subdev *sd = &lt7911d->sd;
    
    	v4l2_ctrl_s_ctrl(lt7911d->detect_tx_5v_ctrl, tx_5v_power_present(sd));
    }
    
    static void lt7911d_delayed_work_res_change(struct work_struct *work)
    {
    	struct delayed_work *dwork = to_delayed_work(work);
    	struct lt7911d_state *lt7911d = container_of(dwork,
    			struct lt7911d_state, delayed_work_res_change);
    	struct v4l2_subdev *sd = &lt7911d->sd;
    
    	lt7911d_format_change(sd);
    }
    
    static int lt7911d_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	return v4l2_ctrl_s_ctrl(lt7911d->detect_tx_5v_ctrl,
    			tx_5v_power_present(sd));
    }
    
    static int lt7911d_s_ctrl_audio_sampling_rate(struct v4l2_subdev *sd)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	return v4l2_ctrl_s_ctrl(lt7911d->audio_sampling_rate_ctrl,
    			get_audio_sampling_rate(sd));
    }
    
    static int lt7911d_s_ctrl_audio_present(struct v4l2_subdev *sd)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	return v4l2_ctrl_s_ctrl(lt7911d->audio_present_ctrl,
    			audio_present(sd));
    }
    
    static int lt7911d_update_controls(struct v4l2_subdev *sd)
    {
    	int ret = 0;
    
    	ret |= lt7911d_s_ctrl_detect_tx_5v(sd);
    	ret |= lt7911d_s_ctrl_audio_sampling_rate(sd);
    	ret |= lt7911d_s_ctrl_audio_present(sd);
    
    	return ret;
    }
    
    static inline void enable_stream(struct v4l2_subdev *sd, bool enable)
    {
    	v4l2_dbg(2, debug, sd, "%s: %sable\n",
    			__func__, enable ? "en" : "dis");
    	lt7911d_i2c_enable(sd);
    	i2c_wr8(sd, STREAM_CTL, enable ? ENABLE_STREAM : DISABLE_STREAM);
    	lt7911d_i2c_disable(sd);
    }
    
    static void lt7911d_format_change(struct v4l2_subdev *sd)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    	struct v4l2_dv_timings timings;
    	const struct v4l2_event lt7911d_ev_fmt = {
    		.type = V4L2_EVENT_SOURCE_CHANGE,
    		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
    	};
    
    	if (lt7911d_get_detected_timings(sd, &timings)) {
    		enable_stream(sd, false);
    
    		v4l2_dbg(1, debug, sd, "%s: No signal\n", __func__);
    	} else {
    		if (!v4l2_match_dv_timings(&lt7911d->timings, &timings, 0, false)) {
    			enable_stream(sd, false);
    			/* automatically set timing rather than set by user */
    			lt7911d_s_dv_timings(sd, 0, &timings);
    			v4l2_print_dv_timings(sd->name,
    					"Format_change: New format: ",
    					&timings, false);
    		}
    	}
    
    	if (sd->devnode)
    		v4l2_subdev_notify_event(sd, &lt7911d_ev_fmt);
    }
    
    static int lt7911d_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	schedule_delayed_work(&lt7911d->delayed_work_res_change, HZ / 20);
    	*handled = true;
    
    	return 0;
    }
    
    static irqreturn_t lt7911d_res_change_irq_handler(int irq, void *dev_id)
    {
    	struct lt7911d_state *lt7911d = dev_id;
    	bool handled;
    
    	lt7911d_isr(&lt7911d->sd, 0, &handled);
    
    	return handled ? IRQ_HANDLED : IRQ_NONE;
    }
    
    static irqreturn_t plugin_detect_irq_handler(int irq, void *dev_id)
    {
    	struct lt7911d_state *lt7911d = dev_id;
    
    	/* control hpd output level after 25ms */
    	schedule_delayed_work(&lt7911d->delayed_work_enable_hotplug,
    			HZ / 40);
    
    	return IRQ_HANDLED;
    }
    
    static void lt7911d_irq_poll_timer(struct timer_list *t)
    {
    	struct lt7911d_state *lt7911d = timer_container_of(lt7911d, t, timer);
    
    	schedule_work(&lt7911d->work_i2c_poll);
    	mod_timer(&lt7911d->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS));
    }
    
    static void lt7911d_work_i2c_poll(struct work_struct *work)
    {
    	struct lt7911d_state *lt7911d = container_of(work,
    			struct lt7911d_state, work_i2c_poll);
    	struct v4l2_subdev *sd = &lt7911d->sd;
    
    	lt7911d_format_change(sd);
    }
    
    static int lt7911d_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
    				    struct v4l2_event_subscription *sub)
    {
    	switch (sub->type) {
    	case V4L2_EVENT_SOURCE_CHANGE:
    		return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
    	case V4L2_EVENT_CTRL:
    		return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
    	default:
    		return -EINVAL;
    	}
    }
    
    static int lt7911d_g_input_status(struct v4l2_subdev *sd, u32 *status)
    {
    	*status = 0;
    	*status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0;
    
    	v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status);
    
    	return 0;
    }
    
    static int lt7911d_s_dv_timings(struct v4l2_subdev *sd, unsigned int pad,
    				 struct v4l2_dv_timings *timings)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	if (!timings)
    		return -EINVAL;
    
    	if (debug)
    		v4l2_print_dv_timings(sd->name, "s_dv_timings: ",
    				timings, false);
    
    	if (v4l2_match_dv_timings(&lt7911d->timings, timings, 0, false)) {
    		v4l2_dbg(1, debug, sd, "%s: no change\n", __func__);
    		return 0;
    	}
    
    	if (!v4l2_valid_dv_timings(timings,
    				&lt7911d_timings_cap, NULL, NULL)) {
    		v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__);
    		return -ERANGE;
    	}
    
    	lt7911d->timings = *timings;
    
    	enable_stream(sd, false);
    
    	return 0;
    }
    
    static int lt7911d_g_dv_timings(struct v4l2_subdev *sd, unsigned int pad,
    				struct v4l2_dv_timings *timings)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	*timings = lt7911d->timings;
    
    	return 0;
    }
    
    static int lt7911d_enum_dv_timings(struct v4l2_subdev *sd,
    				struct v4l2_enum_dv_timings *timings)
    {
    	if (timings->pad != 0)
    		return -EINVAL;
    
    	return v4l2_enum_dv_timings_cap(timings,
    			&lt7911d_timings_cap, NULL, NULL);
    }
    
    static int lt7911d_query_dv_timings(struct v4l2_subdev *sd, unsigned int pad,
    				struct v4l2_dv_timings *timings)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	*timings = lt7911d->timings;
    	if (debug)
    		v4l2_print_dv_timings(sd->name,
    				"query_dv_timings: ", timings, false);
    
    	if (!v4l2_valid_dv_timings(timings, &lt7911d_timings_cap, NULL,
    				NULL)) {
    		v4l2_dbg(1, debug, sd, "%s: timings out of range\n",
    				__func__);
    
    		return -ERANGE;
    	}
    
    	return 0;
    }
    
    static int lt7911d_dv_timings_cap(struct v4l2_subdev *sd,
    				struct v4l2_dv_timings_cap *cap)
    {
    	if (cap->pad != 0)
    		return -EINVAL;
    
    	*cap = lt7911d_timings_cap;
    
    	return 0;
    }
    
    static int lt7911d_g_mbus_config(struct v4l2_subdev *sd,
    			unsigned int pad, struct v4l2_mbus_config *cfg)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	cfg->type = V4L2_MBUS_CSI2_DPHY;
    
    	cfg->bus.mipi_csi2.flags = V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK;
    	cfg->bus.mipi_csi2.num_data_lanes = lt7911d->csi_lanes_in_use;
    
    	return 0;
    }
    
    static int lt7911d_s_stream(struct v4l2_subdev *sd, int enable)
    {
    	enable_stream(sd, enable);
    
    	return 0;
    }
    
    static int lt7911d_enum_mbus_code(struct v4l2_subdev *sd,
    			struct v4l2_subdev_state *sd_state,
    			struct v4l2_subdev_mbus_code_enum *code)
    {
    	switch (code->index) {
    	case 0:
    		code->code = LT7911D_MEDIA_BUS_FMT;
    		break;
    
    	default:
    		return -EINVAL;
    	}
    
    	return 0;
    }
    
    static int lt7911d_enum_frame_sizes(struct v4l2_subdev *sd,
    				   struct v4l2_subdev_state *sd_state,
    				   struct v4l2_subdev_frame_size_enum *fse)
    {
    	if (fse->index >= ARRAY_SIZE(supported_modes))
    		return -EINVAL;
    
    	if (fse->code != LT7911D_MEDIA_BUS_FMT)
    		return -EINVAL;
    
    	fse->min_width  = supported_modes[fse->index].width;
    	fse->max_width  = supported_modes[fse->index].width;
    	fse->max_height = supported_modes[fse->index].height;
    	fse->min_height = supported_modes[fse->index].height;
    
    	return 0;
    }
    
    static int lt7911d_get_fmt(struct v4l2_subdev *sd,
    			struct v4l2_subdev_state *sd_state,
    			struct v4l2_subdev_format *format)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	mutex_lock(&lt7911d->confctl_mutex);
    	format->format.code = lt7911d->mbus_fmt_code;
    	format->format.width = lt7911d->timings.bt.width;
    	format->format.height = lt7911d->timings.bt.height;
    	format->format.field =
    		lt7911d->timings.bt.interlaced ?
    		V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
    	format->format.colorspace = V4L2_COLORSPACE_SRGB;
    	mutex_unlock(&lt7911d->confctl_mutex);
    
    	v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field code:%d\n",
    			__func__, format->format.code, format->format.width,
    			format->format.height, format->format.field);
    
    	return 0;
    }
    
    static int lt7911d_enum_frame_interval(struct v4l2_subdev *sd,
    				struct v4l2_subdev_state *sd_state,
    				struct v4l2_subdev_frame_interval_enum *fie)
    {
    	if (fie->index >= ARRAY_SIZE(supported_modes))
    		return -EINVAL;
    
    	fie->code = LT7911D_MEDIA_BUS_FMT;
    
    	fie->width = supported_modes[fie->index].width;
    	fie->height = supported_modes[fie->index].height;
    	fie->interval = supported_modes[fie->index].max_fps;
    
    	return 0;
    }
    
    static int lt7911d_get_reso_dist(const struct lt7911d_mode *mode,
    				struct v4l2_mbus_framefmt *framefmt)
    {
    	return abs(mode->width - framefmt->width) +
    		abs(mode->height - framefmt->height);
    }
    
    static const struct lt7911d_mode *
    lt7911d_find_best_fit(struct v4l2_subdev_format *fmt)
    {
    	struct v4l2_mbus_framefmt *framefmt = &fmt->format;
    	int dist;
    	int cur_best_fit = 0;
    	int cur_best_fit_dist = -1;
    	unsigned int i;
    
    	for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
    		dist = lt7911d_get_reso_dist(&supported_modes[i], framefmt);
    		if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
    			cur_best_fit_dist = dist;
    			cur_best_fit = i;
    		}
    	}
    
    	return &supported_modes[cur_best_fit];
    }
    
    static int lt7911d_set_fmt(struct v4l2_subdev *sd,
    			struct v4l2_subdev_state *sd_state,
    			struct v4l2_subdev_format *format)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    	const struct lt7911d_mode *mode;
    
    	/* is overwritten by get_fmt */
    	u32 code = format->format.code;
    	int ret = lt7911d_get_fmt(sd, sd_state, format);
    
    	format->format.code = code;
    
    	if (ret)
    		return ret;
    
    	switch (code) {
    	case LT7911D_MEDIA_BUS_FMT:
    		break;
    
    	default:
    		return -EINVAL;
    	}
    
    	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
    		return 0;
    
    	lt7911d->mbus_fmt_code = format->format.code;
    	mode = lt7911d_find_best_fit(format);
    	lt7911d->cur_mode = mode;
    	enable_stream(sd, false);
    
    	return 0;
    }
    
    static int lt7911d_g_frame_interval(struct v4l2_subdev *sd,
    			struct v4l2_subdev_state *sd_state,
    			struct v4l2_subdev_frame_interval *fi)
    {
    	struct lt7911d_state *lt7911d = to_state(sd);
    	const struct lt7911d_mode *mode = lt7911d->cur_mode;
    
    	mutex_lock(&lt7911d->confctl_mutex);
    	fi->interval = mode->max_fps;
    	mutex_unlock(&lt7911d->confctl_mutex);
    
    	return 0;
    }
    
    static const struct v4l2_subdev_core_ops lt7911d_core_ops = {
    	.interrupt_service_routine = lt7911d_isr,
    	.subscribe_event = lt7911d_subscribe_event,
    	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
    };
    
    static const struct v4l2_subdev_video_ops lt7911d_video_ops = {
    	.g_input_status = lt7911d_g_input_status,
    	.s_stream = lt7911d_s_stream,
    };
    
    static const struct v4l2_subdev_pad_ops lt7911d_pad_ops = {
    	.enum_mbus_code = lt7911d_enum_mbus_code,
    	.enum_frame_size = lt7911d_enum_frame_sizes,
    	.enum_frame_interval = lt7911d_enum_frame_interval,
    	.get_frame_interval = lt7911d_g_frame_interval,
    	.set_fmt = lt7911d_set_fmt,
    	.get_fmt = lt7911d_get_fmt,
    	.s_dv_timings = lt7911d_s_dv_timings,
    	.g_dv_timings = lt7911d_g_dv_timings,
    	.query_dv_timings = lt7911d_query_dv_timings,
    	.enum_dv_timings = lt7911d_enum_dv_timings,
    	.dv_timings_cap = lt7911d_dv_timings_cap,
    	.get_mbus_config = lt7911d_g_mbus_config,
    };
    
    static const struct v4l2_subdev_ops lt7911d_ops = {
    	.core = &lt7911d_core_ops,
    	.video = &lt7911d_video_ops,
    	.pad = &lt7911d_pad_ops,
    };
    
    #define V4L2_CID_USER_RK_BASE (V4L2_CID_USER_BASE + 0x1080)
    #define RK_V4L2_CID_AUDIO_SAMPLING_RATE (V4L2_CID_USER_RK_BASE + 0x100)
    #define RK_V4L2_CID_AUDIO_PRESENT (V4L2_CID_USER_RK_BASE + 0x101)
    
    static const struct v4l2_ctrl_config lt7911d_ctrl_audio_sampling_rate = {
    	.id = RK_V4L2_CID_AUDIO_SAMPLING_RATE,
    	.name = "Audio sampling rate",
    	.type = V4L2_CTRL_TYPE_INTEGER,
    	.min = 0,
    	.max = 768000,
    	.step = 1,
    	.def = 0,
    	.flags = V4L2_CTRL_FLAG_READ_ONLY,
    };
    
    static const struct v4l2_ctrl_config lt7911d_ctrl_audio_present = {
    	.id = RK_V4L2_CID_AUDIO_PRESENT,
    	.name = "Audio present",
    	.type = V4L2_CTRL_TYPE_BOOLEAN,
    	.min = 0,
    	.max = 1,
    	.step = 1,
    	.def = 0,
    	.flags = V4L2_CTRL_FLAG_READ_ONLY,
    };
    
    static int lt7911d_init_v4l2_ctrls(struct lt7911d_state *lt7911d)
    {
    	struct v4l2_subdev *sd;
    	int ret;
    
    	sd = &lt7911d->sd;
    	ret = v4l2_ctrl_handler_init(&lt7911d->hdl, 5);
    	if (ret)
    		return ret;
    
    	lt7911d->link_freq = v4l2_ctrl_new_int_menu(&lt7911d->hdl, NULL,
    			V4L2_CID_LINK_FREQ,
    			ARRAY_SIZE(link_freq_menu_items) - 1, 0,
    			link_freq_menu_items);
    	lt7911d->pixel_rate = v4l2_ctrl_new_std(&lt7911d->hdl, NULL,
    			V4L2_CID_PIXEL_RATE,
    			0, LT7911D_PIXEL_RATE, 1, LT7911D_PIXEL_RATE);
    
    	lt7911d->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&lt7911d->hdl,
    			NULL, V4L2_CID_DV_RX_POWER_PRESENT,
    			0, 1, 0, 0);
    
    	lt7911d->audio_sampling_rate_ctrl =
    		v4l2_ctrl_new_custom(&lt7911d->hdl,
    				&lt7911d_ctrl_audio_sampling_rate, NULL);
    	lt7911d->audio_present_ctrl = v4l2_ctrl_new_custom(&lt7911d->hdl,
    			&lt7911d_ctrl_audio_present, NULL);
    
    	sd->ctrl_handler = &lt7911d->hdl;
    	if (lt7911d->hdl.error) {
    		ret = lt7911d->hdl.error;
    		v4l2_err(sd, "cfg v4l2 ctrls failed! ret:%d\n", ret);
    		return ret;
    	}
    
    	__v4l2_ctrl_s_ctrl(lt7911d->link_freq, link_freq_menu_items[0]);
    	__v4l2_ctrl_s_ctrl_int64(lt7911d->pixel_rate, LT7911D_PIXEL_RATE);
    
    	if (lt7911d_update_controls(sd)) {
    		ret = -ENODEV;
    		v4l2_err(sd, "update v4l2 ctrls failed! ret:%d\n", ret);
    		return ret;
    	}
    
    	return 0;
    }
    
    #ifdef CONFIG_OF
    static int lt7911d_probe_of(struct lt7911d_state *lt7911d)
    {
    	struct device *dev = &lt7911d->i2c_client->dev;
    	struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
    	struct device_node *ep;
    	int ret;
    
    	lt7911d->power_gpio = devm_gpiod_get_optional(dev, "power",
    			GPIOD_OUT_LOW);
    	if (IS_ERR(lt7911d->power_gpio)) {
    		dev_err(dev, "failed to get power gpio\n");
    		ret = PTR_ERR(lt7911d->power_gpio);
    		return ret;
    	}
    
    	lt7911d->reset_gpio = devm_gpiod_get_optional(dev, "reset",
    			GPIOD_OUT_HIGH);
    	if (IS_ERR(lt7911d->reset_gpio)) {
    		dev_err(dev, "failed to get reset gpio\n");
    		ret = PTR_ERR(lt7911d->reset_gpio);
    		return ret;
    	}
    
    	lt7911d->plugin_det_gpio = devm_gpiod_get_optional(dev, "plugin-det",
    			GPIOD_IN);
    	if (IS_ERR(lt7911d->plugin_det_gpio)) {
    		dev_err(dev, "failed to get plugin det gpio\n");
    		ret = PTR_ERR(lt7911d->plugin_det_gpio);
    		return ret;
    	}
    
    	ep = of_graph_get_next_endpoint(dev->of_node, NULL);
    	if (!ep) {
    		dev_err(dev, "missing endpoint node\n");
    		return -EINVAL;
    	}
    
    	ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint);
    	if (ret) {
    		dev_err(dev, "failed to parse endpoint\n");
    		goto put_node;
    	}
    
    	if (endpoint.bus_type != V4L2_MBUS_CSI2_DPHY ||
    			endpoint.bus.mipi_csi2.num_data_lanes == 0) {
    		dev_err(dev, "missing CSI-2 properties in endpoint\n");
    		ret = -EINVAL;
    		goto free_endpoint;
    	}
    
    	lt7911d->xvclk = devm_clk_get(dev, "xvclk");
    	if (IS_ERR(lt7911d->xvclk)) {
    		dev_err(dev, "failed to get xvclk\n");
    		ret = -EINVAL;
    		goto free_endpoint;
    	}
    
    	ret = clk_prepare_enable(lt7911d->xvclk);
    	if (ret) {
    		dev_err(dev, "Failed! to enable xvclk\n");
    		goto free_endpoint;
    	}
    
    	lt7911d->csi_lanes_in_use = endpoint.bus.mipi_csi2.num_data_lanes;
    	lt7911d->bus = endpoint.bus.mipi_csi2;
    	lt7911d->enable_hdcp = false;
    
    	gpiod_set_value(lt7911d->power_gpio, 1);
    	usleep_range(2000, 3000);
    	gpiod_set_value(lt7911d->reset_gpio, 0);
    
    	ret = 0;
    
    free_endpoint:
    	v4l2_fwnode_endpoint_free(&endpoint);
    put_node:
    	of_node_put(ep);
    	return ret;
    }
    #else
    static inline int lt7911d_probe_of(struct lt7911d_state *state)
    {
    	return -ENODEV;
    }
    #endif
    static int lt7911d_check_chip_id(struct lt7911d_state *lt7911d)
    {
    	struct device *dev = &lt7911d->i2c_client->dev;
    	struct v4l2_subdev *sd = &lt7911d->sd;
    	u8 id_h, id_l;
    	u32 chipid;
    	int ret = 0;
    
    	lt7911d_i2c_enable(sd);
    	id_l  = i2c_rd8(sd, CHIPID_REGL);
    	id_h  = i2c_rd8(sd, CHIPID_REGH);
    	lt7911d_i2c_disable(sd);
    
    	chipid = (id_h << 8) | id_l;
    	if (chipid != LT7911D_CHIPID) {
    		dev_err(dev, "chipid err, read:%#x, expect:%#x\n",
    				chipid, LT7911D_CHIPID);
    		return -EINVAL;
    	}
    	dev_info(dev, "check chipid ok, id:%#x", chipid);
    
    	return ret;
    }
    
    static int lt7911d_probe(struct i2c_client *client)
    {
    	struct lt7911d_state *lt7911d;
    	struct v4l2_subdev *sd;
    	struct device *dev = &client->dev;
    	int err;
    
    	dev_info(dev, "driver version: %02x.%02x.%02x",
    		DRIVER_VERSION >> 16,
    		(DRIVER_VERSION & 0xff00) >> 8,
    		DRIVER_VERSION & 0x00ff);
    
    	lt7911d = devm_kzalloc(dev, sizeof(struct lt7911d_state), GFP_KERNEL);
    	if (!lt7911d)
    		return -ENOMEM;
    
    	sd = &lt7911d->sd;
    	lt7911d->i2c_client = client;
    	lt7911d->cur_mode = &supported_modes[0];
    	lt7911d->mbus_fmt_code = LT7911D_MEDIA_BUS_FMT;
    
    	err = lt7911d_probe_of(lt7911d);
    	if (err) {
    		v4l2_err(sd, "lt7911d_parse_of failed! err:%d\n", err);
    		return err;
    	}
    
    	err = lt7911d_check_chip_id(lt7911d);
    	if (err < 0)
    		return err;
    
    	mutex_init(&lt7911d->confctl_mutex);
    	err = lt7911d_init_v4l2_ctrls(lt7911d);
    	if (err)
    		goto err_free_hdl;
    
    	client->flags |= I2C_CLIENT_SCCB;
    #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
    	v4l2_i2c_subdev_init(sd, client, &lt7911d_ops);
    	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
    #endif
    
    #if defined(CONFIG_MEDIA_CONTROLLER)
    	lt7911d->pad.flags = MEDIA_PAD_FL_SOURCE;
    	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
    	err = media_entity_pads_init(&sd->entity, 1, &lt7911d->pad);
    	if (err < 0) {
    		v4l2_err(sd, "media entity init failed! err:%d\n", err);
    		goto err_free_hdl;
    	}
    #endif
    
    	snprintf(sd->name, sizeof(sd->name), "m_%s %s",
    		 LT7911D_NAME, dev_name(sd->dev));
    	err = v4l2_async_register_subdev_sensor(sd);
    	if (err < 0) {
    		v4l2_err(sd, "v4l2 register subdev failed! err:%d\n", err);
    		goto err_clean_entity;
    	}
    
    	INIT_DELAYED_WORK(&lt7911d->delayed_work_enable_hotplug,
    			lt7911d_delayed_work_enable_hotplug);
    	INIT_DELAYED_WORK(&lt7911d->delayed_work_res_change,
    			lt7911d_delayed_work_res_change);
    
    	if (lt7911d->i2c_client->irq) {
    		v4l2_dbg(1, debug, sd, "cfg lt7911d irq!\n");
    		err = devm_request_threaded_irq(dev,
    				lt7911d->i2c_client->irq,
    				NULL, lt7911d_res_change_irq_handler,
    				IRQF_TRIGGER_RISING | IRQF_ONESHOT,
    				"lt7911d", lt7911d);
    		if (err) {
    			v4l2_err(sd, "request irq failed! err:%d\n", err);
    			goto err_work_queues;
    		}
    	} else {
    		v4l2_dbg(1, debug, sd, "no irq, cfg poll!\n");
    		INIT_WORK(&lt7911d->work_i2c_poll, lt7911d_work_i2c_poll);
    		timer_setup(&lt7911d->timer, lt7911d_irq_poll_timer, 0);
    		lt7911d->timer.expires = jiffies +
    				       msecs_to_jiffies(POLL_INTERVAL_MS);
    		add_timer(&lt7911d->timer);
    	}
    
    	lt7911d->plugin_irq = gpiod_to_irq(lt7911d->plugin_det_gpio);
    	if (lt7911d->plugin_irq < 0)
    		dev_err(dev, "failed to get plugin det irq, maybe no use\n");
    
    	err = devm_request_threaded_irq(dev, lt7911d->plugin_irq, NULL,
    			plugin_detect_irq_handler, IRQF_TRIGGER_FALLING |
    			IRQF_TRIGGER_RISING | IRQF_ONESHOT, "lt7911d",
    			lt7911d);
    	if (err)
    		dev_err(dev, "failed to register plugin det irq (%d), maybe no use\n", err);
    
    	err = v4l2_ctrl_handler_setup(sd->ctrl_handler);
    	if (err) {
    		v4l2_err(sd, "v4l2 ctrl handler setup failed! err:%d\n", err);
    		goto err_work_queues;
    	}
    
    	v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
    			client->addr << 1, client->adapter->name);
    
    	return 0;
    
    err_work_queues:
    	if (!lt7911d->i2c_client->irq)
    		flush_work(&lt7911d->work_i2c_poll);
    	cancel_delayed_work(&lt7911d->delayed_work_enable_hotplug);
    	cancel_delayed_work(&lt7911d->delayed_work_res_change);
    err_clean_entity:
    #if defined(CONFIG_MEDIA_CONTROLLER)
    	media_entity_cleanup(&sd->entity);
    #endif
    err_free_hdl:
    	v4l2_ctrl_handler_free(&lt7911d->hdl);
    	mutex_destroy(&lt7911d->confctl_mutex);
    	return err;
    }
    
    static void lt7911d_remove(struct i2c_client *client)
    {
    	struct v4l2_subdev *sd = i2c_get_clientdata(client);
    	struct lt7911d_state *lt7911d = to_state(sd);
    
    	if (!lt7911d->i2c_client->irq) {
    		timer_delete_sync(&lt7911d->timer);
    		flush_work(&lt7911d->work_i2c_poll);
    	}
    	cancel_delayed_work_sync(&lt7911d->delayed_work_enable_hotplug);
    	cancel_delayed_work_sync(&lt7911d->delayed_work_res_change);
    	v4l2_async_unregister_subdev(sd);
    	v4l2_device_unregister_subdev(sd);
    #if defined(CONFIG_MEDIA_CONTROLLER)
    	media_entity_cleanup(&sd->entity);
    #endif
    	v4l2_ctrl_handler_free(&lt7911d->hdl);
    	mutex_destroy(&lt7911d->confctl_mutex);
    	clk_disable_unprepare(lt7911d->xvclk);
    }
    
    #if IS_ENABLED(CONFIG_OF)
    static const struct of_device_id lt7911d_of_match[] = {
    	{ .compatible = "lontium,lt7911d" },
    	{},
    };
    MODULE_DEVICE_TABLE(of, lt7911d_of_match);
    #endif
    
    static struct i2c_driver lt7911d_driver = {
    	.driver = {
    		.name = LT7911D_NAME,
    		.of_match_table = of_match_ptr(lt7911d_of_match),
    	},
    	.probe = lt7911d_probe,
    	.remove = lt7911d_remove,
    };
    
    static int __init lt7911d_driver_init(void)
    {
    	return i2c_add_driver(&lt7911d_driver);
    }
    
    static void __exit lt7911d_driver_exit(void)
    {
    	i2c_del_driver(&lt7911d_driver);
    }
    
    device_initcall_sync(lt7911d_driver_init);
    module_exit(lt7911d_driver_exit);
    
    MODULE_DESCRIPTION("Lontium lt7911d HDMI to CSI-2 bridge driver");
    MODULE_AUTHOR("Jianwei Fan <jianwei.fan@rock-chips.com>");
    MODULE_LICENSE("GPL v2");
    
     7587.lt7911d.h 
    // SPDX-License-Identifier: GPL-2.0-only OR MIT
    /*
     * https://beagleboard.org/ai-64
     * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/
     * Copyright (C) 2022-2024 Jason Kridner, BeagleBoard.org Foundation
     * Copyright (C) 2022-2024 Robert Nelson, BeagleBoard.org Foundation
     */
    
    /dts-v1/;
    
    #include "k3-j721e.dtsi"
    #include <dt-bindings/gpio/gpio.h>
    #include <dt-bindings/input/input.h>
    #include <dt-bindings/leds/common.h>
    #include <dt-bindings/net/ti-dp83867.h>
    #include <dt-bindings/phy/phy-cadence.h>
    
    / {
    	compatible = "beagle,j721e-beagleboneai64", "ti,j721e";
    	model = "BeagleBoard.org BeagleBone AI-64";
    
    	aliases {
    		serial0 = &wkup_uart0;
    		serial2 = &main_uart0;
    		mmc0 = &main_sdhci0;
    		mmc1 = &main_sdhci1;
    		i2c0 = &wkup_i2c0;
    		i2c1 = &main_i2c6;
    		i2c2 = &main_i2c2;
    		i2c3 = &main_i2c4;
    	};
    
    	chosen {
    		stdout-path = "serial2:115200n8";
    	};
    
    	memory@80000000 {
    		device_type = "memory";
    		/* 4G RAM */
    		reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
    		      <0x00000008 0x80000000 0x00000000 0x80000000>;
    	};
    
    	reserved_memory: reserved-memory {
    		#address-cells = <2>;
    		#size-cells = <2>;
    		ranges;
    
    		secure_ddr: optee@9e800000 {
    			reg = <0x00 0x9e800000 0x00 0x01800000>;
    			no-map;
    		};
    
    		mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa0000000 0x00 0x100000>;
    			no-map;
    		};
    
    		mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa0100000 0x00 0xf00000>;
    			no-map;
    		};
    
    		mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa1000000 0x00 0x100000>;
    			no-map;
    		};
    
    		mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa1100000 0x00 0xf00000>;
    			no-map;
    		};
    
    		main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa2000000 0x00 0x100000>;
    			no-map;
    		};
    
    		main_r5fss0_core0_memory_region: r5f-memory@a2100000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa2100000 0x00 0xf00000>;
    			no-map;
    		};
    
    		main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa3000000 0x00 0x100000>;
    			no-map;
    		};
    
    		main_r5fss0_core1_memory_region: r5f-memory@a3100000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa3100000 0x00 0xf00000>;
    			no-map;
    		};
    
    		main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa4000000 0x00 0x100000>;
    			no-map;
    		};
    
    		main_r5fss1_core0_memory_region: r5f-memory@a4100000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa4100000 0x00 0xf00000>;
    			no-map;
    		};
    
    		main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa5000000 0x00 0x100000>;
    			no-map;
    		};
    
    		main_r5fss1_core1_memory_region: r5f-memory@a5100000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa5100000 0x00 0xf00000>;
    			no-map;
    		};
    
    		c66_0_dma_memory_region: c66-dma-memory@a6000000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa6000000 0x00 0x100000>;
    			no-map;
    		};
    
    		c66_0_memory_region: c66-memory@a6100000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa6100000 0x00 0xf00000>;
    			no-map;
    		};
    
    		c66_1_dma_memory_region: c66-dma-memory@a7000000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa7000000 0x00 0x100000>;
    			no-map;
    		};
    
    		c66_1_memory_region: c66-memory@a7100000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa7100000 0x00 0xf00000>;
    			no-map;
    		};
    
    		c71_0_dma_memory_region: c71-dma-memory@a8000000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa8000000 0x00 0x100000>;
    			no-map;
    		};
    
    		c71_0_memory_region: c71-memory@a8100000 {
    			compatible = "shared-dma-pool";
    			reg = <0x00 0xa8100000 0x00 0xf00000>;
    			no-map;
    		};
    
    		rtos_ipc_memory_region: ipc-memories@aa000000 {
    			reg = <0x00 0xaa000000 0x00 0x01c00000>;
    			alignment = <0x1000>;
    			no-map;
    		};
    		
    		cma: cma@0 {
    			compatible = "shared-dma-pool";
    			reusable;
    			reg = <0x0 0xf8000000 0x0 0x8000000>;
    			linux,cma-default;
    		};
    	};
    
    	gpio_keys: gpio-keys {
    		compatible = "gpio-keys";
    		pinctrl-names = "default";
    		pinctrl-0 = <&sw_pwr_pins_default>;
    
    		button-1 {
    			label = "BOOT";
    			linux,code = <BTN_0>;
    			gpios = <&wkup_gpio0 0 GPIO_ACTIVE_LOW>;
    		};
    
    		button-2 {
    			label = "POWER";
    			linux,code = <KEY_POWER>;
    			gpios = <&wkup_gpio0 4 GPIO_ACTIVE_LOW>;
    		};
    	};
    
    	leds {
    		compatible = "gpio-leds";
    		pinctrl-names = "default";
    		pinctrl-0 = <&led_pins_default>;
    
    		led-0 {
    			gpios = <&main_gpio0 96 GPIO_ACTIVE_HIGH>;
    			function = LED_FUNCTION_HEARTBEAT;
    			linux,default-trigger = "heartbeat";
    		};
    
    		led-1 {
    			gpios = <&main_gpio0 95 GPIO_ACTIVE_HIGH>;
    			function = LED_FUNCTION_DISK_ACTIVITY;
    			linux,default-trigger = "mmc0";
    		};
    
    		led-2 {
    			gpios = <&main_gpio0 97 GPIO_ACTIVE_HIGH>;
    			function = LED_FUNCTION_CPU;
    			linux,default-trigger = "cpu";
    		};
    
    		led-3 {
    			gpios = <&main_gpio0 110 GPIO_ACTIVE_HIGH>;
    			function = LED_FUNCTION_DISK_ACTIVITY;
    			linux,default-trigger = "mmc1";
    		};
    
    		led-4 {
    			gpios = <&main_gpio0 109 GPIO_ACTIVE_HIGH>;
    			function = LED_FUNCTION_WLAN;
    			default-state = "off";
    		};
    	};
    
    	evm_12v0: regulator-0 {
    		/* main supply */
    		compatible = "regulator-fixed";
    		regulator-name = "evm_12v0";
    		regulator-min-microvolt = <12000000>;
    		regulator-max-microvolt = <12000000>;
    		regulator-always-on;
    		regulator-boot-on;
    	};
    
    	vsys_3v3: regulator-1 {
    		/* Output of LMS140 */
    		compatible = "regulator-fixed";
    		regulator-name = "vsys_3v3";
    		regulator-min-microvolt = <3300000>;
    		regulator-max-microvolt = <3300000>;
    		vin-supply = <&evm_12v0>;
    		regulator-always-on;
    		regulator-boot-on;
    	};
    
    	vsys_5v0: regulator-2 {
    		/* Output of LM5140 */
    		compatible = "regulator-fixed";
    		regulator-name = "vsys_5v0";
    		regulator-min-microvolt = <5000000>;
    		regulator-max-microvolt = <5000000>;
    		vin-supply = <&evm_12v0>;
    		regulator-always-on;
    		regulator-boot-on;
    	};
    
    	vdd_mmc1: regulator-3 {
    		compatible = "regulator-fixed";
    		pinctrl-names = "default";
    		pinctrl-0 = <&sd_pwr_en_pins_default>;
    		regulator-name = "vdd_mmc1";
    		regulator-min-microvolt = <3300000>;
    		regulator-max-microvolt = <3300000>;
    		regulator-boot-on;
    		enable-active-high;
    		vin-supply = <&vsys_3v3>;
    		gpio = <&main_gpio0 82 GPIO_ACTIVE_HIGH>;
    	};
    
    	vdd_sd_dv_alt: regulator-4 {
    		compatible = "regulator-gpio";
    		pinctrl-names = "default";
    		pinctrl-0 = <&vdd_sd_dv_alt_pins_default>;
    		regulator-name = "tlv71033";
    		regulator-min-microvolt = <1800000>;
    		regulator-max-microvolt = <3300000>;
    		regulator-boot-on;
    		vin-supply = <&vsys_5v0>;
    		gpios = <&main_gpio0 117 GPIO_ACTIVE_HIGH>;
    		states = <1800000 0x0>,
    			 <3300000 0x1>;
    	};
    
    	dp_pwr_3v3: regulator-5 {
    		compatible = "regulator-fixed";
    		pinctrl-names = "default";
    		pinctrl-0 = <&dp0_3v3_en_pins_default>;
    		regulator-name = "dp-pwr";
    		regulator-min-microvolt = <3300000>;
    		regulator-max-microvolt = <3300000>;
    		gpio = <&main_gpio0 49 GPIO_ACTIVE_HIGH>; /* DP0_PWR_SW_EN */
    		enable-active-high;
    	};
    
    	dp0: connector {
    		compatible = "dp-connector";
    		label = "DP0";
    		type = "full-size";
    		dp-pwr-supply = <&dp_pwr_3v3>;
    
    		port {
    			dp_connector_in: endpoint {
    				remote-endpoint = <&dp0_out>;
    			};
    		};
    	};
    
    	clk_lt7911d_fixed: lt7911d-xvclk {
    		compatible = "fixed-clock";
    		#clock-cells = <0>;
    		clock-frequency = <27000000>;
            };
    	
    	tc358743_clk: tc358743_clk {
    		#clock-cells = <0>;
    		compatible = "fixed-clock";
    		clock-frequency = <27000000>;
    		status = "okay";
            };
    };
    
    &main_pmx0 {
    	led_pins_default: led-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x184, PIN_INPUT, 7) /* (T23) RGMII5_RD0.GPIO0_96 */
    			J721E_IOPAD(0x180, PIN_INPUT, 7) /* (R23) RGMII5_RD1.GPIO0_95 */
    			J721E_IOPAD(0x188, PIN_INPUT, 7) /* (Y28) RGMII6_TX_CTL.GPIO0_97 */
    			J721E_IOPAD(0x1bc, PIN_INPUT, 7) /* (V24) MDIO0_MDC.GPIO0_110 */
    			J721E_IOPAD(0x1b8, PIN_INPUT, 7) /* (V26) MDIO0_MDIO.GPIO0_109 */
    		>;
    	};
    
    	main_mmc1_pins_default: main-mmc1-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x254, PIN_INPUT, 0) /* (R29) MMC1_CMD */
    			J721E_IOPAD(0x250, PIN_INPUT, 0) /* (P25) MMC1_CLK */
    			J721E_IOPAD(0x2ac, PIN_INPUT, 0) /* (P25) MMC1_CLKLB */
    			J721E_IOPAD(0x24c, PIN_INPUT, 0) /* (R24) MMC1_DAT0 */
    			J721E_IOPAD(0x248, PIN_INPUT, 0) /* (P24) MMC1_DAT1 */
    			J721E_IOPAD(0x244, PIN_INPUT, 0) /* (R25) MMC1_DAT2 */
    			J721E_IOPAD(0x240, PIN_INPUT, 0) /* (R26) MMC1_DAT3 */
    			J721E_IOPAD(0x258, PIN_INPUT, 0) /* (P23) MMC1_SDCD */
    		>;
    	};
    
    	main_uart0_pins_default: main-uart0-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x1e8, PIN_INPUT, 0) /* (AB2) UART0_RXD */
    			J721E_IOPAD(0x1ec, PIN_OUTPUT, 0) /* (AB3) UART0_TXD */
    		>;
    	};
    
    	sd_pwr_en_pins_default: sd-pwr-en-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x14c, PIN_INPUT, 7) /* (AA29) PRG0_PRU1_GPO19.GPIO0_82 */
    		>;
    	};
    
    	vdd_sd_dv_alt_pins_default: vdd-sd-dv-alt-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x1d8, PIN_INPUT, 7) /* (W4) SPI1_CS1.GPIO0_117 */
    		>;
    	};
    
    	main_usbss0_pins_default: main-usbss0-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x210, PIN_INPUT, 7) /* (W3) MCAN1_RX.GPIO1_3 - USBC_DIR */
    		>;
    	};
    
    	main_usbss1_pins_default: main-usbss1-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x290, INPUT_DISABLE, 1) /* (U6) USB0_DRVVBUS.USB1_DRVVBUS */
    		>;
    	};
    
    	dp0_3v3_en_pins_default:dp0-3v3-en-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0xc8, PIN_INPUT, 7) /* (AE26) PRG0_PRU0_GPO6.GPIO0_49 */
    		>;
    	};
    
    	dp0_pins_default: dp0-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x1c4, PIN_INPUT, 5) /* (Y4) SPI0_CS1.DP0_HPD */
    		>;
    	};
    
    	main_i2c0_pins_default: main-i2c0-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x220, PIN_INPUT_PULLUP, 0) /* (AC5) I2C0_SCL */
    			J721E_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (AA5) I2C0_SDA */
    		>;
    	};
    
    	main_i2c1_pins_default: main-i2c1-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x228, PIN_INPUT_PULLUP, 0) /* (Y6) I2C1_SCL */
    			J721E_IOPAD(0x22c, PIN_INPUT_PULLUP, 0) /* (AA6) I2C1_SDA */
    		>;
    	};
    
    	main_i2c2_pins_default: main-i2c2-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x208, PIN_INPUT_PULLUP, 4) /* (W5) MCAN0_RX.I2C2_SCL */
    			J721E_IOPAD(0x20c, PIN_INPUT_PULLUP, 4) /* (W6) MCAN0_TX.I2C2_SDA */
    			J721E_IOPAD(0x138, PIN_INPUT, 7) /* (AE25) PRG0_PRU1_GPO14.GPIO0_77 */
    			J721E_IOPAD(0x13c, PIN_INPUT, 7) /* (AF29) PRG0_PRU1_GPO15.GPIO0_78 */
    		>;
    	};
    
    	main_i2c3_pins_default: main-i2c3-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x270, PIN_INPUT_PULLUP, 4) /* (T26) MMC2_CLK.I2C3_SCL */
    			J721E_IOPAD(0x274, PIN_INPUT_PULLUP, 4) /* (T25) MMC2_CMD.I2C3_SDA */
    		>;
    	};
    
    	main_i2c4_pins_default: main-i2c4-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x1e0, PIN_INPUT_PULLUP, 2) /* (Y5) SPI1_D0.I2C4_SCL */
    			J721E_IOPAD(0x1dc, PIN_INPUT_PULLUP, 2) /* (Y1) SPI1_CLK.I2C4_SDA */
    			J721E_IOPAD(0x30, PIN_INPUT, 7) /* (AF24) PRG1_PRU0_GPO11.GPIO0_12 */
    			J721E_IOPAD(0x34, PIN_INPUT, 7) /* (AJ24) PRG1_PRU0_GPO12.GPIO0_13 */
    		>;
    	};
    
    	main_i2c5_pins_default: main-i2c5-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x150, PIN_INPUT_PULLUP, 2) /* (Y26) PRG0_MDIO0_MDIO.I2C5_SCL */
    			J721E_IOPAD(0x154, PIN_INPUT_PULLUP, 2) /* (AA27) PRG0_MDIO0_MDC.I2C5_SDA */
    		>;
    	};
    
    	main_i2c6_pins_default: main-i2c6-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x1d0, PIN_INPUT_PULLUP, 2) /* (AA3) SPI0_D1.I2C6_SCL */
    			J721E_IOPAD(0x1e4, PIN_INPUT_PULLUP, 2) /* (Y2) SPI1_D1.I2C6_SDA */
    			J721E_IOPAD(0x74, PIN_INPUT, 7) /* (AC21) PRG1_PRU1_GPO7.GPIO0_28 */
    			J721E_IOPAD(0xa4, PIN_INPUT, 7) /* (AH22) PRG1_PRU1_GPO19.GPIO0_40 */
    		>;
    	};
    
    	csi0_gpio_pins_default: csi0-gpio-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x19c, PIN_INPUT_PULLDOWN, 7) /* (W27) RGMII6_TD0.GPIO0_102 */
    			J721E_IOPAD(0x1a0, PIN_INPUT_PULLDOWN, 7) /* (W29) RGMII6_TXC.GPIO0_103 */
    		>;
    	};
    
    	csi1_gpio_pins_default: csi1-gpio-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x198, PIN_INPUT_PULLDOWN, 7) /* (V25) RGMII6_TD1.GPIO0_101 */
    			J721E_IOPAD(0x1b0, PIN_INPUT_PULLDOWN, 7) /* (W24) RGMII6_RD1.GPIO0_107 */
    		>;
    	};
    
    	pcie1_rst_pins_default: pcie1-rst-default-pins {
    		pinctrl-single,pins = <
    			J721E_IOPAD(0x5c, PIN_INPUT, 7) /* (AG23) PRG1_PRU1_GPO1.GPIO0_22 */
    		>;
    	};
    };
    
    &wkup_pmx0 {
    	eeprom_wp_pins_default: eeprom-wp-default-pins {
    		pinctrl-single,pins = <
    			J721E_WKUP_IOPAD(0xc4, PIN_OUTPUT_PULLUP, 7) /* (G24) WKUP_GPIO0_5 */
    		>;
    	};
    
    	mcu_adc0_pins_default: mcu-adc0-default-pins {
    		pinctrl-single,pins = <
    			J721E_WKUP_IOPAD(0x130, PIN_INPUT, 0) /* (K25) MCU_ADC0_AIN0 */
    			J721E_WKUP_IOPAD(0x134, PIN_INPUT, 0) /* (K26) MCU_ADC0_AIN1 */
    			J721E_WKUP_IOPAD(0x138, PIN_INPUT, 0) /* (K28) MCU_ADC0_AIN2 */
    			J721E_WKUP_IOPAD(0x13c, PIN_INPUT, 0) /* (L28) MCU_ADC0_AIN3 */
    			J721E_WKUP_IOPAD(0x140, PIN_INPUT, 0) /* (K24) MCU_ADC0_AIN4 */
    			J721E_WKUP_IOPAD(0x144, PIN_INPUT, 0) /* (K27) MCU_ADC0_AIN5 */
    			J721E_WKUP_IOPAD(0x148, PIN_INPUT, 0) /* (K29) MCU_ADC0_AIN6 */
    		>;
    	};
    
    	mcu_adc1_pins_default: mcu-adc1-default-pins {
    		pinctrl-single,pins = <
    			J721E_WKUP_IOPAD(0x150, PIN_INPUT, 0) /* (N23) MCU_ADC1_AIN0 */
    		>;
    	};
    
    	mikro_bus_pins_default: mikro-bus-default-pins {
    		pinctrl-single,pins = <
    			J721E_WKUP_IOPAD(0x108, PIN_INPUT, 7) /* SDAPULLEN (E26) PMIC_POWER_EN0.WKUP_GPIO0_66 */
    			J721E_WKUP_IOPAD(0xd4, PIN_INPUT, 7) /* SDA (G26) WKUP_GPIO0_9.MCU_I2C1_SDA */
    			J721E_WKUP_IOPAD(0xf4, PIN_INPUT, 7) /* SDA (D25) MCU_I3C0_SDA.WKUP_GPIO0_61 */
    			J721E_WKUP_IOPAD(0xd0, PIN_INPUT, 7) /* SCL (G27) WKUP_GPIO0_8.MCU_I2C1_SCL */
    			J721E_WKUP_IOPAD(0xf0, PIN_INPUT, 7) /* SCL (D26) MCU_I3C0_SCL.WKUP_GPIO0_60 */
    
    			J721E_WKUP_IOPAD(0xb8, PIN_INPUT, 7) /* MOSI (F28) WKUP_GPIO0_2.MCU_SPI1_D1 */
    			J721E_WKUP_IOPAD(0xb4, PIN_INPUT, 7) /* MISO (F25) WKUP_GPIO0_1.MCU_SPI1_D0 */
    			J721E_WKUP_IOPAD(0xb0, PIN_INPUT, 7) /* CLK (F26) WKUP_GPIO0_0.MCU_SPI1_CLK */
    			J721E_WKUP_IOPAD(0xbc, PIN_INPUT, 7) /* CS (F27) WKUP_GPIO0_3.MCU_SPI1_CS0 */
    
    			J721E_WKUP_IOPAD(0x44, PIN_INPUT, 7) /* RX (G22) MCU_OSPI1_D1.WKUP_GPIO0_33 */
    			J721E_WKUP_IOPAD(0x48, PIN_INPUT, 7) /* TX (D23) MCU_OSPI1_D2.WKUP_GPIO0_34 */
    
    			J721E_WKUP_IOPAD(0x4c, PIN_INPUT, 7) /* INT (C23) MCU_OSPI1_D3.WKUP_GPIO0_35 */
    			J721E_WKUP_IOPAD(0x54, PIN_INPUT, 7) /* RST (E22) MCU_OSPI1_CSn1.WKUP_GPIO0_37 */
    			J721E_WKUP_IOPAD(0xdc, PIN_INPUT, 7) /* PWM (H27) WKUP_GPIO0_11 */
    			J721E_WKUP_IOPAD(0xac, PIN_INPUT, 7) /* AN (C29) MCU_MCAN0_RX.WKUP_GPIO0_59 */
    		>;
    	};
    
    	mcu_cpsw_pins_default: mcu-cpsw-default-pins {
    		pinctrl-single,pins = <
    			J721E_WKUP_IOPAD(0x84, PIN_INPUT, 0) /* (B24) MCU_RGMII1_RD0 */
    			J721E_WKUP_IOPAD(0x80, PIN_INPUT, 0) /* (A24) MCU_RGMII1_RD1 */
    			J721E_WKUP_IOPAD(0x7c, PIN_INPUT, 0) /* (D24) MCU_RGMII1_RD2 */
    			J721E_WKUP_IOPAD(0x78, PIN_INPUT, 0) /* (A25) MCU_RGMII1_RD3 */
    			J721E_WKUP_IOPAD(0x74, PIN_INPUT, 0) /* (C24) MCU_RGMII1_RXC */
    			J721E_WKUP_IOPAD(0x5c, PIN_INPUT, 0) /* (C25) MCU_RGMII1_RX_CTL */
    			J721E_WKUP_IOPAD(0x6c, PIN_OUTPUT, 0) /* (B25) MCU_RGMII1_TD0 */
    			J721E_WKUP_IOPAD(0x68, PIN_OUTPUT, 0) /* (A26) MCU_RGMII1_TD1 */
    			J721E_WKUP_IOPAD(0x64, PIN_OUTPUT, 0) /* (A27) MCU_RGMII1_TD2 */
    			J721E_WKUP_IOPAD(0x60, PIN_OUTPUT, 0) /* (A28) MCU_RGMII1_TD3 */
    			J721E_WKUP_IOPAD(0x70, PIN_OUTPUT, 0) /* (B26) MCU_RGMII1_TXC */
    			J721E_WKUP_IOPAD(0x58, PIN_OUTPUT, 0) /* (B27) MCU_RGMII1_TX_CTL */
    		>;
    	};
    
    	mcu_mdio_pins_default: mcu-mdio1-default-pins {
    		pinctrl-single,pins = <
    			J721E_WKUP_IOPAD(0x8c, PIN_OUTPUT, 0) /* (F23) MCU_MDIO0_MDC */
    			J721E_WKUP_IOPAD(0x88, PIN_INPUT, 0) /* (E23) MCU_MDIO0_MDIO */
    		>;
    	};
    
    	sw_pwr_pins_default: sw-pwr-default-pins {
    		pinctrl-single,pins = <
    			J721E_WKUP_IOPAD(0xc0, PIN_INPUT, 7) /* (G25) WKUP_GPIO0_4 */
    		>;
    	};
    
    	wkup_i2c0_pins_default: wkup-i2c0-default-pins {
    		pinctrl-single,pins = <
    			J721E_WKUP_IOPAD(0xf8, PIN_INPUT_PULLUP, 0) /* (J25) WKUP_I2C0_SCL */
    			J721E_WKUP_IOPAD(0xfc, PIN_INPUT_PULLUP, 0) /* (H24) WKUP_I2C0_SDA */
    		>;
    	};
    
    	wkup_uart0_pins_default: wkup-uart0-default-pins {
    		pinctrl-single,pins = <
    			J721E_WKUP_IOPAD(0xa0, PIN_INPUT, 0) /* (J29) WKUP_UART0_RXD */
    			J721E_WKUP_IOPAD(0xa4, PIN_OUTPUT, 0) /* (J28) WKUP_UART0_TXD */
    		>;
    	};
    
    	mcu_usbss1_pins_default: mcu-usbss1-default-pins {
    		pinctrl-single,pins = <
    			J721E_WKUP_IOPAD(0x3c, PIN_OUTPUT_PULLUP, 5) /* (A23) MCU_OSPI1_LBCLKO.WKUP_GPIO0_30 */
    		>;
    	};
    };
    
    &wkup_uart0 {
    	/* Wakeup UART is used by TIFS firmware. */
    	status = "reserved";
    	pinctrl-names = "default";
    	pinctrl-0 = <&wkup_uart0_pins_default>;
    };
    
    &main_uart0 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_uart0_pins_default>;
    	/* Shared with ATF on this platform */
    	power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
    };
    
    &main_sdhci0 {
    	/* eMMC */
    	status = "okay";
    	non-removable;
    	ti,driver-strength-ohm = <50>;
    	disable-wp;
    };
    
    &main_sdhci1 {
    	/* SD Card */
    	status = "okay";
    	vmmc-supply = <&vdd_mmc1>;
    	vqmmc-supply = <&vdd_sd_dv_alt>;
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_mmc1_pins_default>;
    	ti,driver-strength-ohm = <50>;
    	disable-wp;
    };
    
    &main_i2c0 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_i2c0_pins_default>;
    	clock-frequency = <400000>;
    };
    
    &main_i2c1 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_i2c1_pins_default>;
    	clock-frequency = <400000>;
    
    	//CSI 0 interrupt: main_gpio0, 103
    	//CSI 1 interrupt: main_gpio0, 101
    
    	lt7911d@2b {
    		compatible = "lontium,lt7911d";
    		reg = <0x2b>;
    		
    		clocks = <&clk_lt7911d_fixed>;
    		clock-names = "xvclk";
    		
    		interrupt-parent = <&main_gpio0>;
    		interrupts = <101 IRQ_TYPE_LEVEL_HIGH>;
    		interrupt-names = "irq";
    
    		port {
    			csi2rx1_lt7911d: endpoint {
    				remote-endpoint = <&csi2rx1_in_sensor>;
    				link-frequencies = /bits/ 64 <312500000>;
    				clock-lanes = <0>;
    				data-lanes = <1 2 3 4>;
    				clock-noncontinuous;
    			};
    		};
    	};
    };
    
    &main_i2c2 {
    	/* BBB Header: P9.19 and P9.20 */
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_i2c2_pins_default>;
    	clock-frequency = <100000>;
    };
    
    &main_i2c3 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_i2c3_pins_default>;
    	clock-frequency = <400000>;
    };
    
    &main_i2c4 {
    	/* BBB Header: P9.24 and P9.26 */
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_i2c4_pins_default>;
    	clock-frequency = <100000>;
    };
    
    &main_i2c5 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_i2c5_pins_default>;
    	clock-frequency = <400000>;
    
    	//CSI 0 interrupt: main_gpio0, 103
    	//CSI 1 interrupt: main_gpio0, 101
    
    	tc358743@f {
    		compatible = "toshiba,tc358743";
    		reg = <0xf>;
    		clocks = <&tc358743_clk>;
    		clock-names = "refclk";
    		status = "okay";
    		devnode = "video0";
    		port@0 {
    			ret = <0>;
    			status = "okay";
    			csi2rx0_tc358743: endpoint {
    				status = "okay";
    				bus-type = <4>; // CSI2 DPHY.
    				clock-lanes = <0>;
    				data-lanes = <1 2 3 4>;
    				clock-noncontinuous;
    				link-frequencies = /bits/ 64 <312500000>;
    				remote-endpoint = <&csi2rx0_in_sensor>;
    			};
    		};
    	};
    };
    
    &main_i2c6 {
    	/* BBB Header: P9.17 and P9.18 */
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_i2c6_pins_default>;
    	clock-frequency = <100000>;
    	status = "okay";
    };
    
    &wkup_i2c0 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&wkup_i2c0_pins_default>;
    	clock-frequency = <400000>;
    
    	eeprom@50 {
    		compatible = "atmel,24c04";
    		reg = <0x50>;
    		pinctrl-names = "default";
    		pinctrl-0 = <&eeprom_wp_pins_default>;
    	};
    };
    
    &wkup_gpio0 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&mcu_adc0_pins_default>, <&mcu_adc1_pins_default>,
    		    <&mikro_bus_pins_default>;
    };
    
    &main_gpio0 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&csi1_gpio_pins_default>, <&csi0_gpio_pins_default>;
    };
    
    &main_gpio1 {
    	status = "okay";
    };
    
    &usb_serdes_mux {
    	idle-states = <1>, <1>; /* USB0 to SERDES3, USB1 to SERDES2 */
    };
    
    &serdes_ln_ctrl {
    	idle-states = <J721E_SERDES0_LANE0_IP4_UNUSED>, <J721E_SERDES0_LANE1_IP4_UNUSED>,
    		      <J721E_SERDES1_LANE0_PCIE1_LANE0>, <J721E_SERDES1_LANE1_PCIE1_LANE1>,
    		      <J721E_SERDES2_LANE0_IP1_UNUSED>, <J721E_SERDES2_LANE1_USB3_1>,
    		      <J721E_SERDES3_LANE0_USB3_0_SWAP>, <J721E_SERDES3_LANE1_USB3_0>,
    		      <J721E_SERDES4_LANE0_EDP_LANE0>, <J721E_SERDES4_LANE1_EDP_LANE1>,
    		      <J721E_SERDES4_LANE2_EDP_LANE2>, <J721E_SERDES4_LANE3_EDP_LANE3>;
    };
    
    &serdes_wiz3 {
    	typec-dir-gpios = <&main_gpio1 3 GPIO_ACTIVE_LOW>;
    	typec-dir-debounce-ms = <700>;	/* TUSB321, tCCB_DEFAULT 133 ms */
    };
    
    &serdes3 {
    	serdes3_usb_link: phy@0 {
    		reg = <0>;
    		cdns,num-lanes = <2>;
    		#phy-cells = <0>;
    		cdns,phy-type = <PHY_TYPE_USB3>;
    		resets = <&serdes_wiz3 1>, <&serdes_wiz3 2>;
    	};
    };
    
    &serdes4 {
    	torrent_phy_dp: phy@0 {
    		reg = <0>;
    		resets = <&serdes_wiz4 1>;
    		cdns,phy-type = <PHY_TYPE_DP>;
    		cdns,num-lanes = <4>;
    		cdns,max-bit-rate = <5400>;
    		#phy-cells = <0>;
    	};
    };
    
    &mhdp {
    	phys = <&torrent_phy_dp>;
    	phy-names = "dpphy";
    	pinctrl-names = "default";
    	pinctrl-0 = <&dp0_pins_default>;
    };
    
    &usbss0 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_usbss0_pins_default>;
    	ti,vbus-divider;
    };
    
    &usb0 {
    	dr_mode = "peripheral";
    	maximum-speed = "super-speed";
    	phys = <&serdes3_usb_link>;
    	phy-names = "cdns3,usb3-phy";
    };
    
    &serdes2 {
    	serdes2_usb_link: phy@1 {
    		reg = <1>;
    		cdns,num-lanes = <1>;
    		#phy-cells = <0>;
    		cdns,phy-type = <PHY_TYPE_USB3>;
    		resets = <&serdes_wiz2 2>;
    	};
    };
    
    &usbss1 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&main_usbss1_pins_default>, <&mcu_usbss1_pins_default>;
    	ti,vbus-divider;
    };
    
    &usb1 {
    	dr_mode = "host";
    	maximum-speed = "super-speed";
    	phys = <&serdes2_usb_link>;
    	phy-names = "cdns3,usb3-phy";
    };
    
    &tscadc0 {
    	status = "okay";
    	/* BBB Header: P9.39, P9.40, P9.37, P9.38, P9.33, P9.36, P9.35 */
    	adc {
    		ti,adc-channels = <0 1 2 3 4 5 6>;
    	};
    };
    
    &tscadc1 {
    	status = "okay";
    	/* MCU mikroBUS Header J10.1 - MCU_ADC1_AIN0 */
    	adc {
    		ti,adc-channels = <0>;
    	};
    };
    
    &mcu_cpsw {
    	pinctrl-names = "default";
    	pinctrl-0 = <&mcu_cpsw_pins_default>;
    };
    
    &davinci_mdio {
    	pinctrl-names = "default";
    	pinctrl-0 = <&mcu_mdio_pins_default>;
    
    	phy0: ethernet-phy@0 {
    		reg = <0>;
    		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
    		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
    	};
    };
    
    &cpsw_port1 {
    	phy-mode = "rgmii-rxid";
    	phy-handle = <&phy0>;
    };
    
    &dss {
    	/*
    	 * These clock assignments are chosen to enable the following outputs:
    	 *
    	 * VP0 - DisplayPort SST
    	 * VP1 - DPI0
    	 * VP2 - DSI
    	 * VP3 - DPI1
    	 */
    
    	assigned-clocks = <&k3_clks 152 1>,	/* VP 1 pixel clock */
    			  <&k3_clks 152 4>,	/* VP 2 pixel clock */
    			  <&k3_clks 152 9>,	/* VP 3 pixel clock */
    			  <&k3_clks 152 13>;	/* VP 4 pixel clock */
    	assigned-clock-parents = <&k3_clks 152 2>,	/* PLL16_HSDIV0 */
    				 <&k3_clks 152 6>,	/* PLL19_HSDIV0 */
    				 <&k3_clks 152 11>,	/* PLL18_HSDIV0 */
    				 <&k3_clks 152 18>;	/* PLL23_HSDIV0 */
    };
    
    &dss_ports {
    	port {
    		dpi0_out: endpoint {
    			remote-endpoint = <&dp0_in>;
    		};
    	};
    };
    
    &dp0_ports {
    	#address-cells = <1>;
    	#size-cells = <0>;
    
    	port@0 {
    		reg = <0>;
    		dp0_in: endpoint {
    			remote-endpoint = <&dpi0_out>;
    		};
    	};
    
    	port@4 {
    		reg = <4>;
    		dp0_out: endpoint {
    			remote-endpoint = <&dp_connector_in>;
    		};
    	};
    };
    
    &serdes0 {
    	serdes0_pcie_link: phy@0 {
    		reg = <0>;
    		cdns,num-lanes = <1>;
    		#phy-cells = <0>;
    		cdns,phy-type = <PHY_TYPE_PCIE>;
    		resets = <&serdes_wiz0 1>;
    	};
    };
    
    &serdes1 {
    	serdes1_pcie_link: phy@0 {
    		reg = <0>;
    		cdns,num-lanes = <2>;
    		#phy-cells = <0>;
    		cdns,phy-type = <PHY_TYPE_PCIE>;
    		resets = <&serdes_wiz1 1>, <&serdes_wiz1 2>;
    	};
    };
    
    &pcie1_rc {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&pcie1_rst_pins_default>;
    	phys = <&serdes1_pcie_link>;
    	phy-names = "pcie-phy";
    	num-lanes = <2>;
    	max-link-speed = <3>;
    	reset-gpios = <&main_gpio0 22 GPIO_ACTIVE_HIGH>;
    };
    
    &ufs_wrapper {
    	status = "disabled";
    };
    
    &mailbox0_cluster0 {
    	status = "okay";
    	interrupts = <436>;
    
    	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
    		ti,mbox-rx = <0 0 0>;
    		ti,mbox-tx = <1 0 0>;
    	};
    
    	mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
    		ti,mbox-rx = <2 0 0>;
    		ti,mbox-tx = <3 0 0>;
    	};
    };
    
    &mailbox0_cluster1 {
    	status = "okay";
    	interrupts = <432>;
    
    	mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
    		ti,mbox-rx = <0 0 0>;
    		ti,mbox-tx = <1 0 0>;
    	};
    
    	mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 {
    		ti,mbox-rx = <2 0 0>;
    		ti,mbox-tx = <3 0 0>;
    	};
    };
    
    &mailbox0_cluster2 {
    	status = "okay";
    	interrupts = <428>;
    
    	mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
    		ti,mbox-rx = <0 0 0>;
    		ti,mbox-tx = <1 0 0>;
    	};
    
    	mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 {
    		ti,mbox-rx = <2 0 0>;
    		ti,mbox-tx = <3 0 0>;
    	};
    };
    
    &mailbox0_cluster3 {
    	status = "okay";
    	interrupts = <424>;
    
    	mbox_c66_0: mbox-c66-0 {
    		ti,mbox-rx = <0 0 0>;
    		ti,mbox-tx = <1 0 0>;
    	};
    
    	mbox_c66_1: mbox-c66-1 {
    		ti,mbox-rx = <2 0 0>;
    		ti,mbox-tx = <3 0 0>;
    	};
    };
    
    &mailbox0_cluster4 {
    	status = "okay";
    	interrupts = <420>;
    
    	mbox_c71_0: mbox-c71-0 {
    		ti,mbox-rx = <0 0 0>;
    		ti,mbox-tx = <1 0 0>;
    	};
    };
    
    &mcu_r5fss0_core0 {
    	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
    	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
    			<&mcu_r5fss0_core0_memory_region>;
    };
    
    &mcu_r5fss0_core1 {
    	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>;
    	memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
    			<&mcu_r5fss0_core1_memory_region>;
    };
    
    &main_r5fss0_core0 {
    	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>;
    	memory-region = <&main_r5fss0_core0_dma_memory_region>,
    			<&main_r5fss0_core0_memory_region>;
    };
    
    &main_r5fss0_core1 {
    	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>;
    	memory-region = <&main_r5fss0_core1_dma_memory_region>,
    			<&main_r5fss0_core1_memory_region>;
    };
    
    &main_r5fss1_core0 {
    	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>;
    	memory-region = <&main_r5fss1_core0_dma_memory_region>,
    			<&main_r5fss1_core0_memory_region>;
    };
    
    &main_r5fss1_core1 {
    	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>;
    	memory-region = <&main_r5fss1_core1_dma_memory_region>,
    			<&main_r5fss1_core1_memory_region>;
    };
    
    &c66_0 {
    	status = "okay";
    	mboxes = <&mailbox0_cluster3 &mbox_c66_0>;
    	memory-region = <&c66_0_dma_memory_region>,
    			<&c66_0_memory_region>;
    };
    
    &c66_1 {
    	status = "okay";
    	mboxes = <&mailbox0_cluster3 &mbox_c66_1>;
    	memory-region = <&c66_1_dma_memory_region>,
    			<&c66_1_memory_region>;
    };
    
    &c71_0 {
    	status = "okay";
    	mboxes = <&mailbox0_cluster4 &mbox_c71_0>;
    	memory-region = <&c71_0_dma_memory_region>,
    			<&c71_0_memory_region>;
    };
    
    &csi0_port0 {
        status = "okay";
    	csi2rx0_in_sensor: endpoint {
    		//remote-endpoint = <&csi2rx0_lt7911d>;
    		remote-endpoint = <&csi2rx0_tc358743>;
    		bus-type = <4>; // CSI2 DPHY.
    		clock-lanes = <0>;
    		data-lanes = <1 2 3 4>;
    		clock-noncontinuous;
    		link-frequencies = /bits/ 64 <312500000>;
    	};
    };
    
    &cdns_csi2rx1 {
    	ports {
    		#address-cells = <1>;
    		#size-cells = <0>;
    
    		csi1_port0: port@0 {
    			reg = <0>;
    			status = "okay";
    
    			csi2rx1_in_sensor: endpoint {
    				remote-endpoint = <&csi2rx1_lt7911d>;
    				link-frequencies = /bits/ 64 <312500000>;
    				bus-type = <4>; /* CSI2 DPHY. */
    				clock-lanes = <0>;
    				data-lanes = <1 2 3 4>;
    				clock-noncontinuous;
    			};
    		};
    
    		csi1_port1: port@1 {
    			reg = <1>;
    			status = "disabled";
    		};
    
    		csi1_port2: port@2 {
    			reg = <2>;
    			status = "disabled";
    		};
    
    		csi1_port3: port@3 {
    			reg = <3>;
    			status = "disabled";
    		};
    
    		csi1_port4: port@4 {
    			reg = <4>;
    			status = "disabled";
    		};
    	};
    };
    
    &dphy0 {
    	status = "okay";
    };
    
    &ti_csi2rx0 {
    	status = "okay";
    };
    
    &dphy1 {
    	status = "okay";
    };
    
    &ti_csi2rx1 {
    	status = "okay";
    };
    
     
    [    0.000000] Booting Linux on physical CPU 0x0000000000 [0x411fd080]
    [    0.000000] Linux version 6.16.5-gca805e5039b1-dirty (stefan@stefan-VirtualBox) (aarch64-none-linux-gnu-gcc (Arm GNU Toolchain 14.3.Rel1 (Build arm-14.174)) 14.3.1 20250623, GNU ld (Arm GNU Toolchain 14.3.Rel1 (Build arm-14.174)) 2.44.0.20250616) #39 SMP PREEMPT Tue Jan 27 10:30:18 CET 2026
    [    0.000000] KASLR disabled due to lack of seed
    [    0.000000] Machine model: BeagleBoard.org BeagleBone AI-64
    [    0.000000] OF: reserved mem: 0x000000009e800000..0x000000009fffffff (24576 KiB) nomap non-reusable optee@9e800000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a0000000, size 1 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-dma-memory@a0000000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a0000000..0x00000000a00fffff (1024 KiB) nomap non-reusable r5f-dma-memory@a0000000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a0100000, size 15 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-memory@a0100000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a0100000..0x00000000a0ffffff (15360 KiB) nomap non-reusable r5f-memory@a0100000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a1000000, size 1 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-dma-memory@a1000000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a1000000..0x00000000a10fffff (1024 KiB) nomap non-reusable r5f-dma-memory@a1000000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a1100000, size 15 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-memory@a1100000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a1100000..0x00000000a1ffffff (15360 KiB) nomap non-reusable r5f-memory@a1100000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a2000000, size 1 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-dma-memory@a2000000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a2000000..0x00000000a20fffff (1024 KiB) nomap non-reusable r5f-dma-memory@a2000000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a2100000, size 15 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-memory@a2100000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a2100000..0x00000000a2ffffff (15360 KiB) nomap non-reusable r5f-memory@a2100000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a3000000, size 1 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-dma-memory@a3000000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a3000000..0x00000000a30fffff (1024 KiB) nomap non-reusable r5f-dma-memory@a3000000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a3100000, size 15 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-memory@a3100000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a3100000..0x00000000a3ffffff (15360 KiB) nomap non-reusable r5f-memory@a3100000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a4000000, size 1 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-dma-memory@a4000000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a4000000..0x00000000a40fffff (1024 KiB) nomap non-reusable r5f-dma-memory@a4000000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a4100000, size 15 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-memory@a4100000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a4100000..0x00000000a4ffffff (15360 KiB) nomap non-reusable r5f-memory@a4100000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a5000000, size 1 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-dma-memory@a5000000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a5000000..0x00000000a50fffff (1024 KiB) nomap non-reusable r5f-dma-memory@a5000000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a5100000, size 15 MiB
    [    0.000000] OF: reserved mem: initialized node r5f-memory@a5100000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a5100000..0x00000000a5ffffff (15360 KiB) nomap non-reusable r5f-memory@a5100000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a6000000, size 1 MiB
    [    0.000000] OF: reserved mem: initialized node c66-dma-memory@a6000000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a6000000..0x00000000a60fffff (1024 KiB) nomap non-reusable c66-dma-memory@a6000000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a6100000, size 15 MiB
    [    0.000000] OF: reserved mem: initialized node c66-memory@a6100000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a6100000..0x00000000a6ffffff (15360 KiB) nomap non-reusable c66-memory@a6100000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a7000000, size 1 MiB
    [    0.000000] OF: reserved mem: initialized node c66-dma-memory@a7000000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a7000000..0x00000000a70fffff (1024 KiB) nomap non-reusable c66-dma-memory@a7000000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a7100000, size 15 MiB
    [    0.000000] OF: reserved mem: initialized node c66-memory@a7100000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a7100000..0x00000000a7ffffff (15360 KiB) nomap non-reusable c66-memory@a7100000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a8000000, size 1 MiB
    [    0.000000] OF: reserved mem: initialized node c71-dma-memory@a8000000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a8000000..0x00000000a80fffff (1024 KiB) nomap non-reusable c71-dma-memory@a8000000
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000a8100000, size 15 MiB
    [    0.000000] OF: reserved mem: initialized node c71-memory@a8100000, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000a8100000..0x00000000a8ffffff (15360 KiB) nomap non-reusable c71-memory@a8100000
    [    0.000000] OF: reserved mem: 0x00000000aa000000..0x00000000abbfffff (28672 KiB) nomap non-reusable ipc-memories@aa000000
    [    0.000000] Reserved memory: created CMA memory pool at 0x00000000f8000000, size 128 MiB
    [    0.000000] OF: reserved mem: initialized node cma@0, compatible id shared-dma-pool
    [    0.000000] OF: reserved mem: 0x00000000f8000000..0x00000000ffffffff (131072 KiB) map reusable cma@0
    [    0.000000] NUMA: Faking a node at [mem 0x0000000080000000-0x00000008ffffffff]
    [    0.000000] NODE_DATA(0) allocated [mem 0x8ff7e7b80-0x8ff7ea1ff]
    [    0.000000] Zone ranges:
    [    0.000000]   DMA      [mem 0x0000000080000000-0x00000000ffffffff]
    [    0.000000]   DMA32    empty
    [    0.000000]   Normal   [mem 0x0000000100000000-0x00000008ffffffff]
    [    0.000000] Movable zone start for each node
    [    0.000000] Early memory node ranges
    [    0.000000]   node   0: [mem 0x0000000080000000-0x000000009e7fffff]
    [    0.000000]   node   0: [mem 0x000000009e800000-0x00000000a8ffffff]
    [    0.000000]   node   0: [mem 0x00000000a9000000-0x00000000a9ffffff]
    [    0.000000]   node   0: [mem 0x00000000aa000000-0x00000000abbfffff]
    [    0.000000]   node   0: [mem 0x00000000abc00000-0x00000000ffffffff]
    [    0.000000]   node   0: [mem 0x0000000880000000-0x00000008ffffffff]
    [    0.000000] Initmem setup node 0 [mem 0x0000000080000000-0x00000008ffffffff]
    [    0.000000] psci: probing for conduit method from DT.
    [    0.000000] psci: PSCIv1.1 detected in firmware.
    [    0.000000] psci: Using standard PSCI v0.2 function IDs
    [    0.000000] psci: Trusted OS migration not required
    [    0.000000] psci: SMC Calling Convention v1.4
    [    0.000000] percpu: Embedded 24 pages/cpu s61144 r8192 d28968 u98304
    [    0.000000] pcpu-alloc: s61144 r8192 d28968 u98304 alloc=24*4096
    [    0.000000] pcpu-alloc: [0] 0 [0] 1
    [    0.000000] Detected PIPT I-cache on CPU0
    [    0.000000] CPU features: detected: GIC system register CPU interface
    [    0.000000] CPU features: detected: Spectre-v3a
    [    0.000000] CPU features: detected: Spectre-BHB
    [    0.000000] CPU features: detected: ARM erratum 1742098
    [    0.000000] CPU features: detected: ARM errata 1165522, 1319367, or 1530923
    [    0.000000] alternatives: applying boot alternatives
    [    0.000000] Kernel command line: console=ttyS2,115200n8
    [    0.000000] printk: log buffer data + meta data: 131072 + 458752 = 589824 bytes
    [    0.000000] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes, linear)
    [    0.000000] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes, linear)
    [    0.000000] software IO TLB: area num 2.
    [    0.000000] software IO TLB: mapped [mem 0x00000000f4000000-0x00000000f8000000] (64MB)
    [    0.000000] Fallback order for Node 0: 0
    [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 1048576
    [    0.000000] Policy zone: Normal
    [    0.000000] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
    [    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
    [    0.000000] rcu: Preemptible hierarchical RCU implementation.
    [    0.000000] rcu:     RCU event tracing is enabled.
    [    0.000000] rcu:     RCU restricting CPUs from NR_CPUS=512 to nr_cpu_ids=2.
    [    0.000000]  Trampoline variant of Tasks RCU enabled.
    [    0.000000]  Tracing variant of Tasks RCU enabled.
    [    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
    [    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
    [    0.000000] RCU Tasks: Setting shift to 1 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=2.
    [    0.000000] RCU Tasks Trace: Setting shift to 1 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=2.
    [    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
    [    0.000000] GICv3: GIC: Using split EOI/Deactivate mode
    [    0.000000] GICv3: 960 SPIs implemented
    [    0.000000] GICv3: 0 Extended SPIs implemented
    [    0.000000] Root IRQ handler: gic_handle_irq
    [    0.000000] GICv3: GICv3 features: 16 PPIs
    [    0.000000] GICv3: GICD_CTRL.DS=0, SCR_EL3.FIQ=1
    [    0.000000] GICv3: CPU0: found redistributor 0 region 0:0x0000000001900000
    [    0.000000] ITS [mem 0x01820000-0x0182ffff]
    [    0.000000] GIC: enabling workaround for ITS: Socionext Synquacer pre-ITS
    [    0.000000] ITS@0x0000000001820000: Devices Table too large, reduce ids 20->19
    [    0.000000] ITS@0x0000000001820000: allocated 524288 Devices @880800000 (flat, esz 8, psz 64K, shr 0)
    [    0.000000] ITS: using cache flushing for cmd queue
    [    0.000000] GICv3: using LPI property table @0x0000000880040000
    [    0.000000] GIC: using cache flushing for LPI property table
    [    0.000000] GICv3: CPU0: using allocated LPI pending table @0x0000000880050000
    [    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on contention.
    [    0.000000] arch_timer: cp15 timer(s) running at 200.00MHz (phys).
    [    0.000000] clocksource: arch_sys_counter: mask: 0x3ffffffffffffff max_cycles: 0x2e2049d3e8, max_idle_ns: 440795210634 ns
    [    0.000000] sched_clock: 58 bits at 200MHz, resolution 5ns, wraps every 4398046511102ns
    [    0.000263] Console: colour dummy device 80x25
    [    0.000319] Calibrating delay loop (skipped), value calculated using timer frequency.. 400.00 BogoMIPS (lpj=800000)
    [    0.000324] pid_max: default: 32768 minimum: 301
    [    0.000364] LSM: initializing lsm=capability
    [    0.000449] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
    [    0.000464] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
    [    0.001630] rcu: Hierarchical SRCU implementation.
    [    0.001635] rcu:     Max phase no-delay instances is 1000.
    [    0.001765] Timer migration: 1 hierarchy levels; 8 children per group; 1 crossnode level
    [    0.002185] smp: Bringing up secondary CPUs ...
    [    0.010814] Detected PIPT I-cache on CPU1
    [    0.010864] GICv3: CPU1: found redistributor 1 region 0:0x0000000001920000
    [    0.010875] GICv3: CPU1: using allocated LPI pending table @0x0000000880060000
    [    0.010907] CPU1: Booted secondary processor 0x0000000001 [0x411fd080]
    [    0.010997] smp: Brought up 1 node, 2 CPUs
    [    0.011001] SMP: Total of 2 processors activated.
    [    0.011003] CPU: All CPU(s) started at EL2
    [    0.011019] CPU features: detected: 32-bit EL0 Support
    [    0.011021] CPU features: detected: 32-bit EL1 Support
    [    0.011023] CPU features: detected: CRC32 instructions
    [    0.011028] CPU features: detected: PMUv3
    [    0.011048] alternatives: applying system-wide alternatives
    [    0.011864] Memory: 3655164K/4194304K available (15104K kernel code, 1302K rwdata, 5576K rodata, 1600K init, 585K bss, 399960K reserved, 131072K cma-reserved)
    [    0.012431] devtmpfs: initialized
    [    0.018748] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
    [    0.018779] posixtimers hash table entries: 1024 (order: 2, 16384 bytes, linear)
    [    0.018817] futex hash table entries: 512 (32768 bytes on 1 NUMA nodes, total 32 KiB, linear).
    [    0.020229] 26656 pages in range for non-PLT usage
    [    0.020236] 518176 pages in range for PLT usage
    [    0.020419] pinctrl core: initialized pinctrl subsystem
    [    0.022052] NET: Registered PF_NETLINK/PF_ROUTE protocol family
    [    0.022529] DMA: preallocated 512 KiB GFP_KERNEL pool for atomic allocations
    [    0.022632] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
    [    0.022761] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
    [    0.022829] audit: initializing netlink subsys (disabled)
    [    0.022989] audit: type=2000 audit(0.020:1): state=initialized audit_enabled=0 res=1
    [    0.023202] thermal_sys: Registered thermal governor 'step_wise'
    [    0.023204] thermal_sys: Registered thermal governor 'power_allocator'
    [    0.023233] cpuidle: using governor menu
    [    0.023306] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
    [    0.023335] ASID allocator initialised with 65536 entries
    [    0.023419] Serial: AMBA PL011 UART driver
    [    0.027992] /bus@100000/interrupt-controller@1800000: Fixed dependency cycle(s) with /bus@100000/interrupt-controller@1800000
    [    0.028054] /bus@100000/ticsi2rx@4500000/csi-bridge@4504000: Fixed dependency cycle(s) with /bus@100000/i2c@2050000/tc358743@f
    [    0.028074] /bus@100000/ticsi2rx@4510000/csi-bridge@4514000: Fixed dependency cycle(s) with /bus@100000/i2c@2010000/lt7911d@2b
    [    0.028323] /bus@100000/i2c@2010000/lt7911d@2b: Fixed dependency cycle(s) with /bus@100000/ticsi2rx@4510000/csi-bridge@4514000
    [    0.028354] /bus@100000/i2c@2050000/tc358743@f: Fixed dependency cycle(s) with /bus@100000/ticsi2rx@4500000/csi-bridge@4504000
    [    0.028370] /bus@100000/dp-bridge@a000000: Fixed dependency cycle(s) with /bus@100000/dss@4a00000
    [    0.028388] /bus@100000/dss@4a00000: Fixed dependency cycle(s) with /bus@100000/dp-bridge@a000000
    [    0.032320] /bus@100000/ticsi2rx@4500000/csi-bridge@4504000: Fixed dependency cycle(s) with /bus@100000/i2c@2050000/tc358743@f
    [    0.032396] /bus@100000/ticsi2rx@4510000/csi-bridge@4514000: Fixed dependency cycle(s) with /bus@100000/i2c@2010000/lt7911d@2b
    [    0.034684] /bus@100000/i2c@2010000/lt7911d@2b: Fixed dependency cycle(s) with /bus@100000/ticsi2rx@4510000/csi-bridge@4514000
    [    0.034932] /bus@100000/i2c@2050000/tc358743@f: Fixed dependency cycle(s) with /bus@100000/ticsi2rx@4500000/csi-bridge@4504000
    [    0.035070] /bus@100000/dp-bridge@a000000: Fixed dependency cycle(s) with /bus@100000/dss@4a00000
    [    0.035322] /bus@100000/dp-bridge@a000000: Fixed dependency cycle(s) with /bus@100000/dss@4a00000
    [    0.035357] /bus@100000/dss@4a00000: Fixed dependency cycle(s) with /bus@100000/dp-bridge@a000000
    [    0.036989] /bus@100000/dp-bridge@a000000: Fixed dependency cycle(s) with /connector
    [    0.037031] /connector: Fixed dependency cycle(s) with /bus@100000/dp-bridge@a000000
    [    0.037598] HugeTLB: allocation took 0ms with hugepage_allocation_threads=1
    [    0.037604] HugeTLB: allocation took 0ms with hugepage_allocation_threads=1
    [    0.037610] HugeTLB: registered 1.00 GiB page size, pre-allocated 0 pages
    [    0.037612] HugeTLB: 0 KiB vmemmap can be freed for a 1.00 GiB page
    [    0.037614] HugeTLB: registered 32.0 MiB page size, pre-allocated 0 pages
    [    0.037616] HugeTLB: 0 KiB vmemmap can be freed for a 32.0 MiB page
    [    0.037618] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages
    [    0.037620] HugeTLB: 0 KiB vmemmap can be freed for a 2.00 MiB page
    [    0.037622] HugeTLB: registered 64.0 KiB page size, pre-allocated 0 pages
    [    0.037623] HugeTLB: 0 KiB vmemmap can be freed for a 64.0 KiB page
    [    0.038724] k3-chipinfo 43000014.chipid: Family:J721E rev:SR1.1 JTAGID[0x1bb6402f] Detected
    [    0.039076] iommu: Default domain type: Translated
    [    0.039079] iommu: DMA domain TLB invalidation policy: strict mode
    [    0.039426] SCSI subsystem initialized
    [    0.039535] usbcore: registered new interface driver usbfs
    [    0.039551] usbcore: registered new interface driver hub
    [    0.039567] usbcore: registered new device driver usb
    [    0.039929] mc: Linux media interface: v0.10
    [    0.039948] videodev: Linux video capture interface: v2.00
    [    0.039959] pps_core: LinuxPPS API ver. 1 registered
    [    0.039961] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
    [    0.039966] PTP clock support registered
    [    0.039984] EDAC MC: Ver: 3.0.0
    [    0.040193] scmi_core: SCMI protocol bus registered
    [    0.040427] FPGA manager framework
    [    0.040476] Advanced Linux Sound Architecture Driver Initialized.
    [    0.040932] vgaarb: loaded
    [    0.041114] clocksource: Switched to clocksource arch_sys_counter
    [    0.041254] VFS: Disk quotas dquot_6.6.0
    [    0.041263] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
    [    0.044840] NET: Registered PF_INET protocol family
    [    0.044985] IP idents hash table entries: 65536 (order: 7, 524288 bytes, linear)
    [    0.046402] tcp_listen_portaddr_hash hash table entries: 2048 (order: 3, 32768 bytes, linear)
    [    0.046437] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
    [    0.046447] TCP established hash table entries: 32768 (order: 6, 262144 bytes, linear)
    [    0.046583] TCP bind hash table entries: 32768 (order: 8, 1048576 bytes, linear)
    [    0.047591] TCP: Hash tables configured (established 32768 bind 32768)
    [    0.047680] UDP hash table entries: 2048 (order: 5, 131072 bytes, linear)
    [    0.047794] UDP-Lite hash table entries: 2048 (order: 5, 131072 bytes, linear)
    [    0.048011] NET: Registered PF_UNIX/PF_LOCAL protocol family
    [    0.048369] RPC: Registered named UNIX socket transport module.
    [    0.048373] RPC: Registered udp transport module.
    [    0.048374] RPC: Registered tcp transport module.
    [    0.048376] RPC: Registered tcp-with-tls transport module.
    [    0.048377] RPC: Registered tcp NFSv4.1 backchannel transport module.
    [    0.048388] PCI: CLS 0 bytes, default 64
    [    0.048621] Unpacking initramfs...
    [    0.050559] kvm [1]: nv: 566 coarse grained trap handlers
    [    0.050760] kvm [1]: IPA Size Limit: 44 bits
    [    0.051372] kvm [1]: vgic-v2@6f020000
    [    0.051399] kvm [1]: GIC system register CPU interface enabled
    [    0.051421] kvm [1]: vgic interrupt IRQ9
    [    0.051439] kvm [1]: Hyp nVHE mode initialized successfully
    [    0.053689] Initialise system trusted keyrings
    [    0.053880] workingset: timestamp_bits=42 max_order=20 bucket_order=0
    [    0.054204] NFS: Registering the id_resolver key type
    [    0.054220] Key type id_resolver registered
    [    0.054222] Key type id_legacy registered
    [    0.054230] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
    [    0.054234] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
    [    0.080067] Key type asymmetric registered
    [    0.080076] Asymmetric key parser 'x509' registered
    [    0.080144] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 244)
    [    0.080147] io scheduler mq-deadline registered
    [    0.080151] io scheduler kyber registered
    [    0.080186] io scheduler bfq registered
    [    0.082794] pinctrl-single 4301c000.pinctrl: 94 pins, size 376
    [    0.083149] pinctrl-single 11c000.pinctrl: 173 pins, size 692
    [    0.083639] pinctrl-single 104200.pinctrl: 20 pins, size 80
    [    0.083714] pinctrl-single 104280.pinctrl: 8 pins, size 32
    [    0.084561] ledtrig-cpu: registered to indicate activity on CPUs
    [    0.088427] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
    [    0.090393] arm-smmu-v3 36600000.iommu: ias 48-bit, oas 48-bit (features 0x00101faf)
    [    0.090752] arm-smmu-v3 36600000.iommu: allocated 65536 entries for cmdq
    [    0.090980] arm-smmu-v3 36600000.iommu: allocated 32768 entries for evtq
    [    0.091290] arm-smmu-v3 36600000.iommu: msi_domain absent - falling back to wired irqs
    [    0.096984] loop: module loaded
    [    0.097575] megasas: 07.734.00.00-rc1
    [    0.103452] tun: Universal TUN/TAP device driver, 1.6
    [    0.103901] thunder_xcv, ver 1.0
    [    0.103920] thunder_bgx, ver 1.0
    [    0.103940] nicpf, ver 1.0
    [    0.104231] hns3: Hisilicon Ethernet Network Driver for Hip08 Family - version
    [    0.104234] hns3: Copyright (c) 2017 Huawei Corporation.
    [    0.104264] hclge is initializing
    [    0.104282] e1000: Intel(R) PRO/1000 Network Driver
    [    0.104284] e1000: Copyright (c) 1999-2006 Intel Corporation.
    [    0.104301] e1000e: Intel(R) PRO/1000 Network Driver
    [    0.104303] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
    [    0.104322] igb: Intel(R) Gigabit Ethernet Network Driver
    [    0.104323] igb: Copyright (c) 2007-2014 Intel Corporation.
    [    0.104343] igbvf: Intel(R) Gigabit Virtual Function Network Driver
    [    0.104345] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
    [    0.104429] sky2: driver version 1.30
    [    0.105170] VFIO - User Level meta-driver version: 0.3
    [    0.106344] usbcore: registered new interface driver usb-storage
    [    0.107444] i2c_dev: i2c /dev entries driver
    [    0.107771] usbcore: registered new interface driver uvcvideo
    [    0.108607] sdhci: Secure Digital Host Controller Interface driver
    [    0.108610] sdhci: Copyright(c) Pierre Ossman
    [    0.108965] Synopsys Designware Multimedia Card Interface Driver
    [    0.109306] sdhci-pltfm: SDHCI platform and OF driver helper
    [    0.110052] SMCCC: SOC_ID: ARCH_SOC_ID not implemented, skipping ....
    [    0.110633] usbcore: registered new interface driver usbhid
    [    0.110635] usbhid: USB HID core driver
    [    0.111388] hw perfevents: enabled with armv8_cortex_a72 PMU driver, 7 (0,8000003f) counters available
    [    0.111754] optee: probing for conduit method.
    [    0.111771] optee: revision 4.6
    [    0.128280] optee: dynamic shared memory is enabled
    [    0.129238] optee: initialized driver
    [    0.130429] random: crng init done
    [    0.130749] NET: Registered PF_PACKET protocol family
    [    0.130788] Key type dns_resolver registered
    [    0.135776] registered taskstats version 1
    [    0.135859] Loading compiled-in X.509 certificates
    [    0.139942] Demotion targets for Node 0: null
    [    0.144058] ti-sci 44083000.system-controller: ABI: 4.0 (firmware rev 0x000b '11.0.9--v11.00.09+ (Fancy Rat)')
    [    0.278788] omap_i2c 42120000.i2c: bus 0 rev0.12 at 400 kHz
    [    0.279397] omap_i2c 2000000.i2c: bus 4 rev0.12 at 400 kHz
    [    0.279930] /bus@100000/ticsi2rx@4510000/csi-bridge@4514000: Fixed dependency cycle(s) with /bus@100000/i2c@2010000/lt7911d@2b
    [    0.279977] /bus@100000/i2c@2010000/lt7911d@2b: Fixed dependency cycle(s) with /bus@100000/ticsi2rx@4510000/csi-bridge@4514000
    [    0.280083] omap_i2c 2010000.i2c: bus 5 rev0.12 at 400 kHz
    [    0.280650] omap_i2c 2020000.i2c: bus 2 rev0.12 at 100 kHz
    [    0.281170] omap_i2c 2030000.i2c: bus 6 rev0.12 at 400 kHz
    [    0.281666] omap_i2c 2040000.i2c: bus 3 rev0.12 at 100 kHz
    [    0.282214] /bus@100000/ticsi2rx@4500000/csi-bridge@4504000: Fixed dependency cycle(s) with /bus@100000/i2c@2050000/tc358743@f
    [    0.282263] /bus@100000/i2c@2050000/tc358743@f: Fixed dependency cycle(s) with /bus@100000/ticsi2rx@4500000/csi-bridge@4504000
    [    0.282368] tc358743 7-000f: untested bps per lane: 625000000 bps
    [    0.301197] tc358743 7-000f: i2c_rd: reading register 0x0 from 0xf failed: -121
    [    0.301209] tc358743 7-000f: not a TC358743 on address 0x1e
    [    0.301299] omap_i2c 2050000.i2c: bus 7 rev0.12 at 400 kHz
    [    0.302013] omap_i2c 2060000.i2c: bus 1 rev0.12 at 100 kHz
    [    0.302200] ti-sci-intr 42200000.interrupt-controller: Interrupt Router 137 domain created
    [    0.302318] ti-sci-intr bus@100000:interrupt-controller@a00000: Interrupt Router 131 domain created
    [    0.302437] ti-sci-intr 310e0000.interrupt-controller: Interrupt Router 213 domain created
    [    0.302617] ti-sci-inta 33d00000.interrupt-controller: Interrupt Aggregator domain 209 created
    [    0.313511] k3-ringacc 2b800000.ringacc: Ring Accelerator probed rings:286, gp-rings[96,20] sci-dev-id:235
    [    0.313521] k3-ringacc 2b800000.ringacc: dma-ring-reset-quirk: disabled
    [    0.313524] k3-ringacc 2b800000.ringacc: RA Proxy rev. 66346100, num_proxies:64
    [    0.315904] k3-ringacc 3c000000.ringacc: Ring Accelerator probed rings:1024, gp-rings[440,150] sci-dev-id:211
    [    0.315913] k3-ringacc 3c000000.ringacc: dma-ring-reset-quirk: disabled
    [    0.315916] k3-ringacc 3c000000.ringacc: RA Proxy rev. 66346100, num_proxies:64
    [    0.316535] printk: legacy console [ttyS2] disabled
    [    0.316720] 2800000.serial: ttyS2 at MMIO 0x2800000 (irq = 216, base_baud = 3000000) is a 8250
    [    0.316768] printk: legacy console [ttyS2] enabled
    [    0.697619] Freeing initrd memory: 28232K
    [    0.713475] am65-cpsw-nuss 46000000.ethernet: initializing am65 cpsw nuss version 0x6BA00101, cpsw version 0x6BA80100 Ports: 2 quirks:00000000
    [    2.584813] davinci_mdio 46000f00.mdio: Configuring MDIO in manual mode
    [    2.625124] davinci_mdio 46000f00.mdio: davinci mdio revision 9.7, bus freq 1000000
    [    2.636824] davinci_mdio 46000f00.mdio: phy[0]: device 46000f00.mdio:00, driver TI DP83867
    [    2.645185] am65-cpsw-nuss 46000000.ethernet: initialized cpsw ale version 1.4
    [    2.652395] am65-cpsw-nuss 46000000.ethernet: ALE Table size 64, Policers 8
    [    2.661976] mmc0: CQHCI version 5.10
    [    2.672255] LT7911D 5-002b: driver version: 00.01.02
    [    2.693939] LT7911D 5-002b: check chipid ok, id:0x516
    [    2.699156] LT7911D 5-002b: failed to get plugin det irq, maybe no use
    [    2.705667] mmc0: SDHCI controller on 4f80000.mmc [4f80000.mmc] using ADMA 64-bit
    [    2.713200] LT7911D 5-002b: failed to register plugin det irq (-22), maybe no use
    [    2.720723] m_LT7911D 5-002b: lt7911d found @ 0x56 (OMAP I2C adapter)
    [    2.735120] leds-gpio leds: Led :disk-activity renamed to :disk-activity_1 due to name collision
    [    2.744761] j721e-pcie 2910000.pcie: host bridge /bus@100000/pcie@2910000 ranges:
    [    2.752297] j721e-pcie 2910000.pcie:       IO 0x4100001000..0x4100100fff -> 0x0000001000
    [    2.760409] j721e-pcie 2910000.pcie:      MEM 0x4100101000..0x41ffffffff -> 0x0000101000
    [    2.768494] j721e-pcie 2910000.pcie:   IB MEM 0x0000000000..0xffffffffffff -> 0x0000000000
    [    2.826017] mmc0: Command Queue Engine enabled
    [    2.830471] mmc0: new HS200 MMC card at address 0001
    [    2.835765] mmcblk0: mmc0:0001 TB2916 14.6 GiB
    [    2.841130]  mmcblk0: p1 p2
    [    2.844161] mmcblk0boot0: mmc0:0001 TB2916 4.00 MiB
    [    2.850113] mmcblk0boot1: mmc0:0001 TB2916 4.00 MiB
    [    2.855926] mmcblk0rpmb: mmc0:0001 TB2916 4.00 MiB, chardev (237:0)
    [    3.877513] j721e-pcie 2910000.pcie: PCI host bridge to bus 0000:00
    [    3.883824] pci_bus 0000:00: root bus resource [bus 00-ff]
    [    3.889303] pci_bus 0000:00: root bus resource [io  0x0000-0xfffff] (bus address [0x1000-0x100fff])
    [    3.898330] pci_bus 0000:00: root bus resource [mem 0x4100101000-0x41ffffffff] (bus address [0x00101000-0xffffffff])
    [    3.908853] pci 0000:00:00.0: [104c:b00d] type 01 class 0x060400 PCIe Root Port
    [    3.916148] pci_bus 0000:00: 2-byte config write to 0000:00:00.0 offset 0x4 may corrupt adjacent RW1C bits
    [    3.925795] pci 0000:00:00.0: PCI bridge to [bus 00]
    [    3.930751] pci 0000:00:00.0:   bridge window [io  0x0000-0x0fff]
    [    3.936832] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff]
    [    3.943612] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff 64bit pref]
    [    3.951392] pci 0000:00:00.0: supports D1
    [    3.955391] pci 0000:00:00.0: PME# supported from D0 D1 D3hot
    [    3.962711] pci 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring
    [    3.970805] pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01
    [    3.977417] pci 0000:00:00.0: PCI bridge to [bus 01]
    [    3.982375] pci_bus 0000:00: resource 4 [io  0x0000-0xfffff]
    [    3.988024] pci_bus 0000:00: resource 5 [mem 0x4100101000-0x41ffffffff]
    [    3.994711] pcieport 0000:00:00.0: of_irq_parse_pci: failed with rc=-22
    [    4.001536] pcieport 0000:00:00.0: PME: Signaling with IRQ 484
    [    4.007529] pcieport 0000:00:00.0: AER: enabled with IRQ 484
    [    4.014179] ti-udma 285c0000.dma-controller: Channels: 26 (tchan: 13, rchan: 13, gp-rflow: 8)
    [    4.025461] ti-udma 31150000.dma-controller: Channels: 122 (tchan: 61, rchan: 61, gp-rflow: 16)
    [    4.037622] cdns-mhdp8546 a000000.dp-bridge: error -EINVAL: invalid resource (null)
    [    4.045366] cdns-mhdp8546 a000000.dp-bridge: Failed to get SAPB memory resource, HDCP not supported
    [    4.058302] [drm] Initialized tidss 1.0.0 for 4a00000.dss on minor 0
    [    4.064718] tidss 4a00000.dss: [drm] Cannot find any crtc or sizes
    [    4.071475] am65-cpsw-nuss 46000000.ethernet: initializing am65 cpsw nuss version 0x6BA00101, cpsw version 0x6BA80100 Ports: 2 quirks:00000000
    [    4.084551] davinci_mdio 46000f00.mdio: Configuring MDIO in manual mode
    [    4.125130] davinci_mdio 46000f00.mdio: davinci mdio revision 9.7, bus freq 1000000
    [    4.136131] davinci_mdio 46000f00.mdio: phy[0]: device 46000f00.mdio:00, driver TI DP83867
    [    4.144478] am65-cpsw-nuss 46000000.ethernet: initialized cpsw ale version 1.4
    [    4.151688] am65-cpsw-nuss 46000000.ethernet: ALE Table size 64, Policers 8
    [    4.165634] am65-cpsw-nuss 46000000.ethernet: set new flow-id-base 48
    [    4.178732] /bus@100000/i2c@2050000/tc358743@f: Fixed dependency cycle(s) with /bus@100000/ticsi2rx@4500000/csi-bridge@4504000
    [    4.190186] /bus@100000/ticsi2rx@4500000/csi-bridge@4504000: Fixed dependency cycle(s) with /bus@100000/i2c@2050000/tc358743@f
    [    4.202146] j721e-csi2rx 4500000.ticsi2rx: media_gobj_create id 1: entity 'cdns_csi2rx.4504000.csi-bridge'
    [    4.202154] j721e-csi2rx 4500000.ticsi2rx: media_gobj_create id 2: sink pad 'cdns_csi2rx.4504000.csi-bridge':0
    [    4.202159] j721e-csi2rx 4500000.ticsi2rx: media_gobj_create id 3: source pad 'cdns_csi2rx.4504000.csi-bridge':1
    [    4.202163] j721e-csi2rx 4500000.ticsi2rx: media_gobj_create id 4: source pad 'cdns_csi2rx.4504000.csi-bridge':2
    [    4.202167] j721e-csi2rx 4500000.ticsi2rx: media_gobj_create id 5: source pad 'cdns_csi2rx.4504000.csi-bridge':3
    [    4.202171] j721e-csi2rx 4500000.ticsi2rx: media_gobj_create id 6: source pad 'cdns_csi2rx.4504000.csi-bridge':4
    [    4.202179] cdns-csi2rx 4504000.csi-bridge: Probed CSI2RX with 4/4 lanes, 4 streams, external D-PHY
    [    4.214190] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 1: entity 'cdns_csi2rx.4514000.csi-bridge'
    [    4.214201] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 2: sink pad 'cdns_csi2rx.4514000.csi-bridge':0
    [    4.214205] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 3: source pad 'cdns_csi2rx.4514000.csi-bridge':1
    [    4.214209] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 4: source pad 'cdns_csi2rx.4514000.csi-bridge':2
    [    4.214213] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 5: source pad 'cdns_csi2rx.4514000.csi-bridge':3
    [    4.214217] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 6: source pad 'cdns_csi2rx.4514000.csi-bridge':4
    [    4.214225] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 7: entity 'm_LT7911D 5-002b'
    [    4.214229] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 8: source pad 'm_LT7911D 5-002b':0
    [    4.214233] cdns-csi2rx 4514000.csi-bridge: Bound m_LT7911D 5-002b pad: 0
    [    4.214237] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 9: data link id 8 ==> id 2
    [    4.214241] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 10: data link id 8 ==> id 2
    [    4.214327] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 11: entity 'j721e-csi2rx'
    [    4.214332] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 12: sink pad 'j721e-csi2rx':0
    [    4.214336] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 13: intf_devnode v4l-video - major: 81, minor: 0
    [    4.214341] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 14: interface link id 13 ==> id 11
    [    4.214347] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 15: data link id 3 ==> id 12
    [    4.214351] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 16: data link id 3 ==> id 12
    [    4.214404] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 17: intf_devnode v4l-subdev - major: 81, minor: 1
    [    4.214409] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 18: interface link id 17 ==> id 1
    [    4.214464] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 19: intf_devnode v4l-subdev - major: 81, minor: 2
    [    4.214469] j721e-csi2rx 4510000.ticsi2rx: media_gobj_create id 20: interface link id 19 ==> id 7
    [    4.214476] cdns-csi2rx 4514000.csi-bridge: Probed CSI2RX with 4/4 lanes, 4 streams, external D-PHY
    [    4.224760] mmc1: CQHCI version 5.10
    [    4.228775] input: gpio-keys as /devices/platform/gpio-keys/input/input0
    [    4.235846] clk: Disabling unused clocks
    [    4.266421] PM: genpd: Disabling unused power domains
    [    4.271609] ALSA device list:
    [    4.273124] mmc1: SDHCI controller on 4fb0000.mmc [4fb0000.mmc] using ADMA 64-bit
    [    4.274569]   No soundcards found.
    [    4.286264] Freeing unused kernel memory: 1600K
    [    4.290870] Run /init as init process
    [    4.294528]   with arguments:
    [    4.294530]     /init
    [    4.294532]   with environment:
    [    4.294534]     HOME=/
    [    4.294535]     TERM=linux
    [    4.343715] mmc1: new UHS-I speed DDR50 SDHC card at address aaaa
    [    4.350373] mmcblk1: mmc1:aaaa SE32G 29.7 GiB
    [    4.359329]  mmcblk1: p1 p2
    [    4.385863] am65-cpsw-nuss 46000000.ethernet eth0: PHY [46000f00.mdio:00] driver [TI DP83867] (irq=POLL)
    [    4.395812] am65-cpsw-nuss 46000000.ethernet eth0: configuring for phy/rgmii-rxid link mode
    [  605.986261] m_LT7911D 5-002b: act:1920x1080, total:2200x1125, pixclk:148366000, fps:60
    [  605.994178] m_LT7911D 5-002b: hfp:88, hs:44, hbp:148, vfp:4, vs:5, vbp:36
    [  606.000957] m_LT7911D 5-002b: inerlaced:0,
    [  606.006102] m_LT7911D 5-002b: Format_change: New format: 1920x1080p59.94 (2200x1125)
    [  665.120393] j721e-csi2rx 4510000.ticsi2rx: media pipeline: added pad 'j721e-csi2rx':0
    [  665.120410] j721e-csi2rx 4510000.ticsi2rx: media pipeline: pushed entry 0: 'j721e-csi2rx':0
    [  665.120415] j721e-csi2rx 4510000.ticsi2rx: media pipeline: entry 0 has no more links, popping
    [  665.120419] j721e-csi2rx 4510000.ticsi2rx: media pipeline: exploring link 'cdns_csi2rx.4514000.csi-bridge':1 -> 'j721e-csi2rx':0
    [  665.120424] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'j721e-csi2rx':0
    [  665.120428] j721e-csi2rx 4510000.ticsi2rx: media pipeline: added pad 'cdns_csi2rx.4514000.csi-bridge':1
    [  665.120431] j721e-csi2rx 4510000.ticsi2rx: media pipeline: pushed entry 0: 'cdns_csi2rx.4514000.csi-bridge':1
    [  665.120434] j721e-csi2rx 4510000.ticsi2rx: media pipeline: adding unconnected pads of 'j721e-csi2rx'
    [  665.120438] j721e-csi2rx 4510000.ticsi2rx: media pipeline: moved entry 0 to next link
    [  665.120441] j721e-csi2rx 4510000.ticsi2rx: media pipeline: exploring link 'm_LT7911D 5-002b':0 -> 'cdns_csi2rx.4514000.csi-bridge':0
    [  665.120445] j721e-csi2rx 4510000.ticsi2rx: media pipeline: added pad 'cdns_csi2rx.4514000.csi-bridge':0
    [  665.120449] j721e-csi2rx 4510000.ticsi2rx: media pipeline: pushed entry 1: 'cdns_csi2rx.4514000.csi-bridge':0
    [  665.120452] j721e-csi2rx 4510000.ticsi2rx: media pipeline: added pad 'm_LT7911D 5-002b':0
    [  665.120455] j721e-csi2rx 4510000.ticsi2rx: media pipeline: pushed entry 2: 'm_LT7911D 5-002b':0
    [  665.120458] j721e-csi2rx 4510000.ticsi2rx: media pipeline: entry 2 has no more links, popping
    [  665.120461] j721e-csi2rx 4510000.ticsi2rx: media pipeline: exploring link 'm_LT7911D 5-002b':0 -> 'cdns_csi2rx.4514000.csi-bridge':0
    [  665.120465] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'm_LT7911D 5-002b':0
    [  665.120468] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'cdns_csi2rx.4514000.csi-bridge':0
    [  665.120471] j721e-csi2rx 4510000.ticsi2rx: media pipeline: adding unconnected pads of 'm_LT7911D 5-002b'
    [  665.120474] j721e-csi2rx 4510000.ticsi2rx: media pipeline: moved entry 1 to next link
    [  665.120477] j721e-csi2rx 4510000.ticsi2rx: media pipeline: exploring link 'm_LT7911D 5-002b':0 -> 'cdns_csi2rx.4514000.csi-bridge':0
    [  665.120481] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'cdns_csi2rx.4514000.csi-bridge':0
    [  665.120484] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'm_LT7911D 5-002b':0
    [  665.120487] j721e-csi2rx 4510000.ticsi2rx: media pipeline: entry 1 has no more links, popping
    [  665.120490] j721e-csi2rx 4510000.ticsi2rx: media pipeline: exploring link 'cdns_csi2rx.4514000.csi-bridge':1 -> 'j721e-csi2rx':0
    [  665.120494] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'cdns_csi2rx.4514000.csi-bridge':1
    [  665.120497] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'j721e-csi2rx':0
    [  665.120500] j721e-csi2rx 4510000.ticsi2rx: media pipeline: adding unconnected pads of 'cdns_csi2rx.4514000.csi-bridge'
    [  665.120503] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'cdns_csi2rx.4514000.csi-bridge':1
    [  665.120507] j721e-csi2rx 4510000.ticsi2rx: media pipeline: entry 0 has no more links, popping
    [  665.120509] j721e-csi2rx 4510000.ticsi2rx: media pipeline: exploring link 'cdns_csi2rx.4514000.csi-bridge':1 -> 'j721e-csi2rx':0
    [  665.120513] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'cdns_csi2rx.4514000.csi-bridge':1
    [  665.120516] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'j721e-csi2rx':0
    [  665.120519] j721e-csi2rx 4510000.ticsi2rx: media pipeline: adding unconnected pads of 'cdns_csi2rx.4514000.csi-bridge'
    [  665.120522] j721e-csi2rx 4510000.ticsi2rx: media pipeline: already contains pad 'cdns_csi2rx.4514000.csi-bridge':0
    [  665.120525] j721e-csi2rx 4510000.ticsi2rx: media pipeline populated, found pads:
    [  665.120528] j721e-csi2rx 4510000.ticsi2rx: - 'j721e-csi2rx':0
    [  665.120531] j721e-csi2rx 4510000.ticsi2rx: - 'cdns_csi2rx.4514000.csi-bridge':1
    [  665.120534] j721e-csi2rx 4510000.ticsi2rx: - 'cdns_csi2rx.4514000.csi-bridge':0
    [  665.120537] j721e-csi2rx 4510000.ticsi2rx: - 'm_LT7911D 5-002b':0
    [  665.120540] j721e-csi2rx 4510000.ticsi2rx: Validating pad 'j721e-csi2rx':0
    [  665.120545] j721e-csi2rx 4510000.ticsi2rx: Link 'cdns_csi2rx.4514000.csi-bridge':1 -> 'j721e-csi2rx':0 is valid
    [  665.120549] j721e-csi2rx 4510000.ticsi2rx: Validating pad 'cdns_csi2rx.4514000.csi-bridge':1
    [  665.120553] j721e-csi2rx 4510000.ticsi2rx: Validating pad 'cdns_csi2rx.4514000.csi-bridge':0
    [  665.120557] j721e-csi2rx 4510000.ticsi2rx: validating link "m_LT7911D 5-002b":0 -> "cdns_csi2rx.4514000.csi-bridge":0
    [  665.120561] j721e-csi2rx 4510000.ticsi2rx: validating stream "m_LT7911D 5-002b":0:0 -> "cdns_csi2rx.4514000.csi-bridge":0:0
    [  665.120570] j721e-csi2rx 4510000.ticsi2rx: Link 'm_LT7911D 5-002b':0 -> 'cdns_csi2rx.4514000.csi-bridge':0 is valid
    [  665.120573] j721e-csi2rx 4510000.ticsi2rx: Validating pad 'm_LT7911D 5-002b':0
    [  665.120709] cdns-csi2rx 4514000.csi-bridge: Enabling error IRQs
    [  665.126670] cdns-mipi-dphy-rx 4590000.phy: In cdns_dphy_rx_configure
    [  665.133023] DPHY rate match 11
    [  665.145521] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x21100
    [  665.154027] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  665.164272] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x1060
    [  665.172689] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  665.182924] cdns-csi2rx 4514000.csi-bridge: Error interrupt: ECC error detected and corrected
    [  665.191425] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Unrecoverable ECC error
    [  665.199155] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x20010
    [  665.207657] cdns-csi2rx 4514000.csi-bridge: Error interrupt: CRC error
    [  665.214168] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x1060
    [  665.222583] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  665.232818] cdns-csi2rx 4514000.csi-bridge: Error interrupt: ECC error detected and corrected
    [  665.241318] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Unrecoverable ECC error
    [  665.249043] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x20010
    [  665.257544] cdns-csi2rx 4514000.csi-bridge: Error interrupt: CRC error
    [  668.323131] j721e-csi2rx 4510000.ticsi2rx: ti_csi2rx_stop_dma
    [  668.381585] j721e-csi2rx 4510000.ticsi2rx: DMA transfer timed out for drain buffer

    We currently have replicated the hardware (and the issue...) in another location and my colleague will attach some differential probes and a higher-spec oscilloscope to the CSI lanes. Maybe the results can then help...

    Thank you for your patience so far!

    Kind regards,
    Stefan

  • Hi ,

    Could you please point me towards the DT you mean? I found this one https://github.com/TexasInstruments/ti-linux-kernel/blob/ti-linux-6.18.y/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-dual-imx219.dtso, but it also does not contain the link-frequency in the CSI endpoint.

    Apologies, I meant the imx390 and fusion board: k3-fpdlink-imx390-cm-0-0.dtso and k3-j721e-evm-fusion.dtso.

    To not loose track, here are the current versions of the driver and DT as well as a full dmesg of boot and the capture above:

    Does the Toshiba part have anything to do with the pipeline? I assume not.

    Can you send the output of `media-ctl -p` and `yavta -c1 -F "img-#.raw" /dev/video0`?

    Best,
    Jared

  • Does the Toshiba part have anything to do with the pipeline? I assume not.

    No, this was just for testing with a similar device with 4 CSI lanes. Did not work perfectly, but better than with the Lontium. However we need DisplayPort input, not HDMI.

    Can you send the output of `media-ctl -p` and `yavta -c1 -F "img-#.raw" /dev/video0`?

    This is the output after booting:

    # media-ctl -p
    Media controller API version 6.16.5
    
    Media device information
    ------------------------
    driver          j721e-csi2rx
    model           TI-CSI2RX
    serial
    bus info        platform:4500000.ticsi2rx
    hw revision     0x1
    driver version  6.16.5
    
    Device topology
    - entity 1: cdns_csi2rx.4504000.csi-bridge (5 pads, 0 link, 0 routes)
                type V4L2 subdev subtype Unknown flags 0
            pad0: SINK
            pad1: SOURCE
            pad2: SOURCE
            pad3: SOURCE
            pad4: SOURCE
    
    # media-ctl -p -d 1
    Media controller API version 6.16.5
    
    Media device information
    ------------------------
    driver          j721e-csi2rx
    model           TI-CSI2RX
    serial
    bus info        platform:4510000.ticsi2rx
    hw revision     0x1
    driver version  6.16.5
    
    Device topology
    - entity 1: cdns_csi2rx.4514000.csi-bridge (5 pads, 2 links, 0 routes)
                type V4L2 subdev subtype Unknown flags 0
                device node name /dev/v4l-subdev0
            pad0: SINK
                    [stream:0 fmt:UYVY8_1X16/640x480 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
                    <- "m_LT7911D 5-002b":0 [ENABLED,IMMUTABLE]
            pad1: SOURCE
                    [stream:0 fmt:UYVY8_1X16/640x480 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
                    -> "j721e-csi2rx":0 [ENABLED,IMMUTABLE]
            pad2: SOURCE
                    [stream:0 fmt:UYVY8_1X16/640x480 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
            pad3: SOURCE
                    [stream:0 fmt:UYVY8_1X16/640x480 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
            pad4: SOURCE
                    [stream:0 fmt:UYVY8_1X16/640x480 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
    
    - entity 7: m_LT7911D 5-002b (1 pad, 1 link, 0 routes)
                type V4L2 subdev subtype Sensor flags 0
                device node name /dev/v4l-subdev1
            pad0: SOURCE
                    [stream:0 fmt:UYVY8_1X16/1920x1080@10000/300000 field:none colorspace:srgb]
                    [dv.caps:BT.656/1120 min:1x1@0 max:10000x10000@400000000 stds:CEA-861,DMT,CVT,GTF caps:interlaced,progressive,reduced-blanking,custom]
                    [dv.detect:BT.656/1120 1920x1080p59 (2200x1125) stds: flags:]
                    [dv.current:BT.656/1120 1920x1080p59 (2200x1125) stds: flags:]
                    -> "cdns_csi2rx.4514000.csi-bridge":0 [ENABLED,IMMUTABLE]
    
    - entity 11: j721e-csi2rx (1 pad, 1 link)
                 type Node subtype V4L flags 0
                 device node name /dev/video0
            pad0: SINK
                    <- "cdns_csi2rx.4514000.csi-bridge":1 [ENABLED,IMMUTABLE]

    And this after configuring the pipeline:

    # v4l2-ctl -d /dev/v4l-subdev1 --set-dv-bt-timings query
    BT timings set
    # media-ctl -d 1 --set-v4l2 '"cdns_csi2rx.4514000.csi-bridge":0[fmt:UYVY8_1X16/1920x1080 colorspace:srgb]'
    # v4l2-ctl -v width=1920,height=1080,pixelformat=UYVY
    #
    #
    #
    # media-ctl -p
    Media controller API version 6.16.5
    
    Media device information
    ------------------------
    driver          j721e-csi2rx
    model           TI-CSI2RX
    serial
    bus info        platform:4500000.ticsi2rx
    hw revision     0x1
    driver version  6.16.5
    
    Device topology
    - entity 1: cdns_csi2rx.4504000.csi-bridge (5 pads, 0 link, 0 routes)
                type V4L2 subdev subtype Unknown flags 0
            pad0: SINK
            pad1: SOURCE
            pad2: SOURCE
            pad3: SOURCE
            pad4: SOURCE
    
    # media-ctl -p -d 1
    Media controller API version 6.16.5
    
    Media device information
    ------------------------
    driver          j721e-csi2rx
    model           TI-CSI2RX
    serial
    bus info        platform:4510000.ticsi2rx
    hw revision     0x1
    driver version  6.16.5
    
    Device topology
    - entity 1: cdns_csi2rx.4514000.csi-bridge (5 pads, 2 links, 0 routes)
                type V4L2 subdev subtype Unknown flags 0
                device node name /dev/v4l-subdev0
            pad0: SINK
                    [stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb]
                    <- "m_LT7911D 5-002b":0 [ENABLED,IMMUTABLE]
            pad1: SOURCE
                    [stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb]
                    -> "j721e-csi2rx":0 [ENABLED,IMMUTABLE]
            pad2: SOURCE
                    [stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb]
            pad3: SOURCE
                    [stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb]
            pad4: SOURCE
                    [stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb]
    
    - entity 7: m_LT7911D 5-002b (1 pad, 1 link, 0 routes)
                type V4L2 subdev subtype Sensor flags 0
                device node name /dev/v4l-subdev1
            pad0: SOURCE
                    [stream:0 fmt:UYVY8_1X16/1920x1080@10000/300000 field:none colorspace:srgb]
                    [dv.caps:BT.656/1120 min:1x1@0 max:10000x10000@400000000 stds:CEA-861,DMT,CVT,GTF caps:interlaced,progressive,reduced-blanking,custom]
                    [dv.detect:BT.656/1120 1920x1080p59 (2200x1125) stds: flags:]
                    [dv.current:BT.656/1120 1920x1080p59 (2200x1125) stds: flags:]
                    -> "cdns_csi2rx.4514000.csi-bridge":0 [ENABLED,IMMUTABLE]
    
    - entity 11: j721e-csi2rx (1 pad, 1 link)
                 type Node subtype V4L flags 0
                 device node name /dev/video0
            pad0: SINK
                    <- "cdns_csi2rx.4514000.csi-bridge":1 [ENABLED,IMMUTABLE]

    Running YAVTA successfully:

    # yavta -c1 -F"img-#.raw" /dev/video0
    Device /dev/video0 opened.
    Device `j721e-csi2rx' on `platform:4510000.ticsi2rx' (driver 'j721e-csi2rx') supports video, capture, without mplanes.
    Video format: UYVY (59565955) 1920x1080 (stride 3840) field none buffer size 4147200
    8 buffers requested.
    length: 4147200 offset: 0 timestamp type/source: mono/EoF
    Buffer 0/0 mapped at address 0xffffafc5b000.
    length: 4147200 offset: 32768 timestamp type/source: mono/EoF
    Buffer 1/0 mapped at address 0xffffaf866000.
    length: 4147200 offset: 65536 timestamp type/source: mono/EoF
    Buffer 2/0 mapped at address 0xffffaf471000.
    length: 4147200 offset: 98304 timestamp type/source: mono/EoF
    Buffer 3/0 mapped at address 0xffffaf07c000.
    length: 4147200 offset: 131072 timestamp type/source: mono/EoF
    Buffer 4/0 mapped at address 0xffffaec87000.
    length: 4147200 offset: 163840 timestamp type/source: mono/EoF
    Buffer 5/0 mapped at address 0xffffae892000.
    length: 4147200 offset: 196608 timestamp type/source: mono/EoF
    Buffer 6/0 mapped at address 0xffffae49d000.
    length: 4147200 offset: 229376 timestamp type/source: mono/EoF
    Buffer 7/0 mapped at address 0xffffae0a8000.
    0 (0) [-] any 0 4147200 B 318.956754 318.962080 -188.076 fps ts mono/EoF
    Captured 1 frames in 0.000009 seconds (109589.041096 fps, 454487671232.876709 B/s).
    8 buffers released.
    
    ---
    Kernel log:
    [  413.209586] cdns-csi2rx 4514000.csi-bridge: Enabling error IRQs
    [  413.215519] cdns-mipi-dphy-rx 4590000.phy: In cdns_dphy_rx_configure
    [  413.221897] DPHY rate match 11
    [  413.225313] m_LT7911D 5-002b: I2C write 0x80ee = 0x01
    [  413.230539] m_LT7911D 5-002b: I2C write 0x900a = 0xbf
    [  413.235471] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x21100
    [  413.244075] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  413.254321] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x70
    [  413.262564] cdns-csi2rx 4514000.csi-bridge: Error interrupt: ECC error detected and corrected
    [  413.271065] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Unrecoverable ECC error
    [  413.278787] cdns-csi2rx 4514000.csi-bridge: Error interrupt: CRC error
    [  413.285309] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x21040
    [  413.293812] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  413.304046] cdns-csi2rx 4514000.csi-bridge: Error interrupt: ECC error detected and corrected
    [  413.312548] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x20
    [  413.320790] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Unrecoverable ECC error
    [  413.328513] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x1040
    [  413.336927] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  413.347162] cdns-csi2rx 4514000.csi-bridge: Error interrupt: ECC error detected and corrected
    [  413.355664] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x20
    [  413.363906] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Unrecoverable ECC error
    [  413.371842] m_LT7911D 5-002b: I2C write 0x80ee = 0x00
    [  413.382834] m_LT7911D 5-002b: I2C write 0x80ee = 0x01
    [  413.388106] m_LT7911D 5-002b: I2C write 0x900a = 0xbe
    [  413.393326] m_LT7911D 5-002b: I2C write 0x80ee = 0x00
    [  413.398392] j721e-csi2rx 4510000.ticsi2rx: ti_csi2rx_stop_dma

    And a failed/stuck YAVTA run:

    # yavta -c1 -F"img-#.raw" /dev/video0
    Device /dev/video0 opened.
    Device `j721e-csi2rx' on `platform:4510000.ticsi2rx' (driver 'j721e-csi2rx') supports video, capture, without mplanes.
    Video format: UYVY (59565955) 1920x1080 (stride 3840) field none buffer size 4147200
    8 buffers requested.
    length: 4147200 offset: 0 timestamp type/source: mono/EoF
    Buffer 0/0 mapped at address 0xffffb996b000.
    length: 4147200 offset: 32768 timestamp type/source: mono/EoF
    Buffer 1/0 mapped at address 0xffffb9576000.
    length: 4147200 offset: 65536 timestamp type/source: mono/EoF
    Buffer 2/0 mapped at address 0xffffb9181000.
    length: 4147200 offset: 98304 timestamp type/source: mono/EoF
    Buffer 3/0 mapped at address 0xffffb8d8c000.
    length: 4147200 offset: 131072 timestamp type/source: mono/EoF
    Buffer 4/0 mapped at address 0xffffb8997000.
    length: 4147200 offset: 163840 timestamp type/source: mono/EoF
    Buffer 5/0 mapped at address 0xffffb85a2000.
    length: 4147200 offset: 196608 timestamp type/source: mono/EoF
    Buffer 6/0 mapped at address 0xffffb81ad000.
    length: 4147200 offset: 229376 timestamp type/source: mono/EoF
    Buffer 7/0 mapped at address 0xffffb7db8000.
    ^C
    
    ---
    Kernel log:
    [  471.466386] cdns-csi2rx 4514000.csi-bridge: Enabling error IRQs
    [  471.472326] cdns-mipi-dphy-rx 4590000.phy: In cdns_dphy_rx_configure
    [  471.478705] DPHY rate match 11
    [  471.482128] m_LT7911D 5-002b: I2C write 0x80ee = 0x01
    [  471.487355] m_LT7911D 5-002b: I2C write 0x900a = 0xbf
    [  471.492575] m_LT7911D 5-002b: I2C write 0x80ee = 0x00
    [  471.493162] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x21100
    [  471.506110] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  471.516372] cdns-csi2rx 4514000.csi-bridge: csi2rx_irq_handler called, error_status = 0x10f0
    [  471.524789] cdns-csi2rx 4514000.csi-bridge: Error interrupt: A truncated header [short or long] has been received
    [  471.535024] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Data ID error in the header packet
    [  471.543698] cdns-csi2rx 4514000.csi-bridge: Error interrupt: ECC error detected and corrected
    [  471.552200] cdns-csi2rx 4514000.csi-bridge: Error interrupt: Unrecoverable ECC error
    [  471.559921] cdns-csi2rx 4514000.csi-bridge: Error interrupt: CRC error
    <After Ctrl-C>
    [  476.795782] m_LT7911D 5-002b: I2C write 0x80ee = 0x01
    [  476.801095] m_LT7911D 5-002b: I2C write 0x900a = 0xbe
    [  476.806322] m_LT7911D 5-002b: I2C write 0x80ee = 0x00
    [  476.811372] j721e-csi2rx 4510000.ticsi2rx: ti_csi2rx_stop_dma
    

    Stefan

  • Hi ,

    It's interesting that sometimes yavta succeeds. Were there any changes you needed to make to print the error statements?

    If not, I will test our serializer/deserializer and see if the ECC errors occur with it. I assume the ECC errors won't appear, but it's better to check.

    Best,
    Jared

  • Were there any changes you needed to make to print the error statements?

    Those are from cdns-csi2rx.c, which I mainly changed according to this patch: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/media/platform/cadence/cdns-csi2rx.c?h=v6.19-rc5&id=9f2d0da9b8c3477cd5ed4e1ed1e58bb44184561b I also added a dev_info() call to immediately log the error when the interrupt is fired, not just collecting statistics. This is the diff:

    diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
    index cebcae196..9c7000206 100644
    --- a/drivers/media/platform/cadence/cdns-csi2rx.c
    +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
    @@ -4,6 +4,7 @@
      *
      * Copyright (C) 2017 Cadence Design Systems Inc.
      */
    +#define DEBUG
     
     #include <linux/clk.h>
     #include <linux/delay.h>
    @@ -57,6 +58,25 @@
     #define CSI2RX_LANES_MAX	4
     #define CSI2RX_STREAMS_MAX	4
     
    +#define CSI2RX_ERROR_IRQS_REG			0x28
    +#define CSI2RX_ERROR_IRQS_MASK_REG		0x2C
    +
    +#define CSI2RX_STREAM3_FIFO_OVERFLOW_IRQ	BIT(19)
    +#define CSI2RX_STREAM2_FIFO_OVERFLOW_IRQ	BIT(18)
    +#define CSI2RX_STREAM1_FIFO_OVERFLOW_IRQ	BIT(17)
    +#define CSI2RX_STREAM0_FIFO_OVERFLOW_IRQ	BIT(16)
    +#define CSI2RX_FRONT_TRUNC_HDR_IRQ		BIT(12)
    +#define CSI2RX_PROT_TRUNCATED_PACKET_IRQ	BIT(11)
    +#define CSI2RX_FRONT_LP_NO_PAYLOAD_IRQ		BIT(10)
    +#define CSI2RX_SP_INVALID_RCVD_IRQ		BIT(9)
    +#define CSI2RX_DATA_ID_IRQ			BIT(7)
    +#define CSI2RX_HEADER_CORRECTED_ECC_IRQ	BIT(6)
    +#define CSI2RX_HEADER_ECC_IRQ			BIT(5)
    +#define CSI2RX_PAYLOAD_CRC_IRQ			BIT(4)
    +
    +#define CSI2RX_ECC_ERRORS		GENMASK(7, 4)
    +#define CSI2RX_PACKET_ERRORS		GENMASK(12, 9)
    +
     enum csi2rx_pads {
     	CSI2RX_PAD_SINK,
     	CSI2RX_PAD_SOURCE_STREAM0,
    @@ -71,9 +91,32 @@ struct csi2rx_fmt {
     	u8				bpp;
     };
     
    +struct csi2rx_event {
    +	u32 mask;
    +	const char *name;
    +};
    +
    +static const struct csi2rx_event csi2rx_events[] = {
    +	{ CSI2RX_STREAM3_FIFO_OVERFLOW_IRQ, "Overflow of the Stream 3 FIFO detected" },
    +	{ CSI2RX_STREAM2_FIFO_OVERFLOW_IRQ, "Overflow of the Stream 2 FIFO detected" },
    +	{ CSI2RX_STREAM1_FIFO_OVERFLOW_IRQ, "Overflow of the Stream 1 FIFO detected" },
    +	{ CSI2RX_STREAM0_FIFO_OVERFLOW_IRQ, "Overflow of the Stream 0 FIFO detected" },
    +	{ CSI2RX_FRONT_TRUNC_HDR_IRQ, "A truncated header [short or long] has been received" },
    +	{ CSI2RX_PROT_TRUNCATED_PACKET_IRQ, "A truncated long packet has been received" },
    +	{ CSI2RX_FRONT_LP_NO_PAYLOAD_IRQ, "A truncated long packet has been received. No payload" },
    +	{ CSI2RX_SP_INVALID_RCVD_IRQ, "A reserved or invalid short packet has been received" },
    +	{ CSI2RX_DATA_ID_IRQ, "Data ID error in the header packet" },
    +	{ CSI2RX_HEADER_CORRECTED_ECC_IRQ, "ECC error detected and corrected" },
    +	{ CSI2RX_HEADER_ECC_IRQ, "Unrecoverable ECC error" },
    +	{ CSI2RX_PAYLOAD_CRC_IRQ, "CRC error" },
    +};
    +
    +#define CSI2RX_NUM_EVENTS		ARRAY_SIZE(csi2rx_events)
    +
     struct csi2rx_priv {
     	struct device			*dev;
     	unsigned int			count;
    +	int				error_irq;
     
     	/*
     	 * Used to prevent race conditions between multiple,
    @@ -95,6 +138,7 @@ struct csi2rx_priv {
     	u8				max_lanes;
     	u8				max_streams;
     	bool				has_internal_dphy;
    +	u32				events[CSI2RX_NUM_EVENTS];
     
     	struct v4l2_subdev		subdev;
     	struct v4l2_async_notifier	notifier;
    @@ -124,6 +168,59 @@ static const struct csi2rx_fmt formats[] = {
     	{ .code	= MEDIA_BUS_FMT_BGR888_1X24,  .bpp = 24, },
     };
     
    +static void csi2rx_configure_error_irq_mask(void __iomem *base,
    +					    struct csi2rx_priv *csi2rx)
    +{
    +	u32 error_irq_mask = 0;
    +
    +	error_irq_mask |= CSI2RX_ECC_ERRORS;
    +	error_irq_mask |= CSI2RX_PACKET_ERRORS;
    +
    +	/*
    +	 * Iterate through all source pads and check if they are linked
    +	 * to an active remote pad. If an active remote pad is found,
    +	 * calculate the corresponding bit position and set it in
    +	 * mask, enabling the stream overflow error in the mask.
    +	 */
    +	for (int i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++) {
    +		struct media_pad *remote_pad;
    +
    +		remote_pad = media_pad_remote_pad_first(&csi2rx->pads[i]);
    +		if (remote_pad) {
    +			int pad = i - CSI2RX_PAD_SOURCE_STREAM0;
    +			u32 bit_mask = CSI2RX_STREAM0_FIFO_OVERFLOW_IRQ << pad;
    +
    +			error_irq_mask |= bit_mask;
    +		}
    +	}
    +
    +	writel(error_irq_mask, base + CSI2RX_ERROR_IRQS_MASK_REG);
    +}
    +
    +static irqreturn_t csi2rx_irq_handler(int irq, void *dev_id)
    +{
    +	struct csi2rx_priv *csi2rx = dev_id;
    +	int i;
    +	u32 error_status, error_mask;
    +
    +	error_status = readl(csi2rx->base + CSI2RX_ERROR_IRQS_REG);
    +	error_mask = readl(csi2rx->base + CSI2RX_ERROR_IRQS_MASK_REG);
    +
    +	dev_info(csi2rx->dev, "csi2rx_irq_handler called, error_status = 0x%x\n", error_status);
    +
    +	for (i = 0; i < CSI2RX_NUM_EVENTS; i++)
    +		if ((error_status & csi2rx_events[i].mask) &&
    +		    (error_mask & csi2rx_events[i].mask)) {
    +			csi2rx->events[i]++;
    +			dev_info(csi2rx->dev, "Error interrupt: %s\n",
    +				 csi2rx_events[i].name);
    +		}
    +
    +	writel(error_status, csi2rx->base + CSI2RX_ERROR_IRQS_REG);
    +
    +	return IRQ_HANDLED;
    +}
    +
     static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
     {
     	unsigned int i;
    @@ -178,27 +275,36 @@ static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx)
     
     	ret = v4l2_subdev_call_state_active(&csi2rx->subdev, pad, get_fmt,
     					    &sd_fmt);
    -	if (ret < 0)
    +	if (ret < 0) {
    +		dev_err(csi2rx->dev, "v4l2_subdev_call_state_active failed: %d\n", ret);
     		return ret;
    +	}
     
     	fmt = csi2rx_get_fmt_by_code(sd_fmt.format.code);
     
     	link_freq = v4l2_get_link_freq(src_pad,
     				       fmt->bpp, 2 * csi2rx->num_lanes);
    -	if (link_freq < 0)
    +	if (link_freq < 0) {
    +		dev_err(csi2rx->dev, "v4l2_get_link_freq failed: %lld\n", link_freq);
     		return link_freq;
    +	}
     
     	ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq,
     							 csi2rx->num_lanes, cfg);
    -	if (ret)
    +	if (ret) {
    +		dev_err(csi2rx->dev, "phy_mipi_dphy_get_default_config_for_hsclk failed: %d\n", ret);
     		return ret;
    +	}
     
     	ret = phy_power_on(csi2rx->dphy);
    -	if (ret)
    +	if (ret) {
    +		dev_err(csi2rx->dev, "phy_power_on failed: %d\n", ret);
     		return ret;
    +	}
     
     	ret = phy_configure(csi2rx->dphy, &opts);
     	if (ret) {
    +		dev_err(csi2rx->dev, "phy_configure failed: %d\n", ret);
     		phy_power_off(csi2rx->dphy);
     		return ret;
     	}
    @@ -220,6 +326,11 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
     	reset_control_deassert(csi2rx->p_rst);
     	csi2rx_reset(csi2rx);
     
    +	if (csi2rx->error_irq >= 0) {
    +		dev_info(csi2rx->dev, "Enabling error IRQs\n");
    +		csi2rx_configure_error_irq_mask(csi2rx->base, csi2rx);
    +	}
    +
     	reg = csi2rx->num_lanes << 8;
     	for (i = 0; i < csi2rx->num_lanes; i++) {
     		reg |= CSI2RX_STATIC_CFG_DLANE_MAP(i, csi2rx->lanes[i]);
    @@ -332,6 +443,8 @@ static void csi2rx_stop(struct csi2rx_priv *csi2rx)
     	reset_control_assert(csi2rx->sys_rst);
     	clk_disable_unprepare(csi2rx->sys_clk);
     
    +	writel(0, csi2rx->base + CSI2RX_ERROR_IRQS_MASK_REG);
    +
     	for (i = 0; i < csi2rx->max_streams; i++) {
     		writel(CSI2RX_STREAM_CTRL_STOP,
     		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
    @@ -363,6 +476,21 @@ static void csi2rx_stop(struct csi2rx_priv *csi2rx)
     	}
     }
     
    +static int csi2rx_log_status(struct v4l2_subdev *sd)
    +{
    +	struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(sd);
    +	unsigned int i;
    +
    +	for (i = 0; i < CSI2RX_NUM_EVENTS; i++) {
    +		if (csi2rx->events[i])
    +			dev_info(csi2rx->dev, "%s events: %d\n",
    +				 csi2rx_events[i].name,
    +				 csi2rx->events[i]);
    +	}
    +
    +	return 0;
    +}
    +
     static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
     {
     	struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev);
    @@ -468,7 +596,12 @@ static const struct v4l2_subdev_video_ops csi2rx_video_ops = {
     	.s_stream	= csi2rx_s_stream,
     };
     
    +static const struct v4l2_subdev_core_ops csi2rx_core_ops = {
    +	.log_status	= csi2rx_log_status,
    +};
    +
     static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
    +	.core		= &csi2rx_core_ops,
     	.video		= &csi2rx_video_ops,
     	.pad		= &csi2rx_pad_ops,
     };
    @@ -705,6 +838,21 @@ static int csi2rx_probe(struct platform_device *pdev)
     	if (ret)
     		goto err_cleanup;
     
    +	csi2rx->error_irq = platform_get_irq_byname_optional(pdev, "error_irq");
    +
    +	if (csi2rx->error_irq < 0) {
    +		dev_dbg(csi2rx->dev, "Optional interrupt not defined, proceeding without it\n");
    +	} else {
    +		ret = devm_request_irq(csi2rx->dev, csi2rx->error_irq,
    +				       csi2rx_irq_handler, 0,
    +				       dev_name(&pdev->dev), csi2rx);
    +		if (ret) {
    +			dev_err(csi2rx->dev,
    +				"Unable to request interrupt: %d\n", ret);
    +			goto err_cleanup;
    +		}
    +	}
    +
     	ret = v4l2_subdev_init_finalize(&csi2rx->subdev);
     	if (ret)
     		goto err_cleanup;
    

    This also needed the interrupts defined in the DT:

    diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
    index 5bd0d36bf..ab3666ff4 100644
    --- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
    +++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
    @@ -608,6 +608,9 @@ ti_csi2rx0: ticsi2rx@4500000 {
     		cdns_csi2rx0: csi-bridge@4504000 {
     			compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
     			reg = <0x0 0x4504000 0x0 0x1000>;
    +			interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
    +				     <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
    +			interrupt-names = "error_irq", "irq";
     			clocks = <&k3_clks 26 2>, <&k3_clks 26 0>, <&k3_clks 26 2>,
     				<&k3_clks 26 2>, <&k3_clks 26 3>, <&k3_clks 26 3>;
     			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
    @@ -661,6 +664,9 @@ ti_csi2rx1: ticsi2rx@4510000 {
     		cdns_csi2rx1: csi-bridge@4514000 {
     			compatible = "ti,j721e-csi2rx", "cdns,csi2rx";
     			reg = <0x0 0x4514000 0x0 0x1000>;
    +			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
    +				     <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
    +			interrupt-names = "error_irq", "irq";
     			clocks = <&k3_clks 27 2>, <&k3_clks 27 0>, <&k3_clks 27 2>,
     				 <&k3_clks 27 2>, <&k3_clks 27 3>, <&k3_clks 27 3>;
     			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
    

    YAVTA itself is unchanged.

    Kind regards,
    Stefan

  • Hi ,

    I will test this on my EVM.

    Best,
    Jared

  • Hi ,

    I tried testing a CSI camera with the changes/message logs. I can confirm that I do not see the ECC errors with a known working CSI camera.

    Looking at your media-ctl pipeline, mine contains, "4500000.ticsi2rx" and "cdns_csi2rx.4504000.csi-bridge", do you know why your "4500000.ticsi2rx" is named j721e-csirx?

    Best,
    Jared