我是靠谱客的博主 狂野纸鹤,这篇文章主要介绍声卡注册流程(linux-5.4),现在分享给大家,希望可以做个参考。

结构体介绍

先介绍声卡相关结构体

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
struct asoc_simple_priv { struct snd_soc_card snd_card; struct simple_dai_props { struct asoc_simple_dai *cpu_dai; struct asoc_simple_dai *codec_dai; struct snd_soc_dai_link_component cpus; /* single cpu */ struct snd_soc_dai_link_component codecs; /* single codec */ struct snd_soc_dai_link_component platforms; struct asoc_simple_data adata; struct snd_soc_codec_conf *codec_conf; bool mclk_fp; unsigned int mclk_fs; unsigned int cpu_pll_fs; unsigned int codec_pll_fs; } *dai_props; struct asoc_simple_jack hp_jack; struct asoc_simple_jack mic_jack; struct snd_soc_dai_link *dai_link; struct asoc_simple_dai *dais; struct snd_soc_codec_conf *codec_conf; struct gpio_desc *pa_gpio; }; struct snd_soc_card { const char *name; const char *long_name; const char *driver_name; char dmi_longname[80]; char topology_shortname[32]; struct device *dev; struct snd_card *snd_card; struct module *owner; struct mutex mutex; struct mutex dapm_mutex; /* Mutex for PCM operations */ struct mutex pcm_mutex; enum snd_soc_pcm_subclass pcm_subclass; spinlock_t dpcm_lock; bool instantiated; bool topology_shortname_created; int (*probe)(struct snd_soc_card *card); 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); int (*add_dai_link)(struct snd_soc_card *, struct snd_soc_dai_link *link); void (*remove_dai_link)(struct snd_soc_card *, struct snd_soc_dai_link *link); long pmdown_time; /* CPU <--> Codec DAI links */ struct snd_soc_dai_link *dai_link; /* predefined links only */ int num_links; /* predefined links only */ struct list_head dai_link_list; /* all links */ struct list_head rtd_list; int num_rtd; /* 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 list_head aux_comp_list; const struct snd_kcontrol_new *controls; int num_controls; /* * Card-specific routes and widgets. * Note: of_dapm_xxx for Device Tree; Otherwise for driver build-in. */ const struct snd_soc_dapm_widget *dapm_widgets; int num_dapm_widgets; const struct snd_soc_dapm_route *dapm_routes; int num_dapm_routes; const struct snd_soc_dapm_widget *of_dapm_widgets; int num_of_dapm_widgets; const struct snd_soc_dapm_route *of_dapm_routes; int num_of_dapm_routes; bool fully_routed; bool disable_route_checks; /* lists of probed devices belonging to this card */ struct list_head component_dev_list; struct list_head list; struct list_head widgets; struct list_head paths; struct list_head dapm_list; struct list_head dapm_dirty; /* attached dynamic objects */ struct list_head dobj_list; /* Generic DAPM context for the card */ 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; #endif #ifdef CONFIG_PM_SLEEP struct work_struct deferred_resume_work; #endif u32 pop_time; void *drvdata; ANDROID_KABI_RESERVE(1); ANDROID_KABI_RESERVE(2); ANDROID_KABI_RESERVE(3); ANDROID_KABI_RESERVE(4); }; struct snd_card { int number; /* number of soundcard (index to snd_cards) */ char id[16]; /* id string of this card */ char driver[16]; /* driver name */ char shortname[32]; /* short name of this soundcard */ char longname[80]; /* name of this soundcard */ char irq_descr[32]; /* Interrupt description */ char mixername[80]; /* mixer name */ char components[128]; /* card components delimited with space */ struct module *module; /* top-level module */ void *private_data; /* private data for soundcard */ void (*private_free) (struct snd_card *card); /* callback for freeing of private data */ struct list_head devices; /* devices */ struct device ctl_dev; /* control device */ unsigned int last_numid; /* last used numeric ID */ struct rw_semaphore controls_rwsem; /* controls list lock */ rwlock_t ctl_files_rwlock; /* ctl_files list lock */ int controls_count; /* count of all controls */ int user_ctl_count; /* count of all user controls */ struct list_head controls; /* all controls for this card */ struct list_head ctl_files; /* active control files */ struct snd_info_entry *proc_root; /* root for soundcard specific files */ struct proc_dir_entry *proc_root_link; /* number link to real id */ struct list_head files_list; /* all files associated to this card */ struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown state */ spinlock_t files_lock; /* lock the files for this card */ int shutdown; /* this card is going down */ struct completion *release_completion; struct device *dev; /* device assigned to this card */ struct device card_dev; /* cardX object for sysfs */ const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */ bool registered; /* card_dev is registered? */ wait_queue_head_t remove_sleep; #ifdef CONFIG_PM unsigned int power_state; /* power state */ wait_queue_head_t power_sleep; #endif #if IS_ENABLED(CONFIG_SND_MIXER_OSS) struct snd_mixer_oss *mixer_oss; int mixer_oss_change_count; #endif ANDROID_KABI_RESERVE(1); ANDROID_KABI_RESERVE(2); };

