当前位置:网站首页>Introduction to audio alsa architecture

Introduction to audio alsa architecture

2022-06-12 05:01:00 Facing the sea 0902

One 、ALSA framework

ALSA(Advanced Linux Sound Architecture) Advanced Linux Sound architecture .
At present, the audio subsystem of embedded mobile devices is mainly ALSA drive asoc frame , These include codec driver、 platform driver、 machine driver etc. . codec driver Only care about codec In itself ; platform driver Mainly including platform cpu dai( Such as i2s) , dma Other parts ;machine driver Main platform driver and codec driver Connect . platform and dai driver Generally, there are few modifications , Major changes machine and codec driver, This will also be the focus of our subsequent analysis .

ALSA The architecture is as follows :
ALSA Frame diagram
You can take a look at the previous articles for comparison and reference :
Linux—ALSA Audio Tools arecord、aplay、amixer Use
ALSA drive asoc Framework machine
ALSA drive asoc Framework Codec
ALSA drive asoc Framework Platform

Two 、 Other instructions

1.PCM Interface

The simplest audio interface is PCM( Pulse code modulation ) Interface , The interface consists of clock pulses (BCLK)、 Frame synchronization signal (FS) And receive data (DR) And send data (DX) form . stay FS The rising edge of the signal is transmitted from MSB Start ,FS The frequency is equal to the sampling frequency .FS The transmission of data words begins after the signal , Single data bits are transmitted in sequence , One data word is transmitted in one clock cycle .PCM The interface is easy to implement , In principle, it can support any data scheme and any sampling frequency , But you need to get an independent data queue for each audio channel .

2.IIS Interface

IIS Interface in 20 century 80 The s was first PHILIPS For consumption of audio products , And in a place called LRCLK(Left/Right CLOCK) In the signal mechanism of , Turn two audio channels into a single data queue . When LRCLK For the high time , Left channel data is transmitted ;LRCLK For the low , Right channel data is transmitted . And CPM comparison ,IIS More suitable for stereo system , Of course ,IIS The variant of also supports multi-channel time division multiplexing , Therefore, it can support multi-channel .

3.linux ALSA Audio device driver

ALSA The system includes a driver package alsa-driver、 Development kit alsa-libs、 Development kit plug-ins alsa-libplugins、 Set up the Management Kit alsa-utils、 Other sound related processing applets alsa-tools、 Special audio firmware support package alsa-firmware、OSS Interface compatible with simulation layer tools alsa-oss for 7 Subprojects , Only the driver package is required .

at present ALSA The interfaces that the kernel provides to the user space are :

(1) Equipment information interface (/proc/asound)
(2) Device control interface (/dev/snd/controlCX)
(3) Mixer device interface (/dev/snd/mixerCXDX)
(4)PCM Device interface (/dev/snd/pcmCXDX)
(5) original MIDI( MIDI ) Device interface (/dev/snd/midiCXDX)
(6) Sound synthesis (synthesizer) Device interface (/dev/snd/seq)
(7) Timer interface (/dev/snd/timer)
These interfaces are provided to alsa-lib Use , Not for applications , Applications are best served by alsa-lib, Or more advanced interfaces such as jack Provided interface .

4.linux ASoC Audio device driver

ASoC yes ALSA stay SoC The development and evolution of , Its essence still belongs to ALSA, But in ALSA On the basis of architecture CPU Related code and Codec The relevant code is separated , The reason is the adoption of tradition ALSA Architecture , The same model Codec Work in different CPU when , You need different drivers , This does not meet the requirements of code reuse .

ASoC Mainly by 3 Part of it is made up of :
(1)Codec drive , This part only concerns Codec In itself , And CPU Related features do not operate from this part
(2) Platform driven , This part only cares about CPU In itself , It doesn't matter Codec, It mainly deals with two problems :DMA The engine and SoC Released PCM、IIS or AC’97 Digital interface control .
(3) Plate drive , This part will be platform driven and Codec Drivers are bound together , Describes the hardware features at the board level

above 3 In the part ,1 and 2 Basically, it can still be a universal driver , namely Codec The driver thinks it can connect to any CPU, and CPU Of IIS、PCM、 or AC’97 The platform driver corresponding to the interface thinks that it can connect the symbols of its interface type Codec, Only 3 It's not universal , Specific on a particular circuit board CPU and Codec determine , So it's very much like a socket , It has Codec And the platform .ASoC User space programming method and ALSA Exactly the same .

5.card Sound card and component management

/*  For each sound card , You have to create a card example , This function is used to create card  Parameters idx Is the index number   Parameters id Is the identified string   Parameters module Generally point to THIS_MODULE  Parameters extra_size Is the size of the additional data to be allocated , The distribution of extra_size The size of memory will be used as card->private_data*/
 struct snd_card *snd_card_new(int idx, const char *id,struct module *module, int extra_size)

  /*  Register your sound card  */
