微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > AM335x(TQ335x)学习笔记——WM8960声卡驱动移植

AM335x(TQ335x)学习笔记——WM8960声卡驱动移植

时间:11-28 来源:互联网 点击:

  1. {"RightDAC",NULL,"RightInputMixer"},

这样在录音时也会使能DAC产生LRCLK。

由于调试时间比较长,可能有些修改我没有描述到,完整的wm8960.c文件我会一并上传到我的资源,可以下载参考。

3. 编写Machine驱动
内核代码有个很好的例子就是davinci-evm.c,这是am335x-evm评估板的Machine驱动,该评估采用的Codec并不是WM8960,因此,我们在该文件中添加WM8960信息即可。具体的修改如下:

Step1. 添加compatible信息。修改后的内容如下:

  1. staticconststructof_device_iddavinci_evm_dt_ids[]={
  2. {
  3. .compatible="ti,tq-evm-audio",
  4. .data=(void*)&evm_dai_wm8960,
  5. },
  6. {
  7. .compatible="ti,da830-evm-audio",
  8. .data=(void*)&evm_dai_tlv320aic3x,
  9. },
  10. {/*sentinel*/}
  11. };

Step2. 实现em_dai_wm8960。需要添加如下代码:

  1. staticstructsnd_soc_dai_linkevm_dai_wm8960={
  2. .name="wm8960",
  3. .stream_name="wm8960-hifi",
  4. .codec_dai_name="wm8960-hifi",
  5. .ops=&evm_wm8960_ops,
  6. .init=evm_wm8960_init,
  7. .dai_fmt=SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_CBM_CFM|
  8. SND_SOC_DAIFMT_NB_NF,
  9. };

含义:

(1) codec_dai_name = "wm8960-hifi" --> 指定codec设备名称,与wm8960.c中指定的相同即可。

(2) ops --> 指定wm8960的各种操作函数,本文仅实现了hw_params函数。

(3) init --> 指定wm8960的初始化函数,主要是完成dapm相关的初始化。

(4) dai_fmt --> 指定音频的接口方式、主从关系和时钟翻转信息。SND_SOC_DAIFMT_I2S表示音频接口采用I2S协议;SND_SOC_DAIFMT_CBM_CFM表示Codec的BCLK为Master,LRCLK为Master,即wm8960为主,AM335x为从;SND_SOC_DAIFMT_NB_NF表示BCLK和LRCLK都不需要翻转。

Step3.实现evm_wm8960_init

这一部分主要是dapm相关的设置,本人理解也不是非常深刻,直接贴上代码,具体如下:

  1. staticconststructsnd_soc_dapm_widgetevm_wm8960_dapm_widgets[]={
  2. SND_SOC_DAPM_SPK("AudioOut1",NULL),
  3. SND_SOC_DAPM_MIC("myMic",NULL),
  4. SND_SOC_DAPM_MIC("myLineIN",NULL),
  5. };
  6. staticconststructsnd_kcontrol_newevm_wm8960_controls[]={
  7. SOC_DAPM_PIN_SWITCH("AudioOut1"),
  8. SOC_DAPM_PIN_SWITCH("myMic"),
  9. SOC_DAPM_PIN_SWITCH("myLineIN"),
  10. };
  11. staticconststructsnd_soc_dapm_routeevm_wm8960_audio_map[]={
  12. /*Connectionstothe...*/
  13. {"AudioOut1",NULL,"HP_L"},
  14. {"AudioOut1",NULL,"HP_R"},
  15. /*Mic*/
  16. {"LINPUT1",NULL,"MICB"},
  17. {"MICB",NULL,"myMic"},
  18. /*Linein*/
  19. {"LINPUT3",NULL,"myLineIN"},
  20. {"RINPUT3",NULL,"myLineIN"},
  21. };
  22. staticintevm_wm8960_init(structsnd_soc_pcm_runtime*rtd)
  23. {
  24. interr;
  25. structsnd_soc_codec*codec=rtd->codec;
  26. structsnd_soc_dapm_context*dapm=&codec->dapm;
  27. snd_soc_dapm_new_controls(dapm,evm_wm8960_dapm_widgets,
  28. ARRAY_SIZE(evm_wm8960_dapm_widgets));
  29. err=snd_soc_add_codec_controls(codec,evm_wm8960_controls,
  30. ARRAY_SIZE(evm_wm8960_controls));
  31. if(err<0)
  32. returnerr;
  33. snd_soc_dapm_add_routes(dapm,evm_wm8960_audio_map,
  34. ARRAY_SIZE(evm_wm8960_audio_map));
  35. snd_soc_dapm_enable_pin(dapm,"AudioOut1");
  36. snd_soc_dapm_enable_pin(dapm,"myMic");
  37. snd_soc_dapm_sync(dapm);
  38. return0;
  39. }

Step4. 实现evm_wm8960_ops及相关函数,需要添加如下代码:

  1. staticintevm_wm8960_hw_params(structsnd_pcm_substream*substream,
  2. structsnd_pcm_hw_params*params)
  3. {
  4. structsnd_soc_pcm_runtime*rtd=substream->private_data;
  5. structsnd_soc_dai*codec_dai=rtd->codec_dai;
  6. structsnd_soc_dai*cpu_dai=rtd->cpu_dai;
  7. structsnd_soc_card*soc_card=rtd->card;
  8. intret=0;
  9. unsignedsysclk=((structsnd_soc_card_drvdata_davinci*)
  10. snd_soc_card_get_drvdata(soc_card))->sysclk;
  11. /*setthecodecsystemclock*/
  12. ret=snd_soc_dai_set_sysclk(codec_dai,0,sysclk,SND_SOC_CLOCK_IN);
  13. if(ret<0)
  14. returnret;
  15. /*settheCPUsystemclock*/
  16. ret=snd_soc_dai_set_sysclk(cpu_dai,0,sysclk,SND_SOC_CLOCK_IN);
  17. if(ret<0)
  18. returnret;
  19. return0;
  20. }
  21. staticstructsnd_soc_opsevm_wm8960_ops={
  22. .startup=evm_startup,
  23. .shutdown=evm_shutdown,
  24. .hw_params=evm_wm8960_hw_params,
  25. };

至此,就完成了代码移植的全部工作,修改涉及到的三个文件是:tq335x.dts、davinci-evm.c和wm8960.c,修改后的这三个文件我会上传到我的资源,如有需要,请去我的资源中下载。

4. 配置内核

完成了代码的移植工作之后还需要对内核进一步配置。默认的内核将ALSA作为module加载,本文将编译进内核。具体步骤如下

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top