1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > [Linux Audio Driver] 高通TDM总线配置

[Linux Audio Driver] 高通TDM总线配置

时间:2023-12-16 15:19:19

相关推荐

[Linux Audio Driver] 高通TDM总线配置

0. 背景

TDM接口与平台SOC相关,调试前需要确定平台支持TDM,目前一些中高端的平台都支持的。(转载请备注链接)

本文介绍配置: SEN_TDM_TX_0。

1. tinymix查看当前虚拟总线配置

adb shell tinymix > tinymix_source.txt

RX_CDC_DMA_RX_0这个虚拟总线是一直用的,这个显然存在,然后检索TDM。

Line 248: 243BOOL1RX_CDC_DMA_RX_0_DL_HL Switch OffLine 471: 466BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia1 Off OffLine 472: 467BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia2 Off OffLine 473: 468BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia3 Off OffLine 474: 469BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia4 Off OffLine 475: 470BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia5 Off OffLine 476: 471BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia6 Off OffLine 477: 472BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia7 Off OffLine 478: 473BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia8 Off OffLine 479: 474BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia9 Off OffLine 480: 475BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia10 Off OffLine 481: 476BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia11 Off OffLine 482: 477BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia12 Off OffLine 483: 478BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia13 Off OffLine 484: 479BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia14 Off OffLine 485: 480BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia15 Off OffLine 486: 481BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia16 Off OffLine 487: 482BOOL2RX_CDC_DMA_RX_0 Audio Mixer MultiMedia26 Off OffLine 1024: 1019BOOL2RX_CDC_DMA_RX_0_Voice Mixer Voip Off OffLine 1025: 1020BOOL2RX_CDC_DMA_RX_0_Voice Mixer VoiceMMode1 Off OffLine 1026: 1021BOOL2RX_CDC_DMA_RX_0_Voice Mixer VoiceMMode2 Off OffLine 1204: 1199BOOL2RX_CDC_DMA_RX_0 Port Mixer TX_CDC_DMA_TX_3 Off OffLine 1205: 1200BOOL2RX_CDC_DMA_RX_0 Port Mixer SLIM_8_TXOff OffLine 1607: 1602ENUM1RX_CDC_DMA_RX_0 Format S16_LELine 1612: 1607ENUM1RX_CDC_DMA_RX_0 SampleRateKHZ_48Line 2544: 2539ENUM1RX_CDC_DMA_RX_0 Channels One

没有找到上面类似的控件,下面这个TDM log不晓得干嘛的,QUIN_TDM_TX_0是我不需要的,由于硬件设计,目标是要配置SEN_TDM。

Line 1321: 1316ENUM1TERT_TDM_TX_0 LSM FunctionSWAUDIOLine 1595: A_TX_31583BYTE376Source Tracking Audio Tx TX_CDC_DMA_TX_3Line 1595: A_TX_31583BYTE376Source Tracking Audio Tx TX_CDC_DMA_TX_3Line 1595: A_TX_31583BYTE376Source Tracking Audio Tx TX_CDC_DMA_TX_3Line 1595: A_TX_31583BYTE376Source Tracking Audio Tx TX_CDC_DMA_TX_3Line 1595: A_TX_31583BYTE376Source Tracking Audio Tx TX_CDC_DMA_TX_3Line 1595: A_TX_31583BYTE376Source Tracking Audio Tx TX_CDC_DMA_TX_31584BYTE26Sound Focus Voice Tx QUIN_TDM_TX_0 1584BYTE26Sound Focus Voice Tx QUIN_TDM_TX_0 1584BYTE26Sound Focus Voice Tx QUIN_TDM_TX_0 1584BYTE26Sound Focus Voice Tx QUIN_TDM_TX_0 1584BYTE26Sound Focus Voice Tx QUIN_TDM_TX_0 1584BYTE26Sound Focus Voice Tx QUIN_TDM_TX_0 1589BYTE376Source Tracking Audio Tx PRIMARY_TDM15901589BYTE376Source Tracking Audio Tx PRIMARY_TDM15901589BYTE376Source Tracking Audio Tx PRIMARY_TDM15901589BYTE376Source Tracking Audio Tx PRIMARY_TDM15901589BYTE376Source Tracking Audio Tx PRIMARY_TDM1590ENUM1SLIM7_RX ADM ChannelsZeroENUM1SLIM7_RX ADM ChannelsZeroENUM1SLIM7_RX ADM ChannelsZeroENUM1SLIM7_RX ADM ChannelsZeroENUM1SLIM7_RX ADM ChannelsZero

从当前的情况来看,应该是要修改一些设备树配置,或者代码里面的一些宏定义没有打开。于是进入下一步,在machine driver里面加log。

