Post Go back to editing

Problems getting ADV7180-m working with iMX8M PLUS running Boot2Qt

Category: Software
Product Number: ADV7180-m
Software Version: Boot2Qt Kirkstone (Qt 6.4.3, kernel 5.15.60)

Hi,

We are using iMX8MP running Boot2Qt and I have been trying to get ADV7180-m working for a long time. I modified the device tree as follows: 

&mipi_csi_0 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
bus-width = <1>;

clock-frequency = <108000000>;

port@0 {
reg = <0>;

mipi_csi0_ep: endpoint {
csis-hs-settle = <13>;
csis-clk-settle = <2>;
csis-wclk;
data-lanes = <1>;
remote-endpoint = <&adv728xm_mipi_0_ep>;
};
};
};

&i2c3 {
clock-frequency = <400000>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
pinctrl-1 = <&pinctrl_i2c3_gpio>;
scl-gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>;
sda-gpios = <&gpio5 19 GPIO_ACTIVE_HIGH>;
status = "okay";

adv7280-m@21 {
status = "okay";
compatible = "adi,adv7280-m";
reg = <0x21>;

port {
adv728xm_mipi_0_ep: endpoint {
remote-endpoint = <&mipi_csi0_ep>;
};
};
};

};

Then, I added the module to kernel and built the image. The driver is now loaded at bootup, but I cannot work with it. When checking the list of video devices, I would get this output:

root@b2qt-imx8mp-var-dart:~# v4l2-ctl --list-devices
[ 668.839433] mxc-mipi-csi2.0: is_entity_link_setup, No remote pad found!
mxc-isi-cap (platform:32e00000.isi:cap_devic):
/dev/video1

mxc-isi-m2m (platform:32e00000.isi:m2m_devic):
/dev/video0

When I ran my Qt application to display the camera image, the "No remote pad found!" error kept printing on the terminal,

[ 4052.979362] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4052.986788] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote pad found!
[ 4052.993867] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4053.001269] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote pad found!
[ 4053.008339] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4053.015783] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote pad found!
[ 4053.022849] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4053.650958] mxc-mipi-csi2.0: is_entity_link_setup, No remote pad found!
[ 4053.683006] mxc-mipi-csi2.0: is_entity_link_setup, No remote pad found!
[ 4053.690295] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote pad found!
[ 4053.697395] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4053.705015] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote pad found!
[ 4053.712117] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4053.719549] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote pad found!
[ 4053.726622] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4053.734042] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote pad found!
[ 4053.741108] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4053.748501] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote pad found!
[ 4053.755594] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4053.763115] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote pad found!
[ 4053.770371] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4053.777900] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote pad found!
[ 4053.785095] mxc-mipi-csi2.0: mipi_csis_enum_framesizes, No remote subdev found!
[ 4053.816752] mxc-mipi-csi2.0: mipi_csis_g_frame_interval, No remote pad found!
[ 4053.823986] mxc-mipi-csi2.0: mipi_csis_g_frame_interval, No remote subdev found!
[ 4053.852515] mxc-mipi-csi2.0: mipi_csis_s_power, No remote pad found!
[ 4053.858926] mxc-mipi-csi2.0: mipi_csis_s_power, No remote subdev found!
[ 4053.865594] mxc_isi.0: Call subdev s_power fail!

and when I tried enabling the color image from the ADV, I would get this output:

root@b2qt-imx8mp-var-dart:~# v4l2-ctl --set-standard 255
VIDIOC_S_STD: failed: Inappropriate ioctl for device

At this point, I decided to modify the ADV7180.c driver file to silence the "No remote pad found!" error. Although there were some improvements, but the problem still exists. Now, after running the list devices command, I get the following:

root@b2qt-imx8mp-var-dart:~# v4l2-ctl --list-devices
():
/dev/v4l-subdev0
mxc-isi-cap (platform:32e00000.isi:cap_devic):
/dev/video1
mxc-isi-m2m (platform:32e00000.isi:m2m_devic):
/dev/video0
FSL Capture Media Device (platform:mxc-md):
/dev/media0

But I still cannot configure the ADV with --set-standard 255, I get the same error. When I try to take a screenshot with GStreamer, I get the logs attached as gst_logs. I have also attached the device tree file, the dmesg logs, and the modified ADV7180.c driver file.

I hope you can help me with this problem as this should not have taken so long. I have already interfaced the ADV7180 with the Raspberry pi compute module 4, but it has taken too much effort to get past it in iMX8MP. I appreciate any help you could provide.

Regards,

Enayat

gst_logs.txt

