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.

TLV320DAC3100: Unsupported frequency while playing audio

Part Number: TLV320DAC3100
Other Parts Discussed in Thread: TEST, TLV320AIC3120EVM-U

Hi , 

I am working on L5.4.70 kernel on i.MX8 M Mini processor . We are using tlv320dac100 codec module.

 

when I gave : aplay -l

Hardware device listed successfully -->

*** List of PLAYBACK Hardware Devices ***
card 0: imxspdif [imx-spdif], device 0: S/PDIF PCM snd-soc-dummy-dai-0 [S/PDIF PCM snd-soc-dummy-dai-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: Output [Audio Output], device 0: 30050000.sai-tlv320dac31xx-hifi tlv320dac31xx-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0

When I am trying to play audio[earphone ] with 

aplay -D plughw:1,0 /unit_tests/Audio/sample_22_frames.mp3

I am getting following error :

 

root@iWave-G39H:~# aplay -D plughw:1,0 /unit_tests/Audio/sample_22_frames.mp3
Playing raw data '/unit_tests/Audio/sample_22_frames.mp3' : Unsigned 8 bit, Rate 8000 Hz, Mono

[ 3483.772935] tlv320aic31xx-codec 1-0018: aic31xx_set_dai_sysclk: Unsupported frequency 208000
[ 3483.785232] asoc-simple-card sound-tlv320dac31: ASoC: machine hw_params failed: -22
aplay: set_params:1403: 
Unable to install hw params:
ACCESS: RW_INTERLEAVED
FORMAT: U8 SUBFORMAT: STD
SAMPLE_BITS: 8 FRAME_BITS: 8
CHANNELS: 1
RATE: 8000
PERIOD_TIME: 125000
PERIOD_SIZE: 1000
PERIOD_BYTES: 1000
PERIODS: 4
BUFFER_TIME: 500000
BUFFER_SIZE: 4000
BUFFER_BYTES: 4000
TICK_TIME: 0

[ 3483.946043] tlv320aic31xx-codec 1-0018: aic31xx_set_dai_sysclk: Unsupported frequency 0

 

Here I attached my dts tree ,

/ TLV amplifier /
sound-tlv320dac31 {
compatible = "simple-audio-card";
simple-audio-card,name = "Audio Output";
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&sound_codec>;
simple-audio-card,frame-master = <&sound_codec>;
/*simple-audio-card,mclk-fs=<256>;*/
simple-audio-card,widgets =
"Headphone", "Headphone Jack";
simple-audio-card,routing =
"Headphone Jack", "HPL",
"Headphone Jack", "HPR";
/* simple-audio-card,aux-devs = <&hpa1>;* /

simple-audio-card,cpu {
sound-dai = <&sai5>;
};

sound_codec: simple-audio-card,codec {
sound-dai = <&codec>;
/*clocks = <&clk IMX8MM_CLK_SAI5_ROOT>;*/
system-clock-frequency=<12000000>;
};
};

&sai5 {
#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai5>;
assigned-clocks = <&clk IMX8MM_CLK_SAI5>;
assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
assigned-clock-rates = <12000000>;
clocks = <&clk IMX8MM_CLK_SAI5_IPG>, <&clk IMX8MM_CLK_DUMMY>,
<&clk IMX8MM_CLK_SAI5_ROOT>, <&clk IMX8MM_CLK_DUMMY>,
<&clk IMX8MM_CLK_DUMMY>, <&clk IMX8MM_AUDIO_PLL1_OUT>,
<&clk IMX8MM_AUDIO_PLL2_OUT>;
clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3", "pll8k", "pll11k";
status = "okay";
};

 

codec: codec@18 {
compatible = "ti,tlv320dac3100";
pinctrl-names = "default";
/*pinctrl-0 = <&pinctrl_codec>;*/
reg = <0x18>;
#sound-dai-cells = <0>;
HPVDD-supply = <&reg_3p3v>;
SPRVDD-supply = <&reg_3p3v>;
SPLVDD-supply = <&reg_3p3v>;
AVDD-supply = <&reg_3p3v>;
IOVDD-supply = <&reg_3p3v>;
DVDD-supply = <&reg_1p8v>;
/*gpio-reset = <&gpio1 6 GPIO_ACTIVE_LOW>;*/   /* configured in the hardware */
status = "okay";
};

pinctrl_sai5: sai5grp { / SAI5: IOMUX Pin Configuration /
fsl,pins = <
MX8MM_IOMUXC_SAI5_MCLK_SAI5_MCLK 0xd6
MX8MM_IOMUXC_SAI5_RXD2_SAI5_TX_BCLK 0xd6
MX8MM_IOMUXC_SAI5_RXD1_SAI5_TX_SYNC 0xd6
MX8MM_IOMUXC_SAI5_RXD3_SAI5_TX_DATA0 0xd6
MX8MM_IOMUXC_SAI5_RXD0_SAI5_RX_DATA0 0xd6
>;
};

Here is some dmesg print 

dmesg | grep tlv
[ 3.676843] asoc-simple-card sound-tlv320dac31: tlv320dac31xx-hifi <-> 30050000.sai mapping ok
[ 3.689218] asoc-simple-card sound-tlv320dac31: ASoC: no DMI vendor name!
root@iWave-G39H:~# dmesg | grep sai
[ 3.663954] debugfs: Directory '30050000.sai' with parent 'Audio Output' already present!

Anything I am missing out in dts tree, why I am getting hardware parameter failed  and unsupported frequency error. Please help me in resolving this error 

 

Thanks in advance,

Regards,

