ALSA struct process 2

Source: Internet
Author: User

The control interface allows the user space application (ALSA-Lib) to access and control multiple switches and sliding controls in the Audio Codec Chip.

We need to actively call the snd_pcm_new () function to create the PCM device during driver initialization, while the control device is created in snd_card_create,

Snd_card_create () creates a control device node by calling the snd_ctl_create () function. Therefore, you do not need to create a control device explicitly. If you create a sound card, the control device is automatically created.

Similarly, it has an snd_ctl_dev_register, which calls:

  1. Snd_register_device (sndrv_device_type_control, card,-1, & snd_ctl_f_ops, card, name)

/*
* Init part
*/

Static const struct file_operations snd_ctl_f_ops =
{
. Owner = this_module,
. Read = snd_ctl_read,
. Open = snd_ctl_open,
. Release = snd_ctl_release,
. Llseek = no_llseek,
. Poll = snd_ctl_poll,
. Unlocked_ioctl = snd_ctl_ioctl,
. Compat_ioctl = snd_ctl_ioctl_compat,
. Fasync = snd_ctl_fasync,

};

When a user program needs to enable the control device, the driver can use the snd_minors [] global array and the device number to obtain various callback functions in the snd_ctl_f_ops structure,

Then, use these callback functions to access the information and data in the control (several callback functions get, put, info will be called in the end ). You can read the code:/sound/CORE/control. C.

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.

Currently, it has been integrated into the kernel code tree: Sound/SOC. ASOC cannot exist independently. It is only built on the standard ALSA driver. It must be combined with the standard ALSA driver framework to work.

Generally, like abstraction and reuse in the software field, the audio systems of embedded devices can be divided into three parts: On-board hardware (MACHINE), SOC (Platform), and codec, as shown in:

Audio System Structure

Association between important data structures in ASOC:

Static relationships between structures in the Kernel-2.6.35-ASoC

ASOC Data Structure in kernel 3.0

The data structure in 3.0 is more reasonable and clear. snd_soc_device structure is removed, snd_soc_card is used to replace it directly, snd_soc_pcm_runtime is enhanced, and two other data structures snd_soc_codec_driver and snd_soc_platform_driver are added, used to explicitly represent the codec driver and platform driver.

/* 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 );
};

What is its role ???

Through the snd_soc_card structure, the other two data structures of the machine driver are introduced:

  • Snd_soc_dai_link (instance: smdk_dai [])
  • Snd_soc_ops (instance: smdk_ops)

Among them, the names of platform, codec, codec_dai, and cpu_dai are specified in snd_soc_dai_link. Later, the machine driver will use these names to match the platform, codec, and Dai that have already been registered in the system, these registered components are defined in the Code files of the corresponding platform driver and CODEC driver. In this case, the device initialization code of the machine driver is nothing more than selecting the appropriate platform, codec, and Dai, fill in the above data structures with them, and then register the platform device. Of course, we also need to implement the OPS implementation corresponding to the dai_link connecting platform and CODEC. In this example, smdk_ops only implements the hw_params function: smdk_hw_params.

Platform_driver connects snd_soc_card through its probe, and the dai_link (snd_soc_dai_link type) connects the snd_soc_ops struct.

The snd_soc_card Prope function is called when the platform bus matches platform_device and platform_driver. It calls the Handler through snd_soc_register_card..., most of the work is implemented in snd_soc_instantiate_card.

This function first uses card-> instantiated to determine whether the card has been instantiated. If it has been instantiated, it returns directly. Otherwise, it traverses each pair of dai_link to bind codec, platform, and Dai:

/* Bind dais */
For (I = 0; I <card-> num_links; I ++)
Soc_bind_dai_link (card, I );