root@b2qt-imx8mp-var-dart:~# dmesg
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 5.15.60-imx8mp+gb1166e327b21 (oe-user@oe-host) (aarch64-poky-linux-gcc (GCC) 11.3.0, GNU ld (GNU Binutils) 2.38.20220708) #1 SMP PREEMPT Sat Jun 10 07:41:51 UTC 2023
[    0.000000] Machine model: Variscite VAR-SOM-MX8M-PLUS on Symphony-Board
[    0.000000] efi: UEFI not found.
[    0.000000] Reserved memory: bypass linux,cma node, using cmdline CMA params instead
[    0.000000] OF: reserved mem: node linux,cma compatible matching fail
[    0.000000] Reserved memory: created DMA memory pool at 0x0000000094300000, size 1 MiB
[    0.000000] OF: reserved mem: initialized node vdev0buffer@94300000, compatible id shared-dma-pool
[    0.000000] NUMA: No NUMA configuration found
[    0.000000] NUMA: Faking a node at [mem 0x0000000040000000-0x000000013fffffff]
[    0.000000] NUMA: NODE_DATA [mem 0x13f839800-0x13f83bfff]
[    0.000000] Zone ranges:
[    0.000000]   DMA      [mem 0x0000000040000000-0x00000000ffffffff]
[    0.000000]   DMA32    empty
[    0.000000]   Normal   [mem 0x0000000100000000-0x000000013fffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000040000000-0x00000000923fffff]
[    0.000000]   node   0: [mem 0x0000000092400000-0x00000000a43fffff]
[    0.000000]   node   0: [mem 0x00000000a4400000-0x000000013fffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x000000013fffffff]
[    0.000000] cma: Reserved 960 MiB at 0x00000000c4000000
[    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: MIGRATE_INFO_TYPE not supported.
[    0.000000] psci: SMC Calling Convention v1.2
[    0.000000] percpu: Embedded 20 pages/cpu s43288 r8192 d30440 u81920
[    0.000000] pcpu-alloc: s43288 r8192 d30440 u81920 alloc=20*4096
[    0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3
[    0.000000] Detected VIPT I-cache on CPU0
[    0.000000] CPU features: detected: GIC system register CPU interface
[    0.000000] CPU features: detected: ARM erratum 845719
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 1032192
[    0.000000] Policy zone: Normal
[    0.000000] Kernel command line: console=ttymxc1,115200 root=/dev/mmcblk1p1 rootwait rw cma=960M cma_name=linux,cma
[    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] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] software IO TLB: mapped [mem 0x00000000c0000000-0x00000000c4000000] (64MB)
[    0.000000] Memory: 2739304K/4194304K available (18304K kernel code, 1528K rwdata, 7084K rodata, 3008K init, 570K bss, 471960K reserved, 983040K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, 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=256 to nr_cpu_ids=4.
[    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=4
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] GICv3: GIC: Using split EOI/Deactivate mode
[    0.000000] GICv3: 160 SPIs implemented
[    0.000000] GICv3: 0 Extended SPIs implemented
[    0.000000] GICv3: Distributor has no Range Selector support
[    0.000000] Root IRQ handler: gic_handle_irq
[    0.000000] GICv3: 16 PPIs implemented
[    0.000000] GICv3: CPU0: found redistributor 0 region 0:0x0000000038880000
[    0.000000] ITS: No ITS available, not enabling LPIs
[    0.000000] arch_timer: cp15 timer(s) running at 8.00MHz (phys).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 440795202120 ns
[    0.000000] sched_clock: 56 bits at 8MHz, resolution 125ns, wraps every 2199023255500ns
[    0.000432] Console: colour dummy device 80x25
[    0.000498] Calibrating delay loop (skipped), value calculated using timer frequency.. 16.00 BogoMIPS (lpj=32000)
[    0.000512] pid_max: default: 32768 minimum: 301
[    0.000569] LSM: Security Framework initializing
[    0.000657] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.000677] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.002041] rcu: Hierarchical SRCU implementation.
[    0.003256] EFI services will not be available.
[    0.003466] smp: Bringing up secondary CPUs ...
[    0.003876] Detected VIPT I-cache on CPU1
[    0.003902] GICv3: CPU1: found redistributor 1 region 0:0x00000000388a0000
[    0.003938] CPU1: Booted secondary processor 0x0000000001 [0x410fd034]
[    0.004387] Detected VIPT I-cache on CPU2
[    0.004405] GICv3: CPU2: found redistributor 2 region 0:0x00000000388c0000
[    0.004424] CPU2: Booted secondary processor 0x0000000002 [0x410fd034]
[    0.004851] Detected VIPT I-cache on CPU3
[    0.004870] GICv3: CPU3: found redistributor 3 region 0:0x00000000388e0000
[    0.004889] CPU3: Booted secondary processor 0x0000000003 [0x410fd034]
[    0.004947] smp: Brought up 1 node, 4 CPUs
[    0.004974] SMP: Total of 4 processors activated.
[    0.004982] CPU features: detected: 32-bit EL0 Support
[    0.004988] CPU features: detected: 32-bit EL1 Support
[    0.004996] CPU features: detected: CRC32 instructions
[    0.012533] CPU: All CPU(s) started at EL2
[    0.012567] alternatives: patching kernel code
[    0.014017] devtmpfs: initialized
[    0.022482] KASLR disabled due to lack of seed
[    0.022630] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.022649] futex hash table entries: 1024 (order: 4, 65536 bytes, linear)
[    0.047972] pinctrl core: initialized pinctrl subsystem
[    0.048495] DMI not present or invalid.
[    0.049054] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.053911] DMA: preallocated 512 KiB GFP_KERNEL pool for atomic allocations
[    0.054299] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
[    0.054709] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
[    0.054795] audit: initializing netlink subsys (disabled)
[    0.054993] audit: type=2000 audit(0.052:1): state=initialized audit_enabled=0 res=1
[    0.055547] thermal_sys: Registered thermal governor 'step_wise'
[    0.055553] thermal_sys: Registered thermal governor 'power_allocator'
[    0.055836] cpuidle: using governor menu
[    0.056029] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[    0.056127] ASID allocator initialised with 65536 entries
[    0.057167] Serial: AMBA PL011 UART driver
[    0.057230] imx mu driver is registered.
[    0.057251] imx rpmsg driver is registered.
[    0.068085] imx8mp-pinctrl 30330000.pinctrl: initialized IMX pinctrl driver
[    0.078548] platform 32c00000.bus:ldb@32ec005c: Fixing up cyclic dependency with 32e90000.lcd-controller
[    0.083954] platform 32fd8000.hdmi: Fixing up cyclic dependency with 32fc6000.lcd-controller
[    0.090038] platform panel: Fixing up cyclic dependency with 32c00000.bus:ldb@32ec005c
[    0.103303] HugeTLB registered 1.00 GiB page size, pre-allocated 0 pages
[    0.103321] HugeTLB registered 32.0 MiB page size, pre-allocated 0 pages
[    0.103330] HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages
[    0.103338] HugeTLB registered 64.0 KiB page size, pre-allocated 0 pages
[    0.104553] cryptd: max_cpu_qlen set to 1000
[    0.107515] ACPI: Interpreter disabled.
[    0.108532] iommu: Default domain type: Translated
[    0.108543] iommu: DMA domain TLB invalidation policy: strict mode
[    0.108695] vgaarb: loaded
[    0.108953] SCSI subsystem initialized
[    0.109067] libata version 3.00 loaded.
[    0.109253] usbcore: registered new interface driver usbfs
[    0.109289] usbcore: registered new interface driver hub
[    0.109322] usbcore: registered new device driver usb
[    0.110276] mc: Linux media interface: v0.10
[    0.110303] videodev: Linux video capture interface: v2.00
[    0.110375] pps_core: LinuxPPS API ver. 1 registered
[    0.110383] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    0.110400] PTP clock support registered
[    0.110579] EDAC MC: Ver: 3.0.0
[    0.111684] FPGA manager framework
[    0.111769] Advanced Linux Sound Architecture Driver Initialized.
[    0.112283] Bluetooth: Core ver 2.22
[    0.112309] NET: Registered PF_BLUETOOTH protocol family
[    0.112315] Bluetooth: HCI device and connection manager initialized
[    0.112326] Bluetooth: HCI socket layer initialized
[    0.112335] Bluetooth: L2CAP socket layer initialized
[    0.112350] Bluetooth: SCO socket layer initialized
[    0.112991] clocksource: Switched to clocksource arch_sys_counter
[    0.113135] VFS: Disk quotas dquot_6.6.0
[    0.113174] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    0.113315] pnp: PnP ACPI: disabled
[    0.119219] NET: Registered PF_INET protocol family
[    0.119387] IP idents hash table entries: 65536 (order: 7, 524288 bytes, linear)
[    0.120922] tcp_listen_portaddr_hash hash table entries: 2048 (order: 3, 32768 bytes, linear)
[    0.120972] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.121005] TCP established hash table entries: 32768 (order: 6, 262144 bytes, linear)
[    0.121215] TCP bind hash table entries: 32768 (order: 7, 524288 bytes, linear)
[    0.121648] TCP: Hash tables configured (established 32768 bind 32768)
[    0.121736] UDP hash table entries: 2048 (order: 4, 65536 bytes, linear)
[    0.121820] UDP-Lite hash table entries: 2048 (order: 4, 65536 bytes, linear)
[    0.121992] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    0.122382] RPC: Registered named UNIX socket transport module.
[    0.122389] RPC: Registered udp transport module.
[    0.122396] RPC: Registered tcp transport module.
[    0.122403] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.122414] PCI: CLS 0 bytes, default 64
[    0.123041] hw perfevents: enabled with armv8_cortex_a53 PMU driver, 7 counters available
[    0.123789] kvm [1]: IPA Size Limit: 40 bits
[    0.125340] kvm [1]: GICv3: no GICV resource entry
[    0.125347] kvm [1]: disabling GICv2 emulation
[    0.125362] kvm [1]: GIC system register CPU interface enabled
[    0.125439] kvm [1]: vgic interrupt IRQ9
[    0.125544] kvm [1]: Hyp mode initialized successfully
[    0.128731] Initialise system trusted keyrings
[    0.128862] workingset: timestamp_bits=42 max_order=20 bucket_order=0
[    0.135204] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.135732] NFS: Registering the id_resolver key type
[    0.135776] Key type id_resolver registered
[    0.135782] Key type id_legacy registered
[    0.135856] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[    0.135865] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
[    0.135886] jffs2: version 2.2. (NAND) \xc2\xa9 2001-2006 Red Hat, Inc.
[    0.136206] 9p: Installing v9fs 9p2000 file system support
[    0.172035] Key type asymmetric registered
[    0.172046] Asymmetric key parser 'x509' registered
[    0.172098] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 243)
[    0.172190] io scheduler mq-deadline registered
[    0.172197] io scheduler kyber registered
[    0.178781] EINJ: ACPI disabled.
[    0.187818] mxs-dma 33000000.dma-apbh: initialized
[    0.189474] SoC: i.MX8MP revision 1.1
[    0.189908] Bus freq driver module loaded
[    0.195774] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    0.198019] 30860000.serial: ttymxc0 at MMIO 0x30860000 (irq = 33, base_baud = 1500000) is a IMX
[    0.198561] 30880000.serial: ttymxc2 at MMIO 0x30880000 (irq = 34, base_baud = 5000000) is a IMX
[    0.198978] 30890000.serial: ttymxc1 at MMIO 0x30890000 (irq = 35, base_baud = 1500000) is a IMX
[    1.271659] printk: console [ttymxc1] enabled
[    1.276495] 30a60000.serial: ttymxc3 at MMIO 0x30a60000 (irq = 41, base_baud = 1500000) is a IMX
[    1.300651] loop: module loaded
[    1.305200] megasas: 07.717.02.00-rc1
[    1.310504] imx ahci driver is registered.
[    1.320354] tun: Universal TUN/TAP device driver, 1.6
[    1.326347] thunder_xcv, ver 1.0
[    1.329621] thunder_bgx, ver 1.0
[    1.332881] nicpf, ver 1.0
[    1.337986] hclge is initializing
[    1.341327] hns3: Hisilicon Ethernet Network Driver for Hip08 Family - version
[    1.348559] hns3: Copyright (c) 2017 Huawei Corporation.
[    1.353938] e1000: Intel(R) PRO/1000 Network Driver
[    1.358825] e1000: Copyright (c) 1999-2006 Intel Corporation.
[    1.364614] e1000e: Intel(R) PRO/1000 Network Driver
[    1.369588] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    1.375544] igb: Intel(R) Gigabit Ethernet Network Driver
[    1.380948] igb: Copyright (c) 2007-2014 Intel Corporation.
[    1.386566] igbvf: Intel(R) Gigabit Virtual Function Network Driver
[    1.392842] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
[    1.398954] sky2: driver version 1.30
[    1.403264] usbcore: registered new interface driver r8152
[    1.409011] VFIO - User Level meta-driver version: 0.3
[    1.420177] usbcore: registered new interface driver uas
[    1.425556] usbcore: registered new interface driver usb-storage
[    1.431631] usbcore: registered new interface driver usbserial_generic
[    1.438190] usbserial: USB Serial support registered for generic
[    1.444226] usbcore: registered new interface driver ftdi_sio
[    1.449994] usbserial: USB Serial support registered for FTDI USB Serial Device
[    1.457338] usbcore: registered new interface driver usb_serial_simple
[    1.463894] usbserial: USB Serial support registered for carelink
[    1.470010] usbserial: USB Serial support registered for zio
[    1.475690] usbserial: USB Serial support registered for funsoft
[    1.481720] usbserial: USB Serial support registered for flashloader
[    1.488095] usbserial: USB Serial support registered for google
[    1.494037] usbserial: USB Serial support registered for libtransistor
[    1.500584] usbserial: USB Serial support registered for vivopay
[    1.506611] usbserial: USB Serial support registered for moto_modem
[    1.512903] usbserial: USB Serial support registered for motorola_tetra
[    1.519538] usbserial: USB Serial support registered for nokia
[    1.525398] usbserial: USB Serial support registered for novatel_gps
[    1.531771] usbserial: USB Serial support registered for hp4x
[    1.537541] usbserial: USB Serial support registered for suunto
[    1.543482] usbserial: USB Serial support registered for siemens_mpi
[    1.549870] usbcore: registered new interface driver usb_ehset_test
[    1.557649] input: 30370000.snvs:snvs-powerkey as /devices/platform/soc@0/30000000.bus/30370000.snvs/30370000.snvs:snvs-powerkey/input/input0
[    1.571636] i2c_dev: i2c /dev entries driver
[    1.580120] Bluetooth: HCI UART driver ver 2.3
[    1.584591] Bluetooth: HCI UART protocol H4 registered
[    1.589741] Bluetooth: HCI UART protocol BCSP registered
[    1.595080] Bluetooth: HCI UART protocol LL registered
[    1.600224] Bluetooth: HCI UART protocol ATH3K registered
[    1.605655] Bluetooth: HCI UART protocol Three-wire (H5) registered
[    1.612028] Bluetooth: HCI UART protocol Broadcom registered
[    1.617715] Bluetooth: HCI UART protocol QCA registered
[    1.623169] EDAC MC: ECC not enabled
[    1.628195] sdhci: Secure Digital Host Controller Interface driver
[    1.634392] sdhci: Copyright(c) Pierre Ossman
[    1.639531] Synopsys Designware Multimedia Card Interface Driver
[    1.646290] sdhci-pltfm: SDHCI platform and OF driver helper
[    1.654615] ledtrig-cpu: registered to indicate activity on CPUs
[    1.661755] SMCCC: SOC_ID: ARCH_SOC_ID not implemented, skipping ....
[    1.668694] usbcore: registered new interface driver usbhid
[    1.674280] usbhid: USB HID core driver
[    1.682636]  cs_system_cfg: CoreSight Configuration manager initialised
[    1.685500] mmc2: SDHCI controller on 30b60000.mmc [30b60000.mmc] using ADMA
[    1.686147] mmc0: SDHCI controller on 30b40000.mmc [30b40000.mmc] using ADMA
[    1.692832] hantrodec 0 : module inserted. Major = 511
[    1.709009] hantrodec 1 : module inserted. Major = 511
[    1.715564] hantroenc: HW at base <0000000038320000> with ID <0x80006200>
[    1.722486] hx280enc: module inserted. Major <510>
[    1.730493] NET: Registered PF_LLC protocol family
[    1.735810] NET: Registered PF_INET6 protocol family
[    1.743271] Segment Routing with IPv6
[    1.746983] In-situ OAM (IOAM) with IPv6
[    1.750958] NET: Registered PF_PACKET protocol family
[    1.756047] bridge: filtering via arp/ip/ip6tables is no longer available by default. Update your scripts to load br_netfilter if you need this.
[    1.769642] Bluetooth: RFCOMM TTY layer initialized
[    1.773275] mmc2: new HS400 Enhanced strobe MMC card at address 0001
[    1.774543] Bluetooth: RFCOMM socket layer initialized
[    1.782046] mmcblk2: mmc2:0001 AJTD4R 14.6 GiB
[    1.786029] Bluetooth: RFCOMM ver 1.11
[    1.792857] mmcblk2boot0: mmc2:0001 AJTD4R 4.00 MiB
[    1.794336] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[    1.800753] mmcblk2boot1: mmc2:0001 AJTD4R 4.00 MiB
[    1.804606] Bluetooth: BNEP filters: protocol multicast
[    1.804618] Bluetooth: BNEP socket layer initialized
[    1.810920] mmcblk2rpmb: mmc2:0001 AJTD4R 4.00 MiB, chardev (234:0)
[    1.814814] Bluetooth: HIDP (Human Interface Emulation) ver 1.2
[    1.814823] Bluetooth: HIDP socket layer initialized
[    1.837659] 8021q: 802.1Q VLAN Support v1.8
[    1.841875] lib80211: common routines for IEEE802.11 drivers
[    1.847541] lib80211_crypt: registered algorithm 'NULL'
[    1.847546] lib80211_crypt: registered algorithm 'WEP'
[    1.847549] lib80211_crypt: registered algorithm 'CCMP'
[    1.847553] lib80211_crypt: registered algorithm 'TKIP'
[    1.847648] 9pnet: Installing 9P2000 support
[    1.851951] tsn generic netlink module v1 init...
[    1.856750] Key type dns_resolver registered
[    1.861896] Loading compiled-in X.509 certificates
[    1.882750] gpio-6 (cam_buf): hogged as output/low
[    1.922244] gpio-38 (scl): enforced open drain please flag it properly in DT/ACPI DSDT/board file
[    1.943214] nxp-pca9450 0-0025: pca9450bc probed.
[    1.948298] i2c i2c-0: IMX I2C adapter registered
[    1.953599] gpio-146 (scl): enforced open drain please flag it properly in DT/ACPI DSDT/board file
[    1.963303] i2c 2-0021: Fixing up cyclic dependency with 32e40000.csi
[    2.055029] adv7180 2-0021: chip id 0x42 found @ 0x21 (30a40000.i2c)
[    2.061646] i2c 2-003d: Fixing up cyclic dependency with 38100000.usb
[    2.069060] pca953x 2-0020: using no AI
[    2.080530] gpio-508 (usb3_sel): hogged as output/low
[    2.086124] i2c i2c-2: IMX I2C adapter registered
[    2.091537] gpio-148 (scl): enforced open drain please flag it properly in DT/ACPI DSDT/board file
[    2.101489] i2c i2c-3: IMX I2C adapter registered
[    2.106918] imx8mq-usb-phy 381f0040.usb-phy: supply vbus not found, using dummy regulator
[    2.115412] imx8mq-usb-phy 382f0040.usb-phy: supply vbus not found, using dummy regulator
[    2.125116] pwm-backlight backlight: supply power not found, using dummy regulator
[    2.125802] imx6q-pcie 33800000.pcie: supply epdev_on not found, using dummy regulator
[    2.141065] imx6q-pcie 33800000.pcie: EXT REF_CLK is used!.
[    2.147534] imx6q-pcie 33800000.pcie: PCIe PHY PLL clock is locked.
[    2.151930] imx-dwmac 30bf0000.ethernet: IRQ eth_lpi not found
[    2.160861] imx-dwmac 30bf0000.ethernet: User ID: 0x10, Synopsys ID: 0x51
[    2.167675] imx-dwmac 30bf0000.ethernet:     DWMAC4/5
[    2.172479] imx-dwmac 30bf0000.ethernet: DMA HW capability register supported
[    2.179623] imx-dwmac 30bf0000.ethernet: RX Checksum Offload Engine supported
[    2.186769] imx-dwmac 30bf0000.ethernet: TX Checksum insertion supported
[    2.193480] imx-dwmac 30bf0000.ethernet: Wake-Up On Lan supported
[    2.199641] imx-dwmac 30bf0000.ethernet: Enable RX Mitigation via HW Watchdog Timer
[    2.207313] imx-dwmac 30bf0000.ethernet: Enabled L3L4 Flow TC (entries=8)
[    2.209343] imx6q-pcie 33800000.pcie: PCIe PLL is locked.
[    2.214110] imx-dwmac 30bf0000.ethernet: Enabled RFS Flow TC (entries=8)
[    2.219556] imx6q-pcie 33800000.pcie: iATU unroll: enabled
[    2.226226] imx-dwmac 30bf0000.ethernet: Enabling HW TC (entries=256, max_off=256)
[    2.231701] imx6q-pcie 33800000.pcie: Detected iATU regions: 4 outbound, 4 inbound
[    2.239273] imx-dwmac 30bf0000.ethernet: Using 34 bits DMA width
[    2.246847] imx6q-pcie 33800000.pcie: host bridge /soc@0/pcie@33800000 ranges:
[    2.260080] imx6q-pcie 33800000.pcie:   No bus range found for /soc@0/pcie@33800000, using [bus 00-ff]
[    2.269427] imx6q-pcie 33800000.pcie:       IO 0x001ff80000..0x001ff8ffff -> 0x0000000000
[    2.277626] imx6q-pcie 33800000.pcie:      MEM 0x0018000000..0x001fefffff -> 0x0018000000
[    2.285891] imx6q-pcie 33800000.pcie: iATU unroll: enabled
[    2.291388] imx6q-pcie 33800000.pcie: Detected iATU regions: 4 outbound, 4 inbound
[    2.546509] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
[    2.552045] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 1
[    2.560044] xhci-hcd xhci-hcd.0.auto: hcc params 0x0220fe6d hci version 0x110 quirks 0x0000002001010010
[    2.569488] xhci-hcd xhci-hcd.0.auto: irq 75, io mem 0x38200000
[    2.575541] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
[    2.581059] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 2
[    2.588732] xhci-hcd xhci-hcd.0.auto: Host supports USB 3.0 SuperSpeed
[    2.596351] hub 1-0:1.0: USB hub found
[    2.600138] hub 1-0:1.0: 1 port detected
[    2.604367] usb usb2: We don't know the algorithms for LPM for this host, disabling LPM.
[    2.613503] hub 2-0:1.0: USB hub found
[    2.617283] hub 2-0:1.0: 1 port detected
[    2.621793] imx-cpufreq-dt imx-cpufreq-dt: cpu speed grade 5 mkt segment 0 supported-hw 0x20 0x1
[    2.633232] sdhci-esdhc-imx 30b50000.mmc: Got CD GPIO
[    2.635701] mxc-mipi-csi2-sam 32e40000.csi: supply mipi-phy not found, using dummy regulator
[    2.647069] : mipi_csis_imx8mp_phy_reset, No remote pad found!
[    2.652952] mxc-mipi-csi2-sam 32e40000.csi: lanes: 1, hs_settle: 13, clk_settle: 2, wclk: 1, freq: 108000000
[    2.664192] isi-capture 32e00000.isi:cap_device: deferring 32e00000.isi:cap_device device registration
[    2.674154] mxc-isi 32e00000.isi: mxc_isi.0 registered successfully
[    2.674411] mmc1: SDHCI controller on 30b50000.mmc [30b50000.mmc] using ADMA
[    2.684603] fec-phy: supplied by fec-phy-vsel
[    2.719550] dwhdmi-imx 32fd8000.hdmi: Detected HDMI TX controller v2.13a with HDCP (samsung_dw_hdmi_phy2)
[    2.731465] dwhdmi-imx 32fd8000.hdmi: registered DesignWare HDMI I2C bus driver
[    2.744427] imx-drm display-subsystem: bound imx-lcdifv3-crtc.0 (ops lcdifv3_crtc_ops)
[    2.752426] imx-drm display-subsystem: bound imx-lcdifv3-crtc.1 (ops lcdifv3_crtc_ops)
[    2.760612] imx-drm display-subsystem: bound 32c00000.bus:ldb@32ec005c (ops imx8mp_ldb_ops)
[    2.769056] imx-drm display-subsystem: bound 32fd8000.hdmi (ops dw_hdmi_imx_ops)
[    2.777428] [drm] Initialized imx-drm 1.0.0 20120507 for display-subsystem on minor 0
[    2.921888] mmc1: host does not support reading read-only switch, assuming write-enable
[    2.961194] mmc1: new ultra high speed SDR104 SDHC card at address aaaa
[    2.968827] mmcblk1: mmc1:aaaa SE32G 29.7 GiB
[    2.976759]  mmcblk1: p1
[    3.053558] Console: switching to colour frame buffer device 100x30
[    3.076187] imx-drm display-subsystem: [drm] fb0: imx-drmdrmfb frame buffer device
[    3.087135] pps pps0: new PPS source ptp0
[    3.104469] fec 30be0000.ethernet eth1: registered PHC device 0
[    3.117329] input: gpio-keys as /devices/platform/gpio-keys/input/input1
[    3.125968] isi-m2m 32e00000.isi:m2m_device: Register m2m success for ISI.0
[    3.148775] ALSA device list:
[    3.151773]   No soundcards found.
[    3.301647] imx6q-pcie 33800000.pcie: Phy link never came up
[    3.307360] imx6q-pcie: probe of 33800000.pcie failed with error -110
[    3.325613] EXT4-fs (mmcblk1p1): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[    3.335474] VFS: Mounted root (ext4 filesystem) on device 179:97.
[    3.345915] devtmpfs: mounted
[    3.349443] Freeing unused kernel memory: 3008K
[    3.354062] Run /sbin/init as init process
[    3.358208]   with arguments:
[    3.358211]     /sbin/init
[    3.358213]   with environment:
[    3.358215]     HOME=/
[    3.358217]     TERM=linux
[    3.534876] systemd[1]: System time before build time, advancing clock.
[    3.578835] systemd[1]: systemd 250.5+ running in system mode (+PAM -AUDIT -SELINUX -APPARMOR +IMA -SMACK +SECCOMP -GCRYPT -GNUTLS -OPENSSL +ACL +BLKID -CURL -ELFUTILS -FIDO2 -IDN2 -IDN -IPTC +KMOD -LIBCRYPTSETUP +LIBFDISK -PCRE2 -PWQUALITY -P11KIT -QRENCODE -BZIP2 -LZ4 -XZ -ZLIB +ZSTD -BPF_FRAMEWORK -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=hybrid)
[    3.610466] systemd[1]: Detected architecture arm64.
[    3.655779] systemd[1]: Hostname set to <b2qt-imx8mp-var-dart>.
[    3.983386] systemd[1]: Queued start job for default target Multi-User System.
[    4.028645] systemd[1]: Created slice Slice /system/modprobe.
[    4.051800] systemd[1]: Created slice Slice /system/serial-getty.
[    4.075339] systemd[1]: Created slice User and Session Slice.
[    4.097447] systemd[1]: Started Dispatch Password Requests to Console Directory Watch.
[    4.121708] systemd[1]: Started Forward Password Requests to Wall Directory Watch.
[    4.145367] systemd[1]: Reached target Host and Network Name Lookups.
[    4.169501] systemd[1]: Reached target Path Units.
[    4.189120] systemd[1]: Reached target Remote File Systems.
[    4.213164] systemd[1]: Reached target Slice Units.
[    4.233158] systemd[1]: Reached target Swaps.
[    4.268349] systemd[1]: Listening on RPCbind Server Activation Socket.
[    4.289187] systemd[1]: Reached target RPC Port Mapper.
[    4.309761] systemd[1]: Listening on Syslog Socket.
[    4.329369] systemd[1]: Listening on initctl Compatibility Named Pipe.
[    4.353977] systemd[1]: Listening on Journal Audit Socket.
[    4.377698] systemd[1]: Listening on Journal Socket (/dev/log).
[    4.401763] systemd[1]: Listening on Journal Socket.
[    4.421648] systemd[1]: Listening on Network Service Netlink Socket.
[    4.445955] systemd[1]: Listening on udev Control Socket.
[    4.469688] systemd[1]: Listening on udev Kernel Socket.
[    4.489441] systemd[1]: Listening on User Database Manager Socket.
[    4.517263] systemd[1]: Mounting Huge Pages File System...
[    4.540943] systemd[1]: Mounting POSIX Message Queue File System...
[    4.564900] systemd[1]: Mounting Kernel Debug File System...
[    4.585494] systemd[1]: Kernel Trace File System was skipped because of a failed condition check (ConditionPathExists=/sys/kernel/tracing).
[    4.603628] systemd[1]: Mounting Temporary Directory /tmp...
[    4.629859] systemd[1]: Starting Create List of Static Device Nodes...
[    4.657027] systemd[1]: Starting Load Kernel Module configfs...
[    4.680818] systemd[1]: Starting Load Kernel Module drm...
[    4.704315] systemd[1]: Starting Load Kernel Module fuse...
[    4.718543] fuse: init (API version 7.34)
[    4.739542] systemd[1]: Starting RPC Bind...
[    4.757539] systemd[1]: File System Check on Root Device was skipped because of a failed condition check (ConditionPathIsReadWrite=!/).
[    4.774593] systemd[1]: Starting Journal Service...
[    4.799770] systemd[1]: Starting Load Kernel Modules...
[    4.818569] galcore: loading out-of-tree module taints kernel.
[    4.820736] systemd[1]: Starting Generate network units from Kernel command line...
[    4.833962] module built by  at Thu Dec 7 11:45:36 UTC 2023
[    4.835016] Galcore version 6.4.3.p4.398061
[    4.861973] systemd[1]: Starting Remount Root and Kernel File Systems...
[    4.876593] EXT4-fs (mmcblk1p1): re-mounted. Opts: (null). Quota mode: none.
[    4.892529] systemd[1]: Starting Coldplug All udev Devices...
[    4.919417] systemd[1]: Started RPC Bind.
[    4.925973] [drm] Initialized vivante 1.0.0 20170808 for 40000000.mix_gpu_ml on minor 1
[    4.945625] systemd[1]: Started Journal Service.
[    5.225851] systemd-journald[234]: Received client request to flush runtime journal.
[    5.420803] audit: type=1334 audit(1651167746.880:2): prog-id=5 op=LOAD
[    5.427579] audit: type=1334 audit(1651167746.888:3): prog-id=6 op=LOAD
[    5.822503] systemd-journald[234]: Oldest entry in /run/log/journal/59b8cd9f555c452a9b7aa61622f28ba3/system.journal is older than the configured file retention duration (1month), suggesting rotation.
[    5.849853] systemd-journald[234]: /run/log/journal/59b8cd9f555c452a9b7aa61622f28ba3/system.journal: Journal header limits reached or header out-of-date, rotating.
[    6.015697] caam-snvs 30370000.caam-snvs: violation handlers armed - init state
[    6.034113] caam 30900000.crypto: device ID = 0x0a16040100000100 (Era 9)
[    6.040941] caam 30900000.crypto: job rings = 2, qi = 0
[    6.067851] CAN device driver interface
[    6.082539] ptn5150 2-003d: No VBUS GPIO, ignoring VBUS control
[    6.094125] wm8904 0-001a: revision A
[    6.108009] rtc-ds1307 3-0068: registered as rtc0
[    6.115984] rtc-ds1307 3-0068: setting system clock to 2023-12-07T15:06:55 UTC (1701961615)
[    6.119255] imx-sdma 30bd0000.dma-controller: firmware found.
[    6.130415] imx-sdma 30bd0000.dma-controller: loaded firmware 4.5
[    6.139483] edt_ft5x06 3-0038: supply vcc not found, using dummy regulator
[    6.146660] edt_ft5x06 3-0038: supply iovcc not found, using dummy regulator
[    6.156007] edt_ft5x06 3-0038: touchscreen probe failed
[    6.171786] imx-sdma 30e10000.dma-controller: firmware found.
[    6.226917] imx8_media_dev: module is from the staging directory, the quality is unknown, you have been warned.
[    6.259630] mx8-img-md: Registered mxc_isi.0.capture as /dev/video1
[    6.280058] mx8-img-md: Registered sensor subdevice: adv7180 2-0021 (1)
[    6.293979] input: audio-hdmi HDMI Jack as /devices/platform/sound_hdmi/sound/card1/input3
[    6.308914] mx8-img-md: created link [mxc_isi.0] => [mxc_isi.0.capture]
[    6.316015] mx8-img-md: created link [mxc-mipi-csi2.0] => [mxc_isi.0]
[    6.322834] mx8-img-md: created link [adv7180 2-0021] => [mxc-mipi-csi2.0]
[    6.330233] mxc-md 32c00000.bus:camera: mxc_md_create_links
[    6.764348] SPI driver ads7846 has no spi_device_id for ti,tsc2046
[    6.770924] SPI driver ads7846 has no spi_device_id for ti,ads7843
[    6.777151] SPI driver ads7846 has no spi_device_id for ti,ads7845
[    6.780455] caam algorithms registered in /proc/crypto
[    6.783352] SPI driver ads7846 has no spi_device_id for ti,ads7873
[    6.783654] ads7846 spi1.0: supply vcc not found, using dummy regulator
[    6.789473] caam 30900000.crypto: caam pkc algorithms registered in /proc/crypto
[    6.809325] ads7846 spi1.0: touchscreen, irq 88
[    6.813094] caam 30900000.crypto: rng crypto API alg registered prng-caam
[    6.814412] input: ADS7846 Touchscreen as /devices/platform/soc@0/30800000.bus/30820000.spi/spi_master/spi1/spi1.0/input/input4
[    6.820726] caam 30900000.crypto: registering rng-caam
[    6.841232] Device caam-keygen registered
[    6.862851] random: crng init done
[    7.848541] audit: type=1334 audit(1701961617.228:4): prog-id=7 op=LOAD
[    7.855303] audit: type=1334 audit(1701961617.236:5): prog-id=8 op=LOAD
[    8.255047] audit: type=1334 audit(1701961617.636:6): prog-id=9 op=LOAD
[    8.261785] audit: type=1334 audit(1701961617.644:7): prog-id=10 op=LOAD
[    8.513708] audit: type=1334 audit(1701961617.896:8): prog-id=11 op=LOAD
[    8.520503] audit: type=1334 audit(1701961617.896:9): prog-id=12 op=LOAD
[    8.580517] mmc0: SDHCI controller on 30b40000.mmc [30b40000.mmc] using ADMA
[    8.627753] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[    8.650753] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
[    8.717258] mmc0: new ultra high speed SDR104 SDIO card at address 0001
[    8.732325] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac4339-sdio for chip BCM4339/2
[    8.751911] audit: type=1334 audit(1701961618.132:10): prog-id=13 op=LOAD
[    8.759235] audit: type=1334 audit(1701961618.140:11): prog-id=14 op=LOAD
[    8.795021] imx-dwmac 30bf0000.ethernet eth0: PHY [stmmac-0:04] driver [ADIN1300] (irq=POLL)
[    8.807356] imx-dwmac 30bf0000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-0
[    8.825036] imx-dwmac 30bf0000.ethernet eth0: No Safety Features support found
[    8.832390] imx-dwmac 30bf0000.ethernet eth0: IEEE 1588-2008 Advanced Timestamp supported
[    8.842226] imx-dwmac 30bf0000.ethernet eth0: registered PTP clock
[    8.849195] imx-dwmac 30bf0000.ethernet eth0: FPE workqueue start
[    8.855384] imx-dwmac 30bf0000.ethernet eth0: configuring for phy/rgmii link mode
[    8.863474] 8021q: adding VLAN 0 to HW filter on device eth0
[    8.947016] ADIN1300 stmmac-0:05: attached PHY driver (mii_bus:phy_addr=stmmac-0:05, irq=POLL)
[    8.984495] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac4339-sdio for chip BCM4339/2
[    8.993137] brcmfmac: brcmf_c_process_clm_blob: no clm_blob available (err=-2), device may have limited channels available
[    9.004586] brcmfmac: brcmf_c_preinit_dcmds: Firmware: BCM4339/2 wl0: Oct  7 2021 07:48:53 version 6.37.39.134 (r729170 CY)
[    9.103299] brcmfmac: brcmf_cfg80211_attach: Using regulatory domain US
[   10.000236] using random self ethernet address
[   10.004976] using random host ethernet address
[   10.012218] file system registered
[   10.145044] read descriptors
[   10.148015] read strings
[   10.164689] usb0: HOST MAC ae:11:72:2f:f3:1f
[   10.174789] usb0: MAC d6:2e:1c:ef:bd:02
[   12.959083] imx-dwmac 30bf0000.ethernet eth0: Link is Up - 1Gbps/Full - flow control off
[   12.967278] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[   17.996761] NET: Registered PF_ALG protocol family
[   48.134164] kauditd_printk_skb: 11 callbacks suppressed
[   48.134196] audit: type=1334 audit(1701961657.516:17): prog-id=0 op=UNLOAD
[   48.146510] audit: type=1334 audit(1701961657.516:18): prog-id=0 op=UNLOAD
[   80.829330] audit: type=1006 audit(1701961690.212:19): pid=671 uid=0 old-auid=4294967295 auid=0 tty=(none) old-ses=4294967295 ses=2 res=1
[   80.841766] audit: type=1300 audit(1701961690.212:19): arch=c00000b7 syscall=64 success=yes exit=1 a0=7 a1=ffffc3e916e0 a2=1 a3=ffff9ed5f920 items=0 ppid=1 pid=671 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=2 comm="sshd" exe="/usr/sbin/sshd" key=(null)
[   80.867271] audit: type=1327 audit(1701961690.212:19): proctitle=737368643A20726F6F74205B707269765D
[   82.718668] mxc-mipi-csi2.0: unsupported csi-sam command -1068476902.
[   82.742336] mxc-mipi-csi2.0: unsupported csi-sam command -1068476902.
[   83.466262] isi-capture 32e00000.isi:cap_device: mxc_isi_source_fmt_init: src:(720,240), dst:(3840,2160) Not support upscale
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
 * Copyright 2019 NXP
 * Copyright 2020-2021 Variscite Ltd.
 */

