Audio IMX6板的音频问题(max98357a编解码器)

Audio IMX6板的音频问题(max98357a编解码器),audio,linux-device-driver,codec,device-tree,imx6,Audio,Linux Device Driver,Codec,Device Tree,Imx6,我正在一个基于和模块的定制板上工作,试图播放音频。我刚开始学习设备树的工作原理我在4.1.15 linux内核上实现了一个简单的声卡,并使用I.MX6和MA98357a中建议的以下DTS和简单声卡: codec: max98357a@0 { compatible = "maxim,max98357a"; #sound-dai-cells = <0>; }; sound { compatible = "simple-au

我正在一个基于和模块的定制板上工作,试图播放音频。我刚开始学习设备树的工作原理我在4.1.15 linux内核上实现了一个简单的声卡,并使用I.MX6和MA98357a中建议的以下DTS和简单声卡:

codec: max98357a@0 {
        compatible = "maxim,max98357a";
        #sound-dai-cells = <0>;
    };

    sound {
        compatible = "simple-audio-card";
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_ssi1>;
        simple-audio-card,name = "TI3 Audio";
        simple-audio-card,format = "i2s";
        simple-audio-card,widgets = "Speaker", "Speakers";
        simple-audio-card,routing = "Speakers", "Speaker";
        simple-audio-card,bitclock-master = <&cpu_dai>;
        simple-audio-card,frame-master = <&cpu_dai>;
        cpu_dai: simple-audio-card,cpu {
            sound-dai = <&ssi1>;
            system-clock-frequency = <883200>;
            dai-tdm-slot-num = <2>;
            dai-tdm-slot-width = <16>;
        };
        codec_dai: simple-audio-card,codec {
            sound-dai = <&codec>;
        };
    };



&audmux {
    status = "okay";
    // Note: 'ssi1' (node of first SSI) corresponds to '_SSI0' below.
    ssi1 {
         fsl,audmux-port = <MX31_AUDMUX_PORT1_SSI0>;
         fsl,port-config = <
               0x00000000
               IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT3_SSI_PINS_3)
               >;
           };


    aud3 {
      fsl,audmux-port = <MX31_AUDMUX_PORT3_SSI_PINS_3>;
      fsl,port-config = <
          (IMX_AUDMUX_V2_PTCR_TFSDIR |
          IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT1_SSI0) |
          IMX_AUDMUX_V2_PTCR_TCLKDIR |
          IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT1_SSI0))
          IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0)
          >;
     };
};


&ssi1 {
      fsl,mode = "i2s-master";
      assigned-clocks = <&clks IMX6QDL_CLK_SSI1_SEL>, <&clks IMX6QDL_CLK_SSI1>;
      assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
      assigned-clock-rates = <0>, <49152000>; // 48kHz on SSI1 clock
      status = "okay";    
};
MAX98357a编解码器连接到SSI1。声卡由ALSA检测。但当我尝试播放音频文件时,扬声器上没有输出信号,SSI1引脚上也没有I2S信号。有人知道这个问题吗。 谢谢
致以最崇高的敬意

我在让带有简单声卡的声卡MA98357a编解码器与最新版本的imx6q I.MX 6 Quad配合使用时遇到了一些问题,因此我在这里分享我的解决方案:

需要启用与兼容maxim MAX98357A关联的配置和SOC MAX98357A。但默认情况下,无法在make menuconfig下选择此选项。需要修补相关的Kconfig sound/soc/codecs/Kconfig。替换: 作者:

需要启用与兼容简单声卡关联的配置简单声卡

如果尚未应用,请应用/合并/选取以下修补程序:在master::clk:imx6q:disable non-functional divider中提交id。我必须手动合并它,因为我使用的是较旧的内核版本4.19.134

写入此声卡的.dts:

配置audmux,在我的例子中,引脚TXD、CLK、FS连接到AUD5引脚。使用第一个SSI ssi1。该SSI将生成位时钟CLK,并将其提供给max98357a声卡。 配置iomux:需要在正确的模式下配置AUD5引脚 配置ssi1和相关时钟。这方面最好的时钟是PLL4,它是唯一允许精确生成48 kHz的时钟。 添加编解码器和声卡 下面是.dts的摘录:

/dts-v1/;
#include <dt-bindings/sound/fsl-imx-audmux.h>
#include "imx6q.dtsi"
#include "imx6qdl-phytec-phycore-som.dtsi"

/ {
    codec: max98357a@0 {
        compatible = "maxim,max98357a";
        #sound-dai-cells = <0>;
    };

    sound {
        compatible = "simple-audio-card";
        simple-audio-card,name = "max98357a";
        simple-audio-card,format = "i2s";
        simple-audio-card,widgets = "Speaker", "Speakers";
        simple-audio-card,routing = "Speakers", "Speaker";
        simple-audio-card,bitclock-master = <&cpu_dai>;
        simple-audio-card,frame-master = <&cpu_dai>;
        cpu_dai: simple-audio-card,cpu {
            sound-dai = <&ssi1>;
            dai-tdm-slot-num = <2>;
            dai-tdm-slot-width = <16>;
        };
        codec_dai: simple-audio-card,codec {
            sound-dai = <&codec>;
            clocks = <&clks IMX6QDL_CLK_SSI1>;
        };
    };
};

&audmux {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_audmux>;
    status = "okay";

    ssi1 {
        fsl,audmux-port = <MX31_AUDMUX_PORT1_SSI0>;
        fsl,port-config = <
            0x00000000
            IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5)
            >;
    };

    aud5 {
        fsl,audmux-port = <MX31_AUDMUX_PORT5_SSI_PINS_5>;
        fsl,port-config = <
            (IMX_AUDMUX_V2_PTCR_TFSDIR |
             IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT1_SSI0) |
             IMX_AUDMUX_V2_PTCR_TCLKDIR |
             IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT1_SSI0))
             IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0)
             >;
    };
};

/* The clock tree used to generate the SSI1 bit clock (See IMX6DQRM reference manual):
 *  pll4                                    -- 24e6 * (DIV_SELECT + NUM/DENOM)
 *    pll4_bypass                           -- Bypass PLL4: CCM_ANALOG_PLL_AUDIO[BYPASS]
 *      pll4_audio                          -- Enable PLL4: CCM_ANALOG_PLL_AUDIO[ENABLE]
 *        pll4_post_div                     -- Divide PLL4: CCM_ANALOG_PLL_AUDIO[POST_DIV_SELECT]
 *          pll4_audio_div                  -- Reserved: Fixed factor of x1
 *            ssi1_sel                      -- Clock multiplexer
 *              ssi1_pred                   -- Divide SSI1: CS1CDR[SSI1_CLK_PRED]
 *                ssi1_podf                 -- Divide SSI1: CS1CDR[SSI1_CLK_PODF]
 *                  ssi1 (SSI1_CLK_ROOT)    -- Clock gate: CCM_CCGR5[CG9]
 *                    ssi1 (Int. bit clock) -- Divide SSI1: STCCR[DIV2, PSR, PM] (See formula below)
 *
 * With the following constraint:
 *  - (DIV_SELECT + NUM/DENOM): Must be between 27 and 54: PLL4 clock between 650 and 1300 MHz
 *  - DENOM = 24e6: As implemented in clk_pllv3_av_set_rate()
 *  - POST_DIV_SELECT: Can divide by [1; 2; 4]
 *  - SSI1_CLK_PRED: Can divide by [1, 8]
 *  - SSI1_CLK_PODF: Can divide by [1, 64]
 *  - DIV2 and PSR = 0: As implemented in fsl_ssi_set_bclk()
 *  - PM > 0: Since DIV2, PSR and PM should not be all set to zero at the same time.
 *  - SSI bit clock = SSI1_CLK_ROOT / ((DIV2 + 1) * (7 * PSR + 1) * (PM + 1) * 2)
 *
 * SSI bit clock needs to be equal to 3072000 Hz (for 2 channels/stereo, 48kHz) since:
 *  - For 2 channels, slot width is fixed to 32 bits since in I2S Master mode, and STCCR[WL] are
 *    used to control the amount of valid data in those 32 bits.
 *  - 2 slots are used, one for each channel. The slot number (STCCR[DC]) is fixed to 2.
 *  => SSI bit clock = 48000 * 32 * 2 = 3072000
 *
 * SSI bit clock needs to be equal to 1536000 Hz (for 1 channel/mono, 48kHz) since:
 *  - Slot width is set to 16 bits, in I2S Normal mode.
 *  - 2 slots are used (fixed to 2), and data are only provided in first slot
 *  => SSI bit clock = 48000 * 16 * 2 = 1536000
 *
 * So SSI1_CLK_ROOT frequency needs to be equal to: 3072000 * (PM + 1) * 2 = 6144000 * (PM + 1)
 *
 * The following configuration is applied:
 *  - SSI1_SEL parent clock is configured to be PLL4_AUDIO_DIV
 *  - SSI1_SEL clock is automatically configured
 *  - PLL4 clock is set to 663.552 MHz, which is a multiple of 6144000 Hz (x 108).
 *    The PLL4 must be configured in the DTS otherwise Linux keeps the default/reset values, which
 *    are invalid. /sys/kernel/debug/clk/clk_summary report 147456000 Hz but the generated clock
 *    is not at this frequency.
 *  - SSI1_CLK_ROOT is set to 18.432 MHz. (18.432 * 36 = 663.552 MHz)
 *  - STCCR[PM] will be automatically set to 2. (18.432 / (2 + 1) / 2 = 3.072 MHz)
 */
