【Android Audio 入门 六】Audio 结构体分析---待后续更新

【Android Audio 入门 六】Codec分析

    • 六、Codec 分析
      • 6.1 Codec 相关结构体分析
        • 6.1.1 struce snd_soc_dai 结构体
        • 6.1.2 struct snd_soc_dai_driver 驱动 结构体
          • 6.1.2.1 struct snd_soc_dai_ops 硬件参数 结构体
          • 6.1.2.2 struct snd_soc_pcm_stream 软件参数 结构体
        • 6.1.3 struct snd_soc_codec 设备 结构体
        • 6.1.4 struct snd_soc_card 声卡 结构体
          • 6.1.4.1 struct snd_soc_codec_conf 结构体
          • 6.1.4.2 struct snd_kcontrol_new 结构体
          • 6.1.4.3 struct snd_soc_dapm_widget 结构体
          • 6.1.4.4 struct snd_soc_dapm_route 结构体
          • 6.1.4.5 struct snd_soc_dapm_context 结构体
        • 6.1.5 struct snd_soc_pcm_runtime 结构体
          • 6.1.5.1 snd_pcm_ops PCM设备文件结操作方法 构体
          • 6.1.5.2 snd_soc_dpcm_runtime 结构体
          • 6.1.5.3 struct snd_pcm 结构体
          • 6.1.5.4 struct snd_compr 结构体
          • 6.1.5.5 struct snd_soc_platform 结构体
          • 6.1.5.6 struct snd_soc_component 结构体
        • 6.1.6 struct snd_soc_dai_link 结构体
          • 6.1.6.1 struct snd_soc_dai_link_component 结构体
      • 6.2 Codec 相关结构体关系梳理


有关Alsa 代码的编写,推荐看看《wirte an alsa driver》,
等有时间,我也会针对它来写一些中文版的博客文章,敬请期待。

六、Codec 分析

Codec 的作用:
音频芯片的控制,比如静音,打开/关闭 ADC/DAC,设置ADC/DAC的增益,耳机模式的检测等操作。

I2S:数字音频接口,用于CPU 和 Codec 之间的数字音频流 raw data 的传输。每当有 playback 或 record 操作时, snd_soc_dai_ops.prepare() 会被调用,启动 I2S 总线。

音频数据流向:

| copy_from_user |             | DMA |                              | I2S/PCM/AC97 |
RAM--------------->dma buffer--------> I2S tx FIFO -----------------> CODEC -> SPK/Headset

codec 驱动代码位于 @\kernel\msm-3.18\sound\soc\codecs 目录下。
在学习Codec 前,我们先来学习下它的结构体,看懂了它的结构体,代码就差不多了。

6.1 Codec 相关结构体分析

6.1.1 struce snd_soc_dai 结构体

snd_soc_dai 类似一个中枢结构体,它主要的功能有两个:

  1. 定义Codec 相关的信息: name,rate,channels,probed 等
  2. 绑定 snd_soc_dai_driver,snd_soc_codec,snd_soc_card 等结构体

snd_soc_dai 结构体是 codec 最大的结构体,其中有几个很重要的成员:

  1. name : Codec 的名字
  2. capture_active :是否允许Capture,默认为1
  3. playback_active :是否允许playback,默认为1
  4. struct snd_soc_dai_driver :Codec 驱动的核心结构体(后续分析)
  5. probed:是否已经注册过
  6. playback_widget / capture_widget:播放和录音所对应的 kcontrol
  7. rate: 硬件 采样率
  8. channels: 硬件 声道数
  9. sample_bits: 硬件 采样深度
  10. struct snd_soc_codec *codec: 所属的 codec (后续分析)
  11. struct snd_soc_card *card: 对应的声卡结构体 (后续分析)

@\kernel\msm-3.18\include\sound\soc-dai.h
/*
 * Digital Audio Interface runtime data.
 * Holds runtime data for a DAI.
 */
struct snd_soc_dai {
	const char *name;		// Codec DAI 的名字
	int id;					// Codec DAI 的 ID
	struct device *dev;
	void *ac97_pdata;	/* codec 平台私有数据 platform_data for the ac97 codec */

	/* driver ops */
	struct snd_soc_dai_driver *driver;	// Codec 驱动的核心结构体