#include "imx8mp-var-som.dtsi"

/ {
	model = "Variscite VAR-SOM-MX8M-PLUS on Symphony-Board";

	chosen {
		stdout-path = &uart2;
	};

	gpio-keys {
		compatible = "gpio-keys";
		status = "okay";

		back {
			label = "Back";
			linux,code = <KEY_BACK>;
			gpios = <&pca9534 1 GPIO_ACTIVE_LOW>;
			wakeup-source;
		};

		home {
			label = "Home";
			linux,code = <KEY_HOME>;
			gpios = <&pca9534 2 GPIO_ACTIVE_LOW>;
			wakeup-source;
		};

		menu {
			label = "Menu";
			linux,code = <KEY_MENU>;
			gpios = <&pca9534 3 GPIO_ACTIVE_LOW>;
			wakeup-source;
		};
	};

	gpio-leds {
		compatible = "gpio-leds";
		status = "okay";

		heartbeat {
			label = "Heartbeat";
			linux,default-trigger = "heartbeat";
			gpios = <&pca9534 0 GPIO_ACTIVE_HIGH>;
		};
	};

	reg_usdhc2_vmmc: regulator-usdhc2-vmmc {
		compatible = "regulator-fixed";
		regulator-name = "VSD_3V3";
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
		gpio = <&gpio4 22 GPIO_ACTIVE_HIGH>;
		enable-active-high;
		startup-delay-us = <100>;
		off-on-delay-us = <12000>;
	};

	reg_usdhc2_vqmmc: regulator-usdhc2-vqmmc {
		compatible = "regulator-gpio";
		regulator-name = "VSD_VSEL";
		regulator-min-microvolt = <1800000>;
		regulator-max-microvolt = <3300000>;
		gpio = <&gpio2 12 GPIO_ACTIVE_HIGH>;
		gpios-states = <1>;
		states = <3300000 0
			  1800000 1>;
	};

	reg_fec_phy_vsel: regulator-fec-phy-vsel {
		compatible = "regulator-fixed";
		regulator-name = "fec-phy-vsel";
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
		regulator-always-on;
		gpio = <&pca9534 6 GPIO_ACTIVE_HIGH>;
		enable-active-high;
	};

	reg_fec_phy: regulator-fec-phy {
		compatible = "regulator-fixed";
		regulator-name = "fec-phy";
		vin-supply = <&reg_fec_phy_vsel>;
		regulator-min-microvolt = <1800000>;
		regulator-max-microvolt = <1800000>;
		regulator-enable-ramp-delay = <20000>;
		gpio = <&pca9534 7 GPIO_ACTIVE_HIGH>;
		enable-active-high;
		regulator-always-on;
	};

	backlight: backlight {
		compatible = "pwm-backlight";
		pwms = <&pwm1 0 1000000>;
		status = "okay";

		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
				     10 11 12 13 14 15 16 17 18 19
				     20 21 22 23 24 25 26 27 28 29
				     30 31 32 33 34 35 36 37 38 39
				     40 41 42 43 44 45 46 47 48 49
				     50 51 52 53 54 55 56 57 58 59
				     60 61 62 63 64 65 66 67 68 69
				     70 71 72 73 74 75 76 77 78 79
				     80 81 82 83 84 85 86 87 88 89
				     90 91 92 93 94 95 96 97 98 99
				    100>;
		default-brightness-level = <80>;
	};

	panel {
		compatible = "sgd,gktw70sdae4se", "panel-lvds";
		backlight = <&backlight>;
		width-mm = <153>;
		height-mm = <87>;
		label = "gktw70sdae4se";
		data-mapping = "jeida-24";
		status = "okay";

		panel-timing {
			clock-frequency = <33000000>;
			hactive = <800>;
			vactive = <480>;
			hback-porch = <40>;
			hfront-porch = <40>;
			vback-porch = <29>;
			vfront-porch = <13>;
			hsync-len = <48>;
			vsync-len = <3>;
			hsync-active = <0>;
			vsync-active = <0>;
			de-active = <1>;
		};

		port {
			panel_in: endpoint {
				remote-endpoint = <&lvds_out>;
			};
		};
	};

	sound_hdmi: sound_hdmi {
		compatible = "fsl,imx-audio-hdmi";
		model = "audio-hdmi";
		audio-cpu = <&aud2htx>;
		hdmi-out;
		constraint-rate = <44100>,
				<88200>,
				<176400>,
				<32000>,
				<48000>,
				<96000>,
				<192000>;
		status = "okay";
	};
};

