一、audiocodec
audiocodec是具有数模转换功能的内置模块,可将音频数字信号转换成模拟信号发送出去,通常接耳机、扬声器等
1、音频流通路
播放流:
Playback ──> DACL ──> LINEOUTL ──> SPKPlayback ──> DACR ──> LINEOUTR ──> SPK
录音流:
MIC1 ──> ADC1 ──> CaptureMIC2 ──> ADC2 ──> CaptureMIC3 ──> ADC3 ──> Capture
AudioCodec 模块由 3 个设备树节点构建
(1)ASoC 层 codec: codec
(2)ASoC 层 platform: codec_plat
(3)ASoC 层 machine: codec_mach
2、设备树
/* audio dirver module -> audio codec */
&codec {tx-hub-en;rx-sync-en;dac-vol = <63>; /* default value:63 range:0->63 */dacl-vol = <160>; /* default value:160 range:0->255 */dacr-vol = <160>; /* default value:160 range:0->255 */adc1-vol = <160>; /* default value:160 range:0->255 */adc2-vol = <160>; /* default value:160 range:0->255 */adc3-vol = <160>; /* default value:160 range:0->255 */lineout-gain = <31>; /* default value:31 range:0->31 */hpout-gain = <7>; /* default value:7 range:0->7 */adc1-gain = <31>; /* default value:31 range:0->31 */adc2-gain = <31>; /* default value:31 range:0->31 */adc3-gain = <31>; /* default value:31 range:0->31 *//* to do: avcc-1.8 vdd33-3.3 cpvin-1.8 */avcc-external;avcc-supply = <®_aldo4>;avcc-vol = <1800000>;vdd-external;vdd-supply = <®_cldo3>;vdd-vol = <3300000>;cpvin-external;cpvin-supply = <®_bldo3>;cpvin-vol = <1800000>;pa-pin-max = <1>;pa-pin-0 = <&r_pio PL 7 GPIO_ACTIVE_HIGH>;pa-pin-level-0 = <1>;pa-pin-msleep-0 = <0>;jack-det-level = <0>;jack-det-threshold = <8>;jack-det-debouce-time = <250>;/* extcon = <&usb_power_supply>;* jack-swpin-mic-sel = <&pio PH 8 GPIO_ACTIVE_HIGH>;* jack-swpin-hp-en = <&pio PH 15 GPIO_ACTIVE_HIGH>;* jack-swpin-hp-sel = <&pio PH 11 GPIO_ACTIVE_HIGH>;* jack-swmode-hp-off = <0x00>;* jack-swmode-hp-usb = <0x11>;* jack-swmode-hp-audio = <0x10>;* jack-det-level = <1>;* jack-det-threshold = <8>;* jack-det-debouce-time = <250>;*/status = "okay";
};&codec_plat {status = "okay";
};&codec_mach {soundcard-mach,jack-support = <1>;status = "okay";soundcard-mach,cpu {sound-dai = <&codec_plat>;};soundcard-mach,codec {sound-dai = <&codec>;};
};
3、驱动
bsp/drivers/sound/platform/snd_sunxi_aaudio.c:21:
#define DRV_NAME "sunxi-snd-plat-aaudio"
bsp/drivers/sound/platform/snd_sunxi_mach.c:78:static int asoc_simple_hw_params
mach 的时钟设置
static int asoc_simple_hw_params(struct snd_pcm_substream *substream,struct snd_pcm_hw_params *params)
{switch (params_rate(params)) {case 8000:case 12000:case 16000:case 24000:case 32000:case 48000:case 64000:case 96000:case 192000:freq_point = 24576000;
bsp/drivers/sound/platform/snd_sun55iw3_codec.c:695: SOC_ENUM_EXT("ADC HPF0 Mode", sunxi_adchpf0_sta_enum, sunxi_codec_get_dap_status,
时钟设置 sunxi_codec_dai_set_pll
static int snd_sunxi_clk_rate(struct sunxi_codec_clk *clk, int stream,unsigned int freq_in, unsigned int freq_out)
{SND_LOG_DEBUG("\n");if (stream == SNDRV_PCM_STREAM_PLAYBACK) {if (freq_in % 24576000 == 0) {/* If you want to use clk_pll_audio0_4x, must set it 1083801600Hz */if (clk_set_parent(clk->clk_audio_dac, clk->clk_pll_audio0_4x)) {SND_LOG_ERR("set dac parent clk failed\n");return -EINVAL;}if (clk_set_rate(clk->clk_pll_audio0_4x, 1083801600)) {SND_LOG_ERR("set clk_pll_audio0_4x rate failed\n");return -EINVAL;}} else {if (clk_set_parent(clk->clk_audio_dac, clk->clk_pll_audio1_div5)) {SND_LOG_ERR("set dac parent clk failed\n");return -EINVAL;}}if (clk_set_rate(clk->clk_audio_dac, freq_out)) {SND_LOG_ERR("set clk_audio_dac rate failed, rate: %u\n", freq_out);return -EINVAL;}}}static int sunxi_codec_dai_hw_params(struct snd_pcm_substream *substream,struct snd_pcm_hw_params *params,struct snd_soc_dai *dai)
{/* Set rate */for (i = 0; i < ARRAY_SIZE(sunxi_sample_rate_conv); i++) {if (sunxi_sample_rate_conv[i].samplerate == params_rate(params)) {if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {regmap_update_bits(regmap, SUNXI_DAC_FIFO_CTL, 0x7 << DAC_FS,sunxi_sample_rate_conv[i].rate_bit << DAC_FS);} else {if (sunxi_sample_rate_conv[i].samplerate > 48000)return -EINVAL;regmap_update_bits(regmap, SUNXI_ADC_FIFO_CTL, 0x7 << ADC_FS,sunxi_sample_rate_conv[i].rate_bit << ADC_FS);}}}}static const struct snd_soc_dai_ops sunxi_codec_dai_ops = {.startup = sunxi_codec_dai_startup,.hw_params = sunxi_codec_dai_hw_params,.set_pll = sunxi_codec_dai_set_pll,.prepare = sunxi_codec_dai_prepare,.trigger = sunxi_codec_dai_trigger,.shutdown = sunxi_codec_dai_shutdown,
};
二、AUDIO 音频测试
音频流通路:
播放流:
Playback ──> DACL ──> LINEOUTL ──> SPKPlayback ──> DACR ──> LINEOUTR ──> SPK
录音流:
MIC1 ──> ADC1 ──> CaptureMIC2 ──> ADC2 ──> CaptureMIC3 ──> ADC3 ──> Capture
音频设备:
tinymix查看信息
如何使用 tinymix 更改设置
要更改某个控制项的值,可以使用以下命令格式:
tinymix [control id] [value to set]
例如,如果你想把 MIC1 Switch 打开,可以执行:
tinymix 23 1
同理,如果你想调整音量或增益,可以使用类似的方法:
tinymix 12 100 # 设置 DAC Volume 为 100tinymix 18 40 # 设置 LINEOUT Gain 为 40
1.播放音乐
1.1 aplay 播放wav格式音乐
#打开SPK switch
tinymix 29 1
#默认声卡播放
aplay /usr/share/alsa/syfs-chenhuilin.wav
1.2 ffplay 播放MP3格式音乐
ffplay -nodisp /usr/share/alsa/wuyeutian-xingkong.mp3
1.3 music 音量控制
#amixer 控制music音量,范围0~255, 255声音最大
amixer set 'PCM music volume' 90
1.4 FM 音量控制
#x为音量值,范围 0~100
#ep: 设置音量为50
tinymix -D 4 'DSP2_FM_FaderLR02 Volume' 50
#查看当前音量值
tinymix -D 4 'DSP2_FM_FaderLR02 Volume'
2 、录音
#alsa指定声卡录音, dsnoop 录音,可多路同时录音, 录制为wav格式
2.1 打开 MIC 输入
tinymix -D 0 23 1tinymix -D 0 24 1tinymix -D 0 25 1
#ADC HPF0 Mode
tinymix -D 0 5 1
#ADC1 Volume
tinymix -D 0 15 150arecord -r 44100 -f S16_LE -c2 /mnt/UDISK/record.wavarecord -r 44100 -f S16_LE -c2 /mnt/UDISK/record.wav
2.2 播放录音
aplay /media/record.wav
注意录音时双声道, 播放时接左右声道的喇叭应该会同时出声!! 否则可能是mic或功放工作异常。
MIC录音无声音,录音时测量MBIAS电压为1.8V左右,正常
查看原理图,MIC经过了FM1388模块,要先调试FM1388。如果是直连到CPU,录音功能测试正常。FM1388模块调试内容后续更新。