高通音频驱动录音流程(二)
Front End CPU的注册
Front End CPU DAI的注册,与传统的CPU DAI注册类似,不过增加了aif_name的定义,它与vendor/qcom/opensource/audio-kernel/asoc/msm-pcm-routing-v2.c中的定义SND_SOC_DAPM_AIF_OUT(“MM_UL1”, “MultiMedia1 Capture”, 0, 0, 0, 0)是对应的,在这个fe_dai被probe时,调用fe_dai_probe,会动态的创建一个path,以便在open/close fe的stream时,对be的route进行动态的上下电。
38static int fe_dai_probe(struct snd_soc_dai *dai)
39{
40 struct snd_soc_dapm_route intercon;
41 struct snd_soc_dapm_context *dapm;
42
43 if (!dai || !dai->driver) {
44 pr_err("%s invalid params\n", __func__);
45 return -EINVAL;
46 }
47 dapm = snd_soc_component_get_dapm(dai->component);
48 memset(&intercon, 0, sizeof(intercon));
49 if (dai->driver->playback.stream_name &&
50 dai->driver->playback.aif_name) {
51 dev_dbg(dai->dev, "%s add route for widget %s",
52 __func__, dai->driver->playback.stream_name);
53 intercon.source = dai->driver->playback.stream_name;
54 intercon.sink = dai->driver->playback.aif_name;
55 dev_dbg(dai->dev, "%s src %s sink %s\n",
56 __func__, intercon.source, intercon.sink);
57 snd_soc_dapm_add_routes(dapm, &intercon, 1);
58 snd_soc_dapm_ignore_suspend(dapm, intercon.source);
59 }
60 if (dai->driver->capture.stream_name &&
61 dai->driver->capture.aif_name) {
62 dev_dbg(dai->dev, "%s add route for widget %s",
63 __func__, dai->driver->capture.stream_name);
64 intercon.sink = dai->driver->capture.stream_name;
65 intercon.source = dai->driver->capture.aif_name;
66 dev_dbg(dai->dev, "%s src %s sink %s\n",
67 __func__, intercon.source, intercon.sink);
68 snd_soc_dapm_add_routes(dapm, &intercon, 1);
69 snd_soc_dapm_ignore_suspend(dapm, intercon.sink);
70 }
71 return 0;
72}
74static struct snd_soc_dai_ops msm_fe_Multimedia_dai_ops = {
75 .startup = multimedia_startup,
76};
77
78static const struct snd_soc_component_driver msm_fe_dai_component = {
79 .name = "msm-dai-fe",
80};
81
82static struct snd_soc_dai_driver msm_fe_dais[] = {
83 {
98 .capture = {
99 .stream_name = "MultiMedia1 Capture",
100 .aif_name = "MM_UL1",
101 .rates = (SNDRV_PCM_RATE_8000_384000|
102 SNDRV_PCM_RATE_KNOT),
103 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
104 SNDRV_PCM_FMTBIT_S24_LE |
105 SNDRV_PCM_FMTBIT_S24_3LE |
106 SNDRV_PCM_FMTBIT_S32_LE),
107 .channels_min = 1,
108 .channels_max = 32,
109 .rate_min = 8000,
110 .rate_max = 48000,
111 },
112 .ops = &msm_fe_Multimedia_dai_ops,
113 .name = "MultiMedia1",
114 .probe = fe_dai_probe,
115 },
3150static void snd_soc_component_add(struct snd_soc_component *component)
3151{
3152 mutex_lock(&client_mutex);
3153
3154 if (!component->driver->write && !component->driver->read) {
3155 if (!component->regmap)
3156 component->regmap = dev_get_regmap(component->dev, NULL);
3157 if (component->regmap)
3158 snd_soc_component_setup_regmap(component);
3159 }
3160
3161 list_add(&component->list, &component_list);
3162 INIT_LIST_HEAD(&component->dobj_list);
3163
3164 mutex_unlock(&client_mutex);
3165}
3255int snd_soc_register_component(struct device *dev,
3256 const struct snd_soc_component_driver *component_driver,
3257 struct snd_soc_dai_driver *dai_drv,
3258 int num_dai)
3259{
3260 struct snd_soc_component *component;
3261
3262 component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL);
3263 if (!component)
3264 return -ENOMEM;
3265
3266 return snd_soc_add_component(dev, component, component_driver,
3267 dai_drv, num_dai);
3268}
snd_soc_register_component函数调用后,所有的cpu_dai绑定在component->dai_list,这个component绑定在component_list。
其中codec与PCM驱动注册与上面的类似,就不详细介绍了。
Front End Codec注册
kernel/msm-4.19/sound/soc/soc-utils.c
注册完成后,cpu_dai绑定在component->dai_list,component->driver指向component_driver,这个component绑定在component_list。
Front End PCM的注册
vendor/qcom/opensource/audio-kernel/asoc/msm-pcm-q6-v2.c
注册完成后,component->driver指向component_driver,这个component绑定在component_list,在pcm驱动probe时,所有的kcontrol绑定到card->controls。