&aud2htx {
	status = "okay";
};

&pwm1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pwm1>;
	status = "okay";
};

&eqos {
	mdio {
		ethphy1: ethernet-phy@5 {
			compatible = "ethernet-phy-ieee802.3-c22";
			reg = <5>;
			at803x,eee-disabled;
			eee-broken-1000t;
			reset-gpios = <&pca9534 5 GPIO_ACTIVE_LOW>;
			reset-assert-us = <10000>;
			reset-deassert-us = <20000>;
			vddio-supply = <&vddio1>;

			vddio1: vddio-regulator {
				regulator-min-microvolt = <1800000>;
				regulator-max-microvolt = <1800000>;
			};
		};
	};
};

&fec {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_fec>;
	phy-mode = "rgmii";
	phy-handle = <&ethphy1>;
	phy-supply = <&reg_fec_phy>;
	status = "okay";
};

&flexspi {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_flexspi0>;
	status = "disabled";
};
/*
&i2c1 {
    clock-frequency = <100000>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_i2c1>;
    scl-gpios = <&gpio5 14 GPIO_ACTIVE_HIGH>;
    sda-gpios = <&gpio5 15 GPIO_ACTIVE_HIGH>;
    status = "okay";
};*/


&mipi_csi_0 {
	#address-cells = <1>;
	#size-cells = <0>;
	status = "okay";
	bus-width = <1>;

	clock-frequency = <108000000>;

	port@0 {
		reg = <0>;

		mipi_csi0_ep: endpoint {
			csis-hs-settle = <13>;
			csis-clk-settle = <2>;
			csis-wclk;
			data-lanes = <1>;
			remote-endpoint = <&adv728xm_mipi_0_ep>;
		};
	};
};

&i2c3 {
	clock-frequency = <400000>;
	pinctrl-names = "default", "gpio";
	pinctrl-0 = <&pinctrl_i2c3>;
	pinctrl-1 = <&pinctrl_i2c3_gpio>;
	scl-gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>;
	sda-gpios = <&gpio5 19 GPIO_ACTIVE_HIGH>;
	status = "okay";
	
	adv7280-m@21 {	
 	    status = "okay";
	    compatible = "adi,adv7280-m";
	    reg = <0x21>;
	    reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
	    powerdown-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
	    interrupt-parent = <&gpio4>;
	    interrupts = <3 IRQ_TYPE_LEVEL_LOW>;

	    port {
		adv728xm_mipi_0_ep: endpoint {
		    remote-endpoint = <&mipi_csi0_ep>;
	        };
	    };
        }; 

	/* USB Type-C Controller */
	typec@3d {
		compatible = "nxp,ptn5150";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_extcon>;
		reg = <0x3d>;
		interrupt-parent = <&gpio1>;
		interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
		irq-is-id-quirk;
		status ="okay";

		port {
			typec_dr_sw: endpoint {
				remote-endpoint = <&usb3_drd_sw>;
			};
		};
	};

	/* GPIO expander */
	pca9534: gpio@20 {
		compatible = "nxp,pca9534";
		reg = <0x20>;
		gpio-controller;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_pca9534>;
		interrupt-parent = <&gpio1>;
		interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
		#gpio-cells = <2>;
		wakeup-source;
		status = "okay";

		usb3_sel_hog {
			gpio-hog;
			gpios = <4 0>;
			output-low;
			line-name = "usb3_sel";
		};
	};

/*	ov5640_mipi0: ov5640_mipi@3c {
		compatible = "ovti,ov5640";
		reg = <0x3c>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_csi0>;
		clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO2>;
		clock-names = "xclk";*/
/* Disabled CLKO2, since DART-MX8MP camera expansion board uses
 * its own oscillator. Enable CLK02 if your desing requres it
 */
/*#if 0
		assigned-clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO2>;
		assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
#endif
		assigned-clock-rates = <24000000>;
		csi_id = <0>;
		powerdown-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
		reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
		mclk = <24000000>;
		mclk_source = <0>;
		mipi_csi;
		status = "okay";

		port {
			ov5640_mipi_0_ep: endpoint {
				remote-endpoint = <&mipi_csi0_ep>;
				data-lanes = <1 2>;
				clock-lanes = <0>;
			};
		};
	};*/
};

&i2c4 {
	clock-frequency = <400000>;
	pinctrl-names = "default", "gpio";
	pinctrl-0 = <&pinctrl_i2c4>;
	pinctrl-1 = <&pinctrl_i2c4_gpio>;
	scl-gpios = <&gpio5 20 GPIO_ACTIVE_HIGH>;
	sda-gpios = <&gpio5 21 GPIO_ACTIVE_HIGH>;
	status = "okay";

	/* DS1337 RTC module */
	rtc@68 {
		compatible = "dallas,ds1337";
		reg = <0x68>;
		status = "okay";
	};

	/* Capacitive touch controller */
	ft5x06_ts: ft5x06_ts@38 {
		compatible = "edt,edt-ft5206";
		reg = <0x38>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_captouch>;
		interrupt-parent = <&gpio5>;
		interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
		touchscreen-size-x = <800>;
		touchscreen-size-y = <480>;
		touchscreen-inverted-x;
		touchscreen-inverted-y;
		wakeup-source;
		status = "okay";
	};
};

&flexcan2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_flexcan2>;
	status = "okay";
};

&irqsteer_hdmi {
	status = "okay";
};

&hdmi_blk_ctrl {
	status = "okay";
};

&hdmi_pavi {
	status = "okay";
};

&hdmi {
	status = "okay";
};

&hdmiphy {
	status = "okay";
};

/* MIPI-DSI */
&lcdif1 {
	status = "disabled";
};

/* LVDS */
&lcdif2 {
	status = "okay";
};

/* HDMI */
&lcdif3 {
	status = "okay";
	thres-low  = <1 2>;	/* (FIFO * 1 / 2) */
	thres-high = <3 4>;	/* (FIFO * 3 / 4) */
};

&ldb {
	status = "okay";

	lvds-channel@0 {
		fsl,data-mapping = "jeida";
		fsl,data-width = <24>;
		status = "okay";

		port@1 {
			reg = <1>;

			lvds_out: endpoint {
				remote-endpoint = <&panel_in>;
			};
		};
	};
};

&ldb_phy {
	status = "okay";
};

&mipi_dsi {
	status = "disabled";
};

&pcie {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pcie>;
	reset-gpio = <&gpio4 21 GPIO_ACTIVE_LOW>;
	ext_osc = <1>;
	clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
		 <&clk IMX8MP_CLK_PCIE_AUX>,
		 <&clk IMX8MP_CLK_HSIO_AXI>,
		 <&clk IMX8MP_CLK_PCIE_ROOT>;
	clock-names = "pcie", "pcie_aux", "pcie_phy", "pcie_bus";
	assigned-clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
			  <&clk IMX8MP_CLK_PCIE_AUX>;
	assigned-clock-rates = <500000000>, <10000000>;
	assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_500M>,
				 <&clk IMX8MP_SYS_PLL2_50M>;
	l1ss-disabled;
	status = "okay";
};

&pcie_ep {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pcie>;
	ext_osc = <1>;
	clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
		 <&clk IMX8MP_CLK_PCIE_AUX>,
		 <&clk IMX8MP_CLK_HSIO_AXI>,
		 <&clk IMX8MP_CLK_PCIE_ROOT>;
	clock-names = "pcie", "pcie_aux", "pcie_phy", "pcie_bus";
	assigned-clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
			  <&clk IMX8MP_CLK_PCIE_AUX>;
	assigned-clock-rates = <500000000>, <10000000>;
	assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_500M>,
				 <&clk IMX8MP_SYS_PLL2_50M>;
	status = "disabled";
};

&pcie_phy {
	ext_osc = <1>;
	status = "okay";
};

/* Header */
&uart1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart1>;
	status = "okay";
};

/* Console */
&uart2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart2>;
	status = "okay";
};

/* Header */
&uart4 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart4>;
	status = "okay";
};

&usb3_phy0 {
	fsl,phy-tx-vref-tune = <0xe>;
	fsl,phy-tx-preemp-amp-tune = <3>;
	fsl,phy-tx-vboost-level = <5>;
	fsl,phy-comp-dis-tune = <7>;
	fsl,pcs-tx-deemph-3p5db = <0x21>;
	fsl,phy-pcs-tx-swing-full = <0x7f>;
	status = "okay";
};

&usb3_0 {
	status = "okay";
};

&usb_dwc3_0 {
	dr_mode = "otg";
	hnp-disable;
	srp-disable;
	adp-disable;
	usb-role-switch;
	role-switch-default-mode = "none";
	snps,dis-u1-entry-quirk;
	snps,dis-u2-entry-quirk;
	status = "okay";

	port {
		usb3_drd_sw: endpoint {
			remote-endpoint = <&typec_dr_sw>;
		};
	};
};

&usb3_phy1 {
	fsl,phy-tx-preemp-amp-tune = <3>;
	fsl,phy-tx-vref-tune = <0xb>;
	status = "okay";
};

&usb3_1 {
	status = "okay";
};

&usb_dwc3_1 {
	dr_mode = "host";
	status = "okay";
};

&usdhc2 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
	cd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
	vmmc-supply = <&reg_usdhc2_vmmc>;
	vqmmc-supply = <&reg_usdhc2_vqmmc>;
	bus-width = <4>;
	status = "okay";
};
/*
&mipi_csi_0 {
	#address-cells = <1>;
	#size-cells = <0>;
	status = "okay";

	port@0 {
		reg = <0>;
		mipi_csi0_ep: endpoint {
			remote-endpoint = <&ov5640_mipi_0_ep>;
			data-lanes = <2>;
			csis-hs-settle = <13>;
			csis-clk-settle = <2>;
			csis-wclk;
		};
	};
};*/

&mipi_csi_1 {
	status = "disabled";
};

&cameradev {
	status = "okay";
};

&isi_0 {
	status = "okay";

	cap_device {
		status = "okay";
	};

	m2m_device {
		status = "okay";
	};
};

&isi_1 {
	status = "disabled";
};

&ecspi2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_ecspi2>;
	cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
	status = "okay";

	spidev@0 {
		compatible = "var,spidev";
		reg = <0>;
		spi-max-frequency = <12000000>;
		status = "okay";
	};
};