int snd_card_register(struct snd_card *card)

/*  Release ( Cancellation ) Sound card  */
int snd_card_free(struct snd_card *card)

 /*  Create a ALSA Equipment components   Parameters type For the device type , View macro SNDRV_DEV_XXX*/
int snd_device_new(struct snd_card *card, snd_device_type_t type,void *device_data, struct snd_device_ops *ops)

  /*  Device for releasing sound card   Parameters device_data Point to the private data of the device to be  */
int snd_device_free(struct snd_card *card, void *device_data)

6.PCM Device interface

/*  establish PCM example   Parameters card Point to the sound card   Parameters id Is the identification string   Parameters device by PCM Equipment index (0 It means the first one 1 individual PCM equipment )  Parameters playback_count Is the number of sub streams of the playback device   Parameters capture_count Is the number of sub streams of the recording device   The parameter points to the constructed PCM example */
int snd_pcm_new(struct snd_card *card, const char *id, int device,int playback_count, int capture_count,struct snd_pcm ** rpcm)

 /*  Set up PCM Operation function   Parameters direction, View macro SNDRV_PCM_STREAM_XXX*/
void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, struct snd_pcm_ops *ops)

 /*  Distribute DMA buffer , Only when the DMA This function can only be called when the buffer has been pre allocated  */
int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)

 /*  Release from snd_pcm_lib_malloc_pages Function assignment consistency DMA buffer  */
int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)

 /*  The easiest way to allocate a buffer is to call this function  type To view the macro SNDRV_DMA_TYPE_* */
int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,int type, void *data,size_t size, size_t max)

7. Control interface description

/*  Create a control example ----struct snd_kcontrol Structure   Parameters ncontrol Record for initialization  private_data Private data set for  */
struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, void *private_data)

 /*  Add a control instance for the sound card  */
int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)

/*  The driver can call this function in the interrupt service program to change or update a control*/
void snd_ctl_notify(struct snd_card *card, unsigned int mask,struct snd_ctl_elem_id *id)

8. be based on ALSA Audio framework driver design

1:struct snd_card *snd_card_new(int idx, const char *id,struct module *module, int extra_size);/*  Create a sound card  */

2:static struct snd_device_ops ops = {
    
		.dev_free =     xxx_free,
	};

3:struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,void *private_data); /*  establish control example  */

4:int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol);    /*  Add a control instance for the sound card  */

5:int snd_device_new(struct snd_card *card, SNDRV_DEV_CODEC,void *device_data, struct snd_device_ops *ops);  /*  Create a ALSA Equipment components ----- Codec equipment  */

6:int snd_pcm_new(struct snd_card *card, const char *id, int device,int playback_count, int capture_count,struct snd_pcm ** rpcm) /*  establish PCM example  */

8:int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,int type, void *data,size_t size, size_t max)  /*  Allocate buffer  */

9:void snd_pcm_set_ops(struct snd_pcm *pcm, SNDRV_PCM_STREAM_PLAYBACK, struct snd_pcm_ops *ops)  /*  Set up PCM Operation function ---- Play  */

10:void snd_pcm_set_ops(struct snd_pcm *pcm, SNDRV_PCM_STREAM_CAPTURE, struct snd_pcm_ops *ops)  /*  Set up PCM Operation function  ---- sound recording  */

11:/* Audio related initialization : Audio stream correlation 、 Initialization of pins, etc */

12:DMA Related settings 

13:int snd_card_register(struct snd_card *card);  /*  Register your sound card  */IRQ_AC97

9.ASoC Audio drive important structure

/* *1:ASoC Codec drive : */

struct snd_soc_dai {
     /*  Digital audio interface , It describes Codec DAI( Digital audio interface ---Digital Audio Interface) and PCM To configure  */
	/* DAI description */
	char *name;  /*  name  */
	unsigned int id;  /* ID */
	int ac97_control;

	struct device *dev;

	/* DAI callbacks */
	int (*probe)(struct platform_device *pdev,
		     struct snd_soc_dai *dai);
	void (*remove)(struct platform_device *pdev,
		       struct snd_soc_dai *dai);
	int (*suspend)(struct snd_soc_dai *dai);
	int (*resume)(struct snd_soc_dai *dai);

	/* ops */
	struct snd_soc_dai_ops *ops;  /* DAI Operation function  */

	/* DAI capabilities */
	struct snd_soc_pcm_stream capture;  /*  Recording stream  */
	struct snd_soc_pcm_stream playback; /*  Play stream  */

	/* DAI runtime info */
	struct snd_pcm_runtime *runtime;  /* PCM Runtime  */
	struct snd_soc_codec *codec;  /*  codecs  */
	unsigned int active;
	unsigned char pop_wait:1;
	void *dma_data;