	/* DAI runtime info */
	unsigned int capture_active:1;		/* 是否允许Capture,默认为1, stream is in use */
	unsigned int playback_active:1;		/* 是否允许playback,默认为1, stream is in use */
	unsigned int symmetric_rates:1;
	unsigned int symmetric_channels:1;
	unsigned int symmetric_samplebits:1;
	unsigned int active;
	unsigned char probed:1;			// 是否已经 probe 过

	struct snd_soc_dapm_widget *playback_widget;	//播放的kcontrol
	struct snd_soc_dapm_widget *capture_widget;		//录音的kcontrol

	/* DAI DMA data */
	void *playback_dma_data;	//播放时的dma buffer 地址
	void *capture_dma_data;		//录音时的dma buffer 地址

	/* Symmetry data - only valid if symmetry is being enforced */
	unsigned int rate;			// 硬件 采样率
	unsigned int channels;		// 硬件 声道数
	unsigned int sample_bits;	// 硬件 采样深度

	/* parent platform/codec */
	struct snd_soc_platform *platform;		// 所属的 平台驱动
	struct snd_soc_codec *codec;			// 所属的 codec 
	struct snd_soc_component *component;	// 所属的 控件

	/* CODEC TDM slot masks and params (for fixup) */
	unsigned int tx_mask;
	unsigned int rx_mask;

	struct snd_soc_card *card;	// 对应的声卡结构体

	struct list_head list;
};

6.1.2 struct snd_soc_dai_driver 驱动 结构体

重要成员如下:

  1. DAI driver callbacks
    包含probe、remove、suspend、resume 等函数
    当 snd_soc_codec_drive 和 codec device匹配后 Codec DAI 的回调函数

  2. struct snd_soc_dai_ops:用于配置 codec 相关的硬件参数(后续分析)

  3. struct snd_soc_pcm_stream capture/playback :Capture 和 playback 对应的详细参数

  4. probe_order:probe 的顺序

@\kernel\msm-3.18\include\sound\soc-dai.h
struct snd_soc_dai_driver {
	/* DAI description */
	const char *name;		// Codec DAI 的名字
	unsigned int id;		// Codec DAI 的 ID
	int ac97_control;		// codec 平台私有数据
	unsigned int base;

	/* DAI driver callbacks */		
	// 当 snd_soc_codec_drive 和 codec device匹配后 Codec DAI 的回调函数
	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);
	/* compress dai */
	bool compress_dai;

	/* ops */
	const struct snd_soc_dai_ops *ops;	// codec 字符设备结构体,用于配置 Codec 相关的参数

	/* DAI capabilities */
	struct snd_soc_pcm_stream capture;
	struct snd_soc_pcm_stream playback;
	unsigned int symmetric_rates:1;
	unsigned int symmetric_channels:1;
	unsigned int symmetric_samplebits:1;

	/* probe ordering - for components with runtime dependencies */
	int probe_order;	// probe 的顺序
	int remove_order;	// remove 的顺序
};

6.1.2.1 struct snd_soc_dai_ops 硬件参数 结构体

重要成员如下:

  1. 设置 Codec DAI 时钟相关参数
    set_sysclk(设置系统时钟)、set_clkdiv(设置时钟分频)等

  2. 设置 Codec DAI 的信号格式配置
    set_fmt:配置数据格式

  3. 设置 Codec DAI 的静音操作函数
    digital_mute:数字信号静音函数
    mute_stream : 数据流静音函数

  4. 设置PCM 相关控制的操作方法,包手中 硬件参数设定
    hw_params:硬件参数设定

@\kernel\msm-3.18\include\sound\soc.h

struct snd_soc_dai_ops {
	/* 设置 Codec DAI 时钟相关参数
	 * 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);
	int (*set_bclk_ratio)(struct snd_soc_dai *dai, unsigned int ratio);

	/*	设置 Codec DAI 的信号格式配置
	 * DAI format configuration
	 * Called by soc_card drivers, normally in their hw_params.
	 */
	int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
	int (*xlate_tdm_slot_mask)(unsigned int slots, unsigned int *tx_mask, unsigned int *rx_mask);
	int (*set_tdm_slot)(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width);
	int (*set_channel_map)(struct snd_soc_dai *dai, unsigned int tx_num, unsigned int *tx_slot, unsigned int rx_num, unsigned int *rx_slot);
	int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
	int (*get_channel_map)(struct snd_soc_dai *dai, unsigned int *tx_num, unsigned int *tx_slot, unsigned int *rx_num, unsigned int *rx_slot);