&gpio1 {
	cam_buf_hog {
		gpio-hog;
		gpios = <6 0>;
		output-low;
		line-name = "cam_buf";
	};
};

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog>;

	pinctrl_hog: hoggrp {
		fsl,pins = <
			MX8MP_IOMUXC_HDMI_DDC_SCL__HDMIMIX_HDMI_SCL			0x400001c2
			MX8MP_IOMUXC_HDMI_DDC_SDA__HDMIMIX_HDMI_SDA			0x400001c2
			MX8MP_IOMUXC_HDMI_HPD__HDMIMIX_HDMI_HPD				0x40000010
			MX8MP_IOMUXC_HDMI_CEC__HDMIMIX_HDMI_CEC				0x40000010
		>;
	};

	pinctrl_pwm1: pwm1grp {
		fsl,pins = <
			MX8MP_IOMUXC_SPDIF_EXT_CLK__PWM1_OUT				0x116
		>;
	};

	pinctrl_fec: fecgrp {
		fsl,pins = <
			MX8MP_IOMUXC_SAI1_RXD4__ENET1_RGMII_RD0				0x90
			MX8MP_IOMUXC_SAI1_RXD5__ENET1_RGMII_RD1				0x90
			MX8MP_IOMUXC_SAI1_RXD6__ENET1_RGMII_RD2				0x90
			MX8MP_IOMUXC_SAI1_RXD7__ENET1_RGMII_RD3				0x90
			MX8MP_IOMUXC_SAI1_TXC__ENET1_RGMII_RXC				0x90
			MX8MP_IOMUXC_SAI1_TXFS__ENET1_RGMII_RX_CTL			0x90
			MX8MP_IOMUXC_SAI1_TXD0__ENET1_RGMII_TD0				0x00
			MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1				0x00
			MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2				0x00
			MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3				0x00
			MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL			0x00
			MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC				0x00
		>;
	};

	pinctrl_flexspi0: flexspi0grp {
		fsl,pins = <
			MX8MP_IOMUXC_NAND_ALE__FLEXSPI_A_SCLK				0x1c2
			MX8MP_IOMUXC_NAND_CE0_B__FLEXSPI_A_SS0_B			0x82
			MX8MP_IOMUXC_NAND_DATA00__FLEXSPI_A_DATA00			0x82
			MX8MP_IOMUXC_NAND_DATA01__FLEXSPI_A_DATA01			0x82
			MX8MP_IOMUXC_NAND_DATA02__FLEXSPI_A_DATA02			0x82
			MX8MP_IOMUXC_NAND_DATA03__FLEXSPI_A_DATA03			0x82
		>;
	};

	pinctrl_i2c3: i2c3grp {
		fsl,pins = <
			MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL					0x400001c2
			MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA					0x400001c2
		>;
	};

	pinctrl_i2c4: i2c4grp {
		fsl,pins = <
			MX8MP_IOMUXC_I2C4_SCL__I2C4_SCL					0x400001c2
			MX8MP_IOMUXC_I2C4_SDA__I2C4_SDA					0x400001c2
		>;
	};

	pinctrl_i2c3_gpio: i2c3gpiogrp {
		fsl,pins = <
			MX8MP_IOMUXC_I2C3_SCL__GPIO5_IO18				0x1c2
			MX8MP_IOMUXC_I2C3_SDA__GPIO5_IO19				0x1c2
		>;
	};

	pinctrl_i2c4_gpio: i2c4gpiogrp {
		fsl,pins = <
			MX8MP_IOMUXC_I2C4_SCL__GPIO5_IO20				0x1c2
			MX8MP_IOMUXC_I2C4_SDA__GPIO5_IO21				0x1c2
		>;
	};

	pinctrl_uart1: uart1grp {
		fsl,pins = <
			MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX				0x40
			MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX				0x40
		>;
	};

	pinctrl_uart2: uart2grp {
		fsl,pins = <
			MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX				0x40
			MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX				0x40
		>;
	};

	pinctrl_uart3: uart3grp {
		fsl,pins = <
			MX8MP_IOMUXC_ECSPI1_SCLK__UART3_DCE_RX				0x140
			MX8MP_IOMUXC_ECSPI1_MOSI__UART3_DCE_TX				0x140
			MX8MP_IOMUXC_ECSPI1_MISO__UART3_DCE_CTS				0x140
			MX8MP_IOMUXC_ECSPI1_SS0__UART3_DCE_RTS				0x140
		>;
	};

	pinctrl_uart4: uart4grp {
		fsl,pins = <
			MX8MP_IOMUXC_UART4_RXD__UART4_DCE_RX				0x40
			MX8MP_IOMUXC_UART4_TXD__UART4_DCE_TX				0x40
		>;
	};

	pinctrl_usdhc2_gpio: usdhc2grp-gpio {
		fsl,pins = <
			MX8MP_IOMUXC_GPIO1_IO14__GPIO1_IO14 				0x1c4
			MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22				0x10
			MX8MP_IOMUXC_SD2_CD_B__GPIO2_IO12				0xc0
		>;
	};

	pinctrl_usdhc2: usdhc2grp {
		fsl,pins = <
			MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK				0x190
			MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD				0x1d0
			MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0				0x1d0
			MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1				0x1d0
			MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2				0x1d0
			MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3				0x1d0
		>;
	};

	pinctrl_usdhc2_100mhz: usdhc2grp-100mhz {
		fsl,pins = <
			MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK				0x194
			MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD				0x1d4
			MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0				0x1d4
			MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1				0x1d4
			MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2				0x1d4
			MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3				0x1d4
		>;
	};

	pinctrl_usdhc2_200mhz: usdhc2grp-200mhz {
		fsl,pins = <
			MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK				0x196
			MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD				0x1d6
			MX8MP_IOMUXC_SD2_DATA0__USDHC2_DATA0				0x1d6
			MX8MP_IOMUXC_SD2_DATA1__USDHC2_DATA1				0x1d6
			MX8MP_IOMUXC_SD2_DATA2__USDHC2_DATA2				0x1d6
			MX8MP_IOMUXC_SD2_DATA3__USDHC2_DATA3				0x1d6
		>;
	};

	pinctrl_ecspi2: ecspi12grp {
		fsl,pins = <
			MX8MP_IOMUXC_ECSPI2_SCLK__ECSPI2_SCLK				0x12
			MX8MP_IOMUXC_ECSPI2_MOSI__ECSPI2_MOSI				0x12
			MX8MP_IOMUXC_ECSPI2_MISO__ECSPI2_MISO 				0x12
			MX8MP_IOMUXC_ECSPI2_SS0__GPIO5_IO13				0x12
		>;
	};

	pinctrl_captouch: captouchgrp {
		fsl,pins = <
			MX8MP_IOMUXC_SPDIF_TX__GPIO5_IO03 				0x16
		>;
	};

	pinctrl_extcon: extcongrp {
		fsl,pins = <
			MX8MP_IOMUXC_GPIO1_IO05__GPIO1_IO05				0x10
		>;
	};

	pinctrl_flexcan2: flexcan2grp {
		fsl,pins = <
			MX8MP_IOMUXC_UART3_RXD__CAN2_TX					0x154
			MX8MP_IOMUXC_UART3_TXD__CAN2_RX					0x154
		>;
	};

	pinctrl_pcie: pciegrp {
		fsl,pins = <
			MX8MP_IOMUXC_SAI2_RXFS__GPIO4_IO21				0x40
		>;
	};

	pinctrl_csi0: csi0grp {
		fsl,pins = <
			MX8MP_IOMUXC_GPIO1_IO00__GPIO1_IO00				0x10
			MX8MP_IOMUXC_GPIO1_IO08__GPIO1_IO08				0x10
			>;
	};

	pinctrl_csi1: csi1grp {
		fsl,pins = <
			MX8MP_IOMUXC_SAI1_RXD7__GPIO4_IO09				0x10
			MX8MP_IOMUXC_SAI1_TXD0__GPIO4_IO12				0x10
			>;
	};

	pinctrl_pca9534: pca9534grp {
		fsl,pins = <
			MX8MP_IOMUXC_GPIO1_IO15__GPIO1_IO15				0xc0
		>;
	};
};
// adv7180.c
// SPDX-License-Identifier: GPL-2.0
/*
 * adv7180.c Analog Devices ADV7180 video decoder driver
 * Copyright (c) 2009 Intel Corporation
 * Copyright (C) 2013 Cogent Embedded, Inc.
 * Copyright (C) 2013 Renesas Solutions Corp.
 */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/gpio/consumer.h>
#include <linux/videodev2.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
#include <linux/mutex.h>
#include <linux/delay.h>

#define ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM		0x0
#define ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM_PED		0x1
#define ADV7180_STD_AD_PAL_N_NTSC_J_SECAM		0x2
#define ADV7180_STD_AD_PAL_N_NTSC_M_SECAM		0x3
#define ADV7180_STD_NTSC_J				0x4
#define ADV7180_STD_NTSC_M				0x5
#define ADV7180_STD_PAL60				0x6
#define ADV7180_STD_NTSC_443				0x7
#define ADV7180_STD_PAL_BG				0x8
#define ADV7180_STD_PAL_N				0x9
#define ADV7180_STD_PAL_M				0xa
#define ADV7180_STD_PAL_M_PED				0xb
#define ADV7180_STD_PAL_COMB_N				0xc
#define ADV7180_STD_PAL_COMB_N_PED			0xd
#define ADV7180_STD_PAL_SECAM				0xe
#define ADV7180_STD_PAL_SECAM_PED			0xf

#define ADV7180_REG_INPUT_CONTROL			0x0000
#define ADV7180_INPUT_CONTROL_INSEL_MASK		0x0f

#define ADV7182_REG_INPUT_VIDSEL			0x0002

#define ADV7180_REG_OUTPUT_CONTROL			0x0003
#define ADV7180_REG_EXTENDED_OUTPUT_CONTROL		0x0004
#define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS		0xC5

#define ADV7180_REG_AUTODETECT_ENABLE			0x0007
#define ADV7180_AUTODETECT_DEFAULT			0x7f
/* Contrast */
#define ADV7180_REG_CON		0x0008	/*Unsigned */
#define ADV7180_CON_MIN		0
#define ADV7180_CON_DEF		128
#define ADV7180_CON_MAX		255
/* Brightness*/
#define ADV7180_REG_BRI		0x000a	/*Signed */
#define ADV7180_BRI_MIN		-128
#define ADV7180_BRI_DEF		0
#define ADV7180_BRI_MAX		127
/* Hue */
#define ADV7180_REG_HUE		0x000b	/*Signed, inverted */
#define ADV7180_HUE_MIN		-127
#define ADV7180_HUE_DEF		0
#define ADV7180_HUE_MAX		128

#define ADV7180_REG_CTRL		0x000e
#define ADV7180_CTRL_IRQ_SPACE		0x20

#define ADV7180_REG_PWR_MAN		0x0f
#define ADV7180_PWR_MAN_ON		0x04
#define ADV7180_PWR_MAN_OFF		0x24
#define ADV7180_PWR_MAN_RES		0x80

#define ADV7180_REG_STATUS1		0x0010
#define ADV7180_STATUS1_IN_LOCK		0x01
#define ADV7180_STATUS1_AUTOD_MASK	0x70
#define ADV7180_STATUS1_AUTOD_NTSM_M_J	0x00
#define ADV7180_STATUS1_AUTOD_NTSC_4_43 0x10
#define ADV7180_STATUS1_AUTOD_PAL_M	0x20
#define ADV7180_STATUS1_AUTOD_PAL_60	0x30
#define ADV7180_STATUS1_AUTOD_PAL_B_G	0x40
#define ADV7180_STATUS1_AUTOD_SECAM	0x50
#define ADV7180_STATUS1_AUTOD_PAL_COMB	0x60
#define ADV7180_STATUS1_AUTOD_SECAM_525	0x70

#define ADV7180_REG_IDENT 0x0011
#define ADV7180_ID_7180 0x18

#define ADV7180_REG_STATUS3		0x0013
#define ADV7180_REG_ANALOG_CLAMP_CTL	0x0014
#define ADV7180_REG_SHAP_FILTER_CTL_1	0x0017
#define ADV7180_REG_CTRL_2		0x001d
#define ADV7180_REG_VSYNC_FIELD_CTL_1	0x0031
#define ADV7180_VSYNC_FIELD_CTL_1_NEWAV 0x12
#define ADV7180_REG_MANUAL_WIN_CTL_1	0x003d
#define ADV7180_REG_MANUAL_WIN_CTL_2	0x003e
#define ADV7180_REG_MANUAL_WIN_CTL_3	0x003f
#define ADV7180_REG_LOCK_CNT		0x0051
#define ADV7180_REG_CVBS_TRIM		0x0052
#define ADV7180_REG_CLAMP_ADJ		0x005a
#define ADV7180_REG_RES_CIR		0x005f
#define ADV7180_REG_DIFF_MODE		0x0060

#define ADV7180_REG_ICONF1		0x2040
#define ADV7180_ICONF1_ACTIVE_LOW	0x01
#define ADV7180_ICONF1_PSYNC_ONLY	0x10
#define ADV7180_ICONF1_ACTIVE_TO_CLR	0xC0
/* Saturation */
#define ADV7180_REG_SD_SAT_CB	0x00e3	/*Unsigned */
#define ADV7180_REG_SD_SAT_CR	0x00e4	/*Unsigned */
#define ADV7180_SAT_MIN		0
#define ADV7180_SAT_DEF		128
#define ADV7180_SAT_MAX		255

#define ADV7180_IRQ1_LOCK	0x01
#define ADV7180_IRQ1_UNLOCK	0x02
#define ADV7180_REG_ISR1	0x2042
#define ADV7180_REG_ICR1	0x2043
#define ADV7180_REG_IMR1	0x2044
#define ADV7180_REG_IMR2	0x2048
#define ADV7180_IRQ3_AD_CHANGE	0x08
#define ADV7180_REG_ISR3	0x204A
#define ADV7180_REG_ICR3	0x204B
#define ADV7180_REG_IMR3	0x204C
#define ADV7180_REG_IMR4	0x2050

#define ADV7180_REG_NTSC_V_BIT_END	0x00E6
#define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND	0x4F

#define ADV7180_REG_VPP_SLAVE_ADDR	0xFD
#define ADV7180_REG_CSI_SLAVE_ADDR	0xFE

#define ADV7180_REG_ACE_CTRL1		0x4080
#define ADV7180_REG_ACE_CTRL5		0x4084
#define ADV7180_REG_FLCONTROL		0x40e0
#define ADV7180_FLCONTROL_FL_ENABLE 0x1

#define ADV7180_REG_RST_CLAMP	0x809c
#define ADV7180_REG_AGC_ADJ1	0x80b6
#define ADV7180_REG_AGC_ADJ2	0x80c0

#define ADV7180_CSI_REG_PWRDN	0x00
#define ADV7180_CSI_PWRDN	0x80

#define ADV7180_INPUT_CVBS_AIN1 0x00
#define ADV7180_INPUT_CVBS_AIN2 0x01
#define ADV7180_INPUT_CVBS_AIN3 0x02
#define ADV7180_INPUT_CVBS_AIN4 0x03
#define ADV7180_INPUT_CVBS_AIN5 0x04
#define ADV7180_INPUT_CVBS_AIN6 0x05
#define ADV7180_INPUT_SVIDEO_AIN1_AIN2 0x06
#define ADV7180_INPUT_SVIDEO_AIN3_AIN4 0x07
#define ADV7180_INPUT_SVIDEO_AIN5_AIN6 0x08
#define ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3 0x09
#define ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0a

#define ADV7182_INPUT_CVBS_AIN1 0x00
#define ADV7182_INPUT_CVBS_AIN2 0x01
#define ADV7182_INPUT_CVBS_AIN3 0x02
#define ADV7182_INPUT_CVBS_AIN4 0x03
#define ADV7182_INPUT_CVBS_AIN5 0x04
#define ADV7182_INPUT_CVBS_AIN6 0x05
#define ADV7182_INPUT_CVBS_AIN7 0x06
#define ADV7182_INPUT_CVBS_AIN8 0x07
#define ADV7182_INPUT_SVIDEO_AIN1_AIN2 0x08
#define ADV7182_INPUT_SVIDEO_AIN3_AIN4 0x09
#define ADV7182_INPUT_SVIDEO_AIN5_AIN6 0x0a
#define ADV7182_INPUT_SVIDEO_AIN7_AIN8 0x0b
#define ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3 0x0c
#define ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6 0x0d
#define ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2 0x0e
#define ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4 0x0f
#define ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6 0x10
#define ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8 0x11

#define ADV7180_DEFAULT_CSI_I2C_ADDR 0x44
#define ADV7180_DEFAULT_VPP_I2C_ADDR 0x42

#define V4L2_CID_ADV_FAST_SWITCH	(V4L2_CID_USER_ADV7180_BASE + 0x00)

