linux alsa asoc summary

1. Introduction

In the absence of computers, such as the radio that was heard when young, it received electromagnetic waves and demodulated the modulated sound signals. The sound signal was converted to analog electrical signals, and amplified by a suitable amplifying circuit, it could be sent directly to the headset or loudspeaker.

The following is the waveform diagram of a sound, which is a visual display of the analog electrical signal converted from the sound signal. The horizontal axis represents the time, and the vertical axis represents the loudness of the sound (proportional to the current, for example)

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-mm7j9Q5V-1632820540464)(audio.assets/image-20210913113425764.png)]

Later, in the digital age, our concept of sound became audio files.

So, what's the difference between using the radio to listen to crosstalk and using the development board to directly play audio files to listen to crosstalk?

Listening to the radio is an analog signal to the audio playback device

Playing audio files directly with the development board is to convert digital signals into analog signals, and finally give them to the audio playback equipment

The conversion process between digital signal and analog signal is added.

The so-called digital signal here is the digital representation of the analog signal, which converts the analog signal into binary data that can be stored by the computer.

So, how to convert?

2. Digitization of sound signal

As shown in the figure below, use a sampling signal with a higher frequency than the source sound to quantify the source sound and record the value of each sampling point. Finally, if the values of all sampling points are connected, they are consistent with the source sound curve, but not continuous.

As shown in the figure below:

  1. The distance between the two blue dotted lines is the period of the sampling signal, that is, it corresponds to a sampling frequency (FS). It can be imagined that the higher the sampling frequency, the better the final result is consistent with the source sound.

  2. The length of each blue dotted line determines the quantization value of the source sound at that time. The quantization value has another concept linked to it, that is, the quantization bits. Quantized bits represent the number of bits used at each sampling point to represent the data range, usually 16bit, 24bit or 32bit. The higher the bits, the better the sound quality and the larger the amount of data.

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-XOu4GIdP-1632820540469)(audio.assets/45416a2ead90c50a803ef6ab8e89c8b1.png)]

Thus, it can be obtained that,

Sampling frequency: the number of sound wave amplitude samples per second. The higher the sampling frequency, the better the sound quality and the greater the amount of data. Common sampling frequencies include 11.025KHz, 22.05KHz, 44.1KHz, 48KHz, 96KHz, etc.

Quantized bits: how many binary bits are used to represent the data range at each sampling point. Quantization bits are also called sampling bits. The more quantized bits, the better the sound quality and the larger the amount of data. The commonly used sampling bits are 8 bits, 16 bits, 24 bits, 32 bits, etc.

In addition, there is a concept of sound channel,

Number of channels: the number of channels used. Stereo is more expressive than mono, but the amount of data is doubled. The commonly used channel numbers are mono and stereo (left channel and right channel).

Storing the digitized binary data is the original sound data. There are many file formats for storing sound data, such as WAV, mp3, etc. wav generally stores the original sound data, which can be played directly by hardware, while mp3 stores the encoded and compressed sound data, which can be played only after decoding.

Next, let's introduce the wav file format.

3. Audio file storage format WAV

WAV files follow RIFF rules, and their contents are stored in chunks as the minimum unit. WAV files are generally composed of three blocks: RIFF chunk, Format chunk and Data chunk.

It can be seen from the above that the audio file is actually a storage form of digitized binary data of analog electrical signal after sound signal conversion.

Suppose a sound file is stored on nand. When playing, the main control chip reads the sound data from nand to ddr under the control of the upper application, reads the sound data from ddr to the internal fifo of aic(Audio Interface Controller) under the control of the driver, and finally sends it to codec through external wiring.

In this way, the sound data is transmitted to the external codec chip, converted into analog electrical signals after digital to analog conversion, and finally sent to the audio playback device for playback.

Here is an introduction to codec

Codec, i.e. codec, here we refer to audio codec chip, which generally includes a DAC (Digital - > analog signal conversion) and an ADC (Analog - > digital signal conversion), which can convert between analog signals and digital signals.

The protocol of data transmission between master control and codec is generally i2s protocol.

4. I2S bus protocol

4.1 I2S bus overview

I2S (inter IC sound) bus, also known as integrated circuit built-in audio bus, is a bus standard formulated by Philips semiconductor (now NXP semiconductor) for audio data transmission between digital audio devices.