&ssi1 {
    fsl,mode = "i2s-master";
    assigned-clocks = <&clks IMX6QDL_CLK_SSI1_SEL>, <&clks IMX6QDL_CLK_PLL4>, <&clks IMX6QDL_CLK_SSI1>;
    assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
    assigned-clock-rates = <0>, <663552000>, <18432000>;
    status = "okay";
};

/* For iomuxc, pin configuration (pad setting value):
 *  - Bit 0: Slew rate: 1 = fast, 0 = slow
 *  - Bit 3-5: Drive Strength: 0 = HI-Z, 1 = 260 Ohm, 2 = 130 Ohm, 3 = 90 Ohm, 4 = 60 Ohm, 5 = 50 Ohm, 6 = 40 Ohm, 7 = 33 Ohm
 *  - Bit 6-7: Speed: 0 = Low, 1 and 2 = Medium, 3 = Maximum
 *  - Bit 11: Open drain: 0 = Disabled, 1 = Enabled
 *  - Bit 12: Pull / Keep Enable: 0 = Disabled, 1 = Enabled
 *  - Bit 13: Pull / Keep Select: 0 = Keep, 1 = Pull
 *  - Bit 14-15: Pull Up / Down config: 0 = 100K Down, 1 = 47K Up, 2 = 100K Up, 3 = 22K Up
 *  - Bit 16: Hysteresis Enable: 0 = Disabled, 1 = Enabled
 *  - Bit 30: SION: Software Input On Field.
 *  - Bit 31: NO_PAD_CTL: indicate this pin does not need config.
 *
 * See fsl,imx-pinctrl.txt, fsl,imx6q-pinctrl.txt, and pinctrl-bindings.txt
 * See also https://www.nxp.com/docs/en/application-note/AN5078.pdf
 */
&iomuxc {
    pinctrl_audmux: audmuxgrp {
        fsl,pins = <
            MX6QDL_PAD_KEY_ROW0__AUD5_TXD      0x110b0  /* AUDIO: DIN, D56, X_AUD5_TXD, SSI1_TXD */
            MX6QDL_PAD_KEY_COL0__AUD5_TXC      0x130b0  /* AUDIO: BCLK, D53, X_AUD5_TXC, SSI1_CLK */
            MX6QDL_PAD_KEY_COL1__AUD5_TXFS     0x130b0  /* AUDIO: LRCLK, D54, X_AUD5_TXFS, SSI1_FS */
        >;
    };
};