/* Initial number of frames to skip to avoid possible garbage */
#define ADV7180_NUM_OF_SKIP_FRAMES       2

struct adv7180_state;

#define ADV7180_FLAG_RESET_POWERED	BIT(0)
#define ADV7180_FLAG_V2			BIT(1)
#define ADV7180_FLAG_MIPI_CSI2		BIT(2)
#define ADV7180_FLAG_I2P		BIT(3)

struct adv7180_chip_info {
	unsigned int flags;
	unsigned int valid_input_mask;
	int (*set_std)(struct adv7180_state *st, unsigned int std);
	int (*select_input)(struct adv7180_state *st, unsigned int input);
	int (*init)(struct adv7180_state *state);
};

struct adv7180_state {
	struct v4l2_ctrl_handler ctrl_hdl;
	struct v4l2_subdev	sd;
	struct media_pad	pad;
	struct mutex		mutex; /* mutual excl. when accessing chip */
	int			irq;
	struct gpio_desc	*pwdn_gpio;
	struct gpio_desc	*rst_gpio;
	v4l2_std_id		curr_norm;
	bool			powered;
	bool			streaming;
	u8			input;

	struct i2c_client	*client;
	unsigned int		register_page;
	struct i2c_client	*csi_client;
	struct i2c_client	*vpp_client;
	const struct adv7180_chip_info *chip_info;
	enum v4l2_field		field;
	bool			force_bt656_4;
};
#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler,		\
					    struct adv7180_state,	\
					    ctrl_hdl)->sd)

static int adv7180_select_page(struct adv7180_state *state, unsigned int page)
{
	if (state->register_page != page) {
		i2c_smbus_write_byte_data(state->client, ADV7180_REG_CTRL,
			page);
		state->register_page = page;
	}

	return 0;
}

static int adv7180_write(struct adv7180_state *state, unsigned int reg,
	unsigned int value)
{
	lockdep_assert_held(&state->mutex);
	adv7180_select_page(state, reg >> 8);
	return i2c_smbus_write_byte_data(state->client, reg & 0xff, value);
}

static int adv7180_read(struct adv7180_state *state, unsigned int reg)
{
	lockdep_assert_held(&state->mutex);
	adv7180_select_page(state, reg >> 8);
	return i2c_smbus_read_byte_data(state->client, reg & 0xff);
}

static int adv7180_csi_write(struct adv7180_state *state, unsigned int reg,
	unsigned int value)
{
	return i2c_smbus_write_byte_data(state->csi_client, reg, value);
}

static int adv7180_set_video_standard(struct adv7180_state *state,
	unsigned int std)
{
	return state->chip_info->set_std(state, std);
}

static int adv7180_vpp_write(struct adv7180_state *state, unsigned int reg,
	unsigned int value)
{
	return i2c_smbus_write_byte_data(state->vpp_client, reg, value);
}

static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
{
	/* in case V4L2_IN_ST_NO_SIGNAL */
	if (!(status1 & ADV7180_STATUS1_IN_LOCK))
		return V4L2_STD_UNKNOWN;

	switch (status1 & ADV7180_STATUS1_AUTOD_MASK) {
	case ADV7180_STATUS1_AUTOD_NTSM_M_J:
		return V4L2_STD_NTSC;
	case ADV7180_STATUS1_AUTOD_NTSC_4_43:
		return V4L2_STD_NTSC_443;
	case ADV7180_STATUS1_AUTOD_PAL_M:
		return V4L2_STD_PAL_M;
	case ADV7180_STATUS1_AUTOD_PAL_60:
		return V4L2_STD_PAL_60;
	case ADV7180_STATUS1_AUTOD_PAL_B_G:
		return V4L2_STD_PAL;
	case ADV7180_STATUS1_AUTOD_SECAM:
		return V4L2_STD_SECAM;
	case ADV7180_STATUS1_AUTOD_PAL_COMB:
		return V4L2_STD_PAL_Nc | V4L2_STD_PAL_N;
	case ADV7180_STATUS1_AUTOD_SECAM_525:
		return V4L2_STD_SECAM;
	default:
		return V4L2_STD_UNKNOWN;
	}
}

static int v4l2_std_to_adv7180(v4l2_std_id std)
{
	if (std == V4L2_STD_PAL_60)
		return ADV7180_STD_PAL60;
	if (std == V4L2_STD_NTSC_443)
		return ADV7180_STD_NTSC_443;
	if (std == V4L2_STD_PAL_N)
		return ADV7180_STD_PAL_N;
	if (std == V4L2_STD_PAL_M)
		return ADV7180_STD_PAL_M;
	if (std == V4L2_STD_PAL_Nc)
		return ADV7180_STD_PAL_COMB_N;

	if (std & V4L2_STD_PAL)
		return ADV7180_STD_PAL_BG;
	if (std & V4L2_STD_NTSC)
		return ADV7180_STD_NTSC_M;
	if (std & V4L2_STD_SECAM)
		return ADV7180_STD_PAL_SECAM;

	return -EINVAL;
}

static u32 adv7180_status_to_v4l2(u8 status1)
{
	if (!(status1 & ADV7180_STATUS1_IN_LOCK))
		return V4L2_IN_ST_NO_SIGNAL;

	return 0;
}

static int __adv7180_status(struct adv7180_state *state, u32 *status,
			    v4l2_std_id *std)
{
	int status1 = adv7180_read(state, ADV7180_REG_STATUS1);

	if (status1 < 0)
		return status1;

	if (status)
		*status = adv7180_status_to_v4l2(status1);
	if (std)
		*std = adv7180_std_to_v4l2(status1);

	return 0;
}

static inline struct adv7180_state *to_state(struct v4l2_subdev *sd)
{
	return container_of(sd, struct adv7180_state, sd);
}

static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
{
	struct adv7180_state *state = to_state(sd);
	int err = mutex_lock_interruptible(&state->mutex);
	if (err)
		return err;

	if (state->streaming) {
		err = -EBUSY;
		goto unlock;
	}

	err = adv7180_set_video_standard(state,
			ADV7180_STD_AD_PAL_BG_NTSC_J_SECAM);
	if (err)
		goto unlock;

	msleep(100);
	__adv7180_status(state, NULL, std);

	err = v4l2_std_to_adv7180(state->curr_norm);
	if (err < 0)
		goto unlock;

	err = adv7180_set_video_standard(state, err);

unlock:
	mutex_unlock(&state->mutex);
	return err;
}

static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input,
			     u32 output, u32 config)
{
	struct adv7180_state *state = to_state(sd);
	int ret = mutex_lock_interruptible(&state->mutex);

	if (ret)
		return ret;

	if (input > 31 || !(BIT(input) & state->chip_info->valid_input_mask)) {
		ret = -EINVAL;
		goto out;
	}

	ret = state->chip_info->select_input(state, input);

	if (ret == 0)
		state->input = input;
out:
	mutex_unlock(&state->mutex);
	return ret;
}

static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status)
{
	struct adv7180_state *state = to_state(sd);
	int ret = mutex_lock_interruptible(&state->mutex);
	if (ret)
		return ret;

	ret = __adv7180_status(state, status, NULL);
	mutex_unlock(&state->mutex);
	return ret;
}

static int adv7180_program_std(struct adv7180_state *state)
{
	int ret;

	ret = v4l2_std_to_adv7180(state->curr_norm);
	if (ret < 0)
		return ret;

	ret = adv7180_set_video_standard(state, ret);
	if (ret < 0)
		return ret;
	return 0;
}

static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{
	struct adv7180_state *state = to_state(sd);
	int ret = mutex_lock_interruptible(&state->mutex);

	if (ret)
		return ret;

	/* Make sure we can support this std */
	ret = v4l2_std_to_adv7180(std);
	if (ret < 0)
		goto out;

	state->curr_norm = std;

	ret = adv7180_program_std(state);
out:
	mutex_unlock(&state->mutex);
	return ret;
}

static int adv7180_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
{
	struct adv7180_state *state = to_state(sd);

	*norm = state->curr_norm;

	return 0;
}

static int adv7180_g_frame_interval(struct v4l2_subdev *sd,
				    struct v4l2_subdev_frame_interval *fi)
{
	struct adv7180_state *state = to_state(sd);

	if (state->curr_norm & V4L2_STD_525_60) {
		fi->interval.numerator = 1001;
		fi->interval.denominator = 30000;
	} else {
		fi->interval.numerator = 1;
		fi->interval.denominator = 25;
	}

	return 0;
}

static void adv7180_set_power_pin(struct adv7180_state *state, bool on)
{
	if (!state->pwdn_gpio)
		return;

	if (on) {
		gpiod_set_value_cansleep(state->pwdn_gpio, 0);
		usleep_range(5000, 10000);
	} else {
		gpiod_set_value_cansleep(state->pwdn_gpio, 1);
	}
}

static void adv7180_set_reset_pin(struct adv7180_state *state, bool on)
{
	if (!state->rst_gpio)
		return;

	if (on) {
		gpiod_set_value_cansleep(state->rst_gpio, 1);
	} else {
		gpiod_set_value_cansleep(state->rst_gpio, 0);
		usleep_range(5000, 10000);
	}
}

static int adv7180_set_power(struct adv7180_state *state, bool on)
{
	u8 val;
	int ret;

	if (on)
		val = ADV7180_PWR_MAN_ON;
	else
		val = ADV7180_PWR_MAN_OFF;

	ret = adv7180_write(state, ADV7180_REG_PWR_MAN, val);
	if (ret)
		return ret;

	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
		if (on) {
			adv7180_csi_write(state, 0xDE, 0x02);
			adv7180_csi_write(state, 0xD2, 0xF7);
			adv7180_csi_write(state, 0xD8, 0x65);
			adv7180_csi_write(state, 0xE0, 0x09);
			adv7180_csi_write(state, 0x2C, 0x00);
			if (state->field == V4L2_FIELD_NONE)
				adv7180_csi_write(state, 0x1D, 0x80);
			adv7180_csi_write(state, 0x00, 0x00);
		} else {
			adv7180_csi_write(state, 0x00, 0x80);
		}
	}

	return 0;
}

static int adv7180_s_power(struct v4l2_subdev *sd, int on)
{
	struct adv7180_state *state = to_state(sd);
	int ret;

	ret = mutex_lock_interruptible(&state->mutex);
	if (ret)
		return ret;

	ret = adv7180_set_power(state, on);
	if (ret == 0)
		state->powered = on;

	mutex_unlock(&state->mutex);
	return ret;
}

static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct v4l2_subdev *sd = to_adv7180_sd(ctrl);
	struct adv7180_state *state = to_state(sd);
	int ret = mutex_lock_interruptible(&state->mutex);
	int val;

	if (ret)
		return ret;
	val = ctrl->val;
	switch (ctrl->id) {
	case V4L2_CID_BRIGHTNESS:
		ret = adv7180_write(state, ADV7180_REG_BRI, val);
		break;
	case V4L2_CID_HUE:
		/*Hue is inverted according to HSL chart */
		ret = adv7180_write(state, ADV7180_REG_HUE, -val);
		break;
	case V4L2_CID_CONTRAST:
		ret = adv7180_write(state, ADV7180_REG_CON, val);
		break;
	case V4L2_CID_SATURATION:
		/*
		 *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE
		 *Let's not confuse the user, everybody understands saturation
		 */
		ret = adv7180_write(state, ADV7180_REG_SD_SAT_CB, val);
		if (ret < 0)
			break;
		ret = adv7180_write(state, ADV7180_REG_SD_SAT_CR, val);
		break;
	case V4L2_CID_ADV_FAST_SWITCH:
		if (ctrl->val) {
			/* ADI required write */
			adv7180_write(state, 0x80d9, 0x44);
			adv7180_write(state, ADV7180_REG_FLCONTROL,
				ADV7180_FLCONTROL_FL_ENABLE);
		} else {
			/* ADI required write */
			adv7180_write(state, 0x80d9, 0xc4);
			adv7180_write(state, ADV7180_REG_FLCONTROL, 0x00);
		}
		break;
	default:
		ret = -EINVAL;
	}

	mutex_unlock(&state->mutex);
	return ret;
}

static const struct v4l2_ctrl_ops adv7180_ctrl_ops = {
	.s_ctrl = adv7180_s_ctrl,
};

static const struct v4l2_ctrl_config adv7180_ctrl_fast_switch = {
	.ops = &adv7180_ctrl_ops,
	.id = V4L2_CID_ADV_FAST_SWITCH,
	.name = "Fast Switching",
	.type = V4L2_CTRL_TYPE_BOOLEAN,
	.min = 0,
	.max = 1,
	.step = 1,
};

static int adv7180_init_controls(struct adv7180_state *state)
{
	v4l2_ctrl_handler_init(&state->ctrl_hdl, 4);

	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
			  V4L2_CID_BRIGHTNESS, ADV7180_BRI_MIN,
			  ADV7180_BRI_MAX, 1, ADV7180_BRI_DEF);
	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
			  V4L2_CID_CONTRAST, ADV7180_CON_MIN,
			  ADV7180_CON_MAX, 1, ADV7180_CON_DEF);
	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
			  V4L2_CID_SATURATION, ADV7180_SAT_MIN,
			  ADV7180_SAT_MAX, 1, ADV7180_SAT_DEF);
	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
			  V4L2_CID_HUE, ADV7180_HUE_MIN,
			  ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF);
	v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL);

	state->sd.ctrl_handler = &state->ctrl_hdl;
	if (state->ctrl_hdl.error) {
		int err = state->ctrl_hdl.error;

		v4l2_ctrl_handler_free(&state->ctrl_hdl);
		return err;
	}
	v4l2_ctrl_handler_setup(&state->ctrl_hdl);

	return 0;
}
static void adv7180_exit_controls(struct adv7180_state *state)
{
	v4l2_ctrl_handler_free(&state->ctrl_hdl);
}

static int adv7180_enum_mbus_code(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_mbus_code_enum *code)
{
	if (code->index != 0)
		return -EINVAL;

	code->code = MEDIA_BUS_FMT_UYVY8_2X8;

	return 0;
}

static int adv7180_mbus_fmt(struct v4l2_subdev *sd,
			    struct v4l2_mbus_framefmt *fmt)
{
	struct adv7180_state *state = to_state(sd);

	fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
	fmt->width = 720;
	fmt->height = state->curr_norm & V4L2_STD_525_60 ? 480 : 576;

	if (state->field == V4L2_FIELD_ALTERNATE)
		fmt->height /= 2;

	return 0;
}

