rk809-code喇叭耳机调试分享

简介: rk809-code喇叭耳机调试分享

板子:rk3568

平台:android12

1.耳机功能添加

1.1 设备树配置
 
  rk_headset: rk-headset {
    compatible = "rockchip_headset";
    headset_gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
    //hs_select = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>;
    pinctrl-names = "default";
    pinctrl-0 = <&hp_det &hs_select_pin>;
    status = "okay";
 
  };

紧接着是rk809的配置:

  rk809_sound: rk809-sound  {
    status = "okay";
    compatible = "simple-audio-card";
    simple-audio-card,format = "i2s";
    simple-audio-card,name = "rockchip,rk809-codec";
    simple-audio-card,mclk-fs = <256>;
    simple-audio-card,widgets =
    "Microphone", "Mic Jack",
    "Headphone", "Headphone Jack";
    simple-audio-card,routing =
    "Mic Jack", "MICBIAS1",
    "IN1R", "Mic Jack",
    "Headphone Jack", "HPOL",
    "Headphone Jack", "HPOR";
    simple-audio-card,cpu {
      sound-dai = <&i2s1_8ch>;
    };
    simple-audio-card,codec {
      sound-dai = <&rk809_codec>;
    };
  };
...
/* 注意codec要放在rk809pmic节点下 */
    rk809_codec: codec {
      #sound-dai-cells = <0>;
      compatible = "rockchip,rk809-codec", "rockchip,rk817-codec";
      clocks = <&cru I2S1_MCLKOUT>;
      clock-names = "mclk";
      assigned-clocks = <&cru I2S1_MCLKOUT>, <&cru I2S1_MCLK_TX_IOE>;
      assigned-clock-rates = <12288000>;
      assigned-clock-parents = <&cru I2S1_MCLKOUT_TX>, <&cru I2S1_MCLKOUT_TX>;
      pinctrl-names = "default";
      pinctrl-0 = <&i2s1m0_mclk>;
      hp-volume = <20>;
      spk-volume = <3>;
      spk-ctl-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>;
      mic-in-differential;
      status = "okay";
    };
  ...
&i2s1_8ch {
  status = "okay";
  rockchip,clk-trcm = <1>;
  pinctrl-names = "default";
  pinctrl-0 = <&i2s1m0_sclktx
         &i2s1m0_lrcktx
         &i2s1m0_sdi0
         &i2s1m0_sdo0>;
};


由于我的板子还接了一个SPEAKER所以添加了一个SPEAKER控制引脚,spk-ctl-gpios属性在sound/soc/codecs/rk817_codec.c里面会去获取这个属性,并且会去自动控制并切换,相关源码如下:


  rk817->spk_ctl_gpio = devm_gpiod_get_optional(dev, "spk-ctl",
              GPIOD_OUT_LOW);
  if (!IS_ERR_OR_NULL(rk817->spk_ctl_gpio)) {
    DBG("%s : spk-ctl-gpio %d\n", __func__,
        desc_to_gpio(rk817->spk_ctl_gpio));
  }


相应的被调用函数:


static int rk817_codec_ctl_gpio(struct rk817_codec_priv *rk817,
        int gpio, int level)
{
  if ((gpio & CODEC_SET_SPK) &&
      rk817->spk_ctl_gpio) {
    gpiod_set_value(rk817->spk_ctl_gpio, level);
    DBG("%s set spk clt %d\n", __func__, level);
    msleep(rk817->spk_mute_delay);
  }
 
  if ((gpio & CODEC_SET_HP) &&
      rk817->hp_ctl_gpio) {
    gpiod_set_value(rk817->hp_ctl_gpio, level);
    DBG("%s set hp clt %d\n", __func__, level);
    msleep(rk817->hp_mute_delay);
  }
 
  return 0;
}


当然也可以加在head_set下面,我是采用的上面这种,下面是我的patch:


diff --git a/drivers/headset_observe/rk_headset.c b/drivers/headset_observe/rk_headset.c
index 5b16db723317..14f69afe6022 100644
--- a/drivers/headset_observe/rk_headset.c
+++ b/drivers/headset_observe/rk_headset.c
@@ -159,6 +159,22 @@ static void headsetobserve_work(struct work_struct *work)
  printk("---headsetobserve_work---\n");
  mutex_lock(&headset_info->mutex_lock[HEADSET]);
  level = read_gpio(pdata->headset_gpio);
+ if(pdata->hs_select_flg == 1) //judge support headphone speaker select
+ {
+   if(pdata->hs_select_pin)
+   {
+     if (!level) { //headset out
+       gpio_direction_output(pdata->hs_select_pin, pdata->hs_select_sta);
+       printk("%s-----------------------1\r\n",__func__);
+     }
+     else { //headset in
+       gpio_direction_output(pdata->hs_select_pin, !pdata->hs_select_sta);
+       printk("%s-----------------------2\r\n",__func__);
+     }
+     printk("%s: hs_select_pin->%d hs_select_sta->%d----------",__func__,pdata->hs_select_pin,pdata->hs_select_sta);
+   }
+ }
+
  if (level < 0)
    goto out;
  msleep(100);