The bus is specially used for data transmission between audio devices and is widely used in various multimedia systems.

It adopts the design of independent wire transmission clock and data signal. By separating the data and clock signal, it avoids the distortion caused by time difference and saves the cost of purchasing professional equipment to resist audio jitter for users.

4.2 I2S signal line

I2S bus mainly has three signal lines:

  • Serial clock SCK

    Serial clock SCK, also known as bit clock BCLK, has one pulse for each bit of data corresponding to digital audio. Frequency of SCK = number of channels * sampling frequency * sampling bits.

  • Field selection signal WS

    The field selection signal WS, also known as LRCLK, is used to switch the data of left and right channels. Frequency of WS = sampling frequency.

    The field selection signal WS indicates the channel being transmitted.

    The level meaning of I2S Philips standard WS signal is as follows:

    WS is 0, indicating that the data of the left channel is being transmitted;

    WS is 1, which means that the data of the right channel is being transmitted.

  • Serial DATA

    Serial DATA is the audio DATA expressed in binary. I2S serial DATA is transmitted from high order (MSB) to low order (LSB).

  • Master clock MCLK

    Generally, MCLK, the master clock, provides the clock to codec.

4.3 several common I2S data formats

With the development of technology, under the unified I2S hardware interface, there are many different I2S data formats, which can be divided into left aligned (MSB) standard, right aligned (LSB) standard and I2S Philips standard.

For all data formats and communication standards, the most significant bit (MSB first) is always sent first.

The sending end and receiving end must use the same data format to ensure that the data sent and received are consistent.

4.3.1 I2S Philips standard

The LRCLK signal is used to indicate the channel to which the data currently being transmitted belongs. When it is 0, it indicates the left channel data. The LRCLK signal is valid from a clock before the first bit (MSB) of the current channel data. The LRCLK signal changes at the falling edge of BCLK. The sender changes the data on the falling edge of the clock signal BCLK, and the receiver reads the data on the rising edge of the clock signal BCLK. As mentioned above, the LRCLK frequency is equal to the sampling frequency FS, and one LRCLK cycle (1/Fs) includes transmitting left channel and right channel data.

For this standard I2S format signal, no matter how many bits of valid data there are, the highest bit of the data always appears at the second BCLK pulse after the LRCLK change (i.e. the beginning of a frame). This makes the significant bits of the receiving end and the transmitting end different. If the number of significant bits that can be processed by the receiving end is less than that of the transmitting end, the redundant low-order data in the data frame can be discarded; If the receiver can process more significant bits than the sender, it can make up the remaining bits by itself. This synchronization mechanism makes the interconnection of digital audio devices more convenient, and will not cause data dislocation.

I2S Philips standard timing diagram is as follows:

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-Jql8Lggo-1632820540473)(audio.assets/a2408454b51d1434455d5d3cafa8acfb.png)]

4.3.2 left aligned (MSB) standard

Data transmission starts at the same time that the LRCLK flips. This standard is rarely used. Note that when LRCLK is 1, the left channel data is transmitted, which is just opposite to the I2S Philips standard.

The standard timing diagram of left aligned (MSB) is as follows:

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-yfa5l1yq-1632820540478) (audio. Assets / 3a1385d382db5d07533c3d75091070e. PNG)]

4.3.3 right alignment (LSB) standard

When the sound data LSB transmission is completed, the LRCLK completes the second flip (just because the LSB and LRCLK are right aligned, so it is called the right alignment standard). Note that when LRCLK is 1, the left channel data is transmitted, which is just opposite to the I2S Philips standard.

The standard timing diagram of right alignment (LSB) is as follows:

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-aekt0cqs-1632820540480) (audio. Assets / 52f6c8606e7f9fa109dfaf0f728f70. PNG)]

5. ASoC drive frame

5.1 origin of ASoC

ASoC – ALSA System on Chip is a software system built on the standard ALSA driver layer to better support audio Codec in embedded processors and mobile devices.

Before the advent of ASoc, the kernel had some support for audio in SoC, but there were some limitations:

  1. The Codec driver is too tightly coupled with the underlying SoC CPU, which will lead to code duplication. For example, it is only the driver of wm8731. At that time, there were driver codes for four platforms in Linux.

  2. There is no standard method to notify users of audio events, such as plug-in and detection of headphones and microphones. These events are very common in mobile devices, and usually require machine specific code to reconfigure the audio path.

  3. When playing or recording, the driver will power up the entire codec, which is no problem for the PC, but for mobile devices, it means wasting a lot of power. At the same time, it is not supported to save power by changing oversampling frequency and bias current.

    ...