static int adv7180_set_field_mode(struct adv7180_state *state)
{
	if (!(state->chip_info->flags & ADV7180_FLAG_I2P))
		return 0;

	if (state->field == V4L2_FIELD_NONE) {
		if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
			adv7180_csi_write(state, 0x01, 0x20);
			adv7180_csi_write(state, 0x02, 0x28);
			adv7180_csi_write(state, 0x03, 0x38);
			adv7180_csi_write(state, 0x04, 0x30);
			adv7180_csi_write(state, 0x05, 0x30);
			adv7180_csi_write(state, 0x06, 0x80);
			adv7180_csi_write(state, 0x07, 0x70);
			adv7180_csi_write(state, 0x08, 0x50);
		}
		adv7180_vpp_write(state, 0xa3, 0x00);
		adv7180_vpp_write(state, 0x5b, 0x00);
		adv7180_vpp_write(state, 0x55, 0x80);
	} else {
		if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
			adv7180_csi_write(state, 0x01, 0x18);
			adv7180_csi_write(state, 0x02, 0x18);
			adv7180_csi_write(state, 0x03, 0x30);
			adv7180_csi_write(state, 0x04, 0x20);
			adv7180_csi_write(state, 0x05, 0x28);
			adv7180_csi_write(state, 0x06, 0x40);
			adv7180_csi_write(state, 0x07, 0x58);
			adv7180_csi_write(state, 0x08, 0x30);
		}
		adv7180_vpp_write(state, 0xa3, 0x70);
		adv7180_vpp_write(state, 0x5b, 0x80);
		adv7180_vpp_write(state, 0x55, 0x00);
	}

	return 0;
}

static int adv7180_get_pad_format(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_format *format)
{
	struct adv7180_state *state = to_state(sd);

	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
		format->format = *v4l2_subdev_get_try_format(sd, sd_state, 0);
	} else {
		adv7180_mbus_fmt(sd, &format->format);
		format->format.field = state->field;
	}

	return 0;
}

static int adv7180_set_pad_format(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_format *format)
{
	struct adv7180_state *state = to_state(sd);
	struct v4l2_mbus_framefmt *framefmt;
	int ret;

	switch (format->format.field) {
	case V4L2_FIELD_NONE:
		if (state->chip_info->flags & ADV7180_FLAG_I2P)
			break;
		fallthrough;
	default:
		format->format.field = V4L2_FIELD_ALTERNATE;
		break;
	}

	ret = adv7180_mbus_fmt(sd,  &format->format);

	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
		if (state->field != format->format.field) {
			state->field = format->format.field;
			adv7180_set_power(state, false);
			adv7180_set_field_mode(state);
			adv7180_set_power(state, true);
		}
	} else {
		framefmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
		*framefmt = format->format;
	}

	return ret;
}

static int adv7180_init_cfg(struct v4l2_subdev *sd,
			    struct v4l2_subdev_state *sd_state)
{
	struct v4l2_subdev_format fmt = {
		.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY
		: V4L2_SUBDEV_FORMAT_ACTIVE,
	};

	return adv7180_set_pad_format(sd, sd_state, &fmt);
}

static int adv7180_get_mbus_config(struct v4l2_subdev *sd,
				   unsigned int pad,
				   struct v4l2_mbus_config *cfg)
{
	struct adv7180_state *state = to_state(sd);

	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
		cfg->type = V4L2_MBUS_CSI2_DPHY;
		cfg->flags = V4L2_MBUS_CSI2_1_LANE |
				V4L2_MBUS_CSI2_CHANNEL_0 |
				V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
	} else {
		/*
		 * The ADV7180 sensor supports BT.601/656 output modes.
		 * The BT.656 is default and not yet configurable by s/w.
		 */
		cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
				 V4L2_MBUS_DATA_ACTIVE_HIGH;
		cfg->type = V4L2_MBUS_BT656;
	}

	return 0;
}

static int adv7180_get_skip_frames(struct v4l2_subdev *sd, u32 *frames)
{
	*frames = ADV7180_NUM_OF_SKIP_FRAMES;

	return 0;
}

static int adv7180_g_pixelaspect(struct v4l2_subdev *sd, struct v4l2_fract *aspect)
{
	struct adv7180_state *state = to_state(sd);

	if (state->curr_norm & V4L2_STD_525_60) {
		aspect->numerator = 11;
		aspect->denominator = 10;
	} else {
		aspect->numerator = 54;
		aspect->denominator = 59;
	}

	return 0;
}

static int adv7180_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm)
{
	*norm = V4L2_STD_ALL;
	return 0;
}

static int adv7180_s_stream(struct v4l2_subdev *sd, int enable)
{
	struct adv7180_state *state = to_state(sd);
	int ret;

	/* It's always safe to stop streaming, no need to take the lock */
	if (!enable) {
		state->streaming = enable;
		return 0;
	}

	/* Must wait until querystd released the lock */
	ret = mutex_lock_interruptible(&state->mutex);
	if (ret)
		return ret;
	state->streaming = enable;
	mutex_unlock(&state->mutex);
	return 0;
}

static int adv7180_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 const struct v4l2_subdev_video_ops adv7180_video_ops = {
	.s_std = adv7180_s_std,
	.g_std = adv7180_g_std,
	.g_frame_interval = adv7180_g_frame_interval,
	.querystd = adv7180_querystd,
	.g_input_status = adv7180_g_input_status,
	.s_routing = adv7180_s_routing,
	.g_pixelaspect = adv7180_g_pixelaspect,
	.g_tvnorms = adv7180_g_tvnorms,
	.s_stream = adv7180_s_stream,
};

static const struct v4l2_subdev_core_ops adv7180_core_ops = {
	.s_power = adv7180_s_power,
	.subscribe_event = adv7180_subscribe_event,
	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};

static const struct v4l2_subdev_pad_ops adv7180_pad_ops = {
	.init_cfg = adv7180_init_cfg,
	.enum_mbus_code = adv7180_enum_mbus_code,
	.set_fmt = adv7180_set_pad_format,
	.get_fmt = adv7180_get_pad_format,
	.get_mbus_config = adv7180_get_mbus_config,
};

static const struct v4l2_subdev_sensor_ops adv7180_sensor_ops = {
	.g_skip_frames = adv7180_get_skip_frames,
};

static const struct v4l2_subdev_ops adv7180_ops = {
	.core = &adv7180_core_ops,
	.video = &adv7180_video_ops,
	.pad = &adv7180_pad_ops,
	.sensor = &adv7180_sensor_ops,
};

static irqreturn_t adv7180_irq(int irq, void *devid)
{
	struct adv7180_state *state = devid;
	u8 isr3;

	mutex_lock(&state->mutex);
	isr3 = adv7180_read(state, ADV7180_REG_ISR3);
	/* clear */
	adv7180_write(state, ADV7180_REG_ICR3, isr3);

	if (isr3 & ADV7180_IRQ3_AD_CHANGE) {
		static const struct v4l2_event src_ch = {
			.type = V4L2_EVENT_SOURCE_CHANGE,
			.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
		};

		v4l2_subdev_notify_event(&state->sd, &src_ch);
	}
	mutex_unlock(&state->mutex);

	return IRQ_HANDLED;
}

static int adv7180_init(struct adv7180_state *state)
{
	int ret;

	/* ITU-R BT.656-4 compatible */
	ret = adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
			ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
	if (ret < 0)
		return ret;

	/* Manually set V bit end position in NTSC mode */
	return adv7180_write(state, ADV7180_REG_NTSC_V_BIT_END,
					ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
}

static int adv7180_set_std(struct adv7180_state *state, unsigned int std)
{
	return adv7180_write(state, ADV7180_REG_INPUT_CONTROL,
		(std << 4) | state->input);
}

static int adv7180_select_input(struct adv7180_state *state, unsigned int input)
{
	int ret;

	ret = adv7180_read(state, ADV7180_REG_INPUT_CONTROL);
	if (ret < 0)
		return ret;

	ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK;
	ret |= input;
	return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret);
}

static int adv7182_init(struct adv7180_state *state)
{
	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
		adv7180_write(state, ADV7180_REG_CSI_SLAVE_ADDR,
			ADV7180_DEFAULT_CSI_I2C_ADDR << 1);

	if (state->chip_info->flags & ADV7180_FLAG_I2P)
		adv7180_write(state, ADV7180_REG_VPP_SLAVE_ADDR,
			ADV7180_DEFAULT_VPP_I2C_ADDR << 1);

	if (state->chip_info->flags & ADV7180_FLAG_V2) {
		/* ADI recommended writes for improved video quality */
		adv7180_write(state, 0x0080, 0x51);
		adv7180_write(state, 0x0081, 0x51);
		adv7180_write(state, 0x0082, 0x68);
	}

	/* ADI required writes */
	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
		adv7180_write(state, ADV7180_REG_OUTPUT_CONTROL, 0x4e);
		adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x57);
		adv7180_write(state, ADV7180_REG_CTRL_2, 0xc0);
	} else {
		if (state->chip_info->flags & ADV7180_FLAG_V2) {
			if (state->force_bt656_4) {
				/* ITU-R BT.656-4 compatible */
				adv7180_write(state,
					      ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
					      ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
				/* Manually set NEWAVMODE */
				adv7180_write(state,
					      ADV7180_REG_VSYNC_FIELD_CTL_1,
					      ADV7180_VSYNC_FIELD_CTL_1_NEWAV);
				/* Manually set V bit end position in NTSC mode */
				adv7180_write(state,
					      ADV7180_REG_NTSC_V_BIT_END,
					      ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
			} else {
				adv7180_write(state,
					      ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
					      0x17);
			}
		}
		else
			adv7180_write(state,
				      ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
				      0x07);
		adv7180_write(state, ADV7180_REG_OUTPUT_CONTROL, 0x0c);
		adv7180_write(state, ADV7180_REG_CTRL_2, 0x40);
	}

	adv7180_write(state, 0x0013, 0x00);

	return 0;
}

static int adv7182_set_std(struct adv7180_state *state, unsigned int std)
{
	return adv7180_write(state, ADV7182_REG_INPUT_VIDSEL, std << 4);
}

enum adv7182_input_type {
	ADV7182_INPUT_TYPE_CVBS,
	ADV7182_INPUT_TYPE_DIFF_CVBS,
	ADV7182_INPUT_TYPE_SVIDEO,
	ADV7182_INPUT_TYPE_YPBPR,
};

static enum adv7182_input_type adv7182_get_input_type(unsigned int input)
{
	switch (input) {
	case ADV7182_INPUT_CVBS_AIN1:
	case ADV7182_INPUT_CVBS_AIN2:
	case ADV7182_INPUT_CVBS_AIN3:
	case ADV7182_INPUT_CVBS_AIN4:
	case ADV7182_INPUT_CVBS_AIN5:
	case ADV7182_INPUT_CVBS_AIN6:
	case ADV7182_INPUT_CVBS_AIN7:
	case ADV7182_INPUT_CVBS_AIN8:
		return ADV7182_INPUT_TYPE_CVBS;
	case ADV7182_INPUT_SVIDEO_AIN1_AIN2:
	case ADV7182_INPUT_SVIDEO_AIN3_AIN4:
	case ADV7182_INPUT_SVIDEO_AIN5_AIN6:
	case ADV7182_INPUT_SVIDEO_AIN7_AIN8:
		return ADV7182_INPUT_TYPE_SVIDEO;
	case ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3:
	case ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6:
		return ADV7182_INPUT_TYPE_YPBPR;
	case ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2:
	case ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4:
	case ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6:
	case ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8:
		return ADV7182_INPUT_TYPE_DIFF_CVBS;
	default: /* Will never happen */
		return 0;
	}
}

/* ADI recommended writes to registers 0x52, 0x53, 0x54 */
static unsigned int adv7182_lbias_settings[][3] = {
	[ADV7182_INPUT_TYPE_CVBS] = { 0xCB, 0x4E, 0x80 },
	[ADV7182_INPUT_TYPE_DIFF_CVBS] = { 0xC0, 0x4E, 0x80 },
	[ADV7182_INPUT_TYPE_SVIDEO] = { 0x0B, 0xCE, 0x80 },
	[ADV7182_INPUT_TYPE_YPBPR] = { 0x0B, 0x4E, 0xC0 },
};

static unsigned int adv7280_lbias_settings[][3] = {
	[ADV7182_INPUT_TYPE_CVBS] = { 0xCD, 0x4E, 0x80 },
	[ADV7182_INPUT_TYPE_DIFF_CVBS] = { 0xC0, 0x4E, 0x80 },
	[ADV7182_INPUT_TYPE_SVIDEO] = { 0x0B, 0xCE, 0x80 },
	[ADV7182_INPUT_TYPE_YPBPR] = { 0x0B, 0x4E, 0xC0 },
};

static int adv7182_select_input(struct adv7180_state *state, unsigned int input)
{
	enum adv7182_input_type input_type;
	unsigned int *lbias;
	unsigned int i;
	int ret;

	ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, input);
	if (ret)
		return ret;

	/* Reset clamp circuitry - ADI recommended writes */
	adv7180_write(state, ADV7180_REG_RST_CLAMP, 0x00);
	adv7180_write(state, ADV7180_REG_RST_CLAMP, 0xff);

	input_type = adv7182_get_input_type(input);

	switch (input_type) {
	case ADV7182_INPUT_TYPE_CVBS:
	case ADV7182_INPUT_TYPE_DIFF_CVBS:
		/* ADI recommends to use the SH1 filter */
		adv7180_write(state, ADV7180_REG_SHAP_FILTER_CTL_1, 0x41);
		break;
	default:
		adv7180_write(state, ADV7180_REG_SHAP_FILTER_CTL_1, 0x01);
		break;
	}

	if (state->chip_info->flags & ADV7180_FLAG_V2)
		lbias = adv7280_lbias_settings[input_type];
	else
		lbias = adv7182_lbias_settings[input_type];

	for (i = 0; i < ARRAY_SIZE(adv7182_lbias_settings[0]); i++)
		adv7180_write(state, ADV7180_REG_CVBS_TRIM + i, lbias[i]);

	if (input_type == ADV7182_INPUT_TYPE_DIFF_CVBS) {
		/* ADI required writes to make differential CVBS work */
		adv7180_write(state, ADV7180_REG_RES_CIR, 0xa8);
		adv7180_write(state, ADV7180_REG_CLAMP_ADJ, 0x90);
		adv7180_write(state, ADV7180_REG_DIFF_MODE, 0xb0);
		adv7180_write(state, ADV7180_REG_AGC_ADJ1, 0x08);
		adv7180_write(state, ADV7180_REG_AGC_ADJ2, 0xa0);
	} else {
		adv7180_write(state, ADV7180_REG_RES_CIR, 0xf0);
		adv7180_write(state, ADV7180_REG_CLAMP_ADJ, 0xd0);
		adv7180_write(state, ADV7180_REG_DIFF_MODE, 0x10);
		adv7180_write(state, ADV7180_REG_AGC_ADJ1, 0x9c);
		adv7180_write(state, ADV7180_REG_AGC_ADJ2, 0x00);
	}

	return 0;
}

