Audio IMX6板的音频问题(max98357a编解码器)
我正在一个基于和模块的定制板上工作,试图播放音频。我刚开始学习设备树的工作原理我在4.1.15 linux内核上实现了一个简单的声卡,并使用I.MX6和MA98357a中建议的以下DTS和简单声卡: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
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 */
>;
};
};