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

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

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

至此,就完成了DTS的全部配置,后面我会将完整的DTS文件上传到我的资源。

2. Codec驱动完善

Step1. 修改Codec驱动,使其支持DTS

由于我们在DTS中指定了Codec的compatible为"wlf,wm8960",而Linux内核自带的WM8960驱动并没有支持新式的DTS模式关联。修改方法很简单,添加i2c_driver的.driver中指定of_match_table即可,修改后的代码片段如下:

  1. staticconststructof_device_idwm8960_of_match[]={
  2. {.compatible="wlf,wm8960",},
  3. {}
  4. };
  5. MODULE_DEVICE_TABLE(of,wm8960_of_match);
  6. staticstructi2c_driverwm8960_i2c_driver={
  7. .driver={
  8. .name="wm8960",
  9. .owner=THIS_MODULE,
  10. .of_match_table=wm8960_of_match,
  11. },
  12. .probe=wm8960_i2c_probe,
  13. .remove=wm8960_i2c_remove,
  14. .id_table=wm8960_i2c_id,
  15. };

Step2. 完善WM8960的初始化信息

默认的WM8960驱动初始化信息不够完整,还需要对WM8960进行额外的初始化,修改后的代码片段如下:

  1. staticintwm8960_probe(structsnd_soc_codec*codec)
  2. {
  3. structwm8960_priv*wm8960=snd_soc_codec_get_drvdata(codec);
  4. structwm8960_data*pdata=dev_get_platdata(codec->dev);
  5. intret;
  6. wm8960->set_bias_level=wm8960_set_bias_level_out3;
  7. if(!pdata){
  8. dev_warn(codec->dev,"Noplatformdatasupplied");
  9. }else{
  10. if(pdata->capless)
  11. wm8960->set_bias_level=wm8960_set_bias_level_capless;
  12. }
  13. ret=wm8960_reset(codec);
  14. if(ret<0){
  15. dev_err(codec->dev,"Failedtoissuereset");
  16. returnret;
  17. }
  18. wm8960->set_bias_level(codec,SND_SOC_BIAS_STANDBY);
  19. /*Latchtheupdatebits*/
  20. snd_soc_update_bits(codec,WM8960_LINVOL,0x100,0x100);
  21. snd_soc_update_bits(codec,WM8960_RINVOL,0x100,0x100);
  22. snd_soc_update_bits(codec,WM8960_LADC,0x100,0x100);
  23. snd_soc_update_bits(codec,WM8960_RADC,0x100,0x100);
  24. snd_soc_update_bits(codec,WM8960_LDAC,0x100,0x100);
  25. snd_soc_update_bits(codec,WM8960_RDAC,0x100,0x100);
  26. snd_soc_update_bits(codec,WM8960_LOUT1,0x100,0x100);
  27. snd_soc_update_bits(codec,WM8960_ROUT1,0x100,0x100);
  28. snd_soc_update_bits(codec,WM8960_LOUT2,0x100,0x100);
  29. snd_soc_update_bits(codec,WM8960_ROUT2,0x100,0x100);
  30. /*otherconfiguration*/
  31. snd_soc_update_bits(codec,WM8960_POWER1,0x1ea,0x1ea);
  32. snd_soc_update_bits(codec,WM8960_POWER2,0x1f8,0x1f8);
  33. snd_soc_update_bits(codec,WM8960_POWER3,0xcc,0xcc);
  34. snd_soc_update_bits(codec,WM8960_LOUTMIX,0x100,0x100);
  35. snd_soc_update_bits(codec,WM8960_ROUTMIX,0x100,0x100);
  36. snd_soc_update_bits(codec,WM8960_POWER3,0xc,0xc);
  37. snd_soc_update_bits(codec,WM8960_LOUT1,0x7f,0x7f);
  38. snd_soc_update_bits(codec,WM8960_ROUT1,0x7f,0x7f);
  39. snd_soc_update_bits(codec,WM8960_IFACE2,0x40,0x40);
  40. snd_soc_update_bits(codec,WM8960_MONOMIX2,0x120,0x120);
  41. snd_soc_update_bits(codec,WM8960_LINPATH,0x1f8,0x138);
  42. snd_soc_update_bits(codec,WM8960_LINVOL,0x19f,0x11f);
  43. snd_soc_update_bits(codec,WM8960_RINVOL,0x19f,0x11f);
  44. snd_soc_update_bits(codec,WM8960_LOUT2,0x1ff,0x1ff);
  45. snd_soc_update_bits(codec,WM8960_ROUT2,0x1ff,0x1ff);
  46. snd_soc_update_bits(codec,WM8960_CLASSD3,0x1a,0x12);
  47. snd_soc_update_bits(codec,WM8960_CLASSD1,0xc0,0xc0);
  48. snd_soc_add_codec_controls(codec,wm8960_snd_controls,
  49. ARRAY_SIZE(wm8960_snd_controls));
  50. wm8960_add_widgets(codec);
  51. return0;
  52. }

具体的含义可以参考WM8960的芯片手册,这里我就不一一介绍了。

Step3. 调整WM8960驱动结构

内核中自带的WM8960驱动结构很旧,编写Machine是需要过多的了解Codec芯片内部细节,本文对WM8960的驱动结构进行了调整,可以使Machine忽略Codec的内部细节。

修改的大体内容如下:

(1) 添加set_sysclk函数,接收Machine设置的sysclk时钟频率。具体本文就是DTS中设置的24576000。

(2) 在hw_params中添加BCLK、DACCLK、ADCCLK的配置操作。hw_params可以根据参数和sysclk对以上参数进行设置,放在这里很合适。

(3) 去除函数wm8960_set_dai_clkdiv,并将wm8960_set_dai_pll设置为驱动内部函数,不作为set_pll接口提供给内核驱动(实际上内核驱动也不调用这个函数)。

Step4. 修改WM8960的route信息

根据TQ335x的原理图可知,使用WM8960进行录音或放音时使用的LRCLK是同一个,都是DACCLK,故在snd_soc_dapm_route添加如下两行信息:

  1. {"LeftDAC",NULL,"LeftInputMixer"},
  2. {"R

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

网站地图

Top