static const struct adv7180_chip_info adv7180_info = {
	.flags = ADV7180_FLAG_RESET_POWERED,
	/* We cannot discriminate between LQFP and 40-pin LFCSP, so accept
	 * all inputs and let the card driver take care of validation
	 */
	.valid_input_mask = BIT(ADV7180_INPUT_CVBS_AIN1) |
		BIT(ADV7180_INPUT_CVBS_AIN2) |
		BIT(ADV7180_INPUT_CVBS_AIN3) |
		BIT(ADV7180_INPUT_CVBS_AIN4) |
		BIT(ADV7180_INPUT_CVBS_AIN5) |
		BIT(ADV7180_INPUT_CVBS_AIN6) |
		BIT(ADV7180_INPUT_SVIDEO_AIN1_AIN2) |
		BIT(ADV7180_INPUT_SVIDEO_AIN3_AIN4) |
		BIT(ADV7180_INPUT_SVIDEO_AIN5_AIN6) |
		BIT(ADV7180_INPUT_YPRPB_AIN1_AIN2_AIN3) |
		BIT(ADV7180_INPUT_YPRPB_AIN4_AIN5_AIN6),
	.init = adv7180_init,
	.set_std = adv7180_set_std,
	.select_input = adv7180_select_input,
};

static const struct adv7180_chip_info adv7182_info = {
	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
		BIT(ADV7182_INPUT_CVBS_AIN2) |
		BIT(ADV7182_INPUT_CVBS_AIN3) |
		BIT(ADV7182_INPUT_CVBS_AIN4) |
		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
		BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4),
	.init = adv7182_init,
	.set_std = adv7182_set_std,
	.select_input = adv7182_select_input,
};

static const struct adv7180_chip_info adv7280_info = {
	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P,
	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
		BIT(ADV7182_INPUT_CVBS_AIN2) |
		BIT(ADV7182_INPUT_CVBS_AIN3) |
		BIT(ADV7182_INPUT_CVBS_AIN4) |
		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
		BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3),
	.init = adv7182_init,
	.set_std = adv7182_set_std,
	.select_input = adv7182_select_input,
};

static const struct adv7180_chip_info adv7280_m_info = {
	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P,
	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
		BIT(ADV7182_INPUT_CVBS_AIN2) |
		BIT(ADV7182_INPUT_CVBS_AIN3) |
		BIT(ADV7182_INPUT_CVBS_AIN4) |
		BIT(ADV7182_INPUT_CVBS_AIN5) |
		BIT(ADV7182_INPUT_CVBS_AIN6) |
		BIT(ADV7182_INPUT_CVBS_AIN7) |
		BIT(ADV7182_INPUT_CVBS_AIN8) |
		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
		BIT(ADV7182_INPUT_SVIDEO_AIN5_AIN6) |
		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
		BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
		BIT(ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6),
	.init = adv7182_init,
	.set_std = adv7182_set_std,
	.select_input = adv7182_select_input,
};

static const struct adv7180_chip_info adv7281_info = {
	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
		BIT(ADV7182_INPUT_CVBS_AIN2) |
		BIT(ADV7182_INPUT_CVBS_AIN7) |
		BIT(ADV7182_INPUT_CVBS_AIN8) |
		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
	.init = adv7182_init,
	.set_std = adv7182_set_std,
	.select_input = adv7182_select_input,
};

static const struct adv7180_chip_info adv7281_m_info = {
	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
		BIT(ADV7182_INPUT_CVBS_AIN2) |
		BIT(ADV7182_INPUT_CVBS_AIN3) |
		BIT(ADV7182_INPUT_CVBS_AIN4) |
		BIT(ADV7182_INPUT_CVBS_AIN7) |
		BIT(ADV7182_INPUT_CVBS_AIN8) |
		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
		BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
	.init = adv7182_init,
	.set_std = adv7182_set_std,
	.select_input = adv7182_select_input,
};

static const struct adv7180_chip_info adv7281_ma_info = {
	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2,
	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
		BIT(ADV7182_INPUT_CVBS_AIN2) |
		BIT(ADV7182_INPUT_CVBS_AIN3) |
		BIT(ADV7182_INPUT_CVBS_AIN4) |
		BIT(ADV7182_INPUT_CVBS_AIN5) |
		BIT(ADV7182_INPUT_CVBS_AIN6) |
		BIT(ADV7182_INPUT_CVBS_AIN7) |
		BIT(ADV7182_INPUT_CVBS_AIN8) |
		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
		BIT(ADV7182_INPUT_SVIDEO_AIN5_AIN6) |
		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
		BIT(ADV7182_INPUT_YPRPB_AIN1_AIN2_AIN3) |
		BIT(ADV7182_INPUT_YPRPB_AIN4_AIN5_AIN6) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN5_AIN6) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
	.init = adv7182_init,
	.set_std = adv7182_set_std,
	.select_input = adv7182_select_input,
};

static const struct adv7180_chip_info adv7282_info = {
	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P,
	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
		BIT(ADV7182_INPUT_CVBS_AIN2) |
		BIT(ADV7182_INPUT_CVBS_AIN7) |
		BIT(ADV7182_INPUT_CVBS_AIN8) |
		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
	.init = adv7182_init,
	.set_std = adv7182_set_std,
	.select_input = adv7182_select_input,
};

static const struct adv7180_chip_info adv7282_m_info = {
	.flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P,
	.valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) |
		BIT(ADV7182_INPUT_CVBS_AIN2) |
		BIT(ADV7182_INPUT_CVBS_AIN3) |
		BIT(ADV7182_INPUT_CVBS_AIN4) |
		BIT(ADV7182_INPUT_CVBS_AIN7) |
		BIT(ADV7182_INPUT_CVBS_AIN8) |
		BIT(ADV7182_INPUT_SVIDEO_AIN1_AIN2) |
		BIT(ADV7182_INPUT_SVIDEO_AIN3_AIN4) |
		BIT(ADV7182_INPUT_SVIDEO_AIN7_AIN8) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN1_AIN2) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN3_AIN4) |
		BIT(ADV7182_INPUT_DIFF_CVBS_AIN7_AIN8),
	.init = adv7182_init,
	.set_std = adv7182_set_std,
	.select_input = adv7182_select_input,
};

static int init_device(struct adv7180_state *state)
{
	int ret;

	mutex_lock(&state->mutex);

	adv7180_set_power_pin(state, true);
	adv7180_set_reset_pin(state, false);

	adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES);
	usleep_range(5000, 10000);

	ret = state->chip_info->init(state);
	if (ret)
		goto out_unlock;

	ret = adv7180_program_std(state);
	if (ret)
		goto out_unlock;

	adv7180_set_field_mode(state);

	/* register for interrupts */
	if (state->irq > 0) {
		/* config the Interrupt pin to be active low */
		ret = adv7180_write(state, ADV7180_REG_ICONF1,
						ADV7180_ICONF1_ACTIVE_LOW |
						ADV7180_ICONF1_PSYNC_ONLY);
		if (ret < 0)
			goto out_unlock;

		ret = adv7180_write(state, ADV7180_REG_IMR1, 0);
		if (ret < 0)
			goto out_unlock;

		ret = adv7180_write(state, ADV7180_REG_IMR2, 0);
		if (ret < 0)
			goto out_unlock;

		/* enable AD change interrupts interrupts */
		ret = adv7180_write(state, ADV7180_REG_IMR3,
						ADV7180_IRQ3_AD_CHANGE);
		if (ret < 0)
			goto out_unlock;

		ret = adv7180_write(state, ADV7180_REG_IMR4, 0);
		if (ret < 0)
			goto out_unlock;
	}

out_unlock:
	mutex_unlock(&state->mutex);

	return ret;
}

static int adv7180_link_setup(struct media_entity *entity,
			      const struct media_pad *local,
			      const struct media_pad *remote, u32 flags)
{
	return 0;
}

static const struct media_entity_operations adv7180_entity_ops = {
.link_setup = adv7180_link_setup,
};

static const struct media_entity_operations adv7180_sd_entity_ops = {
	.link_setup = adv7180_link_setup,
};


static int adv7180_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	struct device_node *np = client->dev.of_node;
	struct adv7180_state *state;
	struct v4l2_subdev *sd;
	int ret;
	
	sd->entity.ops = &adv7180_sd_entity_ops;
	ret = media_entity_pads_init(&sd->entity, 1, &state->pad);

	/* Check if the adapter supports the needed features */
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
		return -EIO;

	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
	if (state == NULL)
		return -ENOMEM;

	state->client = client;
	state->field = V4L2_FIELD_ALTERNATE;
	state->chip_info = (struct adv7180_chip_info *)id->driver_data;

	state->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
						   GPIOD_OUT_HIGH);
	if (IS_ERR(state->pwdn_gpio)) {
		ret = PTR_ERR(state->pwdn_gpio);
		v4l_err(client, "request for power pin failed: %d\n", ret);
		return ret;
	}

	state->rst_gpio = devm_gpiod_get_optional(&client->dev, "reset",
						  GPIOD_OUT_HIGH);
	if (IS_ERR(state->rst_gpio)) {
		ret = PTR_ERR(state->rst_gpio);
		v4l_err(client, "request for reset pin failed: %d\n", ret);
		return ret;
	}

	if (of_property_read_bool(np, "adv,force-bt656-4"))
		state->force_bt656_4 = true;

	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
		state->csi_client = i2c_new_dummy_device(client->adapter,
				ADV7180_DEFAULT_CSI_I2C_ADDR);
		if (IS_ERR(state->csi_client))
			return PTR_ERR(state->csi_client);
	}

	if (state->chip_info->flags & ADV7180_FLAG_I2P) {
		state->vpp_client = i2c_new_dummy_device(client->adapter,
				ADV7180_DEFAULT_VPP_I2C_ADDR);
		if (IS_ERR(state->vpp_client)) {
			ret = PTR_ERR(state->vpp_client);
			goto err_unregister_csi_client;
		}
	}

	state->irq = client->irq;
	mutex_init(&state->mutex);
	state->curr_norm = V4L2_STD_NTSC;
	if (state->chip_info->flags & ADV7180_FLAG_RESET_POWERED)
		state->powered = true;
	else
		state->powered = false;
	state->input = 0;
	sd = &state->sd;
	v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;

	ret = adv7180_init_controls(state);
	if (ret)
		goto err_unregister_vpp_client;

	state->pad.flags = MEDIA_PAD_FL_SOURCE;
	sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
	ret = media_entity_pads_init(&sd->entity, 1, &state->pad);
	if (ret)
		goto err_free_ctrl;

	ret = init_device(state);
	if (ret)
		goto err_media_entity_cleanup;

	if (state->irq) {
		ret = request_threaded_irq(client->irq, NULL, adv7180_irq,
					   IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
					   KBUILD_MODNAME, state);
		if (ret)
			goto err_media_entity_cleanup;
	}

	ret = v4l2_async_register_subdev(sd);
	if (ret)
		goto err_free_irq;

	mutex_lock(&state->mutex);
	ret = adv7180_read(state, ADV7180_REG_IDENT);
	mutex_unlock(&state->mutex);
	if (ret < 0)
		goto err_v4l2_async_unregister;

	v4l_info(client, "chip id 0x%x found @ 0x%02x (%s)\n",
		 ret, client->addr, client->adapter->name);

	return 0;

err_v4l2_async_unregister:
	v4l2_async_unregister_subdev(sd);
err_free_irq:
	if (state->irq > 0)
		free_irq(client->irq, state);
err_media_entity_cleanup:
	media_entity_cleanup(&sd->entity);
err_free_ctrl:
	adv7180_exit_controls(state);
err_unregister_vpp_client:
	i2c_unregister_device(state->vpp_client);
err_unregister_csi_client:
	i2c_unregister_device(state->csi_client);
	mutex_destroy(&state->mutex);
	return ret;
}

static int adv7180_remove(struct i2c_client *client)
{
	struct v4l2_subdev *sd = i2c_get_clientdata(client);
	struct adv7180_state *state = to_state(sd);

	v4l2_async_unregister_subdev(sd);

	if (state->irq > 0)
		free_irq(client->irq, state);

	media_entity_cleanup(&sd->entity);
	adv7180_exit_controls(state);

	i2c_unregister_device(state->vpp_client);
	i2c_unregister_device(state->csi_client);

	adv7180_set_reset_pin(state, true);
	adv7180_set_power_pin(state, false);

	mutex_destroy(&state->mutex);

	return 0;
}

static const struct i2c_device_id adv7180_id[] = {
	{ "adv7180", (kernel_ulong_t)&adv7180_info },
	{ "adv7180cp", (kernel_ulong_t)&adv7180_info },
	{ "adv7180st", (kernel_ulong_t)&adv7180_info },
	{ "adv7182", (kernel_ulong_t)&adv7182_info },
	{ "adv7280", (kernel_ulong_t)&adv7280_info },
	{ "adv7280-m", (kernel_ulong_t)&adv7280_m_info },
	{ "adv7281", (kernel_ulong_t)&adv7281_info },
	{ "adv7281-m", (kernel_ulong_t)&adv7281_m_info },
	{ "adv7281-ma", (kernel_ulong_t)&adv7281_ma_info },
	{ "adv7282", (kernel_ulong_t)&adv7282_info },
	{ "adv7282-m", (kernel_ulong_t)&adv7282_m_info },
	{},
};
MODULE_DEVICE_TABLE(i2c, adv7180_id);

#ifdef CONFIG_PM_SLEEP
static int adv7180_suspend(struct device *dev)
{
	struct v4l2_subdev *sd = dev_get_drvdata(dev);
	struct adv7180_state *state = to_state(sd);

	return adv7180_set_power(state, false);
}

static int adv7180_resume(struct device *dev)
{
	struct v4l2_subdev *sd = dev_get_drvdata(dev);
	struct adv7180_state *state = to_state(sd);
	int ret;

	ret = init_device(state);
	if (ret < 0)
		return ret;

	ret = adv7180_set_power(state, state->powered);
	if (ret)
		return ret;

	return 0;
}

static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume);
#define ADV7180_PM_OPS (&adv7180_pm_ops)

#else
#define ADV7180_PM_OPS NULL
#endif

#ifdef CONFIG_OF
static const struct of_device_id adv7180_of_id[] = {
	{ .compatible = "adi,adv7180", },
	{ .compatible = "adi,adv7180cp", },
	{ .compatible = "adi,adv7180st", },
	{ .compatible = "adi,adv7182", },
	{ .compatible = "adi,adv7280", },
	{ .compatible = "adi,adv7280-m", },
	{ .compatible = "adi,adv7281", },
	{ .compatible = "adi,adv7281-m", },
	{ .compatible = "adi,adv7281-ma", },
	{ .compatible = "adi,adv7282", },
	{ .compatible = "adi,adv7282-m", },
	{ },
};

MODULE_DEVICE_TABLE(of, adv7180_of_id);
#endif

static struct i2c_driver adv7180_driver = {
	.driver = {
		   .name = KBUILD_MODNAME,
		   .pm = ADV7180_PM_OPS,
		   .of_match_table = of_match_ptr(adv7180_of_id),
		   },
	.probe = adv7180_probe,
	.remove = adv7180_remove,
	.id_table = adv7180_id,
};

module_i2c_driver(adv7180_driver);

MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver");
MODULE_AUTHOR("Mocean Laboratories");
MODULE_LICENSE("GPL v2");



Getting ADV7180-m up and running with iMX8MP
[edited by: Enayat at 5:37 PM (GMT -5) on 8 Dec 2023]