ASoC is proposed to solve the above problems. At present, it has been integrated into the code tree of the kernel: sound/soc. ASoC cannot exist alone. It is based on the standard ALSA driver and must be consistent with the standard

ALSA drives the framework to work.

ASoC abstracts the audio system of embedded devices into three parts:

  1. Machine

  2. Platform

  3. Codec

5.2 machine

Machine refers to a machine, which can be a device, a development board, or a smartphone. It can be seen that machine is almost non reusable, and the hardware implementation on each machine may be different

Different, different CPUs, different codecs, and different audio input and output devices. Machine provides a carrier for CPU, Codec, and input and output devices.

The separate Platform and Codec driver cannot work. It must be combined by the Machine driver to complete the audio processing of the whole device.

5.2.1 registration function

/**
 * snd_soc_register_card - Register a card with the ASoC core
 *
 * @card: Card to register
 *
 */
int snd_soc_register_card(struct snd_soc_card *card)

5.2.2 core structure

Abstraction of sound card

/* SoC card */
struct snd_soc_card {
	......
	/* CPU <--> Codec DAI links  */
	struct snd_soc_dai_link *dai_link;
	int num_links;
	......
};

Describe which platform and codec are used in the board level

Platform, Codec, Codec are specified_ dai,cpu_ The name of Dai. Later, the Machine driver will use these names to match the platform already registered in the system,

Codec and dai are registered in the corresponding Platform driver and codec driver.

struct snd_soc_dai_link {
	/* config - must be set by machine driver */
	const char *name;			/* Codec name */
	const char *stream_name;		/* Stream name */
	/*
	 * You MAY specify the link's CPU-side device, either by device name,
	 * or by DT/OF node, but not both. If this information is omitted,
	 * the CPU-side DAI is matched using .cpu_dai_name only, which hence
	 * must be globally unique. These fields are currently typically used
	 * only for codec to codec links, or systems using device tree.
	 */
	const char *cpu_name;
	struct device_node *cpu_of_node;
	/*
	 * You MAY specify the DAI name of the CPU DAI. If this information is
	 * omitted, the CPU-side DAI is matched using .cpu_name/.cpu_of_node
	 * only, which only works well when that device exposes a single DAI.
	 */
	const char *cpu_dai_name;
	/*
	 * You MUST specify the link's codec, either by device name, or by
	 * DT/OF node, but not both.
	 */
	const char *codec_name;
	struct device_node *codec_of_node;
	/* You MUST specify the DAI name within the codec */
	const char *codec_dai_name;

	struct snd_soc_dai_link_component *codecs;
	unsigned int num_codecs;

	/*
	 * You MAY specify the link's platform/PCM/DMA driver, either by
	 * device name, or by DT/OF node, but not both. Some forms of link
	 * do not need a platform.
	 */
	const char *platform_name;
	struct device_node *platform_of_node;

    ......
    
	/* machine stream operations */
	const struct snd_soc_ops *ops;

    ......
};

Only HW is implemented in the panda board_ Params function is mainly used to set protocol format, clock frequency, clock division, etc.

/* SoC audio ops */
struct snd_soc_ops {
	int (*startup)(struct snd_pcm_substream *);
	void (*shutdown)(struct snd_pcm_substream *);
	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
	int (*hw_free)(struct snd_pcm_substream *);
	int (*prepare)(struct snd_pcm_substream *);
	int (*trigger)(struct snd_pcm_substream *, int);
};

5.3 platform

Platform generally refers to a SoC platform, which usually includes the clock, DMA, I2S, PCM, etc. related to audio in the SOC. As long as the SOC is specified, we can think that it will have a corresponding platform

Platform, which is only related to SoC and has nothing to do with Machine, so we can abstract the platform so that the same SoC can be used in different machines without making any changes.

In fact, it is better to think of the Platform as a SoC.

The Platform driver contains the configuration and control of the audio DMA channel and audio interface (i2s, pcm, spdif, etc.) of the SoC Platform, and cannot contain any board or machine related code.