	/*	设置 Codec DAI 的静音操作函数
	 * DAI digital mute - optional.
	 * Called by soc-core to minimise any pops.
	 */
	int (*digital_mute)(struct snd_soc_dai *dai, int mute);
	int (*mute_stream)(struct snd_soc_dai *dai, int mute, int stream);

	/*  设置PCM 相关控制的操作方法,包手中 硬件参数设定
	 * 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 *);
	int (*bespoke_trigger)(struct snd_pcm_substream *, int, struct snd_soc_dai *);
	
	/*
	 * For hardware based FIFO caused delay reporting.
	 * Optional.
	 */
	snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,struct  snd_soc_dai *);
};

6.1.2.2 struct snd_soc_pcm_stream 软件参数 结构体

配置具体的软件参数,如 传输速率,通道数,格式等。

@\kernel\msm-3.18\include\sound\soc.h

/* SoC PCM stream information */
struct snd_soc_pcm_stream {
	const char *stream_name;
	u64 formats;			/* SNDRV_PCM_FMTBIT_* */
	unsigned int rates;		/* SNDRV_PCM_RATE_* */
	unsigned int rate_min;		/* min rate */
	unsigned int rate_max;		/* max rate */
	unsigned int channels_min;	/* min channels */
	unsigned int channels_max;	/* max channels */
	unsigned int sig_bits;		/* number of bits of content */
	const char *aif_name;		/* DAPM AIF widget name */
};

6.1.3 struct snd_soc_codec 设备 结构体

Audio 的 Codec device 结构体,重要成员如下:

  1. struct snd_soc_codec_driver
    绑定对应的codec driver 结构体

  2. 定义的 Codec 硬件寄存器读写操作方法
    volatile_register(),readable_register() , writable_register()

  3. codec IO
    codec 控制数据指针 control_data

@\kernel\msm-3.18\include\sound\soc.h

/* SoC Audio Codec device */
struct snd_soc_codec {
	struct device *dev;
	const struct snd_soc_codec_driver *driver;	// 对应的codec driver 结构体

	struct mutex mutex;
	struct list_head list;
	struct list_head card_list;
	// Codec 寄存器读写操作方法
	int (*volatile_register)(struct snd_soc_codec *, unsigned int);		
	int (*readable_register)(struct snd_soc_codec *, unsigned int);
	int (*writable_register)(struct snd_soc_codec *, unsigned int);

	/* runtime */
	struct snd_ac97 *ac97;  /* for ad-hoc ac97 devices */
	unsigned int cache_bypass:1; /* Suppress access to the cache */
	unsigned int suspended:1; /* Codec is in suspend PM state */
	unsigned int ac97_registered:1; /* Codec has been AC97 registered */
	unsigned int ac97_created:1; /* Codec has been created by SoC */
	unsigned int cache_init:1; /* codec cache has been initialized */
	u32 cache_sync; /* Cache needs to be synced to hardware */

	/* codec IO */
	void *control_data; /* codec control (i2c/3wire) data */
	hw_write_t hw_write;
	void *reg_cache;
	struct mutex cache_rw_mutex;

	/* component */
	struct snd_soc_component component;

	/* dapm */
	struct snd_soc_dapm_context dapm;

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

6.1.4 struct snd_soc_card 声卡 结构体

最大的声卡结构体

  1. 绑定 snd_card 声卡结构体
  2. probe : 声卡 probe 函数
  3. 休眠/唤醒 前的电源配置函数
  4. 绑定的 snd_soc_dai_link 结构体
  5. 绑定 snd_soc_pcm_runtime 结构体
  6. Codec 配置结构体 struct snd_soc_codec_conf
  7. codec 的 snd_kcontrol_new 结构体
  8. codec dapm 控件结构体 struct snd_soc_dapm_widget
  9. codec dapm 回路结构体 struct snd_soc_dapm_route
  10. 声卡的 DAPM 信息 struct snd_soc_dapm_context
@\kernel\msm-3.18\include\sound\soc.h

/* SoC card */
struct snd_soc_card {
	const char *name;			// 声卡 名字
	const char *long_name;
	const char *driver_name;	// 声卡驱动 名字
	struct device *dev;
	struct snd_card *snd_card;	// 绑定 snd_card 声卡结构体
	struct module *owner;		// 驱动模块

	struct mutex mutex;
	struct mutex dapm_mutex;
	struct mutex dapm_power_mutex;

	bool instantiated;

