Проблема со звуком на плате IMX6 (кодек max98357a)

Я работаю над пользовательской платой на основе процессор IMX6 Solo и модуль TX6S-8035, пытаясь для воспроизведения звука с помощью кодека MAX98357a. Я просто начинаю понимать, как работает дерево устройств. Я реализую простую аудиокарту на ядре Linux 4.1.15 и использую следующие DTS, как это предлагается в i.MX6 и MA98357a с простой аудиокартой:

codec: max98357a@0 {
        compatible = "maxim,max98357a";
        #sound-dai-cells = <0>;
    };

    sound {
        compatible = "simple-audio-card";
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_ssi1>;
        simple-audio-card,name = "TI3 Audio";
        simple-audio-card,format = "i2s";
        simple-audio-card,widgets = "Speaker", "Speakers";
        simple-audio-card,routing = "Speakers", "Speaker";
        simple-audio-card,bitclock-master = <&cpu_dai>;
        simple-audio-card,frame-master = <&cpu_dai>;
        cpu_dai: simple-audio-card,cpu {
            sound-dai = <&ssi1>;
            system-clock-frequency = <883200>;
            dai-tdm-slot-num = <2>;
            dai-tdm-slot-width = <16>;
        };
        codec_dai: simple-audio-card,codec {
            sound-dai = <&codec>;
        };
    };



&audmux {
    status = "okay";
    // Note: 'ssi1' (node of first SSI) corresponds to '_SSI0' below.
    ssi1 {
         fsl,audmux-port = <MX31_AUDMUX_PORT1_SSI0>;
         fsl,port-config = <
               0x00000000
               IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT3_SSI_PINS_3)
               >;
           };


    aud3 {
      fsl,audmux-port = <MX31_AUDMUX_PORT3_SSI_PINS_3>;
      fsl,port-config = <
          (IMX_AUDMUX_V2_PTCR_TFSDIR |
          IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT1_SSI0) |
          IMX_AUDMUX_V2_PTCR_TCLKDIR |
          IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT1_SSI0))
          IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0)
          >;
     };
};


&ssi1 {
      fsl,mode = "i2s-master";
      assigned-clocks = <&clks IMX6QDL_CLK_SSI1_SEL>, <&clks IMX6QDL_CLK_SSI1>;
      assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
      assigned-clock-rates = <0>, <49152000>; // 48kHz on SSI1 clock
      status = "okay";    
};

Кодек MAX98357a подключен к SSI1. Звуковая карта определяется ALSA. Но когда я пытаюсь воспроизвести аудиофайл, на динамик ничего не выходит, и на контакте SSI1 нет сигнала I2S. Есть ли у кого-нибудь идеи по этому вопросу. Спасибо. С наилучшими пожеланиями!


person vlad zouth    schedule 24.10.2018    source источник
comment
Я решаю свою проблему, рассматривая сопоставление audmux с SSI. SS1 подключен в моем случае к audmux5. Итак, вот новая реализация: aud5 { fsl,audmux-port = <MX31_AUDMUX_PORT5_SSI_PINS_5>; fsl,port-config = < (IMX_AUDMUX_V2_PTCR_TFSDIR | IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT1_SSI0) | IMX_AUDMUX_V2_PTCR_TCLKDIR | IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT1_SSI0)) IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0) >; };   -  person vlad zouth    schedule 26.10.2018
comment
Привет, не могли бы вы опубликовать свой полный dts? Либо прямо здесь, например, с помощью pastbin, либо через прямое сообщение? Большое спасибо   -  person YCN-    schedule 21.01.2019
comment
здесь там: pastebin.com/khvqXXDn pastebin.com/MkbQnquL pastebin.com/tMXKpUar pastebin.com/KeksHv7B   -  person vlad zouth    schedule 25.01.2019
comment
Большое спасибо ! Я уже решил свою проблему, но это очень поможет в дальнейшем :)   -  person YCN-    schedule 28.01.2019


Ответы (1)


У меня возникли проблемы с тем, чтобы звуковая карта (кодек MA98357a с простой звуковой картой) работала с последней версией imx6q (i.MX 6 Quad), поэтому я делюсь здесь своим решением:

  • CONFIG_SND_SOC_MAX98357A должен быть включен (связан с совместимым "maxim,max98357a"). Но по умолчанию эту опцию нельзя выбрать под make menuconfig. Связанный Kconfig (sound/soc/codecs/Kconfig) должен быть исправлен. Заменять:
config SND_SOC_MAX98357A
    tristate

By:

config SND_SOC_MAX98357A
    tristate "Maxim MAX98357A CODEC"
  • CONFIG_SND_SIMPLE_CARD должен быть включен (связан с совместимым "simple-audio-card")

  • Примените/Объедините/Cherry-выберите следующий патч, если он еще не был применен: Идентификатор фиксации в мастере: 3ff86050da41e072dd9fffc373c4f5691573cf4e: clk: imx6q: disable non functional divider. Мне пришлось объединить его вручную, так как я использую старую версию ядра 4.19.134.

  • Напишите .dts для этой звуковой карты:

    • Configure audmux, in my case the pins (TXD, CLK, FS) are connected to AUD5 pins. The first SSI (ssi1) is used. This SSI is going to generate the bit clock (CLK) and provide it to the max98357a audio card.
    • Настройте iomux: контакты AUD5 должны быть настроены в правильном режиме.
    • Настройте ssi1 и соответствующие часы. Лучшими часами для этого являются PLL4, которые являются единственными часами, которые позволяют генерировать ровно 48 кГц.
    • Добавьте карты codec и sound

Ниже выдержка из .dts:

/dts-v1/;
#include <dt-bindings/sound/fsl-imx-audmux.h>
#include "imx6q.dtsi"
#include "imx6qdl-phytec-phycore-som.dtsi"

/ {
    codec: max98357a@0 {
        compatible = "maxim,max98357a";
        #sound-dai-cells = <0>;
    };

    sound {
        compatible = "simple-audio-card";
        simple-audio-card,name = "max98357a";
        simple-audio-card,format = "i2s";
        simple-audio-card,widgets = "Speaker", "Speakers";
        simple-audio-card,routing = "Speakers", "Speaker";
        simple-audio-card,bitclock-master = <&cpu_dai>;
        simple-audio-card,frame-master = <&cpu_dai>;
        cpu_dai: simple-audio-card,cpu {
            sound-dai = <&ssi1>;
            dai-tdm-slot-num = <2>;
            dai-tdm-slot-width = <16>;
        };
        codec_dai: simple-audio-card,codec {
            sound-dai = <&codec>;
            clocks = <&clks IMX6QDL_CLK_SSI1>;
        };
    };
};

&audmux {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_audmux>;
    status = "okay";

    ssi1 {
        fsl,audmux-port = <MX31_AUDMUX_PORT1_SSI0>;
        fsl,port-config = <
            0x00000000
            IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5)
            >;
    };

    aud5 {
        fsl,audmux-port = <MX31_AUDMUX_PORT5_SSI_PINS_5>;
        fsl,port-config = <
            (IMX_AUDMUX_V2_PTCR_TFSDIR |
             IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT1_SSI0) |
             IMX_AUDMUX_V2_PTCR_TCLKDIR |
             IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT1_SSI0))
             IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0)
             >;
    };
};