我通过考虑audmux与SSI的映射来解决我的问题。在我的案例中,SS1连接到audmux5。这就是新的实现:aud5{fsl,audmux端口=;fsl,端口配置=config SND_SOC_MAX98357A tristate "Maxim MAX98357A CODEC"
/dts-v1/;
#include <dt-bindings/sound/fsl-imx-audmux.h>
#include "imx6q.dtsi"
#include "imx6qdl-phytec-phycore-som.dtsi"

/ {
    codec: max98357a@0 {
        compatible = "maxim,max98357a";
        #sound-dai-cells = <0>;
    };

    sound {
        compatible = "simple-audio-card";
        simple-audio-card,name = "max98357a";
        simple-audio-card,format = "i2s";
        simple-audio-card,widgets = "Speaker", "Speakers";
        simple-audio-card,routing = "Speakers", "Speaker";
        simple-audio-card,bitclock-master = <&cpu_dai>;
        simple-audio-card,frame-master = <&cpu_dai>;
        cpu_dai: simple-audio-card,cpu {
            sound-dai = <&ssi1>;
            dai-tdm-slot-num = <2>;
            dai-tdm-slot-width = <16>;
        };
        codec_dai: simple-audio-card,codec {
            sound-dai = <&codec>;
            clocks = <&clks IMX6QDL_CLK_SSI1>;
        };
    };
};

&audmux {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_audmux>;
    status = "okay";

    ssi1 {
        fsl,audmux-port = <MX31_AUDMUX_PORT1_SSI0>;
        fsl,port-config = <
            0x00000000
            IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5)
            >;
    };

    aud5 {
        fsl,audmux-port = <MX31_AUDMUX_PORT5_SSI_PINS_5>;
        fsl,port-config = <
            (IMX_AUDMUX_V2_PTCR_TFSDIR |
             IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT1_SSI0) |
             IMX_AUDMUX_V2_PTCR_TCLKDIR |
             IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT1_SSI0))
             IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0)
             >;
    };
};

/* The clock tree used to generate the SSI1 bit clock (See IMX6DQRM reference manual):
 *  pll4                                    -- 24e6 * (DIV_SELECT + NUM/DENOM)
 *    pll4_bypass                           -- Bypass PLL4: CCM_ANALOG_PLL_AUDIO[BYPASS]
 *      pll4_audio                          -- Enable PLL4: CCM_ANALOG_PLL_AUDIO[ENABLE]
 *        pll4_post_div                     -- Divide PLL4: CCM_ANALOG_PLL_AUDIO[POST_DIV_SELECT]
 *          pll4_audio_div                  -- Reserved: Fixed factor of x1
 *            ssi1_sel                      -- Clock multiplexer
 *              ssi1_pred                   -- Divide SSI1: CS1CDR[SSI1_CLK_PRED]
 *                ssi1_podf                 -- Divide SSI1: CS1CDR[SSI1_CLK_PODF]
 *                  ssi1 (SSI1_CLK_ROOT)    -- Clock gate: CCM_CCGR5[CG9]
 *                    ssi1 (Int. bit clock) -- Divide SSI1: STCCR[DIV2, PSR, PM] (See formula below)
 *
 * With the following constraint:
 *  - (DIV_SELECT + NUM/DENOM): Must be between 27 and 54: PLL4 clock between 650 and 1300 MHz
 *  - DENOM = 24e6: As implemented in clk_pllv3_av_set_rate()
 *  - POST_DIV_SELECT: Can divide by [1; 2; 4]
 *  - SSI1_CLK_PRED: Can divide by [1, 8]
 *  - SSI1_CLK_PODF: Can divide by [1, 64]
 *  - DIV2 and PSR = 0: As implemented in fsl_ssi_set_bclk()
 *  - PM > 0: Since DIV2, PSR and PM should not be all set to zero at the same time.
 *  - SSI bit clock = SSI1_CLK_ROOT / ((DIV2 + 1) * (7 * PSR + 1) * (PM + 1) * 2)
 *
 * SSI bit clock needs to be equal to 3072000 Hz (for 2 channels/stereo, 48kHz) since:
 *  - For 2 channels, slot width is fixed to 32 bits since in I2S Master mode, and STCCR[WL] are
 *    used to control the amount of valid data in those 32 bits.
 *  - 2 slots are used, one for each channel. The slot number (STCCR[DC]) is fixed to 2.
 *  => SSI bit clock = 48000 * 32 * 2 = 3072000
 *
 * SSI bit clock needs to be equal to 1536000 Hz (for 1 channel/mono, 48kHz) since:
 *  - Slot width is set to 16 bits, in I2S Normal mode.
 *  - 2 slots are used (fixed to 2), and data are only provided in first slot
 *  => SSI bit clock = 48000 * 16 * 2 = 1536000
 *
 * So SSI1_CLK_ROOT frequency needs to be equal to: 3072000 * (PM + 1) * 2 = 6144000 * (PM + 1)
 *
 * The following configuration is applied:
 *  - SSI1_SEL parent clock is configured to be PLL4_AUDIO_DIV
 *  - SSI1_SEL clock is automatically configured
 *  - PLL4 clock is set to 663.552 MHz, which is a multiple of 6144000 Hz (x 108).
 *    The PLL4 must be configured in the DTS otherwise Linux keeps the default/reset values, which
 *    are invalid. /sys/kernel/debug/clk/clk_summary report 147456000 Hz but the generated clock
 *    is not at this frequency.
 *  - SSI1_CLK_ROOT is set to 18.432 MHz. (18.432 * 36 = 663.552 MHz)
 *  - STCCR[PM] will be automatically set to 2. (18.432 / (2 + 1) / 2 = 3.072 MHz)
 */
