天天看點

am335x+wm8960音頻基于linux 4.9.41移植

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;

BSP