5.3.1 I2S

1. Register function

int snd_soc_register_component(struct device *dev,
			       const struct snd_soc_component_driver *cmpnt_drv,
			       struct snd_soc_dai_driver *dai_drv,
			       int num_dai)

2. Core structure

Describe the digital audio interface. The main functions to be implemented are initialization function, power management function and operation function set

/*
 * Digital Audio Interface Driver.
 *
 * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
 * operations and capabilities. Codec and platform drivers will register this
 * structure for every DAI they have.
 *
 * This structure covers the clocking, formating and ALSA operations for each
 * interface.
 */
struct snd_soc_dai_driver {
	/* DAI description */
	const char *name;
	unsigned int id;
	unsigned int base;

	/* DAI driver callbacks */
	int (*probe)(struct snd_soc_dai *dai);
	int (*remove)(struct snd_soc_dai *dai);
	int (*suspend)(struct snd_soc_dai *dai);
	int (*resume)(struct snd_soc_dai *dai);

	/* ops */
	const struct snd_soc_dai_ops *ops;
	......
};

Operation function set, including clock configuration, format configuration, data flow operation configuration, etc. of the interface, which is mainly manifested in configuring various registers of aic controller according to the function of callback function

struct snd_soc_dai_ops {
	/*
	 * DAI clocking configuration, all optional.
	 * Called by soc_card drivers, normally in their hw_params.
	 */
	int (*set_sysclk)(struct snd_soc_dai *dai,
		int clk_id, unsigned int freq, int dir);
	int (*set_pll)(struct snd_soc_dai *dai, int pll_id, int source,
		unsigned int freq_in, unsigned int freq_out);
	int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);

    /*
	 * DAI format configuration
	 * Called by soc_card drivers, normally in their hw_params.
	 */
	int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);

    ......

	/*
	 * ALSA PCM audio operations - all optional.
	 * Called by soc-core during audio PCM operations.
	 */
	int (*startup)(struct snd_pcm_substream *,
		struct snd_soc_dai *);
	void (*shutdown)(struct snd_pcm_substream *,
		struct snd_soc_dai *);
	int (*hw_params)(struct snd_pcm_substream *,
		struct snd_pcm_hw_params *, struct snd_soc_dai *);
	int (*hw_free)(struct snd_pcm_substream *,
		struct snd_soc_dai *);
	int (*prepare)(struct snd_pcm_substream *,
		struct snd_soc_dai *);
	/*
	 * NOTE: Commands passed to the trigger function are not necessarily
	 * compatible with the current state of the dai. For example this
	 * sequence of commands is possible: START STOP STOP.
	 * So do not unconditionally use refcounting functions in the trigger
	 * function, e.g. clk_enable/disable.
	 */
	int (*trigger)(struct snd_pcm_substream *, int,
		struct snd_soc_dai *);
	......
};

5.3.2 DMA

1. Register function

/**
 * snd_soc_add_platform - Add a platform to the ASoC core
 * @dev: The parent device for the platform
 * @platform: The platform to add
 * @platform_drv: The driver for the platform
 */
int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
		const struct snd_soc_platform_driver *platform_drv)

2. Core structure

The following callback functions need to be implemented

pcm_ Allocate dma space in New

pcm_ Release in free

/* SoC platform interface */
struct snd_soc_platform_driver {
	......
        
	/* pcm creation and destruction */
	int (*pcm_new)(struct snd_soc_pcm_runtime *);
	void (*pcm_free)(struct snd_pcm *);

	......

	/* platform stream pcm ops */
	const struct snd_pcm_ops *ops;

	......
};

The dma operation function set initializes dma, configures dma, starts dma, releases dma in the necessary callback functions according to the functions. In x1600, it mainly uses the DMA engine framework of the kernel to operate the pdma controller.

struct snd_pcm_ops {
	int (*open)(struct snd_pcm_substream *substream);
	int (*close)(struct snd_pcm_substream *substream);
	int (*ioctl)(struct snd_pcm_substream * substream,
		     unsigned int cmd, void *arg);
	int (*hw_params)(struct snd_pcm_substream *substream,
			 struct snd_pcm_hw_params *params);
	int (*hw_free)(struct snd_pcm_substream *substream);
	int (*prepare)(struct snd_pcm_substream *substream);
	int (*trigger)(struct snd_pcm_substream *substream, int cmd);
	snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);

    ......
};

