This thread has been locked.

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

TLV320ADC6140: Interface Nvidia Jetson Nano to TLV320ADC6140

Part Number: TLV320ADC6140

I’m the TI customer who originated this request :

https://e2e.ti.com/support/audio-group/audio/f/audio-forum/1188564/tlv320adc6140-interface-nvidia-jetson-nano-to-tlv320adc6140

 

I’m currently not able to read acoustic sound from the TLV320ADC6140 on the jetson nano.

The jetson nano has a kernel 4.9 version, so I modified the tlv320adcx140 driver to be compatible with this kernel. You will find the driver sources attached.

(I took help from this forum for the adaptation : https://e2e.ti.com/support/audio-group/audio/f/audio-forum/899448/tlv320adc3140-nvidia-jetson-kernel-4-9-driver-for-tlv320adcx140/3346253#3346253)

 

I recompiled the jetson kernel and I didn’t get any errors.

I also modified the device tree of the jetson nano to:

  • Configure the pin muxing
  • Enable I2S and I2C on jetson nano board
  • Attach audio codec to correct I2S and I2C ports

You will also find attached the device tree (please take a look to “tegra_sound” and “hdr40_i2c1” paragraphs).

Next, I reflash the jetson nano SD card and I can see with dmesg command that the codec is correctly registered.

When I run alsamixer, I can see all the codec kcontrol parameters.

 

Then I tried to configure I2S using amixer by typing these commands :

amixer -c tegrasndt210ref cset name =”I2S4 Mux” “ADMAIF1”
amixer -c tegrasndt210ref cset name =”I2S4 fsync width” 0
amixer -c tegrasndt210ref cset name =”I2S4 codec master mode” “cbs-cfs”
amixer -c tegrasndt210ref cset name =”I2S4 codec frame mode” “dsp-a”


When I run the command:

arecord -D hw:tegrasndt210ref,0 -r 48000 -c 4 -f S32_LE test.wav

I do not see any clock coming out of the jetson nano and I have the following error :

arecord: pcm_read:2103: read error: Input/output error

 

I think it's a routing problem. Can you help me please?

Do not hesitate to contact me if you want other information.

  • tegra210-porg-p3448-common.log
    /*
     * arch/arm64/boot/dts/tegra210-porg-p3448-common.dtsi
     *
     * Copyright (c) 2018-2021, NVIDIA CORPORATION.  All rights reserved.
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; version 2 of the License.
     *
     * This program is distributed in the hope that it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     * more details.
     *
     * You should have received a copy of the GNU General Public License along
     * with this program; if not, write to the Free Software Foundation, Inc.,
     * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
     *
     */
    /dts-v1/;
    /memreserve/ 0x80000000 0x00020000;
    
    #include <t210-common-platforms/tegra210-common.dtsi>
    #include <tegra210-soc/tegra210-sdhci.dtsi>
    #include <t210-common-platforms/tegra210-thermal-nct72-p2530.dtsi>
    #include <tegra210-soc/tegra210-thermal-Tboard-Tdiode.dtsi>
    #include "porg-platforms/tegra210-porg-power-tree-p3448-0000-a00.dtsi"
    #include "porg-platforms/tegra210-pinmux-drive-sdmmc-common.dtsi"
    #include "porg-platforms/tegra210-porg-pwm-fan.dtsi"
    #include <t210-common-platforms/tegra210-ers-hdmi-e2190-1100-a00.dtsi>
    #include <t210-common-platforms/tegra210-dp.dtsi>
    #include <t210-common-platforms/tegra210-thermal-userspace-alert.dtsi>
    #include "porg-platforms/tegra210-porg-thermal.dtsi"
    #include "porg-platforms/tegra210-porg-thermal-fan-est.dtsi"
    #include "porg-platforms/tegra210-porg-keys-p3448-0000-a00.dtsi"
    #include <dt-bindings/iio/meter/ina3221x.h>
    #include <tegra210-soc/tegra210-audio.dtsi>
    #include "porg-platforms/tegra210-porg-cpufreq.dtsi"
    #include "porg-platforms/tegra210-porg-powermon-p3448-0000-a00.dtsi"
    #include "porg-plugin-manager/tegra210-porg-eeprom-manager.dtsi"
    #include "porg-plugin-manager/tegra210-porg-plugin-manager.dtsi"
    #include <tegra210-soc/mods-simple-bus.dtsi>
    #include "porg-platforms/tegra210-porg-extcon-p3448-0000-a00.dtsi"
    #include "porg-platforms/tegra210-porg-pcie.dtsi"
    #include "porg-platforms/tegra210-porg-prods.dtsi"
    #include "porg-platforms/tegra210-porg-super-module-e2614.dtsi"
    
    / {
            nvidia,boardids = "3448";
            nvidia,proc-boardid = "3448";
            nvidia,pmu-boardid = "3448";
    	nvidia,fastboot-usb-pid = <0xb442>;
    
    	chosen {
    		nvidia,tegra-porg-sku;
    		stdout-path = "/serial@70006000";
    		nvidia,tegra-always-on-personality;
    		no-tnid-sn;
    		bootargs = "earlycon=uart8250,mmio32,0x70006000";
    	};
    
    	cpus {
    		cpu@0 {
    			clocks = <&tegra_car TEGRA210_CLK_CCLK_G>,
    				 <&tegra_car TEGRA210_CLK_CCLK_LP>,
    				 <&tegra_car TEGRA210_CLK_PLL_X>,
    				 <&tegra_car TEGRA210_CLK_PLL_P_OUT4>,
    				 <&tegra_clk_dfll>;
    			clock-names = "cpu_g", "cpu_lp", "pll_x", "pll_p", "dfll";
    			clock-latency = <300000>;
    		};
    	};
    
    	rollback-protection {
    		status = "okay";
    	};
    
    	host1x {
    		/* Camera unit clocks */
    		assigned-clocks = <&tegra_car TEGRA210_CLK_EXTERN3>,
    						<&tegra_car TEGRA210_CLK_CILE>,
    						<&tegra_car TEGRA210_CLK_CILCD>,
    						<&tegra_car TEGRA210_CLK_CILAB>,
    						<&tegra_car TEGRA210_CLK_VI_I2C>,
    						<&tegra_car TEGRA210_CLK_CLK_OUT_3_MUX>,
    						<&tegra_car TEGRA210_CLK_VI>,
    						<&tegra_car TEGRA210_CLK_ISP>,
    						<&tegra_car TEGRA210_CLK_ISPB>;
    		assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_P>,
    						<&tegra_car TEGRA210_CLK_PLL_P>,
    						<&tegra_car TEGRA210_CLK_PLL_P>,
    						<&tegra_car TEGRA210_CLK_PLL_P>,
    						<&tegra_car TEGRA210_CLK_PLL_P>,
    						<&tegra_car TEGRA210_CLK_EXTERN3>,
    						<&tegra_car TEGRA210_CLK_PLL_C>,
    						<&tegra_car TEGRA210_CLK_PLL_C>,
    						<&tegra_car TEGRA210_CLK_ISP>;
    		assigned-clock-rates = <24000000>,
    						<102000000>,
    						<102000000>,
    						<102000000>,
    						<102000000>,
    						<24000000>,
    						<408000000>,
    						<408000000>,
    						<0>;
    
    		/* tegradc.0 */
    		dc@54200000 {
    			status = "okay";
    			nvidia,dc-flags = <TEGRA_DC_FLAG_ENABLED>;
    			nvidia,emc-clk-rate = <300000000>;
    			nvidia,cmu-enable = <1>;
    			nvidia,fb-bpp = <32>; /* bits per pixel */
    			nvidia,fb-flags = <TEGRA_FB_FLIP_ON_PROBE>;
    			nvidia,dc-or-node = "/host1x/sor1";
    			nvidia,dc-connector = <&sor1>;
    			win-mask = <0x7>; /* Assign only wins A/B/C */
    		};
    		dc@54240000 {
    			status = "okay";
    			nvidia,dc-flags = <TEGRA_DC_FLAG_ENABLED>;
    			nvidia,emc-clk-rate = <300000000>;
    			nvidia,cmu-enable = <1>;
    			nvidia,fb-bpp = <32>; /* bits per pixel */
    			nvidia,fb-flags = <TEGRA_FB_FLIP_ON_PROBE>;
    			nvidia,dc-or-node = "/host1x/sor";
    			nvidia,dc-connector = <&sor0>;
    			win-mask = <0x7>; /* Assign only wins A/B/C */
    		};
    		sor {
    			status = "okay";
    			nvidia,xbar-ctrl = <2 1 0 3 4>;
    			dp-display {
    				status = "okay";
    			};
    		};
    		sor1 {
    			/* Compared to Jetson-TX1's baseboard (P2597), HDMI TX
    			 * lanes 0 and 2 have been swapped in Porg's baseboard
    			 * (P3448) making it a straight lane mapping between
    			 * SOR1 and the pad.
    			 */
    			nvidia,xbar-ctrl = <0 1 2 3 4>;
    			status = "okay";
    			hdmi-display {
    				status = "okay";
    			};
    		};
    		dpaux {
    			status = "okay";
    		};
    		dpaux1 {
    			status = "okay";
    		};
    	};
    
    	pwm@7000a000 {
    		nvidia,no-clk-sleeping-in-ops;
    	};
    
    	pmc@7000e400 {
    		#nvidia,wake-cells = <3>;
    		nvidia,invert-interrupt;
    		nvidia,suspend-mode = <0>;
    		nvidia,cpu-pwr-good-time = <0>;
    		nvidia,cpu-pwr-off-time = <0>;
    		nvidia,core-pwr-good-time = <4587 3876>;
    		nvidia,core-pwr-off-time = <39065>;
    		nvidia,core-pwr-req-active-high;
    		nvidia,sys-clock-req-active-high;
    
    		iopad-defaults {
    			audio-hv-pads {
    				pins = "audio-hv";
    				nvidia,power-source-voltage = <TEGRA_IO_PAD_VOLTAGE_1800000UV>;
    			};
    
    			spi-hv-pads {
    				pins = "spi-hv";
    				nvidia,power-source-voltage = <TEGRA_IO_PAD_VOLTAGE_1800000UV>;
    			};
    
    			gpio-pads {
    				pins = "gpio";
    				nvidia,power-source-voltage = <TEGRA_IO_PAD_VOLTAGE_1800000UV>;
    			};
    
    			sdmmc-io-pads {
    				pins = "sdmmc1", "sdmmc3";
    				nvidia,enable-voltage-switching;
    			};
    		};
    	};
    
    	hdr40_spi1: spi@7000d400 { /* SPI 1 to 40 pin header */
    		status = "okay";
    		spi@0 {
    			compatible = "tegra-spidev";
    			reg = <0x0>;
    			spi-max-frequency = <33000000>;
    			controller-data {
    				nvidia,enable-hw-based-cs;
    				nvidia,rx-clk-tap-delay = <7>;
    			};
    		};
    		spi@1 {
    			compatible = "tegra-spidev";
    			reg = <0x1>;
    			spi-max-frequency = <33000000>;
    			controller-data {
    				nvidia,enable-hw-based-cs;
    				nvidia,rx-clk-tap-delay = <7>;
    			};
    		};
    	};
    
    	hdr40_spi2: spi@7000d600 { /* SPI 2 to 40 pin header */
    		status = "okay";
    		spi@0 {
    			compatible = "tegra-spidev";
    			reg = <0x0>;
    			spi-max-frequency = <33000000>;
    			controller-data {
    				nvidia,enable-hw-based-cs;
    				nvidia,rx-clk-tap-delay = <6>;
    			};
    		};
    		spi@1 {
    			compatible = "tegra-spidev";
    			reg = <0x1>;
    			spi-max-frequency = <33000000>;
    			controller-data {
    				nvidia,enable-hw-based-cs;
    				nvidia,rx-clk-tap-delay = <6>;
    			};
    		};
    	};
    
    	spi@7000d800 {
    		status = "disabled";
    	};
    
    	spi@7000da00 {
    		status = "disabled";
    	};
    
    	spi@70410000 {
    		status = "okay";
    		spi-max-frequency = <104000000>;
    		spiflash@0 {
    			#address-cells = <1>;
    			#size-cells = <1>;
    			compatible = "MX25U3235F";
    			reg = <0>;
    			spi-max-frequency = <104000000>;
    			controller-data {
    				nvidia,x1-len-limit = <4194304>;
    				nvidia,x1-bus-speed = <104000000>;
    				nvidia,x1-dymmy-cycle = <8>;
    				nvidia,ctrl-bus-clk-ratio = /bits/ 8 <0x01>;
    			};
    		};
    	};
    
    	sdhci@700b0600 { /* SDMMC4 for EMMC */
    		uhs-mask = <0x0>;
    		mmc-hs400-enhanced-strobe;
    		built-in;
    		power-off-rail;
    		status = "disabled";
    		bus-width = <8>;
    		non-removable;
    		/delete-property/ nvidia,enable-hs533-mode;
    		no-sdio;
    		no-sd;
    		pll_source = "pll_p", "pll_c4_out2";
    		max-clk-limit = <0xbebc200>;
    	};
    
    	sdhci@700b0400 {
    		status = "disabled";
    		/delete-property/ keep-power-in-suspend;
    		/delete-property/ non-removable;
    		mmc-ddr-1_8v;
    		mmc-ocr-mask = <3>;
    		uhs-mask = <0x0>;
    		tap-delay = <3>;
    	};
    
    	sdhci@700b0200 { /* SDMMC2 for Wifi */
    		uhs-mask = <0x8>;
    		power-off-rail;
    		force-non-removable-rescan;
    		status = "disabled";
    	};
    
    	sdhci@700b0000 { /* SDMMC1 for SD card */
    		default-drv-type = <1>;
    		cd-gpios = <&gpio TEGRA_GPIO(Z, 1) 0>;
    		sd-uhs-sdr104;
    		sd-uhs-sdr50;
    		sd-uhs-sdr25;
    		sd-uhs-sdr12;
    		mmc-ddr-1_8v;
    		mmc-hs200-1_8v;
    		nvidia,cd-wakeup-capable;
    		nvidia,update-pinctrl-settings;
    		nvidia,pmc-wakeup = <&tegra_pmc PMC_WAKE_TYPE_GPIO 35
    			PMC_TRIGGER_TYPE_NONE>;
    		uhs-mask = <0xc>;
    		no-sdio;
    		no-mmc;
    		disable-wp;
    		status = "okay";
    	};
    
    	aconnect@702c0000 {
    		adma@702e2000 {
    			status = "okay";
    		};
    
    		ahub {
    			i2s@702d1000 {
    				status = "disabled";
    			};
    
    			i2s@702d1100 {
    				status = "disabled";
    			};
    
    			i2s@702d1200 {
    				regulator-supplies = "vdd-1v8-dmic";
    				vdd-1v8-dmic-supply = <&max77620_sd3>;
    				fsync-width = <15>;
    				status = "okay";
    			};
    
    			i2s@702d1300 {
    				regulator-supplies = "vddio-uart";
    				vddio-uart-supply = <&max77620_sd3>;
    				fsync-width = <15>;
    				status = "okay";
    
    				/*
    				 * I2S4 on Jetson Nano uses the I2S4B pads
                                     * and to use these pads bit 0 in the I2S_CYA
    				 * register must be set.
    				 */
    				enable-cya;
    			};
    
    			i2s@702d1400 {
    				status = "disabled";
    			};
    
    			dmic@702d4000 {
    				regulator-supplies = "vdd-1v8-dmic";
    				vdd-1v8-dmic-supply = <&max77620_sd3>;
    				status = "okay";
    			};
    
    			dmic@702d4100 {
    				regulator-supplies = "vdd-1v8-dmic";
    				vdd-1v8-dmic-supply = <&max77620_sd3>;
    				status = "okay";
    			};
    
    			dmic@702d4200 {
    				status = "disabled";
    			};
    		};
    	};
    
    	hda@70030000 {
    		status = "okay";
    	};
    
    	tegra_sound: sound {
    		status = "okay";
    		compatible = "nvidia,tegra-audio-t210ref-mobile-rt565x";
    		nvidia,model = "tegra-snd-t210ref-mobile-rt565x";
    
    		clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
    			 <&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
    			 <&tegra_car TEGRA210_CLK_EXTERN1>;
    		clock-names = "pll_a", "pll_a_out0", "extern1";
    		assigned-clocks = <&tegra_car TEGRA210_CLK_EXTERN1>,
    				  <&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
    				  <&tegra_car TEGRA210_CLK_PLL_A>;
    		assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_A_OUT0>;
    		assigned-clock-rates = <12288000>, <49152000>, <368640000>;
    
    		nvidia,num-codec-link = <4>;
    
    		nvidia,audio-routing =
    			"x CH1_ADC",	"x Mic",
    			"x CH2_ADC",	"x Mic",
    			"x CH3_ADC",	"x Mic",
    			"x CH4_ADC",	"x Mic";
    
    		nvidia,xbar = <&tegra_axbar>;
    		mclk-fs = <256>;
    
    		hdr40_snd_link_i2s: i2s_dai_link1: nvidia,dai-link-1 {
    			link-name = "tlv320adcx140-codec";
    			cpu-dai = <&tegra_i2s4>;
    			codec-dai = <&codec_adc6140>;
    			cpu-dai-name = "I2S4";
    			codec-dai-name = "tlv320adcx140-codec";
    			format = "dsp_a";
    			fsync-width = <0>;
    			bitclock-slave;
    			frame-slave;
    			bitclock-noninversion;
    			frame-noninversion;
    			bit-format = "s32_le";
    			srate = <48000>;
    			num-channel = <4>;
    			ignore_suspend;
    			name-prefix = "x";
    			status = "okay";
    		};
    		nvidia,dai-link-2 {
    			link-name = "spdif-dit-1";
    			cpu-dai = <&tegra_i2s3>;
    			codec-dai = <&spdif_dit1>;
    			cpu-dai-name = "I2S3";
    			codec-dai-name = "dit-hifi";
    			format = "i2s";
    			bitclock-slave;
    			frame-slave;
    			bitclock-noninversion;
    			frame-noninversion;
    			bit-format = "s16_le";
    			srate = <48000>;
    			num-channel = <2>;
    			ignore_suspend;
    			name-prefix = "y";
    			status = "disabled";
    		};
    		nvidia,dai-link-3 {
    			link-name = "spdif-dit-2";
    			cpu-dai = <&tegra_dmic1>;
    			codec-dai = <&spdif_dit2>;
    			cpu-dai-name = "DMIC1";
    			codec-dai-name = "dit-hifi";
    			format = "i2s";
    			bit-format = "s16_le";
    			srate = <48000>;
    			ignore_suspend;
    			num-channel = <2>;
    			name-prefix = "a";
    			status = "disabled";
    		};
    		nvidia,dai-link-4 {
    			link-name = "spdif-dit-3";
    			cpu-dai = <&tegra_dmic2>;
    			codec-dai = <&spdif_dit3>;
    			cpu-dai-name = "DMIC2";
    			codec-dai-name = "dit-hifi";
    			format = "i2s";
    			bit-format = "s16_le";
    			srate = <48000>;
    			ignore_suspend;
    			num-channel = <2>;
    			name-prefix = "b";
    			status = "disabled";
    		};
    	};
    
    	extcon {
    		extcon@0 {
    			status = "disabled";
    		};
    	};
    
    	xusb_padctl@7009f000 {
    		status = "okay";
    
    		pads {
    			usb2 {
    				status = "okay";
    
    				lanes {
    					usb2-0 {
    						status = "okay";
    						nvidia,function = "xusb";
    					};
    					usb2-1 {
    						status = "okay";
    						nvidia,function = "xusb";
    					};
    					usb2-2 {
    						status = "okay";
    						nvidia,function = "xusb";
    					};
    				};
    			};
    
    			pcie {
    				status = "okay";
    
    				lanes {
    					pcie-0 {
    						status = "okay";
    						nvidia,function = "pcie-x1";
    					};
    					pcie-1 {
    						status = "okay";
    						nvidia,function = "pcie-x4";
    					};
    					pcie-2 {
    						status = "okay";
    						nvidia,function = "pcie-x4";
    					};
    					pcie-3 {
    						status = "okay";
    						nvidia,function = "pcie-x4";
    					};
    					pcie-4 {
    						status = "okay";
    						nvidia,function = "pcie-x4";
    					};
    					pcie-5 {
    						status = "okay";
    						nvidia,function = "xusb";
    					};
    					pcie-6 {
    						status = "okay";
    						nvidia,function = "xusb";
    					};
    				};
    			};
    		};
    
    		ports {
    			usb2-0 {
    				status = "okay";
    				mode = "otg";
    				nvidia,usb3-port-fake = <3>;
    			};
    			usb2-1 {
    				status = "okay";
    				mode = "host";
    			};
    			usb2-2 {
    				status = "okay";
    				mode = "host";
    			};
    			usb3-0 {
    				status = "okay";
    				nvidia,usb2-companion = <1>;
    			};
    		};
    	};
    
    
    	xusb@70090000 {
    		phys = <&{/xusb_padctl@7009f000/pads/usb2/lanes/usb2-0}>,
    				<&{/xusb_padctl@7009f000/pads/usb2/lanes/usb2-1}>,
    				<&{/xusb_padctl@7009f000/pads/usb2/lanes/usb2-2}>,
    				<&{/xusb_padctl@7009f000/pads/pcie/lanes/pcie-6}>;
    		phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0";
    		#extcon-cells = <1>;
    		nvidia,pmc-wakeup =
    			<&tegra_pmc
    				PMC_WAKE_TYPE_EVENT 39 PMC_TRIGGER_TYPE_HIGH>,
    			<&tegra_pmc
    				PMC_WAKE_TYPE_EVENT 40 PMC_TRIGGER_TYPE_HIGH>,
    			<&tegra_pmc
    				PMC_WAKE_TYPE_EVENT 41 PMC_TRIGGER_TYPE_HIGH>,
    			<&tegra_pmc
    				PMC_WAKE_TYPE_EVENT 42 PMC_TRIGGER_TYPE_HIGH>,
    			<&tegra_pmc
    				PMC_WAKE_TYPE_EVENT 44 PMC_TRIGGER_TYPE_HIGH>;
    		nvidia,boost_cpu_freq = <1200>;
    		status = "okay";
    	};
    
    	xudc@700d0000 {
    		phys =  <&{/xusb_padctl@7009f000/pads/usb2/lanes/usb2-0}>;
    		phy-names = "usb2";
    		charger-detector = <&tegra_usb_cd>;
    		#extcon-cells = <1>;
    		status = "okay";
    	};
    
    	tegra_usb_cd: usb_cd {
    		reg = <0x0 0x7009f000 0x0 0x1000>;
    		phys = <&{/xusb_padctl@7009f000/pads/usb2/lanes/usb2-0}>;
    		phy-names = "otg-phy";
    		status = "disabled";
    	};
    
    	psy_extcon_xudc {
    		status = "disabled";
    		/delete-property/ dt-override-status-odm-data;
    	};
    
    	xotg {
    		status = "disabled";
    		#extcon-cells = <1>;
    	};
    
    	chosen {
    		nvidia,bootloader-vbus-enable=<0x1>;
    		nvidia,fastboot_without_usb;
    		nvidia,gpu-disable-power-saving;
    		board-has-eeprom;
    		firmware-blob-partition = "RP4";
    
    		verified-boot {
    			poweroff-on-red-state;
    		};
    	};
    
    	gpu-dvfs-rework {
    		status = "okay";
    	};
    
    	pwm_regulators {
    		compatible = "simple-bus";
    		#address-cells = <1>;
    		#size-cells = <0>;
    
    		cpu_ovr_reg: pwm-regulator@0 {
    			status = "okay";
    			reg = <0>;
    			compatible = "pwm-regulator";
    			pwms = <&tegra_pwm_dfll 0 2500>;
    			regulator-name = "vdd-cpu";
    			regulator-min-microvolt = <708000>;
    			regulator-max-microvolt = <1323400>;
    			regulator-always-on;
    			regulator-boot-on;
    			voltage-table =
    				<708000 0>, <727200 1>, <746400 2>,
    				<765600 3>, <784800 4>, <804000 5>,
    				<823200 6>, <842400 7>, <861600 8>,
    				<880800 9>, <900000 10>, <919200 11>,
    				<938400 12>, <957600 13>, <976800 14>,
    				<996000 15>, <1015200 16>, <1034400 17>,
    				<1053600 18>, <1072800 19>, <1092000 20>,
    				<1111200 21>, <1130400 22>, <1149600 23>,
    				<1168800 24>, <1188000 25>, <1207200 26>,
    				<1226400 27>, <1245600 28>, <1264800 29>,
    				<1284000 30>, <1303200 31>, <1322400 32>;
    		};
    
    		pwm-regulator@1 {
    			status = "okay";
    			reg = <1>;
    			compatible = "pwm-regulator";
    			pwms = <&tegra_pwm 1 8000>;
    			regulator-name = "vdd-gpu";
    			regulator-min-microvolt = <708000>;
    			regulator-max-microvolt = <1323400>;
    			regulator-init-microvolt = <1000000>;
    			regulator-n-voltages = <62>;
    			regulator-enable-ramp-delay = <2000>;
    			enable-gpio = <&max77620 6 0>;
    			regulator-settling-time-us = <160>;
    		};
    	};
    
    	soctherm@0x700E2000 {
    		throttle-cfgs {
    			throttle_oc1: oc1 {
    				nvidia,priority = <0>;
    				nvidia,polarity-active-low = <0>;
    				nvidia,count-threshold = <0>;
    				nvidia,alarm-filter = <0>;
    				nvidia,alarm-period = <0>;
    				nvidia,cpu-throt-percent = <0>;
    				nvidia,gpu-throt-level =
    					<TEGRA_SOCTHERM_THROT_LEVEL_NONE>;
    			};
    
    			throttle_oc3: oc3 {
    				nvidia,priority = <40>;
    				nvidia,polarity-active-low = <1>;
    				nvidia,count-threshold = <15>;
    				nvidia,alarm-filter = <5100000>;
    				nvidia,alarm-period = <0>;
    				nvidia,cpu-throt-percent = <75>;
    				nvidia,gpu-throt-level =
    					<TEGRA_SOCTHERM_THROT_LEVEL_MED>;
    			};
    		};
    	};
    
    	serial@70006000 { /* UART-A : UART1: Debug */
    		compatible = "nvidia,tegra210-uart", "nvidia,tegra114-hsuart", "nvidia,tegra20-uart";
    		console-port;
    		sqa-automation-port;
    		/delete-property/ resets;
    		/delete-property/ reset-names;
    		status = "okay";
    	};
    
    	serial@70006040 { /* UART-B : UART2 40 pin header */
    		compatible = "nvidia,tegra114-hsuart";
    		status = "okay";
    	};
    
    	serial@70006200 { /* UART-C : UART3 : M.2 Key E */
    		compatible = "nvidia,tegra114-hsuart";
    		dma-names = "tx";
    		nvidia,adjust-baud-rates = <921600 921600 100>;
    		status = "okay";
    	};
    
    	serial@70006300 { /* UART-D not used */
    		status = "disabled";
    	};
    
    	i2c@7000c700 { /* i2c4 */
    		status = "okay";
    	};
    
    	i2c@7000d000 {
    		clock-frequency = <1000000>;
    	};
    
    	dfll-max77621@70110000 {
    		i2c_dfll: dfll-max77621-integration {
    			i2c-fs-rate = <1000000>;
    			pmic-i2c-address = <0x36>;
    			pmic-i2c-voltage-register = <0x01>;
    			sel-conversion-slope = <1>;
    		};
    
    		dfll_max77621_parms: dfll-max77621-board-params {
    			sample-rate = <12500>;
    			fixed-output-forcing;
    			cf = <10>;
    			ci = <0>;
    			cg = <2>;
    			droop-cut-value = <0xf>;
    			droop-restore-ramp = <0x0>;
    			scale-out-ramp = <0x0>;
    		};
    	};
    
    	dfll_cap: dfll-cdev-cap {
    		compatible = "nvidia,tegra-dfll-cdev-action";
    		act-dev = <&tegra_clk_dfll>;
    		cdev-type = "DFLL-cap";
    		#cooling-cells = <2>; /* min followed by max */
    	};
    
    	dfll_floor: dfll-cdev-floor {
    		compatible = "nvidia,tegra-dfll-cdev-action";
    		act-dev = <&tegra_clk_dfll>;
    		cdev-type = "DFLL-floor";
    		#cooling-cells = <2>; /* min followed by max */
    	};
    
    	hdr40_i2c0: i2c@7000c000 {
    		tegra_nct72: temp-sensor@4c {
    			status = "disabled";
    		};
    	};
        	
    	hdr40_i2c1: i2c@7000c400 {
    		#address-cells = <1>;
    		#size-cells = <0>;
    		status="okay";
    		codec_adc6140: codec_adc6140@4c {
    			compatible = "ti,tlv320adc6140";
    			reg = <0x4c>;
    			status="okay";
    			ti,use-internal-areg;
    			ti,mic-bias-source = <6>;
          		};
        	};	
    
    	clock@70110000 {
    		status = "okay";
    		vdd-cpu-supply = <&cpu_ovr_reg>;
    		nvidia,dfll-max-freq-khz = <1479000>;
    		nvidia,pwm-to-pmic;
    		nvidia,init-uv = <1000000>;
    		nvidia,sample-rate = <25000>;
    		nvidia,droop-ctrl = <0x00000f00>;
    		nvidia,force-mode = <1>;
    		nvidia,cf = <6>;
    		nvidia,ci = <0>;
    		nvidia,cg = <2>;
    		nvidia,idle-override;
    		nvidia,one-shot-calibrate;
    		nvidia,pwm-period = <2500>; /* 2.5us */
    		pinctrl-names = "dvfs_pwm_enable", "dvfs_pwm_disable";
    		pinctrl-0 = <&dvfs_pwm_active_state>;
    		pinctrl-1 = <&dvfs_pwm_inactive_state>;
    		nvidia,align-offset-uv = <708000>;
    		nvidia,align-step-uv = <19200>;
    	};
    
    	dvfs {
    		compatible = "nvidia,tegra210-dvfs";
                    vdd-cpu-supply = <&cpu_ovr_reg>;
                    nvidia,gpu-max-freq-khz = <921600>;
    	};
    
    	rtc {
    		nvidia,pmc-wakeup = <&tegra_pmc PMC_WAKE_TYPE_EVENT 16
    			PMC_TRIGGER_TYPE_HIGH>;
    	};
    
    	nvpmodel {
    		status = "okay";
    	};
    
    	r8168 {
    		isolate-gpio = <&gpio TEGRA_GPIO(X, 3) 0>;
    	};
    
    	tegra_udrm: tegra_udrm {
    		compatible = "nvidia,tegra-udrm";
    	};
    
    	tegra_wdt: watchdog@60005100 {
    		dt-override-status-odm-data = <0x00010000 0x00010000>;
    		status = "disabled";
    	};
    
    	soft_wdt: soft_watchdog {
    		compatible = "softdog-platform";
    		dt-override-status-odm-data = <0x00030000 0x00000000>;
    		status = "okay";
    	};
    
    	gpio: gpio@6000d000 {
    		suspend_gpio: system-suspend-gpio {
    			status = "okay";
    			gpio-hog;
    			output-high;
    			gpio-suspend;
    			suspend-output-low;
    			gpios = <
    				TEGRA_GPIO(A, 6) 0
    				>;
    		};
    	};
    
    	leds {
    		compatible = "gpio-leds";
    		status = "disabled";
    		pwr {
    			gpios = <&gpio TEGRA_GPIO(I, 1) GPIO_ACTIVE_HIGH>;
    			default-state = "on";
    			linux,default-trigger = "system-throttle";
    		};
    	};
    
    	memory-controller@70019000 {
    		status = "okay";
    	};
    
    	mailbox@70098000 {
    		status = "okay";
    	};
    
    	memory@80000000 {
    		device_type = "memory";
    		reg = < 0x0 0x80000000 0x0 0x80000000 >;
    	};
    
    	pinmux@700008d4 {
                    dvfs_pwm_active_state: dvfs_pwm_active {
                            dvfs_pwm_pbb1 {
                                    nvidia,pins = "dvfs_pwm_pbb1";
                                    nvidia,tristate = <TEGRA_PIN_DISABLE>;
                            };
                    };
    
                    dvfs_pwm_inactive_state: dvfs_pwm_inactive {
                            dvfs_pwm_pbb1 {
                                    nvidia,pins = "dvfs_pwm_pbb1";
                                    nvidia,tristate = <TEGRA_PIN_ENABLE>;
                            };
                    };
            };
    
            pwm@70110000 {
                    pinctrl-0 = <&dvfs_pwm_active_state>;
                    pinctrl-1 = <&dvfs_pwm_inactive_state>;
                    pwm-regulator = <&cpu_ovr_reg>;
                    status = "okay";
            };
    
    	nvdumper {
    		status = "disabled";
    	};
    
    	cpu_edp {
    		status = "okay";
    		nvidia,edp_limit = <0x61a8>;
    	};
    
    	gpu_edp {
    		status = "okay";
    		nvidia,edp_limit = <0x4e20>;
    	};
    
    	cpu_alert: cpu-throttle-alert {
    		status = "okay";
    	};
    
    	gpu_alert: gpu-throttle-alert {
    		status = "okay";
    	};
    
    	hot_surface_alert: hot-surface-alert {
    		compatible = "userspace-therm-alert";
    		cdev-type = "hot-surface-alert";
    		status = "okay";
    		#cooling-cells = <2>;
    	};
    
    	thermal-zones {
    		GPU-therm {
    			trips {
    				gpu_hot_surface_trip: gpu-hot-surface-trip {
    					temperature = <70000>;
    					hysteresis = <8000>;
    					type = "active";
    				};
    			};
    
    			cooling-maps {
    				gpu-hot-surface-map0 {
    					trip = <&gpu_hot_surface_trip>;
    					cooling-device = <&hot_surface_alert 1 1>;
    				};
    			};
    		};
    
    		PLL-therm {
    			trips {
    				pll_hot_surface_trip: pll-hot-surface-trip {
    					temperature = <70000>;
    					hysteresis = <8000>;
    					type = "active";
    				};
    			};
    
    			cooling-maps {
    				pll-hot-surface-map0 {
    					trip = <&pll_hot_surface_trip>;
    					cooling-device = <&hot_surface_alert 1 1>;
    				};
    			};
    		};
    	};
    };
    
    #if LINUX_VERSION >= 414
    #include <tegra210-linux-4.14.dtsi>
    #endif
    

    8357.tlv320adcx140.h

    6076.tlv320adcx140.c
    // SPDX-License-Identifier: GPL-2.0
    // TLV320ADCX140 Sound driver
    // Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/
    
    #include <linux/module.h>
    #include <linux/moduleparam.h>
    #include <linux/init.h>
    #include <linux/delay.h>
    #include <linux/pm.h>
    #include <linux/i2c.h>
    #include <linux/gpio/consumer.h>
    #include <linux/regulator/consumer.h>
    #include <linux/acpi.h>
    #include <linux/of.h>
    #include <linux/of_gpio.h>
    #include <linux/slab.h>
    #include <sound/core.h>
    #include <sound/pcm.h>
    #include <sound/pcm_params.h>
    #include <sound/soc.h>
    #include <sound/initval.h>
    #include <sound/tlv.h>
    
    #include "tlv320adcx140.h"
    
    struct adcx140_priv {
    	struct snd_soc_codec *component;
    	struct regulator *supply_areg;
    	struct gpio_desc *gpio_reset;
    	struct regmap *regmap;
    	struct device *dev;
    
    	int micbias_vg;
    
    	unsigned int dai_fmt;
    	unsigned int tdm_delay;
    	unsigned int slot_width;
    };
    
    static const char * const gpo_config_names[] = {
    	"ti,gpo-config-1",
    	"ti,gpo-config-2",
    	"ti,gpo-config-3",
    	"ti,gpo-config-4",
    };
    
    static const struct reg_default adcx140_reg_defaults[] = {
    	{ ADCX140_PAGE_SELECT, 0x00 },
    	{ ADCX140_SW_RESET, 0x00 },
    	{ ADCX140_SLEEP_CFG, 0x00 },
    	{ ADCX140_SHDN_CFG, 0x05 },
    	{ ADCX140_ASI_CFG0, 0x30 },
    	{ ADCX140_ASI_CFG1, 0x00 },
    	{ ADCX140_ASI_CFG2, 0x00 },
    	{ ADCX140_ASI_CH1, 0x00 },
    	{ ADCX140_ASI_CH2, 0x01 },
    	{ ADCX140_ASI_CH3, 0x02 },
    	{ ADCX140_ASI_CH4, 0x03 },
    	{ ADCX140_ASI_CH5, 0x04 },
    	{ ADCX140_ASI_CH6, 0x05 },
    	{ ADCX140_ASI_CH7, 0x06 },
    	{ ADCX140_ASI_CH8, 0x07 },
    	{ ADCX140_MST_CFG0, 0x02 },
    	{ ADCX140_MST_CFG1, 0x48 },
    	{ ADCX140_ASI_STS, 0xff },
    	{ ADCX140_CLK_SRC, 0x10 },
    	{ ADCX140_PDMCLK_CFG, 0x40 },
    	{ ADCX140_PDM_CFG, 0x00 },
    	{ ADCX140_GPIO_CFG0, 0x22 },
    	{ ADCX140_GPO_CFG0, 0x00 },
    	{ ADCX140_GPO_CFG1, 0x00 },
    	{ ADCX140_GPO_CFG2, 0x00 },
    	{ ADCX140_GPO_CFG3, 0x00 },
    	{ ADCX140_GPO_VAL, 0x00 },
    	{ ADCX140_GPIO_MON, 0x00 },
    	{ ADCX140_GPI_CFG0, 0x00 },
    	{ ADCX140_GPI_CFG1, 0x00 },
    	{ ADCX140_GPI_MON, 0x00 },
    	{ ADCX140_INT_CFG, 0x00 },
    	{ ADCX140_INT_MASK0, 0xff },
    	{ ADCX140_INT_LTCH0, 0x00 },
    	{ ADCX140_BIAS_CFG, 0x00 },
    	{ ADCX140_CH1_CFG0, 0x00 },
    	{ ADCX140_CH1_CFG1, 0x00 },
    	{ ADCX140_CH1_CFG2, 0xc9 },
    	{ ADCX140_CH1_CFG3, 0x80 },
    	{ ADCX140_CH1_CFG4, 0x00 },
    	{ ADCX140_CH2_CFG0, 0x00 },
    	{ ADCX140_CH2_CFG1, 0x00 },
    	{ ADCX140_CH2_CFG2, 0xc9 },
    	{ ADCX140_CH2_CFG3, 0x80 },
    	{ ADCX140_CH2_CFG4, 0x00 },
    	{ ADCX140_CH3_CFG0, 0x00 },
    	{ ADCX140_CH3_CFG1, 0x00 },
    	{ ADCX140_CH3_CFG2, 0xc9 },
    	{ ADCX140_CH3_CFG3, 0x80 },
    	{ ADCX140_CH3_CFG4, 0x00 },
    	{ ADCX140_CH4_CFG0, 0x00 },
    	{ ADCX140_CH4_CFG1, 0x00 },
    	{ ADCX140_CH4_CFG2, 0xc9 },
    	{ ADCX140_CH4_CFG3, 0x80 },
    	{ ADCX140_CH4_CFG4, 0x00 },
    	{ ADCX140_CH5_CFG2, 0xc9 },
    	{ ADCX140_CH5_CFG3, 0x80 },
    	{ ADCX140_CH5_CFG4, 0x00 },
    	{ ADCX140_CH6_CFG2, 0xc9 },
    	{ ADCX140_CH6_CFG3, 0x80 },
    	{ ADCX140_CH6_CFG4, 0x00 },
    	{ ADCX140_CH7_CFG2, 0xc9 },
    	{ ADCX140_CH7_CFG3, 0x80 },
    	{ ADCX140_CH7_CFG4, 0x00 },
    	{ ADCX140_CH8_CFG2, 0xc9 },
    	{ ADCX140_CH8_CFG3, 0x80 },
    	{ ADCX140_CH8_CFG4, 0x00 },
    	{ ADCX140_DSP_CFG0, 0x01 },
    	{ ADCX140_DSP_CFG1, 0x40 },
    	{ ADCX140_DRE_CFG0, 0x7b },
    	{ ADCX140_AGC_CFG0, 0xe7 },
    	{ ADCX140_IN_CH_EN, 0xf0 },
    	{ ADCX140_ASI_OUT_CH_EN, 0x00 },
    	{ ADCX140_PWR_CFG, 0x00 },
    	{ ADCX140_DEV_STS0, 0x00 },
    	{ ADCX140_DEV_STS1, 0x80 },
    };
    
    static const struct regmap_range_cfg adcx140_ranges[] = {
    	{
    		.range_min = 0,
    		.range_max = 12 * 128,
    		.selector_reg = ADCX140_PAGE_SELECT,
    		.selector_mask = 0xff,
    		.selector_shift = 0,
    		.window_start = 0,
    		.window_len = 128,
    	},
    };
    
    static bool adcx140_volatile(struct device *dev, unsigned int reg)
    {
    	switch (reg) {
    	case ADCX140_SW_RESET:
    	case ADCX140_DEV_STS0:
    	case ADCX140_DEV_STS1:
    	case ADCX140_ASI_STS:
    		return true;
    	default:
    		return false;
    	}
    }
    
    static const struct regmap_config adcx140_i2c_regmap = {
    	.reg_bits = 8,
    	.val_bits = 8,
    	.reg_defaults = adcx140_reg_defaults,
    	.num_reg_defaults = ARRAY_SIZE(adcx140_reg_defaults),
    	.cache_type = REGCACHE_FLAT,
    	.ranges = adcx140_ranges,
    	.num_ranges = ARRAY_SIZE(adcx140_ranges),
    	.max_register = 12 * 128,
    	.volatile_reg = adcx140_volatile,
    };
    
    /* Digital Volume control. From -100 to 27 dB in 0.5 dB steps */
    static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10050, 50, 0);
    
    /* ADC gain. From 0 to 42 dB in 1 dB steps */
    static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
    
    /* DRE Level. From -12 dB to -66 dB in 1 dB steps */
    static DECLARE_TLV_DB_SCALE(dre_thresh_tlv, -6600, 100, 0);
    /* DRE Max Gain. From 2 dB to 26 dB in 2 dB steps */
    static DECLARE_TLV_DB_SCALE(dre_gain_tlv, 200, 200, 0);
    
    /* AGC Level. From -6 dB to -36 dB in 2 dB steps */
    static DECLARE_TLV_DB_SCALE(agc_thresh_tlv, -3600, 200, 0);
    /* AGC Max Gain. From 3 dB to 42 dB in 3 dB steps */
    static DECLARE_TLV_DB_SCALE(agc_gain_tlv, 300, 300, 0);
    
    static const char * const decimation_filter_text[] = {
    	"Linear Phase", "Low Latency", "Ultra-low Latency"
    };
    
    static SOC_ENUM_SINGLE_DECL(decimation_filter_enum, ADCX140_DSP_CFG0, 4,
    			    decimation_filter_text);
    
    static const struct snd_kcontrol_new decimation_filter_controls[] = {
    	SOC_DAPM_ENUM("Decimation Filter", decimation_filter_enum),
    };
    
    static const char * const pdmclk_text[] = {
    	"2.8224 MHz", "1.4112 MHz", "705.6 kHz", "5.6448 MHz"
    };
    
    static SOC_ENUM_SINGLE_DECL(pdmclk_select_enum, ADCX140_PDMCLK_CFG, 0,
    			    pdmclk_text);
    
    static const struct snd_kcontrol_new pdmclk_div_controls[] = {
    	SOC_DAPM_ENUM("PDM Clk Divider Select", pdmclk_select_enum),
    };
    
    static const char * const resistor_text[] = {
    	"2.5 kOhm", "10 kOhm", "20 kOhm"
    };
    
    static SOC_ENUM_SINGLE_DECL(in1_resistor_enum, ADCX140_CH1_CFG0, 2,
    			    resistor_text);
    static SOC_ENUM_SINGLE_DECL(in2_resistor_enum, ADCX140_CH2_CFG0, 2,
    			    resistor_text);
    static SOC_ENUM_SINGLE_DECL(in3_resistor_enum, ADCX140_CH3_CFG0, 2,
    			    resistor_text);
    static SOC_ENUM_SINGLE_DECL(in4_resistor_enum, ADCX140_CH4_CFG0, 2,
    			    resistor_text);
    
    static const struct snd_kcontrol_new in1_resistor_controls[] = {
    	SOC_DAPM_ENUM("CH1 Resistor Select", in1_resistor_enum),
    };
    static const struct snd_kcontrol_new in2_resistor_controls[] = {
    	SOC_DAPM_ENUM("CH2 Resistor Select", in2_resistor_enum),
    };
    static const struct snd_kcontrol_new in3_resistor_controls[] = {
    	SOC_DAPM_ENUM("CH3 Resistor Select", in3_resistor_enum),
    };
    static const struct snd_kcontrol_new in4_resistor_controls[] = {
    	SOC_DAPM_ENUM("CH4 Resistor Select", in4_resistor_enum),
    };
    
    /* Analog/Digital Selection */
    static const char * const adcx140_mic_sel_text[] = {"Analog", "Line In", "Digital"};
    static const char * const adcx140_analog_sel_text[] = {"Analog", "Line In"};
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic1p_enum,
    			    ADCX140_CH1_CFG0, 5,
    			    adcx140_mic_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic1p_control =
    SOC_DAPM_ENUM("MIC1P MUX", adcx140_mic1p_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic1_analog_enum,
    			    ADCX140_CH1_CFG0, 7,
    			    adcx140_analog_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic1_analog_control =
    SOC_DAPM_ENUM("MIC1 Analog MUX", adcx140_mic1_analog_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic1m_enum,
    			    ADCX140_CH1_CFG0, 5,
    			    adcx140_mic_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic1m_control =
    SOC_DAPM_ENUM("MIC1M MUX", adcx140_mic1m_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic2p_enum,
    			    ADCX140_CH2_CFG0, 5,
    			    adcx140_mic_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic2p_control =
    SOC_DAPM_ENUM("MIC2P MUX", adcx140_mic2p_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic2_analog_enum,
    			    ADCX140_CH2_CFG0, 7,
    			    adcx140_analog_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic2_analog_control =
    SOC_DAPM_ENUM("MIC2 Analog MUX", adcx140_mic2_analog_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic2m_enum,
    			    ADCX140_CH2_CFG0, 5,
    			    adcx140_mic_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic2m_control =
    SOC_DAPM_ENUM("MIC2M MUX", adcx140_mic2m_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic3p_enum,
    			    ADCX140_CH3_CFG0, 5,
    			    adcx140_mic_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic3p_control =
    SOC_DAPM_ENUM("MIC3P MUX", adcx140_mic3p_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic3_analog_enum,
    			    ADCX140_CH3_CFG0, 7,
    			    adcx140_analog_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic3_analog_control =
    SOC_DAPM_ENUM("MIC3 Analog MUX", adcx140_mic3_analog_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic3m_enum,
    			    ADCX140_CH3_CFG0, 5,
    			    adcx140_mic_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic3m_control =
    SOC_DAPM_ENUM("MIC3M MUX", adcx140_mic3m_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic4p_enum,
    			    ADCX140_CH4_CFG0, 5,
    			    adcx140_mic_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic4p_control =
    SOC_DAPM_ENUM("MIC4P MUX", adcx140_mic4p_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic4_analog_enum,
    			    ADCX140_CH4_CFG0, 7,
    			    adcx140_analog_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic4_analog_control =
    SOC_DAPM_ENUM("MIC4 Analog MUX", adcx140_mic4_analog_enum);
    
    static SOC_ENUM_SINGLE_DECL(adcx140_mic4m_enum,
    			    ADCX140_CH4_CFG0, 5,
    			    adcx140_mic_sel_text);
    
    static const struct snd_kcontrol_new adcx140_dapm_mic4m_control =
    SOC_DAPM_ENUM("MIC4M MUX", adcx140_mic4m_enum);
    
    static const struct snd_kcontrol_new adcx140_dapm_ch1_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 7, 1, 0);
    static const struct snd_kcontrol_new adcx140_dapm_ch2_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 6, 1, 0);
    static const struct snd_kcontrol_new adcx140_dapm_ch3_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 5, 1, 0);
    static const struct snd_kcontrol_new adcx140_dapm_ch4_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 4, 1, 0);
    static const struct snd_kcontrol_new adcx140_dapm_ch5_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 3, 1, 0);
    static const struct snd_kcontrol_new adcx140_dapm_ch6_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 2, 1, 0);
    static const struct snd_kcontrol_new adcx140_dapm_ch7_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 1, 1, 0);
    static const struct snd_kcontrol_new adcx140_dapm_ch8_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_ASI_OUT_CH_EN, 0, 1, 0);
    
    static const struct snd_kcontrol_new adcx140_dapm_ch1_dre_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_CH1_CFG0, 0, 1, 0);
    static const struct snd_kcontrol_new adcx140_dapm_ch2_dre_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_CH2_CFG0, 0, 1, 0);
    static const struct snd_kcontrol_new adcx140_dapm_ch3_dre_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_CH3_CFG0, 0, 1, 0);
    static const struct snd_kcontrol_new adcx140_dapm_ch4_dre_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_CH4_CFG0, 0, 1, 0);
    
    static const struct snd_kcontrol_new adcx140_dapm_dre_en_switch =
    	SOC_DAPM_SINGLE("Switch", ADCX140_DSP_CFG1, 3, 1, 0);
    
    /* Output Mixer */
    static const struct snd_kcontrol_new adcx140_output_mixer_controls[] = {
    	SOC_DAPM_SINGLE("Digital CH1 Switch", 0, 0, 0, 0),
    	SOC_DAPM_SINGLE("Digital CH2 Switch", 0, 0, 0, 0),
    	SOC_DAPM_SINGLE("Digital CH3 Switch", 0, 0, 0, 0),
    	SOC_DAPM_SINGLE("Digital CH4 Switch", 0, 0, 0, 0),
    };
    
    static const struct snd_soc_dapm_widget adcx140_dapm_widgets[] = {
    	/* Analog Differential Inputs */
    	SND_SOC_DAPM_INPUT("MIC1P"),
    	SND_SOC_DAPM_INPUT("MIC1M"),
    	SND_SOC_DAPM_INPUT("MIC2P"),
    	SND_SOC_DAPM_INPUT("MIC2M"),
    	SND_SOC_DAPM_INPUT("MIC3P"),
    	SND_SOC_DAPM_INPUT("MIC3M"),
    	SND_SOC_DAPM_INPUT("MIC4P"),
    	SND_SOC_DAPM_INPUT("MIC4M"),
    
    	SND_SOC_DAPM_OUTPUT("CH1_OUT"),
    	SND_SOC_DAPM_OUTPUT("CH2_OUT"),
    	SND_SOC_DAPM_OUTPUT("CH3_OUT"),
    	SND_SOC_DAPM_OUTPUT("CH4_OUT"),
    	SND_SOC_DAPM_OUTPUT("CH5_OUT"),
    	SND_SOC_DAPM_OUTPUT("CH6_OUT"),
    	SND_SOC_DAPM_OUTPUT("CH7_OUT"),
    	SND_SOC_DAPM_OUTPUT("CH8_OUT"),
    
    	SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0,
    		&adcx140_output_mixer_controls[0],
    		ARRAY_SIZE(adcx140_output_mixer_controls)),
    
    	/* Input Selection to MIC_PGA */
    	SND_SOC_DAPM_MUX("MIC1P Input Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic1p_control),
    	SND_SOC_DAPM_MUX("MIC2P Input Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic2p_control),
    	SND_SOC_DAPM_MUX("MIC3P Input Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic3p_control),
    	SND_SOC_DAPM_MUX("MIC4P Input Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic4p_control),
    
    	/* Input Selection to MIC_PGA */
    	SND_SOC_DAPM_MUX("MIC1 Analog Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic1_analog_control),
    	SND_SOC_DAPM_MUX("MIC2 Analog Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic2_analog_control),
    	SND_SOC_DAPM_MUX("MIC3 Analog Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic3_analog_control),
    	SND_SOC_DAPM_MUX("MIC4 Analog Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic4_analog_control),
    
    	SND_SOC_DAPM_MUX("MIC1M Input Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic1m_control),
    	SND_SOC_DAPM_MUX("MIC2M Input Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic2m_control),
    	SND_SOC_DAPM_MUX("MIC3M Input Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic3m_control),
    	SND_SOC_DAPM_MUX("MIC4M Input Mux", SND_SOC_NOPM, 0, 0,
    			 &adcx140_dapm_mic4m_control),
    
    	SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH1", SND_SOC_NOPM, 0, 0, NULL, 0),
    	SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH2", SND_SOC_NOPM, 0, 0, NULL, 0),
    	SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH3", SND_SOC_NOPM, 0, 0, NULL, 0),
    	SND_SOC_DAPM_PGA("MIC_GAIN_CTL_CH4", SND_SOC_NOPM, 0, 0, NULL, 0),
    
    	SND_SOC_DAPM_ADC("CH1_ADC", "CH1 Capture", ADCX140_IN_CH_EN, 7, 0),
    	SND_SOC_DAPM_ADC("CH2_ADC", "CH2 Capture", ADCX140_IN_CH_EN, 6, 0),
    	SND_SOC_DAPM_ADC("CH3_ADC", "CH3 Capture", ADCX140_IN_CH_EN, 5, 0),
    	SND_SOC_DAPM_ADC("CH4_ADC", "CH4 Capture", ADCX140_IN_CH_EN, 4, 0),
    
    	SND_SOC_DAPM_SWITCH("CH1_ASI_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch1_en_switch),
    	SND_SOC_DAPM_SWITCH("CH2_ASI_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch2_en_switch),
    	SND_SOC_DAPM_SWITCH("CH3_ASI_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch3_en_switch),
    	SND_SOC_DAPM_SWITCH("CH4_ASI_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch4_en_switch),
    
    	SND_SOC_DAPM_SWITCH("CH5_ASI_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch5_en_switch),
    	SND_SOC_DAPM_SWITCH("CH6_ASI_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch6_en_switch),
    	SND_SOC_DAPM_SWITCH("CH7_ASI_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch7_en_switch),
    	SND_SOC_DAPM_SWITCH("CH8_ASI_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch8_en_switch),
    
    	SND_SOC_DAPM_SWITCH("DRE_ENABLE", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_dre_en_switch),
    
    	SND_SOC_DAPM_SWITCH("CH1_DRE_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch1_dre_en_switch),
    	SND_SOC_DAPM_SWITCH("CH2_DRE_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch2_dre_en_switch),
    	SND_SOC_DAPM_SWITCH("CH3_DRE_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch3_dre_en_switch),
    	SND_SOC_DAPM_SWITCH("CH4_DRE_EN", SND_SOC_NOPM, 0, 0,
    			    &adcx140_dapm_ch4_dre_en_switch),
    
    	SND_SOC_DAPM_MUX("IN1 Analog Mic Resistor", SND_SOC_NOPM, 0, 0,
    			in1_resistor_controls),
    	SND_SOC_DAPM_MUX("IN2 Analog Mic Resistor", SND_SOC_NOPM, 0, 0,
    			in2_resistor_controls),
    	SND_SOC_DAPM_MUX("IN3 Analog Mic Resistor", SND_SOC_NOPM, 0, 0,
    			in3_resistor_controls),
    	SND_SOC_DAPM_MUX("IN4 Analog Mic Resistor", SND_SOC_NOPM, 0, 0,
    			in4_resistor_controls),
    
    	SND_SOC_DAPM_MUX("PDM Clk Div Select", SND_SOC_NOPM, 0, 0,
    			pdmclk_div_controls),
    
    	SND_SOC_DAPM_MUX("Decimation Filter", SND_SOC_NOPM, 0, 0,
    			decimation_filter_controls),
    };
    
    static const struct snd_soc_dapm_route adcx140_audio_map[] = {
    	/* Outputs */
    	{"CH1_OUT", NULL, "Output Mixer"},
    	{"CH2_OUT", NULL, "Output Mixer"},
    	{"CH3_OUT", NULL, "Output Mixer"},
    	{"CH4_OUT", NULL, "Output Mixer"},
    
    	{"CH1_ASI_EN", "Switch", "CH1_ADC"},
    	{"CH2_ASI_EN", "Switch", "CH2_ADC"},
    	{"CH3_ASI_EN", "Switch", "CH3_ADC"},
    	{"CH4_ASI_EN", "Switch", "CH4_ADC"},
    
    	{"CH5_ASI_EN", "Switch", "CH5_OUT"},
    	{"CH6_ASI_EN", "Switch", "CH6_OUT"},
    	{"CH7_ASI_EN", "Switch", "CH7_OUT"},
    	{"CH8_ASI_EN", "Switch", "CH8_OUT"},
    
    	{"Decimation Filter", "Linear Phase", "DRE_ENABLE"},
    	{"Decimation Filter", "Low Latency", "DRE_ENABLE"},
    	{"Decimation Filter", "Ultra-low Latency", "DRE_ENABLE"},
    
    	{"DRE_ENABLE", "Switch", "CH1_DRE_EN"},
    	{"DRE_ENABLE", "Switch", "CH2_DRE_EN"},
    	{"DRE_ENABLE", "Switch", "CH3_DRE_EN"},
    	{"DRE_ENABLE", "Switch", "CH4_DRE_EN"},
    
    	{"CH1_DRE_EN", "Switch", "CH1_ADC"},
    	{"CH2_DRE_EN", "Switch", "CH2_ADC"},
    	{"CH3_DRE_EN", "Switch", "CH3_ADC"},
    	{"CH4_DRE_EN", "Switch", "CH4_ADC"},
    
    	/* Mic input */
    	{"CH1_ADC", NULL, "MIC_GAIN_CTL_CH1"},
    	{"CH2_ADC", NULL, "MIC_GAIN_CTL_CH2"},
    	{"CH3_ADC", NULL, "MIC_GAIN_CTL_CH3"},
    	{"CH4_ADC", NULL, "MIC_GAIN_CTL_CH4"},
    
    	{"MIC_GAIN_CTL_CH1", NULL, "IN1 Analog Mic Resistor"},
    	{"MIC_GAIN_CTL_CH1", NULL, "IN1 Analog Mic Resistor"},
    	{"MIC_GAIN_CTL_CH2", NULL, "IN2 Analog Mic Resistor"},
    	{"MIC_GAIN_CTL_CH2", NULL, "IN2 Analog Mic Resistor"},
    	{"MIC_GAIN_CTL_CH3", NULL, "IN3 Analog Mic Resistor"},
    	{"MIC_GAIN_CTL_CH3", NULL, "IN3 Analog Mic Resistor"},
    	{"MIC_GAIN_CTL_CH4", NULL, "IN4 Analog Mic Resistor"},
    	{"MIC_GAIN_CTL_CH4", NULL, "IN4 Analog Mic Resistor"},
    
    	{"IN1 Analog Mic Resistor", "2.5 kOhm", "MIC1P Input Mux"},
    	{"IN1 Analog Mic Resistor", "10 kOhm", "MIC1P Input Mux"},
    	{"IN1 Analog Mic Resistor", "20 kOhm", "MIC1P Input Mux"},
    
    	{"IN1 Analog Mic Resistor", "2.5 kOhm", "MIC1M Input Mux"},
    	{"IN1 Analog Mic Resistor", "10 kOhm", "MIC1M Input Mux"},
    	{"IN1 Analog Mic Resistor", "20 kOhm", "MIC1M Input Mux"},
    
    	{"IN2 Analog Mic Resistor", "2.5 kOhm", "MIC2P Input Mux"},
    	{"IN2 Analog Mic Resistor", "10 kOhm", "MIC2P Input Mux"},
    	{"IN2 Analog Mic Resistor", "20 kOhm", "MIC2P Input Mux"},
    
    	{"IN2 Analog Mic Resistor", "2.5 kOhm", "MIC2M Input Mux"},
    	{"IN2 Analog Mic Resistor", "10 kOhm", "MIC2M Input Mux"},
    	{"IN2 Analog Mic Resistor", "20 kOhm", "MIC2M Input Mux"},
    
    	{"IN3 Analog Mic Resistor", "2.5 kOhm", "MIC3P Input Mux"},
    	{"IN3 Analog Mic Resistor", "10 kOhm", "MIC3P Input Mux"},
    	{"IN3 Analog Mic Resistor", "20 kOhm", "MIC3P Input Mux"},
    
    	{"IN3 Analog Mic Resistor", "2.5 kOhm", "MIC3M Input Mux"},
    	{"IN3 Analog Mic Resistor", "10 kOhm", "MIC3M Input Mux"},
    	{"IN3 Analog Mic Resistor", "20 kOhm", "MIC3M Input Mux"},
    
    	{"IN4 Analog Mic Resistor", "2.5 kOhm", "MIC4P Input Mux"},
    	{"IN4 Analog Mic Resistor", "10 kOhm", "MIC4P Input Mux"},
    	{"IN4 Analog Mic Resistor", "20 kOhm", "MIC4P Input Mux"},
    
    	{"IN4 Analog Mic Resistor", "2.5 kOhm", "MIC4M Input Mux"},
    	{"IN4 Analog Mic Resistor", "10 kOhm", "MIC4M Input Mux"},
    	{"IN4 Analog Mic Resistor", "20 kOhm", "MIC4M Input Mux"},
    
    	{"PDM Clk Div Select", "2.8224 MHz", "MIC1P Input Mux"},
    	{"PDM Clk Div Select", "1.4112 MHz", "MIC1P Input Mux"},
    	{"PDM Clk Div Select", "705.6 kHz", "MIC1P Input Mux"},
    	{"PDM Clk Div Select", "5.6448 MHz", "MIC1P Input Mux"},
    
    	{"MIC1 Analog Mux", "Line In", "MIC1P"},
    	{"MIC2 Analog Mux", "Line In", "MIC2P"},
    	{"MIC3 Analog Mux", "Line In", "MIC3P"},
    	{"MIC4 Analog Mux", "Line In", "MIC4P"},
    
    	{"MIC1P Input Mux", "Analog", "MIC1P"},
    	{"MIC1M Input Mux", "Analog", "MIC1M"},
    	{"MIC2P Input Mux", "Analog", "MIC2P"},
    	{"MIC2M Input Mux", "Analog", "MIC2M"},
    	{"MIC3P Input Mux", "Analog", "MIC3P"},
    	{"MIC3M Input Mux", "Analog", "MIC3M"},
    	{"MIC4P Input Mux", "Analog", "MIC4P"},
    	{"MIC4M Input Mux", "Analog", "MIC4M"},
    };
    
    static const struct snd_kcontrol_new adcx140_snd_controls[] = {
    	SOC_SINGLE_TLV("ALSEAMAR Analog CH1 Mic Gain Volume", ADCX140_CH1_CFG1, 2, 42, 0,
    			adc_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR Analog CH2 Mic Gain Volume", ADCX140_CH2_CFG1, 2, 42, 0,
    			adc_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR Analog CH3 Mic Gain Volume", ADCX140_CH3_CFG1, 2, 42, 0,
    			adc_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR Analog CH4 Mic Gain Volume", ADCX140_CH4_CFG1, 2, 42, 0,
    			adc_tlv),
    
    	SOC_SINGLE_TLV("ALSEAMAR DRE Threshold", ADCX140_DRE_CFG0, 4, 9, 0,
    		       dre_thresh_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR DRE Max Gain", ADCX140_DRE_CFG0, 0, 12, 0,
    		       dre_gain_tlv),
    
    	SOC_SINGLE_TLV("ALSEAMAR AGC Threshold", ADCX140_AGC_CFG0, 4, 15, 0,
    		       agc_thresh_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR AGC Max Gain", ADCX140_AGC_CFG0, 0, 13, 0,
    		       agc_gain_tlv),
    
    	SOC_SINGLE_TLV("ALSEAMAR Digital CH1 Out Volume", ADCX140_CH1_CFG2,
    			0, 0xff, 0, dig_vol_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR Digital CH2 Out Volume", ADCX140_CH2_CFG2,
    			0, 0xff, 0, dig_vol_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR Digital CH3 Out Volume", ADCX140_CH3_CFG2,
    			0, 0xff, 0, dig_vol_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR Digital CH4 Out Volume", ADCX140_CH4_CFG2,
    			0, 0xff, 0, dig_vol_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR Digital CH5 Out Volume", ADCX140_CH5_CFG2,
    			0, 0xff, 0, dig_vol_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR Digital CH6 Out Volume", ADCX140_CH6_CFG2,
    			0, 0xff, 0, dig_vol_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR Digital CH7 Out Volume", ADCX140_CH7_CFG2,
    			0, 0xff, 0, dig_vol_tlv),
    	SOC_SINGLE_TLV("ALSEAMAR Digital CH8 Out Volume", ADCX140_CH8_CFG2,
    			0, 0xff, 0, dig_vol_tlv),
    };
    
    static int adcx140_reset(struct adcx140_priv *adcx140)
    {
    	int ret = 0;
    
    	if (adcx140->gpio_reset) {
    		gpiod_direction_output(adcx140->gpio_reset, 0);
    		/* 8.4.1: wait for hw shutdown (25ms) + >= 1ms */
    		usleep_range(30000, 100000);
    		gpiod_direction_output(adcx140->gpio_reset, 1);
    	} else {
    		ret = regmap_write(adcx140->regmap, ADCX140_SW_RESET,
    				   ADCX140_RESET);
    	}
    
    	/* 8.4.2: wait >= 10 ms after entering sleep mode. */
    	usleep_range(10000, 100000);
    
    	return ret;
    }
    
    static int adcx140_hw_params(struct snd_pcm_substream *substream,
    			     struct snd_pcm_hw_params *params,
    			     struct snd_soc_dai *dai)
    {
    	struct snd_soc_codec *codec = dai->codec;
    	u8 data = 0;
    
    	switch (params_width(params)) {
    	case 16:
    		data = ADCX140_16_BIT_WORD;
    		break;
    	case 20:
    		data = ADCX140_20_BIT_WORD;
    		break;
    	case 24:
    		data = ADCX140_24_BIT_WORD;
    		break;
    	case 32:
    		data = ADCX140_32_BIT_WORD;
    		break;
    	default:
    		dev_err(codec->dev, "%s: Unsupported width %d\n",
    			__func__, params_width(params));
    		return -EINVAL;
    	}
    
    	snd_soc_update_bits(codec, ADCX140_ASI_CFG0,
    			    ADCX140_WORD_LEN_MSK, data);
    
    	return 0;
    }
    
    static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai,
    			       unsigned int fmt)
    {
    	struct snd_soc_codec *codec = codec_dai->codec;
    	struct adcx140_priv *adcx140 = snd_soc_codec_get_drvdata(codec);
    	u8 iface_reg1 = 0;
    	u8 iface_reg2 = 0;
    	int offset = 0;
    	int width = adcx140->slot_width;
    
    	/* set master/slave audio interface */
    	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
    	case SND_SOC_DAIFMT_CBM_CFM:
    		iface_reg2 |= ADCX140_BCLK_FSYNC_MASTER;
    		break;
    	case SND_SOC_DAIFMT_CBS_CFS:
    		break;
    	case SND_SOC_DAIFMT_CBS_CFM:
    	case SND_SOC_DAIFMT_CBM_CFS:
    	default:
    		dev_err(codec->dev, "Invalid DAI master/slave interface\n");
    		return -EINVAL;
    	}
    
    	/* signal polarity */
    	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
    	case SND_SOC_DAIFMT_NB_IF:
    		iface_reg1 |= ADCX140_FSYNCINV_BIT;
    		break;
    	case SND_SOC_DAIFMT_IB_IF:
    		iface_reg1 |= ADCX140_BCLKINV_BIT | ADCX140_FSYNCINV_BIT;
    		break;
    	case SND_SOC_DAIFMT_IB_NF:
    		iface_reg1 |= ADCX140_BCLKINV_BIT;
    		break;
    	case SND_SOC_DAIFMT_NB_NF:
    		break;
    	default:
    		dev_err(codec->dev, "Invalid DAI clock signal polarity\n");
    		return -EINVAL;
    	}
    
    	/* interface format */
    	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    	case SND_SOC_DAIFMT_I2S:
    		iface_reg1 |= ADCX140_I2S_MODE_BIT;
    		break;
    	case SND_SOC_DAIFMT_LEFT_J:
    		iface_reg1 |= ADCX140_LEFT_JUST_BIT;
    		break;
    	case SND_SOC_DAIFMT_DSP_A:
    		offset += (adcx140->tdm_delay * width + 1);
    		break;
    	case SND_SOC_DAIFMT_DSP_B:
    		offset += adcx140->tdm_delay * width;
    		break;
    	default:
    		dev_err(codec->dev, "Invalid DAI interface format\n");
    		return -EINVAL;
    	}
    
    	adcx140->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
    
    	snd_soc_update_bits(codec, ADCX140_ASI_CFG0,
    				      ADCX140_FSYNCINV_BIT |
    				      ADCX140_BCLKINV_BIT |
    				      ADCX140_ASI_FORMAT_MSK,
    				      iface_reg1);
    	snd_soc_update_bits(codec, ADCX140_MST_CFG0,
    				      ADCX140_BCLK_FSYNC_MASTER, iface_reg2);
    
    	/* Configure data offset */
    	snd_soc_update_bits(codec, ADCX140_ASI_CFG1,
    				      ADCX140_TX_OFFSET_MASK, offset);
    
    	dev_err(codec->dev, "Set DAI format done with format %x\n", fmt);
    
    	return 0;
    }
    
    static int adcx140_set_dai_tdm_slot(struct snd_soc_dai *codec_dai,
    				  unsigned int tx_mask, unsigned int rx_mask,
    				  int slots, int slot_width)
    {
    	struct snd_soc_codec *codec = codec_dai->codec;
    	struct adcx140_priv *adcx140 = snd_soc_codec_get_drvdata(codec);
    	unsigned int lsb;
    
    	/* TDM based on DSP mode requires slots to be adjacent */
    	lsb = __ffs(tx_mask);
    	if ((lsb + 1) != __fls(tx_mask)) {
    		dev_err(codec->dev, "Invalid mask, slots must be adjacent\n");
    		return -EINVAL;
    	}
    
    	switch (slot_width) {
    	case 16:
    	case 20:
    	case 24:
    	case 32:
    		break;
    	default:
    		dev_err(codec->dev, "Unsupported slot width %d\n", slot_width);
    		return -EINVAL;
    	}
    
    	adcx140->tdm_delay = lsb;
    	adcx140->slot_width = slot_width;
    	
    	dev_err(codec->dev, "Set DAI TDM done : %d\n", slot_width);
    
    	return 0;
    }
    
    static const struct snd_soc_dai_ops adcx140_dai_ops = {
    	.hw_params	= adcx140_hw_params,
    	.set_fmt	= adcx140_set_dai_fmt,
    	.set_tdm_slot	= adcx140_set_dai_tdm_slot,
    };
    
    static int adcx140_configure_gpo(struct adcx140_priv *adcx140)
    {
    	u32 gpo_outputs[ADCX140_NUM_GPOS];
    	u32 gpo_output_val = 0;
    	int ret;
    	int i;
    
    	for (i = 0; i < ADCX140_NUM_GPOS; i++) {
    		ret = device_property_read_u32_array(adcx140->dev,
    						     gpo_config_names[i],
    						     gpo_outputs,
    						     ADCX140_NUM_GPO_CFGS);
    		if (ret)
    			continue;
    
    		if (gpo_outputs[0] > ADCX140_GPO_CFG_MAX) {
    			dev_err(adcx140->dev, "GPO%d config out of range\n", i + 1);
    			return -EINVAL;
    		}
    
    		if (gpo_outputs[1] > ADCX140_GPO_DRV_MAX) {
    			dev_err(adcx140->dev, "GPO%d drive out of range\n", i + 1);
    			return -EINVAL;
    		}
    
    		gpo_output_val = gpo_outputs[0] << ADCX140_GPO_SHIFT |
    				 gpo_outputs[1];
    		ret = regmap_write(adcx140->regmap, ADCX140_GPO_CFG0 + i,
    				   gpo_output_val);
    		if (ret)
    			return ret;
    	}
    
    	return 0;
    
    }
    
    static int adcx140_codec_probe(struct snd_soc_codec *codec)
    {
    	struct adcx140_priv *adcx140 = snd_soc_codec_get_drvdata(codec);
    	int sleep_cfg_val = ADCX140_WAKE_DEV;
    	u32 bias_source;
    	u32 vref_source;
    	u8 bias_cfg;
    	u32 pdm_count;
    	u32 pdm_edges[ADCX140_NUM_PDM_EDGES];
    	u32 pdm_edge_val = 0;
    	u32 gpi_count;
    	u32 gpi_inputs[ADCX140_NUM_GPI_PINS];
    	u32 gpi_input_val = 0;
    	int i;
    	int ret;
    
    	ret = device_property_read_u32(adcx140->dev, "ti,mic-bias-source",
    				      &bias_source);
    	if (ret)
    		bias_source = ADCX140_MIC_BIAS_VAL_VREF;
    
    	if (bias_source > ADCX140_MIC_BIAS_VAL_AVDD) {
    		dev_err(adcx140->dev, "Mic Bias source value is invalid\n");
    		return -EINVAL;
    	}
    
    	ret = device_property_read_u32(adcx140->dev, "ti,vref-source",
    				      &vref_source);
    	if (ret)
    		vref_source = ADCX140_MIC_BIAS_VREF_275V;
    
    	if (vref_source > ADCX140_MIC_BIAS_VREF_1375V) {
    		dev_err(adcx140->dev, "Mic Bias source value is invalid\n");
    		return -EINVAL;
    	}
    
    	bias_cfg = bias_source << ADCX140_MIC_BIAS_SHIFT | vref_source;
    
    	ret = adcx140_reset(adcx140);
    	if (ret)
    	{
    		dev_err(adcx140->dev, "Error after ADC reset %d\n", ret);
    		goto out;
    	}
    
    	if (adcx140->supply_areg == NULL)
    		sleep_cfg_val |= ADCX140_AREG_INTERNAL;
    
    	ret = regmap_write(adcx140->regmap, ADCX140_SLEEP_CFG, sleep_cfg_val);
    	if (ret) {
    		dev_err(adcx140->dev, "setting sleep config failed %d\n", ret);
    		goto out;
    	}
    
    	/* 8.4.3: Wait >= 1ms after entering active mode. */
    	usleep_range(1000, 100000);
    
    	device_property_read_u32(adcx140->dev,
    					      "ti,pdm-edge-select", &pdm_count);
    	if (pdm_count <= ADCX140_NUM_PDM_EDGES && pdm_count > 0) {
    		ret = device_property_read_u32_array(adcx140->dev,
    						     "ti,pdm-edge-select",
    						     pdm_edges, pdm_count);
    		if (ret)
    		{
    			dev_err(adcx140->dev, "Error after read ti,pdm-edge-select %d\n", ret);
    			return ret;
    		}
    
    		for (i = 0; i < pdm_count; i++)
    			pdm_edge_val |= pdm_edges[i] << (ADCX140_PDM_EDGE_SHIFT - i);
    
    		ret = regmap_write(adcx140->regmap, ADCX140_PDM_CFG,
    				   pdm_edge_val);
    		if (ret)
    		{
    			dev_err(adcx140->dev, "Error after regmap_write pdm conf %d\n", ret);
    			return ret;
    		}
    	}
    
    	device_property_read_u32(adcx140->dev, "ti,gpi-config", &gpi_count);
    	if (gpi_count <= ADCX140_NUM_GPI_PINS && gpi_count > 0) {
    		ret = device_property_read_u32_array(adcx140->dev,
    						     "ti,gpi-config",
    						     gpi_inputs, gpi_count);
    		if (ret)
    		{
    			dev_err(adcx140->dev, "Error after read ti,gpi-config %d\n", ret);
    			return ret;
    		}
    
    		gpi_input_val = gpi_inputs[ADCX140_GPI1_INDEX] << ADCX140_GPI_SHIFT |
    				gpi_inputs[ADCX140_GPI2_INDEX];
    
    		ret = regmap_write(adcx140->regmap, ADCX140_GPI_CFG0,
    				   gpi_input_val);
    		if (ret)
    		{
    			dev_err(adcx140->dev, "Error after regmap_write gpi-config0 %d\n", ret);
    			return ret;
    		}
    
    		gpi_input_val = gpi_inputs[ADCX140_GPI3_INDEX] << ADCX140_GPI_SHIFT |
    				gpi_inputs[ADCX140_GPI4_INDEX];
    
    		ret = regmap_write(adcx140->regmap, ADCX140_GPI_CFG1,
    				   gpi_input_val);
    		if (ret)
    		{
    			dev_err(adcx140->dev, "Error after regmap_write gpi-config1 %d\n", ret);
    			return ret;
    		}
    	}
    
    	ret = adcx140_configure_gpo(adcx140);
    	if (ret)
    	{
    		dev_err(adcx140->dev, "Error after configure gpo %d\n", ret);
    		goto out;
    	}
    
    	ret = regmap_update_bits(adcx140->regmap, ADCX140_BIAS_CFG,
    				ADCX140_MIC_BIAS_VAL_MSK |
    				ADCX140_MIC_BIAS_VREF_MSK, bias_cfg);
    	if (ret)
    		dev_err(adcx140->dev, "setting MIC bias failed %d\n", ret);
    out:
    	return ret;
    }
    
    static int adcx140_set_bias_level(struct snd_soc_codec *codec,
    				  enum snd_soc_bias_level level)
    {
    	struct adcx140_priv *adcx140 = snd_soc_codec_get_drvdata(codec);
    	int pwr_cfg = 0;
    
    	switch (level) {
    	case SND_SOC_BIAS_ON:
    	case SND_SOC_BIAS_PREPARE:
    	case SND_SOC_BIAS_STANDBY:
    		pwr_cfg = ADCX140_PWR_CFG_BIAS_PDZ | ADCX140_PWR_CFG_PLL_PDZ |
    			  ADCX140_PWR_CFG_ADC_PDZ;
    		break;
    	case SND_SOC_BIAS_OFF:
    		pwr_cfg = 0x0;
    		break;
    	}
    
    	return regmap_write(adcx140->regmap, ADCX140_PWR_CFG, pwr_cfg);
    }
    
    /*static const struct snd_soc_component_driver soc_codec_driver_adcx140 = {
    	.probe			= adcx140_codec_probe,
    	.set_bias_level		= adcx140_set_bias_level,
    	.controls		= adcx140_snd_controls,
    	.num_controls		= ARRAY_SIZE(adcx140_snd_controls),
    	.dapm_widgets		= adcx140_dapm_widgets,
    	.num_dapm_widgets	= ARRAY_SIZE(adcx140_dapm_widgets),
    	.dapm_routes		= adcx140_audio_map,
    	.num_dapm_routes	= ARRAY_SIZE(adcx140_audio_map),
    	.suspend_bias_off	= 1,
    	.idle_bias_on		= 0,
    	.use_pmdown_time	= 1,
    	.endianness		= 1,
    	.non_legacy_dai_naming	= 1,
    };*/
    
    static const struct snd_soc_codec_driver soc_codec_driver_adcx140 = {
    	.probe			    = adcx140_codec_probe,
    	.set_bias_level     = adcx140_set_bias_level,
    	.suspend_bias_off	= true,
    	.idle_bias_off		= true,
    	.ignore_pmdown_time	= false,
    /*	.endianness		    = true,*/
    /*	.non_legacy_dai_naming	= true,*/
    	.component_driver = {
    		.controls		    = adcx140_snd_controls,
    		.num_controls		= ARRAY_SIZE(adcx140_snd_controls),
    		.dapm_widgets		= adcx140_dapm_widgets,
    		.num_dapm_widgets	= ARRAY_SIZE(adcx140_dapm_widgets),
    		.dapm_routes		= adcx140_audio_map,
    		.num_dapm_routes	= ARRAY_SIZE(adcx140_audio_map),
    	},
    };
    
    static struct snd_soc_dai_driver adcx140_dai_driver[] = {
    	{
    		.name = "tlv320adcx140-codec",
    		.capture = {
    			.stream_name	 = "Capture",
    			.channels_min	 = 2,
    			.channels_max	 = ADCX140_MAX_CHANNELS,
    			.rates		 = ADCX140_RATES,
    			.formats	 = ADCX140_FORMATS,
    		},
    		.ops = &adcx140_dai_ops,
    		.symmetric_rates = 1,
    	}
    };
    
    static const struct of_device_id tlv320adcx140_of_match[] = {
    	{ .compatible = "ti,tlv320adc3140" },
    	{ .compatible = "ti,tlv320adc5140" },
    	{ .compatible = "ti,tlv320adc6140" },
    	{},
    };
    MODULE_DEVICE_TABLE(of, tlv320adcx140_of_match);
    
    static int adcx140_i2c_probe(struct i2c_client *i2c,
    			     const struct i2c_device_id *id)
    {
    	struct adcx140_priv *adcx140;
    	int ret;
    
    	adcx140 = devm_kzalloc(&i2c->dev, sizeof(*adcx140), GFP_KERNEL);
    	if (!adcx140)
    		return -ENOMEM;
    
    	adcx140->dev = &i2c->dev;
    
    	adcx140->gpio_reset = devm_gpiod_get_optional(adcx140->dev,
    						      "reset", GPIOD_OUT_LOW);
    	if (IS_ERR(adcx140->gpio_reset))
    		dev_info(&i2c->dev, "Reset GPIO not defined\n");
    
    	adcx140->supply_areg = devm_regulator_get_optional(adcx140->dev,
    							   "areg");
    	if (IS_ERR(adcx140->supply_areg)) {
    		if (PTR_ERR(adcx140->supply_areg) == -EPROBE_DEFER)
    			return -EPROBE_DEFER;
    
    		adcx140->supply_areg = NULL;
    	} else {
    		ret = regulator_enable(adcx140->supply_areg);
    		if (ret) {
    			dev_err(adcx140->dev, "Failed to enable areg\n");
    			return ret;
    		}
    	}
    
    	adcx140->regmap = devm_regmap_init_i2c(i2c, &adcx140_i2c_regmap);
    	if (IS_ERR(adcx140->regmap)) {
    		ret = PTR_ERR(adcx140->regmap);
    		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
    			ret);
    		return ret;
    	}
    
    	i2c_set_clientdata(i2c, adcx140);
    
    	return snd_soc_register_codec(&i2c->dev,
    					       &soc_codec_driver_adcx140,
    					       adcx140_dai_driver, 1);
    }
    
    static const struct i2c_device_id adcx140_i2c_id[] = {
    	{ "tlv320adc3140", 0 },
    	{ "tlv320adc5140", 1 },
    	{ "tlv320adc6140", 2 },
    	{}
    };
    MODULE_DEVICE_TABLE(i2c, adcx140_i2c_id);
    
    static struct i2c_driver adcx140_i2c_driver = {
    	.driver = {
    		.name	= "tlv320adcx140-codec",
    		.of_match_table = of_match_ptr(tlv320adcx140_of_match),
    	},
    	.probe		= adcx140_i2c_probe,
    	.id_table	= adcx140_i2c_id,
    };
    module_i2c_driver(adcx140_i2c_driver);
    
    MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
    MODULE_DESCRIPTION("ASoC TLV320ADCX140 CODEC Driver");
    MODULE_LICENSE("GPL v2");
    

  • Since you have register the sound card, kind run following commands

    # ls /dev/snd

     # ls /sys/bus/i2c/devices/2-0038 

    2: i2c bus no,  38 is the hex-format 7-bit i2c address

     # cat /proc/asound/pcm

     # cat /proc/asound/cards

    One more thing, can you ass some log into adcx140_i2c_probe and adcx140_codec_probe, pls check whecher these codes have been called