2. 加log调试分析

./vendor/qcom/opensource/audio-kernel/asoc/kona.c

在machine driver里面检索TDM,发现了大量的结构体以及宏定义,于是准备在所有TDM的调用代码里面加log分析。

(其实后面都没分析log,因为在加log的过程中就把代码看的差不多了-_-。)

Line 79: #define TDM_CHANNEL_MAX8Line 108: TDM_0 = 0,Line 109: TDM_1,Line 110: TDM_2,Line 111: TDM_3,Line 112: TDM_4,Line 113: TDM_5,Line 114: TDM_6,Line 115: TDM_7,Line 116: TDM_PORT_MAX,Line 119: #define TDM_MAX_SLOTS 8Line 120: #define TDM_SLOT_WIDTH_BITS 32Line 121: #define TDM_SLOT_WIDTH_BYTES TDM_SLOT_WIDTH_BITS/8Line 121: #define TDM_SLOT_WIDTH_BYTES TDM_SLOT_WIDTH_BITS/8Line 124: TDM_PRI = 0,Line 125: TDM_SEC,Line 126: TDM_TERT,Line 127: TDM_QUAT,Line 128: TDM_QUIN,Line 129: TDM_SEN,Line 130: TDM_INTERFACE_MAX,Line 212: u32 tdm_max_slots; /* Max TDM slots used */Line 212: u32 tdm_max_slots; /* Max TDM slots used */Line 217: struct tdm_port {Line 222: struct tdm_dev_config {Line 223: unsigned int tdm_slot_offset[TDM_MAX_SLOTS];Line 223: unsigned int tdm_slot_offset[TDM_MAX_SLOTS];Line 347: /* Default configuration of TDM channels */Line 348: static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {Line 348: static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {Line 348: static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {Line 349: {/* PRI TDM */Line 359: {/* SEC TDM */Line 369: {/* TERT TDM */Line 379: {/* QUAT TDM */Line 389: {/* QUIN TDM */Line 399: {/* SEN TDM */Line 411: static struct dev_config tdm_tx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {Line 411: static struct dev_config tdm_tx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {Line 411: static struct dev_config tdm_tx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {

就像下面这样,相关函数都加上log。

static int tdm_rx_sample_rate_put(struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol){struct tdm_port port;int ret = tdm_get_port_idx(kcontrol, &port);+ pr_err("#nigulasi#,debug,fun=%s,ret=%d",__func__,ret);if (ret) {pr_err("%s: unsupported control: %s\n",__func__, kcontrol->id.name);} else {tdm_rx_cfg[port.mode][port.channel].sample_rate =tdm_get_sample_rate(ucontrol->value.enumerated.item[0]);pr_debug("%s: tdm_rx_sample_rate = %d, item = %d\n", __func__,tdm_rx_cfg[port.mode][port.channel].sample_rate,ucontrol->value.enumerated.item[0]);}return ret;}

在加log的时候,发现几个地方可能是重点:

static int msm_asoc_machine_probe(struct platform_device *pdev)...ret = of_property_read_u32(pdev->dev.of_node, "qcom,tdm-max-slots",&pdata->tdm_max_slots);pr_err("#nigulasi#,debug,fun=%s,ret=%d",__func__,ret);if (ret) {dev_err(&pdev->dev, "%s: No DT match for tdm max slots\n",__func__);}if ((pdata->tdm_max_slots <= 0) || (pdata->tdm_max_slots >TDM_MAX_SLOTS)) {pdata->tdm_max_slots = TDM_MAX_SLOTS;dev_err(&pdev->dev, "%s: Using default tdm max slot: %d\n",__func__, pdata->tdm_max_slots);}

#define TDM_MAX_SLOTS 8

qcom,tdm-max-slots这个设备树属性要解析放在pdata->tdm_max_slots里面,代码里面还有控制,超出范围强制配置为8,这个后面看了下参考链接1,意思应该是LRCK/WS包含的声道数,这个就是同时包含8声道数据。

static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)...rc = of_property_read_u32(dev->of_node, "qcom,tdm-audio-intf",&val);pr_err("#nigulasi#,debug,fun=%s,rc=%d,val=%d",__func__,rc,val);if (!rc && val) {memcpy(msm_kona_dai_links + total_links,msm_tdm_be_dai_links,sizeof(msm_tdm_be_dai_links));total_links +=ARRAY_SIZE(msm_tdm_be_dai_links);}

