RK3288_Android7.1:调试es8388(es8323)

张裕  高级会员 | 2024-7-24 08:53:49 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 212|帖子 212|积分 636

主控:RK3288_android7.1
配景:公司须要在RK3288主板上调试ES8388音频芯片,实现喇叭外放,耳机,MIC灌音功能,原理图如下。


1、ES8388 简介

   ES8388是一种高性能、低功耗、低资本的音频编解码器。它由两路ADC,2通道DAC,发话器放大器、耳机放大器、数字音效、模拟混淆和增益功能。     ES8388采用先辈的多位Δ∑调制技能实现数字与模拟之间的数据转换。多比特Δ∑调制器使器件对时钟抖动和低带外噪声的敏捷度低。它应用于:MID,MP3, MP4, PMP,无线音频,数码相机,摄像机,GPS范畴,蓝牙,便携式音频设备。     因为具有双路特性。     ADC特点为:24位,8千赫到96千赫取样频率;95分贝动态范围,95分贝信噪比,85分贝THD + N;立体声或单麦克风接口与麦克风放大器;主动电平控制和噪声门;2模拟输入选择;各种模拟输入混淆和增益。     DAC特点为:24位,8千赫到96千赫取样频率;动态范围为96 dB,96 dB的信噪比,83分贝THD + N;40毫瓦耳机放大器无噪音的;耳机无模式;立体声增强;各种模拟输出混淆并获得Low Power等等   2、驱动

   在RK的sdk中没有ES8388的驱动,但是有ES8323的驱动,与ES8388通用。  