	int (*probe)(struct snd_soc_card *card);	// Card  probe 函数
	int (*late_probe)(struct snd_soc_card *card);
	int (*remove)(struct snd_soc_card *card);

	// 休眠/唤醒 前的电源配置函数
	/* the pre and post PM functions are used to do any PM work before and
	 * after the codec and DAI's do any PM work. */
	int (*suspend_pre)(struct snd_soc_card *card);
	int (*suspend_post)(struct snd_soc_card *card);
	int (*resume_pre)(struct snd_soc_card *card);
	int (*resume_post)(struct snd_soc_card *card);

	/* callbacks */
	int (*set_bias_level)(struct snd_soc_card *, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level);
	int (*set_bias_level_post)(struct snd_soc_card *, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level);

	long pmdown_time;

	// 绑定的 snd_soc_dai_link 结构休 
	/* CPU <--> Codec DAI links  */
	struct snd_soc_dai_link *dai_link;
	int num_links;

	struct snd_soc_pcm_runtime *rtd;
	int num_rtd;

	// Codec 配置结构体 struct snd_soc_codec_conf 
	/* optional codec specific configuration */
	struct snd_soc_codec_conf *codec_conf;
	int num_configs;

	/*
	 * optional auxiliary devices such as amplifiers or codecs with DAI
	 * link unused
	 */
	struct snd_soc_aux_dev *aux_dev;
	int num_aux_devs;
	struct snd_soc_pcm_runtime *rtd_aux;
	int num_aux_rtd;

	// codec 的 snd_kcontrol_new  结构体
	const struct snd_kcontrol_new *controls;
	int num_controls;

	/*
	 * Card-specific routes and widgets.
	 */
	// codec dapm 控件结构体 struct snd_soc_dapm_widget
	const struct snd_soc_dapm_widget *dapm_widgets;
	int num_dapm_widgets;

	// codec dapm 回路结构体 struct snd_soc_dapm_route
	const struct snd_soc_dapm_route *dapm_routes;
	int num_dapm_routes;
	bool fully_routed;

	struct work_struct deferred_resume_work;

	/* lists of probed devices belonging to this card */
	struct list_head codec_dev_list;

	struct list_head widgets;
	struct list_head paths;
	struct list_head dapm_list;
	struct list_head dapm_dirty;

	/* Generic DAPM context for the card */
	// 声卡的 DAPM 信息  struct snd_soc_dapm_context
	struct snd_soc_dapm_context dapm;
	struct snd_soc_dapm_stats dapm_stats;
	struct snd_soc_dapm_update *update;

#ifdef CONFIG_DEBUG_FS
	struct dentry *debugfs_card_root;
	struct dentry *debugfs_pop_time;
#endif
	u32 pop_time;

	void *drvdata;
};

6.1.4.1 struct snd_soc_codec_conf 结构体
@ \kernel\msm-3.18\include\sound\soc.h

struct snd_soc_codec_conf {
	/*
	 * specify device either by device name, or by
	 * DT/OF node, but not both.
	 */
	const char *dev_name;
	const struct device_node *of_node;

	/*
	 * optional map of kcontrol, widget and path name prefixes that are
	 * associated per device
	 */
	const char *name_prefix;
};

6.1.4.2 struct snd_kcontrol_new 结构体

kcontrol 结构体

@ \kernel\msm-3.18\include\sound\control.h

struct snd_kcontrol_new {
	snd_ctl_elem_iface_t iface;	/* interface identifier */
	unsigned int device;		/* device/client number */
	unsigned int subdevice;		/* subdevice (substream) number */
	const unsigned char *name;	/* ASCII name of item */
	unsigned int index;		/* index of item */
	unsigned int access;		/* access rights */
	unsigned int count;		/* count of same elements */
	snd_kcontrol_info_t *info;
	snd_kcontrol_get_t *get;
	snd_kcontrol_put_t *put;
	union {
		snd_kcontrol_tlv_rw_t *c;
		const unsigned int *p;
	} tlv;
	unsigned long private_value;
};

6.1.4.3 struct snd_soc_dapm_widget 结构体
@ \kernel\msm-3.18\include\sound\soc-dapm.h

/* dapm widget */
struct snd_soc_dapm_widget {
	enum snd_soc_dapm_type id;
	const char *name;		/* widget name */
	const char *sname;	/* stream name */
	struct snd_soc_codec *codec;
	struct list_head list;
	struct snd_soc_dapm_context *dapm;