/* The clock tree used to generate the SSI1 bit clock (See IMX6DQRM reference manual):
 *  pll4                                    -- 24e6 * (DIV_SELECT + NUM/DENOM)
 *    pll4_bypass                           -- Bypass PLL4: CCM_ANALOG_PLL_AUDIO[BYPASS]
 *      pll4_audio                          -- Enable PLL4: CCM_ANALOG_PLL_AUDIO[ENABLE]
 *        pll4_post_div                     -- Divide PLL4: CCM_ANALOG_PLL_AUDIO[POST_DIV_SELECT]
 *          pll4_audio_div                  -- Reserved: Fixed factor of x1
 *            ssi1_sel                      -- Clock multiplexer
 *              ssi1_pred                   -- Divide SSI1: CS1CDR[SSI1_CLK_PRED]
 *                ssi1_podf                 -- Divide SSI1: CS1CDR[SSI1_CLK_PODF]
 *                  ssi1 (SSI1_CLK_ROOT)    -- Clock gate: CCM_CCGR5[CG9]
 *                    ssi1 (Int. bit clock) -- Divide SSI1: STCCR[DIV2, PSR, PM] (See formula below)
 *
 * With the following constraint:
 *  - (DIV_SELECT + NUM/DENOM): Must be between 27 and 54: PLL4 clock between 650 and 1300 MHz
 *  - DENOM = 24e6: As implemented in clk_pllv3_av_set_rate()
 *  - POST_DIV_SELECT: Can divide by [1; 2; 4]
 *  - SSI1_CLK_PRED: Can divide by [1, 8]
 *  - SSI1_CLK_PODF: Can divide by [1, 64]
 *  - DIV2 and PSR = 0: As implemented in fsl_ssi_set_bclk()
 *  - PM > 0: Since DIV2, PSR and PM should not be all set to zero at the same time.
 *  - SSI bit clock = SSI1_CLK_ROOT / ((DIV2 + 1) * (7 * PSR + 1) * (PM + 1) * 2)
 *
 * SSI bit clock needs to be equal to 3072000 Hz (for 2 channels/stereo, 48kHz) since:
 *  - For 2 channels, slot width is fixed to 32 bits since in I2S Master mode, and STCCR[WL] are
 *    used to control the amount of valid data in those 32 bits.
 *  - 2 slots are used, one for each channel. The slot number (STCCR[DC]) is fixed to 2.
 *  => SSI bit clock = 48000 * 32 * 2 = 3072000
 *
 * SSI bit clock needs to be equal to 1536000 Hz (for 1 channel/mono, 48kHz) since:
 *  - Slot width is set to 16 bits, in I2S Normal mode.
 *  - 2 slots are used (fixed to 2), and data are only provided in first slot
 *  => SSI bit clock = 48000 * 16 * 2 = 1536000
 *
 * So SSI1_CLK_ROOT frequency needs to be equal to: 3072000 * (PM + 1) * 2 = 6144000 * (PM + 1)
 *
 * The following configuration is applied:
 *  - SSI1_SEL parent clock is configured to be PLL4_AUDIO_DIV
 *  - SSI1_SEL clock is automatically configured
 *  - PLL4 clock is set to 663.552 MHz, which is a multiple of 6144000 Hz (x 108).
 *    The PLL4 must be configured in the DTS otherwise Linux keeps the default/reset values, which
 *    are invalid. /sys/kernel/debug/clk/clk_summary report 147456000 Hz but the generated clock
 *    is not at this frequency.
 *  - SSI1_CLK_ROOT is set to 18.432 MHz. (18.432 * 36 = 663.552 MHz)
 *  - STCCR[PM] will be automatically set to 2. (18.432 / (2 + 1) / 2 = 3.072 MHz)
 */
&ssi1 {
    fsl,mode = "i2s-master";
    assigned-clocks = <&clks IMX6QDL_CLK_SSI1_SEL>, <&clks IMX6QDL_CLK_PLL4>, <&clks IMX6QDL_CLK_SSI1>;
    assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
    assigned-clock-rates = <0>, <663552000>, <18432000>;
    status = "okay";
};

/* For iomuxc, pin configuration (pad setting value):
 *  - Bit 0: Slew rate: 1 = fast, 0 = slow
 *  - Bit 3-5: Drive Strength: 0 = HI-Z, 1 = 260 Ohm, 2 = 130 Ohm, 3 = 90 Ohm, 4 = 60 Ohm, 5 = 50 Ohm, 6 = 40 Ohm, 7 = 33 Ohm
 *  - Bit 6-7: Speed: 0 = Low, 1 and 2 = Medium, 3 = Maximum
 *  - Bit 11: Open drain: 0 = Disabled, 1 = Enabled
 *  - Bit 12: Pull / Keep Enable: 0 = Disabled, 1 = Enabled
 *  - Bit 13: Pull / Keep Select: 0 = Keep, 1 = Pull
 *  - Bit 14-15: Pull Up / Down config: 0 = 100K Down, 1 = 47K Up, 2 = 100K Up, 3 = 22K Up
 *  - Bit 16: Hysteresis Enable: 0 = Disabled, 1 = Enabled
 *  - Bit 30: SION: Software Input On Field.
 *  - Bit 31: NO_PAD_CTL: indicate this pin does not need config.
 *
 * See fsl,imx-pinctrl.txt, fsl,imx6q-pinctrl.txt, and pinctrl-bindings.txt
 * See also https://www.nxp.com/docs/en/application-note/AN5078.pdf
 */
&iomuxc {
    pinctrl_audmux: audmuxgrp {
        fsl,pins = <
            MX6QDL_PAD_KEY_ROW0__AUD5_TXD      0x110b0  /* AUDIO: DIN, D56, X_AUD5_TXD, SSI1_TXD */
            MX6QDL_PAD_KEY_COL0__AUD5_TXC      0x130b0  /* AUDIO: BCLK, D53, X_AUD5_TXC, SSI1_CLK */
            MX6QDL_PAD_KEY_COL1__AUD5_TXFS     0x130b0  /* AUDIO: LRCLK, D54, X_AUD5_TXFS, SSI1_FS */
        >;
    };
};
person benjarobin    schedule 10.08.2020
comment
Очень полезный и подробный ответ. - person Bayou; 03.02.2021