Deeksha

  • Hi,

    We'll get our Linux expert to assist you.

    Regards.

  • Hi ,

    I wanted to add one more query , mclk is set through external oscillator to 26Mhz, How i can set this in dts file.

    If I set system clock frequency as 26MHz , module is giving unsupported frequency error while booting.

    Regards,

    Deeksha

  • Sure, we will look into it.

    Regards,

    Arash

  • Hi Deeksha,

    What are your system clock frequencies? Please notice it should match one of the settings from static const struct aic31xx_rate_divs aic31xx_divs[]

    I'm requesting feedback from driver expert regarding 26MHz as system clock frequency, will get further comments as soon as possible,

    Best regards,
    -Ivan Salazar
    Applications Engineer

  • Deeksha,

    Unsupported frequency error means there was no P divider result based on sys clk to match one of the settings from aic31xx_divs[].

    You may try adding this to the struct:

    {  13000000,    8000,   1,  6,  3803,   128,    3,  27, 128,    3,  27},

    This is specifically for 8k sample rate, if need a different sample rate the clock divs can be calculated accordignly.

    Best regards,
    -Ivan Salazar
    Applications Engineer

  • Hi,

    Thanks for your support .

    Now I am not getting unsupported frequency error.

    When I tried to play audio , am not hearing any sound from microphone.

    Here is my debug prints while playing audio and I attached dmesg and driver c file

    debug.txt
    [    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
    [    0.000000] Linux version 5.4.70+gfd7f722f444d (iwave@iwave) (gcc version 9.2.0 (GCC)) #28 SMP PREEMPT Fri Jan 21 14:51:52 IST 2022
    [    0.000000] Machine model: iW-G39H-i.MX8MM-SODIMM-2GB
    [    0.000000] efi: Getting EFI parameters from FDT:
    [    0.000000] efi: UEFI not found.
    [    0.000000] Reserved memory: created CMA memory pool at 0x0000000058000000, size 640 MiB
    [    0.000000] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000b8000000, size 0 MiB
    [    0.000000] OF: reserved mem: initialized node vdev0vring0@b8000000, compatible id shared-dma-pool
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000b8008000, size 0 MiB
    [    0.000000] OF: reserved mem: initialized node vdev0vring1@b8008000, compatible id shared-dma-pool
    [    0.000000] Reserved memory: created DMA memory pool at 0x00000000b8400000, size 1 MiB
    [    0.000000] OF: reserved mem: initialized node vdevbuffer@b8400000, compatible id shared-dma-pool
    [    0.000000] NUMA: No NUMA configuration found
    [    0.000000] NUMA: Faking a node at [mem 0x0000000040000000-0x00000000bfffffff]
    [    0.000000] NUMA: NODE_DATA [mem 0xbfbcd500-0xbfbcefff]
    [    0.000000] Zone ranges:
    [    0.000000]   DMA32    [mem 0x0000000040000000-0x00000000bfffffff]
    [    0.000000]   Normal   empty
    [    0.000000] Movable zone start for each node
    [    0.000000] Early memory node ranges
    [    0.000000]   node   0: [mem 0x0000000040000000-0x000000007fffffff]
    [    0.000000]   node   0: [mem 0x0000000081000000-0x00000000b7ffffff]
    [    0.000000]   node   0: [mem 0x00000000b8010000-0x00000000b80fefff]
    [    0.000000]   node   0: [mem 0x00000000b8100000-0x00000000b83fffff]
    [    0.000000]   node   0: [mem 0x00000000b8500000-0x00000000bfffffff]
    [    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x00000000bfffffff]
    [    0.000000] On node 0 totalpages: 519919
    [    0.000000]   DMA32 zone: 8192 pages used for memmap
    [    0.000000]   DMA32 zone: 0 pages reserved
    [    0.000000]   DMA32 zone: 519919 pages, LIFO batch:63
    [    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.1
    [    0.000000] percpu: Embedded 24 pages/cpu s58904 r8192 d31208 u98304
    [    0.000000] pcpu-alloc: s58904 r8192 d31208 u98304 alloc=24*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: ARM erratum 845719
    [    0.000000] CPU features: detected: GIC system register CPU interface
    [    0.000000] Speculative Store Bypass Disable mitigation not required
    [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 511727
    [    0.000000] Policy zone: DMA32
    [    0.000000] Kernel command line: console=ttymxc3,115200 root=/dev/mmcblk0p2 rootwait rw
    [    0.000000] Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes, linear)
    [    0.000000] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes, linear)
    [    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
    [    0.000000] Memory: 1354988K/2079676K available (16764K kernel code, 1282K rwdata, 6688K rodata, 2880K init, 1015K bss, 69328K reserved, 655360K 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 restricting CPUs from NR_CPUS=256 to nr_cpu_ids=4.
    [    0.000000] 	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: 128 SPIs implemented
    [    0.000000] GICv3: 0 Extended SPIs implemented
    [    0.000000] GICv3: Distributor has no Range Selector support
    [    0.000000] GICv3: 16 PPIs implemented
    [    0.000000] GICv3: no VLPI support, no direct LPI support
    [    0.000000] GICv3: CPU0: found redistributor 0 region 0:0x0000000038880000
    [    0.000000] ITS: No ITS available, not enabling LPIs
    [    0.000000] random: get_random_bytes called from start_kernel+0x2b8/0x44c with crng_init=0
    [    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.000003] sched_clock: 56 bits at 8MHz, resolution 125ns, wraps every 2199023255500ns
    [    0.000396] Console: colour dummy device 80x25
    [    0.000465] Calibrating delay loop (skipped), value calculated using timer frequency.. 16.00 BogoMIPS (lpj=32000)
    [    0.000474] pid_max: default: 32768 minimum: 301
    [    0.000545] LSM: Security Framework initializing
    [    0.000597] Mount-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
    [    0.000608] Mountpoint-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
    [    0.001737] ASID allocator initialised with 32768 entries
    [    0.001809] rcu: Hierarchical SRCU implementation.
    [    0.002772] EFI services will not be available.
    [    0.002930] smp: Bringing up secondary CPUs ...
    [    0.003282] Detected VIPT I-cache on CPU1
    [    0.003305] GICv3: CPU1: found redistributor 1 region 0:0x00000000388a0000
    [    0.003338] CPU1: Booted secondary processor 0x0000000001 [0x410fd034]
    [    0.003727] Detected VIPT I-cache on CPU2
    [    0.003744] GICv3: CPU2: found redistributor 2 region 0:0x00000000388c0000
    [    0.003761] CPU2: Booted secondary processor 0x0000000002 [0x410fd034]
    [    0.004185] Detected VIPT I-cache on CPU3
    [    0.004202] GICv3: CPU3: found redistributor 3 region 0:0x00000000388e0000
    [    0.004218] CPU3: Booted secondary processor 0x0000000003 [0x410fd034]
    [    0.004269] smp: Brought up 1 node, 4 CPUs
    [    0.004278] SMP: Total of 4 processors activated.
    [    0.004284] CPU features: detected: 32-bit EL0 Support
    [    0.004291] CPU features: detected: CRC32 instructions
    [    0.010901] CPU: All CPU(s) started at EL2
    [    0.010920] alternatives: patching kernel code
    [    0.012138] devtmpfs: initialized
    [    0.019365] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
    [    0.019385] futex hash table entries: 1024 (order: 4, 65536 bytes, linear)
    [    0.037004] pinctrl core: initialized pinctrl subsystem
    [    0.037738] DMI not present or invalid.
    [    0.037983] NET: Registered protocol family 16
    [    0.045322] DMA: preallocated 256 KiB pool for atomic allocations
    [    0.045352] audit: initializing netlink subsys (disabled)
    [    0.045593] audit: type=2000 audit(0.044:1): state=initialized audit_enabled=0 res=1
    [    0.046443] cpuidle: using governor menu
    [    0.046911] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
    [    0.047711] Serial: AMBA PL011 UART driver
    [    0.047766] imx mu driver is registered.
    [    0.047786] imx rpmsg driver is registered.
    [    0.052668] imx8mm-pinctrl 30330000.pinctrl: Invalid fsl,pins or pins property in node /soc@0/bus@30000000/pinctrl@30330000/imx8mm-iwg34m/usb1grp
    [    0.052683] imx8mm-pinctrl 30330000.pinctrl: Invalid fsl,pins or pins property in node /soc@0/bus@30000000/pinctrl@30330000/imx8mm-iwg34m/carrier_rst
    [    0.052707] imx8mm-pinctrl 30330000.pinctrl: Invalid fsl,pins or pins property in node /soc@0/bus@30000000/pinctrl@30330000/imx8mm-iwg34m/pwr_grp
    [    0.052746] imx8mm-pinctrl 30330000.pinctrl: initialized IMX pinctrl driver
    [    0.076965] HugeTLB registered 1.00 GiB page size, pre-allocated 0 pages
    [    0.076976] HugeTLB registered 32.0 MiB page size, pre-allocated 0 pages
    [    0.076982] HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages
    [    0.076989] HugeTLB registered 64.0 KiB page size, pre-allocated 0 pages
    [    0.077817] cryptd: max_cpu_qlen set to 1000
    [    0.085219] iw_em05_gpio em05_gpios: gpios DT property empty / missing
    [    0.085693] ACPI: Interpreter disabled.
    [    0.087084] iommu: Default domain type: Translated 
    [    0.087237] vgaarb: loaded
    [    0.087534] SCSI subsystem initialized
    [    0.087675] libata version 3.00 loaded.
    [    0.087889] usbcore: registered new interface driver usbfs
    [    0.087925] usbcore: registered new interface driver hub
    [    0.087975] usbcore: registered new device driver usb
    [    0.089252] mc: Linux media interface: v0.10
    [    0.089282] videodev: Linux video capture interface: v2.00
    [    0.089345] pps_core: LinuxPPS API ver. 1 registered
    [    0.089352] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
    [    0.089363] PTP clock support registered
    [    0.089503] EDAC MC: Ver: 3.0.0
    [    0.090277] No BMan portals available!
    [    0.090488] QMan: Allocated lookup table at (____ptrval____), entry count 65537
    [    0.090754] No QMan portals available!
    [    0.091152] No USDPAA memory, no 'fsl,usdpaa-mem' in device-tree
    [    0.091560] FPGA manager framework
    [    0.091653] Advanced Linux Sound Architecture Driver Initialized.
    [    0.092200] Bluetooth: Core ver 2.22
    [    0.092226] NET: Registered protocol family 31
    [    0.092232] Bluetooth: HCI device and connection manager initialized
    [    0.092245] Bluetooth: HCI socket layer initialized
    [    0.092251] Bluetooth: L2CAP socket layer initialized
    [    0.092264] Bluetooth: SCO socket layer initialized
    [    0.092954] clocksource: Switched to clocksource arch_sys_counter
    [    0.093126] VFS: Disk quotas dquot_6.6.0
    [    0.093176] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
    [    0.093320] pnp: PnP ACPI: disabled
    [    0.098819] thermal_sys: Registered thermal governor 'step_wise'
    [    0.098823] thermal_sys: Registered thermal governor 'power_allocator'
    [    0.099148] NET: Registered protocol family 2
    [    0.099450] tcp_listen_portaddr_hash hash table entries: 1024 (order: 2, 16384 bytes, linear)
    [    0.099481] TCP established hash table entries: 16384 (order: 5, 131072 bytes, linear)
    [    0.099590] TCP bind hash table entries: 16384 (order: 6, 262144 bytes, linear)
    [    0.099816] TCP: Hash tables configured (established 16384 bind 16384)
    [    0.099895] UDP hash table entries: 1024 (order: 3, 32768 bytes, linear)
    [    0.099937] UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes, linear)
    [    0.100068] NET: Registered protocol family 1
    [    0.100402] RPC: Registered named UNIX socket transport module.
    [    0.100407] RPC: Registered udp transport module.
    [    0.100411] RPC: Registered tcp transport module.
    [    0.100415] RPC: Registered tcp NFSv4.1 backchannel transport module.
    [    0.100788] PCI: CLS 0 bytes, default 64
    [    0.101470] hw perfevents: enabled with armv8_pmuv3 PMU driver, 7 counters available
    [    0.101846] kvm [1]: IPA Size Limit: 40bits
    [    0.102464] kvm [1]: GICv3: no GICV resource entry
    [    0.102469] kvm [1]: disabling GICv2 emulation
    [    0.102487] kvm [1]: GIC system register CPU interface enabled
    [    0.102543] kvm [1]: vgic interrupt IRQ1
    [    0.102627] kvm [1]: Hyp mode initialized successfully
    [    0.105478] Initialise system trusted keyrings
    [    0.105609] workingset: timestamp_bits=44 max_order=19 bucket_order=0
    [    0.111688] squashfs: version 4.0 (2009/01/31) Phillip Lougher
    [    0.112328] NFS: Registering the id_resolver key type
    [    0.112351] Key type id_resolver registered
    [    0.112356] Key type id_legacy registered
    [    0.112367] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
    [    0.112385] jffs2: version 2.2. (NAND) \xc2\xa9 2001-2006 Red Hat, Inc.
    [    0.112733] 9p: Installing v9fs 9p2000 file system support
    [    0.126207] Key type asymmetric registered
    [    0.126214] Asymmetric key parser 'x509' registered
    [    0.126248] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 244)
    [    0.126254] io scheduler mq-deadline registered
    [    0.126261] io scheduler kyber registered
    [    0.128871] gpio-control: GPIO major number243
    [    0.132344] EINJ: ACPI disabled.
    [    0.141398] imx-sdma 302c0000.dma-controller: Direct firmware load for imx/sdma/sdma-imx7d.bin failed with error -2
    [    0.141411] imx-sdma 302c0000.dma-controller: Falling back to sysfs fallback for: imx/sdma/sdma-imx7d.bin
    [    0.149873] mxs-dma 33000000.dma-controller: initialized
    [    0.151178] Bus freq driver module loaded
    
    [    0.151723] Board Info:
    [    0.151729] 	BSP Version               : iW-PRGPP-SC-01-R2.0-REL1.0-Linux5.4.70
    [    0.151734] 	SOM Version               : iW-PRFYZ-AP-01-R1.0
    [    0.151737] 	CPU Unique ID             : 0x131CB209DAB5FC2F
    [    0.151796] 	Carrier Board Version     : iW-PRGPP-01-R2.0
    
    [    0.156810] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
    [    0.158957] 30860000.serial: ttymxc0 at MMIO 0x30860000 (irq = 36, base_baud = 5000000) is a IMX
    [    0.159402] 30880000.serial: ttymxc2 at MMIO 0x30880000 (irq = 37, base_baud = 1500000) is a IMX
    [    0.159770] 30890000.serial: ttymxc1 at MMIO 0x30890000 (irq = 38, base_baud = 1500000) is a IMX
    [    0.160151] 30a60000.serial: ttymxc3 at MMIO 0x30a60000 (irq = 43, base_baud = 1500000) is a IMX
    [    1.302095] printk: console [ttymxc3] enabled
    [    1.312512] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
    [    1.319155] [drm] No driver support for vblank timestamp query.
    [    1.325148] imx-drm soc@0:bus@32c00000:display-subsystem: bound imx-lcdif-crtc.0 (ops lcdif_crtc_ops)
    [    1.334472] [DEBUG] Inside sec_mipi_dsim_bind: sec-dsim bridge bind begin
    [    1.341394] imx_sec_dsim_drv 32e10000.mipi_dsi: version number is 0x1060200
    [    1.348402] [DEBUG] before drm_bridge_attach
    [    1.352700] imx_sec_dsim_drv 32e10000.mipi_dsi: Failed to attach bridge: 32e10000.mipi_dsi
    [    1.360975] imx_sec_dsim_drv 32e10000.mipi_dsi: failed to bind sec dsim bridge: -517
    [    1.378467] loop: module loaded
    [    1.383849] imx ahci driver is registered.
    [    1.390756] spi_imx 30820000.spi: probed
    [    1.395271] ------------[ cut here ]------------
    [    1.399906] /soc@0/bus@30800000/spi@30830000/spi@0: buggy DT: spidev listed directly in DT
    [    1.408227] WARNING: CPU: 1 PID: 1 at drivers/spi/spidev.c:736 spidev_probe+0x104/0x220
    [    1.416229] Modules linked in:
    [    1.419289] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.4.70+gfd7f722f444d #28
    [    1.426510] Hardware name: iW-G39H-i.MX8MM-SODIMM-2GB (DT)
    [    1.431996] pstate: 60000005 (nZCv daif -PAN -UAO)
    [    1.436785] pc : spidev_probe+0x104/0x220
    [    1.440793] lr : spidev_probe+0x104/0x220
    [    1.444801] sp : ffff80001003b7c0
    [    1.448114] x29: ffff80001003b7c0 x28: 0000000000000000 
    [    1.453425] x27: ffff0000785a5800 x26: ffff800011ac7d50 
    [    1.458738] x25: 0000000000000000 x24: 0000000000000000 
    [    1.464050] x23: ffff800011ad82e8 x22: 0000000000000000 
    [    1.469363] x21: ffff800011ad82c8 x20: ffff000076980800 
    [    1.474676] x19: 0000000000000000 x18: 0000000000000010 
    [    1.479988] x17: 0000000000000001 x16: 0000000000000019 
    [    1.485301] x15: ffff0000780a0470 x14: 796c746365726964 
    [    1.490613] x13: 2064657473696c20 x12: 766564697073203a 
    [    1.495926] x11: 5444207967677562 x10: 203a30406970732f 
    [    1.501239] x9 : 3030303033383033 x8 : ffff800011ba1000 
    [    1.506550] x7 : ffff8000106a3828 x6 : 00000000000000d8 
    [    1.511862] x5 : 0000000000000000 x4 : 0000000000000000 
    [    1.517174] x3 : 00000000ffffffff x2 : ffff800011a721c8 
    [    1.522487] x1 : 72888a825a38d200 x0 : 0000000000000000 
    [    1.527801] Call trace:
    [    1.530250]  spidev_probe+0x104/0x220
    [    1.533912]  spi_drv_probe+0x7c/0xd8
    [    1.537491]  really_probe+0xd4/0x318
    [    1.541066]  driver_probe_device+0x54/0xe8
    [    1.545162]  __device_attach_driver+0x80/0xb8
    [    1.549521]  bus_for_each_drv+0x74/0xc0
    [    1.553356]  __device_attach+0xe8/0x148
    [    1.557192]  device_initial_probe+0x10/0x18
    [    1.561377]  bus_probe_device+0x90/0x98
    [    1.565214]  device_add+0x378/0x648
    [    1.568702]  spi_add_device+0xf0/0x1d0
    [    1.572451]  of_register_spi_device+0x204/0x3c8
    [    1.576982]  spi_register_controller+0x43c/0x790
    [    1.581600]  spi_bitbang_start+0x34/0x80
    [    1.585524]  spi_imx_probe+0x448/0x6a8
    [    1.589274]  platform_drv_probe+0x50/0xa0
    [    1.593282]  really_probe+0xd4/0x318
    [    1.596859]  driver_probe_device+0x54/0xe8
    [    1.600953]  device_driver_attach+0x6c/0x78
    [    1.605134]  __driver_attach+0x54/0xd0
    [    1.608884]  bus_for_each_dev+0x6c/0xc0
    [    1.612721]  driver_attach+0x20/0x28
    [    1.616295]  bus_add_driver+0x140/0x1e8
    [    1.620131]  driver_register+0x60/0x110
    [    1.623965]  __platform_driver_register+0x44/0x50
    [    1.628672]  spi_imx_driver_init+0x1c/0x24
    [    1.632770]  do_one_initcall+0x50/0x1a8
    [    1.636607]  kernel_init_freeable+0x194/0x23c
    [    1.640966]  kernel_init+0x10/0x100
    [    1.644456]  ret_from_fork+0x10/0x1c
    [    1.648035] ---[ end trace 3f1c3fd879b795c9 ]---
    [    1.652811] spi_imx 30830000.spi: probed
    [    1.657314] spi_imx 30840000.spi: probed
    [    1.662801] libphy: Fixed MDIO Bus: probed
    [    1.667658] tun: Universal TUN/TAP device driver, 1.6
    [    1.672881] CAN device driver interface
    [    1.787460] tcan4x5x spi0.0 (unnamed net_device) (uninitialized): Failed to init module
    [    1.797356] random: fast init done
    [    1.826072] tcan4x5x spi0.0: m_can device registered (irq=73, version=32)
    [    1.832903] tcan4x5x spi0.0 can0: TCAN4X5X successfully initialized.
    [    1.947376] tcan4x5x spi2.0 (unnamed net_device) (uninitialized): Failed to init module
    [    1.999205] tcan4x5x spi2.0: m_can device registered (irq=82, version=32)
    [    2.006006] tcan4x5x spi2.0 can1: TCAN4X5X successfully initialized.
    [    2.013187] thunder_xcv, ver 1.0
    [    2.016447] thunder_bgx, ver 1.0
    [    2.019715] nicpf, ver 1.0
    [    2.025310] pps pps0: new PPS source ptp0
    [    2.034874] libphy: fec_enet_mii_bus: probed
    [    2.040334] fec 30be0000.ethernet eth0: registered PHC device 0
    [    2.046913] Freescale FM module, FMD API version 21.1.0
    [    2.052412] Freescale FM Ports module
    [    2.056085] fsl_mac: fsl_mac: FSL FMan MAC API based driver
    [    2.061822] fsl_dpa: FSL DPAA Ethernet driver
    [    2.066291] fsl_advanced: FSL DPAA Advanced drivers:
    [    2.071261] fsl_proxy: FSL DPAA Proxy initialization driver
    [    2.076958] fsl_oh: FSL FMan Offline Parsing port driver
    [    2.083167] hclge is initializing
    [    2.086493] hns3: Hisilicon Ethernet Network Driver for Hip08 Family - version
    [    2.093719] hns3: Copyright (c) 2017 Huawei Corporation.
    [    2.099085] e1000: Intel(R) PRO/1000 Network Driver - version 7.3.21-k8-NAPI
    [    2.106139] e1000: Copyright (c) 1999-2006 Intel Corporation.
    [    2.111922] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
    [    2.117762] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
    [    2.123717] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.6.0-k
    [    2.130685] igb: Copyright (c) 2007-2014 Intel Corporation.
    [    2.136293] igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.4.0-k
    [    2.144127] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
    [    2.150219] sky2: driver version 1.30
    [    2.154620] usbcore: registered new interface driver cdc_ether
    [    2.160726] VFIO - User Level meta-driver version: 0.3
    [    2.167717] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
    [    2.174307] ehci-pci: EHCI PCI platform driver
    [    2.178793] ehci-platform: EHCI generic platform driver
    [    2.184218] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
    [    2.190420] ohci-pci: OHCI PCI platform driver
    [    2.194904] ohci-platform: OHCI generic platform driver
    [    2.200864] usbcore: registered new interface driver uas
    [    2.206236] usbcore: registered new interface driver usb-storage
    [    2.212315] usbcore: registered new interface driver usbserial_generic
    [    2.218868] usbserial: USB Serial support registered for generic
    [    2.224906] usbcore: registered new interface driver ftdi_sio
    [    2.230671] usbserial: USB Serial support registered for FTDI USB Serial Device
    [    2.238008] usbcore: registered new interface driver option
    [    2.243605] usbserial: USB Serial support registered for GSM modem (1-port)
    [    2.250597] usbcore: registered new interface driver usb_serial_simple
    [    2.257150] usbserial: USB Serial support registered for carelink
    [    2.263264] usbserial: USB Serial support registered for zio
    [    2.268954] usbserial: USB Serial support registered for funsoft
    [    2.274984] usbserial: USB Serial support registered for flashloader
    [    2.281359] usbserial: USB Serial support registered for google
    [    2.287295] usbserial: USB Serial support registered for libtransistor
    [    2.293843] usbserial: USB Serial support registered for vivopay
    [    2.299873] usbserial: USB Serial support registered for moto_modem
    [    2.306165] usbserial: USB Serial support registered for motorola_tetra
    [    2.312801] usbserial: USB Serial support registered for novatel_gps
    [    2.319174] usbserial: USB Serial support registered for hp4x
    [    2.324948] usbserial: USB Serial support registered for suunto
    [    2.330888] usbserial: USB Serial support registered for siemens_mpi
    [    2.337275] usbcore: registered new interface driver usb_ehset_test
    [    2.345236] imx_usb 32e40000.usb: No over current polarity defined
    [    2.351622] imx_usb 32e50000.usb: No over current polarity defined
    [    2.358866] input: 30370000.snvs:snvs-powerkey as /devices/platform/soc@0/soc@0:bus@30000000/30370000.snvs/30370000.snvs:snvs-powerkey/input/input0
    [    2.372656]  linc HYN:[LINE=2615] linc hyn is entering cst3xx_ts_init.
    [    2.380918] snvs_rtc 30370000.snvs:snvs-rtc-lp: registered as rtc0
    [    2.387222] i2c /dev entries driver
    [    2.391411] mx6s-csi 32e20000.csi1_bridge: initialising
    [    2.397221] mxc_mipi-csi 32e30000.mipi_csi: 32e30000.mipi_csi supply mipi-phy not found, using dummy regulator
    [    2.407427] mxc_mipi-csi 32e30000.mipi_csi: mipi csi v4l2 device registered
    [    2.414403] CSI: Registered sensor subdevice: mxc_mipi-csi.0
    [    2.420084] mxc_mipi-csi 32e30000.mipi_csi: lanes: 2, hs_settle: 13, clk_settle: 2, wclk: 1, freq: 333000000
    [    2.434140] imx2-wdt 30280000.watchdog: timeout 60 sec (nowayout=0)
    [    2.440755] Bluetooth: HCI UART driver ver 2.3
    [    2.445214] Bluetooth: HCI UART protocol H4 registered
    [    2.450358] Bluetooth: HCI UART protocol BCSP registered
    [    2.455692] Bluetooth: HCI UART protocol LL registered
    [    2.460840] Bluetooth: HCI UART protocol ATH3K registered
    [    2.466269] Bluetooth: HCI UART protocol Three-wire (H5) registered
    [    2.472641] Bluetooth: HCI UART protocol Broadcom registered
    [    2.478325] Bluetooth: HCI UART protocol QCA registered
    [    2.485748] sdhci: Secure Digital Host Controller Interface driver
    [    2.491946] sdhci: Copyright(c) Pierre Ossman
    [    2.496514] Synopsys Designware Multimedia Card Interface Driver
    [    2.503111] sdhci-pltfm: SDHCI platform and OF driver helper
    [    2.509586] mmc2: CQHCI version 5.10
    [    2.513236] sdhci-esdhc-imx 30b40000.mmc: allocated mmc-pwrseq
    [    2.550762] mmc2: SDHCI controller on 30b40000.mmc [30b40000.mmc] using ADMA
    [    2.558264] mmc1: CQHCI version 5.10
    [    2.561937] sdhci-esdhc-imx 30b50000.mmc: Got CD GPIO
    [    2.601102] mmc1: SDHCI controller on 30b50000.mmc [30b50000.mmc] using ADMA
    [    2.608756] mmc0: CQHCI version 5.10
    [    2.613420] mmc2: queuing unknown CIS tuple 0x80 (2 bytes)
    [    2.623096] mmc2: queuing unknown CIS tuple 0x80 (3 bytes)
    [    2.633375] mmc2: queuing unknown CIS tuple 0x80 (3 bytes)
    [    2.645897] mmc0: SDHCI controller on 30b60000.mmc [30b60000.mmc] using ADMA
    [    2.646831] mmc2: queuing unknown CIS tuple 0x80 (7 bytes)
    [    2.659406] ledtrig-cpu: registered to indicate activity on CPUs
    [    2.664411] mmc2: queuing unknown CIS tuple 0x80 (6 bytes)
    [    2.666883] caam 30900000.crypto: device ID = 0x0a16040100000000 (Era 9)
    [    2.677681] caam 30900000.crypto: job rings = 3, qi = 0
    [    2.711074] caam algorithms registered in /proc/crypto
    [    2.720071] caam 30900000.crypto: caam pkc algorithms registered in /proc/crypto
    [    2.727496] caam 30900000.crypto: registering rng-caam
    [    2.734104] Device caam-keygen registered
    [    2.741715] caam-snvs 30370000.caam-snvs: violation handlers armed - non-secure state
    [    2.750267] usbcore: registered new interface driver usbhid
    [    2.752766] mmc2: new ultra high speed SDR104 SDIO card at address 0001
    [    2.755852] usbhid: USB HID core driver
    [    2.757429] No fsl,qman node
    [    2.757446] random: crng init done
    [    2.772631] Freescale USDPAA process driver
    [    2.776900] fsl-usdpaa: no region found
    [    2.778407] mmc0: Command Queue Engine enabled
    [    2.780779] Freescale USDPAA process IRQ driver
    [    2.785226] mmc0: new HS400 Enhanced strobe MMC card at address 0001
    [    2.794337] galcore: clk_get vg clock failed, disable vg!
    [    2.797159] mmcblk0: mmc0:0001 DG4008 7.28 GiB 
    [    2.801884] Galcore version 6.4.3.p1.305572
    [    2.806175] mmcblk0boot0: mmc0:0001 DG4008 partition 1 4.00 MiB
    [    2.816297] mmcblk0boot1: mmc0:0001 DG4008 partition 2 4.00 MiB
    [    2.822979] mmcblk0rpmb: mmc0:0001 DG4008 partition 3 4.00 MiB, chardev (236:0)
    [    2.833528]  mmcblk0: p1 p2
    [    2.887504] [drm] Initialized vivante 1.0.0 20170808 for 38000000.gpu on minor 0
    [    2.896477] hantrodec 0 : module inserted. Major = 235
    [    2.902163] hantrodec 1 : module inserted. Major = 235
    [    2.908125] hx280enc: module inserted. Major <234>
    [    2.916404] simple card ---------asoc_simple_probe...........
    [    2.963622] imx-spdif sound-spdif: snd-soc-dummy-dai <-> 30090000.spdif mapping ok
    [    2.971262] imx-spdif sound-spdif: ASoC: no DMI vendor name!
    [    2.980245] pktgen: Packet Generator for packet performance testing. Version: 2.75
    [    2.992768] NET: Registered protocol family 26
    [    2.997855] NET: Registered protocol family 10
    [    3.002969] Segment Routing with IPv6
    [    3.006707] NET: Registered protocol family 17
    [    3.011167] can: controller area network core (rev 20170425 abi 9)
    [    3.017394] NET: Registered protocol family 29
    [    3.021847] can: raw protocol (rev 20170425)
    [    3.026123] can: broadcast manager protocol (rev 20170425 t)
    [    3.031792] can: netlink gateway (rev 20190810) max_hops=1
    [    3.037871] Bluetooth: RFCOMM TTY layer initialized
    [    3.042772] Bluetooth: RFCOMM socket layer initialized
    [    3.047938] Bluetooth: RFCOMM ver 1.11
    [    3.051700] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
    [    3.057020] Bluetooth: BNEP filters: protocol multicast
    [    3.062253] Bluetooth: BNEP socket layer initialized
    [    3.067225] Bluetooth: HIDP (Human Interface Emulation) ver 1.2
    [    3.073154] Bluetooth: HIDP socket layer initialized
    [    3.078154] 8021q: 802.1Q VLAN Support v1.8
    [    3.082358] lib80211: common routines for IEEE802.11 drivers
    [    3.088023] lib80211_crypt: registered algorithm 'NULL'
    [    3.088026] lib80211_crypt: registered algorithm 'WEP'
    [    3.088029] lib80211_crypt: registered algorithm 'CCMP'
    [    3.088031] lib80211_crypt: registered algorithm 'TKIP'
    [    3.088120] 9pnet: Installing 9P2000 support
    [    3.092438] tsn generic netlink module v1 init...
    [    3.097211] Key type dns_resolver registered
    [    3.102478] registered taskstats version 1
    [    3.106589] Loading compiled-in X.509 certificates
    [    3.124402] imx-rpmsg b8000000.rpmsg: assigned reserved memory node vdevbuffer@b8400000
    [    3.153322] virtio_rpmsg_bus virtio0: rpmsg host is online
    [    3.159111] usb_phy_generic usbphynop1: usbphynop1 supply vcc not found, using dummy regulator
    [    3.167896] usb_phy_generic usbphynop2: usbphynop2 supply vcc not found, using dummy regulator
    [    3.183622] pcf85363 0-0051: registered as rtc1
    [    3.201821] ldo6: supplied by regulator-dummy
    [    3.207299] i2c i2c-0: IMX I2C adapter registered
    [    3.213482]  TLV ..........aic31xx_i2c_probe............
    [    3.219155] i2c i2c-1: IMX I2C adapter registered
    [    3.225007]  linc HYN:[LINE=2216] linc hyn is entering tpd_i2c_probe. 
    [    3.338431]  linc HYN:[LINE=2297]linc cst3xx hyn i2c communication failed.
    [    3.345337] hynitron-ts: probe of 2-001a failed with error -1
    [    3.351405] ov5640_mipi 2-003c: No sensor pwdn pin available
    [    3.357123] ov5640_mipi 2-003c: 2-003c supply DOVDD not found, using dummy regulator
    [    3.364926] ov5640_mipi 2-003c: 2-003c supply DVDD not found, using dummy regulator
    [    3.372628] ov5640_mipi 2-003c: 2-003c supply AVDD not found, using dummy regulator
    [    3.380529] ov5640_mipi 2-003c: Read reg error: reg=300a
    [    3.385850] ov5640_mipi 2-003c: Camera is not found
    [    3.390890] i2c i2c-2: IMX I2C adapter registered
    [    3.397911] imx6q-pcie 33800000.pcie: 33800000.pcie supply epdev_on not found, using dummy regulator
    [    3.397958] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
    [    3.407347] imx6q-pcie 33800000.pcie: EXT REF_CLK is used!.
    [    3.413723] [drm] No driver support for vblank timestamp query.
    [    3.420161] imx6q-pcie 33800000.pcie: PCIe PLL locked after 20 us.
    [    3.425289] imx-drm soc@0:bus@32c00000:display-subsystem: bound imx-lcdif-crtc.0 (ops lcdif_crtc_ops)
    [    3.431447] imx6q-pcie 33800000.pcie: host bridge /soc@0/pcie@33800000 ranges:
    [    3.440723] [DEBUG] Inside sec_mipi_dsim_bind: sec-dsim bridge bind begin
    [    3.447899] imx6q-pcie 33800000.pcie:    IO 0x1ff80000..0x1ff8ffff -> 0x00000000
    [    3.454789] imx_sec_dsim_drv 32e10000.mipi_dsi: version number is 0x1060200
    [    3.462074] imx6q-pcie 33800000.pcie:   MEM 0x18000000..0x1fefffff -> 0x18000000
    [    3.469062] [DEBUG] before drm_bridge_attach
    [    3.480718] imx_sec_dsim_drv 32e10000.mipi_dsi: Failed to attach bridge: 32e10000.mipi_dsi
    [    3.488992] imx_sec_dsim_drv 32e10000.mipi_dsi: failed to bind sec dsim bridge: -517
    [    3.498121] imx_usb 32e40000.usb: No over current polarity defined
    [    3.504378] imx_usb 32e40000.usb: 32e40000.usb supply vbus not found, using dummy regulator
    [    3.516505] usbmisc_imx 32e40200.usbmisc: vbus is error
    [    3.521767] usbmisc_imx 32e40200.usbmisc: Error occurs during detection: -22
    [    3.530966] imx_usb 32e50000.usb: No over current polarity defined
    [    3.537236] imx_usb 32e50000.usb: 32e50000.usb supply vbus not found, using dummy regulator
    [    3.548469] ci_hdrc ci_hdrc.1: EHCI Host Controller
    [    3.553376] ci_hdrc ci_hdrc.1: new USB bus registered, assigned bus number 1
    [    3.572961] ci_hdrc ci_hdrc.1: USB 2.0 started, EHCI 1.00
    [    3.579461] hub 1-0:1.0: USB hub found
    [    3.583245] hub 1-0:1.0: 1 port detected
    [    3.589116] input: pwm-beeper as /devices/platform/pwm_beeper/input/input1
    [    3.597066] imx-cpufreq-dt imx-cpufreq-dt: cpu speed grade 2 mkt segment 2 supported-hw 0x4 0x4
    [    3.609246] simple card ---------asoc_simple_probe...........
    [    3.615253]  TLV ..........aic31xx_codec_probe............
    [    3.620759]  TLV ..........aic31xx_add_controls............
    [    3.626345]  TLV ..........aic31xx_add_controls............2
    [    3.632017]  TLV ..........aic31xx_add_controls............4
    [    3.637685]  TLV ..........aic31xx_add_widgets............
    [    3.643176]  tlv codec type ---  8
    [    3.646584]  tlv widgets route ---  8
    [    3.650273]  TLV ..........aic31xx_codec_probe.....end.......
    [    3.656049] debugfs: Directory '30050000.sai' with parent 'Audio Output' already present!
    [    3.664240]  TLV ..........aic31xx_set_dai_sysclk............
    [    3.669991] clk_id = 0, freq = 26000000, dir = 0
    [    3.674610] TLV ----i= 0,mclk=12000000
    [    3.674612]  tlv aic31xx->p_div=2,freq=26000000
    [    3.682891] TLV ----i= 1,mclk=12000000
    [    3.682893]  tlv aic31xx->p_div=2,freq=26000000
    [    3.691181] TLV ----i= 2,mclk=12500000
    [    3.691182]  tlv aic31xx->p_div=2,freq=26000000
    [    3.699470] TLV ----i= 3,mclk=13000000
    [    3.699472]  tlv aic31xx->p_div=2,freq=26000000
    [    3.707757]  TLV ..........aic31xx_set_dai_fmt............
    [    3.713249]  TLV ..........aic31xx_clock_master_routes............
    [    3.719508] asoc-simple-card sound-tlv320dac31: tlv320dac31xx-hifi <-> 30050000.sai mapping ok
    [    3.728134] asoc-simple-card sound-tlv320dac31: ASoC: no DMI vendor name!
    [    3.735364] TLV..........aic31xx_set_bias_level............
    [    3.740949]  tlv value of level = 1 
    [    3.744523]  tlv value of snd_soc_component_get_bias_level(component)=0
    [    3.751155]  TLV ..........aic31xx_power_on............
    [    3.757957]  TLV..........aic31xx_reset............
    [    3.762857]  tlv ..........aic31xx_software reset............
    [    3.905968] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
    [    3.912605] [drm] No driver support for vblank timestamp query.
    [    3.918589] imx-drm soc@0:bus@32c00000:display-subsystem: bound imx-lcdif-crtc.0 (ops lcdif_crtc_ops)
    [    3.925579] usb 1-1: new high-speed USB device number 2 using ci_hdrc
    [    3.927894] [DEBUG] Inside sec_mipi_dsim_bind: sec-dsim bridge bind begin
    [    3.941196] imx_sec_dsim_drv 32e10000.mipi_dsi: version number is 0x1060200
    [    3.948211] [DEBUG] before drm_bridge_attach
    [    3.952683] imx-drm soc@0:bus@32c00000:display-subsystem: bound 32e10000.mipi_dsi (ops imx_sec_dsim_ops)
    [    3.962874] [drm] Initialized imx-drm 1.0.0 20120507 for soc@0:bus@32c00000:display-subsystem on minor 1
    [    4.072886] lt8912 1-0048: "1280x800": 60 74202 1280 1350 1420 1490 800 810 820 830 0x48 0x5
    [    4.073501] lt8912 1-0048: LT8912 ID: 12, b2
    [    4.100278] hub 1-1:1.0: USB hub found
    [    4.100659] hub 1-1:1.0: 4 ports detected
    [    4.143668] Console: switching to colour frame buffer device 160x50
    [    4.183815] imx-drm soc@0:bus@32c00000:display-subsystem: fb0: imx-drmdrmfb frame buffer device
    [    4.194715] input: gpio-keys as /devices/platform/gpio-keys/input/input2
    [    4.202659] input: bd718xx-pwrkey as /devices/platform/soc@0/soc@0:bus@30800000/30a20000.i2c/i2c-0/0-004b/gpio-keys.1.auto/input/input3
    [    4.216138] pcf85363 0-0051: setting system clock to 2000-01-01T00:00:12 UTC (946684812)
    [    4.224665] cfg80211: Loading compiled-in X.509 certificates for regulatory database
    [    4.235427] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
    [    4.242025] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
    [    4.247252] ALSA device list:
    [    4.250659] platform regulatory.0: Falling back to sysfs fallback for: regulatory.db
    [    4.253627]   #0: imx-spdif
    [    4.264160]   #1: Audio Output
    [    4.405342] usb 1-1.1: new high-speed USB device number 3 using ci_hdrc
    [    4.469922] imx6q-pcie 33800000.pcie: Phy link never came up
    [    4.475632] imx6q-pcie 33800000.pcie: failed to initialize host
    [    4.481564] imx6q-pcie 33800000.pcie: unable to add pcie port.
    [    4.531828] usb-storage 1-1.1:1.0: USB Mass Storage device detected
    [    4.537010] EXT4-fs (mmcblk0p2): recovery complete
    [    4.538824] scsi host0: usb-storage 1-1.1:1.0
    [    4.543718] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
    [    4.555421] VFS: Mounted root (ext4 filesystem) on device 179:2.
    [    4.564621] devtmpfs: mounted
    [    4.568432] Freeing unused kernel memory: 2880K
    [    4.573052] Run /sbin/init as init process
    [    4.644109] systemd[1]: System time before build time, advancing clock.
    [    4.662828] systemd[1]: systemd 243.2+ running in system mode. (+PAM -AUDIT -SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP -LIBCRYPTSETUP -GCRYPT -GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID -ELFUTILS +KMOD -IDN2 -IDN -PCRE2 default-hierarchy=hybrid)
    [    4.684805] systemd[1]: Detected architecture arm64.
    [    4.725708] systemd[1]: Set hostname to <iWave-G39H>.
    [    4.855719] systemd[1]: /lib/systemd/system/dbus.socket:5: ListenStream= references a path below legacy directory /var/run/, updating /var/run/dbus/system_bus_socket \xe2\x86\x92 /run/dbus/system_bus_socket; please update the unit file accordingly.
    [    4.883317] systemd[1]: /lib/systemd/system/syslogd.service:8: PIDFile= references a path below legacy directory /var/run/, updating /var/run/syslogd.pid \xe2\x86\x92 /run/syslogd.pid; please update the unit file accordingly.
    [    4.911278] systemd[1]: /lib/systemd/system/rpcbind.socket:5: ListenStream= references a path below legacy directory /var/run/, updating /var/run/rpcbind.sock \xe2\x86\x92 /run/rpcbind.sock; please update the unit file accordingly.
    [    4.934436] systemd[1]: /lib/systemd/system/klogd.service:8: PIDFile= references a path below legacy directory /var/run/, updating /var/run/klogd.pid \xe2\x86\x92 /run/klogd.pid; please update the unit file accordingly.
    [    5.032713] systemd[1]: system-getty.slice: unit configures an IP firewall, but the local system does not support BPF/cgroup firewalling.
    [    5.045110] systemd[1]: (This warning is only shown for the first unit using IP firewalling.)
    [    5.055454] systemd[1]: Created slice system-getty.slice.
    [    5.463550] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
    [    5.570309] scsi 0:0:0:0: Direct-Access     Generic- Compact Flash    1.01 PQ: 0 ANSI: 0
    [    5.581166] scsi 0:0:0:1: Direct-Access     Multiple Flash Reader     1.05 PQ: 0 ANSI: 0
    [    5.682972] systemd-journald[258]: Received client request to flush runtime journal.
    [    5.956836] sd 0:0:0:1: [sdb] 15523840 512-byte logical blocks: (7.95 GB/7.40 GiB)
    [    5.967207] sd 0:0:0:0: [sda] Attached SCSI removable disk
    [    5.974214] sd 0:0:0:1: [sdb] Write Protect is off
    [    5.982004] sd 0:0:0:1: [sdb] Mode Sense: 03 00 00 00
    [    5.982823] sd 0:0:0:1: [sdb] No Caching mode page found
    [    5.991745] sd 0:0:0:1: [sdb] Assuming drive cache: write through
    [    6.022885]  sdb: sdb1 sdb2
    [    6.033289] sd 0:0:0:1: [sdb] Attached SCSI removable disk
    [    6.515451] imx-sdma 302b0000.dma-controller: loaded firmware 4.5
    [    7.038898] Atheros 8031 ethernet 30be0000.ethernet-1:04: attached PHY driver [Atheros 8031 ethernet] (mii_bus:phy_addr=30be0000.ethernet-1:04, irq=POLL)
    [    7.775999] audit: type=1006 audit(1640869463.128:2): pid=635 uid=0 old-auid=4294967295 auid=0 tty=(none) old-ses=4294967295 ses=1 res=1
    [    8.436227] EXT4-fs (sdb2): mounted filesystem with ordered data mode. Opts: (null)
    
    for reference.

     aplay -D plughw:1,0 file_example_WAV_1MG.wav

    0434.tlv320aic31xx.c
    // SPDX-License-Identifier: GPL-2.0
    /*
     * ALSA SoC TLV320AIC31xx CODEC Driver
     *
     * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/
     *	Jyri Sarha <jsarha@ti.com>
     *
     * Based on ground work by: Ajit Kulkarni <x0175765@ti.com>
     *
     * The TLV320AIC31xx series of audio codecs are low-power, highly integrated
     * high performance codecs which provides a stereo DAC, a mono ADC,
     * and mono/stereo Class-D speaker driver.
     */
    
    #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/jack.h>
    #include <sound/pcm.h>
    #include <sound/pcm_params.h>
    #include <sound/soc.h>
    #include <sound/initval.h>
    #include <sound/tlv.h>
    #include <dt-bindings/sound/tlv320aic31xx-micbias.h>
    
    #include "tlv320aic31xx.h"
    
    static const struct reg_default aic31xx_reg_defaults[] = {
    	{ AIC31XX_CLKMUX, 0x00 },
    	{ AIC31XX_PLLPR, 0x11 },
    	{ AIC31XX_PLLJ, 0x04 },
    	{ AIC31XX_PLLDMSB, 0x00 },
    	{ AIC31XX_PLLDLSB, 0x00 },
    	{ AIC31XX_NDAC, 0x01 },
    	{ AIC31XX_MDAC, 0x01 },
    	{ AIC31XX_DOSRMSB, 0x00 },
    	{ AIC31XX_DOSRLSB, 0x80 },
    	{ AIC31XX_NADC, 0x01 },
    	{ AIC31XX_MADC, 0x01 },
    	{ AIC31XX_AOSR, 0x80 },
    	{ AIC31XX_IFACE1, 0x00 },
    	{ AIC31XX_DATA_OFFSET, 0x00 },
    	{ AIC31XX_IFACE2, 0x00 },
    	{ AIC31XX_BCLKN, 0x01 },
    	{ AIC31XX_DACSETUP, 0x14 },
    	{ AIC31XX_DACMUTE, 0x0c },
    	{ AIC31XX_LDACVOL, 0x00 },
    	{ AIC31XX_RDACVOL, 0x00 },
    	{ AIC31XX_ADCSETUP, 0x00 },
    	{ AIC31XX_ADCFGA, 0x80 },
    	{ AIC31XX_ADCVOL, 0x00 },
    	{ AIC31XX_HPDRIVER, 0x04 },
    	{ AIC31XX_SPKAMP, 0x06 },
    	{ AIC31XX_DACMIXERROUTE, 0x00 },
    	{ AIC31XX_LANALOGHPL, 0x7f },
    	{ AIC31XX_RANALOGHPR, 0x7f },
    	{ AIC31XX_LANALOGSPL, 0x7f },
    	{ AIC31XX_RANALOGSPR, 0x7f },
    	{ AIC31XX_HPLGAIN, 0x02 },
    	{ AIC31XX_HPRGAIN, 0x02 },
    	{ AIC31XX_SPLGAIN, 0x00 },
    	{ AIC31XX_SPRGAIN, 0x00 },
    	{ AIC31XX_MICBIAS, 0x00 },
    	{ AIC31XX_MICPGA, 0x80 },
    	{ AIC31XX_MICPGAPI, 0x00 },
    	{ AIC31XX_MICPGAMI, 0x00 },
    };
    
    static bool aic31xx_volatile(struct device *dev, unsigned int reg)
    {
    	switch (reg) {
    	case AIC31XX_PAGECTL: /* regmap implementation requires this */
    	case AIC31XX_RESET: /* always clears after write */
    	case AIC31XX_OT_FLAG:
    	case AIC31XX_ADCFLAG:
    	case AIC31XX_DACFLAG1:
    	case AIC31XX_DACFLAG2:
    	case AIC31XX_OFFLAG: /* Sticky interrupt flags */
    	case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */
    	case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */
    	case AIC31XX_INTRDACFLAG2:
    	case AIC31XX_INTRADCFLAG2:
    	case AIC31XX_HSDETECT:
    		return true;
    	}
    	return false;
    }
    
    static bool aic31xx_writeable(struct device *dev, unsigned int reg)
    {
    	switch (reg) {
    	case AIC31XX_OT_FLAG:
    	case AIC31XX_ADCFLAG:
    	case AIC31XX_DACFLAG1:
    	case AIC31XX_DACFLAG2:
    	case AIC31XX_OFFLAG: /* Sticky interrupt flags */
    	case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */
    	case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */
    	case AIC31XX_INTRDACFLAG2:
    	case AIC31XX_INTRADCFLAG2:
    		return false;
    	}
    	return true;
    }
    
    static const struct regmap_range_cfg aic31xx_ranges[] = {
    	{
    		.range_min = 0,
    		.range_max = 12 * 128,
    		.selector_reg = AIC31XX_PAGECTL,
    		.selector_mask = 0xff,
    		.selector_shift = 0,
    		.window_start = 0,
    		.window_len = 128,
    	},
    };
    
    static const struct regmap_config aic31xx_i2c_regmap = {
    	.reg_bits = 8,
    	.val_bits = 8,
    	.writeable_reg = aic31xx_writeable,
    	.volatile_reg = aic31xx_volatile,
    	.reg_defaults = aic31xx_reg_defaults,
    	.num_reg_defaults = ARRAY_SIZE(aic31xx_reg_defaults),
    	.cache_type = REGCACHE_RBTREE,
    	.ranges = aic31xx_ranges,
    	.num_ranges = ARRAY_SIZE(aic31xx_ranges),
    	.max_register = 12 * 128,
    };
    
    static const char * const aic31xx_supply_names[] = {
    	"HPVDD",
    	"SPRVDD",
    	"SPLVDD",
    	"AVDD",
    	"IOVDD",
    	"DVDD",
    };
    
    #define AIC31XX_NUM_SUPPLIES ARRAY_SIZE(aic31xx_supply_names)
    
    struct aic31xx_disable_nb {
    	struct notifier_block nb;
    	struct aic31xx_priv *aic31xx;
    };
    
    struct aic31xx_priv {
    	struct snd_soc_component *component;
    	u8 i2c_regs_status;
    	struct device *dev;
    	struct regmap *regmap;
    	enum aic31xx_type codec_type;
    	struct gpio_desc *gpio_reset;
    	int micbias_vg;
    	struct aic31xx_pdata pdata;
    	struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES];
    	struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES];
    	struct snd_soc_jack *jack;
    	unsigned int sysclk;
    	u8 p_div;
    	int rate_div_line;
    	bool master_dapm_route_applied;
    	int irq;
    };
    
    struct aic31xx_rate_divs {
    	u32 mclk_p;
    	u32 rate;
    	u8 pll_j;
    	u16 pll_d;
    	u16 dosr;
    	u8 ndac;
    	u8 mdac;
    	u8 aosr;
    	u8 nadc;
    	u8 madc;
    };
    
    /* ADC dividers can be disabled by configuring them to 0 */
    static const struct aic31xx_rate_divs aic31xx_divs[] = {
    	/* mclk/p    rate  pll: j     d        dosr ndac mdac  aors nadc madc */
    	/* 8k rate */
    	{12000000,   8000,	8, 1920,	128,  48,  2,	128,  48,  2},
    	{12000000,   8000,	8, 1920,	128,  32,  3,	128,  32,  3},
    	{12500000,   8000,	7, 8643,	128,  48,  2,	128,  48,  2},
    	/* 11.025k rate */
    	{12000000,  11025,	7, 5264,	128,  32,  2,	128,  32,  2},
    	{12000000,  11025,	8, 4672,	128,  24,  3,	128,  24,  3},
    	{12500000,  11025,	7, 2253,	128,  32,  2,	128,  32,  2},
    	/* 16k rate */
    	{12000000,  16000,	8, 1920,	128,  24,  2,	128,  24,  2},
    	{12000000,  16000,	8, 1920,	128,  16,  3,	128,  16,  3},
    	{12500000,  16000,	7, 8643,	128,  24,  2,	128,  24,  2},
    	/* 22.05k rate */
    	{12000000,  22050,	7, 5264,	128,  16,  2,	128,  16,  2},
    	{12000000,  22050,	8, 4672,	128,  12,  3,	128,  12,  3},
    	{12500000,  22050,	7, 2253,	128,  16,  2,	128,  16,  2},
    	/* 32k rate */
    	{12000000,  32000,	8, 1920,	128,  12,  2,	128,  12,  2},
    	{12000000,  32000,	8, 1920,	128,   8,  3,	128,   8,  3},
    	{12500000,  32000,	7, 8643,	128,  12,  2,	128,  12,  2},
    	/* 44.1k rate */
    	{12000000,  44100,	7, 5264,	128,   8,  2,	128,   8,  2},
    	{12000000,  44100,	8, 4672,	128,   6,  3,	128,   6,  3},
    	{12500000,  44100,	7, 2253,	128,   8,  2,	128,   8,  2},
    	/* 48k rate */
    	{12000000,  48000,	8, 1920,	128,   8,  2,	128,   8,  2},
    	{12000000,  48000,	7, 6800,	 96,   5,  4,	 96,   5,  4},
    	{12500000,  48000,	7, 8643,	128,   8,  2,	128,   8,  2},
    	/* 88.2k rate */
    	{12000000,  88200,	7, 5264,	 64,   8,  2,	 64,   8,  2},
    	{12000000,  88200,	8, 4672,	 64,   6,  3,	 64,   6,  3},
    	{12500000,  88200,	7, 2253,	 64,   8,  2,	 64,   8,  2},
    	/* 96k rate */
    	{12000000,  96000,	8, 1920,	 64,   8,  2,	 64,   8,  2},
    	{12000000,  96000,	7, 6800,	 48,   5,  4,	 48,   5,  4},
    	{12500000,  96000,	7, 8643,	 64,   8,  2,	 64,   8,  2},
    	/* 176.4k rate */
    	{12000000, 176400,	7, 5264,	 32,   8,  2,	 32,   8,  2},
    	{12000000, 176400,	8, 4672,	 32,   6,  3,	 32,   6,  3},
    	{12500000, 176400,	7, 2253,	 32,   8,  2,	 32,   8,  2},
    	/* 192k rate */
    	{12000000, 192000,	8, 1920,	 32,   8,  2,	 32,   8,  2},
    	{12000000, 192000,	7, 6800,	 24,   5,  4,	 24,   5,  4},
    	{12500000, 192000,	7, 8643,	 32,   8,  2,	 32,   8,  2},
    };
    
    static const char * const ldac_in_text[] = {
    	"Off", "Left Data", "Right Data", "Mono"
    };
    
    static const char * const rdac_in_text[] = {
    	"Off", "Right Data", "Left Data", "Mono"
    };
    
    static SOC_ENUM_SINGLE_DECL(ldac_in_enum, AIC31XX_DACSETUP, 4, ldac_in_text);
    
    static SOC_ENUM_SINGLE_DECL(rdac_in_enum, AIC31XX_DACSETUP, 2, rdac_in_text);
    
    static const char * const mic_select_text[] = {
    	"Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm"
    };
    
    static SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6,
    	mic_select_text);
    static SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4,
    	mic_select_text);
    static SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2,
    	mic_select_text);
    
    static SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4,
    	mic_select_text);
    
    static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0);
    static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0);
    static const DECLARE_TLV_DB_SCALE(adc_cgain_tlv, -2000, 50, 0);
    static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, 0, 50, 0);
    static const DECLARE_TLV_DB_SCALE(hp_drv_tlv, 0, 100, 0);
    static const DECLARE_TLV_DB_SCALE(class_D_drv_tlv, 600, 600, 0);
    static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -6350, 50, 0);
    static const DECLARE_TLV_DB_SCALE(sp_vol_tlv, -6350, 50, 0);
    
    /*
     * controls to be exported to the user space
     */
    static const struct snd_kcontrol_new common31xx_snd_controls[] = {
    	SOC_DOUBLE_R_S_TLV("DAC Playback Volume", AIC31XX_LDACVOL,
    			   AIC31XX_RDACVOL, 0, -127, 48, 7, 0, dac_vol_tlv),
    
    	SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN,
    		     AIC31XX_HPRGAIN, 2, 1, 0),
    	SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN,
    			 AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv),
    
    	SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL,
    			 AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv),
    };
    
    static const struct snd_kcontrol_new aic31xx_snd_controls[] = {
    	SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1,
    		       adc_fgain_tlv),
    
    	SOC_SINGLE("ADC Capture Switch", AIC31XX_ADCFGA, 7, 1, 1),
    	SOC_DOUBLE_R_S_TLV("ADC Capture Volume", AIC31XX_ADCVOL, AIC31XX_ADCVOL,
    			   0, -24, 40, 6, 0, adc_cgain_tlv),
    
    	SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0,
    		       119, 0, mic_pga_tlv),
    };
    
    static const struct snd_kcontrol_new aic311x_snd_controls[] = {
    	SOC_DOUBLE_R("Speaker Driver Playback Switch", AIC31XX_SPLGAIN,
    		     AIC31XX_SPRGAIN, 2, 1, 0),
    	SOC_DOUBLE_R_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN,
    			 AIC31XX_SPRGAIN, 3, 3, 0, class_D_drv_tlv),
    
    	SOC_DOUBLE_R_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL,
    			 AIC31XX_RANALOGSPR, 0, 0x7F, 1, sp_vol_tlv),
    };
    
    static const struct snd_kcontrol_new aic310x_snd_controls[] = {
    	SOC_SINGLE("Speaker Driver Playback Switch", AIC31XX_SPLGAIN,
    		   2, 1, 0),
    	SOC_SINGLE_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN,
    		       3, 3, 0, class_D_drv_tlv),
    
    	SOC_SINGLE_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL,
    		       0, 0x7F, 1, sp_vol_tlv),
    };
    
    static const struct snd_kcontrol_new ldac_in_control =
    	SOC_DAPM_ENUM("DAC Left Input", ldac_in_enum);
    
    static const struct snd_kcontrol_new rdac_in_control =
    	SOC_DAPM_ENUM("DAC Right Input", rdac_in_enum);
    
    static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg,
    			     unsigned int mask, unsigned int wbits, int sleep,
    			     int count)
    {
    	unsigned int bits;
    	int counter = count;
    	int ret = regmap_read(aic31xx->regmap, reg, &bits);
    
    	while ((bits & mask) != wbits && counter && !ret) {
    		usleep_range(sleep, sleep * 2);
    		ret = regmap_read(aic31xx->regmap, reg, &bits);
    		counter--;
    	}
    	if ((bits & mask) != wbits) {
    		dev_err(aic31xx->dev,
    			"%s: Failed! 0x%x was 0x%x expected 0x%x (%d, 0x%x, %d us)\n",
    			__func__, reg, bits, wbits, ret, mask,
    			(count - counter) * sleep);
    		ret = -1;
    	}
    	return ret;
    }
    
    #define WIDGET_BIT(reg, shift) (((shift) << 8) | (reg))
    
    static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w,
    				    struct snd_kcontrol *kcontrol, int event)
    {
    	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    	unsigned int reg = AIC31XX_DACFLAG1;
    	unsigned int mask;
    
    	switch (WIDGET_BIT(w->reg, w->shift)) {
    	case WIDGET_BIT(AIC31XX_DACSETUP, 7):
    		mask = AIC31XX_LDACPWRSTATUS_MASK;
    		break;
    	case WIDGET_BIT(AIC31XX_DACSETUP, 6):
    		mask = AIC31XX_RDACPWRSTATUS_MASK;
    		break;
    	case WIDGET_BIT(AIC31XX_HPDRIVER, 7):
    		mask = AIC31XX_HPLDRVPWRSTATUS_MASK;
    		break;
    	case WIDGET_BIT(AIC31XX_HPDRIVER, 6):
    		mask = AIC31XX_HPRDRVPWRSTATUS_MASK;
    		break;
    	case WIDGET_BIT(AIC31XX_SPKAMP, 7):
    		mask = AIC31XX_SPLDRVPWRSTATUS_MASK;
    		break;
    	case WIDGET_BIT(AIC31XX_SPKAMP, 6):
    		mask = AIC31XX_SPRDRVPWRSTATUS_MASK;
    		break;
    	case WIDGET_BIT(AIC31XX_ADCSETUP, 7):
    		mask = AIC31XX_ADCPWRSTATUS_MASK;
    		reg = AIC31XX_ADCFLAG;
    		break;
    	default:
    		dev_err(component->dev, "Unknown widget '%s' calling %s\n",
    			w->name, __func__);
    		return -EINVAL;
    	}
    
    	switch (event) {
    	case SND_SOC_DAPM_POST_PMU:
    		return aic31xx_wait_bits(aic31xx, reg, mask, mask, 5000, 100);
    	case SND_SOC_DAPM_POST_PMD:
    		return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100);
    	default:
    		dev_dbg(component->dev,
    			"Unhandled dapm widget event %d from %s\n",
    			event, w->name);
    	}
    	return 0;
    }
    
    static const struct snd_kcontrol_new aic31xx_left_output_switches[] = {
    	SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0),
    	SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0),
    	SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0),
    };
    
    static const struct snd_kcontrol_new aic31xx_right_output_switches[] = {
    	SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0),
    	SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0),
    };
    
    static const struct snd_kcontrol_new dac31xx_left_output_switches[] = {
    	SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0),
    	SOC_DAPM_SINGLE("From AIN1", AIC31XX_DACMIXERROUTE, 5, 1, 0),
    	SOC_DAPM_SINGLE("From AIN2", AIC31XX_DACMIXERROUTE, 4, 1, 0),
    };
    
    static const struct snd_kcontrol_new dac31xx_right_output_switches[] = {
    	SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0),
    	SOC_DAPM_SINGLE("From AIN2", AIC31XX_DACMIXERROUTE, 1, 1, 0),
    };
    
    static const struct snd_kcontrol_new p_term_mic1lp =
    	SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum);
    
    static const struct snd_kcontrol_new p_term_mic1rp =
    	SOC_DAPM_ENUM("MIC1RP P-Terminal", mic1rp_p_enum);
    
    static const struct snd_kcontrol_new p_term_mic1lm =
    	SOC_DAPM_ENUM("MIC1LM P-Terminal", mic1lm_p_enum);
    
    static const struct snd_kcontrol_new m_term_mic1lm =
    	SOC_DAPM_ENUM("MIC1LM M-Terminal", mic1lm_m_enum);
    
    static const struct snd_kcontrol_new aic31xx_dapm_hpl_switch =
    	SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGHPL, 7, 1, 0);
    
    static const struct snd_kcontrol_new aic31xx_dapm_hpr_switch =
    	SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGHPR, 7, 1, 0);
    
    static const struct snd_kcontrol_new aic31xx_dapm_spl_switch =
    	SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGSPL, 7, 1, 0);
    
    static const struct snd_kcontrol_new aic31xx_dapm_spr_switch =
    	SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGSPR, 7, 1, 0);
    
    static int mic_bias_event(struct snd_soc_dapm_widget *w,
    			  struct snd_kcontrol *kcontrol, int event)
    {
    	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    
    	switch (event) {
    	case SND_SOC_DAPM_POST_PMU:
    		/* change mic bias voltage to user defined */
    		snd_soc_component_update_bits(component, AIC31XX_MICBIAS,
    				    AIC31XX_MICBIAS_MASK,
    				    aic31xx->micbias_vg <<
    				    AIC31XX_MICBIAS_SHIFT);
    		dev_dbg(component->dev, "%s: turned on\n", __func__);
    		break;
    	case SND_SOC_DAPM_PRE_PMD:
    		/* turn mic bias off */
    		snd_soc_component_update_bits(component, AIC31XX_MICBIAS,
    				    AIC31XX_MICBIAS_MASK, 0);
    		dev_dbg(component->dev, "%s: turned off\n", __func__);
    		break;
    	}
    	return 0;
    }
    
    static const struct snd_soc_dapm_widget common31xx_dapm_widgets[] = {
    	SND_SOC_DAPM_AIF_IN("AIF IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
    
    	SND_SOC_DAPM_MUX("DAC Left Input",
    			 SND_SOC_NOPM, 0, 0, &ldac_in_control),
    	SND_SOC_DAPM_MUX("DAC Right Input",
    			 SND_SOC_NOPM, 0, 0, &rdac_in_control),
    	/* DACs */
    	SND_SOC_DAPM_DAC_E("DAC Left", "Left Playback",
    			   AIC31XX_DACSETUP, 7, 0, aic31xx_dapm_power_event,
    			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
    
    	SND_SOC_DAPM_DAC_E("DAC Right", "Right Playback",
    			   AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event,
    			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
    
    	/* HP */
    	SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0,
    			    &aic31xx_dapm_hpl_switch),
    	SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0,
    			    &aic31xx_dapm_hpr_switch),
    
    	/* Output drivers */
    	SND_SOC_DAPM_OUT_DRV_E("HPL Driver", AIC31XX_HPDRIVER, 7, 0,
    			       NULL, 0, aic31xx_dapm_power_event,
    			       SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
    	SND_SOC_DAPM_OUT_DRV_E("HPR Driver", AIC31XX_HPDRIVER, 6, 0,
    			       NULL, 0, aic31xx_dapm_power_event,
    			       SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
    
    	/* Mic Bias */
    	SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event,
    			    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
    
    	/* Keep BCLK/WCLK enabled even if DAC/ADC is powered down */
    	SND_SOC_DAPM_SUPPLY("Activate I2S clocks", AIC31XX_IFACE2, 2, 0,
    			    NULL, 0),
    
    	/* Outputs */
    	SND_SOC_DAPM_OUTPUT("HPL"),
    	SND_SOC_DAPM_OUTPUT("HPR"),
    };
    
    static const struct snd_soc_dapm_widget dac31xx_dapm_widgets[] = {
    	/* Inputs */
    	SND_SOC_DAPM_INPUT("AIN1"),
    	SND_SOC_DAPM_INPUT("AIN2"),
    
    	/* Output Mixers */
    	SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0,
    			   dac31xx_left_output_switches,
    			   ARRAY_SIZE(dac31xx_left_output_switches)),
    	SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0,
    			   dac31xx_right_output_switches,
    			   ARRAY_SIZE(dac31xx_right_output_switches)),
    };
    
    static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = {
    	/* Inputs */
    	SND_SOC_DAPM_INPUT("MIC1LP"),
    	SND_SOC_DAPM_INPUT("MIC1RP"),
    	SND_SOC_DAPM_INPUT("MIC1LM"),
    
    	/* Input Selection to MIC_PGA */
    	SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0,
    			 &p_term_mic1lp),
    	SND_SOC_DAPM_MUX("MIC1RP P-Terminal", SND_SOC_NOPM, 0, 0,
    			 &p_term_mic1rp),
    	SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0,
    			 &p_term_mic1lm),
    
    	/* ADC */
    	SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0,
    			   aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
    			   SND_SOC_DAPM_POST_PMD),
    
    	SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0,
    			 &m_term_mic1lm),
    
    	/* Enabling & Disabling MIC Gain Ctl */
    	SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA,
    			 7, 1, NULL, 0),
    
    	/* Output Mixers */
    	SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0,
    			   aic31xx_left_output_switches,
    			   ARRAY_SIZE(aic31xx_left_output_switches)),
    	SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0,
    			   aic31xx_right_output_switches,
    			   ARRAY_SIZE(aic31xx_right_output_switches)),
    
    	SND_SOC_DAPM_AIF_OUT("AIF OUT", "Capture", 0, SND_SOC_NOPM, 0, 0),
    };
    
    static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = {
    	/* AIC3111 and AIC3110 have stereo class-D amplifier */
    	SND_SOC_DAPM_OUT_DRV_E("SPL ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0,
    			       aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
    			       SND_SOC_DAPM_POST_PMD),
    	SND_SOC_DAPM_OUT_DRV_E("SPR ClassD", AIC31XX_SPKAMP, 6, 0, NULL, 0,
    			       aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
    			       SND_SOC_DAPM_POST_PMD),
    	SND_SOC_DAPM_SWITCH("Speaker Left", SND_SOC_NOPM, 0, 0,
    			    &aic31xx_dapm_spl_switch),
    	SND_SOC_DAPM_SWITCH("Speaker Right", SND_SOC_NOPM, 0, 0,
    			    &aic31xx_dapm_spr_switch),
    	SND_SOC_DAPM_OUTPUT("SPL"),
    	SND_SOC_DAPM_OUTPUT("SPR"),
    };
    
    /* AIC3100 and AIC3120 have only mono class-D amplifier */
    static const struct snd_soc_dapm_widget aic310x_dapm_widgets[] = {
    	SND_SOC_DAPM_OUT_DRV_E("SPK ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0,
    			       aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU |
    			       SND_SOC_DAPM_POST_PMD),
    	SND_SOC_DAPM_SWITCH("Speaker", SND_SOC_NOPM, 0, 0,
    			    &aic31xx_dapm_spl_switch),
    	SND_SOC_DAPM_OUTPUT("SPK"),
    };
    
    static const struct snd_soc_dapm_route
    common31xx_audio_map[] = {
    	/* DAC Input Routing */
    	{"DAC Left Input", "Left Data", "AIF IN"},
    	{"DAC Left Input", "Right Data", "AIF IN"},
    	{"DAC Left Input", "Mono", "AIF IN"},
    	{"DAC Right Input", "Left Data", "AIF IN"},
    	{"DAC Right Input", "Right Data", "AIF IN"},
    	{"DAC Right Input", "Mono", "AIF IN"},
    	{"DAC Left", NULL, "DAC Left Input"},
    	{"DAC Right", NULL, "DAC Right Input"},
    
    	/* HPL path */
    	{"HP Left", "Switch", "Output Left"},
    	{"HPL Driver", NULL, "HP Left"},
    	{"HPL", NULL, "HPL Driver"},
    
    	/* HPR path */
    	{"HP Right", "Switch", "Output Right"},
    	{"HPR Driver", NULL, "HP Right"},
    	{"HPR", NULL, "HPR Driver"},
    };
    
    static const struct snd_soc_dapm_route
    dac31xx_audio_map[] = {
    	/* Left Output */
    	{"Output Left", "From Left DAC", "DAC Left"},
    	{"Output Left", "From AIN1", "AIN1"},
    	{"Output Left", "From AIN2", "AIN2"},
    
    	/* Right Output */
    	{"Output Right", "From Right DAC", "DAC Right"},
    	{"Output Right", "From AIN2", "AIN2"},
    };
    
    static const struct snd_soc_dapm_route
    aic31xx_audio_map[] = {
    	/* Mic input */
    	{"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"},
    	{"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"},
    	{"MIC1LP P-Terminal", "FFR 40 Ohm", "MIC1LP"},
    	{"MIC1RP P-Terminal", "FFR 10 Ohm", "MIC1RP"},
    	{"MIC1RP P-Terminal", "FFR 20 Ohm", "MIC1RP"},
    	{"MIC1RP P-Terminal", "FFR 40 Ohm", "MIC1RP"},
    	{"MIC1LM P-Terminal", "FFR 10 Ohm", "MIC1LM"},
    	{"MIC1LM P-Terminal", "FFR 20 Ohm", "MIC1LM"},
    	{"MIC1LM P-Terminal", "FFR 40 Ohm", "MIC1LM"},
    
    	{"MIC1LM M-Terminal", "FFR 10 Ohm", "MIC1LM"},
    	{"MIC1LM M-Terminal", "FFR 20 Ohm", "MIC1LM"},
    	{"MIC1LM M-Terminal", "FFR 40 Ohm", "MIC1LM"},
    
    	{"MIC_GAIN_CTL", NULL, "MIC1LP P-Terminal"},
    	{"MIC_GAIN_CTL", NULL, "MIC1RP P-Terminal"},
    	{"MIC_GAIN_CTL", NULL, "MIC1LM P-Terminal"},
    	{"MIC_GAIN_CTL", NULL, "MIC1LM M-Terminal"},
    
    	{"ADC", NULL, "MIC_GAIN_CTL"},
    
    	{"AIF OUT", NULL, "ADC"},
    
    	/* Left Output */
    	{"Output Left", "From Left DAC", "DAC Left"},
    	{"Output Left", "From MIC1LP", "MIC1LP"},
    	{"Output Left", "From MIC1RP", "MIC1RP"},
    
    	/* Right Output */
    	{"Output Right", "From Right DAC", "DAC Right"},
    	{"Output Right", "From MIC1RP", "MIC1RP"},
    };
    
    static const struct snd_soc_dapm_route
    aic311x_audio_map[] = {
    	/* SP L path */
    	{"Speaker Left", "Switch", "Output Left"},
    	{"SPL ClassD", NULL, "Speaker Left"},
    	{"SPL", NULL, "SPL ClassD"},
    
    	/* SP R path */
    	{"Speaker Right", "Switch", "Output Right"},
    	{"SPR ClassD", NULL, "Speaker Right"},
    	{"SPR", NULL, "SPR ClassD"},
    };
    
    static const struct snd_soc_dapm_route
    aic310x_audio_map[] = {
    	/* SP L path */
    	{"Speaker", "Switch", "Output Left"},
    	{"SPK ClassD", NULL, "Speaker"},
    	{"SPK", NULL, "SPK ClassD"},
    };
    
    /*
     * Always connected DAPM routes for codec clock master modes.
     * If the codec is the master on the I2S bus, we need to power up components
     * to have valid DAC_CLK.
     *
     * In order to have the I2S clocks on the bus either the DACs/ADC need to be
     * enabled, or the P0/R29/D2 (Keep bclk/wclk in power down) need to be set.
     *
     * Otherwise the codec will not generate clocks on the bus.
     */
    static const struct snd_soc_dapm_route
    common31xx_cm_audio_map[] = {
    	{"HPL", NULL, "AIF IN"},
    	{"HPR", NULL, "AIF IN"},
    
    	{"AIF IN", NULL, "Activate I2S clocks"},
    };
    
    static const struct snd_soc_dapm_route
    aic31xx_cm_audio_map[] = {
    	{"AIF OUT", NULL, "MIC1LP"},
    	{"AIF OUT", NULL, "MIC1RP"},
    	{"AIF OUT", NULL, "MIC1LM"},
    
    	{"AIF OUT", NULL, "Activate I2S clocks"},
    };
    
    static int aic31xx_add_controls(struct snd_soc_component *component)
    {
    	int ret = 0;
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    
    	if (!(aic31xx->codec_type & DAC31XX_BIT))
    		ret = snd_soc_add_component_controls(
    			component, aic31xx_snd_controls,
    			ARRAY_SIZE(aic31xx_snd_controls));
    	if (ret)
    		return ret;
    
    	if (aic31xx->codec_type & AIC31XX_STEREO_CLASS_D_BIT)
    		ret = snd_soc_add_component_controls(
    			component, aic311x_snd_controls,
    			ARRAY_SIZE(aic311x_snd_controls));
    	else
    		ret = snd_soc_add_component_controls(
    			component, aic310x_snd_controls,
    			ARRAY_SIZE(aic310x_snd_controls));
    
    	return ret;
    }
    
    static int aic31xx_add_widgets(struct snd_soc_component *component)
    {
    	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    	int ret = 0;
    
    	if (aic31xx->codec_type & DAC31XX_BIT) {
    		ret = snd_soc_dapm_new_controls(
    			dapm, dac31xx_dapm_widgets,
    			ARRAY_SIZE(dac31xx_dapm_widgets));
    		if (ret)
    			return ret;
    
    		ret = snd_soc_dapm_add_routes(dapm, dac31xx_audio_map,
    					      ARRAY_SIZE(dac31xx_audio_map));
    		if (ret)
    			return ret;
    	} else {
    		ret = snd_soc_dapm_new_controls(
    			dapm, aic31xx_dapm_widgets,
    			ARRAY_SIZE(aic31xx_dapm_widgets));
    		if (ret)
    			return ret;
    
    		ret = snd_soc_dapm_add_routes(dapm, aic31xx_audio_map,
    					      ARRAY_SIZE(aic31xx_audio_map));
    		if (ret)
    			return ret;
    	}
    
    	if (aic31xx->codec_type & AIC31XX_STEREO_CLASS_D_BIT) {
    		ret = snd_soc_dapm_new_controls(
    			dapm, aic311x_dapm_widgets,
    			ARRAY_SIZE(aic311x_dapm_widgets));
    		if (ret)
    			return ret;
    
    		ret = snd_soc_dapm_add_routes(dapm, aic311x_audio_map,
    					      ARRAY_SIZE(aic311x_audio_map));
    		if (ret)
    			return ret;
    	} else {
    		ret = snd_soc_dapm_new_controls(
    			dapm, aic310x_dapm_widgets,
    			ARRAY_SIZE(aic310x_dapm_widgets));
    		if (ret)
    			return ret;
    
    		ret = snd_soc_dapm_add_routes(dapm, aic310x_audio_map,
    					      ARRAY_SIZE(aic310x_audio_map));
    		if (ret)
    			return ret;
    	}
    
    	return 0;
    }
    
    static int aic31xx_setup_pll(struct snd_soc_component *component,
    			     struct snd_pcm_hw_params *params)
    {
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    	int bclk_score = snd_soc_params_to_frame_size(params);
    	int mclk_p;
    	int bclk_n = 0;
    	int match = -1;
    	int i;
    
    	if (!aic31xx->sysclk || !aic31xx->p_div) {
    		dev_err(component->dev, "Master clock not supplied\n");
    		return -EINVAL;
    	}
    	mclk_p = aic31xx->sysclk / aic31xx->p_div;
    
    	/* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */
    	snd_soc_component_update_bits(component, AIC31XX_CLKMUX,
    			    AIC31XX_CODEC_CLKIN_MASK, AIC31XX_CODEC_CLKIN_PLL);
    	snd_soc_component_update_bits(component, AIC31XX_IFACE2,
    			    AIC31XX_BDIVCLK_MASK, AIC31XX_DAC2BCLK);
    
    	for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) {
    		if (aic31xx_divs[i].rate == params_rate(params) &&
    		    aic31xx_divs[i].mclk_p == mclk_p) {
    			int s =	(aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) %
    				snd_soc_params_to_frame_size(params);
    			int bn = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) /
    				snd_soc_params_to_frame_size(params);
    			if (s < bclk_score && bn > 0) {
    				match = i;
    				bclk_n = bn;
    				bclk_score = s;
    			}
    		}
    	}
    
    	if (match == -1) {
    		dev_err(component->dev,
    			"%s: Sample rate (%u) and format not supported\n",
    			__func__, params_rate(params));
    		/* See bellow for details how fix this. */
    		return -EINVAL;
    	}
    	if (bclk_score != 0) {
    		dev_warn(component->dev, "Can not produce exact bitclock");
    		/* This is fine if using dsp format, but if using i2s
    		   there may be trouble. To fix the issue edit the
    		   aic31xx_divs table for your mclk and sample
    		   rate. Details can be found from:
    		   http://www.ti.com/lit/ds/symlink/tlv320aic3100.pdf
    		   Section: 5.6 CLOCK Generation and PLL
    		*/
    	}
    	i = match;
    
    	/* PLL configuration */
    	snd_soc_component_update_bits(component, AIC31XX_PLLPR, AIC31XX_PLL_MASK,
    			    (aic31xx->p_div << 4) | 0x01);
    	snd_soc_component_write(component, AIC31XX_PLLJ, aic31xx_divs[i].pll_j);
    
    	snd_soc_component_write(component, AIC31XX_PLLDMSB,
    		      aic31xx_divs[i].pll_d >> 8);
    	snd_soc_component_write(component, AIC31XX_PLLDLSB,
    		      aic31xx_divs[i].pll_d & 0xff);
    
    	/* DAC dividers configuration */
    	snd_soc_component_update_bits(component, AIC31XX_NDAC, AIC31XX_PLL_MASK,
    			    aic31xx_divs[i].ndac);
    	snd_soc_component_update_bits(component, AIC31XX_MDAC, AIC31XX_PLL_MASK,
    			    aic31xx_divs[i].mdac);
    
    	snd_soc_component_write(component, AIC31XX_DOSRMSB, aic31xx_divs[i].dosr >> 8);
    	snd_soc_component_write(component, AIC31XX_DOSRLSB, aic31xx_divs[i].dosr & 0xff);
    
    	/* ADC dividers configuration. Write reset value 1 if not used. */
    	snd_soc_component_update_bits(component, AIC31XX_NADC, AIC31XX_PLL_MASK,
    			    aic31xx_divs[i].nadc ? aic31xx_divs[i].nadc : 1);
    	snd_soc_component_update_bits(component, AIC31XX_MADC, AIC31XX_PLL_MASK,
    			    aic31xx_divs[i].madc ? aic31xx_divs[i].madc : 1);
    
    	snd_soc_component_write(component, AIC31XX_AOSR, aic31xx_divs[i].aosr);
    
    	/* Bit clock divider configuration. */
    	snd_soc_component_update_bits(component, AIC31XX_BCLKN,
    			    AIC31XX_PLL_MASK, bclk_n);
    
    	aic31xx->rate_div_line = i;
    
    	dev_dbg(component->dev,
    		"pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n",
    		aic31xx_divs[i].pll_j,
    		aic31xx_divs[i].pll_d,
    		aic31xx->p_div,
    		aic31xx_divs[i].dosr,
    		aic31xx_divs[i].ndac,
    		aic31xx_divs[i].mdac,
    		aic31xx_divs[i].aosr,
    		aic31xx_divs[i].nadc,
    		aic31xx_divs[i].madc,
    		bclk_n
    	);
    
    	return 0;
    }
    
    static int aic31xx_hw_params(struct snd_pcm_substream *substream,
    			     struct snd_pcm_hw_params *params,
    			     struct snd_soc_dai *dai)
    {
    	struct snd_soc_component *component = dai->component;
    	u8 data = 0;
    
    	dev_dbg(component->dev, "## %s: width %d rate %d\n",
    		__func__, params_width(params),
    		params_rate(params));
    
    	switch (params_width(params)) {
    	case 16:
    		break;
    	case 20:
    		data = (AIC31XX_WORD_LEN_20BITS <<
    			AIC31XX_IFACE1_DATALEN_SHIFT);
    		break;
    	case 24:
    		data = (AIC31XX_WORD_LEN_24BITS <<
    			AIC31XX_IFACE1_DATALEN_SHIFT);
    		break;
    	case 32:
    		data = (AIC31XX_WORD_LEN_32BITS <<
    			AIC31XX_IFACE1_DATALEN_SHIFT);
    		break;
    	default:
    		dev_err(component->dev, "%s: Unsupported width %d\n",
    			__func__, params_width(params));
    		return -EINVAL;
    	}
    
    	snd_soc_component_update_bits(component, AIC31XX_IFACE1,
    			    AIC31XX_IFACE1_DATALEN_MASK,
    			    data);
    
    	return aic31xx_setup_pll(component, params);
    }
    
    static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute)
    {
    	struct snd_soc_component *component = codec_dai->component;
    
    	if (mute) {
    		snd_soc_component_update_bits(component, AIC31XX_DACMUTE,
    				    AIC31XX_DACMUTE_MASK,
    				    AIC31XX_DACMUTE_MASK);
    	} else {
    		snd_soc_component_update_bits(component, AIC31XX_DACMUTE,
    				    AIC31XX_DACMUTE_MASK, 0x0);
    	}
    
    	return 0;
    }
    
    static int aic31xx_clock_master_routes(struct snd_soc_component *component,
    				       unsigned int fmt)
    {
    	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    	int ret;
    
    	fmt &= SND_SOC_DAIFMT_MASTER_MASK;
    	if (fmt == SND_SOC_DAIFMT_CBS_CFS &&
    	    aic31xx->master_dapm_route_applied) {
    		/*
    		 * Remove the DAPM route(s) for codec clock master modes,
    		 * if applied
    		 */
    		ret = snd_soc_dapm_del_routes(dapm, common31xx_cm_audio_map,
    					ARRAY_SIZE(common31xx_cm_audio_map));
    		if (!ret && !(aic31xx->codec_type & DAC31XX_BIT))
    			ret = snd_soc_dapm_del_routes(dapm,
    					aic31xx_cm_audio_map,
    					ARRAY_SIZE(aic31xx_cm_audio_map));
    
    		if (ret)
    			return ret;
    
    		aic31xx->master_dapm_route_applied = false;
    	} else if (fmt != SND_SOC_DAIFMT_CBS_CFS &&
    		   !aic31xx->master_dapm_route_applied) {
    		/*
    		 * Add the needed DAPM route(s) for codec clock master modes,
    		 * if it is not done already
    		 */
    		ret = snd_soc_dapm_add_routes(dapm, common31xx_cm_audio_map,
    					ARRAY_SIZE(common31xx_cm_audio_map));
    		if (!ret && !(aic31xx->codec_type & DAC31XX_BIT))
    			ret = snd_soc_dapm_add_routes(dapm,
    					aic31xx_cm_audio_map,
    					ARRAY_SIZE(aic31xx_cm_audio_map));
    
    		if (ret)
    			return ret;
    
    		aic31xx->master_dapm_route_applied = true;
    	}
    
    	return 0;
    }
    
    static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai,
    			       unsigned int fmt)
    {
    	struct snd_soc_component *component = codec_dai->component;
    	u8 iface_reg1 = 0;
    	u8 iface_reg2 = 0;
    	u8 dsp_a_val = 0;
    
    	dev_dbg(component->dev, "## %s: fmt = 0x%x\n", __func__, fmt);
    
    	/* set master/slave audio interface */
    	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
    	case SND_SOC_DAIFMT_CBM_CFM:
    		iface_reg1 |= AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER;
    		break;
    	case SND_SOC_DAIFMT_CBS_CFM:
    		iface_reg1 |= AIC31XX_WCLK_MASTER;
    		break;
    	case SND_SOC_DAIFMT_CBM_CFS:
    		iface_reg1 |= AIC31XX_BCLK_MASTER;
    		break;
    	case SND_SOC_DAIFMT_CBS_CFS:
    		break;
    	default:
    		dev_err(component->dev, "Invalid DAI master/slave interface\n");
    		return -EINVAL;
    	}
    
    	/* signal polarity */
    	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
    	case SND_SOC_DAIFMT_NB_NF:
    		break;
    	case SND_SOC_DAIFMT_IB_NF:
    		iface_reg2 |= AIC31XX_BCLKINV_MASK;
    		break;
    	default:
    		dev_err(component->dev, "Invalid DAI clock signal polarity\n");
    		return -EINVAL;
    	}
    
    	/* interface format */
    	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    	case SND_SOC_DAIFMT_I2S:
    		break;
    	case SND_SOC_DAIFMT_DSP_A:
    		dsp_a_val = 0x1; /* fall through */
    	case SND_SOC_DAIFMT_DSP_B:
    		/*
    		 * NOTE: This CODEC samples on the falling edge of BCLK in
    		 * DSP mode, this is inverted compared to what most DAIs
    		 * expect, so we invert for this mode
    		 */
    		iface_reg2 ^= AIC31XX_BCLKINV_MASK;
    		iface_reg1 |= (AIC31XX_DSP_MODE <<
    			       AIC31XX_IFACE1_DATATYPE_SHIFT);
    		break;
    	case SND_SOC_DAIFMT_RIGHT_J:
    		iface_reg1 |= (AIC31XX_RIGHT_JUSTIFIED_MODE <<
    			       AIC31XX_IFACE1_DATATYPE_SHIFT);
    		break;
    	case SND_SOC_DAIFMT_LEFT_J:
    		iface_reg1 |= (AIC31XX_LEFT_JUSTIFIED_MODE <<
    			       AIC31XX_IFACE1_DATATYPE_SHIFT);
    		break;
    	default:
    		dev_err(component->dev, "Invalid DAI interface format\n");
    		return -EINVAL;
    	}
    
    	snd_soc_component_update_bits(component, AIC31XX_IFACE1,
    			    AIC31XX_IFACE1_DATATYPE_MASK |
    			    AIC31XX_IFACE1_MASTER_MASK,
    			    iface_reg1);
    	snd_soc_component_update_bits(component, AIC31XX_DATA_OFFSET,
    			    AIC31XX_DATA_OFFSET_MASK,
    			    dsp_a_val);
    	snd_soc_component_update_bits(component, AIC31XX_IFACE2,
    			    AIC31XX_BCLKINV_MASK,
    			    iface_reg2);
    
    	return aic31xx_clock_master_routes(component, fmt);
    }
    
    static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
    				  int clk_id, unsigned int freq, int dir)
    {
    	struct snd_soc_component *component = codec_dai->component;
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    	int i;
    
    	dev_dbg(component->dev, "## %s: clk_id = %d, freq = %d, dir = %d\n",
    		__func__, clk_id, freq, dir);
    
    	for (i = 1; i < 8; i++)
    		if (freq / i <= 20000000)
    			break;
    	if (freq/i > 20000000) {
    		dev_err(aic31xx->dev, "%s: Too high mclk frequency %u\n",
    			__func__, freq);
    		return -EINVAL;
    	}
    	aic31xx->p_div = i;
    
    	for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++)
    		if (aic31xx_divs[i].mclk_p == freq / aic31xx->p_div)
    			break;
    	if (i == ARRAY_SIZE(aic31xx_divs)) {
    		dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n",
    			__func__, freq);
    		return -EINVAL;
    	}
    
    	/* set clock on MCLK, BCLK, or GPIO1 as PLL input */
    	snd_soc_component_update_bits(component, AIC31XX_CLKMUX, AIC31XX_PLL_CLKIN_MASK,
    			    clk_id << AIC31XX_PLL_CLKIN_SHIFT);
    
    	aic31xx->sysclk = freq;
    
    	return 0;
    }
    
    static int aic31xx_regulator_event(struct notifier_block *nb,
    				   unsigned long event, void *data)
    {
    	struct aic31xx_disable_nb *disable_nb =
    		container_of(nb, struct aic31xx_disable_nb, nb);
    	struct aic31xx_priv *aic31xx = disable_nb->aic31xx;
    
    	if (event & REGULATOR_EVENT_DISABLE) {
    		/*
    		 * Put codec to reset and as at least one of the
    		 * supplies was disabled.
    		 */
    		if (aic31xx->gpio_reset)
    			gpiod_set_value(aic31xx->gpio_reset, 1);
    
    		regcache_mark_dirty(aic31xx->regmap);
    		dev_dbg(aic31xx->dev, "## %s: DISABLE received\n", __func__);
    	}
    
    	return 0;
    }
    
    static int aic31xx_reset(struct aic31xx_priv *aic31xx)
    {
    	int ret = 0;
    
    	if (aic31xx->gpio_reset) {
    		gpiod_set_value(aic31xx->gpio_reset, 1);
    		ndelay(10); /* At least 10ns */
    		gpiod_set_value(aic31xx->gpio_reset, 0);
    	} else {
    		ret = regmap_write(aic31xx->regmap, AIC31XX_RESET, 1);
    	}
    	mdelay(1); /* At least 1ms */
    
    	return ret;
    }
    
    static void aic31xx_clk_on(struct snd_soc_component *component)
    {
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    	u8 mask = AIC31XX_PM_MASK;
    	u8 on = AIC31XX_PM_MASK;
    
    	dev_dbg(component->dev, "codec clock -> on (rate %d)\n",
    		aic31xx_divs[aic31xx->rate_div_line].rate);
    	snd_soc_component_update_bits(component, AIC31XX_PLLPR, mask, on);
    	mdelay(10);
    	snd_soc_component_update_bits(component, AIC31XX_NDAC, mask, on);
    	snd_soc_component_update_bits(component, AIC31XX_MDAC, mask, on);
    	if (aic31xx_divs[aic31xx->rate_div_line].nadc)
    		snd_soc_component_update_bits(component, AIC31XX_NADC, mask, on);
    	if (aic31xx_divs[aic31xx->rate_div_line].madc)
    		snd_soc_component_update_bits(component, AIC31XX_MADC, mask, on);
    	snd_soc_component_update_bits(component, AIC31XX_BCLKN, mask, on);
    }
    
    static void aic31xx_clk_off(struct snd_soc_component *component)
    {
    	u8 mask = AIC31XX_PM_MASK;
    	u8 off = 0;
    
    	dev_dbg(component->dev, "codec clock -> off\n");
    	snd_soc_component_update_bits(component, AIC31XX_BCLKN, mask, off);
    	snd_soc_component_update_bits(component, AIC31XX_MADC, mask, off);
    	snd_soc_component_update_bits(component, AIC31XX_NADC, mask, off);
    	snd_soc_component_update_bits(component, AIC31XX_MDAC, mask, off);
    	snd_soc_component_update_bits(component, AIC31XX_NDAC, mask, off);
    	snd_soc_component_update_bits(component, AIC31XX_PLLPR, mask, off);
    }
    
    static int aic31xx_power_on(struct snd_soc_component *component)
    {
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    	int ret;
    
    	ret = regulator_bulk_enable(ARRAY_SIZE(aic31xx->supplies),
    				    aic31xx->supplies);
    	if (ret)
    		return ret;
    
    	regcache_cache_only(aic31xx->regmap, false);
    
    	/* Reset device registers for a consistent power-on like state */
    	ret = aic31xx_reset(aic31xx);
    	if (ret < 0)
    		dev_err(aic31xx->dev, "Could not reset device: %d\n", ret);
    
    	ret = regcache_sync(aic31xx->regmap);
    	if (ret) {
    		dev_err(component->dev,
    			"Failed to restore cache: %d\n", ret);
    		regcache_cache_only(aic31xx->regmap, true);
    		regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies),
    				       aic31xx->supplies);
    		return ret;
    	}
    
    	return 0;
    }
    
    static void aic31xx_power_off(struct snd_soc_component *component)
    {
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    
    	regcache_cache_only(aic31xx->regmap, true);
    	regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies),
    			       aic31xx->supplies);
    }
    
    static int aic31xx_set_bias_level(struct snd_soc_component *component,
    				  enum snd_soc_bias_level level)
    {
    	dev_dbg(component->dev, "## %s: %d -> %d\n", __func__,
    		snd_soc_component_get_bias_level(component), level);
    
    	switch (level) {
    	case SND_SOC_BIAS_ON:
    		break;
    	case SND_SOC_BIAS_PREPARE:
    		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_STANDBY)
    			aic31xx_clk_on(component);
    		break;
    	case SND_SOC_BIAS_STANDBY:
    		switch (snd_soc_component_get_bias_level(component)) {
    		case SND_SOC_BIAS_OFF:
    			aic31xx_power_on(component);
    			break;
    		case SND_SOC_BIAS_PREPARE:
    			aic31xx_clk_off(component);
    			break;
    		default:
    			BUG();
    		}
    		break;
    	case SND_SOC_BIAS_OFF:
    		if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_STANDBY)
    			aic31xx_power_off(component);
    		break;
    	}
    
    	return 0;
    }
    
    static int aic31xx_set_jack(struct snd_soc_component *component,
    			    struct snd_soc_jack *jack, void *data)
    {
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    
    	aic31xx->jack = jack;
    
    	/* Enable/Disable jack detection */
    	regmap_write(aic31xx->regmap, AIC31XX_HSDETECT,
    		     jack ? AIC31XX_HSD_ENABLE : 0);
    
    	return 0;
    }
    
    static int aic31xx_codec_probe(struct snd_soc_component *component)
    {
    	struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component);
    	int i, ret;
    
    	dev_dbg(aic31xx->dev, "## %s\n", __func__);
    
    	aic31xx->component = component;
    
    	for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) {
    		aic31xx->disable_nb[i].nb.notifier_call =
    			aic31xx_regulator_event;
    		aic31xx->disable_nb[i].aic31xx = aic31xx;
    		ret = devm_regulator_register_notifier(
    						aic31xx->supplies[i].consumer,
    						&aic31xx->disable_nb[i].nb);
    		if (ret) {
    			dev_err(component->dev,
    				"Failed to request regulator notifier: %d\n",
    				ret);
    			return ret;
    		}
    	}
    
    	regcache_cache_only(aic31xx->regmap, true);
    	regcache_mark_dirty(aic31xx->regmap);
    
    	ret = aic31xx_add_controls(component);
    	if (ret)
    		return ret;
    
    	ret = aic31xx_add_widgets(component);
    	if (ret)
    		return ret;
    
    	return 0;
    }
    
    static const struct snd_soc_component_driver soc_codec_driver_aic31xx = {
    	.probe			= aic31xx_codec_probe,
    	.set_jack		= aic31xx_set_jack,
    	.set_bias_level		= aic31xx_set_bias_level,
    	.controls		= common31xx_snd_controls,
    	.num_controls		= ARRAY_SIZE(common31xx_snd_controls),
    	.dapm_widgets		= common31xx_dapm_widgets,
    	.num_dapm_widgets	= ARRAY_SIZE(common31xx_dapm_widgets),
    	.dapm_routes		= common31xx_audio_map,
    	.num_dapm_routes	= ARRAY_SIZE(common31xx_audio_map),
    	.suspend_bias_off	= 1,
    	.idle_bias_on		= 1,
    	.use_pmdown_time	= 1,
    	.endianness		= 1,
    	.non_legacy_dai_naming	= 1,
    };
    
    static const struct snd_soc_dai_ops aic31xx_dai_ops = {
    	.hw_params	= aic31xx_hw_params,
    	.set_sysclk	= aic31xx_set_dai_sysclk,
    	.set_fmt	= aic31xx_set_dai_fmt,
    	.digital_mute	= aic31xx_dac_mute,
    };
    
    static struct snd_soc_dai_driver dac31xx_dai_driver[] = {
    	{
    		.name = "tlv320dac31xx-hifi",
    		.playback = {
    			.stream_name	 = "Playback",
    			.channels_min	 = 2,
    			.channels_max	 = 2,
    			.rates		 = AIC31XX_RATES,
    			.formats	 = AIC31XX_FORMATS,
    		},
    		.ops = &aic31xx_dai_ops,
    		.symmetric_rates = 1,
    	}
    };
    
    static struct snd_soc_dai_driver aic31xx_dai_driver[] = {
    	{
    		.name = "tlv320aic31xx-hifi",
    		.playback = {
    			.stream_name	 = "Playback",
    			.channels_min	 = 2,
    			.channels_max	 = 2,
    			.rates		 = AIC31XX_RATES,
    			.formats	 = AIC31XX_FORMATS,
    		},
    		.capture = {
    			.stream_name	 = "Capture",
    			.channels_min	 = 2,
    			.channels_max	 = 2,
    			.rates		 = AIC31XX_RATES,
    			.formats	 = AIC31XX_FORMATS,
    		},
    		.ops = &aic31xx_dai_ops,
    		.symmetric_rates = 1,
    	}
    };
    
    #if defined(CONFIG_OF)
    static const struct of_device_id tlv320aic31xx_of_match[] = {
    	{ .compatible = "ti,tlv320aic310x" },
    	{ .compatible = "ti,tlv320aic311x" },
    	{ .compatible = "ti,tlv320aic3100" },
    	{ .compatible = "ti,tlv320aic3110" },
    	{ .compatible = "ti,tlv320aic3120" },
    	{ .compatible = "ti,tlv320aic3111" },
    	{ .compatible = "ti,tlv320dac3100" },
    	{ .compatible = "ti,tlv320dac3101" },
    	{},
    };
    MODULE_DEVICE_TABLE(of, tlv320aic31xx_of_match);
    #endif /* CONFIG_OF */
    
    #ifdef CONFIG_ACPI
    static const struct acpi_device_id aic31xx_acpi_match[] = {
    	{ "10TI3100", 0 },
    	{ }
    };
    MODULE_DEVICE_TABLE(acpi, aic31xx_acpi_match);
    #endif
    
    static irqreturn_t aic31xx_irq(int irq, void *data)
    {
    	struct aic31xx_priv *aic31xx = data;
    	struct device *dev = aic31xx->dev;
    	unsigned int value;
    	bool handled = false;
    	int ret;
    
    	ret = regmap_read(aic31xx->regmap, AIC31XX_INTRDACFLAG, &value);
    	if (ret) {
    		dev_err(dev, "Failed to read interrupt mask: %d\n", ret);
    		goto exit;
    	}
    
    	if (value)
    		handled = true;
    	else
    		goto read_overflow;
    
    	if (value & AIC31XX_HPLSCDETECT)
    		dev_err(dev, "Short circuit on Left output is detected\n");
    	if (value & AIC31XX_HPRSCDETECT)
    		dev_err(dev, "Short circuit on Right output is detected\n");
    	if (value & (AIC31XX_HSPLUG | AIC31XX_BUTTONPRESS)) {
    		unsigned int val;
    		int status = 0;
    
    		ret = regmap_read(aic31xx->regmap, AIC31XX_INTRDACFLAG2,
    				  &val);
    		if (ret) {
    			dev_err(dev, "Failed to read interrupt mask: %d\n",
    				ret);
    			goto exit;
    		}
    
    		if (val & AIC31XX_BUTTONPRESS)
    			status |= SND_JACK_BTN_0;
    
    		ret = regmap_read(aic31xx->regmap, AIC31XX_HSDETECT, &val);
    		if (ret) {
    			dev_err(dev, "Failed to read headset type: %d\n", ret);
    			goto exit;
    		}
    
    		switch ((val & AIC31XX_HSD_TYPE_MASK) >>
    			AIC31XX_HSD_TYPE_SHIFT) {
    		case AIC31XX_HSD_HP:
    			status |= SND_JACK_HEADPHONE;
    			break;
    		case AIC31XX_HSD_HS:
    			status |= SND_JACK_HEADSET;
    			break;
    		default:
    			break;
    		}
    
    		if (aic31xx->jack)
    			snd_soc_jack_report(aic31xx->jack, status,
    					    AIC31XX_JACK_MASK);
    	}
    	if (value & ~(AIC31XX_HPLSCDETECT |
    		      AIC31XX_HPRSCDETECT |
    		      AIC31XX_HSPLUG |
    		      AIC31XX_BUTTONPRESS))
    		dev_err(dev, "Unknown DAC interrupt flags: 0x%08x\n", value);
    
    read_overflow:
    	ret = regmap_read(aic31xx->regmap, AIC31XX_OFFLAG, &value);
    	if (ret) {
    		dev_err(dev, "Failed to read overflow flag: %d\n", ret);
    		goto exit;
    	}
    
    	if (value)
    		handled = true;
    	else
    		goto exit;
    
    	if (value & AIC31XX_DAC_OF_LEFT)
    		dev_warn(dev, "Left-channel DAC overflow has occurred\n");
    	if (value & AIC31XX_DAC_OF_RIGHT)
    		dev_warn(dev, "Right-channel DAC overflow has occurred\n");
    	if (value & AIC31XX_DAC_OF_SHIFTER)
    		dev_warn(dev, "DAC barrel shifter overflow has occurred\n");
    	if (value & AIC31XX_ADC_OF)
    		dev_warn(dev, "ADC overflow has occurred\n");
    	if (value & AIC31XX_ADC_OF_SHIFTER)
    		dev_warn(dev, "ADC barrel shifter overflow has occurred\n");
    	if (value & ~(AIC31XX_DAC_OF_LEFT |
    		      AIC31XX_DAC_OF_RIGHT |
    		      AIC31XX_DAC_OF_SHIFTER |
    		      AIC31XX_ADC_OF |
    		      AIC31XX_ADC_OF_SHIFTER))
    		dev_warn(dev, "Unknown overflow interrupt flags: 0x%08x\n", value);
    
    exit:
    	if (handled)
    		return IRQ_HANDLED;
    	else
    		return IRQ_NONE;
    }
    
    static int aic31xx_i2c_probe(struct i2c_client *i2c,
    			     const struct i2c_device_id *id)
    {
    	struct aic31xx_priv *aic31xx;
    	unsigned int micbias_value = MICBIAS_2_0V;
    	int i, ret;
    
    	dev_dbg(&i2c->dev, "## %s: %s codec_type = %d\n", __func__,
    		id->name, (int)id->driver_data);
    
    	aic31xx = devm_kzalloc(&i2c->dev, sizeof(*aic31xx), GFP_KERNEL);
    	if (!aic31xx)
    		return -ENOMEM;
    
    	aic31xx->regmap = devm_regmap_init_i2c(i2c, &aic31xx_i2c_regmap);
    	if (IS_ERR(aic31xx->regmap)) {
    		ret = PTR_ERR(aic31xx->regmap);
    		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
    			ret);
    		return ret;
    	}
    	aic31xx->dev = &i2c->dev;
    	aic31xx->irq = i2c->irq;
    
    	aic31xx->codec_type = id->driver_data;
    
    	dev_set_drvdata(aic31xx->dev, aic31xx);
    
    	fwnode_property_read_u32(aic31xx->dev->fwnode, "ai31xx-micbias-vg",
    				 &micbias_value);
    	switch (micbias_value) {
    	case MICBIAS_2_0V:
    	case MICBIAS_2_5V:
    	case MICBIAS_AVDDV:
    		aic31xx->micbias_vg = micbias_value;
    		break;
    	default:
    		dev_err(aic31xx->dev, "Bad ai31xx-micbias-vg value %d\n",
    			micbias_value);
    		aic31xx->micbias_vg = MICBIAS_2_0V;
    	}
    
    	if (dev_get_platdata(aic31xx->dev)) {
    		memcpy(&aic31xx->pdata, dev_get_platdata(aic31xx->dev), sizeof(aic31xx->pdata));
    		aic31xx->codec_type = aic31xx->pdata.codec_type;
    		aic31xx->micbias_vg = aic31xx->pdata.micbias_vg;
    	}
    
    	aic31xx->gpio_reset = devm_gpiod_get_optional(aic31xx->dev, "reset",
    						      GPIOD_OUT_LOW);
    	if (IS_ERR(aic31xx->gpio_reset)) {
    		if (PTR_ERR(aic31xx->gpio_reset) != -EPROBE_DEFER)
    			dev_err(aic31xx->dev, "not able to acquire gpio\n");
    		return PTR_ERR(aic31xx->gpio_reset);
    	}
    
    	for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++)
    		aic31xx->supplies[i].supply = aic31xx_supply_names[i];
    
    	ret = devm_regulator_bulk_get(aic31xx->dev,
    				      ARRAY_SIZE(aic31xx->supplies),
    				      aic31xx->supplies);
    	if (ret) {
    		if (ret != -EPROBE_DEFER)
    			dev_err(aic31xx->dev,
    				"Failed to request supplies: %d\n", ret);
    		return ret;
    	}
    
    	if (aic31xx->irq > 0) {
    		regmap_update_bits(aic31xx->regmap, AIC31XX_GPIO1,
    				   AIC31XX_GPIO1_FUNC_MASK,
    				   AIC31XX_GPIO1_INT1 <<
    				   AIC31XX_GPIO1_FUNC_SHIFT);
    
    		regmap_write(aic31xx->regmap, AIC31XX_INT1CTRL,
    			     AIC31XX_HSPLUGDET |
    			     AIC31XX_BUTTONPRESSDET |
    			     AIC31XX_SC |
    			     AIC31XX_ENGINE);
    
    		ret = devm_request_threaded_irq(aic31xx->dev, aic31xx->irq,
    						NULL, aic31xx_irq,
    						IRQF_ONESHOT, "aic31xx-irq",
    						aic31xx);
    		if (ret) {
    			dev_err(aic31xx->dev, "Unable to request IRQ\n");
    			return ret;
    		}
    	}
    
    	if (aic31xx->codec_type & DAC31XX_BIT)
    		return devm_snd_soc_register_component(&i2c->dev,
    				&soc_codec_driver_aic31xx,
    				dac31xx_dai_driver,
    				ARRAY_SIZE(dac31xx_dai_driver));
    	else
    		return devm_snd_soc_register_component(&i2c->dev,
    				&soc_codec_driver_aic31xx,
    				aic31xx_dai_driver,
    				ARRAY_SIZE(aic31xx_dai_driver));
    }
    
    static const struct i2c_device_id aic31xx_i2c_id[] = {
    	{ "tlv320aic310x", AIC3100 },
    	{ "tlv320aic311x", AIC3110 },
    	{ "tlv320aic3100", AIC3100 },
    	{ "tlv320aic3110", AIC3110 },
    	{ "tlv320aic3120", AIC3120 },
    	{ "tlv320aic3111", AIC3111 },
    	{ "tlv320dac3100", DAC3100 },
    	{ "tlv320dac3101", DAC3101 },
    	{ }
    };
    MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id);
    
    static struct i2c_driver aic31xx_i2c_driver = {
    	.driver = {
    		.name	= "tlv320aic31xx-codec",
    		.of_match_table = of_match_ptr(tlv320aic31xx_of_match),
    		.acpi_match_table = ACPI_PTR(aic31xx_acpi_match),
    	},
    	.probe		= aic31xx_i2c_probe,
    	.id_table	= aic31xx_i2c_id,
    };
    module_i2c_driver(aic31xx_i2c_driver);
    
    MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
    MODULE_DESCRIPTION("ASoC TLV320AIC31xx CODEC Driver");
    MODULE_LICENSE("GPL v2");
    

    [2022-01-21 15:20:57.657] Playing WAVE 'file_example_WAV_1M[  960.427075]  tlv hw parameters ..........
    [2022-01-21 15:20:57.657] G.wav' : Signed 16 bit Little End[  960.433268]  tlv hw width=16,rate=8000..........
    [2022-01-21 15:20:57.657] [  960.440759]  tlv end of hw parameters ..........
    [2022-01-21 15:20:57.657] [  960.445405]  tlv hw parameters set up plll..........
    [2022-01-21 15:20:57.657] [  960.450389] tlv mclk_p value = 13000000
    [2022-01-21 15:20:57.657] ian, Rate 8000 Hz, Stereo
    [2022-01-21 15:20:57.657] [  960.461345]  pll 8.3803/2 dosr 128 n 48 m 2 aosr 128 n 48 m 2 bclk_n 8
    [2022-01-21 15:20:57.658] [  960.467883]  tlv hw parameters pllllll   end ..........
    [2022-01-21 15:20:57.658] [  960.473391] TLV..........aic31xx_set_bias_level............
    [2022-01-21 15:20:57.689] [  960.478981]  tlv value of level = 2
    [2022-01-21 15:20:57.689] [  960.482571]  tlv value of snd_soc_component_get_bias_level(component)=1
    [2022-01-21 15:20:57.689] [  960.489197]  TLV ..........aic31xx_clk_on............
    [2022-01-21 15:20:57.737] [  960.509317] TLV .............aic31xx_dapm_power_event...............
    [2022-01-21 15:20:57.737] [  960.515691] TLV .............aic31xx_wait_bits...............
    [2022-01-21 15:20:57.738] [  960.523717] TLV .............aic31xx_dapm_power_event...............
    [2022-01-21 15:20:57.738] [  960.530093] TLV .............aic31xx_wait_bits...............
    [2022-01-21 15:20:57.738] [  960.536472] TLV..........aic31xx_set_bias_level............
    [2022-01-21 15:20:57.738] [  960.542074]  tlv value of level = 3
    [2022-01-21 15:20:57.738] [  960.545665]  tlv value of snd_soc_component_get_bias_level(component)=2
    [2022-01-21 15:20:57.738] [  960.552315]  TLV ..........aic31xx_dac_mute............
    [2022-01-21 15:20:57.758] [  960.558126]  tlv ......... unmute
    [2022-01-21 15:21:28.102] [  990.895846]  TLV ..........aic31xx_dac_mute............
    [2022-01-21 15:21:28.102] [  990.904075]  tlv ......... mute
    [2022-01-21 15:21:28.102] root@iWave-G39H:~# [  996.061581] TLV..........aic31xx_set_bias_level............
    [2022-01-21 15:21:33.290] [  996.067179]  tlv value of level = 2
    [2022-01-21 15:21:33.290] [  996.070782]  tlv value of snd_soc_component_get_bias_level(component)=3
    [2022-01-21 15:21:33.291] [  996.078030] TLV .............aic31xx_dapm_power_event...............
    [2022-01-21 15:21:33.291] [  996.084409] TLV .............aic31xx_wait_bits...............
    [2022-01-21 15:21:33.291] [  996.090760] TLV .............aic31xx_dapm_power_event...............
    [2022-01-21 15:21:33.291] [  996.097131] TLV .............aic31xx_wait_bits...............
    [2022-01-21 15:21:33.291] [  996.104045] TLV..........aic31xx_set_bias_level............
    [2022-01-21 15:21:33.322] [  996.109638]  tlv value of level = 1
    [2022-01-21 15:21:33.322] [  996.113226]  tlv value of snd_soc_component_get_bias_level(component)=2
    [2022-01-21 15:21:33.322] [  996.119851]  TLV ..........aic31xx_clk_off............

    Please let me know , Is there any issue with device tree routing and widgets properties mentioned in previous query.

    Regards,

    Deeksha

  • Hi Deeksha,

    Do you mean you can play audio from wav file to the speaker successfully, but the input from mic is not coming through to the speaker?

    Could you please confirm what is your use case? Are you using the AIC to play from the host, and record from mic to the host or want to route the mic inputs to speaker outputs without going through the host?

    Best regards,
    -Ivan Salazar
    Applications Engineer

  • Hi,

    Sorry for the late reply.

    Our product is HMI solution. We are using TLV320DAC3100 codec IC in our HMI board. Currently, we are not testing with Speaker output SPKP and SPKM. We are testing with Headphone JACK.
    That means HPL and HPR output. We are not using mic. Mic input is not considered for our design.
    We have connected 26MHz MCLK through an external crystal oscillator and audio is connected to DIN pin through I2S interface.
    We are not using AIN1, AIN2 and VOL MIC/DET pins. Currently these pins are left floated.
    We are not getting audio output through headphone HPL and HPR. This is our issue. Please help.
    Our Schematics snip is attached.

    Regards,
    Deeksha

  • Hi Deeksha,

    Thanks for the additional information.

    Can you please do a register dump once the device is initialized, before playback. And also do the same after trying playback. I'd like to compare the register settings before and after playback test. Page 0 and 1 should be OK for the analysis

    Also can you double check your I2S signals are enabled and at the correct frequency during the test?

    Best regards,
    -Ivan Salazar
    Applications Engineer

  • Hi,


     Test is conducted by connecting HeadPhone Jack to HPL and HPR.
     Here I attached i2cdump
     1. Page 0 register Dump after booting system and before Playback
     i2cdump -f -y 1 0x18
    [2022-01-26 11:52:46.339] No size specified (using byte-data access)
    [2022-01-26 11:52:46.339]      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    [2022-01-26 11:52:46.382] 00: 00 00 01 66 00 91 04 00 00 00 00 81 81 00 80 80    ..?f.??....??.??
    [2022-01-26 11:52:46.382] 10: 08 00 81 81 80 80 04 00 00 00 01 0c 00 00 81 00    ?.?????...??..?.
    [2022-01-26 11:52:46.382] 20: 00 00 00 00 80 10 00 00 00 00 00 00 00 00 00 00    ....??..........
    [2022-01-26 11:52:46.383] 30: 00 00 00 02 32 12 03 02 02 11 10 00 01 04 00 14    ...?2??????.??.?
    [2022-01-26 11:52:46.383] 40: 0c d8 d8 00 6f 38 00 00 00 00 00 ee 10 d8 7e e3    ???.o8.....???~?
    [2022-01-26 11:52:46.383] 50: 00 00 80 00 00 00 00 00 7f 00 00 00 00 00 00 00    ..?.....?.......
    [2022-01-26 11:52:46.425] 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:52:46.425] 70: 00 00 00 00 00 2e 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:52:46.425] 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:52:46.425] 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:52:46.426] a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:52:46.426] b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:52:46.426] c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:52:46.472] d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:52:46.472] e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:52:46.472] f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
     
    2. Page 1 register Dump after booting system and before Playback
     root@iWave-G39H:~# i2cdump -f -y 1 0x18
    [2022-01-26 11:55:24.065] No size specified (using byte-data access)
    [2022-01-26 11:55:24.108]      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    [2022-01-26 11:55:24.108] 00: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
    [2022-01-26 11:55:24.109] 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04    ...............?
    [2022-01-26 11:55:24.109] 20: 86 3e 00 00 7f 7f 7f 7f 02 02 01 00 20 86 00 80    ?>..???????. ?.?
    [2022-01-26 11:55:24.109] 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.109] 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.109] 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.151] 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.151] 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.152] 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.152] 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.152] a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.152] b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.152] c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.188] d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.188] e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:55:24.188] f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
     
     3. Page 0 register Dump during playback [ by running aplay in background]
     i2cdump -f -y 1 0x18
    [2022-01-26 11:59:36.361] No size specified (using byte-data access)
    [2022-01-26 11:59:36.361]      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    [2022-01-26 11:59:36.361] 00: 00 00 01 66 03 a1 08 0e db 00 00 b0 82 00 80 80    ..?f?????..??.??
    [2022-01-26 11:59:36.361] 10: 08 00 b0 82 80 80 04 00 00 00 01 0c 00 04 88 00    ?.?????...??.??.
    [2022-01-26 11:59:36.362] 20: 00 00 00 00 80 10 00 00 00 00 00 00 00 00 00 00    ....??..........
    [2022-01-26 11:59:36.362] 30: 00 00 00 02 32 12 03 02 02 11 10 00 01 04 00 14    ...?2??????.??.?
    [2022-01-26 11:59:36.362] 40: 00 d8 d8 00 6f 38 00 00 00 00 00 ee 10 d8 7e e3    .??.o8.....???~?
    [2022-01-26 11:59:36.362] 50: 00 00 80 00 00 00 00 00 7f 00 00 00 00 00 00 00    ..?.....?.......
    [2022-01-26 11:59:36.404] 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:36.404] 70: 00 00 00 00 00 2e 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:36.404] 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:36.404] 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:36.404] a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:36.405] b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:36.453] c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:36.454] d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:36.454] e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:36.454] f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
     
     4.Page 1 register Dump during playback [ by running aplay in background]
      i2cdump -f -y 1 0x18
    [2022-01-26 11:59:59.832] No size specified (using byte-data access)
    [2022-01-26 11:59:59.833]      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    [2022-01-26 11:59:59.833] 00: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
    [2022-01-26 11:59:59.848] 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04    ...............?
    [2022-01-26 11:59:59.879] 20: 86 3e 00 00 7f 7f 7f 7f 02 02 01 00 20 86 00 80    ?>..???????. ?.?
    [2022-01-26 11:59:59.895] 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:59.946] 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:59.946] 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:59.947] 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:59.947] 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:59.947] 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:59.947] 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 11:59:59.947] a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:00.018] b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:00.018] c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:00.018] d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:00.018] e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:00.018] f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
     
    5. Page 0 register Dump after Playback
     i2cdump -f -y 1 0x18
    [2022-01-26 12:00:45.773] No size specified (using byte-data access)
    [2022-01-26 12:00:45.773]      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    [2022-01-26 12:00:45.773] 00: 00 00 01 66 03 a1 08 0e db 00 00 b0 82 00 80 80    ..?f?????..??.??
    [2022-01-26 12:00:45.773] 10: 08 00 b0 82 80 80 04 00 00 00 01 0c 00 00 88 00    ?.?????...??..?.
    [2022-01-26 12:00:45.774] 20: 00 00 00 00 80 10 00 00 00 00 00 00 00 00 00 00    ....??..........
    [2022-01-26 12:00:45.774] 30: 00 00 00 02 32 12 03 02 02 11 10 00 01 04 00 14    ...?2??????.??.?
    [2022-01-26 12:00:45.774] 40: 0c d8 d8 00 6f 38 00 00 00 00 00 ee 10 d8 7e e3    ???.o8.....???~?
    [2022-01-26 12:00:45.774] 50: 00 00 80 00 00 00 00 00 7f 00 00 00 00 00 00 00    ..?.....?.......
    [2022-01-26 12:00:45.816] 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:45.816] 70: 00 00 00 00 00 2e 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:45.816] 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:45.817] 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:45.817] a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:45.817] b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:45.868] c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:45.868] d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:45.868] e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:00:45.868] f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
     
    6. Page 1 register Dump after Playback
     i2cdump -f -y 1 0x18
    [2022-01-26 12:01:14.042] No size specified (using byte-data access)
    [2022-01-26 12:01:14.042]      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    [2022-01-26 12:01:14.042] 00: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
    [2022-01-26 12:01:14.042] 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04    ...............?
    [2022-01-26 12:01:14.042] 20: 86 3e 00 00 7f 7f 7f 7f 02 02 01 00 20 86 00 80    ?>..???????. ?.?
    [2022-01-26 12:01:14.043] 30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.043] 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.043] 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.085] 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.085] 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.085] 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.085] 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.085] a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.086] b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.122] c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.122] d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.122] e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    [2022-01-26 12:01:14.122] f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
     

    Regarding I2S signals below is our findings :

     1. Played .wav file named file_example_WAV_1MG.wav [file_example_WAV_1MG.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 8000 Hz]
     Below attached wave form captured for BCLK, WCLK and DIN.
     

           A.  i2s BCLK and i2s DIN (8KHz Audio)

           B. i2s BCLK and i2s WCLK (8KHz Audio)

       

      
    2. Played .wave file named equinox-48KHz.wav[equinox-48KHz.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 48000 Hz]
    Attached below wave form captured for BCLK & WCLK.

            i2s BCLK and i2s WCLK (48KHz Audio)

      

    Please check and let us know these i2s wave forms are fine.
     
    Also as told earlier, We are not using AIN1, AIN2 and VOL MIC/DET pins of the IC. Currently these pins are left floated. Please let us know whether this will be making any problem for the sound output.
     
    Regards,
    Deeksha

  • Hi Deeksha,

    Thanks for sharing the register settings.
    Let me go over this data and come back with further comments.

    Best regards,
    -Ivan Salazar
    Applications Engineer

  • Hi Ivan,

    Thank you for your support.
    Can we hear from you on your analysis of the data shared today?
    Do you need any more data for your analysis?

    Looking forward for your reply.

    Regards,
    Deeksha

  • Hi Deeksha,

    Please comment on a few of the items below:

    • The clock frequencies are a bit odd, eg. instead of 8k it seems the clock is 8.865k. However the ratios seems to be close to expected like 284k/8.865k = ~32. So this may still be OK
    • I have some questions on the code:
      • The clock divider configuration does not match either one of the table from the code, or the one I listed before. Perhaps the capture is from a previous version before edits?
      • I also noticed that your code capture is not matching the syntax that I shared before in terms of clock configuration (divs have 10 vs 11 parameters). Are you using the code from this link: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/sound/soc/codecs/tlv320aic31xx.c
      • Is the device being configured as Master to generate WCLK and BCLK?
    • I wonder if there is a clock error causing the DAC to mute. You still have playback issues when testing at different sample rates?

    Best regards,
    -Ivan Salazar
    Applications Engineer

  • Hi Ivan,
     
    >> The clock divider configuration does not match either one of the table from the code, or the one I listed before. Perhaps the capture is from a previous version before edits?
     
    ANS : I have used driver from nxp L.5.40.70 Kernel and table mentioned in that driver has slight difference with driver u suggested in  previously.
    Below values are added in NXP tlv320aic31xx.c driver and tested,
    {13000000,   8000,      8, 3803,        128,  48,  2,   128,  48,  2},
    {13000000,   8000,      8, 1920,        128,  32,  3,   128,  32,  3},
    {13500000,   8000,      7, 8643,        128,  48,  2,   128,  48,  2},
     
    >> I also noticed that your code capture is not matching the syntax that I shared before in terms of clock configuration (divs have 10 vs 11 parameters). Are you using the code from this link: git.kernel.org/.../tlv320aic31xx.c ?

    ANS: No,I have not used driver code from this link. I used NXP driver , it has 10 parameters.
     
    >> Is the device being configured as Master to generate WCLK and BCLK?
     ANS: Yes
     
    >> I wonder if there is a clock error causing the DAC to mute. You still have playback issues when testing at different sample rates?
    ANS: Yes, There is playback issues at different sample rate. Before and after playback DAC Volume Control(P0, R64 ,0x40) is mute but while playing it is unmute according to the i2c dump.


    I tested Speaker out with driver suggested in above link by you today.

    I have attached i2cdump before, after and during playback.

    i2cdump before playing:
     
    i2cdump -f -y 1 0x18
    No size specified (using byte-data access)
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 00 00 01 66 00 91 04 00 00 00 00 81 81 00 80 80    ..?f.??....??.??
    10: 08 00 81 81 80 80 04 00 00 00 01 0c 00 00 81 00    ?.?????...??..?.
    20: 00 00 00 00 80 10 00 00 00 00 00 00 00 00 00 00    ....??..........
    30: 00 00 00 02 32 12 03 02 02 11 10 00 01 04 00 14    ...?2??????.??.?
    40: 0c d8 d8 00 6f 38 00 00 00 00 00 ee 10 d8 7e e3    ???.o8.....???~?
    50: 00 00 80 00 00 00 00 00 7f 00 00 00 00 00 00 00    ..?.....?.......
    60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    70: 00 00 00 00 00 2c 00 00 00 00 00 00 00 00 00 00    .....,..........
    80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

     i2cdump -f -y 1 0x18         
    No size specified (using byte-data access)
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
    10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14    ...............?
    20: 86 3e 00 00 7f 7f 7f 7f 02 02 01 00 20 86 00 80    ?>..???????. ?.?
    30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

    i2cdump during playing

     i2cdump -f -y 1 0x18
    No size specified (using byte-data access)
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 00 00 01 66 03 a1 06 0e db 00 00 83 9b 00 80 80    ..?f?????..??.??
    10: 08 00 83 9b 80 80 04 00 00 00 01 0c 00 04 ec 00    ?.?????...??.??.
    20: 00 00 00 00 80 10 00 00 00 00 00 00 00 00 00 00    ....??..........
    30: 00 00 00 02 32 12 03 02 02 11 10 00 01 04 00 14    ...?2??????.??.?
    40: 00 d8 d8 00 6f 38 00 00 00 00 00 ee 10 d8 7e e3    .??.o8.....???~?
    50: 00 00 80 00 00 00 00 00 7f 00 00 00 00 00 00 00    ..?.....?.......
    60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    70: 00 00 00 00 00 2c 00 00 00 00 00 00 00 00 00 00    .....,..........
    80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
     
    i2cdump -f -y 1 0x18
    No size specified (using byte-data access)
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
    10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14    ...............?
    20: 86 3e 00 00 7f 7f 7f 7f 02 02 01 00 20 86 00 80    ?>..???????. ?.?
    30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

     i2cdump after playing:
     

    i2cdump -f -y 1 0x18
    No size specified (using byte-data access)
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 00 00 01 66 03 a1 06 0e db 00 00 83 9b 00 80 80    ..?f?????..??.??
    10: 08 00 83 9b 80 80 04 00 00 00 01 0c 00 00 ec 00    ?.?????...??..?.
    20: 00 00 00 00 80 10 00 00 00 00 00 00 00 00 00 00    ....??..........
    30: 00 00 00 02 32 12 03 02 02 11 10 00 01 04 00 14    ...?2??????.??.?
    40: 0c d8 d8 00 6f 38 00 00 00 00 00 ee 10 d8 7e e3    ???.o8.....???~?
    50: 00 00 80 00 00 00 00 00 7f 00 00 00 00 00 00 00    ..?.....?.......
    60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    70: 00 00 00 00 00 2c 00 00 00 00 00 00 00 00 00 00    .....,..........
    80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
     

    i2cdump -f -y 1 0x18
    No size specified (using byte-data access)
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
    10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14    ...............?
    20: 86 3e 00 00 7f 7f 7f 7f 02 02 01 00 20 86 00 80    ?>..???????. ?.?
    30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

    Please find below wave forms captured for DIN, BCLK & WCLK(8kHz audio) while playing.

      

    Regards,

    Deeksha

  • Hi Deeksha,

    Thanks for confirming the information, I'll consider the device is in master mode and provide further comments as soon as possible,

    Best regards,
    -Ivan Salazar
    Applications Engineer

  • Hi Ivan,

    I had tested speaker out with following changes using amixer and alsamixer application.I am able to hear audio[.wave file] from speaker
    but there is some noise.

    I mentioned the settings below:

    amixer -c 1 sset 'Speaker' on
    amixer -c 1 sset 'Speaker Driver' on
    amixer -c 1 sset 'Output Left From Left DAC' on
    amixer -c 1 sset 'Output Right From Right DAC' on

    alsamixer -c 1

    'Speaker Analog' is set to 12dB gain
    'Speaker Driver' is set to 12dB gain
    'Dac' is set to 8dB gain
    'Volume Soft Stepping' is set to fast

    Please let me know your suggestions on these settings.

    Regards,
    Deeksha

  • Hi Deeksha,

    So it seems analog path and DAC are not initialized during boot up. I'll inspect those parts from the code and also check the register dump of those specific registers to confirm this. I'll provide further comments later today.

    Best regards,
    -Ivan Salazar
    Applications Engineer

  • Deeksha,

    Did you used the suggested clock setting values mentioned from previous post?:

    You may try adding this to the struct:

    Fullscreen
    1
    { 13000000, 8000, 1, 6, 3803, 128, 3, 27, 128, 3, 27},
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    This is specifically for 8k sample rate, if need a different sample rate the clock divs can be calculated accordignly.

    What is the noise like? Is it random like white noise? Is it present at all times or only when playing audio?

    Best regards,
    -Ivan Salazar
    Applications Engineer

  • Hi Ivan,

    Issue had not resolved yet. By mistake Issue resolved button got pressed.

    I have tested with driver suggested by you in previous link and I had  added struct suggested by you .

    Please answer my below questions :

    1. Could you tell me , how to calculate clock divs for different sample rate. Is there any application available to calculate that.

    2. With Speaker , I was able to test with .wav file and there is minute noise while playing with audio . This noise comes only while playing audio.

     We are trying to fine tune audio sound by  adjusting the filter circuit .

      

    Is there any suggestions on this.

    3. Whether I have to fine tune below mentioned gain value to get proper audio . Suggest

    'Speaker Analog' is set to 12dB gain
    'Speaker Driver' is set to 12dB gain
    'Dac' is set to [13.05,13.05] dB gain

    4. With headPhone , I tried below commands with amixer and alsamixer application and I am able to hear audio clearly . Any suggestions on DAC, HP Analog and HP Driver gain settings ?

     Here is the below commands:

    $ amixer -c 1 sset 'HP Driver' on
    $ amixer -c 1 sset 'HP Left' on
    $ amixer -c 1 sset 'HP Right' on
    $ amixer -c 1 sset 'Output Left From Left DAC' on
    $ amixer -c 1 sset 'Output Right From Right DAC' on

    -> DAC is set to [13.50,13.50] dB gain
    -> Volume Soft Stepping is set to fast
    -> HP Analog is set to [13.50,13.50] dB gain
    -> HP Driver is set to [6.00,6.00] dB gain

    5. Whether other formats file can be played with this module via headphone/speaker like mp3 etc. I tried with mp3, aac,ac3,aiff etc but it is giving complete noise. 

    6. Do you have any comments on below reply by you , why DAC path is not enabled during boot time.

    "So it seems analog path and DAC are not initialized during boot up. I'll inspect those parts from the code and also check the register dump of those specific registers to confirm this. I'll provide further comments later today."

    6. Is it possible to test lineout using amixer or any modification in driver required to do it . Please Suggest .

    Waiting for your reply.

    Regards,

    Deeksha

  • Hi Deeksha,

    You can use the attached GUI to calculate the clock settings. Don't connect any EVM to USB, open CodecControl and then go to File->New EVM Simulation, select any AIC device from the list, eg. TLV320AIC3120EVM-U. Then click on the right-most block "Digital Audio Processing..." and then click on the "Internal Clock Gen...." block. On the new window set the Input Frequency and the Sample Rate (on the ADC side), this will automatically generate clock tree values in the table.

    /cfs-file/__key/communityserver-discussions-components-files/6/3808.CCDAC310x.zip

    Regarding the filter, what you have seems OK considering it's a ferrite bead filter, you can refer to a similar Class-D driver like this: https://www.ti.com/lit/ds/symlink/tpa2011d1.pdf#page=14&zoom=100,0,200

    I would suggest to start without any gain on the speaker driver, so set Speaker Analog and Speaker Driver to 0dB, then you can start adding gain if sound is good.

    The file format support depends on the alsa driver I think, you may specific a different format as part of the command parameters

    I'll be discussing all the driver and initialization settings questions with some of our driver experts, I'll get some feedback over the next week.