	void *priv;				/* widget specific data */
	struct regulator *regulator;		/* attached regulator */
	const struct snd_soc_pcm_stream *params; /* params for dai links */

	/* dapm control */
	int reg;				/* negative reg = no direct dapm */
	unsigned char shift;			/* bits to shift */
	unsigned int mask;			/* non-shifted mask */
	unsigned int on_val;			/* on state value */
	unsigned int off_val;			/* off state value */
	unsigned char power:1;			/* block power status */
	unsigned char active:1;			/* active stream on DAC, ADC's */
	unsigned char connected:1;		/* connected codec pin */
	unsigned char new:1;			/* cnew complete */
	unsigned char ext:1;			/* has external widgets */
	unsigned char force:1;			/* force state */
	unsigned char ignore_suspend:1;         /* kept enabled over suspend */
	unsigned char new_power:1;		/* power from this run */
	unsigned char power_checked:1;		/* power checked this run */
	int subseq;				/* sort within widget type */

	int (*power_check)(struct snd_soc_dapm_widget *w);

	/* external events */
	unsigned short event_flags;		/* flags to specify event types */
	int (*event)(struct snd_soc_dapm_widget*, struct snd_kcontrol *, int);

	/* kcontrols that relate to this widget */
	int num_kcontrols;
	const struct snd_kcontrol_new *kcontrol_news;
	struct snd_kcontrol **kcontrols;

	/* widget input and outputs */
	struct list_head sources;
	struct list_head sinks;

	/* used during DAPM updates */
	struct list_head power_list;
	struct list_head dirty;
	int inputs;
	int outputs;

	struct clk *clk;
};

6.1.4.4 struct snd_soc_dapm_route 结构体
@ \kernel\msm-3.18\include\sound\soc-dapm.h

struct snd_soc_dapm_route {
	const char *sink;
	const char *control;
	const char *source;

	/* Note: currently only supported for links where source is a supply */
	int (*connected)(struct snd_soc_dapm_widget *source,
			 struct snd_soc_dapm_widget *sink);
};

6.1.4.5 struct snd_soc_dapm_context 结构体

dapm 上下文环境变量

@ \kernel\msm-3.18\include\sound\soc-dapm.h

/* DAPM context */
struct snd_soc_dapm_context {
	enum snd_soc_bias_level bias_level;
	enum snd_soc_bias_level suspend_bias_level;
	struct delayed_work delayed_work;
	unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
	/* Go to BIAS_OFF in suspend if the DAPM context is idle */
	unsigned int suspend_bias_off:1;
	void (*seq_notifier)(struct snd_soc_dapm_context *,
			     enum snd_soc_dapm_type, int);

	struct device *dev; /* from parent - for debug */
	struct snd_soc_component *component; /* parent component */
	struct snd_soc_card *card; /* parent card */

	/* used during DAPM updates */
	enum snd_soc_bias_level target_bias_level;
	struct list_head list;

	int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
	int (*set_bias_level)(struct snd_soc_dapm_context *dapm,
			      enum snd_soc_bias_level level);

#ifdef CONFIG_DEBUG_FS
	struct dentry *debugfs_dapm;
#endif
};


6.1.5 struct snd_soc_pcm_runtime 结构体

snd_pcm_runtime是pcm运行时的信息。当打开一个pcm子流时,pcm运行时实例就会分配给这个子流。它拥有很多多种信息:hw_params和sw_params配置拷贝,缓冲区指针,mmap记录,自旋锁等。snd_pcm_runtime对于驱动程序操作集函数是只读的,仅pcm中间层可以改变或更新这些信息。

@ \src\kernel\msm-3.18\include\sound\soc.h
	
/* 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;	// snd_soc_dai_link 结构体
	struct mutex pcm_mutex;
	enum snd_soc_pcm_subclass pcm_subclass;
	struct snd_pcm_ops ops;		// snd_pcm_ops  pcm文件的操作方法,包括 打开,读,写等方法

	unsigned int dev_registered:1;

	/* Dynamic PCM BE runtime data */
	struct snd_soc_dpcm_runtime dpcm[2];
	int fe_compr;

	long pmdown_time;
	unsigned char pop_wait:1;

	/* err in case of ops failed */
	int err_ops;
	/* runtime devices */
	struct snd_pcm *pcm;		// snd_pcm 		
	struct snd_compr *compr;
	struct snd_soc_codec *codec;
	struct snd_soc_platform *platform;
	struct snd_soc_dai *codec_dai;
	struct snd_soc_dai *cpu_dai;
	struct snd_soc_component *component; /* Only valid for AUX dev rtds */

