This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TLV320AIC3100:Linux 启动了器件支持

Guru**** 1828310 points
Other Parts Discussed in Thread: TLV320AIC3100
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/audio-group/audio/f/audio-forum/1307005/tlv320aic3100-linux-bring-up-the-device-support

器件型号:TLV320AIC3100

我们正在尝试为具有 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 = <&reg_audio_pwr>;
                SPRVDD-supply = <&vdd_input>;
                SPLVDD-supply = <&vdd_input>;
                AVDD-supply = <&reg_audio_pwr>;
                IOVDD-supply = <&reg_audio_pwr>;
                DVDD-supply = <&reg_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	

接口和编解码器这两个节点似乎都是延迟的。 是接口或编解码器配置导致的问题。 我们如何调试该问题? 感谢您的任何想法! 提前感谢您!

此致!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    那么、您的意思是 i2c 通信仍然异常、正确吗?

    还有一点、请为我提供内核版本

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的答复、

    我使用以下命令检查了总线、得到了以下范围的结果、可以、但编解码器没有答案。 NXP 指出其 SAI 时钟仅在发送或接收数据时启用。 因此、如果 TI 编解码器需要 MCLK 来初始化器件、这可能就是问题所在。 我们的情况是这样吗? 提前感谢您!

    内核版本为6.1.55

    我认为有一个 i2c 连接、至少已探测 tlv320aic31xx.c i2c 驱动器器件。 但器件没有返回。 至少这是我们通过示波器观察到的情况。

    root@imx8mp-lpddr4-evk:~# i2cdump -y -f 4 0x18
    

    提前感谢您!

    此致。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    aic31xx 作为从设备运行则不需要 MCLK。

    请检查是否调用了 aic31xx 中的 CODEC_PROBE?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    不、它不被调用。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    DTS 有什么问题? 是否咨询平台供应商?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的,我也和他们分享了 DTS。 他们没有什么可补充的。 根据您提供的最新信息、我将再次咨询。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    tlv320aic31xx.txt«sound«bindings«devicetree«Documentation - kernel/git/Torvalds/linux.git - Linux 内核源码树

    请尝试关注

    simple-audio-card、name ="tlv320aic31xx";

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    没问题、使用 simple-audio 卡、name ="tlv320aic31xx";更改。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    另外、NXP 指出这是关于 TI 驱动程序集成、它们指出 DT 配置有效。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是 imx8上的成功案例。 希望这对新的一年有所帮助。

    (+) TLV320AIC3100:TLV320AIC3100 24MHz 驱动程序支持-音频论坛-音频- TI E2E 支持论坛