5.4 codec

Codec is the codec. Codec contains I2S interface, D/A, A/D, Mixer and PA (power amplifier). It usually contains a variety of inputs (Mic, line in, I2S and PCM) and multiple outputs (headphones, speakers and listeners)

Like the Platform, Codec is a reusable component. The same Codec can be used by different machines. Embedded Codec usually controls the internal registers through I2C.

An important design principle in ASoC is that Codec driver is platform independent. It includes some audio Controls, audio interface and DAMP (dynamic audio power management)

Define and some Codec IO functions. In order to ensure hardware independence, any Platform and Machine specific code should be moved to Platform and Machine drivers.

5.4.1 registration function

/**
 * snd_soc_register_codec - Register a codec with the ASoC core
 *
 * @dev: The parent device for this codec
 * @codec_drv: Codec driver
 * @dai_drv: The associated DAI driver
 * @num_dai: Number of DAIs
 */
int snd_soc_register_codec(struct device *dev,
			   const struct snd_soc_codec_driver *codec_drv,
			   struct snd_soc_dai_driver *dai_drv,
			   int num_dai)

5.4.2 core structure

It mainly includes initialization function, power management function, audio control description structure, power management control, clock operation function, register read-write function, etc.

/* codec driver */
struct snd_soc_codec_driver {

	/* driver ops */
	int (*probe)(struct snd_soc_codec *);
	int (*remove)(struct snd_soc_codec *);
	int (*suspend)(struct snd_soc_codec *);
	int (*resume)(struct snd_soc_codec *);
	struct snd_soc_component_driver component_driver;

	/* Default control and setup, added after probe() is run */
	const struct snd_kcontrol_new *controls;
	int num_controls;
	const struct snd_soc_dapm_widget *dapm_widgets;
	int num_dapm_widgets;
	const struct snd_soc_dapm_route *dapm_routes;
	int num_dapm_routes;

	/* codec wide operations */
	int (*set_sysclk)(struct snd_soc_codec *codec,
			  int clk_id, int source, unsigned int freq, int dir);
	int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source,
		unsigned int freq_in, unsigned int freq_out);

	/* codec IO */
	struct regmap *(*get_regmap)(struct device *);
	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
	unsigned int reg_cache_size;
	short reg_cache_step;
	short reg_word_size;
	const void *reg_cache_default;

	/* codec bias level */
	int (*set_bias_level)(struct snd_soc_codec *,
			      enum snd_soc_bias_level level);
	bool idle_bias_off;
	bool suspend_bias_off;

	void (*seq_notifier)(struct snd_soc_dapm_context *,
			     enum snd_soc_dapm_type, int);

	bool ignore_pmdown_time;  /* Doesn't benefit from pmdown delay */
};

Describe the digital audio interface, the same as i2s

/*
 * Digital Audio Interface Driver.
 *
 * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
 * operations and capabilities. Codec and platform drivers will register this
 * structure for every DAI they have.
 *
 * This structure covers the clocking, formating and ALSA operations for each
 * interface.
 */
struct snd_soc_dai_driver {
	/* DAI description */
	const char *name;
	unsigned int id;
	unsigned int base;

	/* DAI driver callbacks */
	int (*probe)(struct snd_soc_dai *dai);
	int (*remove)(struct snd_soc_dai *dai);
	int (*suspend)(struct snd_soc_dai *dai);
	int (*resume)(struct snd_soc_dai *dai);

    ......

	/* ops */
	const struct snd_soc_dai_ops *ops;

	/* DAI capabilities */
	struct snd_soc_pcm_stream capture;
	struct snd_soc_pcm_stream playback;

    ......
};

Operation function set, including clock configuration, format configuration, data flow operation configuration, etc. of the interface, which is mainly manifested in configuring various registers in codec according to the function of callback function