ASOC defines three global linked list header variables: codec_list, dai_list, and platform_list. All codec, Dai, and platform in the system are connected to these three global linked lists during registration. The soc_bind_dai_link function scans these three linked lists one by one, matches them according to the name in card-> dai_link [], and matches the corresponding codec, the Dai and platform instances are assigned to card-> RTD [] (snd_soc_pcm_runtime ). After this process, the codec, Dai, and platform drivers used in the machine are saved in snd_soc_pcm_runtime :( card-> RTD.

/* SOC machine Dai configuration, glues A codec and CPU Dai together */
Struct snd_soc_pcm_runtime {
Struct device dev;
Struct snd_soc_card * card;
Struct snd_soc_dai_link * dai_link;

Unsigned int complete: 1;
Unsigned int dev_registered: 1;

/* Transport ry data-only valid if transport ry is being enforced */
Unsigned int rate;
Long pmdown_time;

/* Runtime devices */
Struct snd_pcm * PCM;
Struct snd_soc_codec * codec;
Struct snd_soc_platform * platform;
Struct snd_soc_dai * codec_dai;
Struct snd_soc_dai * cpu_dai;

Struct delayed_work;
};

Snd_soc_instantiate_card then initializes the codec register cache, and then calls the standard ALSA function to create a sound card instance:


  1. /* Card bind complete so register a sound card */
  2. Ret = snd_card_create (sndrv_default_idx1, sndrv_default_str1, card-> owner, 0, & Card-> snd_card );
  3. Card-> snd_card-> Dev = card-> dev;
  4. Card-> dapm. bias_level = snd_soc_bias_off;
  5. Card-> dapm. Dev = card-> dev;
  6. Card-> dapm. Card = card;
  7. List_add (& Card-> dapm. List, & Card-> dapm_list );

Then, call the probe functions of each sub-structure in sequence:

/* Initialise the sound card only once */
If (card-> probe ){
Ret = card-> probe (card); // It may be null
If (Ret <0)
Goto card_probe_error;
}

For (I = 0; I <card-> num_links; I ++ ){
Ret = soc_probe_dai_link (card, I );
If (Ret <0 ){
Pr_err ("ASOC: failed to instantiate card % s: % d \ n ",
Card-> name, RET );
Goto probe_dai_err;
}
}

In the above soc_probe_dai_link () function, we have done a lot of things. This function not only calls the probe function driven by codec, Dai, and platform one by one,

Finally, the soc_new_pcm () function is called to create a PCM Logical Device Driven by the standard ALSA. (It will call:

Ret = snd_pcm_new (RTD-> card-> snd_card, new_name,
Num, playback, capture, & PCM );

)

Call the snd_pcm_new () function for creating PCM in the standard ALSA driver to create the PCM instance of the sound card. Set the private_data field of PCM to the runtime variable RTD, then, replace the snd_pcm_ops field in some PCM with the snd_pcm_ops field in the platform driver. Finally, call the pcm_new callback of the platform driver to implement the DMA memory application and DMA initialization in the platform. Now, the sound card and its PCM instance are created.

Return to the snd_soc_instantiate_card function. After snd_card and snd_pcm are created, initialize and combine the formats supported by dapm and Dai, and call card-> late_probe (card) perform some final initialization and configuration work, and finally call the sound card registration function of the standard ALSA driver to register the sound card:

// Damp controls
If (card-> dapm_widgets)
Snd_soc_dapm_new_controls (& Card-> dapm, card-> dapm_widgets,
Card-> num_dapm_widgets );
If (card-> dapm_routes)
Snd_soc_dapm_add_routes (& Card-> dapm, card-> dapm_routes,
Card-> num_dapm_routes );

...

// In init. c
// Create card device, register all the devices on the card.
Ret = snd_card_register (card-> snd_card );
If (Ret <0 ){
Printk (kern_err "ASOC: failed to register Soundcard for % s \ n", card-> name );
Goto probe_aux_dev_err;
}

So far, the initialization of the entire machine driver has been completed. In fact, some platfrom and CODEC drivers have been initialized through probe calls of each sub-structure, the entire process can be represented in a sequence diagram:

Soc_probe Sequence Diagram Based on 3.0 Kernel

Soc_probe Sequence Diagram Based on 2.6.35

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.