Notepad:Linux and Pillgram::Audio: Difference between pages

From Amar Wiki
(Difference between pages)
 
 
Line 1: Line 1:
= Linux Tips and Tricks =
= TLV320AIC3110 =
Linux stuff I often have to lookup. Just my personal list of things.
== Schematics ==
[[File:Tlv320aic3110-schematics-copyright.png|thumb]]


== Device Tree ==
<syntaxhighlight>
/dts-v1/;
/plugin/;
 
/ {
    compatible = "brcm,bcm2712", "brcm,bcm2711", "brcm,bcm2835";
    // compatible = "brcm,bcm2835";
    fragment@0 {
        target = <&i2s_clk_consumer>;
        __overlay__ {
            status = "okay";
            #sound-dai-cells = <0>;
            brcm,tx-channels = <2>;
            brcm,rx-channels = <1>;
        };
    };
    fragment@1 {
        target-path = "/";
        __overlay__ {
            status = "okay";
            codec_1v8_reg: codec-1v8-reg {
                compatible = "regulator-fixed";
                regulator-name = "tlv320aic3104_1v8";
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
                regulator-always-on;
                status = "okay";
            };
        };
    };
    fragment@2 {
        target = <&i2c1>;
        __overlay__ {
            #address-cells = <1>; /* Single cell for I2C address */
            #size-cells = <0>;    /* No size cells for I2C devices */
            status = "okay";
            tlv320aic3110: tlv320aic3110@18 {
                compatible = "ti-pg,tlv320aic3110", "ti,tlv320aic3110", "ti,tlv320aic311x";
                reg = <0x18>;
                #sound-dai-cells = <0>;
                // system-clock-frequency = <12288000>;  // Codec clock config
                // system-clock-direction-out;          // Codec as master
                status = "okay";
                HPVDD-supply = <&vdd_3v3_reg>;
                SPRVDD-supply = <&vdd_5v0_reg>;
                SPLVDD-supply = <&vdd_5v0_reg>;
                AVDD-supply = <&vdd_3v3_reg>;
                IOVDD-supply = <&vdd_3v3_reg>;
                DVDD-supply = <&codec_1v8_reg>;
                clocks = <&mclk_external>;
                clock-names = "mclk";
                // system-clk-frequency = <12288000>;
                mclk-frequency = <12288000>;
                // gpio-controller;
                reset-gpios = <&gpio 13 1>; // GPIO 13 as active low reset
                reset-delay-us = <10000>;    /* 10ms delay */
                // Debug properties (must precede subnodes)
                debug;
                linux,debug;
            };
        };
    };
    fragment@3 {
        target = <&sound>;
        __overlay__ {
            compatible = "simple-audio-card";
            i2s-controller = <&i2s_clk_consumer>;
            simple-audio-card,name = "TLV320AIC3110";
            simple-audio-card,format = "i2s";
            simple-audio-card,convert-rate = <48000>;
            simple-audio-card,mclk-fs = <256>;
            simple-audio-card,bitclock-master = <&snd_codec>;
            simple-audio-card,frame-master = <&snd_codec>;
            simple-audio-card,widgets =
                "Microphone", "Mic Jack",
                "Speaker", "External Speaker";
            simple-audio-card,routing =
                "External Speaker", "SPL",
                "External Speaker", "SPR",
                "MIC1LP", "Mic Jack",
                "MIC1LM", "Mic Jack";
            status = "okay";
            dailink0_master: simple-audio-card,cpu {
                sound-dai = <&i2s_clk_consumer>;
                dai-tdm-slot-num = <2>;
                dai-tdm-slot-width = <32>;
            };
            snd_codec: simple-audio-card,codec {
                sound-dai = <&tlv320aic3110>;
                clocks = <&mclk_external>;
                system-clock-direction-out = "out";
                system-clock-frequency = <12288000>; //*** added LAX
                mclk-fs = <256>; //*** added LAX
            };
        };
    };
    fragment@4 {
        target-path = "/";
        __overlay__ {
            mclk_external: mclk_external {
                compatible = "fixed-clock";
                #clock-cells = <0>;
                clock-frequency = <12288000>; // 12.288 MHz
                clock-output-names = "mclk";
            };
        };
    };
};
</syntaxhighlight>


