This Page describes Xilinx ALSA sound card driver based on ASoC framework. All the work is based on Linux kernel and design consists of ZYNQ+MPSoC, I2S, CDMA, FIFOMM2S IPs and video FMC codec audio chips.The I2S bus is used to transmit the audio data. ASoC audio driver architecture has the characteristics of high code re-usability and modular. The Page is also describes components of ASoC wiz. machine driver, codec driver and platform driver to achieve voice recording and playback functionality. This solution is tested using ALSA commands (arecord/aplay).

In the current Linux kernel, ALSA architecture has replaced OSS architecture and become the default schema of the audio driver module. ASoC architecture extends ALSA framework to support in embedded audio system.

Overview

Audio Sound card system has following components in hardware:
  • CPU(ZYNQ+MPSoC),
  • (Only for I2S)video FMC card (comprise of line-in and line out interface) - it is capable of receive/send audio data from PC to the speakers and vice-versa.
  • CDMA - enabled MEMORY-STREAM and STREAM-MEMORY modes
  • I2S/HDMI (supports Rx and Tx modes) and
  • FIFOMM2S(enabled both Rx FIFO and Tx FIFO modes).

Above hardware components enables audio data routing from Video FMC to memory and vice-versa.
Audio Sound card has following components in software:

ASoC Layers_.png


ASoC based driver is involved in a number of important structures, each of which is represented by the structure. ASoC components are as follows:
1. platform driver : Platform driver is only related to the SoC platform(it contains code for CDMA, FIFOMM2S and I2S/HDMI).(sound/soc/xilinx/xlnx_audioss.c)
2. codec driver : Codec driver is independent from platform and responsible for driving ADC/DAC. Since codec is not programmable in design so registered as Linux dummy codec (i.e sound/soc/soc-utils.c).
3. machine driver : Machine driver is responsible for the binding of codec driver and platform driver to finish audio information processing.(sound/soc/xilinx/xlnx_snd_card.c)

ASoC core layer of above diagram is a part of traditional ALSA Framework, which will do processing of audio data.

Design of Audio Driver

Audio driver is involved in a number of important structures.

Design of Machine Driver

The work of machine driver is to handle machine specific controls and audio events. In addition, it is also responsible for the coupling with platform driver and codec driver. Machine driver is responsible to register sound card with ASoC,(xlnx_snd_card.c).

Design of Codec Driver

This driver is using Linux default Codec Dummy driver. (i.e sound/soc/soc-utils.c).

Design of Platform Driver

Platform driver transmits audio data by DMA, and transmits to the codec by dai of CPU side. It has two important structures: snd_soc_platform_driver and snd_soc_dai_driver. The former is responsible for DMA data management, and the latter is responsible for the parameter configuration of dai.(xlnx_audioss.c and xlnx_iis.c).

Kernel Configurations:

CONFIG_SND_SOC=y
 

Device Tree Bindings:

        soft_audio_axi_fifo_mm_s_0: axi_fifo_mm_s@80030000 {
            compatible = "xlnx,axi-fifo-mm-s-4.1";
            interrupt-parent = <&gic>;
            interrupts = <0 92 4>;
            reg = <0x0 0x80030000 0x0 0x10000>;
            xlnx,axi-str-rxd-protocol = "XIL_AXI_STREAM_ETH_DATA";
            xlnx,axi-str-rxd-tdata-width = <0x20>;
            xlnx,axi-str-txc-protocol = "XIL_AXI_STREAM_ETH_CTRL";
            xlnx,axi-str-txc-tdata-width = <0x20>;
            xlnx,axi-str-txd-protocol = "XIL_AXI_STREAM_ETH_DATA";
            xlnx,axi-str-txd-tdata-width = <0x20>;
            xlnx,axis-tdest-width = <0x4>;
            xlnx,axis-tid-width = <0x4>;
            xlnx,axis-tuser-width = <0x4>;
            xlnx,data-interface-type = <0x1>;
            xlnx,has-axis-tdest = <0x0>;
            xlnx,has-axis-tid = <0x0>;
            xlnx,has-axis-tkeep = <0x0>;
            xlnx,has-axis-tstrb = <0x0>;
            xlnx,has-axis-tuser = <0x0>;
            xlnx,rx-fifo-depth = <0x1000>;
            xlnx,rx-fifo-pe-threshold = <0x32>;
            xlnx,rx-fifo-pf-threshold = <0x800>;
            xlnx,s-axi-id-width = <0x1>;
            xlnx,s-axi4-data-width = <0x20>;
            xlnx,select-xpm = <0x0>;
            xlnx,tx-fifo-depth = <0x1000>;
            xlnx,tx-fifo-pe-threshold = <0x32>;
            xlnx,tx-fifo-pf-threshold = <0x800>;
            xlnx,use-rx-cut-through = <0x0>;
            xlnx,use-rx-data = <0x1>;
            xlnx,use-tx-ctrl = <0x0>;
            xlnx,use-tx-cut-through = <0x0>;
            xlnx,use-tx-data = <0x1>;
        };
        audio_subsystem: xlnx_audio_ss {
            compatible = "xlnx,audio";
            fifo_gen = <&soft_audio_axi_fifo_mm_s_0>;
            i2srx_dma = <&axi_cdma_0>;
            i2stx_dma = <&axi_cdma_1>;
        };
        xlnx_snd_card: xlnx-audio {
             compatible = "xilnx,xlnx-audio";
        };

Related Links:


soft_audio_axi_fifo_mm_s_0: axi_fifo_mm_s@80030000 {

compatible = "xlnx,axi-fifo-mm-s-4.1";

interrupt-parent = <&gic>;

interrupts = <0 92 4>;

reg = <0x0 0x80030000 0x0 0x10000>;

xlnx,axi-str-rxd-protocol = "XIL_AXI_STREAM_ETH_DATA";

xlnx,axi-str-rxd-tdata-width = <0x20>;

xlnx,axi-str-txc-protocol = "XIL_AXI_STREAM_ETH_CTRL";

xlnx,axi-str-txc-tdata-width = <0x20>;

xlnx,axi-str-txd-protocol = "XIL_AXI_STREAM_ETH_DATA";

xlnx,axi-str-txd-tdata-width = <0x20>;

xlnx,axis-tdest-width = <0x4>;

xlnx,axis-tid-width = <0x4>;

xlnx,axis-tuser-width = <0x4>;

xlnx,data-interface-type = <0x1>;

xlnx,has-axis-tdest = <0x0>;

xlnx,has-axis-tid = <0x0>;

xlnx,has-axis-tkeep = <0x0>;

xlnx,has-axis-tstrb = <0x0>;

xlnx,has-axis-tuser = <0x0>;

xlnx,rx-fifo-depth = <0x1000>;

xlnx,rx-fifo-pe-threshold = <0x32>;

xlnx,rx-fifo-pf-threshold = <0x800>;

xlnx,s-axi-id-width = <0x1>;

xlnx,s-axi4-data-width = <0x20>;

xlnx,select-xpm = <0x0>;

xlnx,tx-fifo-depth = <0x1000>;

xlnx,tx-fifo-pe-threshold = <0x32>;

xlnx,tx-fifo-pf-threshold = <0x800>;

xlnx,use-rx-cut-through = <0x0>;

xlnx,use-rx-data = <0x1>;

xlnx,use-tx-ctrl = <0x0>;

xlnx,use-tx-cut-through = <0x0>;

xlnx,use-tx-data = <0x1>;

};