Other Parts Discussed in Thread: TAC5111
器件型号: TAC5111
您好、
我们将在 i.MX8M Plus 的新设计中使用 TAC5111。
为了进行播放、我们有 1 个模拟扬声器、其放大器连接到 OUT1P/OUT1M。
为了进行录音、我们在引脚 GPIO2(时钟)和 GPIO1(数据)上有 2 个 PDM 麦克风。
麦克风配置为交替时钟相位。 这通过连接双通道示波器并在每个相位期间看到脉冲来确认。
与 CPU 的接口是针对 I2S 配置的、对于本问题、我们在每个通道 16 位的速率下进行记录。 编解码器相应地通过 amixer 命令进行配置、对于 2 通道数字 PDM 输入:
amixer -c 0 sset 'IN1 Source Mux' 'PDM'
amixer -c 0 sset 'IN2 Source Mux' 'PDM'
amixer sset 'ASI_TX_CH1_EN' cap
amixer sset 'ASI_TX_CH2_EN' cap
amixer sset 'PDM1 Digital' 255
amixer sset 'PDM2 Digital' 255
# must record in S16_LE format to avoid driver bugs
amixer sset 'PDM Clk Divider' '1.4112 MHz or 1.536 MHz'
arecord -D hw:0,0 -c 2 -r 48000 -f S16_LE -d 15 rec.wav
相应地配置器件树:
/ {
sound-tac5111 {
/*
* TAC5111 Codec on i.MX8 SAI3 with 4-wire i2s interface.
*
* - SoC generates MCLK for Codec at 24.576
* (avoids clock drift between SoC and Codec)
* - SoC is bitclock and frame master
* - I2S interface width max. S32_LE
* - Codec GPIO1 & GPIO2 with dual PDM microphone
* - Codec OUT1P/OUT1M differential mono output
* routed to speaker through amplifier
*
*/
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "Analog";
simple-audio-card,bitclock-master = <&cpu_dai>;
simple-audio-card,frame-master = <&cpu_dai>;
simple-audio-card,widgets =
"Line", "Line In",
"Line", "Line Out";
simple-audio-card,routing =
"DIN1", "Line In",
"DIN2", "Line In",
"Line Out", "OUT1";
cpu_dai: simple-audio-card,cpu {
sound-dai = <&sai3>;
/* TODO: clock rate? */
/* ensure mclk is generated by SoC for Codec */
//system-clock-direction-out;
/* force 32-bit slots */
//dai-tdm-slot-num = <2>;
//dai-tdm-slot-width = <32>;
};
codec_dai: simple-audio-card,codec {
sound-dai = <&codec>;
/* this ensures codec set_sysclk call-back executes */
system-clock-frequency = <24576000>;
mclk-fs = <512>;
};
};
};
&i2c2 {
codec: audio-codec@50 {
compatible = "ti,tac5111";
reg = <0x50>;
#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_codec>;
interrupts-extended = <&gpio4 21 IRQ_TYPE_EDGE_FALLING>;
avdd-supply = <&v_3_3>;
iovdd-supply = <&v_3_3>;
/*
* configure gpio functionality on gpio pins:
* - GPIO1: pdm data input
* - GPIO2: pdm clock output
* - GPO1: chip irq output
*/
ti,gpios-func = <1>, <4>, <3>;
/*
* select pdm input pins for channels 1/2 & 3/4:
* - ch0/1: gpio1
* - ch2/3: not used
*/
ti,pdm-input-pins = <1>, <0>;
/* configure gpi1 as cclk input */
ti,gpi1-func = <2>;
/*
* configure MICBIAS and VREF to fix driver probe error:
* [ 8.570840] tac5x1x-codec 1-0050: Fail to get verf E:-22
*
* Yet bindings clearly state to that these are powered down if "node" (read property) omitted:
* - "If node is omitted then MicBias is powered down."
* - "If node is omitted then VREF is powered down."
* This board does not use them ...
*/
ti,vref = <0>;
ti,micbias-vg = <3>;
/* configure gpi(o) drive:
* - GPIO1: floating, i.e. output buffer disabled
* - GPIO2: push-pull, i.e. active low & active high (PDM clock)
* - GPO1: open-drain, i.e. active low & high impedance
*/
ti,gpios-drive = <0>, <1>, <3>;
ti,gpa-gpio = <0>;
ti,gpa-threshold = <75>, <186>;
};
};
据观察、在正确设置混频器控制并开始录制后、驱动器禁用了其中一个 PDM 通道:
amixer -c 0 sset 'IN1 Source Mux' 'PDM'
amixer -c 0 sset 'IN2 Source Mux' 'PDM'
amixer sset 'ASI_TX_CH1_EN' cap
amixer sset 'ASI_TX_CH2_EN' cap
amixer sset 'PDM1 Digital' 255
amixer sset 'PDM2 Digital' 255
arecord -D hw:0,0 -c 2 -r 48000 -f S16_LE -d 60 rec.wav &
i2cget -f -y 1 0x50 0x76
0x80
Expected value 0xC0, for both channels 1&2 active.
Ben 确认、当该寄存器用值 0xc0 更新后、编解码器会在 I2S 上将 2 通道音频传输到主 CPU。
跟踪 dapm 小工具事件、我们可以看到 Linux 驱动程序通过 CH1_ADC_EN 为该记录选择了错误的路由 — 这应该不会发生,因为我们使用 PDM 并相应地设置输入多路复用器混频器控制:
# arecord -D hw:0,0 -c 2 -r 48000 -f S16_LE -d 60 rec.wav
[ 1186.960011] tac5x1x_adc_event CH1_ADC_EN (efault) 2
[ 1186.964920] tac5x1x_enable_channel_unlocked adc left
Recording WAVE 'rec.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
因此、在移除违规路由(禁用 ADC 路径)后、无需手动 i2cset 即可自动更正通道使能寄存器值:
diff --git a/src/tac5x1x-i2c.c b/src/tac5x1x-i2c.c
index da6300e..10a8465 100644
--- a/src/tac5x1x-i2c.c
+++ b/src/tac5x1x-i2c.c
@@ -1098,8 +1106,6 @@ static const struct snd_soc_dapm_route taa5x1x_dapm_routes[] = {
/* ADC channel1 */
{"IN1 Source Mux", "Analog", "AIN1"},
{"IN2 Source Mux", "Analog", "IN1 Source Mux"},
- {"CH1_ADC_EN", NULL, "IN2 Source Mux"},
- {"ASI_TX_CH1_EN", "Capture Switch", "CH1_ADC_EN"},
{"ADC1 Config", "Differential", "ASI_TX_CH1_EN"},
{"ADC1 Config", "Single-ended", "ASI_TX_CH1_EN"},
{"ADC1 Config", "Single-ended mux INxP",
# arecord -D hw:0,0 -c 2 -r 48000 -f S16_LE -d 60 rec.wav &
Recording WAVE 'rec.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
# i2cget -f -y 1 0x50 0x76
0xc0
ADC 路由应由 IN1 和 IN2 多路复用器进行控制、这两个多路复用器已针对 PDM 进行了配置(请参阅上文)。
删除有问题的路由后、所有信道现在都处于静默状态。
这是因为与 CH1_ADC_EN 小工具不同、PDM 小工具没有 连接事件处理程序(比较 tac5x1x_adc_event)。
该事件处理程序启用了必要的寄存器值、但也启用了 ADC、这导致 I2S 上的第一个通道数据仅包含未连接模拟麦克风的电路板上的噪声:
static int tac5x1x_adc_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
u8 pwr_cfg;
u32 right = w->shift;
s32 ret = 0;
struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
struct tac5x1x_priv *tac5x1x = snd_soc_component_get_drvdata(c);
printk("tac5x1x_adc_event %s %s %d\n", w->name, kcontrol->id.name, event);
mutex_lock(&tac5x1x->ch_lock);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
ret = tac5x1x_enable_channel_unlocked(c, true, right);
if (ret < 0) {
dev_err(c->dev,
"Failed to update enable ADC channels\n");
break;
}
pwr_cfg = TAC5X1X_PWR_CFG_ADC_PDZ |
TAC5X1X_PWR_CFG_MICBIAS |
TAC5X1X_PWR_CFG_DAC_PDZ;
ret = snd_soc_component_write(c, TAC5X1X_PWR_CFG,
pwr_cfg);
if (ret) {
dev_err(c->dev,
"Failed to power up ADC\n");
tac5x1x_disable_channel_unlocked(c, true, right);
}
print_regs();
schedule_delayed_work(&tac5x1x->powerup_work,
msecs_to_jiffies(0));
break;
case SND_SOC_DAPM_PRE_PMD:
tac5x1x_disable_channel_unlocked(c, true, right);
if (IS_ADC_CH(tac5x1x->ch_enabled) == 0)
snd_soc_component_update_bits(c, TAC5X1X_PWR_CFG,
TAC5X1X_PWR_CFG_ADC_PDZ |
TAC5X1X_PWR_CFG_MICBIAS,
0);
print_regs()
break;
}
mutex_unlock(&tac5x1x->ch_lock);
return ret;
}
请修复驱动程序、以便在通道 1 和 2 上正确设置 PDM 2 通道录音。