	struct snd_soc_dai **codec_dais;
	unsigned int num_codecs;

	struct delayed_work delayed_work;
#ifdef CONFIG_DEBUG_FS
	struct dentry *debugfs_dpcm_root;
	struct dentry *debugfs_dpcm_state;
#endif
};

6.1.5.1 snd_pcm_ops PCM设备文件结操作方法 构体

PCM 的字符设备文件操作方法结构体

@ \kernel\msm-3.18\include\sound\pcm.h
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 (*compat_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);
	int (*delay_blk)(struct snd_pcm_substream *substream);
	int (*wall_clock)(struct snd_pcm_substream *substream,
			  struct timespec *audio_ts);
	int (*copy)(struct snd_pcm_substream *substream, int channel,
		    snd_pcm_uframes_t pos,
		    void __user *buf, snd_pcm_uframes_t count);
	int (*silence)(struct snd_pcm_substream *substream, int channel,
		       snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
	struct page *(*page)(struct snd_pcm_substream *substream,
			     unsigned long offset);
	int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
	int (*ack)(struct snd_pcm_substream *substream);
	int (*restart)(struct snd_pcm_substream *substream);
};

6.1.5.2 snd_soc_dpcm_runtime 结构体
@ \kernel\msm-3.18\include\sound\soc-dpcm.h
/*
 * Dynamic PCM runtime data.
 */
struct snd_soc_dpcm_runtime {
	struct list_head be_clients;
	struct list_head fe_clients;

	int users;
	struct snd_pcm_runtime *runtime;
	struct snd_pcm_hw_params hw_params;

	/* state and update */
	enum snd_soc_dpcm_update runtime_update;
	enum snd_soc_dpcm_state state;

	int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */
};

6.1.5.3 struct snd_pcm 结构体
@ \kernel\msm-3.18\include\sound\pcm.h
struct snd_pcm {
	struct snd_card *card;
	struct list_head list;
	int device; /* device number */
	unsigned int info_flags;
	unsigned short dev_class;
	unsigned short dev_subclass;
	char id[64];
	char name[80];
	struct snd_pcm_str streams[2];
	struct mutex open_mutex;
	wait_queue_head_t open_wait;
	void *private_data;
	void (*private_free) (struct snd_pcm *pcm);
	struct device *dev; /* actual hw device this belongs to */
	bool internal; /* pcm is for internal use only */
	bool nonatomic; /* whole PCM operations are in non-atomic context */
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
	struct snd_pcm_oss oss;
#endif
};

6.1.5.4 struct snd_compr 结构体

dsp 描述结构体

@ \kernel\msm-3.18\include\sound\compress_driver.h
/**
 * struct snd_compr: Compressed device
 * @name: DSP device name
 * @dev: Device pointer
 * @ops: pointer to DSP callbacks
 * @private_data: pointer to DSP pvt data
 * @card: sound card pointer
 * @direction: Playback or capture direction
 * @lock: device lock
 * @device: device id
 */
struct snd_compr {
	const char *name;
	struct device *dev;
	struct snd_compr_ops *ops;
	void *private_data;
	struct snd_card *card;
	unsigned int direction;
	struct mutex lock;
	int device;
};

6.1.5.5 struct snd_soc_platform 结构体
@ \kernel\msm-3.18\include\sound\soc.h

struct snd_soc_platform {
	struct device *dev;
	const struct snd_soc_platform_driver *driver;

	unsigned int suspended:1; /* platform is suspended */

	struct list_head list;

	struct snd_soc_component component;
};

6.1.5.6 struct snd_soc_component 结构体
@ \kernel\msm-3.18\include\sound\soc.h
struct snd_soc_component {
	const char *name;
	int id;
	const char *name_prefix;
	struct device *dev;
	struct snd_soc_card *card;

	unsigned int active;

	unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
	unsigned int registered_as_component:1;
	unsigned int probed:1;

	struct list_head list;

	struct snd_soc_dai_driver *dai_drv;
	int num_dai;

	const struct snd_soc_component_driver *driver;

	struct list_head dai_list;

	int (*read)(struct snd_soc_component *, unsigned int, unsigned int *);
	int (*write)(struct snd_soc_component *, unsigned int, unsigned int);