&ssi1 {
    fsl,mode = "i2s-master";
    assigned-clocks = <&clks IMX6QDL_CLK_SSI1_SEL>, <&clks IMX6QDL_CLK_PLL4>, <&clks IMX6QDL_CLK_SSI1>;
    assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
    assigned-clock-rates = <0>, <663552000>, <18432000>;
    status = "okay";
};

/* For iomuxc, pin configuration (pad setting value):
 *  - Bit 0: Slew rate: 1 = fast, 0 = slow
 *  - Bit 3-5: Drive Strength: 0 = HI-Z, 1 = 260 Ohm, 2 = 130 Ohm, 3 = 90 Ohm, 4 = 60 Ohm, 5 = 50 Ohm, 6 = 40 Ohm, 7 = 33 Ohm
 *  - Bit 6-7: Speed: 0 = Low, 1 and 2 = Medium, 3 = Maximum
 *  - Bit 11: Open drain: 0 = Disabled, 1 = Enabled
 *  - Bit 12: Pull / Keep Enable: 0 = Disabled, 1 = Enabled
 *  - Bit 13: Pull / Keep Select: 0 = Keep, 1 = Pull
 *  - Bit 14-15: Pull Up / Down config: 0 = 100K Down, 1 = 47K Up, 2 = 100K Up, 3 = 22K Up
 *  - Bit 16: Hysteresis Enable: 0 = Disabled, 1 = Enabled
 *  - Bit 30: SION: Software Input On Field.
 *  - Bit 31: NO_PAD_CTL: indicate this pin does not need config.
 *
 * See fsl,imx-pinctrl.txt, fsl,imx6q-pinctrl.txt, and pinctrl-bindings.txt
 * See also https://www.nxp.com/docs/en/application-note/AN5078.pdf
 */
&iomuxc {
    pinctrl_audmux: audmuxgrp {
        fsl,pins = <
            MX6QDL_PAD_KEY_ROW0__AUD5_TXD      0x110b0  /* AUDIO: DIN, D56, X_AUD5_TXD, SSI1_TXD */
            MX6QDL_PAD_KEY_COL0__AUD5_TXC      0x130b0  /* AUDIO: BCLK, D53, X_AUD5_TXC, SSI1_CLK */
            MX6QDL_PAD_KEY_COL1__AUD5_TXFS     0x130b0  /* AUDIO: LRCLK, D54, X_AUD5_TXFS, SSI1_FS */
        >;
    };
};