3、修改 rockchip_defconfig

   CONFIG_SND_SOC_ES8323=y   4、修改dts

       sound_card {            status = "okay";            compatible = "simple-audio-card";            simple-audio-card,format = "i2s";            simple-audio-card,name = "rockchip,es8323-codec";            simple-audio-card,mclk-fs = <512>;            simple-audio-card,widgets =                "Microphone", "Microphone Jack",                "Headphone", "Headphone Jack";            simple-audio-card,routing =                "MIC1", "Microphone Jack", "MIC2",                "Microphone Jack", "Microphone Jack",                "micbias1", "Headphone Jack", "HPOL",                "Headphone Jack", "HPOR";             simple-audio-card,dai-link@0 {                format = "i2s";                 cpu {                    sound-dai = <&i2s>;                };                 codec {                    sound-dai = <&es8323>;                };            };             simple-audio-card,dai-link@1 {                format = "i2s";                 cpu {                    sound-dai = <&i2s>;                };                 codec {                    sound-dai = <&hdmi>;                };            };        };     &i2c2 {        status = "okay";        es8323: es8323@10 {            #sound-dai-cells = <0>;            compatible = "everest,es8323";            reg = <0x10>;            clocks = <&cru SCLK_I2S0_OUT>;            clock-names = "mclk";            pinctrl-names = "default";            pinctrl-0 = <&i2s0_mclk>;            spk-con-gpio = <&gpio7 RK_PA5 GPIO_ACTIVE_LOW>;            hp-det-gpio = <&gpio7 RK_PB7 GPIO_ACTIVE_LOW>;            status = "okay";        };    };   后续问题1:

添加完上述部分es8388的MIC和耳机都能正常利用了,喇叭只有在耳机插入时才有声音,说明耳机插入检测反了,须要修改驱动。
kernel\sound\soc\codecs\es8323.c
  1. static irqreturn_t hp_det_irq_handler(int irq, void *dev_id)
  2. {
  3.         struct es8323_priv *es8323 = es8323_private;
  4. -   if (gpio_get_value(es8323->hp_det_gpio)){
  5. +        if (!gpio_get_value(es8323->hp_det_gpio)){
  6.                 es8323->hp_inserted = 0;
  7.         }
  8.         else{
  9.                 es8323->hp_inserted = 1;
  10.         }
  11.         if (es8323->muted == 0) {
  12.                 if (es8323->hp_det_level != es8323->hp_inserted){
  13.                         es8323_set_gpio(ES8323_CODEC_SET_SPK, !es8323->spk_gpio_level);
  14.                 }               
  15.                 else{
  16.                         es8323_set_gpio(ES8323_CODEC_SET_SPK, es8323->spk_gpio_level);
  17.                 }       
  18.         }
  19.         return IRQ_HANDLED;
  20. }
复制代码
后续问题2:

修改之后耳机检测正常,插入耳机时喇叭静音,但后续又发现耳机插入时无耳机图标,之前在做rk3568搭配rk809codec时是有耳机图标的,查抄dts发现之前3568是利用了rk_headset.c驱动来检测耳机插入,将耳机插入事件上报到上层,才显示耳机图标。

现在es8323驱动有耳机检测脚但不会上报插入事件,如果换成将耳机检测也换成rockchip_headset来检测,耳机插入时会有图标显示,但是喇叭不会静音,二者不可兼得。
于是我检察了rk_headset.c驱动发现了耳机插入事件上报的地方,理论上只要将这部分处理惩罚也添加到es8323里即可
rk_headset.c中在headsetobserve_work的中断处理惩罚函数来检测耳机是否插入,在检测完后有一个switch_set_state函数去更改耳机状态。

   百度了一下发现,Android会利用switch处理惩罚模块来检测一些开关量,例如hdmi,耳机等等。那就说明耳机插入是通过witch模块来检测的,但是还是不知道如何它是如何上报这个事件的。     背面想到了抓取耳机插入的日志,发现了事件上报的位置。    frameworks\base\services\core\java\com\android\server\WiredAccessoryManager.java
  

  它是通过检测/sys/devices/virtual/switch/h2w/state(/sys/class/switch/h2w/state)节点的值,来判定耳机插入。
  

  

  具体流程参考该文章 :Android 耳机事件传递流程_msg_new_device_state-CSDN博客
  现在知道是通过检测/sys/devices/virtual/switch/h2w/节点来判定耳机是否插入,那我们就只须要效仿rk_headset.c在es8323驱动中添加这一部分代码。
  1. --- a/kernel/sound/soc/codecs/es8323.c
  2. +++ b/kernel/sound/soc/codecs/es8323.c
  3. @@ -33,6 +33,7 @@
  4. #include <linux/gpio.h>
  5. #include <linux/interrupt.h>
  6. #include <linux/irq.h>
  7. +#include <linux/switch.h> //add by xuan 2024.03.14
  8. #include "es8323.h"
  9. #define INVALID_GPIO -1
  10. @@ -42,6 +43,13 @@
  11. #define es8323_DEF_VOL 0x1b
  12. +struct switch_dev headset_switch; //add by xuan 2024.03.14
  13. +
  14. +static ssize_t Headset_print_name(struct switch_dev *sdev, char *buf)
  15. +{
  16. +       return sprintf(buf, "Headset\n");
  17. +}
  18. +
  19. static int es8323_set_bias_level(struct snd_soc_codec *codec,
  20.                                  enum snd_soc_bias_level level);
  21. @@ -103,16 +111,26 @@ static irqreturn_t hp_det_irq_handler(int irq, void *dev_id)
  22. {
  23.         struct es8323_priv *es8323 = es8323_private;
  24. -       if (gpio_get_value(es8323->hp_det_gpio))
  25. +       if (!gpio_get_value(es8323->hp_det_gpio)){
  26.                 es8323->hp_inserted = 0;
  27. -       else
  28. +               switch_set_state(&headset_switch, 0); //add by xuan 2024.03.14 (耳机插入状态更改)
  29. +       }
  30. +       else{
  31.                 es8323->hp_inserted = 1;
  32. +               switch_set_state(&headset_switch, 1); //add by xuan 2024.03.14 (耳机插入状态更改)
  33. +       }
  34. +
  35. +       printk("es8323->hp_inserted = %d\n", es8323->hp_inserted);
  36.         if (es8323->muted == 0) {
  37. -               if (es8323->hp_det_level != es8323->hp_inserted)
  38. +               if (es8323->hp_det_level != es8323->hp_inserted){
  39.                         es8323_set_gpio(ES8323_CODEC_SET_SPK, !es8323->spk_gpio_level);
  40. -               else
  41. +                       printk("es8323_set_gpio = %d\n", !es8323->spk_gpio_level);
  42. +               }
  43. +               else{
  44.                         es8323_set_gpio(ES8323_CODEC_SET_SPK, es8323->spk_gpio_level);
  45. +                       printk("es8323_set_gpio = %d\n", es8323->spk_gpio_level);
  46. +               }
  47.         }
  48.         return IRQ_HANDLED;
  49. }
  50. @@ -799,6 +817,14 @@ static int es8323_probe(struct snd_soc_codec *codec)
  51.         struct es8323_priv *es8323 = snd_soc_codec_get_drvdata(codec);
  52.         int ret = 0;
  53. +       /* add by xuan 2024.03.14 [耳机插入检测switch事件上报 (参考:rk_headset.c的switch上报处理)] */
  54. +       headset_switch.name = "h2w";
  55. +       headset_switch.print_name = Headset_print_name;
  56. +       ret = switch_dev_register(&headset_switch);
  57. +       if(ret < 0){
  58. +               printk("es8323: register headset_switch failed!!!\n");
  59. +       }
  60. +       /* end, add by xuan 2024.03.14 */
  61.         if (codec == NULL) {
  62.                 dev_err(codec->dev, "Codec device not registered\n");
  63.                 return -ENODEV;
复制代码


  修改完后,dts中rockchip_headset和es8323不能同时打开,否则都会生成h2w节点,会辩论
  总结:

  这次调试的主要问题还是在耳机检测部分,这部分问题笔者以为还是利用了讨巧的方法解决,希望以后能有更好的解决方式。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张裕

高级会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表