* [[Notepad:NFS unload| NFS unload filesystem]]
== Explanation ==
* [[Notepad:mysql slave skip error| mysql slave skip error]]
After carefully reading the source code, I finally found the culprit of my issues. Even if the datasheet suggest I can bypass the PLL if use a proper frequency for MCLK (I chose 12.288Mhz and 11.2896Mhz which divided by 256 gives 48Khz and 41.1Khz), the device driver does not support any arbitrary frequency! They have a bunch of lookup tables for clock rates and playback and if your choice is not present, the driver will fail.
* [[Notepad:GRUB install| GRUB install]]
 
* [http://www.enterux.com/en/resources/yahoo-domainkeys-howto-debian Domain Keys]
I modified the source code and added the proper lookups for my custom frequencies
* [[Notepad:Change Timezone| Change Timezone]]
* [http://datatag.web.cern.ch/datatag/howto/tcp.html Gigabit Network]
* [[Notepad:Syncookie| Syncookie]]
* [[Notepad:Local Mount| Local Mount]]
* [[Notepad:SWAP| SWAP]]
* [[Notepad:depmod| depmod]]
* [[Notepad:Chain of IP addresses| Chain of IP addresses]]
* [[Notepad:Xterm startup|Xterm startup]] with different colors and font sizes
* [[Notepad:RPM - YUM Platform]]
* [http://fedoraproject.org/wiki/YumUpgradeFaq In place upgrade of Fedora Core by yum]
* [http://www.cyberciti.biz/tips/rhel-centos-fedora-linux-iscsi-howto.html CentOS / Red Hat Linux: Install and manage iSCSI Volume]
* [https://www.certdepot.net/rhel7-configure-ldap-directory-service-user-connection/ Configure a LDAP directory service ]
* [[Notepad:NetworkManager Configuration| NetworkManager Configuration]]
* [http://bobpeers.com/technical/telnet_imap Accessing IMAP email accounts using telnet.]
* Enable service syslog to have /var/log/messages populated
* Force a disk check on reboot
shutdown -rF now
* [http://www.rootninja.com/create-a-network-bridge-for-virtual-machines/ Create a network bridge for Virtual Machines]
* [http://www.rfxn.com/upgrade-centos-4-to-5/ Upgrade CentOS 4 to 5]
* [[Notepad:SSL CRT generation | Create a CRT for an SSL certificate]]
* [[Notepad:Samba | Properly configure Samba on Linux]]
* [[Notepad:Postfix | Postfix config]]
* [[Notepad:wget | Use wget to download full website]]
* [http://manuel.kiessling.net/2013/03/19/converting-a-running-physical-machine-to-a-kvm-virtual-machine/ Converting a running physical machine to a kvm virtual machine]
* Generate XAUTH on a new host
xauth add `hostname`/unix:0 . `openssl rand -hex 32`
* yum versionlock - allows to lock an rpm
* install faster random for dns etc.
<syntaxhighlight lang='bash' line>
yum install haveged;
systemctl enable haveged;
systemctl start haveged
</syntaxhighlight>
* [https://askubuntu.com/questions/73864/how-to-modify-an-invalid-etc-sudoers-file How to modify an invalud sudoers file]
sudo visudo -f /mnt/etc/sudoers
* [http://manuel.kiessling.net/2013/03/19/converting-a-running-physical-machine-to-a-kvm-virtual-machine/ Converting a running physical machine into a KVM virtual machine]
* Which Process is listening on a port
netstat -tulpn
* [https://www.unixarena.com/2018/05/how-to-recover-grub-on-rhel-7-centos-7.html/ Recover GRUB 2]
* Install all package from another machine
xargs yum -y install < file
* Create Default Home Directory
mkhomedir_helper username
* [[Notepad:crontab | Schedule crontab with lock]]
* [https://hackernoon.com/how-to-shutdown-your-servers-in-case-of-power-failure-ups-nut-co-34d22a08e92 Configure UPS shutdown frmo Linux with nut]
* [[Notepad:mc | Midnight Commander]]
* [[Notepad:nagios | Nagios]]
* [https://wiki.archlinux.org/index.php/Google_Authenticator Google Authenticator Setup]
* [https://www.svennd.be/software-raid-1-on-centos-7-eufi-running-system/ Boot from Centos 7 RAID 1 EUFI]
* [https://serverfault.com/questions/779634/create-a-directory-under-var-run-at-boot Create a directory under var at boot or startup]
use tmpfiles.d and have your package create at startup or boot a file or directory /usr/lib/tmpfiles.d/mydaemon.conf :
man tmpfiles.d
#Type Path            Mode UID      GID    Age Argument
d    /run/mydaemon  0755 myuser myuser  -  -


* [https://wiki.archlinux.org/index.php/Lm_sensors lm_sensors]
Code: Select all
* [https://unix.stackexchange.com/questions/227017/how-to-change-systemd-service-timeout-value Change systemd Timeout]
* [https://jumpcloud.com/blog/sharing-google-authenticator-secret-keys-across-servers/ Google Authenticator Across Servers]
* Yum install with missing deps
rpm -Uvh --nodeps $(repoquery --location <module>)
* [[Notepad:LVM Snapshot| LVM Snapshot]]
* [https://www.linuxquestions.org/questions/slackware-14/how-to-configure-iptables-for-router-with-2-public-ip-addresses-4175618196/ Example routing iptables firewall]
* [[Notepad:Disable IPv6 | Disable IPv6]]
* [https://serverfault.com/questions/620019/smartctl-megaraid-how-to-find-the-right-device-node-for-an-adapter find the right device for smartctl]
* ssh into a machine without a terminal '''<nowiki>-T</nowiki>'''
* [https://unix.stackexchange.com/questions/620427/how-to-detect-and-clean-up-junk-journal-files Clean Out Journal]
  sudo journalctl --vacuum-time=3weeks
* [https://www.jamescoyle.net/how-to/323-reclaim-disk-space-from-a-sparse-image-file-qcow2-vmdk Reclaim disk space from a sparse image file (qcow2/ vmdk)]
* [https://medium.com/swlh/make-your-raspberry-pi-file-system-read-only-raspbian-buster-c558694de79 Make your Raspberry Pi file system read-only]
* [https://unix.stackexchange.com/questions/87990/linux-as-router-with-multiple-internet-providers Linux Multiple Interface NAT]
* Get Ethernet Address of network (Exclude lo, virtual and ethernet)
  ip -br l | awk '$1 !~ "lo|vir|eth" { print $3 }'


== LVM Expand ==
/* ADC dividers can be disabled by configuring them to 0 */
Expand the physical size
  static const struct aic31xx_rate_divs aic31xx_divs[] = {
  gparted
  ...
Expand the logical volume
    /* 11.2896 MHz (11289600 Hz) */
  lvextend -l +100%FREE /dev/vg.../lv....
    { 11289600, 44100, 1, 7, 6800, 128, 8, 2, 128, 8, 2},
Resize the file system
    /* 12.288 MHz (12288000 Hz) */
resize2fs /dev/vg.../lv...
    { 12288000, 44100,  1, 7, 5264, 128,  8,  2,  128,  8,  2},
    /* 11.2896 MHz (11289600 Hz) */
    { 11289600, 48000,  1, 7, 6800, 128,  8,  2,  128,  8,  2},
    /* 12.288 MHz (12288000 Hz) */
    { 12288000, 48000,  1, 8, 1920, 128,  8,  2,  128,  8,  2},


After a fun fight with Ubuntu to compile this, lo and behold, everything plays!


{{notepad}}
Now for my project which involves an Iot device, I don't want to have to include an unsigned device driver that will need DKMS to install with every kernel update, I will redo my PCB hardware oscillator to use a natively supported frequency. I leave as an exercise to the people at TI to write a function that dynamically creates a lookup entry for a random frequency MCLK and playback combo!

Revision as of 20:45, 20 January 2025

TLV320AIC3110

Schematics

Device Tree

/dts-v1/;
/plugin/;
  
/ {
    compatible = "brcm,bcm2712", "brcm,bcm2711", "brcm,bcm2835";
    // compatible = "brcm,bcm2835";
 
    fragment@0 {
        target = <&i2s_clk_consumer>;
        __overlay__ {
            status = "okay";
            #sound-dai-cells = <0>;
            brcm,tx-channels = <2>;
            brcm,rx-channels = <1>;
        };
    };
 
    fragment@1 {
        target-path = "/";
        __overlay__ {
            status = "okay";
 
            codec_1v8_reg: codec-1v8-reg {
                compatible = "regulator-fixed";
                regulator-name = "tlv320aic3104_1v8";
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
                regulator-always-on;
                status = "okay";
            };
        };
    };
 
    fragment@2 {
        target = <&i2c1>;
        __overlay__ {
            #address-cells = <1>; /* Single cell for I2C address */
            #size-cells = <0>;    /* No size cells for I2C devices */
            status = "okay";
 
            tlv320aic3110: tlv320aic3110@18 {
                compatible = "ti-pg,tlv320aic3110", "ti,tlv320aic3110", "ti,tlv320aic311x"; 
                reg = <0x18>;
                #sound-dai-cells = <0>;
                // system-clock-frequency = <12288000>;  // Codec clock config
                // system-clock-direction-out;           // Codec as master
                status = "okay";
 
                HPVDD-supply = <&vdd_3v3_reg>;
                SPRVDD-supply = <&vdd_5v0_reg>;
                SPLVDD-supply = <&vdd_5v0_reg>;
                AVDD-supply = <&vdd_3v3_reg>;
                IOVDD-supply = <&vdd_3v3_reg>;
                DVDD-supply = <&codec_1v8_reg>;
 
                clocks = <&mclk_external>;
                clock-names = "mclk";
                // system-clk-frequency = <12288000>;
                mclk-frequency = <12288000>;
                // gpio-controller;
 
                reset-gpios = <&gpio 13 1>; // GPIO 13 as active low reset
                reset-delay-us = <10000>;     /* 10ms delay */
 
                // Debug properties (must precede subnodes)
                debug;
                linux,debug;
 
            };
        };
    };
 
    fragment@3 {
        target = <&sound>;
        __overlay__ {
            compatible = "simple-audio-card";
            i2s-controller = <&i2s_clk_consumer>;
            simple-audio-card,name = "TLV320AIC3110";
            simple-audio-card,format = "i2s";
            simple-audio-card,convert-rate = <48000>;
            simple-audio-card,mclk-fs = <256>;
 
            simple-audio-card,bitclock-master = <&snd_codec>;
            simple-audio-card,frame-master = <&snd_codec>;
 
            simple-audio-card,widgets =
                "Microphone", "Mic Jack",
                "Speaker", "External Speaker";
            simple-audio-card,routing =
                "External Speaker", "SPL",
                "External Speaker", "SPR",
                "MIC1LP", "Mic Jack",
                "MIC1LM", "Mic Jack";
 
            status = "okay";
 
            dailink0_master: simple-audio-card,cpu {
                sound-dai = <&i2s_clk_consumer>;
                dai-tdm-slot-num = <2>;
                dai-tdm-slot-width = <32>;
            };
 
            snd_codec: simple-audio-card,codec {
                sound-dai = <&tlv320aic3110>;
                clocks = <&mclk_external>;
                system-clock-direction-out = "out";
                system-clock-frequency = <12288000>; //*** added LAX
                mclk-fs = <256>; //*** added LAX
            };
        };
    };
 
    fragment@4 {
        target-path = "/";
        __overlay__ {
            mclk_external: mclk_external {
                compatible = "fixed-clock";
                #clock-cells = <0>;
                clock-frequency = <12288000>; // 12.288 MHz
                clock-output-names = "mclk";
            };
        };
    };
};

Explanation

After carefully reading the source code, I finally found the culprit of my issues. Even if the datasheet suggest I can bypass the PLL if use a proper frequency for MCLK (I chose 12.288Mhz and 11.2896Mhz which divided by 256 gives 48Khz and 41.1Khz), the device driver does not support any arbitrary frequency! They have a bunch of lookup tables for clock rates and playback and if your choice is not present, the driver will fail.

I modified the source code and added the proper lookups for my custom frequencies

Code: Select all

/* ADC dividers can be disabled by configuring them to 0 */
static const struct aic31xx_rate_divs aic31xx_divs[] = {
...
   /* 11.2896 MHz (11289600 Hz) */
   { 11289600, 44100, 1, 7, 6800, 128, 8, 2, 128, 8, 2},
   /* 12.288 MHz (12288000 Hz) */
   { 12288000, 44100,  1, 7, 5264, 128,   8,  2,   128,   8,  2},
   /* 11.2896 MHz (11289600 Hz) */
   { 11289600, 48000,  1, 7, 6800, 128,   8,  2,   128,   8,  2},
   /* 12.288 MHz (12288000 Hz) */
   { 12288000, 48000,  1, 8, 1920, 128,   8,  2,   128,   8,  2},

After a fun fight with Ubuntu to compile this, lo and behold, everything plays!

Now for my project which involves an Iot device, I don't want to have to include an unsigned device driver that will need DKMS to install with every kernel update, I will redo my PCB hardware oscillator to use a natively supported frequency. I leave as an exercise to the people at TI to write a function that dynamically creates a lookup entry for a random frequency MCLK and playback combo!