diff --git a/drivers/headset_observe/rk_headset.h b/drivers/headset_observe/rk_headset.h
index c10961ce66f8..9d911a082f9e 100644
--- a/drivers/headset_observe/rk_headset.h
+++ b/drivers/headset_observe/rk_headset.h
@@ -17,6 +17,12 @@ struct rk_headset_pdata {
  unsigned int hook_gpio;
  /* Hook key down status */
  unsigned int hook_down_type;
+
+ unsigned int hs_select_pin; //headphone/speaker select
+ unsigned int hs_select_sta; //headphone/speaker select state
+ unsigned int hs_select_flg; //headphone/speaker ping dts flag 1:suport headphone/speaker select 0:not support
+
+
 #ifdef CONFIG_MODEM_MIC_SWITCH
  /* mic about */
  unsigned int mic_switch_gpio;
diff --git a/drivers/headset_observe/rockchip_headset_core.c b/drivers/headset_observe/rockchip_headset_core.c
index 3c2eeb7ac213..f283a22303bf 100644
--- a/drivers/headset_observe/rockchip_headset_core.c
+++ b/drivers/headset_observe/rockchip_headset_core.c
@@ -107,6 +107,29 @@ static int rockchip_headset_probe(struct platform_device *pdev)
    }
  }
 
+ //headphone/speaker select gpio
+ ret = of_get_named_gpio_flags(node, "hs_select", 0, &pdata->hs_select_sta);
+ if(ret < 0)
+ {
+   pdata->hs_select_flg = 0;
+   printk("%s:can not get hs_select gpio property---------- %d",__func__,pdata->hs_select_flg);
+   
+ }
+ else
+ {
+   pdata->hs_select_pin = ret;
+   ret = devm_gpio_request(&pdev->dev, pdata->hs_select_pin,
+     "hs_select");
+   if(ret < 0)
+   {
+     printk("%s:can not request hs_select gpio ----------",__func__);
+     goto err;
+   }
+   printk("%s: hs_select_pin->%d hs_select_sta->%d----------",__func__,pdata->hs_select_pin,pdata->hs_select_sta);
+
+   pdata->hs_select_flg = 1;
+ }
+
 #ifdef CONFIG_MODEM_MIC_SWITCH
  /* mic */
  ret = of_get_named_gpio_flags(node, "mic_switch_gpio", 0, &flags);


但是我按照上面的添加了发现耳机是有声音的,不插耳机SPEAKER无声音输出,并且我尝试在插入耳机的同时也将SPEAKER控制脚打开SPEAKER就能有声音,所以确定上层应该是没有问题的,所以将问题锁定在驱动上,参考瑞星微文档解析:


 
Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt 
- compatible: "rockchip,rk817-codec" 
- - clocks: a list of phandle + clock-specifer pairs, one for each entry inclock-names. 
- - clock-names: should be "mclk". 
- - spk-ctl-gpios: spk mute enable/disable 用于外置功放使能脚,如果产品上有使用外置功放,请配置对应的使能脚 
- - hp-ctl-gpios: hp mute enable/disable 
- - spk-mute-delay-ms: spk mute delay time 
- - hp-mute-delay-ms: hp mute delay time 
- - spk-volume: DAC L/R volume digital setting for Speaker 配置喇叭输出音量,0 最大,255 最小 
- - hp-volume: DAC L/R volume digital setting for Headphone 配置耳机输出音量,0 最大,255 最小 
*
* DDAC L/R volume setting 
*  0db~-95db,0.375db/step,for example: 
* 0: 0dB 
*  10: -3.75dB * 125: -46dB 
*  255: -95dB 
* 
- capture-volume: ADC L/R volume digital setting for Microphone 配置录音输入音量,0 最大,255 最小 
*
* DADC L/R volume setting 
*  0db~-95db,0.375db/step,for example: 
*  0: 0dB * 10: -3.75dB 
*  125: -46dB * 255: -95dB 
* 
- mic-in-differential: 
 Boolean. Indicate MIC input is differential, rather than single-ended.
  指定使用差分 MIC,否则为单端 MIC,所以使用差分 MIC 时加上此 property。 
 - pdmdata-out-enable: 
 Boolean. Indicate pdmdata output is enabled or disabled. 
 录音数据使用 PDM 数字接口。 
 - use-ext-amplifier: 
 Boolean. Indicate use external amplifier or not. 
 指定是否使用外部功放。 - 
 adc-for-loopback: 
 Boolean. Indicate adc use for loopback or not. 指定 ADC 用于回采,一般音箱类产品使用。