	struct regmap *regmap;
	int val_bytes;

	struct mutex io_mutex;

#ifdef CONFIG_DEBUG_FS
	struct dentry *debugfs_root;
#endif

	/*
	* DO NOT use any of the fields below in drivers, they are temporary and
	* are going to be removed again soon. If you use them in driver code the
	* driver will be marked as BROKEN when these fields are removed.
	*/

	/* Don't use these, use snd_soc_component_get_dapm() */
	struct snd_soc_dapm_context dapm;
	struct snd_soc_dapm_context *dapm_ptr;

	const struct snd_kcontrol_new *controls;
	unsigned int num_controls;
	const struct snd_soc_dapm_widget *dapm_widgets;
	unsigned int num_dapm_widgets;
	const struct snd_soc_dapm_route *dapm_routes;
	unsigned int num_dapm_routes;
	struct snd_soc_codec *codec;

	int (*probe)(struct snd_soc_component *);
	void (*remove)(struct snd_soc_component *);

#ifdef CONFIG_DEBUG_FS
	void (*init_debugfs)(struct snd_soc_component *component);
	const char *debugfs_prefix;
#endif
};

6.1.6 struct snd_soc_dai_link 结构体

在 snd_soc_dai_link 中没有实际的操作 方法,其充当的角色更多的是一个媒介的作用,
通过它,就能够找到对应的platform ,codec dai ,codec,CPU, cpu dai等。

在其结构体中,比较重要的

@\kernel\msm-3.18\include\sound\soc.h

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;		// CPU 的名字
	struct device_node *cpu_of_node;	// cpu 的dts 节点
	/*
	 * 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;  // Cpu dai 的名字
	/*
	 * You MUST specify the link's codec, either by device name, or by
	 * DT/OF node, but not both.
	 */
	const char *codec_name;		// codec 名字
	struct device_node *codec_of_node;	// codec 节点
	/* You MUST specify the DAI name within the codec */
	const char *codec_dai_name;	// codec dai 的名字

	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;	// platform 的名字
	struct device_node *platform_of_node;	// platform 的dts 节点
	int be_id;	/* optional ID for machine driver BE identification */

	const struct snd_soc_pcm_stream *params;	// playbakc 和 capture 的参数

	unsigned int dai_fmt;           /* format to set on init */

	enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */

	/* Keep DAI active over suspend */
	unsigned int ignore_suspend:1;	// 永不休眠

	/* Symmetry requirements */
	unsigned int symmetric_rates:1;
	unsigned int symmetric_channels:1;
	unsigned int symmetric_samplebits:1;

	/* Do not create a PCM for this DAI link (Backend link) */
	unsigned int no_pcm:1;

	/* This DAI link can route to other DAI links at runtime (Frontend)*/
	unsigned int dynamic:1;

	/* This DAI can support no host IO (no pcm data is copied to from host) */
	unsigned int no_host_mode:2;

	/* DPCM capture and Playback support */
	unsigned int dpcm_capture:1;
	unsigned int dpcm_playback:1;

	/* pmdown_time is ignored at stop */
	unsigned int ignore_pmdown_time:1;

	/* codec/machine specific init - e.g. add machine controls */
	int (*init)(struct snd_soc_pcm_runtime *rtd);	// 初始化方法

	/* optional hw_params re-writing for BE and FE sync */
	// 重新设置 硬件参数的方法
	int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params);

	/* machine stream operations */
	const struct snd_soc_ops *ops;
	const struct snd_soc_compr_ops *compr_ops;

	/* For unidirectional dai links */
	bool playback_only;
	bool capture_only;

	/* this value determines what all ops can be started asynchronously */
	enum snd_soc_async_ops async_ops;
};

6.1.6.1 struct snd_soc_dai_link_component 结构体
struct snd_soc_dai_link_component {
	const char *name;
	const struct device_node *of_node;
	const char *dai_name;
};


6.2 Codec 相关结构体关系梳理

本来想详细整理学习下Audio 的结构体,
但写到后面发现,发现功力远远还不够,以致于在 6.1 中,后面挺多结构体都写不明白。

这里给未来的自已留个作业,等后面真的对Audio 有更深入的了解后,
再重新回来,查询梳理 Audio 各大结构体之间的关系。

Date:2019/09/22 - 14:21




参考博文:
https://blog.csdn.net/azloong/article/details/6146378

谢谢

你可能感兴趣的:(Android,Audio)