static struct snd_soc_dai_link msm_tdm_be_dai_links[] = {{.name = LPASS_BE_PRI_TDM_RX_0,.stream_name = "Primary TDM0 Playback",.cpu_dai_name = "msm-dai-q6-tdm.36864",.platform_name = "msm-pcm-routing",.codec_name = "msm-stub-codec.1",.codec_dai_name = "msm-stub-rx",.no_pcm = 1,.dpcm_playback = 1,.id = MSM_BACKEND_DAI_PRI_TDM_RX_0,.be_hw_params_fixup = msm_be_hw_params_fixup,.ops = &kona_tdm_be_ops,.ignore_suspend = 1,.ignore_pmdown_time = 1,},....

这个地方来看qcom,tdm-audio-intf的值必须为1(true),原因是结构体数组msm_tdm_be_dai_links里面全是TDM相关的东西,

于是在对应的音频设备树里面加上两个修改:

./vendor/qcom/proprietary/devicetree-4.19/qcom/lagoon-audio.dtsi

&q6core {lagoon_snd: sound {compatible = "qcom,kona-asoc-snd";......clock-names = "lpass_audio_hw_vote";clocks = <&lpass_audio_hw_vote 0>;+ qcom,tdm-audio-intf = <1>;//config TDM + qcom,tdm-max-slots = <8>;

还有个宏,

#ifndef CONFIG_TDM_DISABLEstatic void msm_add_tdm_snd_controls(struct snd_soc_component *component){pr_err("#nigulasi#,debug,fun=%s",__func__);snd_soc_add_component_controls(component, msm_tdm_snd_controls,ARRAY_SIZE(msm_tdm_snd_controls));}#elsestatic void msm_add_tdm_snd_controls(struct snd_soc_component *component){pr_err("#nigulasi#,debug,fun=%s",__func__);return;}#endif#ifndef CONFIG_MI2S_DISABLEstatic void msm_add_mi2s_snd_controls(struct snd_soc_component *component){snd_soc_add_component_controls(component, msm_mi2s_snd_controls,ARRAY_SIZE(msm_mi2s_snd_controls));}#elsestatic void msm_add_mi2s_snd_controls(struct snd_soc_component *component){return;}#endif

这里说如果没定义CONFIG_TDM_DISABLE,那么就走下面这个函数,然后就走空函数,我们需要TDM功能,那么得把这个宏定义给干掉,

grep -nr "CONFIG_TDM_DISABLE" ./vendor/vim ./vendor/qcom/opensource/audio-kernel/config/litoautoconf.h//#define CONFIG_TDM_DISABLE 1

3. 编译报错与继续分析

/kernel/msm-4.19/../../vendor/qcom/opensource/audio-kernel/asoc/msm-pcm-routing-v2.c:25533:5: error: use of undeclared identifier 'sen_mi2s_rx_voice_mixer_controls'; did you mean 'slimbus_rx_voice_mixer_controls'?sen_mi2s_rx_voice_mixer_controls,

这个报错我有点懵逼, 它说用了没定义的sen_mi2s_rx_voice_mixer_controls,找到报错的地方,它被宏:

CONFIG_MI2S_DISABLE包含了,

#ifndef CONFIG_MI2S_DISABLE...static const struct snd_kcontrol_new sen_mi2s_rx_voice_mixer_controls[] = {SOC_DOUBLE_EXT("Voip", SND_SOC_NOPM,MSM_BACKEND_DAI_SENARY_MI2S_RX,MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,msm_routing_put_voice_mixer),SOC_DOUBLE_EXT("DTMF", SND_SOC_NOPM,MSM_BACKEND_DAI_SENARY_MI2S_RX,MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,msm_routing_put_voice_mixer),SOC_DOUBLE_EXT("QCHAT", SND_SOC_NOPM,MSM_BACKEND_DAI_SENARY_MI2S_RX,MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,msm_routing_put_voice_mixer),SOC_DOUBLE_EXT("VoiceMMode1", SND_SOC_NOPM,MSM_BACKEND_DAI_SENARY_MI2S_RX,MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer,msm_routing_put_voice_mixer),SOC_DOUBLE_EXT("VoiceMMode2", SND_SOC_NOPM,MSM_BACKEND_DAI_SENARY_MI2S_RX,MSM_FRONTEND_DAI_VOICEMMODE2, 1, 0, msm_routing_get_voice_mixer,msm_routing_put_voice_mixer),};

这个宏就在我注释掉CONFIG_TDM_DISABLE的前面,默认就是打开的,这里没毛病,配置TDM嘛,就关掉MI2S。

也就是说这个结构体数组的原型被宏注释掉了,那直接把调用的函数干掉即可:

//SND_SOC_DAPM_MIXER("SEN_MI2S_RX_Voice Mixer",//SND_SOC_NOPM, 0, 0,//sen_mi2s_rx_voice_mixer_controls,//ARRAY_SIZE(sen_mi2s_rx_voice_mixer_controls)),

编译好了之后,烧录vendor.img,把tinymix控件都打印出来。

adb shell tinymix > tinymix.txt

检索TDM,好家伙匹配了1920次,SEN_TDM_TX_0这个虚拟总线是我们需要的。但是这里还不算完,我们总要看看TDM波形才能说配置好了吧。

4. 抓TDM波形

比如我们要配置一个12.288MHz,BCLK的TDM总线,WS/LRCK一般都是配置48Khz,位深度是32 bit,然后有8个声道,计算起来SCLK/BCLK就是12.288MHz。

12.288 MHz = 48 kHz * 32 bits per slot * 8 slots/channels

./vendor/qcom/proprietary/devicetree-4.19/qcom/lagoon-audio-overlay.dtsi

然后我们修改SEN总线相关的GPIO配置,这里LPI对应10、11、12、13;正常GPIO号对应137、138、139、140;其实他们的本质是一致的。

lpi_i2s2_clk – LPI_GPIO_10lpi_i2s2_ws – LPI_GPIO_11lpi_i2s2_data0 – LPI_GPIO_12lpi_i2s2_data1 – LPI_GPIO_13

lpi_i2s2_clk – GPIO_137lpi_i2s2_ws – GPIO_138lpi_i2s2_data0 – GPIO_139lpi_i2s2_data1 – GPIO_140

代码里面发现sen的几个gpio在如下位置被解析。

./vendor/qcom/opensource/audio-kernel/asoc/kona.c

static int msm_asoc_machine_probe(struct platform_device *pdev)...pdata->mi2s_gpio_p[SEN_MI2S] = of_parse_phandle(pdev->dev.of_node,"qcom,sen-mi2s-gpios", 0);

于是对设备树增加修改如下(就是把占用gpio的干掉,其他抄相邻的格式修改):

qcom,cdc-dmic23-gpios = <&cdc_dmic23_gpios>;- qcom,cdc-dmic45-gpios = <&cdc_dmic45_gpios>;+ //qcom,cdc-dmic45-gpios = <&cdc_dmic45_gpios>;+ qcom,sen-mi2s-gpios = <&lpi_tdm2_gpios>;asoc-codec = <&stub_codec>, <&bolero>;asoc-codec-names = "msm-stub-codec.1", "bolero_codec";qcom,wsa-max-devs = <0>;@@ -364,6 +365,7 @@};cdc_dmic45_gpios: cdc_dmic45_pinctrl {+status = "disabled";compatible = "qcom,msm-cdc-pinctrl";pinctrl-names = "aud_active", "aud_sleep";pinctrl-0 = <&cdc_dmic45_clk_active &cdc_dmic45_data_active>;@@ -372,6 +374,16 @@qcom,tlmm-gpio = <139 140>;};+ lpi_tdm2_gpios: lpi_tdm2_pinctrl {+status = "ok";+compatible = "qcom,msm-cdc-pinctrl";+pinctrl-names = "aud_active", "aud_sleep";+pinctrl-0 = <&lpi_tdm2_sck_active &lpi_tdm2_ws_active + &lpi_tdm2_sd0_active &lpi_tdm2_sd1_active>;+pinctrl-1 = <&lpi_tdm2_sck_sleep &lpi_tdm2_ws_sleep + &lpi_tdm2_sd0_sleep &lpi_tdm2_sd1_sleep>;+qcom,lpi-gpios;+qcom,tlmm-gpio = <137 138 139 140>;+ };

改了之后用示波器抓波形,然后执行以下tinyalsa命令使得总线工作:

tinymix "MultiMedia1 Mixer SEN_TDM_TX_0" "1"

WS以及LRCK都是稳稳的一条直线,木得一点反应。。。

之后反应过来,要让他起个进程才能让总线一直工作,所以这回除了配置AFE,还加上了tinycap命令。

tinymix "MultiMedia1 Mixer SEN_TDM_TX_0" "1"tinycap /sdcard/test.wav

然后就有波形了,WS(48Khz),BCLK(12.288Mhz)

ws从高通文档里面看到三种模式:

./vendor/qcom/proprietary/devicetree-4.19/qcom/msm-audio-lpass.dtsi

AFE_PORT_TDM_SHORT_SYNC_BIT_MODE 0AFE_PORT_TDM_LONG_SYNC_MODE 1AFE_PORT_TDM_SHORT_SYNC_MODE 2

qcom,msm-cpudai-tdm-sync-mode = <1>;

代码默认为1就是上面那种方波,

如果改成0,就是这种脉冲波形,为2不晓得,当初没抓波形-_-,(后来板子被烧了也没法抓了)。

TDM总线配置出来并不是终点,从这里就看出来芯片的WS就至少有两种,这个应该要和调试的外部CODEC 芯片相匹配,需要和FAE沟通。

5. 参考链接

/fellow1988/p/11055680.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。