struct snd_soc_dai_ops {
	/*
	 * DAI clocking configuration, all optional.
	 * Called by soc_card drivers, normally in their hw_params.
	 */
	int (*set_sysclk)(struct snd_soc_dai *dai,
		int clk_id, unsigned int freq, int dir);
	int (*set_pll)(struct snd_soc_dai *dai, int pll_id, int source,
		unsigned int freq_in, unsigned int freq_out);
	int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);

    /*
	 * DAI format configuration
	 * Called by soc_card drivers, normally in their hw_params.
	 */
	int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);

    ......

	/*
	 * ALSA PCM audio operations - all optional.
	 * Called by soc-core during audio PCM operations.
	 */
	int (*startup)(struct snd_pcm_substream *,
		struct snd_soc_dai *);
	void (*shutdown)(struct snd_pcm_substream *,
		struct snd_soc_dai *);
	int (*hw_params)(struct snd_pcm_substream *,
		struct snd_pcm_hw_params *, struct snd_soc_dai *);
	int (*hw_free)(struct snd_pcm_substream *,
		struct snd_soc_dai *);
	int (*prepare)(struct snd_pcm_substream *,
		struct snd_soc_dai *);
	/*
	 * NOTE: Commands passed to the trigger function are not necessarily
	 * compatible with the current state of the dai. For example this
	 * sequence of commands is possible: START STOP STOP.
	 * So do not unconditionally use refcounting functions in the trigger
	 * function, e.g. clk_enable/disable.
	 */
	int (*trigger)(struct snd_pcm_substream *, int,
		struct snd_soc_dai *);

    ......
};

5.5 summary

ASoC is an extension based on ALSA driver framework. ALSA driver is essentially a character device driver. As long as it is a character device driver, it will have open, close, ioctl and other interfaces to communicate with the upper application.

The most important one is ioctl, which calls different ops callback functions according to different parameters.

6. Upper layer application

Use the strace command to track the system call when executing the aplay Windows.wav command. The part is as follows:

execve("/usr/bin/aplay", ["aplay", "Windows.wav"], [/* 7 vars */]) = 0
brk(0)                                  = 0x20000
uname({sys="Linux", node="192.168.1.17", ...}) = 0
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = -1 ENOENT (No such file or directory)
open("/lib/tls/v4l/half/librt.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v4l/half", 0xbef92460) = -1 ENOENT (No such file or directory)
open("/lib/tls/v4l/librt.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/v4l", 0xbef92460)      = -1 ENOENT (No such file or directory)
open("/lib/tls/half/librt.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/tls/half", 0xbef92460)     = -1 ENOENT (No such file or directory)
open("/lib/tls/librt.so.1", O_RDONLY)   = -1 ENOENT (No such file or directory)
stat64("/lib/tls", 0xbef92460)          = -1 ENOENT (No such file or directory)
open("/lib/v4l/half/librt.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
stat64("/lib/v4l/half", 0xbef92460)     = -1 ENOENT (No such file or directory)
open("/lib/v4l/librt.so.1", O_RDONLY)   = -1 ENOENT (No such file or directory)
stat64("/lib/v4l", 0xbef92460)          = -1 ENOENT (No such file or directory)
open("/lib/half/librt.so.1", O_RDONLY)  = -1 ENOENT (No such file or directory)
stat64("/lib/half", 0xbef92460)         = -1 ENOENT (No such file or directory)
open("/lib/librt.so.1", O_RDONLY)       = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\240\26\0\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=40807, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f31000
mmap2(NULL, 57872, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6eff000
mprotect(0xb6f05000, 28672, PROT_NONE)  = 0
mmap2(0xb6f0c000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5000) = 0xb6f0c000
close(3)                                = 0

......
    
ioctl(4, SNDRV_PCM_IOCTL_HW_REFINE, 0xbef92490) = 0
ioctl(4, SNDRV_PCM_IOCTL_HW_REFINE, 0xbef92860) = 0
ioctl(4, SNDRV_PCM_IOCTL_HW_PARAMS, 0xbef92860) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
ioctl(4, SNDRV_PCM_IOCTL_SW_PARAMS, 0xbef92404) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
ioctl(4, SNDRV_PCM_IOCTL_PREPARE, 0xc54f8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
ioctl(4, SNDRV_PCM_IOCTL_SW_PARAMS, 0xbef927f0) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
ioctl(4, SNDRV_PCM_IOCTL_WRITEI_FRAMES, 0xbef92ab8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
ioctl(4, SNDRV_PCM_IOCTL_WRITEI_FRAMES, 0xbef92ab8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
ioctl(4, SNDRV_PCM_IOCTL_WRITEI_FRAMES, 0xbef92ab8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
ioctl(4, SNDRV_PCM_IOCTL_WRITEI_FRAMES, 0xbef92ab8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
ioctl(4, SNDRV_PCM_IOCTL_WRITEI_FRAMES, 0xbef92ab8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
ioctl(4, SNDRV_PCM_IOCTL_WRITEI_FRAMES, 0xbef92ab8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
ioctl(4, SNDRV_PCM_IOCTL_WRITEI_FRAMES, 0xbef92ab8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
ioctl(4, SNDRV_PCM_IOCTL_WRITEI_FRAMES, 0xbef92ab8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
ioctl(4, SNDRV_PCM_IOCTL_WRITEI_FRAMES, 0xbef92ab8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192
ioctl(4, SNDRV_PCM_IOCTL_WRITEI_FRAMES, 0xbef92ab8) = 0
ioctl(4, SNDRV_PCM_IOCTL_SYNC_PTR, 0x2e858) = 0
    
......    
    
fcntl64(4, F_GETFL)                     = 0x80002 (flags O_RDWR|O_CLOEXEC)
fcntl64(4, F_SETFL, O_RDWR|O_CLOEXEC)   = 0
ioctl(4, SNDRV_PCM_IOCTL_DRAIN, 0xc50a4) = 0
fcntl64(4, F_GETFL)                     = 0x80002 (flags O_RDWR|O_CLOEXEC)
fcntl64(4, F_SETFL, O_RDWR|O_CLOEXEC)   = 0
close(3)                                = 0
ioctl(4, SNDRV_PCM_IOCTL_DROP, 0xc51ac) = 0
ioctl(4, SNDRV_PCM_IOCTL_HW_FREE, 0)    = 0
close(4)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

It can be seen that playing a sound alone requires so many system calls, which is really inhuman.

Therefore, the kernel provides developers with alsa lib tool library at the application layer to shield various open, ioctl, read, write and other operations, and integrates interfaces of various functions for upper layer calls. Some interfaces are as follows:

int snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode)
int snd_pcm_close (snd_pcm_t *pcm)
int snd_pcm_set_params (snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, 
               unsigned int rate, int soft_resample, unsigned int latency)
int snd_pcm_get_params (snd_pcm_t *pcm, snd_pcm_uframes_t *buffer_size, snd_pcm_uframes_t *period_size) 
snd_pcm_sframes_t snd_pcm_writei (snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
snd_pcm_sframes_t 	snd_pcm_readi (snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
......    

The familiar aplay, arecord, amixer and other commands are implemented based on the above interfaces provided by alsa lib and are included in the alsa utils toolkit.

7. Some commissioning experience

7.1 noise problems

During dma transmission, when the number of moves of a descriptor (total data to be moved / size of each move) cannot be divided, there will be data loss, resulting in all subsequent data dislocation and noise.

7.2 relationship between clock and sampling rate

If there is no sound or there is a problem with the sound, you can check the clock first

  1. Let's see if there is mclk, because the clock provides the master clock
  2. Then look at lrclk. The clock has the same sampling rate as playing audio files
  3. Finally, look at bclk. Generally, the clock has a multiple relationship with lrclk. In the aic of x1600, bclk=64lrclk

7.3 the playback speed becomes faster or slower

  1. When the clock frequency of lrclk > the sampling rate of playing audio files, the sound becomes faster
  2. When the clock frequency of lrclk is less than the sampling rate of playing audio files, the sound will slow down

7.4 some problems in executing aplay/arecord

7.4.1 underrun/overrun problem

Underrun: it usually occurs during playback. When the upper layer data is not sent to the driver's buffer in time, the driver has no data to read, that is, an underrun error will occur

Overrun: it usually occurs during recording. When the upper layer does not take away the data in the drive buffer in time, the drive buffer has no space to write, that is, an overrun error will occur

Because aplay/arecord is used, if this problem occurs, it is generally a driver problem. At this time, it indicates that the recording and playback channel has been opened, but there is a problem matching with the upper application

7.4.2 PCM input / output error problem

This problem indicates that the recording and playback channel is not open. At this time, you can first pay attention to the next clock to see whether there is a clock or whether the clock is correct, and then focus on checking whether the dma is configured correctly and whether the dma descriptor chain turns up.

Tags: Linux Alsa

Posted on Tue, 28 Sep 2021 04:46:34 -0400 by rledieu