从这里我们看出要使用外放功能设备树里面就要添加 use-ext-amplifier: 这个属性

所以更改设备树:


    rk809_codec: codec {
      #sound-dai-cells = <0>;
      compatible = "rockchip,rk809-codec", "rockchip,rk817-codec";
      clocks = <&cru I2S1_MCLKOUT>;
      clock-names = "mclk";
      assigned-clocks = <&cru I2S1_MCLKOUT>, <&cru I2S1_MCLK_TX_IOE>;
      assigned-clock-rates = <12288000>;
      assigned-clock-parents = <&cru I2S1_MCLKOUT_TX>, <&cru I2S1_MCLKOUT_TX>;
      pinctrl-names = "default";
      pinctrl-0 = <&i2s1m0_mclk>;
      hp-volume = <20>;
      spk-volume = <3>;
      use-ext-amplifier;
      spk-ctl-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>;
      mic-in-differential;
      status = "okay";
    };


use-ext-amplifier;这个属性指定是否使用外部功放,改过之后就可以正常放音了,下面是adb shellz中使用tinymix看到的,输出Playback Path是speaker:


sbc_rk3568:/ # tinymix                                                                                                                                                                                 
Mixer name: 'rockchip,rk809-codec'
Number of controls: 2
ctl type  num name                                     value
 
0 ENUM  1 Playback Path                            SPK
1 ENUM  1 Capture MIC Path                         MIC OFF
 


插上耳机后显示的Playback Path是HP_NO_MIC:


sbc_rk3568:/ # tinymix                                                                                                                                                                                     
Mixer name: 'rockchip,rk809-codec'
Number of controls: 2
ctl type  num name                                     value
 
0 ENUM  1 Playback Path                            HP_NO_MIC
1 ENUM  1 Capture MIC Path                         MIC OFF
 


下面是瑞芯微给出的思路:


播放无声

  • 确认音频源为 非静音文件
  • 使用 aplay 或者 tinyplay 播放,定位问题是发生在用户态还是内核态
  • 播放等待10秒以上确认是否为 I/O error 问题
  • 使用 amixer 或者 tinymix 检查 CODEC 内部 DAC 通路是否打开,音量是否静音
  • 查看 寄存器 配置,配合芯片手册或者 CODEC 手册确认配置是否正确:IOMUX,DAI,CODEC。
  • 使用 万用表 和 示波器 测量电压,时钟,数据。确认电压,时钟正常,数据线上有波形;测量
  • CODEC 近端 模拟输出信号是否正常,测量 PA 使能 gpio 电平,逐级定位问题点


目录
相关文章
|
4天前
|
编解码 Android开发 芯片
RK3288 主板上的RT5651芯片SPK音频无声音问题解决方案
RK3288 主板上的RT5651芯片SPK音频无声音问题解决方案
50 2
arduino环境基于wemos串口调试小助手控制小车前后左右烧写源码
arduino环境基于wemos串口调试小助手控制小车前后左右烧写源码
93 0
arduino环境基于wemos串口调试小助手控制小车前后左右烧写源码
Win系统 - WIN10 更新后蓝牙音箱无法连接成 Stereo 模式(立体声)
Win系统 - WIN10 更新后蓝牙音箱无法连接成 Stereo 模式(立体声)
897 0
Win系统 - WIN10 更新后蓝牙音箱无法连接成 Stereo 模式(立体声)
|
8月前
|
芯片
记一次段码屏调试总结
记一次段码屏调试总结
|
传感器 Ubuntu Java
ESP-IDF 蓝牙开发实战 — 传感器数据上传及手机控制开发板
ESP32-C3 蓝牙部分我们学习了GATT,本文博主手把手带领大家使用 ESP32-C3的蓝牙做一个简单的小应用。
829 0
ESP-IDF 蓝牙开发实战 — 传感器数据上传及手机控制开发板
|
数据采集 IDE 开发工具
在Airtest中如何使用无线模式控制手机
在Airtest中如何使用无线模式控制手机
250 0
|
安全 芯片
bluez5.50+pulseaudio实现蓝牙音响音频播放
bluez5.50+pulseaudio实现蓝牙音响音频播放
632 0
bluez5.50+pulseaudio实现蓝牙音响音频播放
语音模块语音输入树莓派打印开灯关灯源码
语音模块语音输入树莓派打印开灯关灯源码
57 0
语音模块语音输入树莓派打印开灯关灯源码
|
内存技术
RK3288 Android7.1 接USB摄像头后扬声器无声音
RK3288 Android7.1 接USB摄像头后扬声器无声音
241 0
|
Java 开发工具 Android开发
利用MCU实现制作一台蓝牙控制小车方法
今天主要和大家分享一下,如何使用MCU自己做一台蓝牙小车,并通过自己写的APP进行控制。
156 0
利用MCU实现制作一台蓝牙控制小车方法