我们先来看看数字音频接口做了什么?
以下具体的就是就是音频接口的操作,根据PCM音频和playback来进行设置
同时,也加载了alc5623_dai_ops这个操作集合
static struct snd_soc_dai_driver alc5623_dai = {
.name = "alc5623-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
.rate_max = 48000,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = ALC5623_FORMATS,},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
.rate_max = 48000,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = ALC5623_FORMATS,},
.ops = &alc5623_dai_ops,
};
(1)alc5623_dai_ops操作集合的实现
以下这些得找具体的调音频的工程师才知道怎么设置相应的操作,具体我也不是特别懂,有兴趣可以看看函数的实现,对着数据手册的寄存器一个个看
static struct snd_soc_dai_ops alc5623_dai_ops = {
.hw_params = alc5623_pcm_hw_params,
.digital_mute = alc5623_mute,
.set_fmt = alc5623_set_dai_fmt,
.set_sysclk = alc5623_set_dai_sysclk,
.set_pll = alc5623_set_dai_pll,
};
(2)soc_codec_device_alc5623
static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
.probe = alc5623_probe,
.remove = alc5623_remove,
.suspend = alc5623_suspend, // 1
.resume = alc5623_resume, // 2 1和2是电源管理的回调函数,分别在声卡加载和卸载的时候被调用
.set_bias_level = alc5623_set_bias_level, //设置偏置电压配置函数
.reg_cache_size = ALC5623_VENDOR_ID2+2,
.reg_word_size = sizeof(u16),
.reg_cache_step = 2,
};
<1> alc5623_probe函数分析
//这部分我们不详细进行分析,拿出最主要的东西来讲,比如后面的snd_soc_add_codec_controls,主要说说它的作用
static int alc5623_probe(struct snd_soc_codec *codec)
{
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); //获取数据
struct snd_soc_dapm_context *dapm = &codec->dapm; //dapm相当于音频的一个组件
int ret;
ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
alc5623_reset(codec); //复位芯片
alc5623_fill_cache(codec);
/* power on device */
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
if (alc5623->add_ctrl) {
snd_soc_write(codec, ALC5623_ADD_CTRL_REG,
alc5623->add_ctrl);
}
if (alc5623->jack_det_ctrl) {
snd_soc_write(codec, ALC5623_JACK_DET_CTRL,
alc5623->jack_det_ctrl);
}
//根据芯片的id执行对应的snd_soc_add_codec_controls,这个controls就是给上层提供相应的操作接口
//比如调节音量,耳机模式等等。
//这里是alc5621,我们找到了这个controls的集合
switch (alc5623->id) {
case 0x21:
snd_soc_add_codec_controls(codec, alc5621_vol_snd_controls,
ARRAY_SIZE(alc5621_vol_snd_controls));
break;
case 0x22:
snd_soc_add_codec_controls(codec, alc5622_vol_snd_controls,
ARRAY_SIZE(alc5622_vol_snd_controls));
break;
case 0x23:
snd_soc_add_codec_controls(codec, alc5623_vol_snd_controls,
ARRAY_SIZE(alc5623_vol_snd_controls));
break;
default:
return -EINVAL;
}
snd_soc_add_codec_controls(codec, alc5623_snd_controls,
ARRAY_SIZE(alc5623_snd_controls));
snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets,
ARRAY_SIZE(alc5623_dapm_widgets));
/* set up audio path interconnects */
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));