我们正在尝试为具有 NXP 的 i.MX8MP MPU 的定制电路板引入 TLV320AIC3100音频编解码器。 我们针对编解码器的 DT 配置基于此论坛上发布的许多其他内容、如下所示:
/ reg_audio_pwr: regulator-audio-pwr { compatible = "regulator-fixed"; regulator-name = "audio-pwr"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; enable-active-high; regulator-always-on; }; reg_audio_pwr_1v8: regulator-audio-pwr { compatible = "regulator-fixed"; regulator-name = "audio-pwr"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; enable-active-high; regulator-always-on; }; vdd_input: vdd_input { compatible = "regulator-fixed"; regulator-name = "vdd_input"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; enable-active-high; regulator-always-on; }; sound-tlv320aic31xx { compatible = "simple-audio-card"; simple-audio-card,name = "tlv320aic31xx-Codec"; simple-audio-card,format = "i2s"; simple-audio-card,frame-master = <&dailink_master>;//Which one is master simple-audio-card,bitclock-master = <&dailink_master>;//which one is master simple-audio-card,mclk-fs = <256>;//Multiplication rate between stream rate and codec mclk simple-audio-card,widgets = "Speaker", "External Speaker", "Headphone", "Headphone Jack"; simple-audio-card,routing = "External Speaker", "SPK", "Headphone Jack", "HPL", "Headphone Jack", "HPR"; dailink_master:simple-audio-card,cpu { sound-dai = <&sai3>; }; thecodec:simple-audio-card,codec { sound-dai = <&tlv320aic3100>; clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIO_BLK_CTRL_SAI3_MCLK1>; }; }; &i2c5 { clock-frequency = <100000>; /* Lower clock speed for external bus. */ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c5>; status = "okay"; tlv320aic3100: tlv320aic31xx@18 { pinctrl-0 = <&pinctrl_dac_rst>; pinctrl-names= "default"; compatible = "ti,tlv320aic3100"; #sound-dai-cells =<0>; reg = <0x18>; clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIO_BLK_CTRL_SAI3_MCLK1>; clock-names = "mclk1"; reset-gpios = <&gpio4 29 GPIO_ACTIVE_LOW>; HPVDD-supply = <®_audio_pwr>; SPRVDD-supply = <&vdd_input>; SPLVDD-supply = <&vdd_input>; AVDD-supply = <®_audio_pwr>; IOVDD-supply = <®_audio_pwr>; DVDD-supply = <®_audio_pwr_1v8>; }; }; &sai3 { #sound-dai-cells=<0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sai3>; assigned-clocks = <&clk IMX8MP_CLK_SAI3>; assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>; assigned-clock-rates = <12288000>; clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIO_BLK_CTRL_SAI3_IPG>, <&clk IMX8MP_CLK_DUMMY>, <&audio_blk_ctrl IMX8MP_CLK_AUDIO_BLK_CTRL_SAI3_MCLK1>, <&clk IMX8MP_CLK_DUMMY>, <&clk IMX8MP_CLK_DUMMY>; clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3"; fsl,sai-synchronous-rx; status = "okay"; }; &iomuxc { pinctrl_dac_rst: dacrstgrp { fsl,pins = < MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0x19 //DAC RST TODO >; }; pinctrl_sai3: sai3grp { fsl,pins = < MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_SYNC 0xd6 MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI3_TX_BCLK 0xd6 MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_SAI3_RX_DATA00 0xd6 MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI3_TX_DATA00 0xd6 MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SAI3_MCLK 0xd6 >; }; };
这似乎是我们得到某种解析错误的 DAI 链接。 我们收到 simple-card.c 驱动程序的 Di-links 解析错误。 我们已经修补了驱动程序以查看一些日志、似乎问题是基于此部分驱动程序:
static int __simple_for_each_link(struct asoc_simple_priv *priv, struct link_info *li, int (*func_noml)(struct asoc_simple_priv *priv, struct device_node *np, struct device_node *codec, struct link_info *li, bool is_top), int (*func_dpcm)(struct asoc_simple_priv *priv, struct device_node *np, struct device_node *codec, struct link_info *li, bool is_top)) { struct device *dev = simple_priv_to_dev(priv); struct device_node *top = dev->of_node; struct device_node *node; uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev); bool is_top = 0; int ret = 0; printk("Entering __simple_for_each_link\n"); /* Check if it has dai-link */ node = of_get_child_by_name(top, PREFIX "dai-link"); if (!node) { node = of_node_get(top); is_top = 1; printk("No Dai-Link?\n"); } /* loop for all dai-link */ do { struct asoc_simple_data adata; struct device_node *codec; struct device_node *plat; struct device_node *np; int num = of_get_child_count(node); printk("Inside do-while loop\n"); /* get codec */ codec = of_get_child_by_name(node, is_top ? PREFIX "codec" : "codec"); if (!codec) { ret = -ENODEV; goto error; } /* get platform */ plat = of_get_child_by_name(node, is_top ? PREFIX "plat" : "plat"); /* get convert-xxx property */ memset(&adata, 0, sizeof(adata)); for_each_child_of_node(node, np) simple_parse_convert(dev, np, &adata); /* loop for all CPU/Codec node */ for_each_child_of_node(node, np) { printk("Inside for_each_child_of_node loop\n"); if (plat == np) continue; /* * It is DPCM * if it has many CPUs, * or has convert-xxx property */ if (dpcm_selectable && (num > 2 || asoc_simple_is_convert_required(&adata))) { /* * np * |1(CPU)|0(Codec) li->cpu * CPU |Pass |return * Codec |return|Pass */ if (li->cpu != (np == codec)) ret = func_dpcm(priv, np, codec, li, is_top); /* else normal sound */ } else { /* * np * |1(CPU)|0(Codec) li->cpu * CPU |Pass |return * Codec |return|return */ if (li->cpu && (np != codec)) ret = func_noml(priv, np, codec, li, is_top); } if (ret < 0) { of_node_put(codec); of_node_put(plat); of_node_put(np); goto error; } } of_node_put(codec); node = of_get_next_child(top, node); } while (!is_top && node); error: of_node_put(node); printk("Exiting __simple_for_each_link with ret: %d\n", ret); return ret; }
我们已从内核配置中启用了该驱动程序:下面是带补丁驱动程序的引导日志:
imx8mp-lpddr4-evk login: [ 14.563842] probing for the TLV320AIC [ 14.567547] Entering __simple_for_each_link [ 14.571790] No Dai-Link? [ 14.574337] Inside do-while loop [ 14.577629] Inside for_each_child_of_node loop [ 14.582111] Inside for_each_child_of_node loop [ 14.586592] Exiting __simple_for_each_link with ret: 0 [ 14.591763] Entering __simple_for_each_link [ 14.595972] No Dai-Link? [ 14.598509] Inside do-while loop [ 14.601772] Inside for_each_child_of_node loop [ 14.606235] Inside for_each_child_of_node loop [ 14.610715] Exiting __simple_for_each_link with ret: 0 [ 14.615960] Entering __simple_for_each_link [ 14.620193] No Dai-Link? [ 14.622730] Inside do-while loop [ 14.625987] Inside for_each_child_of_node loop [ 14.630481] Exiting __simple_for_each_link with ret: -517 [ 14.635887] li->cpu val:1 ret val:-517 [ 14.639641] parsing error occured on dai links parsing link [ 14.645324] parse error: -517
使用 i2cdetect 命令时、我们可以看到填充了0x18区域、但当我们观察 i2c 总线时使用此命令时、无法看到0x18、我们会看到下面不是0x18的输出:
我们看不到 MCLK 的任何移动、并且我们的 SAI 接口被观察为从控制台延迟:
root@imx8mp-lpddr4-evk:~# cat /sys/kernel/debug/devices_deferred 30c30000.sai sound-bt-sco asoc-simple-card: parse error sound-tlv320aic31xx asoc-simple-card: parse error 30c20000.sai
接口和编解码器这两个节点似乎都是延迟的。 是接口或编解码器配置导致的问题。 我们如何调试该问题? 感谢您的任何想法! 提前感谢您!
此致!