可以看出,三个结构体的大致内容:

asoc_simple_priv:

  1. 属于该结构体的snd_soc_card

  2. dai相关

  3. 时钟相关

  4. 耳机、麦克风拔插相关

  5. 功放相关

snd_soc_card:

  1. snd_soc_card的基本信息

  2. 属于该结构体的snd_card

  3. 各种mutex(PCM、DAPM等)

  4. 电源管理相关的操作函数

  5. 回调函数(DAPM、DAI LINK)

  6. DAPM、DAI LINK相关

snd_card:

  1. 声卡的基本信息

  2. 属于该声卡的control设备

  3. proc文件系统的相关配置

  4. sys文件系统的相关配置

流程介绍

probe()

  1. 为asoc_simple_priv分配空间并初始化 --- devm_kzalloc_priv() asoc_simple_init_priv()

  2. 判断pdev->dev的status是否为okay --- of_device_is_available()

  3. 最后跳到进行声卡注册 --- devm_snd_soc_register_card()
    3.1 snd_soc_register_card() --- 初始化card里的内核链表以及mutex,
         3.1.1 然后return snd_soc_bind_card()

snd_soc_bind_card()

  1. 实例化snd_soc_card --- snd_soc_instantiate_card()

snd_soc_instantiate_card()

  1. 初始化snd_soc_dai_link结构体(关于dai匹配)--- soc_init_dai_link()

  2. 初始化dapm,并把dapm->list加到card->dapm_list里面 --- snd_soc_dapm_init()

  3. 绑定dai link--- soc_bind_dai_link()
    3.1 soc_new_pcm_runtime() --- 初始化rtd(该结构体与绑定codec和platform有关)
    3.2 通过snd_soc_find_dai() 和 snd_soc_rtdcom_add()来拿到已经注册的codec和platform并添加到rtd
    3.3 通过soc_add_pcm_runtime()将rtd添加到card

  4. 绑定aux设备(耳机口),也是从component list中找到再给card --- soc_bind_aux_dev()

  5. 都完成都开始创建声卡 --- snd_card_new()

  6. 初始化dubugfs --- soc_init_card_debugfs()

  7. 初始化dapm部分 --- snd_soc_dapm_new_controls()

  8. 初始化声卡(仅一次)--- card->probe

  9. 初始化所有dai用到的component --- soc_probe_link_components()

  10. 初始化所有aux设备 --- soc_probe_aux_devices()

  11. 初始化dai links的时候可能会添加新的dais和dai links,所以还需要再进行一次1和3

  12. 初始化所有的dai link --- soc_probe_link_dais()

  13. 创建、添加PCM设备 --- soc_link_init()

  14. 连接dapm --- snd_soc_dapm_link_dai_widgets() snd_soc_dapm_connect_dai_link_widgets()

  15. 注册control设备 --- snd_soc_add_card_controls()

  16. 注册dapm的route --- snd_soc_dapm_add_routes()

  17. 注册设备树的dapm的route --- snd_soc_dapm_add_routes()

  18. 尝试设置dmi_name --- snd_soc_set_dmi_name()

  19. 设置snd_card->name --- snprintf(card->snd_card->**name, ...)

  20. 执行后部分初始化 --- card->late_probe()

  21. 注册dapm_widget --- snd_soc_dapm_new_widgets()

  22. 注册声卡 --- snd_card_register(card->snd_card)

  23. 检查所有dapm尾指针 --- dapm_mark_endpoints_dirty() snd_soc_dapm_sync()

snd_card_register()

  1. 注册声卡设备 --- device_add(&card->card_dev)

  2. 注册所属声卡的所有设备 --- snd_device_register_all()

  3. 通过 if 判断声卡是否已经注册 --- snd_cards[card->num]

  4. 设置card->id --- snd_card_set_id_no_lock()

  5. 加入到snd_cards[ ]中 --- snd_card[card->num] = card

  6. 注册card的proc文件--- snd_info_card_register()

最后

以上就是狂野纸鹤最近收集整理的关于声卡注册流程(linux-5.4)的全部内容,更多相关声卡注册流程(linux-5内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(86)

评论列表共有 0 条评论

立即
投稿
返回
顶部