1.配置核心驅動
-> Device Drivers -> Sound card support (SOUND [=y]) -> Advanced Linux Sound Architecture (SND [=y]) -> ALSA for SoC audio support (SND_SOC [=y])
-> SoC Audio for Texas Instruments chips using eDMA
-> SoC Audio for the AM33XX chip based boards
2.配置DTS
am335x-evm.dts檔案:
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "AM335x-EVM";
simple-audio-card,widgets =
"Speaker", "Speaker",
"Headphone", "Headphone Jack",
"Speaker", "Speaker Jack",
"Line", "Line In";
simple-audio-card,routing =
"Speaker", "SPK_LN",
"Speaker", "SPK_LP";
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&sound_master>;
simple-audio-card,frame-master = <&sound_master>;
simple-audio-card,cpu {
sound-dai = <&mcasp1>;
};
sound_master: simple-audio-card,codec {
sound-dai = <&codec>;
system-clock-frequency = <14400000>;
};
};
我的闆子wm8960晶片mclk時鐘輸入這裡是晶振14.745600MHz,但是由于該頻率不能很好用于晶片倍頻分頻(會出現噪音),是以根據晶片手冊這裡使用14.4MHz的推薦值,具體數值還是得參考具體闆子。
codec: [email protected] {
#sound-dai-cells = <0>;
compatible = "wlf,wm8960";
reg = <0x1a>;
status = "okay";
};
......
&mcasp1 {
#sound-dai-cells = <0>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mcasp1_pins>;
pinctrl-1 = <&mcasp1_pins_sleep>;
status = "okay";
op-mode = <0>;
tdm-slots = <2>;
num-serializer = <4>;
serial-dir = <
1 2 0 0
>;
tx-num-evt = <1>;
rx-num-evt = <1>;
};
......
mcasp1_pins: mcasp1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE3)
AM33XX_IOPAD(0x9a4, PIN_INPUT_PULLDOWN | MUX_MODE3)
AM33XX_IOPAD(0x9a8, PIN_OUTPUT_PULLDOWN | MUX_MODE3)
AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE3)
>;
};
mcasp1_pins_sleep: mcasp1_pins_sleep {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x9a4, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x9a8, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
3.修改驅動(如果上述配置無法播放聲音,繼續進行下面修改)
這裡主要是為了使用PLL獲得wm8960工作時鐘。
sound/soc/codecs/wm8960.c (一下紅色粗體為添加内容)
static int wm8960_configure_clocking(struct snd_soc_codec *codec)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
int sysclk, bclk, lrclk, freq_out, freq_in;
u16 iface1 = snd_soc_read(codec, WM8960_IFACE1);
int i, j, k;
if (!(iface1 & (1<<6))) {
dev_dbg(codec->dev,
"Codec is slave mode, no need to configure clock\n");
return 0;
}
wm8960->clk_id = WM8960_SYSCLK_PLL;
freq_in = wm8960->freq_in = 14400000;
if (wm8960->clk_id != WM8960_SYSCLK_MCLK && !wm8960->freq_in) {
dev_err(codec->dev, "No MCLK configured\n");
return -EINVAL;
}
freq_in = wm8960->freq_in;
bclk = wm8960->bclk;
lrclk = wm8960->lrclk;