EmailServer:Mail Page and Pillgram::Audio: Difference between pages

From Amar Wiki
(Difference between pages)
 
 
Line 1: Line 1:
= Email Server Setup =
= TLV320AIC3110 =
* [https://www.linode.com/docs/guides/email-with-postfix-dovecot-and-mysql/ Configure an Email Server with Postfix, Dovecot, and MySQL]
== Schematics ==
* [https://wiki.dovecot.org/HowTo/PostfixDovecotLMTP Postfix and Dovecot LMTP]
[[File:Tlv320aic3110-schematics-copyright.png|thumb]]
== Postfix ==
* [https://wiki.archlinux.org/title/postfix Install Postfix (with security)]
* [https://www.linuxbabe.com/mail-server/host-multiple-mail-domains-in-postfixadmin Multiple Mail Domains]
* [https://www.linuxbabe.com/mail-server/setting-up-dkim-and-spf Set up SPF and DKIM with Postfix]
* [https://www.postfix.org/VIRTUAL_README.html#local_vs_database Postfix Virtual Domain Hosting]
* [https://www.postfix.org/DEBUG_README.html Postfix Debugging]


== Dovecot ==
== Device Tree ==
* [https://github.com/postfixadmin/postfixadmin/blob/master/DOCUMENTS/DOVECOT.txt Password Schemes]
<syntaxhighlight>
* [https://wiki.dovecot.org/TestInstallation Test Installation]
/dts-v1/;
* [https://doc.dovecot.org/admin_manual/logging/ Dovecot Logging]
/plugin/;
* [https://wiki.dovecot.org/FindMailLocation Find mail location]
 
/ {
    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>


== Roundcube ==
== Explanation ==
* [https://www.linuxbabe.com/mail-server/install-roundcube-webmail-ubuntu-20-04-apache-nginx Install Roundcube Webmail]
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.
* [https://github.com/postfixadmin/postfixadmin/blob/master/DOCUMENTS/DOVECOT.txt Multi Domain Setup]
* [https://github.com/roundcube/roundcubemail/blob/master/config/defaults.inc.php#L921 defaults]


== Postfix Admin ==
I modified the source code and added the proper lookups for my custom frequencies
* [https://github.com/postfixadmin/postfixadmin/blob/2882f86ad83fad04e997d9b9acb514ec8ac51927/DOCUMENTS/POSTFIX_CONF.txt POSTFIX_CONF.txt]
* [https://github.com/postfixadmin/postfixadmin/blob/master/DOCUMENTS/DOVECOT.txt DOVECOT.txt]


== Let's do Postfix slowly and properly ==
Code: Select all
* [https://brokkr.net/2018/06/04/setting-up-postfix-and-dovecot-slowly-and-properly/ Setting up Postfix and Dovecot]
* [https://brokkr.net/2015/10/15/lets-do-postfix-again-but-slowly-and-properly-this-time-part-1-a-simple-local-mail-receiving-server/ Part 1: A simple local mail receiving server]
* [https://brokkr.net/2015/10/18/lets-do-postfix-again-but-slowly-and-properly-this-time-part-2-address-manipulation/ Part 2: Address manipulation]
* [https://brokkr.net/2015/10/22/lets-do-postfix-again-but-slowly-and-properly-this-time-part-3-opening-up-to-the-outside/ Part 3: Opening up to the outside]
* [https://brokkr.net/2015/10/26/lets-do-postfix-again-but-slowly-and-properly-this-time-part-4-virtual-domains/ Part 4: Virtual Domains]
* [https://brokkr.net/2015/11/01/lets-do-postfix-again-but-slowly-and-properly-this-time-part-5-relaying-from-the-local-network/ Part 5: Relaying from the local network]
* [https://brokkr.net/2019/09/13/lets-do-postfix-again-but-slowly-and-properly-this-time-part-6-authentication/ Part 6: Relay authenticating with SASL]
* [https://brokkr.net/2020/08/12/lets-do-postfix-slowly-and-properly-part-7-encryption/ Part 7: Encryption]
* [https://brokkr.net/2020/08/12/lets-do-postfix-slowly-and-properly-part-8-ptr-records/ Part 8: PTR and SPF records]
* [https://brokkr.net/2020/08/13/rspamd/ Part 9: Using RSpamd as a spam milter]
* [https://www.postfix.org/DEBUG_README.html Part 10: Restricting access]
* [https://brokkr.net/2020/08/30/postfix-11-pflogsumm/ Part 11: pflogsumm]


== Let's do Dovecot slowly and properly ==
/* ADC dividers can be disabled by configuring them to 0 */
* [https://brokkr.net/2018/06/04/lets-do-dovecot-slowly-and-properly-part-1-plain-as-day/ Part 1: PLAIN as day]
static const struct aic31xx_rate_divs aic31xx_divs[] = {
* [https://brokkr.net/2018/06/19/lets-do-dovecot-slowly-and-properly-part-2-proper-authentication/ Part 2: Proper authentication]
...
* [https://brokkr.net/2019/10/31/lets-do-dovecot-slowly-and-properly-part-3-lmtp/ Part 3: LMTP]
    /* 11.2896 MHz (11289600 Hz) */
* [https://brokkr.net/2020/08/20/dovecot-4-sieve/ Part 4: Filtering with Sieve]
    { 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!

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!