Linux 音频 ALSA 机制学习笔记<一>
首先宏观看内核暴露给上层的接口:
root@android:/ # cat /dev/snd/
controlC0 pcmC0D10p pcmC0D13c pcmC0D15c pcmC0D2c pcmC0D3c pcmC0D5p pcmC0D8c
pcmC0D0c pcmC0D11p pcmC0D13p pcmC0D15p pcmC0D2p pcmC0D3p pcmC0D6c pcmC0D9c
pcmC0D0p pcmC0D12c pcmC0D14c pcmC0D1c pcmC0D31c pcmC0D4p pcmC0D6p pcmC0D9p
pcmC0D10c pcmC0D12p pcmC0D14p pcmC0D1p pcmC0D32p pcmC0D5c pcmC0D7p timer
主要由 control 与许多 pcm 设备组成,其中控制类 control 接口是通过 get 与 put 来实现上层与内核的交互的;
而 pcm 接口主要是实现音频数据流的,其组成 C0 表示 0 号声卡,最后面的 c 表示 capture p 表示 palyback,D 后面表示 pcm 设备号。
为什么 pcm 有这么多的设备号?原因是 dsp 底层通道不一样。必须在我们平台上 audio speaker 打开 pcmC0D14p,audio handset 打开
pcmC0D12p。为什么设备号 0-32 有的没有?原因是有的前端 dsi links 定义了.no_pcm = 1 这样就不会注册 pcm。
static struct snd_soc_dai_link msm_dai[] = {
/* FrontEnd DAI Links */
{
.name = "MSM8960 Media1",
.stream_name = "MultiMedia1",
.cpu_dai_name = "MultiMedia1",
.platform_name = "msm-pcm-dsp",
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.ignore_suspend = 1,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
},
-----------
{
.name = LPASS_BE_SLIMBUS_0_TX,
.stream_name = "Slimbus Capture",
.cpu_dai_name = "msm-dai-q6.16385",
.platform_name = "msm-pcm-routing",
.codec_name = "tabla_codec",
.codec_dai_name = "tabla_tx1",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
.ops = &msm_be_ops,
},
-----------
};
注意在 snd_soc_dai_link 中 的 platform_name,最终 pcm 数据流是通过 platform_name 对应的平台驱动将数据流发送到最底层的。在平台驱
动需要实现 pcm 数据流接口:
static struct snd_pcm_ops msm_pcm_ops = {
.open = msm_pcm_open,
.copy = msm_pcm_copy,
.hw_params = msm_pcm_hw_params,
.close = msm_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.prepare = msm_pcm_prepare,
.trigger = msm_pcm_trigger,
.pointer = msm_pcm_pointer,
.mmap = msm_pcm_mmap,
};
下面重点说 kcontrol 以及如何与上层交互:
<一>直接注册 kcontrol,这类 kcontrol 重点是实现更改寄存器的值:
static const struct snd_kcontrol_new tabla_snd_controls[] = {
-------------
SOC_ENUM_EXT("EAR PA Gain", tabla_ear_pa_gain_enum[0],
tabla_pa_gain_get, tabla_pa_gain_put),
SOC_SINGLE_TLV("LINEOUT1 Volume", TABLA_A_RX_LINE_1_GAIN, 0, 12, 1,
line_gain),
--------------
};
static struct snd_soc_codec_driver soc_codec_dev_tabla = {
--------
.controls = tabla_snd_controls,
.num_controls = ARRAY_SIZE(tabla_snd_controls),
---------
评论0