	/* DAI private data */
	void *private_data;

	/* parent codec/platform */
	union {
    
		struct snd_soc_codec *codec;  /*  codecs  */
		struct snd_soc_platform *platform;  /*  Platform driven ----CPU */
	};

	struct list_head list; /*  Used to form a linked list  */
};

struct snd_soc_codec {
     /* SoC Audio codec ---IO operation 、 Dynamic audio power management and clock 、PLL Wait for control  */
	char *name;  /*  name  */
	struct module *owner; /* THIS_MODULE */
	struct mutex mutex;
	struct device *dev;

	struct list_head list; /*  Used to form a linked list  */

	/* callbacks */
	int (*set_bias_level)(struct snd_soc_codec *,
			      enum snd_soc_bias_level level); /*  Callback function  */

	/* runtime */
	struct snd_card *card;  /*  Sound card  */
	struct snd_ac97 *ac97;  /* for ad-hoc ac97 devices */ /* AC97 equipment  */
	unsigned int active;
	unsigned int pcm_devs;
	void *private_data;

	/* codec IO */
	void *control_data; /* codec control (i2c/3wire) data */
	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
	int (*display_register)(struct snd_soc_codec *, char *,
				size_t, unsigned int);
	hw_write_t hw_write;
	hw_read_t hw_read;
	void *reg_cache;
	short reg_cache_size;
	short reg_cache_step;

	/* dapm */
	u32 pop_time;
	struct list_head dapm_widgets;
	struct list_head dapm_paths;
	enum snd_soc_bias_level bias_level;
	enum snd_soc_bias_level suspend_bias_level;
	struct delayed_work delayed_work;

	/* codec DAI's */
	struct snd_soc_dai *dai; /* SoC Layer interface  */
	unsigned int num_dai;

#ifdef CONFIG_DEBUG_FS
	struct dentry *debugfs_reg;
	struct dentry *debugfs_pop_time;
#endif
};

struct snd_soc_dai_ops {
     /*  Digital audio interface DAI Operation function set  */
	/* * 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); /*  Set the system clock  */
	int (*set_pll)(struct snd_soc_dai *dai,
		int pll_id, unsigned int freq_in, unsigned int freq_out); /*  Set up PLL */
	int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);  /*  Set clock division  */

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

	/* * DAI digital mute - optional. * Called by soc-core to minimise any pops. */
	int (*digital_mute)(struct snd_soc_dai *dai, int mute); /*  Digital mute  */

	/* * ALSA PCM audio operations - all optional. * Called by soc-core during audio PCM operations. */
	 /* ALSA PCM Audio operation  */
	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 *);
	int (*trigger)(struct snd_pcm_substream *, int,
		struct snd_soc_dai *);
};

struct snd_soc_ops {
     /* SoC Operation function ----Codec Audio operation  */
	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);
};

/* *2:ASoC Platform driven : * * stay ASoC Platform drive part , There is also Codec In drive snd_soc_dai、snd_soc_dai_ops、snd_soc_ops Examples of these three structures are used to describe  *DAI and DAI The operation of , But here's the difference , In platform driven , They only describe CPU Relevant parts without describing Codec. besides , stay ASoC * Platform driven , It has to be complete DMA drive , That is, tradition ALSA Of and_pcm_ops Structure member function trigger()、pointer() etc. , therefore ASoC platform  * The drive is usually driven by DAI and DMA Two parts . */

/* *ASoC Plate drive : * In the board driven module initialization function , Will pass platform_device_add() Sign up for a "soc-audio" Of platform equipment , This is because soc-core.c * Registered a "soc-audio" Of platform drive  */

struct snd_soc_device {
     /* SoC equipment  */
	struct device *dev; /*  Embedded device model device  */
	struct snd_soc_card *card; /* SoC card  */
	struct snd_soc_codec_device *codec_dev;  /* SoC Codec equipment  */
	void *codec_data;  /*  Data used by encoding and decoding equipment  */
};

struct snd_soc_dai_link  {
     /*  binding ASoC Codec Drive and CPU Platform driven data structure at the end  */
	char *name;			/* Codec name */ /*  The name of the codec  */
	char *stream_name;		/* Stream name */ /*  The name of the stream  */

	/* DAI */
	struct snd_soc_dai *codec_dai; /* SoC Layer interface ---- Codec end  */
	struct snd_soc_dai *cpu_dai;     /* SoC Layer interface ----CPU End */

	/* machine stream operations */
	struct snd_soc_ops *ops; /* SoC Operation function ---- Stream operation function  */

	/* codec/machine specific init - e.g. add machine controls */
	int (*init)(struct snd_soc_codec *codec);  /*  initialization  */

	/* DAI pcm */
	struct snd_pcm *pcm; /*  Point to pcm */
};
原网站

版权声明
本文为[Facing the sea 0902]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/03/202203010621524692.html