blob: 7efcf3475d6f92aa380874bc5bb75c4cb49b755b [file] [log] [blame]
Kuninori Morimoto873486e2018-07-02 06:24:18 +00001// SPDX-License-Identifier: GPL-2.0+
2//
3// soc-core.c -- ALSA SoC Audio Layer
4//
5// Copyright 2005 Wolfson Microelectronics PLC.
6// Copyright 2005 Openedhand Ltd.
7// Copyright (C) 2010 Slimlogic Ltd.
8// Copyright (C) 2010 Texas Instruments Inc.
9//
10// Author: Liam Girdwood <lrg@slimlogic.co.uk>
11// with code, comments and ideas from :-
12// Richard Purdie <richard@openedhand.com>
13//
14// TODO:
15// o Add hw rules to enforce rates, etc.
16// o More testing with other codecs/machines.
17// o Add more codecs and platforms to ensure good API coverage.
18// o Support TDM on PCM and I2S
Frank Mandarinodb2a4162006-10-06 18:31:09 +020019
20#include <linux/module.h>
21#include <linux/moduleparam.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/pm.h>
25#include <linux/bitops.h>
Troy Kisky12ef1932008-10-13 17:42:14 -070026#include <linux/debugfs.h>
Frank Mandarinodb2a4162006-10-06 18:31:09 +020027#include <linux/platform_device.h>
Markus Pargmann741a5092013-08-19 17:05:55 +020028#include <linux/pinctrl/consumer.h>
Mark Brownf0e8ed82011-09-20 11:41:54 +010029#include <linux/ctype.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090030#include <linux/slab.h>
Stephen Warrenbec4fa02011-12-12 15:55:34 -070031#include <linux/of.h>
Kuninori Morimotoa180e8b2017-05-18 01:39:25 +000032#include <linux/of_graph.h>
Liam Girdwood345233d2017-01-14 16:13:02 +080033#include <linux/dmi.h>
Frank Mandarinodb2a4162006-10-06 18:31:09 +020034#include <sound/core.h>
Mark Brown3028eb82010-12-05 12:22:46 +000035#include <sound/jack.h>
Frank Mandarinodb2a4162006-10-06 18:31:09 +020036#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/soc.h>
Liam Girdwood01d75842012-04-25 12:12:49 +010039#include <sound/soc-dpcm.h>
Liam Girdwood8a978232015-05-29 19:06:14 +010040#include <sound/soc-topology.h>
Frank Mandarinodb2a4162006-10-06 18:31:09 +020041#include <sound/initval.h>
42
Mark Browna8b1d342010-11-03 18:05:58 -040043#define CREATE_TRACE_POINTS
44#include <trace/events/asoc.h>
45
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000046#define NAME_SIZE 32
47
Mark Brown384c89e2008-12-03 17:34:03 +000048#ifdef CONFIG_DEBUG_FS
Mark Brown8a9dab12011-01-10 22:25:21 +000049struct dentry *snd_soc_debugfs_root;
50EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
Mark Brown384c89e2008-12-03 17:34:03 +000051#endif
52
Mark Brownc5af3a22008-11-28 13:29:45 +000053static DEFINE_MUTEX(client_mutex);
Kuninori Morimoto030e79f2013-03-11 18:27:21 -070054static LIST_HEAD(component_list);
Srinivas Kandagatlae894efe2018-09-12 10:15:00 +010055static LIST_HEAD(unbind_card_list);
Mark Brownc5af3a22008-11-28 13:29:45 +000056
Frank Mandarinodb2a4162006-10-06 18:31:09 +020057/*
58 * This is a timeout to do a DAPM powerdown after a stream is closed().
59 * It can be used to eliminate pops between different playback streams, e.g.
60 * between two audio tracks.
61 */
62static int pmdown_time = 5000;
63module_param(pmdown_time, int, 0);
64MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
65
Mengdong Lin98faf432017-06-28 15:01:39 +080066/* If a DMI filed contain strings in this blacklist (e.g.
67 * "Type2 - Board Manufacturer" or "Type1 - TBD by OEM"), it will be taken
68 * as invalid and dropped when setting the card long name from DMI info.
69 */
70static const char * const dmi_blacklist[] = {
71 "To be filled by OEM",
72 "TBD by OEM",
73 "Default String",
74 "Board Manufacturer",
75 "Board Vendor Name",
76 "Board Product Name",
77 NULL, /* terminator */
78};
79
Mark Browndbe21402010-02-12 11:37:24 +000080static ssize_t pmdown_time_show(struct device *dev,
81 struct device_attribute *attr, char *buf)
82{
Mark Brown36ae1a92012-01-06 17:12:45 -080083 struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
Mark Browndbe21402010-02-12 11:37:24 +000084
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000085 return sprintf(buf, "%ld\n", rtd->pmdown_time);
Mark Browndbe21402010-02-12 11:37:24 +000086}
87
88static ssize_t pmdown_time_set(struct device *dev,
89 struct device_attribute *attr,
90 const char *buf, size_t count)
91{
Mark Brown36ae1a92012-01-06 17:12:45 -080092 struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
Mark Brownc593b522010-10-27 20:11:17 -070093 int ret;
Mark Browndbe21402010-02-12 11:37:24 +000094
Jingoo Hanb785a492013-07-19 16:24:59 +090095 ret = kstrtol(buf, 10, &rtd->pmdown_time);
Mark Brownc593b522010-10-27 20:11:17 -070096 if (ret)
97 return ret;
Mark Browndbe21402010-02-12 11:37:24 +000098
99 return count;
100}
101
102static DEVICE_ATTR(pmdown_time, 0644, pmdown_time_show, pmdown_time_set);
103
Takashi Iwaid29697d2015-01-30 20:16:37 +0100104static struct attribute *soc_dev_attrs[] = {
Takashi Iwaid29697d2015-01-30 20:16:37 +0100105 &dev_attr_pmdown_time.attr,
106 NULL
107};
108
109static umode_t soc_dev_attr_is_visible(struct kobject *kobj,
110 struct attribute *attr, int idx)
111{
112 struct device *dev = kobj_to_dev(kobj);
113 struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
114
115 if (attr == &dev_attr_pmdown_time.attr)
116 return attr->mode; /* always visible */
Kuninori Morimoto3b6eed8d2017-12-05 04:20:42 +0000117 return rtd->num_codecs ? attr->mode : 0; /* enabled only with codec */
Takashi Iwaid29697d2015-01-30 20:16:37 +0100118}
119
120static const struct attribute_group soc_dapm_dev_group = {
121 .attrs = soc_dapm_dev_attrs,
122 .is_visible = soc_dev_attr_is_visible,
123};
124
Mark Brownf7e73b262018-03-09 12:46:27 +0000125static const struct attribute_group soc_dev_group = {
Takashi Iwaid29697d2015-01-30 20:16:37 +0100126 .attrs = soc_dev_attrs,
127 .is_visible = soc_dev_attr_is_visible,
128};
129
130static const struct attribute_group *soc_dev_attr_groups[] = {
131 &soc_dapm_dev_group,
Mark Brownf7e73b262018-03-09 12:46:27 +0000132 &soc_dev_group,
Takashi Iwaid29697d2015-01-30 20:16:37 +0100133 NULL
134};
135
Mark Brown2624d5f2009-11-03 21:56:13 +0000136#ifdef CONFIG_DEBUG_FS
Lars-Peter Clausen81c7cfd2014-08-19 15:51:18 +0200137static void soc_init_component_debugfs(struct snd_soc_component *component)
Russell Kinge73f3de2014-06-26 15:22:50 +0100138{
Lars-Peter Clausen6553bf062015-04-09 10:52:38 +0200139 if (!component->card->debugfs_card_root)
140 return;
141
Lars-Peter Clausen81c7cfd2014-08-19 15:51:18 +0200142 if (component->debugfs_prefix) {
143 char *name;
Russell Kinge73f3de2014-06-26 15:22:50 +0100144
Lars-Peter Clausen81c7cfd2014-08-19 15:51:18 +0200145 name = kasprintf(GFP_KERNEL, "%s:%s",
146 component->debugfs_prefix, component->name);
147 if (name) {
148 component->debugfs_root = debugfs_create_dir(name,
149 component->card->debugfs_card_root);
150 kfree(name);
151 }
152 } else {
153 component->debugfs_root = debugfs_create_dir(component->name,
154 component->card->debugfs_card_root);
155 }
Russell Kinge73f3de2014-06-26 15:22:50 +0100156
Lars-Peter Clausen81c7cfd2014-08-19 15:51:18 +0200157 if (!component->debugfs_root) {
158 dev_warn(component->dev,
159 "ASoC: Failed to create component debugfs directory\n");
Mark Brown2624d5f2009-11-03 21:56:13 +0000160 return;
161 }
162
Lars-Peter Clausen81c7cfd2014-08-19 15:51:18 +0200163 snd_soc_dapm_debugfs_init(snd_soc_component_get_dapm(component),
164 component->debugfs_root);
Lars-Peter Clausen81c7cfd2014-08-19 15:51:18 +0200165}
166
167static void soc_cleanup_component_debugfs(struct snd_soc_component *component)
168{
169 debugfs_remove_recursive(component->debugfs_root);
170}
171
Peng Donglinc15b2a12018-02-14 22:48:07 +0800172static int dai_list_show(struct seq_file *m, void *v)
Mark Brownf3208782010-09-15 18:19:07 +0100173{
Lars-Peter Clausen1438c2f2014-03-09 17:41:47 +0100174 struct snd_soc_component *component;
Mark Brownf3208782010-09-15 18:19:07 +0100175 struct snd_soc_dai *dai;
176
Lars-Peter Clausen34e81ab2015-03-07 19:34:03 +0100177 mutex_lock(&client_mutex);
178
Donglin Peng700c17c2018-01-18 13:31:26 +0800179 list_for_each_entry(component, &component_list, list)
180 list_for_each_entry(dai, &component->dai_list, list)
181 seq_printf(m, "%s\n", dai->name);
Mark Brownf3208782010-09-15 18:19:07 +0100182
Lars-Peter Clausen34e81ab2015-03-07 19:34:03 +0100183 mutex_unlock(&client_mutex);
184
Donglin Peng700c17c2018-01-18 13:31:26 +0800185 return 0;
186}
Peng Donglinc15b2a12018-02-14 22:48:07 +0800187DEFINE_SHOW_ATTRIBUTE(dai_list);
Mark Brownf3208782010-09-15 18:19:07 +0100188
Kuninori Morimotodb795f92018-05-08 03:21:00 +0000189static int component_list_show(struct seq_file *m, void *v)
190{
191 struct snd_soc_component *component;
192
193 mutex_lock(&client_mutex);
194
195 list_for_each_entry(component, &component_list, list)
196 seq_printf(m, "%s\n", component->name);
197
198 mutex_unlock(&client_mutex);
199
200 return 0;
201}
202DEFINE_SHOW_ATTRIBUTE(component_list);
203
Jarkko Nikulaa6052152010-11-05 20:35:19 +0200204static void soc_init_card_debugfs(struct snd_soc_card *card)
205{
Lars-Peter Clausen6553bf062015-04-09 10:52:38 +0200206 if (!snd_soc_debugfs_root)
207 return;
208
Jarkko Nikulaa6052152010-11-05 20:35:19 +0200209 card->debugfs_card_root = debugfs_create_dir(card->name,
Mark Brown8a9dab12011-01-10 22:25:21 +0000210 snd_soc_debugfs_root);
Jarkko Nikula3a45b862010-11-05 20:35:21 +0200211 if (!card->debugfs_card_root) {
Jarkko Nikulaa6052152010-11-05 20:35:19 +0200212 dev_warn(card->dev,
Lothar Waßmann7c08be82011-12-09 14:16:29 +0100213 "ASoC: Failed to create card debugfs directory\n");
Jarkko Nikula3a45b862010-11-05 20:35:21 +0200214 return;
215 }
216
217 card->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644,
218 card->debugfs_card_root,
219 &card->pop_time);
220 if (!card->debugfs_pop_time)
221 dev_warn(card->dev,
Liam Girdwoodf110bfc2012-11-19 14:47:09 +0000222 "ASoC: Failed to create pop time debugfs file\n");
Jarkko Nikulaa6052152010-11-05 20:35:19 +0200223}
224
225static void soc_cleanup_card_debugfs(struct snd_soc_card *card)
226{
227 debugfs_remove_recursive(card->debugfs_card_root);
228}
229
Lars-Peter Clausen6553bf062015-04-09 10:52:38 +0200230static void snd_soc_debugfs_init(void)
231{
232 snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
Fabio Estevamd9a02c52017-08-07 09:08:53 -0300233 if (IS_ERR_OR_NULL(snd_soc_debugfs_root)) {
Lars-Peter Clausen6553bf062015-04-09 10:52:38 +0200234 pr_warn("ASoC: Failed to create debugfs directory\n");
235 snd_soc_debugfs_root = NULL;
236 return;
237 }
238
Lars-Peter Clausen6553bf062015-04-09 10:52:38 +0200239 if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL,
240 &dai_list_fops))
241 pr_warn("ASoC: Failed to create DAI list debugfs file\n");
Kuninori Morimotodb795f92018-05-08 03:21:00 +0000242
243 if (!debugfs_create_file("components", 0444, snd_soc_debugfs_root, NULL,
244 &component_list_fops))
245 pr_warn("ASoC: Failed to create component list debugfs file\n");
Lars-Peter Clausen6553bf062015-04-09 10:52:38 +0200246}
247
248static void snd_soc_debugfs_exit(void)
249{
250 debugfs_remove_recursive(snd_soc_debugfs_root);
251}
252
Mark Brown2624d5f2009-11-03 21:56:13 +0000253#else
254
Lars-Peter Clausen81c7cfd2014-08-19 15:51:18 +0200255static inline void soc_init_component_debugfs(
256 struct snd_soc_component *component)
Mark Brown2624d5f2009-11-03 21:56:13 +0000257{
258}
259
Lars-Peter Clausen81c7cfd2014-08-19 15:51:18 +0200260static inline void soc_cleanup_component_debugfs(
261 struct snd_soc_component *component)
Sebastien Guiriec731f1ab2012-02-15 15:25:31 +0000262{
263}
264
Axel Linb95fccb2010-11-09 17:06:44 +0800265static inline void soc_init_card_debugfs(struct snd_soc_card *card)
266{
267}
268
269static inline void soc_cleanup_card_debugfs(struct snd_soc_card *card)
270{
271}
Lars-Peter Clausen6553bf062015-04-09 10:52:38 +0200272
273static inline void snd_soc_debugfs_init(void)
274{
275}
276
277static inline void snd_soc_debugfs_exit(void)
278{
279}
280
Mark Brown2624d5f2009-11-03 21:56:13 +0000281#endif
282
Kuninori Morimotoa0ac4412017-08-08 06:17:47 +0000283static int snd_soc_rtdcom_add(struct snd_soc_pcm_runtime *rtd,
284 struct snd_soc_component *component)
285{
286 struct snd_soc_rtdcom_list *rtdcom;
287 struct snd_soc_rtdcom_list *new_rtdcom;
288
289 for_each_rtdcom(rtd, rtdcom) {
290 /* already connected */
291 if (rtdcom->component == component)
292 return 0;
293 }
294
295 new_rtdcom = kmalloc(sizeof(*new_rtdcom), GFP_KERNEL);
296 if (!new_rtdcom)
297 return -ENOMEM;
298
299 new_rtdcom->component = component;
300 INIT_LIST_HEAD(&new_rtdcom->list);
301
302 list_add_tail(&new_rtdcom->list, &rtd->component_list);
303
304 return 0;
305}
306
307static void snd_soc_rtdcom_del_all(struct snd_soc_pcm_runtime *rtd)
308{
309 struct snd_soc_rtdcom_list *rtdcom1, *rtdcom2;
310
311 for_each_rtdcom_safe(rtd, rtdcom1, rtdcom2)
312 kfree(rtdcom1);
313
314 INIT_LIST_HEAD(&rtd->component_list);
315}
316
317struct snd_soc_component *snd_soc_rtdcom_lookup(struct snd_soc_pcm_runtime *rtd,
318 const char *driver_name)
319{
320 struct snd_soc_rtdcom_list *rtdcom;
321
Kuninori Morimoto971da242018-01-23 00:41:24 +0000322 if (!driver_name)
323 return NULL;
324
Kuninori Morimotoa0ac4412017-08-08 06:17:47 +0000325 for_each_rtdcom(rtd, rtdcom) {
Kuninori Morimoto971da242018-01-23 00:41:24 +0000326 const char *component_name = rtdcom->component->driver->name;
327
328 if (!component_name)
329 continue;
330
331 if ((component_name == driver_name) ||
332 strcmp(component_name, driver_name) == 0)
Kuninori Morimotoa0ac4412017-08-08 06:17:47 +0000333 return rtdcom->component;
334 }
335
336 return NULL;
337}
Kuninori Morimoto031734b2018-01-18 01:13:54 +0000338EXPORT_SYMBOL_GPL(snd_soc_rtdcom_lookup);
Kuninori Morimotoa0ac4412017-08-08 06:17:47 +0000339
Liam Girdwood47c88ff2012-04-25 12:12:53 +0100340struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
341 const char *dai_link, int stream)
342{
Mengdong Lin1a497982015-11-18 02:34:11 -0500343 struct snd_soc_pcm_runtime *rtd;
Liam Girdwood47c88ff2012-04-25 12:12:53 +0100344
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000345 for_each_card_rtds(card, rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -0500346 if (rtd->dai_link->no_pcm &&
347 !strcmp(rtd->dai_link->name, dai_link))
348 return rtd->pcm->streams[stream].substream;
Liam Girdwood47c88ff2012-04-25 12:12:53 +0100349 }
Liam Girdwoodf110bfc2012-11-19 14:47:09 +0000350 dev_dbg(card->dev, "ASoC: failed to find dai link %s\n", dai_link);
Liam Girdwood47c88ff2012-04-25 12:12:53 +0100351 return NULL;
352}
353EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream);
354
Kuninori Morimoto75ab9eb2017-09-26 00:40:42 +0000355static const struct snd_soc_ops null_snd_soc_ops;
356
Mengdong Lin1a497982015-11-18 02:34:11 -0500357static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
358 struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
359{
360 struct snd_soc_pcm_runtime *rtd;
361
362 rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL);
363 if (!rtd)
364 return NULL;
365
Kuninori Morimotoa0ac4412017-08-08 06:17:47 +0000366 INIT_LIST_HEAD(&rtd->component_list);
Mengdong Lin1a497982015-11-18 02:34:11 -0500367 rtd->card = card;
368 rtd->dai_link = dai_link;
Kuninori Morimoto75ab9eb2017-09-26 00:40:42 +0000369 if (!rtd->dai_link->ops)
370 rtd->dai_link->ops = &null_snd_soc_ops;
371
Kees Cook6396bb22018-06-12 14:03:40 -0700372 rtd->codec_dais = kcalloc(dai_link->num_codecs,
373 sizeof(struct snd_soc_dai *),
Mengdong Lin1a497982015-11-18 02:34:11 -0500374 GFP_KERNEL);
375 if (!rtd->codec_dais) {
376 kfree(rtd);
377 return NULL;
378 }
379
380 return rtd;
381}
382
383static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd)
384{
Kuninori Morimotodb1721f2017-09-25 01:38:13 +0000385 kfree(rtd->codec_dais);
Kuninori Morimotoa0ac4412017-08-08 06:17:47 +0000386 snd_soc_rtdcom_del_all(rtd);
Mengdong Lin1a497982015-11-18 02:34:11 -0500387 kfree(rtd);
388}
389
390static void soc_add_pcm_runtime(struct snd_soc_card *card,
391 struct snd_soc_pcm_runtime *rtd)
392{
393 list_add_tail(&rtd->list, &card->rtd_list);
394 rtd->num = card->num_rtd;
395 card->num_rtd++;
396}
397
398static void soc_remove_pcm_runtimes(struct snd_soc_card *card)
399{
400 struct snd_soc_pcm_runtime *rtd, *_rtd;
401
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000402 for_each_card_rtds_safe(card, rtd, _rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -0500403 list_del(&rtd->list);
404 soc_free_pcm_runtime(rtd);
405 }
406
407 card->num_rtd = 0;
408}
409
Liam Girdwood47c88ff2012-04-25 12:12:53 +0100410struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
411 const char *dai_link)
412{
Mengdong Lin1a497982015-11-18 02:34:11 -0500413 struct snd_soc_pcm_runtime *rtd;
Liam Girdwood47c88ff2012-04-25 12:12:53 +0100414
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000415 for_each_card_rtds(card, rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -0500416 if (!strcmp(rtd->dai_link->name, dai_link))
417 return rtd;
Liam Girdwood47c88ff2012-04-25 12:12:53 +0100418 }
Liam Girdwoodf110bfc2012-11-19 14:47:09 +0000419 dev_dbg(card->dev, "ASoC: failed to find rtd %s\n", dai_link);
Liam Girdwood47c88ff2012-04-25 12:12:53 +0100420 return NULL;
421}
422EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime);
423
Richard Fitzgerald9d58a072013-08-05 13:17:28 +0100424static void codec2codec_close_delayed_work(struct work_struct *work)
425{
426 /* Currently nothing to do for c2c links
427 * Since c2c links are internal nodes in the DAPM graph and
428 * don't interface with the outside world or application layer
429 * we don't have to do any special handling on close.
430 */
431}
432
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000433#ifdef CONFIG_PM_SLEEP
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200434/* powers down audio subsystem for suspend */
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000435int snd_soc_suspend(struct device *dev)
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200436{
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000437 struct snd_soc_card *card = dev_get_drvdata(dev);
Kuninori Morimotod9fc4062016-11-30 06:22:36 +0000438 struct snd_soc_component *component;
Mengdong Lin1a497982015-11-18 02:34:11 -0500439 struct snd_soc_pcm_runtime *rtd;
440 int i;
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200441
Lars-Peter Clausenc5599b82014-08-19 15:51:30 +0200442 /* If the card is not initialized yet there is nothing to do */
443 if (!card->instantiated)
Daniel Macke3509ff2009-06-03 17:44:49 +0200444 return 0;
445
Andy Green6ed25972008-06-13 16:24:05 +0100446 /* Due to the resume being scheduled into a workqueue we could
447 * suspend before that's finished - wait for it to complete.
448 */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000449 snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0);
Andy Green6ed25972008-06-13 16:24:05 +0100450
451 /* we're going to block userspace touching us until resume completes */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000452 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot);
Andy Green6ed25972008-06-13 16:24:05 +0100453
Mark Browna00f90f2010-12-02 16:24:24 +0000454 /* mute any active DACs */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000455 for_each_card_rtds(card, rtd) {
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +0000456 struct snd_soc_dai *dai;
Mark Brown3efab7d2010-05-09 13:25:43 +0100457
Mengdong Lin1a497982015-11-18 02:34:11 -0500458 if (rtd->dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100459 continue;
460
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +0000461 for_each_rtd_codec_dai(rtd, i, dai) {
Benoit Cousson88bd8702014-07-08 23:19:34 +0200462 struct snd_soc_dai_driver *drv = dai->driver;
463
464 if (drv->ops->digital_mute && dai->playback_active)
465 drv->ops->digital_mute(dai, 1);
466 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200467 }
468
Liam Girdwood4ccab3e2008-01-10 14:39:01 +0100469 /* suspend all pcms */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000470 for_each_card_rtds(card, rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -0500471 if (rtd->dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100472 continue;
473
Mengdong Lin1a497982015-11-18 02:34:11 -0500474 snd_pcm_suspend_all(rtd->pcm);
Mark Brown3efab7d2010-05-09 13:25:43 +0100475 }
Liam Girdwood4ccab3e2008-01-10 14:39:01 +0100476
Mark Brown87506542008-11-18 20:50:34 +0000477 if (card->suspend_pre)
Mark Brown70b2ac12011-01-26 14:05:25 +0000478 card->suspend_pre(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200479
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000480 for_each_card_rtds(card, rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -0500481 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Mark Brown3efab7d2010-05-09 13:25:43 +0100482
Mengdong Lin1a497982015-11-18 02:34:11 -0500483 if (rtd->dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100484 continue;
485
Lars-Peter Clausenbc263212014-11-10 22:41:52 +0100486 if (cpu_dai->driver->suspend && !cpu_dai->driver->bus_control)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000487 cpu_dai->driver->suspend(cpu_dai);
Mark Brown1547aba2010-05-07 21:11:40 +0100488 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200489
Lars-Peter Clausen37660b62015-03-30 21:04:50 +0200490 /* close any waiting streams */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000491 for_each_card_rtds(card, rtd)
Mengdong Lin1a497982015-11-18 02:34:11 -0500492 flush_delayed_work(&rtd->delayed_work);
Mark Brown3efab7d2010-05-09 13:25:43 +0100493
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000494 for_each_card_rtds(card, rtd) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000495
Mengdong Lin1a497982015-11-18 02:34:11 -0500496 if (rtd->dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100497 continue;
498
Mengdong Lin1a497982015-11-18 02:34:11 -0500499 snd_soc_dapm_stream_event(rtd,
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800500 SNDRV_PCM_STREAM_PLAYBACK,
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800501 SND_SOC_DAPM_STREAM_SUSPEND);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000502
Mengdong Lin1a497982015-11-18 02:34:11 -0500503 snd_soc_dapm_stream_event(rtd,
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800504 SNDRV_PCM_STREAM_CAPTURE,
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800505 SND_SOC_DAPM_STREAM_SUSPEND);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000506 }
507
Lars-Peter Clausen8be4da22014-10-25 17:42:01 +0200508 /* Recheck all endpoints too, their state is affected by suspend */
509 dapm_mark_endpoints_dirty(card);
Mark Browne2d32ff2012-08-31 17:38:32 -0700510 snd_soc_dapm_sync(&card->dapm);
511
Kuninori Morimoto9178feb2016-11-30 06:23:13 +0000512 /* suspend all COMPONENTs */
Kuninori Morimotod9fc4062016-11-30 06:22:36 +0000513 list_for_each_entry(component, &card->component_dev_list, card_list) {
514 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
Kuninori Morimotod9fc4062016-11-30 06:22:36 +0000515
Kuninori Morimoto9178feb2016-11-30 06:23:13 +0000516 /* If there are paths active then the COMPONENT will be held with
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000517 * bias _ON and should not be suspended. */
Kuninori Morimoto9178feb2016-11-30 06:23:13 +0000518 if (!component->suspended) {
Lars-Peter Clausen48901402015-07-06 15:38:11 +0200519 switch (snd_soc_dapm_get_bias_level(dapm)) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000520 case SND_SOC_BIAS_STANDBY:
Mark Brown125a25d2012-01-31 15:49:10 +0000521 /*
Kuninori Morimoto9178feb2016-11-30 06:23:13 +0000522 * If the COMPONENT is capable of idle
Mark Brown125a25d2012-01-31 15:49:10 +0000523 * bias off then being in STANDBY
524 * means it's doing something,
525 * otherwise fall through.
526 */
Lars-Peter Clausen48901402015-07-06 15:38:11 +0200527 if (dapm->idle_bias_off) {
Kuninori Morimoto9178feb2016-11-30 06:23:13 +0000528 dev_dbg(component->dev,
Michał Mirosław10e8aa92013-05-04 22:21:38 +0200529 "ASoC: idle_bias_off CODEC on over suspend\n");
Mark Brown125a25d2012-01-31 15:49:10 +0000530 break;
531 }
Gustavo A. R. Silva1a12d5d2018-08-03 11:34:30 -0500532 /* fall through */
Lars-Peter Clausena8093292014-09-04 19:44:07 +0200533
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000534 case SND_SOC_BIAS_OFF:
Kuninori Morimoto999f7f52018-05-08 03:20:24 +0000535 if (component->driver->suspend)
536 component->driver->suspend(component);
Kuninori Morimoto9178feb2016-11-30 06:23:13 +0000537 component->suspended = 1;
538 if (component->regmap)
539 regcache_mark_dirty(component->regmap);
Nicolin Chen988e8cc2013-11-04 14:57:31 +0800540 /* deactivate pins to sleep state */
Kuninori Morimoto9178feb2016-11-30 06:23:13 +0000541 pinctrl_pm_select_sleep_state(component->dev);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000542 break;
543 default:
Kuninori Morimoto9178feb2016-11-30 06:23:13 +0000544 dev_dbg(component->dev,
545 "ASoC: COMPONENT is on over suspend\n");
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000546 break;
547 }
548 }
549 }
550
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000551 for_each_card_rtds(card, rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -0500552 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000553
Mengdong Lin1a497982015-11-18 02:34:11 -0500554 if (rtd->dai_link->ignore_suspend)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000555 continue;
556
Lars-Peter Clausenbc263212014-11-10 22:41:52 +0100557 if (cpu_dai->driver->suspend && cpu_dai->driver->bus_control)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000558 cpu_dai->driver->suspend(cpu_dai);
Nicolin Chen988e8cc2013-11-04 14:57:31 +0800559
560 /* deactivate pins to sleep state */
561 pinctrl_pm_select_sleep_state(cpu_dai->dev);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200562 }
563
Mark Brown87506542008-11-18 20:50:34 +0000564 if (card->suspend_post)
Mark Brown70b2ac12011-01-26 14:05:25 +0000565 card->suspend_post(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200566
567 return 0;
568}
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000569EXPORT_SYMBOL_GPL(snd_soc_suspend);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200570
Andy Green6ed25972008-06-13 16:24:05 +0100571/* deferred resume work, so resume can complete before we finished
572 * setting our codec back up, which can be very slow on I2C
573 */
574static void soc_resume_deferred(struct work_struct *work)
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200575{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000576 struct snd_soc_card *card =
577 container_of(work, struct snd_soc_card, deferred_resume_work);
Mengdong Lin1a497982015-11-18 02:34:11 -0500578 struct snd_soc_pcm_runtime *rtd;
Kuninori Morimotod9fc4062016-11-30 06:22:36 +0000579 struct snd_soc_component *component;
Mengdong Lin1a497982015-11-18 02:34:11 -0500580 int i;
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200581
Andy Green6ed25972008-06-13 16:24:05 +0100582 /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
583 * so userspace apps are blocked from touching us
584 */
585
Liam Girdwoodf110bfc2012-11-19 14:47:09 +0000586 dev_dbg(card->dev, "ASoC: starting resume work\n");
Andy Green6ed25972008-06-13 16:24:05 +0100587
Mark Brown9949788b2010-05-07 20:24:05 +0100588 /* Bring us up into D2 so that DAPM starts enabling things */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000589 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2);
Mark Brown9949788b2010-05-07 20:24:05 +0100590
Mark Brown87506542008-11-18 20:50:34 +0000591 if (card->resume_pre)
Mark Brown70b2ac12011-01-26 14:05:25 +0000592 card->resume_pre(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200593
Lars-Peter Clausenbc263212014-11-10 22:41:52 +0100594 /* resume control bus DAIs */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000595 for_each_card_rtds(card, rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -0500596 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Mark Brown3efab7d2010-05-09 13:25:43 +0100597
Mengdong Lin1a497982015-11-18 02:34:11 -0500598 if (rtd->dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100599 continue;
600
Lars-Peter Clausenbc263212014-11-10 22:41:52 +0100601 if (cpu_dai->driver->resume && cpu_dai->driver->bus_control)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000602 cpu_dai->driver->resume(cpu_dai);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200603 }
604
Kuninori Morimotod9fc4062016-11-30 06:22:36 +0000605 list_for_each_entry(component, &card->component_dev_list, card_list) {
Kuninori Morimoto9178feb2016-11-30 06:23:13 +0000606 if (component->suspended) {
Kuninori Morimoto999f7f52018-05-08 03:20:24 +0000607 if (component->driver->resume)
608 component->driver->resume(component);
Kuninori Morimoto9178feb2016-11-30 06:23:13 +0000609 component->suspended = 0;
Mark Brown1547aba2010-05-07 21:11:40 +0100610 }
611 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200612
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000613 for_each_card_rtds(card, rtd) {
Mark Brown3efab7d2010-05-09 13:25:43 +0100614
Mengdong Lin1a497982015-11-18 02:34:11 -0500615 if (rtd->dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100616 continue;
617
Mengdong Lin1a497982015-11-18 02:34:11 -0500618 snd_soc_dapm_stream_event(rtd,
Liam Girdwoodd9b09512012-03-07 16:32:59 +0000619 SNDRV_PCM_STREAM_PLAYBACK,
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800620 SND_SOC_DAPM_STREAM_RESUME);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000621
Mengdong Lin1a497982015-11-18 02:34:11 -0500622 snd_soc_dapm_stream_event(rtd,
Liam Girdwoodd9b09512012-03-07 16:32:59 +0000623 SNDRV_PCM_STREAM_CAPTURE,
Mark Brown7bd3a6f2012-02-16 15:03:27 -0800624 SND_SOC_DAPM_STREAM_RESUME);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200625 }
626
Mark Brown3ff3f642008-05-19 12:32:25 +0200627 /* unmute any active DACs */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000628 for_each_card_rtds(card, rtd) {
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +0000629 struct snd_soc_dai *dai;
Mark Brown3efab7d2010-05-09 13:25:43 +0100630
Mengdong Lin1a497982015-11-18 02:34:11 -0500631 if (rtd->dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100632 continue;
633
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +0000634 for_each_rtd_codec_dai(rtd, i, dai) {
Benoit Cousson88bd8702014-07-08 23:19:34 +0200635 struct snd_soc_dai_driver *drv = dai->driver;
636
637 if (drv->ops->digital_mute && dai->playback_active)
638 drv->ops->digital_mute(dai, 0);
639 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200640 }
641
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000642 for_each_card_rtds(card, rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -0500643 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Mark Brown3efab7d2010-05-09 13:25:43 +0100644
Mengdong Lin1a497982015-11-18 02:34:11 -0500645 if (rtd->dai_link->ignore_suspend)
Mark Brown3efab7d2010-05-09 13:25:43 +0100646 continue;
647
Lars-Peter Clausenbc263212014-11-10 22:41:52 +0100648 if (cpu_dai->driver->resume && !cpu_dai->driver->bus_control)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000649 cpu_dai->driver->resume(cpu_dai);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200650 }
651
Mark Brown87506542008-11-18 20:50:34 +0000652 if (card->resume_post)
Mark Brown70b2ac12011-01-26 14:05:25 +0000653 card->resume_post(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200654
Liam Girdwoodf110bfc2012-11-19 14:47:09 +0000655 dev_dbg(card->dev, "ASoC: resume work completed\n");
Andy Green6ed25972008-06-13 16:24:05 +0100656
Lars-Peter Clausen8be4da22014-10-25 17:42:01 +0200657 /* Recheck all endpoints too, their state is affected by suspend */
658 dapm_mark_endpoints_dirty(card);
Mark Browne2d32ff2012-08-31 17:38:32 -0700659 snd_soc_dapm_sync(&card->dapm);
Jeeja KP1a7aaa52015-11-23 21:22:31 +0530660
661 /* userspace can access us now we are back as we were before */
662 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0);
Andy Green6ed25972008-06-13 16:24:05 +0100663}
664
665/* powers up audio subsystem after a suspend */
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000666int snd_soc_resume(struct device *dev)
Andy Green6ed25972008-06-13 16:24:05 +0100667{
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000668 struct snd_soc_card *card = dev_get_drvdata(dev);
Lars-Peter Clausenbc263212014-11-10 22:41:52 +0100669 bool bus_control = false;
Mengdong Lin1a497982015-11-18 02:34:11 -0500670 struct snd_soc_pcm_runtime *rtd;
Peter Ujfalusib9dd94a2010-02-22 13:27:13 +0200671
Lars-Peter Clausenc5599b82014-08-19 15:51:30 +0200672 /* If the card is not initialized yet there is nothing to do */
673 if (!card->instantiated)
Eric Miao5ff1ddf2011-11-23 22:37:00 +0800674 return 0;
675
Nicolin Chen988e8cc2013-11-04 14:57:31 +0800676 /* activate pins from sleep state */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000677 for_each_card_rtds(card, rtd) {
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +0000678 struct snd_soc_dai *codec_dai;
Benoit Cousson88bd8702014-07-08 23:19:34 +0200679 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
680 int j;
681
Nicolin Chen988e8cc2013-11-04 14:57:31 +0800682 if (cpu_dai->active)
683 pinctrl_pm_select_default_state(cpu_dai->dev);
Benoit Cousson88bd8702014-07-08 23:19:34 +0200684
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +0000685 for_each_rtd_codec_dai(rtd, j, codec_dai) {
Benoit Cousson88bd8702014-07-08 23:19:34 +0200686 if (codec_dai->active)
687 pinctrl_pm_select_default_state(codec_dai->dev);
688 }
Nicolin Chen988e8cc2013-11-04 14:57:31 +0800689 }
690
Lars-Peter Clausenbc263212014-11-10 22:41:52 +0100691 /*
692 * DAIs that also act as the control bus master might have other drivers
693 * hanging off them so need to resume immediately. Other drivers don't
694 * have that problem and may take a substantial amount of time to resume
Mark Brown64ab9ba2009-03-31 11:27:03 +0100695 * due to I/O costs and anti-pop so handle them out of line.
696 */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000697 for_each_card_rtds(card, rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -0500698 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Lars-Peter Clausenbc263212014-11-10 22:41:52 +0100699 bus_control |= cpu_dai->driver->bus_control;
Stephen Warren82e14e82011-05-25 14:06:41 -0600700 }
Lars-Peter Clausenbc263212014-11-10 22:41:52 +0100701 if (bus_control) {
702 dev_dbg(dev, "ASoC: Resuming control bus master immediately\n");
Stephen Warren82e14e82011-05-25 14:06:41 -0600703 soc_resume_deferred(&card->deferred_resume_work);
704 } else {
Liam Girdwoodf110bfc2012-11-19 14:47:09 +0000705 dev_dbg(dev, "ASoC: Scheduling resume work\n");
Stephen Warren82e14e82011-05-25 14:06:41 -0600706 if (!schedule_work(&card->deferred_resume_work))
Liam Girdwoodf110bfc2012-11-19 14:47:09 +0000707 dev_err(dev, "ASoC: resume work item may be lost\n");
Mark Brown64ab9ba2009-03-31 11:27:03 +0100708 }
Andy Green6ed25972008-06-13 16:24:05 +0100709
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200710 return 0;
711}
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000712EXPORT_SYMBOL_GPL(snd_soc_resume);
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200713#else
Mark Brown6f8ab4a2011-01-26 14:59:27 +0000714#define snd_soc_suspend NULL
715#define snd_soc_resume NULL
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200716#endif
717
Lars-Peter Clausen85e76522011-11-23 11:40:40 +0100718static const struct snd_soc_dai_ops null_dai_ops = {
Barry Song02a06d32009-10-16 18:13:38 +0800719};
720
Lars-Peter Clausen65d93612014-08-19 15:51:22 +0200721static struct snd_soc_component *soc_find_component(
722 const struct device_node *of_node, const char *name)
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100723{
Lars-Peter Clausen65d93612014-08-19 15:51:22 +0200724 struct snd_soc_component *component;
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100725
Lars-Peter Clausen34e81ab2015-03-07 19:34:03 +0100726 lockdep_assert_held(&client_mutex);
727
Lars-Peter Clausen65d93612014-08-19 15:51:22 +0200728 list_for_each_entry(component, &component_list, list) {
729 if (of_node) {
730 if (component->dev->of_node == of_node)
731 return component;
732 } else if (strcmp(component->name, name) == 0) {
733 return component;
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100734 }
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100735 }
736
737 return NULL;
738}
739
Kuninori Morimotobe6ac0a2018-09-11 06:51:45 +0000740static int snd_soc_is_matching_component(
741 const struct snd_soc_dai_link_component *dlc,
742 struct snd_soc_component *component)
743{
744 struct device_node *component_of_node;
745
746 component_of_node = component->dev->of_node;
747 if (!component_of_node && component->dev->parent)
748 component_of_node = component->dev->parent->of_node;
749
750 if (dlc->of_node && component_of_node != dlc->of_node)
751 return 0;
752 if (dlc->name && strcmp(component->name, dlc->name))
753 return 0;
754
755 return 1;
756}
757
Mengdong Linfbb88b52016-04-22 12:25:33 +0800758/**
759 * snd_soc_find_dai - Find a registered DAI
760 *
Jeffy Chen49584712017-08-22 15:57:21 +0800761 * @dlc: name of the DAI or the DAI driver and optional component info to match
Mengdong Linfbb88b52016-04-22 12:25:33 +0800762 *
Stephen Boydad61dd32017-05-08 15:57:50 -0700763 * This function will search all registered components and their DAIs to
Mengdong Linfbb88b52016-04-22 12:25:33 +0800764 * find the DAI of the same name. The component's of_node and name
765 * should also match if being specified.
766 *
767 * Return: pointer of DAI, or NULL if not found.
768 */
Mengdong Lin305e9022016-04-19 13:12:25 +0800769struct snd_soc_dai *snd_soc_find_dai(
Lars-Peter Clausen14621c72014-08-19 15:51:27 +0200770 const struct snd_soc_dai_link_component *dlc)
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100771{
Lars-Peter Clausen14621c72014-08-19 15:51:27 +0200772 struct snd_soc_component *component;
773 struct snd_soc_dai *dai;
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100774
Lars-Peter Clausen34e81ab2015-03-07 19:34:03 +0100775 lockdep_assert_held(&client_mutex);
776
Lars-Peter Clausen14621c72014-08-19 15:51:27 +0200777 /* Find CPU DAI from registered DAIs*/
778 list_for_each_entry(component, &component_list, list) {
Kuninori Morimotobe6ac0a2018-09-11 06:51:45 +0000779 if (!snd_soc_is_matching_component(dlc, component))
Lars-Peter Clausen14621c72014-08-19 15:51:27 +0200780 continue;
781 list_for_each_entry(dai, &component->dai_list, list) {
Jeffy Chen49584712017-08-22 15:57:21 +0800782 if (dlc->dai_name && strcmp(dai->name, dlc->dai_name)
Jeffy Chen6a6dafd2017-08-24 12:40:17 +0800783 && (!dai->driver->name
784 || strcmp(dai->driver->name, dlc->dai_name)))
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100785 continue;
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100786
Lars-Peter Clausen14621c72014-08-19 15:51:27 +0200787 return dai;
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100788 }
789 }
790
791 return NULL;
792}
Mengdong Lin305e9022016-04-19 13:12:25 +0800793EXPORT_SYMBOL_GPL(snd_soc_find_dai);
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100794
Mengdong Lin17fb17552016-11-03 01:04:12 +0800795
796/**
797 * snd_soc_find_dai_link - Find a DAI link
798 *
799 * @card: soc card
800 * @id: DAI link ID to match
801 * @name: DAI link name to match, optional
Charles Keepax8abab352017-01-12 11:38:15 +0000802 * @stream_name: DAI link stream name to match, optional
Mengdong Lin17fb17552016-11-03 01:04:12 +0800803 *
804 * This function will search all existing DAI links of the soc card to
805 * find the link of the same ID. Since DAI links may not have their
806 * unique ID, so name and stream name should also match if being
807 * specified.
808 *
809 * Return: pointer of DAI link, or NULL if not found.
810 */
811struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card,
812 int id, const char *name,
813 const char *stream_name)
814{
815 struct snd_soc_dai_link *link, *_link;
816
817 lockdep_assert_held(&client_mutex);
818
Kuninori Morimoto98061fd2018-09-18 01:29:16 +0000819 for_each_card_links_safe(card, link, _link) {
Mengdong Lin17fb17552016-11-03 01:04:12 +0800820 if (link->id != id)
821 continue;
822
823 if (name && (!link->name || strcmp(name, link->name)))
824 continue;
825
826 if (stream_name && (!link->stream_name
827 || strcmp(stream_name, link->stream_name)))
828 continue;
829
830 return link;
831 }
832
833 return NULL;
834}
835EXPORT_SYMBOL_GPL(snd_soc_find_dai_link);
836
Mengdong Lin49a5ba12015-12-02 14:11:40 +0800837static bool soc_is_dai_link_bound(struct snd_soc_card *card,
838 struct snd_soc_dai_link *dai_link)
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200839{
Mengdong Lin49a5ba12015-12-02 14:11:40 +0800840 struct snd_soc_pcm_runtime *rtd;
841
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000842 for_each_card_rtds(card, rtd) {
Mengdong Lin49a5ba12015-12-02 14:11:40 +0800843 if (rtd->dai_link == dai_link)
844 return true;
845 }
846
847 return false;
848}
849
Mengdong Lin6f2f1ff2015-11-23 11:03:52 -0500850static int soc_bind_dai_link(struct snd_soc_card *card,
851 struct snd_soc_dai_link *dai_link)
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200852{
Mengdong Lin1a497982015-11-18 02:34:11 -0500853 struct snd_soc_pcm_runtime *rtd;
Benoit Cousson88bd8702014-07-08 23:19:34 +0200854 struct snd_soc_dai_link_component *codecs = dai_link->codecs;
Lars-Peter Clausen14621c72014-08-19 15:51:27 +0200855 struct snd_soc_dai_link_component cpu_dai_component;
Kuninori Morimoto90be7112017-08-08 06:18:10 +0000856 struct snd_soc_component *component;
Mengdong Lin1a497982015-11-18 02:34:11 -0500857 struct snd_soc_dai **codec_dais;
Benoit Cousson88bd8702014-07-08 23:19:34 +0200858 int i;
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200859
Liam Girdwooda655de82018-07-02 16:59:54 +0100860 if (dai_link->ignore)
861 return 0;
862
Mengdong Lin6f2f1ff2015-11-23 11:03:52 -0500863 dev_dbg(card->dev, "ASoC: binding %s\n", dai_link->name);
Mark Brown63084192008-12-02 15:08:03 +0000864
Mengdong Lin49a5ba12015-12-02 14:11:40 +0800865 if (soc_is_dai_link_bound(card, dai_link)) {
866 dev_dbg(card->dev, "ASoC: dai link %s already bound\n",
867 dai_link->name);
868 return 0;
869 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +0200870
Sudip Mukherjee513cb3112016-02-22 14:14:31 +0530871 rtd = soc_new_pcm_runtime(card, dai_link);
872 if (!rtd)
873 return -ENOMEM;
874
Lars-Peter Clausen14621c72014-08-19 15:51:27 +0200875 cpu_dai_component.name = dai_link->cpu_name;
876 cpu_dai_component.of_node = dai_link->cpu_of_node;
877 cpu_dai_component.dai_name = dai_link->cpu_dai_name;
878 rtd->cpu_dai = snd_soc_find_dai(&cpu_dai_component);
Mark Brownb19e6e72012-03-14 21:18:39 +0000879 if (!rtd->cpu_dai) {
Martin Hundebøll6b490872018-02-01 11:09:41 +0100880 dev_info(card->dev, "ASoC: CPU DAI %s not registered\n",
881 dai_link->cpu_dai_name);
Mengdong Lin1a497982015-11-18 02:34:11 -0500882 goto _err_defer;
Mark Brownc5af3a22008-11-28 13:29:45 +0000883 }
Kuninori Morimoto90be7112017-08-08 06:18:10 +0000884 snd_soc_rtdcom_add(rtd, rtd->cpu_dai->component);
Mark Brownc5af3a22008-11-28 13:29:45 +0000885
Benoit Cousson88bd8702014-07-08 23:19:34 +0200886 rtd->num_codecs = dai_link->num_codecs;
887
888 /* Find CODEC from registered CODECs */
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +0000889 /* we can use for_each_rtd_codec_dai() after this */
Mengdong Lin1a497982015-11-18 02:34:11 -0500890 codec_dais = rtd->codec_dais;
Benoit Cousson88bd8702014-07-08 23:19:34 +0200891 for (i = 0; i < rtd->num_codecs; i++) {
Lars-Peter Clausen14621c72014-08-19 15:51:27 +0200892 codec_dais[i] = snd_soc_find_dai(&codecs[i]);
Benoit Cousson88bd8702014-07-08 23:19:34 +0200893 if (!codec_dais[i]) {
894 dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n",
895 codecs[i].dai_name);
Mengdong Lin1a497982015-11-18 02:34:11 -0500896 goto _err_defer;
Benoit Cousson88bd8702014-07-08 23:19:34 +0200897 }
Kuninori Morimoto90be7112017-08-08 06:18:10 +0000898 snd_soc_rtdcom_add(rtd, codec_dais[i]->component);
Mark Brownb19e6e72012-03-14 21:18:39 +0000899 }
Mark Brown848dd8b2011-04-27 18:16:32 +0100900
Benoit Cousson88bd8702014-07-08 23:19:34 +0200901 /* Single codec links expect codec and codec_dai in runtime data */
902 rtd->codec_dai = codec_dais[0];
Misael Lopez Cruz12023a92014-03-21 16:27:25 +0100903
Mark Brownb19e6e72012-03-14 21:18:39 +0000904 /* find one from the set of registered platforms */
Kuninori Morimoto90be7112017-08-08 06:18:10 +0000905 list_for_each_entry(component, &component_list, list) {
Kuninori Morimotobe6ac0a2018-09-11 06:51:45 +0000906 if (!snd_soc_is_matching_component(dai_link->platform,
907 component))
908 continue;
Kuninori Morimoto90be7112017-08-08 06:18:10 +0000909
910 snd_soc_rtdcom_add(rtd, component);
911 }
912
Mengdong Lin1a497982015-11-18 02:34:11 -0500913 soc_add_pcm_runtime(card, rtd);
Mark Brownb19e6e72012-03-14 21:18:39 +0000914 return 0;
Mengdong Lin1a497982015-11-18 02:34:11 -0500915
916_err_defer:
917 soc_free_pcm_runtime(rtd);
918 return -EPROBE_DEFER;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000919}
920
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +0200921static void soc_remove_component(struct snd_soc_component *component)
Stephen Warrend12cd192012-06-08 12:34:22 -0600922{
Lars-Peter Clausenabd31b32015-07-08 20:47:44 +0200923 if (!component->card)
Lars-Peter Clausen70090bb2014-08-19 15:51:24 +0200924 return;
Stephen Warrend12cd192012-06-08 12:34:22 -0600925
Kuninori Morimotod9fc4062016-11-30 06:22:36 +0000926 list_del(&component->card_list);
Stephen Warrend12cd192012-06-08 12:34:22 -0600927
Kuninori Morimoto999f7f52018-05-08 03:20:24 +0000928 if (component->driver->remove)
929 component->driver->remove(component);
Stephen Warrend12cd192012-06-08 12:34:22 -0600930
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +0200931 snd_soc_dapm_free(snd_soc_component_get_dapm(component));
Stephen Warrend12cd192012-06-08 12:34:22 -0600932
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +0200933 soc_cleanup_component_debugfs(component);
Lars-Peter Clausenabd31b32015-07-08 20:47:44 +0200934 component->card = NULL;
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +0200935 module_put(component->dev->driver->owner);
Stephen Warrend12cd192012-06-08 12:34:22 -0600936}
937
Lars-Peter Clausene60cd142014-08-19 15:51:26 +0200938static void soc_remove_dai(struct snd_soc_dai *dai, int order)
Jarkko Nikula589c3562010-12-06 16:27:07 +0200939{
940 int err;
941
Kuninori Morimoto2eda3cb2018-09-11 06:54:26 +0000942 if (!dai || !dai->probed ||
943 dai->driver->remove_order != order)
944 return;
945
946 if (dai->driver->remove) {
947 err = dai->driver->remove(dai);
948 if (err < 0)
949 dev_err(dai->dev,
950 "ASoC: failed to remove %s: %d\n",
951 dai->name, err);
Misael Lopez Cruzb0aa88a2014-03-21 16:27:26 +0100952 }
Kuninori Morimoto2eda3cb2018-09-11 06:54:26 +0000953 dai->probed = 0;
Misael Lopez Cruzb0aa88a2014-03-21 16:27:26 +0100954}
955
Mengdong Lin1a497982015-11-18 02:34:11 -0500956static void soc_remove_link_dais(struct snd_soc_card *card,
957 struct snd_soc_pcm_runtime *rtd, int order)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000958{
Lars-Peter Clausene60cd142014-08-19 15:51:26 +0200959 int i;
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +0000960 struct snd_soc_dai *codec_dai;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000961
962 /* unregister the rtd device */
963 if (rtd->dev_registered) {
Mark Brown36ae1a92012-01-06 17:12:45 -0800964 device_unregister(rtd->dev);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000965 rtd->dev_registered = 0;
966 }
967
968 /* remove the CODEC DAI */
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +0000969 for_each_rtd_codec_dai(rtd, i, codec_dai)
970 soc_remove_dai(codec_dai, order);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000971
Lars-Peter Clausene60cd142014-08-19 15:51:26 +0200972 soc_remove_dai(rtd->cpu_dai, order);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000973}
974
Mengdong Lin1a497982015-11-18 02:34:11 -0500975static void soc_remove_link_components(struct snd_soc_card *card,
976 struct snd_soc_pcm_runtime *rtd, int order)
Stephen Warren62ae68f2012-06-08 12:34:23 -0600977{
Lars-Peter Clausen61aca562014-08-19 15:51:21 +0200978 struct snd_soc_component *component;
Kuninori Morimoto90be7112017-08-08 06:18:10 +0000979 struct snd_soc_rtdcom_list *rtdcom;
Stephen Warren62ae68f2012-06-08 12:34:23 -0600980
Kuninori Morimoto90be7112017-08-08 06:18:10 +0000981 for_each_rtdcom(rtd, rtdcom) {
982 component = rtdcom->component;
Stephen Warren62ae68f2012-06-08 12:34:23 -0600983
Lars-Peter Clausen70090bb2014-08-19 15:51:24 +0200984 if (component->driver->remove_order == order)
Lars-Peter Clausen61aca562014-08-19 15:51:21 +0200985 soc_remove_component(component);
Stephen Warren62ae68f2012-06-08 12:34:23 -0600986 }
Stephen Warren62ae68f2012-06-08 12:34:23 -0600987}
988
Kuninori Morimoto0671fd82011-04-08 14:50:44 +0900989static void soc_remove_dai_links(struct snd_soc_card *card)
990{
Mengdong Lin1a497982015-11-18 02:34:11 -0500991 int order;
992 struct snd_soc_pcm_runtime *rtd;
Mengdong Linf8f80362015-12-02 14:11:22 +0800993 struct snd_soc_dai_link *link, *_link;
Kuninori Morimoto0671fd82011-04-08 14:50:44 +0900994
Liam Girdwood0168bf02011-06-07 16:08:05 +0100995 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
996 order++) {
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +0000997 for_each_card_rtds(card, rtd)
Mengdong Lin1a497982015-11-18 02:34:11 -0500998 soc_remove_link_dais(card, rtd, order);
Liam Girdwood0168bf02011-06-07 16:08:05 +0100999 }
Stephen Warren62ae68f2012-06-08 12:34:23 -06001000
1001 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1002 order++) {
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +00001003 for_each_card_rtds(card, rtd)
Mengdong Lin1a497982015-11-18 02:34:11 -05001004 soc_remove_link_components(card, rtd, order);
Stephen Warren62ae68f2012-06-08 12:34:23 -06001005 }
1006
Kuninori Morimoto98061fd2018-09-18 01:29:16 +00001007 for_each_card_links_safe(card, link, _link) {
Mengdong Linf8f80362015-12-02 14:11:22 +08001008 if (link->dobj.type == SND_SOC_DOBJ_DAI_LINK)
1009 dev_warn(card->dev, "Topology forgot to remove link %s?\n",
1010 link->name);
1011
1012 list_del(&link->list);
Mengdong Linf8f80362015-12-02 14:11:22 +08001013 }
Kuninori Morimoto0671fd82011-04-08 14:50:44 +09001014}
1015
Kuninori Morimotodaecf462018-08-31 03:10:08 +00001016static int snd_soc_init_platform(struct snd_soc_card *card,
1017 struct snd_soc_dai_link *dai_link)
1018{
Kuninori Morimoto4a9ed392018-09-11 06:51:14 +00001019 struct snd_soc_dai_link_component *platform = dai_link->platform;
1020
Kuninori Morimotodaecf462018-08-31 03:10:08 +00001021 /*
1022 * FIXME
1023 *
1024 * this function should be removed in the future
1025 */
1026 /* convert Legacy platform link */
Kuninori Morimoto4a9ed392018-09-11 06:51:14 +00001027 if (!platform) {
1028 platform = devm_kzalloc(card->dev,
Kuninori Morimotodaecf462018-08-31 03:10:08 +00001029 sizeof(struct snd_soc_dai_link_component),
1030 GFP_KERNEL);
Kuninori Morimoto4a9ed392018-09-11 06:51:14 +00001031 if (!platform)
1032 return -ENOMEM;
Kuninori Morimotodaecf462018-08-31 03:10:08 +00001033
Kuninori Morimoto4a9ed392018-09-11 06:51:14 +00001034 dai_link->platform = platform;
1035 platform->name = dai_link->platform_name;
1036 platform->of_node = dai_link->platform_of_node;
1037 platform->dai_name = NULL;
1038 }
1039
1040 /* if there's no platform we match on the empty platform */
1041 if (!platform->name &&
1042 !platform->of_node)
1043 platform->name = "snd-soc-dummy";
Kuninori Morimotodaecf462018-08-31 03:10:08 +00001044
1045 return 0;
1046}
1047
Mengdong Lin923c5e612015-11-23 11:01:49 -05001048static int snd_soc_init_multicodec(struct snd_soc_card *card,
1049 struct snd_soc_dai_link *dai_link)
1050{
1051 /* Legacy codec/codec_dai link is a single entry in multicodec */
1052 if (dai_link->codec_name || dai_link->codec_of_node ||
1053 dai_link->codec_dai_name) {
1054 dai_link->num_codecs = 1;
1055
1056 dai_link->codecs = devm_kzalloc(card->dev,
1057 sizeof(struct snd_soc_dai_link_component),
1058 GFP_KERNEL);
1059 if (!dai_link->codecs)
1060 return -ENOMEM;
1061
1062 dai_link->codecs[0].name = dai_link->codec_name;
1063 dai_link->codecs[0].of_node = dai_link->codec_of_node;
1064 dai_link->codecs[0].dai_name = dai_link->codec_dai_name;
1065 }
1066
1067 if (!dai_link->codecs) {
1068 dev_err(card->dev, "ASoC: DAI link has no CODECs\n");
1069 return -EINVAL;
1070 }
1071
1072 return 0;
1073}
1074
1075static int soc_init_dai_link(struct snd_soc_card *card,
1076 struct snd_soc_dai_link *link)
1077{
1078 int i, ret;
Kuninori Morimoto3db769f2018-09-03 02:12:40 +00001079 struct snd_soc_dai_link_component *codec;
Mengdong Lin923c5e612015-11-23 11:01:49 -05001080
Kuninori Morimotodaecf462018-08-31 03:10:08 +00001081 ret = snd_soc_init_platform(card, link);
1082 if (ret) {
1083 dev_err(card->dev, "ASoC: failed to init multiplatform\n");
1084 return ret;
1085 }
1086
Mengdong Lin923c5e612015-11-23 11:01:49 -05001087 ret = snd_soc_init_multicodec(card, link);
1088 if (ret) {
1089 dev_err(card->dev, "ASoC: failed to init multicodec\n");
1090 return ret;
1091 }
1092
Kuninori Morimoto3db769f2018-09-03 02:12:40 +00001093 for_each_link_codecs(link, i, codec) {
Mengdong Lin923c5e612015-11-23 11:01:49 -05001094 /*
1095 * Codec must be specified by 1 of name or OF node,
1096 * not both or neither.
1097 */
Kuninori Morimoto3db769f2018-09-03 02:12:40 +00001098 if (!!codec->name ==
1099 !!codec->of_node) {
Mengdong Lin923c5e612015-11-23 11:01:49 -05001100 dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n",
1101 link->name);
1102 return -EINVAL;
1103 }
1104 /* Codec DAI name must be specified */
Kuninori Morimoto3db769f2018-09-03 02:12:40 +00001105 if (!codec->dai_name) {
Mengdong Lin923c5e612015-11-23 11:01:49 -05001106 dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n",
1107 link->name);
1108 return -EINVAL;
1109 }
1110 }
1111
1112 /*
1113 * Platform may be specified by either name or OF node, but
1114 * can be left unspecified, and a dummy platform will be used.
1115 */
Kuninori Morimotodaecf462018-08-31 03:10:08 +00001116 if (link->platform->name && link->platform->of_node) {
Mengdong Lin923c5e612015-11-23 11:01:49 -05001117 dev_err(card->dev,
1118 "ASoC: Both platform name/of_node are set for %s\n",
1119 link->name);
1120 return -EINVAL;
1121 }
Mengdong Lin923c5e612015-11-23 11:01:49 -05001122 /*
1123 * CPU device may be specified by either name or OF node, but
1124 * can be left unspecified, and will be matched based on DAI
1125 * name alone..
1126 */
1127 if (link->cpu_name && link->cpu_of_node) {
1128 dev_err(card->dev,
1129 "ASoC: Neither/both cpu name/of_node are set for %s\n",
1130 link->name);
1131 return -EINVAL;
1132 }
1133 /*
1134 * At least one of CPU DAI name or CPU device name/node must be
1135 * specified
1136 */
1137 if (!link->cpu_dai_name &&
1138 !(link->cpu_name || link->cpu_of_node)) {
1139 dev_err(card->dev,
1140 "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
1141 link->name);
1142 return -EINVAL;
1143 }
1144
1145 return 0;
1146}
1147
Kuninori Morimotoef2e8172017-11-28 06:27:09 +00001148void snd_soc_disconnect_sync(struct device *dev)
1149{
1150 struct snd_soc_component *component = snd_soc_lookup_component(dev, NULL);
1151
1152 if (!component || !component->card)
1153 return;
1154
1155 snd_card_disconnect_sync(component->card->snd_card);
1156}
Kuninori Morimotodf532182017-11-29 02:38:27 +00001157EXPORT_SYMBOL_GPL(snd_soc_disconnect_sync);
Kuninori Morimotoef2e8172017-11-28 06:27:09 +00001158
Mengdong Linf8f80362015-12-02 14:11:22 +08001159/**
1160 * snd_soc_add_dai_link - Add a DAI link dynamically
1161 * @card: The ASoC card to which the DAI link is added
1162 * @dai_link: The new DAI link to add
1163 *
1164 * This function adds a DAI link to the ASoC card's link list.
1165 *
1166 * Note: Topology can use this API to add DAI links when probing the
1167 * topology component. And machine drivers can still define static
1168 * DAI links in dai_link array.
1169 */
1170int snd_soc_add_dai_link(struct snd_soc_card *card,
1171 struct snd_soc_dai_link *dai_link)
1172{
1173 if (dai_link->dobj.type
1174 && dai_link->dobj.type != SND_SOC_DOBJ_DAI_LINK) {
1175 dev_err(card->dev, "Invalid dai link type %d\n",
1176 dai_link->dobj.type);
1177 return -EINVAL;
1178 }
1179
1180 lockdep_assert_held(&client_mutex);
Mengdong Lind6f220e2015-12-02 14:11:32 +08001181 /* Notify the machine driver for extra initialization
1182 * on the link created by topology.
1183 */
1184 if (dai_link->dobj.type && card->add_dai_link)
1185 card->add_dai_link(card, dai_link);
1186
Mengdong Linf8f80362015-12-02 14:11:22 +08001187 list_add_tail(&dai_link->list, &card->dai_link_list);
Mengdong Linf8f80362015-12-02 14:11:22 +08001188
1189 return 0;
1190}
1191EXPORT_SYMBOL_GPL(snd_soc_add_dai_link);
1192
1193/**
1194 * snd_soc_remove_dai_link - Remove a DAI link from the list
1195 * @card: The ASoC card that owns the link
1196 * @dai_link: The DAI link to remove
1197 *
1198 * This function removes a DAI link from the ASoC card's link list.
1199 *
1200 * For DAI links previously added by topology, topology should
1201 * remove them by using the dobj embedded in the link.
1202 */
1203void snd_soc_remove_dai_link(struct snd_soc_card *card,
1204 struct snd_soc_dai_link *dai_link)
1205{
1206 struct snd_soc_dai_link *link, *_link;
1207
1208 if (dai_link->dobj.type
1209 && dai_link->dobj.type != SND_SOC_DOBJ_DAI_LINK) {
1210 dev_err(card->dev, "Invalid dai link type %d\n",
1211 dai_link->dobj.type);
1212 return;
1213 }
1214
1215 lockdep_assert_held(&client_mutex);
Mengdong Lind6f220e2015-12-02 14:11:32 +08001216 /* Notify the machine driver for extra destruction
1217 * on the link created by topology.
1218 */
1219 if (dai_link->dobj.type && card->remove_dai_link)
1220 card->remove_dai_link(card, dai_link);
1221
Kuninori Morimoto98061fd2018-09-18 01:29:16 +00001222 for_each_card_links_safe(card, link, _link) {
Mengdong Linf8f80362015-12-02 14:11:22 +08001223 if (link == dai_link) {
1224 list_del(&link->list);
Mengdong Linf8f80362015-12-02 14:11:22 +08001225 return;
1226 }
1227 }
1228}
1229EXPORT_SYMBOL_GPL(snd_soc_remove_dai_link);
1230
Jerome Brunetaefba452018-07-13 14:50:43 +02001231static void soc_set_of_name_prefix(struct snd_soc_component *component)
1232{
1233 struct device_node *component_of_node = component->dev->of_node;
1234 const char *str;
1235 int ret;
1236
1237 if (!component_of_node && component->dev->parent)
1238 component_of_node = component->dev->parent->of_node;
1239
1240 ret = of_property_read_string(component_of_node, "sound-name-prefix",
1241 &str);
1242 if (!ret)
1243 component->name_prefix = str;
1244}
1245
Jarkko Nikulaead9b912010-11-13 20:40:44 +02001246static void soc_set_name_prefix(struct snd_soc_card *card,
Lars-Peter Clausen94f99c82014-06-16 18:13:01 +02001247 struct snd_soc_component *component)
Jarkko Nikulaead9b912010-11-13 20:40:44 +02001248{
1249 int i;
1250
Jerome Brunetaefba452018-07-13 14:50:43 +02001251 for (i = 0; i < card->num_configs && card->codec_conf; i++) {
Dimitris Papastamosff819b82010-12-02 14:53:03 +00001252 struct snd_soc_codec_conf *map = &card->codec_conf[i];
Charles Keepaxb24c5392018-04-27 13:54:36 +01001253 struct device_node *component_of_node = component->dev->of_node;
1254
1255 if (!component_of_node && component->dev->parent)
1256 component_of_node = component->dev->parent->of_node;
1257
1258 if (map->of_node && component_of_node != map->of_node)
Sebastian Reichel3ca041e2014-04-28 16:07:22 +02001259 continue;
Lars-Peter Clausen94f99c82014-06-16 18:13:01 +02001260 if (map->dev_name && strcmp(component->name, map->dev_name))
Sebastian Reichel3ca041e2014-04-28 16:07:22 +02001261 continue;
Lars-Peter Clausen94f99c82014-06-16 18:13:01 +02001262 component->name_prefix = map->name_prefix;
Jerome Brunetaefba452018-07-13 14:50:43 +02001263 return;
Jarkko Nikulaead9b912010-11-13 20:40:44 +02001264 }
Jerome Brunetaefba452018-07-13 14:50:43 +02001265
1266 /*
1267 * If there is no configuration table or no match in the table,
1268 * check if a prefix is provided in the node
1269 */
1270 soc_set_of_name_prefix(component);
Jarkko Nikulaead9b912010-11-13 20:40:44 +02001271}
1272
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001273static int soc_probe_component(struct snd_soc_card *card,
1274 struct snd_soc_component *component)
Jarkko Nikula589c3562010-12-06 16:27:07 +02001275{
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001276 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
Mark Brown888df392012-02-16 19:37:51 -08001277 struct snd_soc_dai *dai;
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001278 int ret;
Jarkko Nikula589c3562010-12-06 16:27:07 +02001279
Lars-Peter Clausen1b7c1232015-07-08 20:47:43 +02001280 if (!strcmp(component->name, "snd-soc-dummy"))
Lars-Peter Clausen70090bb2014-08-19 15:51:24 +02001281 return 0;
Jarkko Nikula589c3562010-12-06 16:27:07 +02001282
Lars-Peter Clausenabd31b32015-07-08 20:47:44 +02001283 if (component->card) {
Lars-Peter Clausen1b7c1232015-07-08 20:47:43 +02001284 if (component->card != card) {
1285 dev_err(component->dev,
1286 "Trying to bind component to card \"%s\" but is already bound to card \"%s\"\n",
1287 card->name, component->card->name);
1288 return -ENODEV;
1289 }
1290 return 0;
1291 }
1292
Lars-Peter Clausenabd31b32015-07-08 20:47:44 +02001293 if (!try_module_get(component->dev->driver->owner))
1294 return -ENODEV;
1295
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001296 component->card = card;
1297 dapm->card = card;
1298 soc_set_name_prefix(card, component);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001299
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001300 soc_init_component_debugfs(component);
Lars-Peter Clausend5d1e0b2011-04-30 19:45:49 +02001301
Kuninori Morimoto688d0eb2017-08-25 00:29:20 +00001302 if (component->driver->dapm_widgets) {
1303 ret = snd_soc_dapm_new_controls(dapm,
1304 component->driver->dapm_widgets,
1305 component->driver->num_dapm_widgets);
Nariman Poushinb318ad52014-04-01 13:59:33 +01001306
1307 if (ret != 0) {
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001308 dev_err(component->dev,
Nariman Poushinb318ad52014-04-01 13:59:33 +01001309 "Failed to create new controls %d\n", ret);
1310 goto err_probe;
1311 }
1312 }
Lars-Peter Clausen77530152011-05-05 16:59:09 +02001313
Lars-Peter Clausen06348142014-08-20 13:08:49 +02001314 list_for_each_entry(dai, &component->dai_list, list) {
1315 ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
Nariman Poushin261edc72014-03-31 15:47:12 +01001316 if (ret != 0) {
Lars-Peter Clausen06348142014-08-20 13:08:49 +02001317 dev_err(component->dev,
Nariman Poushin261edc72014-03-31 15:47:12 +01001318 "Failed to create DAI widgets %d\n", ret);
1319 goto err_probe;
1320 }
1321 }
Mark Brown888df392012-02-16 19:37:51 -08001322
Kuninori Morimoto999f7f52018-05-08 03:20:24 +00001323 if (component->driver->probe) {
1324 ret = component->driver->probe(component);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001325 if (ret < 0) {
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001326 dev_err(component->dev,
1327 "ASoC: failed to probe component %d\n", ret);
Jarkko Nikula70d293312011-01-27 16:24:22 +02001328 goto err_probe;
Jarkko Nikula589c3562010-12-06 16:27:07 +02001329 }
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001330
1331 WARN(dapm->idle_bias_off &&
1332 dapm->bias_level != SND_SOC_BIAS_OFF,
Michał Mirosław10e8aa92013-05-04 22:21:38 +02001333 "codec %s can not start from non-off bias with idle_bias_off==1\n",
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001334 component->name);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001335 }
1336
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001337 /* machine specific init */
1338 if (component->init) {
1339 ret = component->init(component);
1340 if (ret < 0) {
1341 dev_err(component->dev,
1342 "Failed to do machine specific init %d\n", ret);
1343 goto err_probe;
1344 }
1345 }
1346
Kuninori Morimotob8972bf2017-08-25 00:29:01 +00001347 if (component->driver->controls)
1348 snd_soc_add_component_controls(component,
1349 component->driver->controls,
1350 component->driver->num_controls);
Kuninori Morimoto6969b2b2017-08-25 00:29:41 +00001351 if (component->driver->dapm_routes)
1352 snd_soc_dapm_add_routes(dapm,
1353 component->driver->dapm_routes,
1354 component->driver->num_dapm_routes);
Mark Brown89b95ac02011-03-07 16:38:44 +00001355
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001356 list_add(&dapm->list, &card->dapm_list);
Kuninori Morimotod9fc4062016-11-30 06:22:36 +00001357 list_add(&component->card_list, &card->component_dev_list);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001358
Jarkko Nikula70d293312011-01-27 16:24:22 +02001359 return 0;
1360
1361err_probe:
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001362 soc_cleanup_component_debugfs(component);
Lars-Peter Clausenabd31b32015-07-08 20:47:44 +02001363 component->card = NULL;
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001364 module_put(component->dev->driver->owner);
Liam Girdwood956245e2011-07-01 16:54:08 +01001365
1366 return ret;
1367}
1368
Mark Brown36ae1a92012-01-06 17:12:45 -08001369static void rtd_release(struct device *dev)
1370{
1371 kfree(dev);
1372}
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001373
Lars-Peter Clausen5f3484a2014-07-01 22:13:48 +02001374static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd,
1375 const char *name)
Misael Lopez Cruz503ae5e2014-04-24 14:01:44 +02001376{
Jarkko Nikula589c3562010-12-06 16:27:07 +02001377 int ret = 0;
1378
Jarkko Nikula589c3562010-12-06 16:27:07 +02001379 /* register the rtd device */
Mark Brown36ae1a92012-01-06 17:12:45 -08001380 rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
1381 if (!rtd->dev)
1382 return -ENOMEM;
1383 device_initialize(rtd->dev);
Lars-Peter Clausen5f3484a2014-07-01 22:13:48 +02001384 rtd->dev->parent = rtd->card->dev;
Mark Brown36ae1a92012-01-06 17:12:45 -08001385 rtd->dev->release = rtd_release;
Takashi Iwaid29697d2015-01-30 20:16:37 +01001386 rtd->dev->groups = soc_dev_attr_groups;
Lars-Peter Clausenf294afe2014-08-17 11:28:35 +02001387 dev_set_name(rtd->dev, "%s", name);
Mark Brown36ae1a92012-01-06 17:12:45 -08001388 dev_set_drvdata(rtd->dev, rtd);
Liam Girdwoodb8c0dab2011-06-09 17:04:39 +01001389 mutex_init(&rtd->pcm_mutex);
Liam Girdwood01d75842012-04-25 12:12:49 +01001390 INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients);
1391 INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients);
1392 INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients);
1393 INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
Mark Brown36ae1a92012-01-06 17:12:45 -08001394 ret = device_add(rtd->dev);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001395 if (ret < 0) {
Chuansheng Liu865df9c2012-12-26 00:56:05 +08001396 /* calling put_device() here to free the rtd->dev */
1397 put_device(rtd->dev);
Lars-Peter Clausen5f3484a2014-07-01 22:13:48 +02001398 dev_err(rtd->card->dev,
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00001399 "ASoC: failed to register runtime device: %d\n", ret);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001400 return ret;
1401 }
1402 rtd->dev_registered = 1;
Jarkko Nikula589c3562010-12-06 16:27:07 +02001403 return 0;
1404}
1405
Mengdong Lin1a497982015-11-18 02:34:11 -05001406static int soc_probe_link_components(struct snd_soc_card *card,
1407 struct snd_soc_pcm_runtime *rtd,
Stephen Warren62ae68f2012-06-08 12:34:23 -06001408 int order)
1409{
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001410 struct snd_soc_component *component;
Kuninori Morimoto90be7112017-08-08 06:18:10 +00001411 struct snd_soc_rtdcom_list *rtdcom;
1412 int ret;
Stephen Warren62ae68f2012-06-08 12:34:23 -06001413
Kuninori Morimoto90be7112017-08-08 06:18:10 +00001414 for_each_rtdcom(rtd, rtdcom) {
1415 component = rtdcom->component;
Stephen Warren62ae68f2012-06-08 12:34:23 -06001416
Lars-Peter Clausen70090bb2014-08-19 15:51:24 +02001417 if (component->driver->probe_order == order) {
Lars-Peter Clausenf1d45cc32014-08-19 15:51:19 +02001418 ret = soc_probe_component(card, component);
Benoit Cousson88bd8702014-07-08 23:19:34 +02001419 if (ret < 0)
1420 return ret;
1421 }
Stephen Warren62ae68f2012-06-08 12:34:23 -06001422 }
1423
Stephen Warren62ae68f2012-06-08 12:34:23 -06001424 return 0;
1425}
1426
Lars-Peter Clausen8e2be562014-11-04 11:30:59 +01001427static int soc_probe_dai(struct snd_soc_dai *dai, int order)
Misael Lopez Cruzb0aa88a2014-03-21 16:27:26 +01001428{
Kuninori Morimoto7a2ccad2018-02-14 02:58:03 +00001429 if (dai->probed ||
1430 dai->driver->probe_order != order)
1431 return 0;
Misael Lopez Cruzb0aa88a2014-03-21 16:27:26 +01001432
Kuninori Morimoto7a2ccad2018-02-14 02:58:03 +00001433 if (dai->driver->probe) {
1434 int ret = dai->driver->probe(dai);
1435 if (ret < 0) {
1436 dev_err(dai->dev, "ASoC: failed to probe DAI %s: %d\n",
1437 dai->name, ret);
1438 return ret;
Misael Lopez Cruzb0aa88a2014-03-21 16:27:26 +01001439 }
Misael Lopez Cruzb0aa88a2014-03-21 16:27:26 +01001440 }
1441
Kuninori Morimoto7a2ccad2018-02-14 02:58:03 +00001442 dai->probed = 1;
1443
Misael Lopez Cruzb0aa88a2014-03-21 16:27:26 +01001444 return 0;
1445}
1446
Arnaud Pouliquen25f7b702017-01-03 16:52:51 +01001447static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais,
1448 struct snd_soc_pcm_runtime *rtd)
1449{
1450 int i, ret = 0;
1451
1452 for (i = 0; i < num_dais; ++i) {
1453 struct snd_soc_dai_driver *drv = dais[i]->driver;
1454
1455 if (!rtd->dai_link->no_pcm && drv->pcm_new)
1456 ret = drv->pcm_new(rtd, dais[i]);
1457 if (ret < 0) {
1458 dev_err(dais[i]->dev,
1459 "ASoC: Failed to bind %s with pcm device\n",
1460 dais[i]->name);
1461 return ret;
1462 }
1463 }
1464
1465 return 0;
1466}
1467
Mengdong Lin1a497982015-11-18 02:34:11 -05001468static int soc_probe_link_dais(struct snd_soc_card *card,
1469 struct snd_soc_pcm_runtime *rtd, int order)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001470{
Mengdong Lin1a497982015-11-18 02:34:11 -05001471 struct snd_soc_dai_link *dai_link = rtd->dai_link;
Mark Brownc74184e2012-04-04 22:12:09 +01001472 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Liam Girdwooda655de82018-07-02 16:59:54 +01001473 struct snd_soc_rtdcom_list *rtdcom;
1474 struct snd_soc_component *component;
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +00001475 struct snd_soc_dai *codec_dai;
Liam Girdwooda655de82018-07-02 16:59:54 +01001476 int i, ret, num;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001477
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00001478 dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n",
Mengdong Lin1a497982015-11-18 02:34:11 -05001479 card->name, rtd->num, order);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001480
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001481 /* set default power off timeout */
1482 rtd->pmdown_time = pmdown_time;
1483
Lars-Peter Clausen8e2be562014-11-04 11:30:59 +01001484 ret = soc_probe_dai(cpu_dai, order);
1485 if (ret)
1486 return ret;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001487
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001488 /* probe the CODEC DAI */
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +00001489 for_each_rtd_codec_dai(rtd, i, codec_dai) {
1490 ret = soc_probe_dai(codec_dai, order);
Benoit Cousson88bd8702014-07-08 23:19:34 +02001491 if (ret)
1492 return ret;
1493 }
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001494
Liam Girdwood0168bf02011-06-07 16:08:05 +01001495 /* complete DAI probe during last probe */
1496 if (order != SND_SOC_COMP_ORDER_LAST)
1497 return 0;
1498
Lars-Peter Clausen5f3484a2014-07-01 22:13:48 +02001499 /* do machine specific initialization */
1500 if (dai_link->init) {
1501 ret = dai_link->init(rtd);
1502 if (ret < 0) {
1503 dev_err(card->dev, "ASoC: failed to init %s: %d\n",
1504 dai_link->name, ret);
1505 return ret;
1506 }
1507 }
1508
Kuninori Morimotoa5053a82015-04-10 09:47:00 +00001509 if (dai_link->dai_fmt)
1510 snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
1511
Lars-Peter Clausen5f3484a2014-07-01 22:13:48 +02001512 ret = soc_post_component_init(rtd, dai_link->name);
Jarkko Nikula589c3562010-12-06 16:27:07 +02001513 if (ret)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001514 return ret;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02001515
Lars-Peter Clausen5f3484a2014-07-01 22:13:48 +02001516#ifdef CONFIG_DEBUG_FS
1517 /* add DPCM sysfs entries */
Lars-Peter Clausen2e55b902015-04-09 10:52:37 +02001518 if (dai_link->dynamic)
1519 soc_dpcm_debugfs_add(rtd);
Lars-Peter Clausen5f3484a2014-07-01 22:13:48 +02001520#endif
1521
Liam Girdwooda655de82018-07-02 16:59:54 +01001522 num = rtd->num;
1523
1524 /*
1525 * most drivers will register their PCMs using DAI link ordering but
1526 * topology based drivers can use the DAI link id field to set PCM
1527 * device number and then use rtd + a base offset of the BEs.
1528 */
1529 for_each_rtdcom(rtd, rtdcom) {
1530 component = rtdcom->component;
1531
1532 if (!component->driver->use_dai_pcm_id)
1533 continue;
1534
1535 if (rtd->dai_link->no_pcm)
1536 num += component->driver->be_pcm_base;
1537 else
1538 num = rtd->dai_link->id;
1539 }
1540
Jie Yang6f0c4222015-10-13 23:41:00 +08001541 if (cpu_dai->driver->compress_new) {
Namarta Kohli1245b702012-08-16 17:10:41 +05301542 /*create compress_device"*/
Liam Girdwooda655de82018-07-02 16:59:54 +01001543 ret = cpu_dai->driver->compress_new(rtd, num);
Mark Brownc74184e2012-04-04 22:12:09 +01001544 if (ret < 0) {
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00001545 dev_err(card->dev, "ASoC: can't create compress %s\n",
Namarta Kohli1245b702012-08-16 17:10:41 +05301546 dai_link->stream_name);
Mark Brownc74184e2012-04-04 22:12:09 +01001547 return ret;
1548 }
1549 } else {
Namarta Kohli1245b702012-08-16 17:10:41 +05301550
1551 if (!dai_link->params) {
1552 /* create the pcm */
Liam Girdwooda655de82018-07-02 16:59:54 +01001553 ret = soc_new_pcm(rtd, num);
Namarta Kohli1245b702012-08-16 17:10:41 +05301554 if (ret < 0) {
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00001555 dev_err(card->dev, "ASoC: can't create pcm %s :%d\n",
Namarta Kohli1245b702012-08-16 17:10:41 +05301556 dai_link->stream_name, ret);
Mark Brownc74184e2012-04-04 22:12:09 +01001557 return ret;
1558 }
Arnaud Pouliquen25f7b702017-01-03 16:52:51 +01001559 ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd);
1560 if (ret < 0)
1561 return ret;
1562 ret = soc_link_dai_pcm_new(rtd->codec_dais,
1563 rtd->num_codecs, rtd);
1564 if (ret < 0)
1565 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +05301566 } else {
Richard Fitzgerald9d58a072013-08-05 13:17:28 +01001567 INIT_DELAYED_WORK(&rtd->delayed_work,
1568 codec2codec_close_delayed_work);
Mark Brownc74184e2012-04-04 22:12:09 +01001569 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001570 }
1571
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001572 return 0;
1573}
1574
Lars-Peter Clausen44c69bb2014-07-01 22:13:47 +02001575static int soc_bind_aux_dev(struct snd_soc_card *card, int num)
Mark Brownb19e6e72012-03-14 21:18:39 +00001576{
Sebastian Reichel3ca041e2014-04-28 16:07:22 +02001577 struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001578 struct snd_soc_component *component;
1579 const char *name;
1580 struct device_node *codec_of_node;
Sebastian Reichel3ca041e2014-04-28 16:07:22 +02001581
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001582 if (aux_dev->codec_of_node || aux_dev->codec_name) {
1583 /* codecs, usually analog devices */
1584 name = aux_dev->codec_name;
1585 codec_of_node = aux_dev->codec_of_node;
1586 component = soc_find_component(codec_of_node, name);
1587 if (!component) {
1588 if (codec_of_node)
1589 name = of_node_full_name(codec_of_node);
1590 goto err_defer;
1591 }
1592 } else if (aux_dev->name) {
1593 /* generic components */
1594 name = aux_dev->name;
1595 component = soc_find_component(NULL, name);
1596 if (!component)
1597 goto err_defer;
1598 } else {
1599 dev_err(card->dev, "ASoC: Invalid auxiliary device\n");
1600 return -EINVAL;
Lars-Peter Clausen44c69bb2014-07-01 22:13:47 +02001601 }
1602
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001603 component->init = aux_dev->init;
Sylwester Nawrockid2e3a132016-12-29 14:11:21 +01001604 list_add(&component->card_aux_list, &card->aux_comp_list);
Kuninori Morimoto1a653aa2016-11-30 06:22:55 +00001605
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001606 return 0;
1607
1608err_defer:
1609 dev_err(card->dev, "ASoC: %s not registered\n", name);
1610 return -EPROBE_DEFER;
1611}
1612
1613static int soc_probe_aux_devices(struct snd_soc_card *card)
1614{
Kuninori Morimoto991454e2017-03-24 00:13:00 +00001615 struct snd_soc_component *comp;
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001616 int order;
1617 int ret;
1618
1619 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1620 order++) {
Kuninori Morimoto991454e2017-03-24 00:13:00 +00001621 list_for_each_entry(comp, &card->aux_comp_list, card_aux_list) {
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001622 if (comp->driver->probe_order == order) {
1623 ret = soc_probe_component(card, comp);
1624 if (ret < 0) {
1625 dev_err(card->dev,
1626 "ASoC: failed to probe aux component %s %d\n",
1627 comp->name, ret);
1628 return ret;
1629 }
1630 }
1631 }
1632 }
Lars-Peter Clausen65d93612014-08-19 15:51:22 +02001633
Lars-Peter Clausen44c69bb2014-07-01 22:13:47 +02001634 return 0;
Mark Brownb19e6e72012-03-14 21:18:39 +00001635}
1636
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001637static void soc_remove_aux_devices(struct snd_soc_card *card)
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001638{
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001639 struct snd_soc_component *comp, *_comp;
1640 int order;
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001641
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001642 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1643 order++) {
1644 list_for_each_entry_safe(comp, _comp,
Kuninori Morimoto991454e2017-03-24 00:13:00 +00001645 &card->aux_comp_list, card_aux_list) {
Kuninori Morimoto1a653aa2016-11-30 06:22:55 +00001646
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001647 if (comp->driver->remove_order == order) {
1648 soc_remove_component(comp);
Kuninori Morimoto991454e2017-03-24 00:13:00 +00001649 /* remove it from the card's aux_comp_list */
1650 list_del(&comp->card_aux_list);
Mengdong Linf2ed6b02016-01-06 13:29:31 +08001651 }
Lars-Peter Clausen5f3484a2014-07-01 22:13:48 +02001652 }
1653 }
Jarkko Nikula2eea3922010-11-25 17:47:38 +02001654}
1655
Lars-Peter Clausence64c8b2015-01-06 15:17:20 +01001656/**
1657 * snd_soc_runtime_set_dai_fmt() - Change DAI link format for a ASoC runtime
1658 * @rtd: The runtime for which the DAI link format should be changed
1659 * @dai_fmt: The new DAI link format
1660 *
1661 * This function updates the DAI link format for all DAIs connected to the DAI
1662 * link for the specified runtime.
1663 *
1664 * Note: For setups with a static format set the dai_fmt field in the
1665 * corresponding snd_dai_link struct instead of using this function.
1666 *
1667 * Returns 0 on success, otherwise a negative error code.
1668 */
1669int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
1670 unsigned int dai_fmt)
1671{
Lars-Peter Clausence64c8b2015-01-06 15:17:20 +01001672 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +00001673 struct snd_soc_dai *codec_dai;
Lars-Peter Clausence64c8b2015-01-06 15:17:20 +01001674 unsigned int i;
1675 int ret;
1676
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +00001677 for_each_rtd_codec_dai(rtd, i, codec_dai) {
Lars-Peter Clausence64c8b2015-01-06 15:17:20 +01001678 ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
1679 if (ret != 0 && ret != -ENOTSUPP) {
1680 dev_warn(codec_dai->dev,
1681 "ASoC: Failed to set DAI format: %d\n", ret);
1682 return ret;
1683 }
1684 }
1685
1686 /* Flip the polarity for the "CPU" end of a CODEC<->CODEC link */
Kuninori Morimotocb2cf0d2017-12-15 05:10:47 +00001687 /* the component which has non_legacy_dai_naming is Codec */
Kuninori Morimoto999f7f52018-05-08 03:20:24 +00001688 if (cpu_dai->component->driver->non_legacy_dai_naming) {
Lars-Peter Clausence64c8b2015-01-06 15:17:20 +01001689 unsigned int inv_dai_fmt;
1690
1691 inv_dai_fmt = dai_fmt & ~SND_SOC_DAIFMT_MASTER_MASK;
1692 switch (dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1693 case SND_SOC_DAIFMT_CBM_CFM:
1694 inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
1695 break;
1696 case SND_SOC_DAIFMT_CBM_CFS:
1697 inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
1698 break;
1699 case SND_SOC_DAIFMT_CBS_CFM:
1700 inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFS;
1701 break;
1702 case SND_SOC_DAIFMT_CBS_CFS:
1703 inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
1704 break;
1705 }
1706
1707 dai_fmt = inv_dai_fmt;
1708 }
1709
1710 ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
1711 if (ret != 0 && ret != -ENOTSUPP) {
1712 dev_warn(cpu_dai->dev,
1713 "ASoC: Failed to set DAI format: %d\n", ret);
1714 return ret;
1715 }
1716
1717 return 0;
1718}
Lars-Peter Clausenddaca252015-01-08 12:23:05 +01001719EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt);
Lars-Peter Clausence64c8b2015-01-06 15:17:20 +01001720
Liam Girdwood345233d2017-01-14 16:13:02 +08001721
Takashi Iwai1f5a4532017-04-24 08:54:41 +02001722#ifdef CONFIG_DMI
Liam Girdwood345233d2017-01-14 16:13:02 +08001723/* Trim special characters, and replace '-' with '_' since '-' is used to
1724 * separate different DMI fields in the card long name. Only number and
1725 * alphabet characters and a few separator characters are kept.
1726 */
1727static void cleanup_dmi_name(char *name)
1728{
1729 int i, j = 0;
1730
1731 for (i = 0; name[i]; i++) {
1732 if (isalnum(name[i]) || (name[i] == '.')
1733 || (name[i] == '_'))
1734 name[j++] = name[i];
1735 else if (name[i] == '-')
1736 name[j++] = '_';
1737 }
1738
1739 name[j] = '\0';
1740}
1741
Mengdong Lin98faf432017-06-28 15:01:39 +08001742/* Check if a DMI field is valid, i.e. not containing any string
1743 * in the black list.
1744 */
1745static int is_dmi_valid(const char *field)
1746{
1747 int i = 0;
1748
1749 while (dmi_blacklist[i]) {
1750 if (strstr(field, dmi_blacklist[i]))
1751 return 0;
1752 i++;
Wu Fengguang46b5a4d2017-06-30 00:27:13 +08001753 }
Mengdong Lin98faf432017-06-28 15:01:39 +08001754
1755 return 1;
1756}
1757
Liam Girdwood345233d2017-01-14 16:13:02 +08001758/**
1759 * snd_soc_set_dmi_name() - Register DMI names to card
1760 * @card: The card to register DMI names
1761 * @flavour: The flavour "differentiator" for the card amongst its peers.
1762 *
1763 * An Intel machine driver may be used by many different devices but are
1764 * difficult for userspace to differentiate, since machine drivers ususally
1765 * use their own name as the card short name and leave the card long name
1766 * blank. To differentiate such devices and fix bugs due to lack of
1767 * device-specific configurations, this function allows DMI info to be used
1768 * as the sound card long name, in the format of
1769 * "vendor-product-version-board"
1770 * (Character '-' is used to separate different DMI fields here).
1771 * This will help the user space to load the device-specific Use Case Manager
1772 * (UCM) configurations for the card.
1773 *
1774 * Possible card long names may be:
1775 * DellInc.-XPS139343-01-0310JH
1776 * ASUSTeKCOMPUTERINC.-T100TA-1.0-T100TA
1777 * Circuitco-MinnowboardMaxD0PLATFORM-D0-MinnowBoardMAX
1778 *
1779 * This function also supports flavoring the card longname to provide
1780 * the extra differentiation, like "vendor-product-version-board-flavor".
1781 *
1782 * We only keep number and alphabet characters and a few separator characters
1783 * in the card long name since UCM in the user space uses the card long names
1784 * as card configuration directory names and AudoConf cannot support special
1785 * charactors like SPACE.
1786 *
1787 * Returns 0 on success, otherwise a negative error code.
1788 */
1789int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
1790{
1791 const char *vendor, *product, *product_version, *board;
1792 size_t longname_buf_size = sizeof(card->snd_card->longname);
1793 size_t len;
1794
1795 if (card->long_name)
1796 return 0; /* long name already set by driver or from DMI */
1797
1798 /* make up dmi long name as: vendor.product.version.board */
1799 vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
Mengdong Lin98faf432017-06-28 15:01:39 +08001800 if (!vendor || !is_dmi_valid(vendor)) {
Liam Girdwood345233d2017-01-14 16:13:02 +08001801 dev_warn(card->dev, "ASoC: no DMI vendor name!\n");
1802 return 0;
1803 }
1804
Mengdong Lin98faf432017-06-28 15:01:39 +08001805
Liam Girdwood345233d2017-01-14 16:13:02 +08001806 snprintf(card->dmi_longname, sizeof(card->snd_card->longname),
1807 "%s", vendor);
1808 cleanup_dmi_name(card->dmi_longname);
1809
1810 product = dmi_get_system_info(DMI_PRODUCT_NAME);
Mengdong Lin98faf432017-06-28 15:01:39 +08001811 if (product && is_dmi_valid(product)) {
Liam Girdwood345233d2017-01-14 16:13:02 +08001812 len = strlen(card->dmi_longname);
1813 snprintf(card->dmi_longname + len,
1814 longname_buf_size - len,
1815 "-%s", product);
1816
1817 len++; /* skip the separator "-" */
1818 if (len < longname_buf_size)
1819 cleanup_dmi_name(card->dmi_longname + len);
1820
1821 /* some vendors like Lenovo may only put a self-explanatory
1822 * name in the product version field
1823 */
1824 product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
Mengdong Lin98faf432017-06-28 15:01:39 +08001825 if (product_version && is_dmi_valid(product_version)) {
Liam Girdwood345233d2017-01-14 16:13:02 +08001826 len = strlen(card->dmi_longname);
1827 snprintf(card->dmi_longname + len,
1828 longname_buf_size - len,
1829 "-%s", product_version);
1830
1831 len++;
1832 if (len < longname_buf_size)
1833 cleanup_dmi_name(card->dmi_longname + len);
1834 }
1835 }
1836
1837 board = dmi_get_system_info(DMI_BOARD_NAME);
Mengdong Lin98faf432017-06-28 15:01:39 +08001838 if (board && is_dmi_valid(board)) {
Liam Girdwood345233d2017-01-14 16:13:02 +08001839 len = strlen(card->dmi_longname);
1840 snprintf(card->dmi_longname + len,
1841 longname_buf_size - len,
1842 "-%s", board);
1843
1844 len++;
1845 if (len < longname_buf_size)
1846 cleanup_dmi_name(card->dmi_longname + len);
1847 } else if (!product) {
1848 /* fall back to using legacy name */
1849 dev_warn(card->dev, "ASoC: no DMI board/product name!\n");
1850 return 0;
1851 }
1852
1853 /* Add flavour to dmi long name */
1854 if (flavour) {
1855 len = strlen(card->dmi_longname);
1856 snprintf(card->dmi_longname + len,
1857 longname_buf_size - len,
1858 "-%s", flavour);
1859
1860 len++;
1861 if (len < longname_buf_size)
1862 cleanup_dmi_name(card->dmi_longname + len);
1863 }
1864
1865 /* set the card long name */
1866 card->long_name = card->dmi_longname;
1867
1868 return 0;
1869}
1870EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name);
Takashi Iwai1f5a4532017-04-24 08:54:41 +02001871#endif /* CONFIG_DMI */
Liam Girdwood345233d2017-01-14 16:13:02 +08001872
Liam Girdwooda655de82018-07-02 16:59:54 +01001873static void soc_check_tplg_fes(struct snd_soc_card *card)
1874{
1875 struct snd_soc_component *component;
1876 const struct snd_soc_component_driver *comp_drv;
1877 struct snd_soc_dai_link *dai_link;
1878 int i;
1879
1880 list_for_each_entry(component, &component_list, list) {
1881
1882 /* does this component override FEs ? */
1883 if (!component->driver->ignore_machine)
1884 continue;
1885
1886 /* for this machine ? */
1887 if (strcmp(component->driver->ignore_machine,
1888 card->dev->driver->name))
1889 continue;
1890
1891 /* machine matches, so override the rtd data */
Kuninori Morimoto7fe072b2018-09-18 01:28:49 +00001892 for_each_card_prelinks(card, i, dai_link) {
Liam Girdwooda655de82018-07-02 16:59:54 +01001893
1894 /* ignore this FE */
1895 if (dai_link->dynamic) {
1896 dai_link->ignore = true;
1897 continue;
1898 }
1899
1900 dev_info(card->dev, "info: override FE DAI link %s\n",
1901 card->dai_link[i].name);
1902
1903 /* override platform component */
Kuninori Morimotodaecf462018-08-31 03:10:08 +00001904 if (snd_soc_init_platform(card, dai_link) < 0) {
1905 dev_err(card->dev, "init platform error");
1906 continue;
1907 }
1908 dai_link->platform->name = component->name;
Liam Girdwooda655de82018-07-02 16:59:54 +01001909
1910 /* convert non BE into BE */
1911 dai_link->no_pcm = 1;
1912
1913 /* override any BE fixups */
1914 dai_link->be_hw_params_fixup =
1915 component->driver->be_hw_params_fixup;
1916
1917 /* most BE links don't set stream name, so set it to
1918 * dai link name if it's NULL to help bind widgets.
1919 */
1920 if (!dai_link->stream_name)
1921 dai_link->stream_name = dai_link->name;
1922 }
1923
1924 /* Inform userspace we are using alternate topology */
1925 if (component->driver->topology_name_prefix) {
1926
1927 /* topology shortname created ? */
1928 if (!card->topology_shortname_created) {
1929 comp_drv = component->driver;
1930
1931 snprintf(card->topology_shortname, 32, "%s-%s",
1932 comp_drv->topology_name_prefix,
1933 card->name);
1934 card->topology_shortname_created = true;
1935 }
1936
1937 /* use topology shortname */
1938 card->name = card->topology_shortname;
1939 }
1940 }
1941}
1942
Mark Brownb19e6e72012-03-14 21:18:39 +00001943static int snd_soc_instantiate_card(struct snd_soc_card *card)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001944{
Mengdong Lin1a497982015-11-18 02:34:11 -05001945 struct snd_soc_pcm_runtime *rtd;
Mengdong Lin61b00882015-12-02 14:11:48 +08001946 struct snd_soc_dai_link *dai_link;
Lars-Peter Clausence64c8b2015-01-06 15:17:20 +01001947 int ret, i, order;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001948
Lars-Peter Clausen34e81ab2015-03-07 19:34:03 +01001949 mutex_lock(&client_mutex);
Liam Girdwood01b9d992012-03-07 10:38:25 +00001950 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001951
Liam Girdwooda655de82018-07-02 16:59:54 +01001952 /* check whether any platform is ignore machine FE and using topology */
1953 soc_check_tplg_fes(card);
1954
Mark Brownb19e6e72012-03-14 21:18:39 +00001955 /* bind DAIs */
Kuninori Morimoto7fe072b2018-09-18 01:28:49 +00001956 for_each_card_prelinks(card, i, dai_link) {
1957 ret = soc_bind_dai_link(card, dai_link);
Mark Brownb19e6e72012-03-14 21:18:39 +00001958 if (ret != 0)
1959 goto base_error;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001960 }
1961
Lars-Peter Clausen44c69bb2014-07-01 22:13:47 +02001962 /* bind aux_devs too */
Mark Brownb19e6e72012-03-14 21:18:39 +00001963 for (i = 0; i < card->num_aux_devs; i++) {
Lars-Peter Clausen44c69bb2014-07-01 22:13:47 +02001964 ret = soc_bind_aux_dev(card, i);
Mark Brownb19e6e72012-03-14 21:18:39 +00001965 if (ret != 0)
1966 goto base_error;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001967 }
1968
Mengdong Linf8f80362015-12-02 14:11:22 +08001969 /* add predefined DAI links to the list */
Kuninori Morimoto7fe072b2018-09-18 01:28:49 +00001970 for_each_card_prelinks(card, i, dai_link)
1971 snd_soc_add_dai_link(card, dai_link);
Mengdong Linf8f80362015-12-02 14:11:22 +08001972
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001973 /* card bind complete so register a sound card */
Takashi Iwai102b5a82014-01-29 14:42:55 +01001974 ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001975 card->owner, 0, &card->snd_card);
1976 if (ret < 0) {
Michał Mirosław10e8aa92013-05-04 22:21:38 +02001977 dev_err(card->dev,
1978 "ASoC: can't create sound card for card %s: %d\n",
1979 card->name, ret);
Mark Brownb19e6e72012-03-14 21:18:39 +00001980 goto base_error;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001981 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00001982
Lars-Peter Clausen0757d832015-04-09 10:52:36 +02001983 soc_init_card_debugfs(card);
1984
Mark Browne37a4972011-03-02 18:21:57 +00001985 card->dapm.bias_level = SND_SOC_BIAS_OFF;
1986 card->dapm.dev = card->dev;
1987 card->dapm.card = card;
1988 list_add(&card->dapm.list, &card->dapm_list);
1989
Lars-Peter Clausend5d1e0b2011-04-30 19:45:49 +02001990#ifdef CONFIG_DEBUG_FS
1991 snd_soc_dapm_debugfs_init(&card->dapm, card->debugfs_card_root);
1992#endif
1993
Mark Brown88ee1c62011-02-02 10:43:26 +00001994#ifdef CONFIG_PM_SLEEP
Andy Green6ed25972008-06-13 16:24:05 +01001995 /* deferred resume work */
Mark Brown63084192008-12-02 15:08:03 +00001996 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
Randy Dunlap1301a962008-06-17 19:19:34 +01001997#endif
Andy Green6ed25972008-06-13 16:24:05 +01001998
Mark Brown9a841eb2011-04-12 17:51:37 -07001999 if (card->dapm_widgets)
2000 snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets,
2001 card->num_dapm_widgets);
2002
Nicolin Chenf23e8602015-02-14 17:22:49 -08002003 if (card->of_dapm_widgets)
2004 snd_soc_dapm_new_controls(&card->dapm, card->of_dapm_widgets,
2005 card->num_of_dapm_widgets);
2006
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002007 /* initialise the sound card only once */
2008 if (card->probe) {
Mark Browne7361ec2011-01-26 14:17:20 +00002009 ret = card->probe(card);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002010 if (ret < 0)
2011 goto card_probe_error;
2012 }
2013
Stephen Warren62ae68f2012-06-08 12:34:23 -06002014 /* probe all components used by DAI links on this card */
Liam Girdwood0168bf02011-06-07 16:08:05 +01002015 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
2016 order++) {
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +00002017 for_each_card_rtds(card, rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -05002018 ret = soc_probe_link_components(card, rtd, order);
Liam Girdwood0168bf02011-06-07 16:08:05 +01002019 if (ret < 0) {
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00002020 dev_err(card->dev,
2021 "ASoC: failed to instantiate card %d\n",
2022 ret);
Stephen Warren62ae68f2012-06-08 12:34:23 -06002023 goto probe_dai_err;
2024 }
2025 }
2026 }
2027
Mengdong Linf2ed6b02016-01-06 13:29:31 +08002028 /* probe auxiliary components */
2029 ret = soc_probe_aux_devices(card);
2030 if (ret < 0)
2031 goto probe_dai_err;
2032
Mengdong Lin61b00882015-12-02 14:11:48 +08002033 /* Find new DAI links added during probing components and bind them.
2034 * Components with topology may bring new DAIs and DAI links.
2035 */
Kuninori Morimoto98061fd2018-09-18 01:29:16 +00002036 for_each_card_links(card, dai_link) {
Mengdong Lin61b00882015-12-02 14:11:48 +08002037 if (soc_is_dai_link_bound(card, dai_link))
2038 continue;
2039
2040 ret = soc_init_dai_link(card, dai_link);
2041 if (ret)
2042 goto probe_dai_err;
2043 ret = soc_bind_dai_link(card, dai_link);
2044 if (ret)
2045 goto probe_dai_err;
2046 }
2047
Stephen Warren62ae68f2012-06-08 12:34:23 -06002048 /* probe all DAI links on this card */
2049 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
2050 order++) {
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +00002051 for_each_card_rtds(card, rtd) {
Mengdong Lin1a497982015-11-18 02:34:11 -05002052 ret = soc_probe_link_dais(card, rtd, order);
Stephen Warren62ae68f2012-06-08 12:34:23 -06002053 if (ret < 0) {
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00002054 dev_err(card->dev,
2055 "ASoC: failed to instantiate card %d\n",
2056 ret);
Liam Girdwood0168bf02011-06-07 16:08:05 +01002057 goto probe_dai_err;
2058 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002059 }
2060 }
2061
Mark Brown888df392012-02-16 19:37:51 -08002062 snd_soc_dapm_link_dai_widgets(card);
Liam Girdwoodb893ea52014-01-08 10:40:19 +00002063 snd_soc_dapm_connect_dai_link_widgets(card);
Mark Brown888df392012-02-16 19:37:51 -08002064
Mark Brownb7af1da2011-04-07 19:18:44 +09002065 if (card->controls)
Liam Girdwood022658b2012-02-03 17:43:09 +00002066 snd_soc_add_card_controls(card, card->controls, card->num_controls);
Mark Brownb7af1da2011-04-07 19:18:44 +09002067
Mark Brownb8ad29d2011-03-02 18:35:51 +00002068 if (card->dapm_routes)
2069 snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
2070 card->num_dapm_routes);
2071
Nicolin Chenf23e8602015-02-14 17:22:49 -08002072 if (card->of_dapm_routes)
2073 snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes,
2074 card->num_of_dapm_routes);
Mark Brown75d9ac42011-09-27 16:41:01 +01002075
Takashi Iwai861886d2017-04-24 08:54:42 +02002076 /* try to set some sane longname if DMI is available */
2077 snd_soc_set_dmi_name(card, NULL);
2078
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002079 snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002080 "%s", card->name);
Liam Girdwood22de71b2011-05-12 16:14:04 +01002081 snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
2082 "%s", card->long_name ? card->long_name : card->name);
Mark Brownf0e8ed82011-09-20 11:41:54 +01002083 snprintf(card->snd_card->driver, sizeof(card->snd_card->driver),
2084 "%s", card->driver_name ? card->driver_name : card->name);
2085 for (i = 0; i < ARRAY_SIZE(card->snd_card->driver); i++) {
2086 switch (card->snd_card->driver[i]) {
2087 case '_':
2088 case '-':
2089 case '\0':
2090 break;
2091 default:
2092 if (!isalnum(card->snd_card->driver[i]))
2093 card->snd_card->driver[i] = '_';
2094 break;
2095 }
2096 }
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002097
Mark Brown28e9ad92011-03-02 18:36:34 +00002098 if (card->late_probe) {
2099 ret = card->late_probe(card);
2100 if (ret < 0) {
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00002101 dev_err(card->dev, "ASoC: %s late_probe() failed: %d\n",
Mark Brown28e9ad92011-03-02 18:36:34 +00002102 card->name, ret);
2103 goto probe_aux_dev_err;
2104 }
2105 }
2106
Lars-Peter Clausen824ef822013-08-27 15:51:01 +02002107 snd_soc_dapm_new_widgets(card);
Lars-Peter Clausen8c193b82013-08-27 15:51:00 +02002108
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002109 ret = snd_card_register(card->snd_card);
2110 if (ret < 0) {
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00002111 dev_err(card->dev, "ASoC: failed to register soundcard %d\n",
2112 ret);
Axel Lin6b3ed782010-12-07 16:12:29 +08002113 goto probe_aux_dev_err;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002114 }
2115
Mark Brown435c5e22008-12-04 15:32:53 +00002116 card->instantiated = 1;
Mark Brown4f4c0072011-10-07 14:29:19 +01002117 snd_soc_dapm_sync(&card->dapm);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002118 mutex_unlock(&card->mutex);
Lars-Peter Clausen34e81ab2015-03-07 19:34:03 +01002119 mutex_unlock(&client_mutex);
Mark Brownb19e6e72012-03-14 21:18:39 +00002120
2121 return 0;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002122
Jarkko Nikula2eea3922010-11-25 17:47:38 +02002123probe_aux_dev_err:
Mengdong Linf2ed6b02016-01-06 13:29:31 +08002124 soc_remove_aux_devices(card);
Jarkko Nikula2eea3922010-11-25 17:47:38 +02002125
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002126probe_dai_err:
Kuninori Morimoto0671fd82011-04-08 14:50:44 +09002127 soc_remove_dai_links(card);
Mark Brownfe3e78e2009-11-03 22:13:13 +00002128
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002129card_probe_error:
Mark Brown87506542008-11-18 20:50:34 +00002130 if (card->remove)
Mark Browne7361ec2011-01-26 14:17:20 +00002131 card->remove(card);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002132
Lars-Peter Clausen22104382015-07-08 22:14:48 +02002133 snd_soc_dapm_free(&card->dapm);
Lars-Peter Clausen0757d832015-04-09 10:52:36 +02002134 soc_cleanup_card_debugfs(card);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002135 snd_card_free(card->snd_card);
2136
Mark Brownb19e6e72012-03-14 21:18:39 +00002137base_error:
Mengdong Lin1a497982015-11-18 02:34:11 -05002138 soc_remove_pcm_runtimes(card);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002139 mutex_unlock(&card->mutex);
Lars-Peter Clausen34e81ab2015-03-07 19:34:03 +01002140 mutex_unlock(&client_mutex);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002141
Mark Brownb19e6e72012-03-14 21:18:39 +00002142 return ret;
Mark Brown435c5e22008-12-04 15:32:53 +00002143}
2144
2145/* probes a new socdev */
2146static int soc_probe(struct platform_device *pdev)
2147{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002148 struct snd_soc_card *card = platform_get_drvdata(pdev);
Mark Brown435c5e22008-12-04 15:32:53 +00002149
Vinod Koul70a7ca32011-01-14 19:22:48 +05302150 /*
2151 * no card, so machine driver should be registering card
2152 * we should not be here in that case so ret error
2153 */
2154 if (!card)
2155 return -EINVAL;
2156
Mark Brownfe4085e2012-03-02 13:07:41 +00002157 dev_warn(&pdev->dev,
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00002158 "ASoC: machine %s should use snd_soc_register_card()\n",
Mark Brownfe4085e2012-03-02 13:07:41 +00002159 card->name);
2160
Mark Brown435c5e22008-12-04 15:32:53 +00002161 /* Bodge while we unpick instantiation */
2162 card->dev = &pdev->dev;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002163
Mark Brown28d528c2012-08-09 18:45:23 +01002164 return snd_soc_register_card(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002165}
2166
Vinod Koulb0e26482011-01-13 22:48:02 +05302167static int soc_cleanup_card_resources(struct snd_soc_card *card)
2168{
Mengdong Lin1a497982015-11-18 02:34:11 -05002169 struct snd_soc_pcm_runtime *rtd;
Vinod Koulb0e26482011-01-13 22:48:02 +05302170
2171 /* make sure any delayed work runs */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +00002172 for_each_card_rtds(card, rtd)
Tejun Heo43829732012-08-20 14:51:24 -07002173 flush_delayed_work(&rtd->delayed_work);
Vinod Koulb0e26482011-01-13 22:48:02 +05302174
Takashi Iwai4efda5f22017-05-24 10:19:45 +02002175 /* free the ALSA card at first; this syncs with pending operations */
2176 snd_card_free(card->snd_card);
2177
Vinod Koulb0e26482011-01-13 22:48:02 +05302178 /* remove and free each DAI */
Kuninori Morimoto0671fd82011-04-08 14:50:44 +09002179 soc_remove_dai_links(card);
Mengdong Lin1a497982015-11-18 02:34:11 -05002180 soc_remove_pcm_runtimes(card);
Vinod Koulb0e26482011-01-13 22:48:02 +05302181
Mengdong Linf2ed6b02016-01-06 13:29:31 +08002182 /* remove auxiliary devices */
2183 soc_remove_aux_devices(card);
2184
Mark Brownd1e81422016-08-18 19:32:59 +01002185 snd_soc_dapm_free(&card->dapm);
Vinod Koulb0e26482011-01-13 22:48:02 +05302186 soc_cleanup_card_debugfs(card);
2187
2188 /* remove the card */
2189 if (card->remove)
Mark Browne7361ec2011-01-26 14:17:20 +00002190 card->remove(card);
Vinod Koulb0e26482011-01-13 22:48:02 +05302191
Vinod Koulb0e26482011-01-13 22:48:02 +05302192 return 0;
Vinod Koulb0e26482011-01-13 22:48:02 +05302193}
2194
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002195/* removes a socdev */
2196static int soc_remove(struct platform_device *pdev)
2197{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002198 struct snd_soc_card *card = platform_get_drvdata(pdev);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002199
Mark Brownc5af3a22008-11-28 13:29:45 +00002200 snd_soc_unregister_card(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002201 return 0;
2202}
2203
Mark Brown6f8ab4a2011-01-26 14:59:27 +00002204int snd_soc_poweroff(struct device *dev)
Mark Brown51737472009-06-22 13:16:51 +01002205{
Mark Brown6f8ab4a2011-01-26 14:59:27 +00002206 struct snd_soc_card *card = dev_get_drvdata(dev);
Mengdong Lin1a497982015-11-18 02:34:11 -05002207 struct snd_soc_pcm_runtime *rtd;
Mark Brown51737472009-06-22 13:16:51 +01002208
2209 if (!card->instantiated)
Mark Brown416356f2009-06-30 19:05:15 +01002210 return 0;
Mark Brown51737472009-06-22 13:16:51 +01002211
2212 /* Flush out pmdown_time work - we actually do want to run it
2213 * now, we're shutting down so no imminent restart. */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +00002214 for_each_card_rtds(card, rtd)
Tejun Heo43829732012-08-20 14:51:24 -07002215 flush_delayed_work(&rtd->delayed_work);
Mark Brown51737472009-06-22 13:16:51 +01002216
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002217 snd_soc_dapm_shutdown(card);
Mark Brown416356f2009-06-30 19:05:15 +01002218
Nicolin Chen988e8cc2013-11-04 14:57:31 +08002219 /* deactivate pins to sleep state */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +00002220 for_each_card_rtds(card, rtd) {
Benoit Cousson88bd8702014-07-08 23:19:34 +02002221 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +00002222 struct snd_soc_dai *codec_dai;
Mengdong Lin1a497982015-11-18 02:34:11 -05002223 int i;
Benoit Cousson88bd8702014-07-08 23:19:34 +02002224
Nicolin Chen988e8cc2013-11-04 14:57:31 +08002225 pinctrl_pm_select_sleep_state(cpu_dai->dev);
Kuninori Morimoto0b7990e2018-09-03 02:12:56 +00002226 for_each_rtd_codec_dai(rtd, i, codec_dai) {
Benoit Cousson88bd8702014-07-08 23:19:34 +02002227 pinctrl_pm_select_sleep_state(codec_dai->dev);
2228 }
Nicolin Chen988e8cc2013-11-04 14:57:31 +08002229 }
2230
Mark Brown416356f2009-06-30 19:05:15 +01002231 return 0;
Mark Brown51737472009-06-22 13:16:51 +01002232}
Mark Brown6f8ab4a2011-01-26 14:59:27 +00002233EXPORT_SYMBOL_GPL(snd_soc_poweroff);
Mark Brown51737472009-06-22 13:16:51 +01002234
Mark Brown6f8ab4a2011-01-26 14:59:27 +00002235const struct dev_pm_ops snd_soc_pm_ops = {
Viresh Kumarb1dd5892012-02-24 16:25:49 +05302236 .suspend = snd_soc_suspend,
2237 .resume = snd_soc_resume,
2238 .freeze = snd_soc_suspend,
2239 .thaw = snd_soc_resume,
Mark Brown6f8ab4a2011-01-26 14:59:27 +00002240 .poweroff = snd_soc_poweroff,
Viresh Kumarb1dd5892012-02-24 16:25:49 +05302241 .restore = snd_soc_resume,
Mark Brown416356f2009-06-30 19:05:15 +01002242};
Stephen Warrendeb26072011-04-05 19:35:30 -06002243EXPORT_SYMBOL_GPL(snd_soc_pm_ops);
Mark Brown416356f2009-06-30 19:05:15 +01002244
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002245/* ASoC platform driver */
2246static struct platform_driver soc_driver = {
2247 .driver = {
2248 .name = "soc-audio",
Mark Brown6f8ab4a2011-01-26 14:59:27 +00002249 .pm = &snd_soc_pm_ops,
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002250 },
2251 .probe = soc_probe,
2252 .remove = soc_remove,
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002253};
2254
Mark Brown096e49d2009-07-05 15:12:22 +01002255/**
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002256 * snd_soc_cnew - create new control
2257 * @_template: control template
2258 * @data: control private data
Mark Brownac11a2b2009-01-01 12:18:17 +00002259 * @long_name: control long name
Mark Brownefb7ac32011-03-08 17:23:24 +00002260 * @prefix: control name prefix
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002261 *
2262 * Create a new mixer control from a template control.
2263 *
2264 * Returns 0 for success, else error.
2265 */
2266struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
Mark Brown30565572012-02-16 17:07:42 -08002267 void *data, const char *long_name,
Mark Brownefb7ac32011-03-08 17:23:24 +00002268 const char *prefix)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002269{
2270 struct snd_kcontrol_new template;
Mark Brownefb7ac32011-03-08 17:23:24 +00002271 struct snd_kcontrol *kcontrol;
2272 char *name = NULL;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002273
2274 memcpy(&template, _template, sizeof(template));
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002275 template.index = 0;
2276
Mark Brownefb7ac32011-03-08 17:23:24 +00002277 if (!long_name)
2278 long_name = template.name;
2279
2280 if (prefix) {
Lars-Peter Clausen2b581072013-05-14 11:05:32 +02002281 name = kasprintf(GFP_KERNEL, "%s %s", prefix, long_name);
Mark Brownefb7ac32011-03-08 17:23:24 +00002282 if (!name)
2283 return NULL;
2284
Mark Brownefb7ac32011-03-08 17:23:24 +00002285 template.name = name;
2286 } else {
2287 template.name = long_name;
2288 }
2289
2290 kcontrol = snd_ctl_new1(&template, data);
2291
2292 kfree(name);
2293
2294 return kcontrol;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002295}
2296EXPORT_SYMBOL_GPL(snd_soc_cnew);
2297
Liam Girdwood022658b2012-02-03 17:43:09 +00002298static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
2299 const struct snd_kcontrol_new *controls, int num_controls,
2300 const char *prefix, void *data)
2301{
2302 int err, i;
2303
2304 for (i = 0; i < num_controls; i++) {
2305 const struct snd_kcontrol_new *control = &controls[i];
2306 err = snd_ctl_add(card, snd_soc_cnew(control, data,
2307 control->name, prefix));
2308 if (err < 0) {
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00002309 dev_err(dev, "ASoC: Failed to add %s: %d\n",
2310 control->name, err);
Liam Girdwood022658b2012-02-03 17:43:09 +00002311 return err;
2312 }
2313 }
2314
2315 return 0;
2316}
2317
Dimitris Papastamos4fefd692013-07-29 13:51:58 +01002318struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
2319 const char *name)
2320{
2321 struct snd_card *card = soc_card->snd_card;
2322 struct snd_kcontrol *kctl;
2323
2324 if (unlikely(!name))
2325 return NULL;
2326
2327 list_for_each_entry(kctl, &card->controls, list)
2328 if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name)))
2329 return kctl;
2330 return NULL;
2331}
2332EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol);
2333
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002334/**
Lars-Peter Clausen0f2780a2014-07-17 22:01:08 +02002335 * snd_soc_add_component_controls - Add an array of controls to a component.
2336 *
2337 * @component: Component to add controls to
2338 * @controls: Array of controls to add
2339 * @num_controls: Number of elements in the array
2340 *
2341 * Return: 0 for success, else error.
2342 */
2343int snd_soc_add_component_controls(struct snd_soc_component *component,
2344 const struct snd_kcontrol_new *controls, unsigned int num_controls)
2345{
2346 struct snd_card *card = component->card->snd_card;
2347
2348 return snd_soc_add_controls(card, component->dev, controls,
2349 num_controls, component->name_prefix, component);
2350}
2351EXPORT_SYMBOL_GPL(snd_soc_add_component_controls);
2352
2353/**
Liam Girdwood022658b2012-02-03 17:43:09 +00002354 * snd_soc_add_card_controls - add an array of controls to a SoC card.
2355 * Convenience function to add a list of controls.
2356 *
2357 * @soc_card: SoC card to add controls to
2358 * @controls: array of controls to add
2359 * @num_controls: number of elements in the array
2360 *
2361 * Return 0 for success, else error.
2362 */
2363int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
2364 const struct snd_kcontrol_new *controls, int num_controls)
2365{
2366 struct snd_card *card = soc_card->snd_card;
2367
2368 return snd_soc_add_controls(card, soc_card->dev, controls, num_controls,
2369 NULL, soc_card);
2370}
2371EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
2372
2373/**
2374 * snd_soc_add_dai_controls - add an array of controls to a DAI.
2375 * Convienience function to add a list of controls.
2376 *
2377 * @dai: DAI to add controls to
2378 * @controls: array of controls to add
2379 * @num_controls: number of elements in the array
2380 *
2381 * Return 0 for success, else error.
2382 */
2383int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
2384 const struct snd_kcontrol_new *controls, int num_controls)
2385{
Lars-Peter Clausen313665b2014-11-04 11:30:58 +01002386 struct snd_card *card = dai->component->card->snd_card;
Liam Girdwood022658b2012-02-03 17:43:09 +00002387
2388 return snd_soc_add_controls(card, dai->dev, controls, num_controls,
2389 NULL, dai);
2390}
2391EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
2392
2393/**
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002394 * snd_soc_dai_set_sysclk - configure DAI system or master clock.
2395 * @dai: DAI
2396 * @clk_id: DAI specific clock ID
2397 * @freq: new clock frequency in Hz
2398 * @dir: new clock direction - input/output.
2399 *
2400 * Configures the DAI master (MCLK) or system (SYSCLK) clocking.
2401 */
2402int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
2403 unsigned int freq, int dir)
2404{
Kuninori Morimoto46471922017-09-25 01:38:34 +00002405 if (dai->driver->ops->set_sysclk)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002406 return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
Kuninori Morimoto71ccef02017-08-24 00:57:35 +00002407
2408 return snd_soc_component_set_sysclk(dai->component, clk_id, 0,
2409 freq, dir);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002410}
2411EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
2412
2413/**
Kuninori Morimoto71ccef02017-08-24 00:57:35 +00002414 * snd_soc_component_set_sysclk - configure COMPONENT system or master clock.
2415 * @component: COMPONENT
2416 * @clk_id: DAI specific clock ID
2417 * @source: Source for the clock
2418 * @freq: new clock frequency in Hz
2419 * @dir: new clock direction - input/output.
2420 *
2421 * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
2422 */
2423int snd_soc_component_set_sysclk(struct snd_soc_component *component, int clk_id,
2424 int source, unsigned int freq, int dir)
2425{
Kuninori Morimoto71ccef02017-08-24 00:57:35 +00002426 if (component->driver->set_sysclk)
2427 return component->driver->set_sysclk(component, clk_id, source,
2428 freq, dir);
2429
2430 return -ENOTSUPP;
2431}
2432EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk);
2433
2434/**
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002435 * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
2436 * @dai: DAI
Mark Brownac11a2b2009-01-01 12:18:17 +00002437 * @div_id: DAI specific clock divider ID
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002438 * @div: new clock divisor.
2439 *
2440 * Configures the clock dividers. This is used to derive the best DAI bit and
2441 * frame clocks from the system or master clock. It's best to set the DAI bit
2442 * and frame clocks as low as possible to save system power.
2443 */
2444int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
2445 int div_id, int div)
2446{
Kuninori Morimoto46471922017-09-25 01:38:34 +00002447 if (dai->driver->ops->set_clkdiv)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002448 return dai->driver->ops->set_clkdiv(dai, div_id, div);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002449 else
2450 return -EINVAL;
2451}
2452EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
2453
2454/**
2455 * snd_soc_dai_set_pll - configure DAI PLL.
2456 * @dai: DAI
2457 * @pll_id: DAI specific PLL ID
Mark Brown85488032009-09-05 18:52:16 +01002458 * @source: DAI specific source for the PLL
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002459 * @freq_in: PLL input clock frequency in Hz
2460 * @freq_out: requested PLL output clock frequency in Hz
2461 *
2462 * Configures and enables PLL to generate output clock based on input clock.
2463 */
Mark Brown85488032009-09-05 18:52:16 +01002464int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
2465 unsigned int freq_in, unsigned int freq_out)
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002466{
Kuninori Morimoto46471922017-09-25 01:38:34 +00002467 if (dai->driver->ops->set_pll)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002468 return dai->driver->ops->set_pll(dai, pll_id, source,
Mark Brown85488032009-09-05 18:52:16 +01002469 freq_in, freq_out);
Kuninori Morimotoef641e52017-08-24 00:57:51 +00002470
2471 return snd_soc_component_set_pll(dai->component, pll_id, source,
2472 freq_in, freq_out);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002473}
2474EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
2475
Mark Brownec4ee522011-03-07 20:58:11 +00002476/*
Kuninori Morimotoef641e52017-08-24 00:57:51 +00002477 * snd_soc_component_set_pll - configure component PLL.
2478 * @component: COMPONENT
2479 * @pll_id: DAI specific PLL ID
2480 * @source: DAI specific source for the PLL
2481 * @freq_in: PLL input clock frequency in Hz
2482 * @freq_out: requested PLL output clock frequency in Hz
2483 *
2484 * Configures and enables PLL to generate output clock based on input clock.
2485 */
2486int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
2487 int source, unsigned int freq_in,
2488 unsigned int freq_out)
2489{
Kuninori Morimotoef641e52017-08-24 00:57:51 +00002490 if (component->driver->set_pll)
2491 return component->driver->set_pll(component, pll_id, source,
2492 freq_in, freq_out);
2493
2494 return -EINVAL;
2495}
2496EXPORT_SYMBOL_GPL(snd_soc_component_set_pll);
2497
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002498/**
Liam Girdwoode54cf762013-09-16 13:01:46 +01002499 * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
2500 * @dai: DAI
Masanari Iida231b86b2015-07-15 23:02:38 +09002501 * @ratio: Ratio of BCLK to Sample rate.
Liam Girdwoode54cf762013-09-16 13:01:46 +01002502 *
2503 * Configures the DAI for a preset BCLK to sample rate ratio.
2504 */
2505int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
2506{
Kuninori Morimoto46471922017-09-25 01:38:34 +00002507 if (dai->driver->ops->set_bclk_ratio)
Liam Girdwoode54cf762013-09-16 13:01:46 +01002508 return dai->driver->ops->set_bclk_ratio(dai, ratio);
2509 else
2510 return -EINVAL;
2511}
2512EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
2513
2514/**
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002515 * snd_soc_dai_set_fmt - configure DAI hardware audio format.
2516 * @dai: DAI
Randy Dunlapbb19ba22017-10-29 17:10:34 -07002517 * @fmt: SND_SOC_DAIFMT_* format value.
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002518 *
2519 * Configures the DAI hardware format and clocking.
2520 */
2521int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2522{
Shawn Guo5e4ba562012-03-09 00:59:40 +08002523 if (dai->driver->ops->set_fmt == NULL)
2524 return -ENOTSUPP;
2525 return dai->driver->ops->set_fmt(dai, fmt);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002526}
2527EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
2528
2529/**
Xiubo Lie5c21512014-03-21 14:17:12 +08002530 * snd_soc_xlate_tdm_slot - generate tx/rx slot mask.
Xiubo Li89c67852014-02-14 09:34:35 +08002531 * @slots: Number of slots in use.
2532 * @tx_mask: bitmask representing active TX slots.
2533 * @rx_mask: bitmask representing active RX slots.
2534 *
2535 * Generates the TDM tx and rx slot default masks for DAI.
2536 */
Xiubo Lie5c21512014-03-21 14:17:12 +08002537static int snd_soc_xlate_tdm_slot_mask(unsigned int slots,
Xiubo Li89c67852014-02-14 09:34:35 +08002538 unsigned int *tx_mask,
2539 unsigned int *rx_mask)
2540{
2541 if (*tx_mask || *rx_mask)
2542 return 0;
2543
2544 if (!slots)
2545 return -EINVAL;
2546
2547 *tx_mask = (1 << slots) - 1;
2548 *rx_mask = (1 << slots) - 1;
2549
2550 return 0;
2551}
2552
2553/**
Lars-Peter Clausene46c9362015-01-12 10:27:20 +01002554 * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation
2555 * @dai: The DAI to configure
Daniel Ribeiroa5479e32009-06-15 21:44:31 -03002556 * @tx_mask: bitmask representing active TX slots.
2557 * @rx_mask: bitmask representing active RX slots.
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002558 * @slots: Number of slots in use.
Daniel Ribeiroa5479e32009-06-15 21:44:31 -03002559 * @slot_width: Width in bits for each slot.
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002560 *
Lars-Peter Clausene46c9362015-01-12 10:27:20 +01002561 * This function configures the specified DAI for TDM operation. @slot contains
2562 * the total number of slots of the TDM stream and @slot_with the width of each
2563 * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the
2564 * active slots of the TDM stream for the specified DAI, i.e. which slots the
2565 * DAI should write to or read from. If a bit is set the corresponding slot is
2566 * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to
2567 * the first slot, bit 1 to the second slot and so on. The first active slot
2568 * maps to the first channel of the DAI, the second active slot to the second
2569 * channel and so on.
2570 *
2571 * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask,
2572 * @rx_mask and @slot_width will be ignored.
2573 *
2574 * Returns 0 on success, a negative error code otherwise.
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002575 */
2576int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
Daniel Ribeiroa5479e32009-06-15 21:44:31 -03002577 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002578{
Kuninori Morimoto46471922017-09-25 01:38:34 +00002579 if (dai->driver->ops->xlate_tdm_slot_mask)
Xiubo Lie5c21512014-03-21 14:17:12 +08002580 dai->driver->ops->xlate_tdm_slot_mask(slots,
Xiubo Li89c67852014-02-14 09:34:35 +08002581 &tx_mask, &rx_mask);
2582 else
Xiubo Lie5c21512014-03-21 14:17:12 +08002583 snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
Xiubo Li89c67852014-02-14 09:34:35 +08002584
Benoit Cousson88bd8702014-07-08 23:19:34 +02002585 dai->tx_mask = tx_mask;
2586 dai->rx_mask = rx_mask;
2587
Kuninori Morimoto46471922017-09-25 01:38:34 +00002588 if (dai->driver->ops->set_tdm_slot)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002589 return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
Daniel Ribeiroa5479e32009-06-15 21:44:31 -03002590 slots, slot_width);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002591 else
Xiubo Lib2cbb6e2014-01-23 13:02:47 +08002592 return -ENOTSUPP;
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002593}
2594EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
2595
2596/**
Barry Song472df3c2009-09-12 01:16:29 +08002597 * snd_soc_dai_set_channel_map - configure DAI audio channel map
2598 * @dai: DAI
2599 * @tx_num: how many TX channels
2600 * @tx_slot: pointer to an array which imply the TX slot number channel
2601 * 0~num-1 uses
2602 * @rx_num: how many RX channels
2603 * @rx_slot: pointer to an array which imply the RX slot number channel
2604 * 0~num-1 uses
2605 *
2606 * configure the relationship between channel number and TDM slot number.
2607 */
2608int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
2609 unsigned int tx_num, unsigned int *tx_slot,
2610 unsigned int rx_num, unsigned int *rx_slot)
2611{
Kuninori Morimoto46471922017-09-25 01:38:34 +00002612 if (dai->driver->ops->set_channel_map)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002613 return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
Barry Song472df3c2009-09-12 01:16:29 +08002614 rx_num, rx_slot);
2615 else
2616 return -EINVAL;
2617}
2618EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
2619
2620/**
Srinivas Kandagatla467b0612018-07-23 16:54:03 +01002621 * snd_soc_dai_get_channel_map - Get DAI audio channel map
2622 * @dai: DAI
2623 * @tx_num: how many TX channels
2624 * @tx_slot: pointer to an array which imply the TX slot number channel
2625 * 0~num-1 uses
2626 * @rx_num: how many RX channels
2627 * @rx_slot: pointer to an array which imply the RX slot number channel
2628 * 0~num-1 uses
2629 */
2630int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
2631 unsigned int *tx_num, unsigned int *tx_slot,
2632 unsigned int *rx_num, unsigned int *rx_slot)
2633{
2634 if (dai->driver->ops->get_channel_map)
2635 return dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,
2636 rx_num, rx_slot);
2637 else
2638 return -ENOTSUPP;
2639}
2640EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);
2641
2642/**
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002643 * snd_soc_dai_set_tristate - configure DAI system or master clock.
2644 * @dai: DAI
2645 * @tristate: tristate enable
2646 *
2647 * Tristates the DAI so that others can use it.
2648 */
2649int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
2650{
Kuninori Morimoto46471922017-09-25 01:38:34 +00002651 if (dai->driver->ops->set_tristate)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002652 return dai->driver->ops->set_tristate(dai, tristate);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002653 else
2654 return -EINVAL;
2655}
2656EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
2657
2658/**
2659 * snd_soc_dai_digital_mute - configure DAI system or master clock.
2660 * @dai: DAI
2661 * @mute: mute enable
Mark Brownda183962013-02-06 15:44:07 +00002662 * @direction: stream to mute
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002663 *
2664 * Mutes the DAI DAC.
2665 */
Mark Brownda183962013-02-06 15:44:07 +00002666int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
2667 int direction)
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002668{
Mark Brownda183962013-02-06 15:44:07 +00002669 if (dai->driver->ops->mute_stream)
2670 return dai->driver->ops->mute_stream(dai, mute, direction);
2671 else if (direction == SNDRV_PCM_STREAM_PLAYBACK &&
2672 dai->driver->ops->digital_mute)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002673 return dai->driver->ops->digital_mute(dai, mute);
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002674 else
Mark Brown04570c62012-04-13 19:16:03 +01002675 return -ENOTSUPP;
Liam Girdwood8c6529d2008-07-08 13:19:13 +01002676}
2677EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
2678
Srinivas Kandagatlae894efe2018-09-12 10:15:00 +01002679static int snd_soc_bind_card(struct snd_soc_card *card)
2680{
2681 struct snd_soc_pcm_runtime *rtd;
2682 int ret;
2683
2684 ret = snd_soc_instantiate_card(card);
2685 if (ret != 0)
2686 return ret;
2687
2688 /* deactivate pins to sleep state */
Kuninori Morimotobcb1fd12018-09-18 01:29:35 +00002689 for_each_card_rtds(card, rtd) {
Srinivas Kandagatlae894efe2018-09-12 10:15:00 +01002690 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
2691 struct snd_soc_dai *codec_dai;
2692 int j;
2693
2694 for_each_rtd_codec_dai(rtd, j, codec_dai) {
2695 if (!codec_dai->active)
2696 pinctrl_pm_select_sleep_state(codec_dai->dev);
2697 }
2698
2699 if (!cpu_dai->active)
2700 pinctrl_pm_select_sleep_state(cpu_dai->dev);
2701 }
2702
2703 return ret;
2704}
2705
Mark Brownc5af3a22008-11-28 13:29:45 +00002706/**
2707 * snd_soc_register_card - Register a card with the ASoC core
2708 *
Mark Brownac11a2b2009-01-01 12:18:17 +00002709 * @card: Card to register
Mark Brownc5af3a22008-11-28 13:29:45 +00002710 *
Mark Brownc5af3a22008-11-28 13:29:45 +00002711 */
Vinod Koul70a7ca32011-01-14 19:22:48 +05302712int snd_soc_register_card(struct snd_soc_card *card)
Mark Brownc5af3a22008-11-28 13:29:45 +00002713{
Mengdong Lin923c5e612015-11-23 11:01:49 -05002714 int i, ret;
Kuninori Morimoto7fe072b2018-09-18 01:28:49 +00002715 struct snd_soc_dai_link *link;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002716
Mark Brownc5af3a22008-11-28 13:29:45 +00002717 if (!card->name || !card->dev)
2718 return -EINVAL;
2719
Kuninori Morimoto7fe072b2018-09-18 01:28:49 +00002720 for_each_card_prelinks(card, i, link) {
Stephen Warren5a504962011-12-21 10:40:59 -07002721
Mengdong Lin923c5e612015-11-23 11:01:49 -05002722 ret = soc_init_dai_link(card, link);
Benoit Cousson88bd8702014-07-08 23:19:34 +02002723 if (ret) {
Mengdong Lin923c5e612015-11-23 11:01:49 -05002724 dev_err(card->dev, "ASoC: failed to init link %s\n",
2725 link->name);
Benoit Cousson88bd8702014-07-08 23:19:34 +02002726 return ret;
Stephen Warren5a504962011-12-21 10:40:59 -07002727 }
Stephen Warren5a504962011-12-21 10:40:59 -07002728 }
2729
Mark Browned77cc12011-05-03 18:25:34 +01002730 dev_set_drvdata(card->dev, card);
2731
Stephen Warren111c6412011-01-28 14:26:35 -07002732 snd_soc_initialize_card_lists(card);
2733
Mengdong Linf8f80362015-12-02 14:11:22 +08002734 INIT_LIST_HEAD(&card->dai_link_list);
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002735
Mengdong Lin1a497982015-11-18 02:34:11 -05002736 INIT_LIST_HEAD(&card->rtd_list);
Mark Brown91151712008-11-30 23:31:24 +00002737 card->num_rtd = 0;
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002738
Mark Browndb432b42011-10-03 21:06:40 +01002739 INIT_LIST_HEAD(&card->dapm_dirty);
Liam Girdwood8a978232015-05-29 19:06:14 +01002740 INIT_LIST_HEAD(&card->dobj_list);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002741 card->instantiated = 0;
2742 mutex_init(&card->mutex);
Liam Girdwooda73fb2d2012-03-07 10:38:26 +00002743 mutex_init(&card->dapm_mutex);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002744
Srinivas Kandagatlae894efe2018-09-12 10:15:00 +01002745 return snd_soc_bind_card(card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002746}
Vinod Koul70a7ca32011-01-14 19:22:48 +05302747EXPORT_SYMBOL_GPL(snd_soc_register_card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002748
Srinivas Kandagatlae894efe2018-09-12 10:15:00 +01002749static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister)
2750{
2751 if (card->instantiated) {
2752 card->instantiated = false;
2753 snd_soc_dapm_shutdown(card);
2754 soc_cleanup_card_resources(card);
2755 if (!unregister)
2756 list_add(&card->list, &unbind_card_list);
2757 } else {
2758 if (unregister)
2759 list_del(&card->list);
2760 }
2761}
2762
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002763/**
2764 * snd_soc_unregister_card - Unregister a card with the ASoC core
2765 *
2766 * @card: Card to unregister
2767 *
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002768 */
Vinod Koul70a7ca32011-01-14 19:22:48 +05302769int snd_soc_unregister_card(struct snd_soc_card *card)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002770{
Srinivas Kandagatlae894efe2018-09-12 10:15:00 +01002771 snd_soc_unbind_card(card, true);
2772 dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002773
2774 return 0;
2775}
Vinod Koul70a7ca32011-01-14 19:22:48 +05302776EXPORT_SYMBOL_GPL(snd_soc_unregister_card);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002777
2778/*
2779 * Simplify DAI link configuration by removing ".-1" from device names
2780 * and sanitizing names.
2781 */
Dimitris Papastamos0b9a2142010-12-06 15:49:20 +00002782static char *fmt_single_name(struct device *dev, int *id)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002783{
2784 char *found, name[NAME_SIZE];
2785 int id1, id2;
2786
2787 if (dev_name(dev) == NULL)
2788 return NULL;
2789
Dimitris Papastamos58818a72010-12-06 15:42:17 +00002790 strlcpy(name, dev_name(dev), NAME_SIZE);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02002791
2792 /* are we a "%s.%d" name (platform and SPI components) */
Mark Brownc5af3a22008-11-28 13:29:45 +00002793 found = strstr(name, dev->driver->name);
2794 if (found) {
2795 /* get ID */
2796 if (sscanf(&found[strlen(dev->driver->name)], ".%d", id) == 1) {
2797
2798 /* discard ID from name if ID == -1 */
2799 if (*id == -1)
2800 found[strlen(dev->driver->name)] = '\0';
2801 }
2802
2803 } else {
2804 /* I2C component devices are named "bus-addr" */
2805 if (sscanf(name, "%x-%x", &id1, &id2) == 2) {
2806 char tmp[NAME_SIZE];
2807
2808 /* create unique ID number from I2C addr and bus */
2809 *id = ((id1 & 0xffff) << 16) + id2;
2810
2811 /* sanitize component name for DAI link creation */
2812 snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name);
Dimitris Papastamos58818a72010-12-06 15:42:17 +00002813 strlcpy(name, tmp, NAME_SIZE);
Mark Brownc5af3a22008-11-28 13:29:45 +00002814 } else
2815 *id = 0;
2816 }
2817
2818 return kstrdup(name, GFP_KERNEL);
2819}
2820
2821/*
2822 * Simplify DAI link naming for single devices with multiple DAIs by removing
2823 * any ".-1" and using the DAI name (instead of device name).
2824 */
2825static inline char *fmt_multiple_name(struct device *dev,
2826 struct snd_soc_dai_driver *dai_drv)
2827{
2828 if (dai_drv->name == NULL) {
Michał Mirosław10e8aa92013-05-04 22:21:38 +02002829 dev_err(dev,
2830 "ASoC: error - multiple DAI %s registered with no name\n",
2831 dev_name(dev));
Mark Brownc5af3a22008-11-28 13:29:45 +00002832 return NULL;
2833 }
2834
2835 return kstrdup(dai_drv->name, GFP_KERNEL);
2836}
2837
2838/**
Lars-Peter Clausen32c9ba52014-03-09 17:41:45 +01002839 * snd_soc_unregister_dai - Unregister DAIs from the ASoC core
Mark Brown91151712008-11-30 23:31:24 +00002840 *
Lars-Peter Clausen32c9ba52014-03-09 17:41:45 +01002841 * @component: The component for which the DAIs should be unregistered
Mark Brown91151712008-11-30 23:31:24 +00002842 */
Lars-Peter Clausen32c9ba52014-03-09 17:41:45 +01002843static void snd_soc_unregister_dais(struct snd_soc_component *component)
Mark Brown91151712008-11-30 23:31:24 +00002844{
Lars-Peter Clausen5c1d5f02014-03-12 08:34:39 +01002845 struct snd_soc_dai *dai, *_dai;
Mark Brown91151712008-11-30 23:31:24 +00002846
Lars-Peter Clausen5c1d5f02014-03-12 08:34:39 +01002847 list_for_each_entry_safe(dai, _dai, &component->dai_list, list) {
Lars-Peter Clausen32c9ba52014-03-09 17:41:45 +01002848 dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n",
2849 dai->name);
Lars-Peter Clausen5c1d5f02014-03-12 08:34:39 +01002850 list_del(&dai->list);
Lars-Peter Clausen32c9ba52014-03-09 17:41:45 +01002851 kfree(dai->name);
Mark Brown91151712008-11-30 23:31:24 +00002852 kfree(dai);
Mark Brown91151712008-11-30 23:31:24 +00002853 }
Mark Brown91151712008-11-30 23:31:24 +00002854}
Mark Brown91151712008-11-30 23:31:24 +00002855
Mengdong Lin5e4fb372015-12-31 16:40:20 +08002856/* Create a DAI and add it to the component's DAI list */
2857static struct snd_soc_dai *soc_add_dai(struct snd_soc_component *component,
2858 struct snd_soc_dai_driver *dai_drv,
2859 bool legacy_dai_naming)
2860{
2861 struct device *dev = component->dev;
2862 struct snd_soc_dai *dai;
2863
2864 dev_dbg(dev, "ASoC: dynamically register DAI %s\n", dev_name(dev));
2865
2866 dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
2867 if (dai == NULL)
2868 return NULL;
2869
2870 /*
2871 * Back in the old days when we still had component-less DAIs,
2872 * instead of having a static name, component-less DAIs would
2873 * inherit the name of the parent device so it is possible to
2874 * register multiple instances of the DAI. We still need to keep
2875 * the same naming style even though those DAIs are not
2876 * component-less anymore.
2877 */
2878 if (legacy_dai_naming &&
2879 (dai_drv->id == 0 || dai_drv->name == NULL)) {
2880 dai->name = fmt_single_name(dev, &dai->id);
2881 } else {
2882 dai->name = fmt_multiple_name(dev, dai_drv);
2883 if (dai_drv->id)
2884 dai->id = dai_drv->id;
2885 else
2886 dai->id = component->num_dai;
2887 }
2888 if (dai->name == NULL) {
2889 kfree(dai);
2890 return NULL;
2891 }
2892
2893 dai->component = component;
2894 dai->dev = dev;
2895 dai->driver = dai_drv;
2896 if (!dai->driver->ops)
2897 dai->driver->ops = &null_dai_ops;
2898
Kuninori Morimoto58bf4172017-12-20 01:48:29 +00002899 list_add_tail(&dai->list, &component->dai_list);
Mengdong Lin5e4fb372015-12-31 16:40:20 +08002900 component->num_dai++;
2901
2902 dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
2903 return dai;
2904}
2905
Mark Brown91151712008-11-30 23:31:24 +00002906/**
Lars-Peter Clausen32c9ba52014-03-09 17:41:45 +01002907 * snd_soc_register_dais - Register a DAI with the ASoC core
Mark Brown91151712008-11-30 23:31:24 +00002908 *
Lars-Peter Clausen6106d122014-03-05 13:17:46 +01002909 * @component: The component the DAIs are registered for
2910 * @dai_drv: DAI driver to use for the DAIs
Mark Brownac11a2b2009-01-01 12:18:17 +00002911 * @count: Number of DAIs
Mark Brown91151712008-11-30 23:31:24 +00002912 */
Lars-Peter Clausen6106d122014-03-05 13:17:46 +01002913static int snd_soc_register_dais(struct snd_soc_component *component,
Kuninori Morimoto0e7b25c2018-05-08 03:23:01 +00002914 struct snd_soc_dai_driver *dai_drv, size_t count)
Mark Brown91151712008-11-30 23:31:24 +00002915{
Lars-Peter Clausen6106d122014-03-05 13:17:46 +01002916 struct device *dev = component->dev;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002917 struct snd_soc_dai *dai;
Lars-Peter Clausen32c9ba52014-03-09 17:41:45 +01002918 unsigned int i;
2919 int ret;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002920
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -08002921 dev_dbg(dev, "ASoC: dai register %s #%zu\n", dev_name(dev), count);
Mark Brown91151712008-11-30 23:31:24 +00002922
2923 for (i = 0; i < count; i++) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +00002924
Mengdong Lin5e4fb372015-12-31 16:40:20 +08002925 dai = soc_add_dai(component, dai_drv + i,
Kuninori Morimoto0e7b25c2018-05-08 03:23:01 +00002926 count == 1 && !component->driver->non_legacy_dai_naming);
Axel Linc46e0072010-11-03 15:04:45 +08002927 if (dai == NULL) {
2928 ret = -ENOMEM;
2929 goto err;
2930 }
Mark Brown91151712008-11-30 23:31:24 +00002931 }
2932
2933 return 0;
2934
2935err:
Lars-Peter Clausen32c9ba52014-03-09 17:41:45 +01002936 snd_soc_unregister_dais(component);
Mark Brown91151712008-11-30 23:31:24 +00002937
2938 return ret;
2939}
Mark Brown91151712008-11-30 23:31:24 +00002940
Mengdong Lin68003e62015-12-31 16:40:43 +08002941/**
2942 * snd_soc_register_dai - Register a DAI dynamically & create its widgets
2943 *
2944 * @component: The component the DAIs are registered for
2945 * @dai_drv: DAI driver to use for the DAI
2946 *
2947 * Topology can use this API to register DAIs when probing a component.
2948 * These DAIs's widgets will be freed in the card cleanup and the DAIs
2949 * will be freed in the component cleanup.
2950 */
2951int snd_soc_register_dai(struct snd_soc_component *component,
2952 struct snd_soc_dai_driver *dai_drv)
2953{
2954 struct snd_soc_dapm_context *dapm =
2955 snd_soc_component_get_dapm(component);
2956 struct snd_soc_dai *dai;
2957 int ret;
2958
2959 if (dai_drv->dobj.type != SND_SOC_DOBJ_PCM) {
2960 dev_err(component->dev, "Invalid dai type %d\n",
2961 dai_drv->dobj.type);
2962 return -EINVAL;
2963 }
2964
2965 lockdep_assert_held(&client_mutex);
2966 dai = soc_add_dai(component, dai_drv, false);
2967 if (!dai)
2968 return -ENOMEM;
2969
2970 /* Create the DAI widgets here. After adding DAIs, topology may
2971 * also add routes that need these widgets as source or sink.
2972 */
2973 ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
2974 if (ret != 0) {
2975 dev_err(component->dev,
2976 "Failed to create DAI widgets %d\n", ret);
2977 }
2978
2979 return ret;
2980}
2981EXPORT_SYMBOL_GPL(snd_soc_register_dai);
2982
Lars-Peter Clausen14e8bde2014-06-16 18:13:08 +02002983static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm,
2984 enum snd_soc_dapm_type type, int subseq)
Kuninori Morimotod191bd82013-09-04 19:39:03 -07002985{
Lars-Peter Clausen14e8bde2014-06-16 18:13:08 +02002986 struct snd_soc_component *component = dapm->component;
Kuninori Morimotod191bd82013-09-04 19:39:03 -07002987
Lars-Peter Clausen14e8bde2014-06-16 18:13:08 +02002988 component->driver->seq_notifier(component, type, subseq);
2989}
Kuninori Morimotod191bd82013-09-04 19:39:03 -07002990
Lars-Peter Clausen14e8bde2014-06-16 18:13:08 +02002991static int snd_soc_component_stream_event(struct snd_soc_dapm_context *dapm,
2992 int event)
2993{
2994 struct snd_soc_component *component = dapm->component;
2995
2996 return component->driver->stream_event(component, event);
2997}
2998
Kuninori Morimoto7ba236c2017-09-26 01:01:10 +00002999static int snd_soc_component_set_bias_level(struct snd_soc_dapm_context *dapm,
3000 enum snd_soc_bias_level level)
3001{
3002 struct snd_soc_component *component = dapm->component;
3003
3004 return component->driver->set_bias_level(component, level);
3005}
3006
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003007static int snd_soc_component_initialize(struct snd_soc_component *component,
3008 const struct snd_soc_component_driver *driver, struct device *dev)
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003009{
Lars-Peter Clausence0fc932014-06-16 18:13:06 +02003010 struct snd_soc_dapm_context *dapm;
3011
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003012 component->name = fmt_single_name(dev, &component->id);
3013 if (!component->name) {
3014 dev_err(dev, "ASoC: Failed to allocate name\n");
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003015 return -ENOMEM;
3016 }
3017
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003018 component->dev = dev;
3019 component->driver = driver;
Lars-Peter Clausene2c330b2014-04-22 13:23:13 +02003020
Kuninori Morimoto88c27462017-08-25 01:06:04 +00003021 dapm = snd_soc_component_get_dapm(component);
Lars-Peter Clausence0fc932014-06-16 18:13:06 +02003022 dapm->dev = dev;
3023 dapm->component = component;
3024 dapm->bias_level = SND_SOC_BIAS_OFF;
Kuninori Morimoto7ba236c2017-09-26 01:01:10 +00003025 dapm->idle_bias_off = !driver->idle_bias_on;
3026 dapm->suspend_bias_off = driver->suspend_bias_off;
Lars-Peter Clausen14e8bde2014-06-16 18:13:08 +02003027 if (driver->seq_notifier)
3028 dapm->seq_notifier = snd_soc_component_seq_notifier;
3029 if (driver->stream_event)
3030 dapm->stream_event = snd_soc_component_stream_event;
Kuninori Morimoto7ba236c2017-09-26 01:01:10 +00003031 if (driver->set_bias_level)
3032 dapm->set_bias_level = snd_soc_component_set_bias_level;
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003033
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003034 INIT_LIST_HEAD(&component->dai_list);
3035 mutex_init(&component->io_mutex);
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003036
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003037 return 0;
3038}
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003039
Lars-Peter Clausen20feb882014-11-18 19:45:52 +01003040static void snd_soc_component_setup_regmap(struct snd_soc_component *component)
Lars-Peter Clausen886f5692014-08-19 15:51:28 +02003041{
Lars-Peter Clausen20feb882014-11-18 19:45:52 +01003042 int val_bytes = regmap_get_val_bytes(component->regmap);
3043
3044 /* Errors are legitimate for non-integer byte multiples */
3045 if (val_bytes > 0)
3046 component->val_bytes = val_bytes;
Lars-Peter Clausen886f5692014-08-19 15:51:28 +02003047}
3048
Lars-Peter Clausene874bf52014-11-25 21:41:03 +01003049#ifdef CONFIG_REGMAP
3050
Lars-Peter Clausen20feb882014-11-18 19:45:52 +01003051/**
3052 * snd_soc_component_init_regmap() - Initialize regmap instance for the component
3053 * @component: The component for which to initialize the regmap instance
3054 * @regmap: The regmap instance that should be used by the component
3055 *
3056 * This function allows deferred assignment of the regmap instance that is
3057 * associated with the component. Only use this if the regmap instance is not
3058 * yet ready when the component is registered. The function must also be called
3059 * before the first IO attempt of the component.
3060 */
3061void snd_soc_component_init_regmap(struct snd_soc_component *component,
3062 struct regmap *regmap)
3063{
3064 component->regmap = regmap;
3065 snd_soc_component_setup_regmap(component);
3066}
3067EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap);
3068
3069/**
3070 * snd_soc_component_exit_regmap() - De-initialize regmap instance for the component
3071 * @component: The component for which to de-initialize the regmap instance
3072 *
3073 * Calls regmap_exit() on the regmap instance associated to the component and
3074 * removes the regmap instance from the component.
3075 *
3076 * This function should only be used if snd_soc_component_init_regmap() was used
3077 * to initialize the regmap instance.
3078 */
3079void snd_soc_component_exit_regmap(struct snd_soc_component *component)
3080{
3081 regmap_exit(component->regmap);
3082 component->regmap = NULL;
3083}
3084EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
3085
Lars-Peter Clausene874bf52014-11-25 21:41:03 +01003086#endif
3087
Kuninori Morimoto359c71e2018-05-08 03:22:11 +00003088static void snd_soc_component_add(struct snd_soc_component *component)
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003089{
Kuninori Morimoto359c71e2018-05-08 03:22:11 +00003090 mutex_lock(&client_mutex);
3091
Kuninori Morimoto999f7f52018-05-08 03:20:24 +00003092 if (!component->driver->write && !component->driver->read) {
Lars-Peter Clausen20feb882014-11-18 19:45:52 +01003093 if (!component->regmap)
3094 component->regmap = dev_get_regmap(component->dev, NULL);
3095 if (component->regmap)
3096 snd_soc_component_setup_regmap(component);
3097 }
Lars-Peter Clausen886f5692014-08-19 15:51:28 +02003098
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003099 list_add(&component->list, &component_list);
Liam Girdwood8a978232015-05-29 19:06:14 +01003100 INIT_LIST_HEAD(&component->dobj_list);
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003101
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003102 mutex_unlock(&client_mutex);
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003103}
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003104
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003105static void snd_soc_component_cleanup(struct snd_soc_component *component)
3106{
3107 snd_soc_unregister_dais(component);
3108 kfree(component->name);
3109}
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003110
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003111static void snd_soc_component_del_unlocked(struct snd_soc_component *component)
3112{
Kuninori Morimotoc12c1aa2017-04-03 06:31:22 +00003113 struct snd_soc_card *card = component->card;
3114
3115 if (card)
Srinivas Kandagatlae894efe2018-09-12 10:15:00 +01003116 snd_soc_unbind_card(card, false);
Kuninori Morimotoc12c1aa2017-04-03 06:31:22 +00003117
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003118 list_del(&component->list);
3119}
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003120
Kuninori Morimoto273d7782017-10-11 01:38:29 +00003121#define ENDIANNESS_MAP(name) \
3122 (SNDRV_PCM_FMTBIT_##name##LE | SNDRV_PCM_FMTBIT_##name##BE)
3123static u64 endianness_format_map[] = {
3124 ENDIANNESS_MAP(S16_),
3125 ENDIANNESS_MAP(U16_),
3126 ENDIANNESS_MAP(S24_),
3127 ENDIANNESS_MAP(U24_),
3128 ENDIANNESS_MAP(S32_),
3129 ENDIANNESS_MAP(U32_),
3130 ENDIANNESS_MAP(S24_3),
3131 ENDIANNESS_MAP(U24_3),
3132 ENDIANNESS_MAP(S20_3),
3133 ENDIANNESS_MAP(U20_3),
3134 ENDIANNESS_MAP(S18_3),
3135 ENDIANNESS_MAP(U18_3),
3136 ENDIANNESS_MAP(FLOAT_),
3137 ENDIANNESS_MAP(FLOAT64_),
3138 ENDIANNESS_MAP(IEC958_SUBFRAME_),
3139};
3140
3141/*
3142 * Fix up the DAI formats for endianness: codecs don't actually see
3143 * the endianness of the data but we're using the CPU format
3144 * definitions which do need to include endianness so we ensure that
3145 * codec DAIs always have both big and little endian variants set.
3146 */
3147static void convert_endianness_formats(struct snd_soc_pcm_stream *stream)
3148{
3149 int i;
3150
3151 for (i = 0; i < ARRAY_SIZE(endianness_format_map); i++)
3152 if (stream->formats & endianness_format_map[i])
3153 stream->formats |= endianness_format_map[i];
3154}
3155
Srinivas Kandagatlae894efe2018-09-12 10:15:00 +01003156static void snd_soc_try_rebind_card(void)
3157{
3158 struct snd_soc_card *card, *c;
3159
3160 if (!list_empty(&unbind_card_list)) {
3161 list_for_each_entry_safe(card, c, &unbind_card_list, list) {
3162 if (!snd_soc_bind_card(card))
3163 list_del(&card->list);
3164 }
3165 }
3166}
3167
Kuninori Morimotoe0dac412017-10-02 05:10:17 +00003168int snd_soc_add_component(struct device *dev,
3169 struct snd_soc_component *component,
3170 const struct snd_soc_component_driver *component_driver,
3171 struct snd_soc_dai_driver *dai_drv,
3172 int num_dai)
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003173{
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003174 int ret;
Kuninori Morimoto273d7782017-10-11 01:38:29 +00003175 int i;
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003176
Kuninori Morimotocf9e8292017-08-07 02:06:23 +00003177 ret = snd_soc_component_initialize(component, component_driver, dev);
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003178 if (ret)
3179 goto err_free;
3180
Kuninori Morimoto273d7782017-10-11 01:38:29 +00003181 if (component_driver->endianness) {
3182 for (i = 0; i < num_dai; i++) {
3183 convert_endianness_formats(&dai_drv[i].playback);
3184 convert_endianness_formats(&dai_drv[i].capture);
3185 }
3186 }
3187
Kuninori Morimoto0e7b25c2018-05-08 03:23:01 +00003188 ret = snd_soc_register_dais(component, dai_drv, num_dai);
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003189 if (ret < 0) {
Masanari Iidaf42cf8d2015-02-24 23:11:26 +09003190 dev_err(dev, "ASoC: Failed to register DAIs: %d\n", ret);
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003191 goto err_cleanup;
3192 }
3193
Kuninori Morimotocf9e8292017-08-07 02:06:23 +00003194 snd_soc_component_add(component);
Srinivas Kandagatlae894efe2018-09-12 10:15:00 +01003195 snd_soc_try_rebind_card();
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003196
3197 return 0;
3198
3199err_cleanup:
Kuninori Morimotocf9e8292017-08-07 02:06:23 +00003200 snd_soc_component_cleanup(component);
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003201err_free:
Lars-Peter Clausenbb131092014-06-16 18:13:03 +02003202 return ret;
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003203}
Kuninori Morimotoe0dac412017-10-02 05:10:17 +00003204EXPORT_SYMBOL_GPL(snd_soc_add_component);
3205
3206int snd_soc_register_component(struct device *dev,
3207 const struct snd_soc_component_driver *component_driver,
3208 struct snd_soc_dai_driver *dai_drv,
3209 int num_dai)
3210{
3211 struct snd_soc_component *component;
3212
Kuninori Morimoto7ecbd6a2018-03-19 07:27:17 +00003213 component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL);
Kuninori Morimoto08e61d02017-10-02 05:10:33 +00003214 if (!component)
Kuninori Morimotoe0dac412017-10-02 05:10:17 +00003215 return -ENOMEM;
Kuninori Morimotoe0dac412017-10-02 05:10:17 +00003216
3217 return snd_soc_add_component(dev, component, component_driver,
3218 dai_drv, num_dai);
3219}
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003220EXPORT_SYMBOL_GPL(snd_soc_register_component);
3221
3222/**
Kuninori Morimoto2eccea82017-08-07 02:06:55 +00003223 * snd_soc_unregister_component - Unregister all related component
3224 * from the ASoC core
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003225 *
Jonathan Corbet628536e2015-08-25 01:14:48 -06003226 * @dev: The device to unregister
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003227 */
Kuninori Morimoto2eccea82017-08-07 02:06:55 +00003228static int __snd_soc_unregister_component(struct device *dev)
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003229{
Kuninori Morimotocf9e8292017-08-07 02:06:23 +00003230 struct snd_soc_component *component;
Kuninori Morimoto21a035282017-08-07 02:06:40 +00003231 int found = 0;
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003232
Lars-Peter Clausen34e81ab2015-03-07 19:34:03 +01003233 mutex_lock(&client_mutex);
Kuninori Morimotocf9e8292017-08-07 02:06:23 +00003234 list_for_each_entry(component, &component_list, list) {
Kuninori Morimoto999f7f52018-05-08 03:20:24 +00003235 if (dev != component->dev)
Kuninori Morimoto21a035282017-08-07 02:06:40 +00003236 continue;
3237
3238 snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL);
3239 snd_soc_component_del_unlocked(component);
3240 found = 1;
3241 break;
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003242 }
Lars-Peter Clausen34e81ab2015-03-07 19:34:03 +01003243 mutex_unlock(&client_mutex);
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003244
Kuninori Morimoto21a035282017-08-07 02:06:40 +00003245 if (found) {
3246 snd_soc_component_cleanup(component);
Kuninori Morimoto21a035282017-08-07 02:06:40 +00003247 }
Kuninori Morimoto2eccea82017-08-07 02:06:55 +00003248
3249 return found;
3250}
3251
3252void snd_soc_unregister_component(struct device *dev)
3253{
3254 while (__snd_soc_unregister_component(dev));
Kuninori Morimotod191bd82013-09-04 19:39:03 -07003255}
3256EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
3257
Kuninori Morimoto7dd5d0d2017-10-02 05:09:52 +00003258struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
3259 const char *driver_name)
3260{
3261 struct snd_soc_component *component;
3262 struct snd_soc_component *ret;
3263
3264 ret = NULL;
3265 mutex_lock(&client_mutex);
3266 list_for_each_entry(component, &component_list, list) {
3267 if (dev != component->dev)
3268 continue;
3269
3270 if (driver_name &&
3271 (driver_name != component->driver->name) &&
3272 (strcmp(component->driver->name, driver_name) != 0))
3273 continue;
3274
3275 ret = component;
3276 break;
3277 }
3278 mutex_unlock(&client_mutex);
3279
3280 return ret;
3281}
3282EXPORT_SYMBOL_GPL(snd_soc_lookup_component);
3283
Stephen Warrenbec4fa02011-12-12 15:55:34 -07003284/* Retrieve a card's name from device tree */
Kuninori Morimotob07609ce2017-01-27 06:37:51 +00003285int snd_soc_of_parse_card_name(struct snd_soc_card *card,
3286 const char *propname)
Stephen Warrenbec4fa02011-12-12 15:55:34 -07003287{
Kuninori Morimotob07609ce2017-01-27 06:37:51 +00003288 struct device_node *np;
Stephen Warrenbec4fa02011-12-12 15:55:34 -07003289 int ret;
3290
Tushar Behera7e07e7c2014-07-04 14:23:00 +05303291 if (!card->dev) {
3292 pr_err("card->dev is not set before calling %s\n", __func__);
3293 return -EINVAL;
3294 }
3295
Kuninori Morimotob07609ce2017-01-27 06:37:51 +00003296 np = card->dev->of_node;
Tushar Behera7e07e7c2014-07-04 14:23:00 +05303297
Stephen Warrenbec4fa02011-12-12 15:55:34 -07003298 ret = of_property_read_string_index(np, propname, 0, &card->name);
3299 /*
3300 * EINVAL means the property does not exist. This is fine providing
3301 * card->name was previously set, which is checked later in
3302 * snd_soc_register_card.
3303 */
3304 if (ret < 0 && ret != -EINVAL) {
3305 dev_err(card->dev,
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00003306 "ASoC: Property '%s' could not be read: %d\n",
Stephen Warrenbec4fa02011-12-12 15:55:34 -07003307 propname, ret);
3308 return ret;
3309 }
3310
3311 return 0;
3312}
Kuninori Morimotob07609ce2017-01-27 06:37:51 +00003313EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name);
Stephen Warrenbec4fa02011-12-12 15:55:34 -07003314
Xiubo Li9a6d4862014-02-08 15:59:52 +08003315static const struct snd_soc_dapm_widget simple_widgets[] = {
3316 SND_SOC_DAPM_MIC("Microphone", NULL),
3317 SND_SOC_DAPM_LINE("Line", NULL),
3318 SND_SOC_DAPM_HP("Headphone", NULL),
3319 SND_SOC_DAPM_SPK("Speaker", NULL),
3320};
3321
Kuninori Morimoto21efde52017-01-27 06:37:34 +00003322int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
Xiubo Li9a6d4862014-02-08 15:59:52 +08003323 const char *propname)
3324{
Kuninori Morimoto21efde52017-01-27 06:37:34 +00003325 struct device_node *np = card->dev->of_node;
Xiubo Li9a6d4862014-02-08 15:59:52 +08003326 struct snd_soc_dapm_widget *widgets;
3327 const char *template, *wname;
3328 int i, j, num_widgets, ret;
3329
3330 num_widgets = of_property_count_strings(np, propname);
3331 if (num_widgets < 0) {
3332 dev_err(card->dev,
3333 "ASoC: Property '%s' does not exist\n", propname);
3334 return -EINVAL;
3335 }
3336 if (num_widgets & 1) {
3337 dev_err(card->dev,
3338 "ASoC: Property '%s' length is not even\n", propname);
3339 return -EINVAL;
3340 }
3341
3342 num_widgets /= 2;
3343 if (!num_widgets) {
3344 dev_err(card->dev, "ASoC: Property '%s's length is zero\n",
3345 propname);
3346 return -EINVAL;
3347 }
3348
3349 widgets = devm_kcalloc(card->dev, num_widgets, sizeof(*widgets),
3350 GFP_KERNEL);
3351 if (!widgets) {
3352 dev_err(card->dev,
3353 "ASoC: Could not allocate memory for widgets\n");
3354 return -ENOMEM;
3355 }
3356
3357 for (i = 0; i < num_widgets; i++) {
3358 ret = of_property_read_string_index(np, propname,
3359 2 * i, &template);
3360 if (ret) {
3361 dev_err(card->dev,
3362 "ASoC: Property '%s' index %d read error:%d\n",
3363 propname, 2 * i, ret);
3364 return -EINVAL;
3365 }
3366
3367 for (j = 0; j < ARRAY_SIZE(simple_widgets); j++) {
3368 if (!strncmp(template, simple_widgets[j].name,
3369 strlen(simple_widgets[j].name))) {
3370 widgets[i] = simple_widgets[j];
3371 break;
3372 }
3373 }
3374
3375 if (j >= ARRAY_SIZE(simple_widgets)) {
3376 dev_err(card->dev,
3377 "ASoC: DAPM widget '%s' is not supported\n",
3378 template);
3379 return -EINVAL;
3380 }
3381
3382 ret = of_property_read_string_index(np, propname,
3383 (2 * i) + 1,
3384 &wname);
3385 if (ret) {
3386 dev_err(card->dev,
3387 "ASoC: Property '%s' index %d read error:%d\n",
3388 propname, (2 * i) + 1, ret);
3389 return -EINVAL;
3390 }
3391
3392 widgets[i].name = wname;
3393 }
3394
Nicolin Chenf23e8602015-02-14 17:22:49 -08003395 card->of_dapm_widgets = widgets;
3396 card->num_of_dapm_widgets = num_widgets;
Xiubo Li9a6d4862014-02-08 15:59:52 +08003397
3398 return 0;
3399}
Kuninori Morimoto21efde52017-01-27 06:37:34 +00003400EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets);
Xiubo Li9a6d4862014-02-08 15:59:52 +08003401
Jerome Brunetcbdfab32018-07-17 17:43:02 +02003402int snd_soc_of_get_slot_mask(struct device_node *np,
3403 const char *prop_name,
3404 unsigned int *mask)
Jyri Sarha61310842015-09-09 21:27:43 +03003405{
3406 u32 val;
Jyri Sarha6c84e5912015-09-17 13:13:38 +03003407 const __be32 *of_slot_mask = of_get_property(np, prop_name, &val);
Jyri Sarha61310842015-09-09 21:27:43 +03003408 int i;
3409
3410 if (!of_slot_mask)
3411 return 0;
3412 val /= sizeof(u32);
3413 for (i = 0; i < val; i++)
3414 if (be32_to_cpup(&of_slot_mask[i]))
3415 *mask |= (1 << i);
3416
3417 return val;
3418}
Jerome Brunetcbdfab32018-07-17 17:43:02 +02003419EXPORT_SYMBOL_GPL(snd_soc_of_get_slot_mask);
Jyri Sarha61310842015-09-09 21:27:43 +03003420
Xiubo Li89c67852014-02-14 09:34:35 +08003421int snd_soc_of_parse_tdm_slot(struct device_node *np,
Jyri Sarha61310842015-09-09 21:27:43 +03003422 unsigned int *tx_mask,
3423 unsigned int *rx_mask,
Xiubo Li89c67852014-02-14 09:34:35 +08003424 unsigned int *slots,
3425 unsigned int *slot_width)
3426{
3427 u32 val;
3428 int ret;
3429
Jyri Sarha61310842015-09-09 21:27:43 +03003430 if (tx_mask)
3431 snd_soc_of_get_slot_mask(np, "dai-tdm-slot-tx-mask", tx_mask);
3432 if (rx_mask)
3433 snd_soc_of_get_slot_mask(np, "dai-tdm-slot-rx-mask", rx_mask);
3434
Xiubo Li89c67852014-02-14 09:34:35 +08003435 if (of_property_read_bool(np, "dai-tdm-slot-num")) {
3436 ret = of_property_read_u32(np, "dai-tdm-slot-num", &val);
3437 if (ret)
3438 return ret;
3439
3440 if (slots)
3441 *slots = val;
3442 }
3443
3444 if (of_property_read_bool(np, "dai-tdm-slot-width")) {
3445 ret = of_property_read_u32(np, "dai-tdm-slot-width", &val);
3446 if (ret)
3447 return ret;
3448
3449 if (slot_width)
3450 *slot_width = val;
3451 }
3452
3453 return 0;
3454}
3455EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot);
3456
Kuninori Morimoto440a3002017-01-27 06:37:16 +00003457void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
Kuninori Morimoto5e3cdaa2015-07-15 07:07:42 +00003458 struct snd_soc_codec_conf *codec_conf,
3459 struct device_node *of_node,
3460 const char *propname)
3461{
Kuninori Morimoto440a3002017-01-27 06:37:16 +00003462 struct device_node *np = card->dev->of_node;
Kuninori Morimoto5e3cdaa2015-07-15 07:07:42 +00003463 const char *str;
3464 int ret;
3465
3466 ret = of_property_read_string(np, propname, &str);
3467 if (ret < 0) {
3468 /* no prefix is not error */
3469 return;
3470 }
3471
3472 codec_conf->of_node = of_node;
3473 codec_conf->name_prefix = str;
3474}
Kuninori Morimoto440a3002017-01-27 06:37:16 +00003475EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix);
Kuninori Morimoto5e3cdaa2015-07-15 07:07:42 +00003476
Kuninori Morimoto2bc644a2017-01-27 06:36:50 +00003477int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003478 const char *propname)
3479{
Kuninori Morimoto2bc644a2017-01-27 06:36:50 +00003480 struct device_node *np = card->dev->of_node;
Mark Browne3b1e6a2014-12-18 11:46:38 +00003481 int num_routes;
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003482 struct snd_soc_dapm_route *routes;
3483 int i, ret;
3484
3485 num_routes = of_property_count_strings(np, propname);
Richard Zhaoc34ce322012-04-24 15:24:43 +08003486 if (num_routes < 0 || num_routes & 1) {
Michał Mirosław10e8aa92013-05-04 22:21:38 +02003487 dev_err(card->dev,
3488 "ASoC: Property '%s' does not exist or its length is not even\n",
3489 propname);
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003490 return -EINVAL;
3491 }
3492 num_routes /= 2;
3493 if (!num_routes) {
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00003494 dev_err(card->dev, "ASoC: Property '%s's length is zero\n",
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003495 propname);
3496 return -EINVAL;
3497 }
3498
Kees Cooka86854d2018-06-12 14:07:58 -07003499 routes = devm_kcalloc(card->dev, num_routes, sizeof(*routes),
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003500 GFP_KERNEL);
3501 if (!routes) {
3502 dev_err(card->dev,
Liam Girdwoodf110bfc2012-11-19 14:47:09 +00003503 "ASoC: Could not allocate DAPM route table\n");
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003504 return -EINVAL;
3505 }
3506
3507 for (i = 0; i < num_routes; i++) {
3508 ret = of_property_read_string_index(np, propname,
Mark Browne3b1e6a2014-12-18 11:46:38 +00003509 2 * i, &routes[i].sink);
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003510 if (ret) {
Mark Brownc871bd02012-12-10 16:19:52 +09003511 dev_err(card->dev,
3512 "ASoC: Property '%s' index %d could not be read: %d\n",
3513 propname, 2 * i, ret);
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003514 return -EINVAL;
3515 }
3516 ret = of_property_read_string_index(np, propname,
Mark Browne3b1e6a2014-12-18 11:46:38 +00003517 (2 * i) + 1, &routes[i].source);
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003518 if (ret) {
3519 dev_err(card->dev,
Mark Brownc871bd02012-12-10 16:19:52 +09003520 "ASoC: Property '%s' index %d could not be read: %d\n",
3521 propname, (2 * i) + 1, ret);
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003522 return -EINVAL;
3523 }
3524 }
3525
Nicolin Chenf23e8602015-02-14 17:22:49 -08003526 card->num_of_dapm_routes = num_routes;
3527 card->of_dapm_routes = routes;
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003528
3529 return 0;
3530}
Kuninori Morimoto2bc644a2017-01-27 06:36:50 +00003531EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing);
Stephen Warrena4a54dd2011-12-12 15:55:35 -07003532
Kuninori Morimotoa7930ed2013-01-14 18:36:04 -08003533unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
Jyri Sarha389cb832014-03-24 12:15:24 +02003534 const char *prefix,
3535 struct device_node **bitclkmaster,
3536 struct device_node **framemaster)
Kuninori Morimotoa7930ed2013-01-14 18:36:04 -08003537{
3538 int ret, i;
3539 char prop[128];
3540 unsigned int format = 0;
3541 int bit, frame;
3542 const char *str;
3543 struct {
3544 char *name;
3545 unsigned int val;
3546 } of_fmt_table[] = {
3547 { "i2s", SND_SOC_DAIFMT_I2S },
3548 { "right_j", SND_SOC_DAIFMT_RIGHT_J },
3549 { "left_j", SND_SOC_DAIFMT_LEFT_J },
3550 { "dsp_a", SND_SOC_DAIFMT_DSP_A },
3551 { "dsp_b", SND_SOC_DAIFMT_DSP_B },
3552 { "ac97", SND_SOC_DAIFMT_AC97 },
3553 { "pdm", SND_SOC_DAIFMT_PDM},
3554 { "msb", SND_SOC_DAIFMT_MSB },
3555 { "lsb", SND_SOC_DAIFMT_LSB },
Kuninori Morimotoa7930ed2013-01-14 18:36:04 -08003556 };
3557
3558 if (!prefix)
3559 prefix = "";
3560
3561 /*
Kuninori Morimoto5711c972017-04-20 01:33:24 +00003562 * check "dai-format = xxx"
3563 * or "[prefix]format = xxx"
Kuninori Morimotoa7930ed2013-01-14 18:36:04 -08003564 * SND_SOC_DAIFMT_FORMAT_MASK area
3565 */
Kuninori Morimoto5711c972017-04-20 01:33:24 +00003566 ret = of_property_read_string(np, "dai-format", &str);
3567 if (ret < 0) {
3568 snprintf(prop, sizeof(prop), "%sformat", prefix);
3569 ret = of_property_read_string(np, prop, &str);
3570 }
Kuninori Morimotoa7930ed2013-01-14 18:36:04 -08003571 if (ret == 0) {
3572 for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) {
3573 if (strcmp(str, of_fmt_table[i].name) == 0) {
3574 format |= of_fmt_table[i].val;
3575 break;
3576 }
3577 }
3578 }
3579
3580 /*
Kuninori Morimoto8c2d6a92013-01-29 21:03:36 -08003581 * check "[prefix]continuous-clock"
Kuninori Morimotoa7930ed2013-01-14 18:36:04 -08003582 * SND_SOC_DAIFMT_CLOCK_MASK area
3583 */
Kuninori Morimoto8c2d6a92013-01-29 21:03:36 -08003584 snprintf(prop, sizeof(prop), "%scontinuous-clock", prefix);
Julia Lawall51930292016-08-05 10:56:51 +02003585 if (of_property_read_bool(np, prop))
Kuninori Morimoto8c2d6a92013-01-29 21:03:36 -08003586 format |= SND_SOC_DAIFMT_CONT;
3587 else
3588 format |= SND_SOC_DAIFMT_GATED;
Kuninori Morimotoa7930ed2013-01-14 18:36:04 -08003589
3590 /*
3591 * check "[prefix]bitclock-inversion"
3592 * check "[prefix]frame-inversion"
3593 * SND_SOC_DAIFMT_INV_MASK area
3594 */
3595 snprintf(prop, sizeof(prop), "%sbitclock-inversion", prefix);
3596 bit = !!of_get_property(np, prop, NULL);
3597
3598 snprintf(prop, sizeof(prop), "%sframe-inversion", prefix);
3599 frame = !!of_get_property(np, prop, NULL);
3600
3601 switch ((bit << 4) + frame) {
3602 case 0x11:
3603 format |= SND_SOC_DAIFMT_IB_IF;
3604 break;
3605 case 0x10:
3606 format |= SND_SOC_DAIFMT_IB_NF;
3607 break;
3608 case 0x01:
3609 format |= SND_SOC_DAIFMT_NB_IF;
3610 break;
3611 default:
3612 /* SND_SOC_DAIFMT_NB_NF is default */
3613 break;
3614 }
3615
3616 /*
3617 * check "[prefix]bitclock-master"
3618 * check "[prefix]frame-master"
3619 * SND_SOC_DAIFMT_MASTER_MASK area
3620 */
3621 snprintf(prop, sizeof(prop), "%sbitclock-master", prefix);
3622 bit = !!of_get_property(np, prop, NULL);
Jyri Sarha389cb832014-03-24 12:15:24 +02003623 if (bit && bitclkmaster)
3624 *bitclkmaster = of_parse_phandle(np, prop, 0);
Kuninori Morimotoa7930ed2013-01-14 18:36:04 -08003625
3626 snprintf(prop, sizeof(prop), "%sframe-master", prefix);
3627 frame = !!of_get_property(np, prop, NULL);
Jyri Sarha389cb832014-03-24 12:15:24 +02003628 if (frame && framemaster)
3629 *framemaster = of_parse_phandle(np, prop, 0);
Kuninori Morimotoa7930ed2013-01-14 18:36:04 -08003630
3631 switch ((bit << 4) + frame) {
3632 case 0x11:
3633 format |= SND_SOC_DAIFMT_CBM_CFM;
3634 break;
3635 case 0x10:
3636 format |= SND_SOC_DAIFMT_CBM_CFS;
3637 break;
3638 case 0x01:
3639 format |= SND_SOC_DAIFMT_CBS_CFM;
3640 break;
3641 default:
3642 format |= SND_SOC_DAIFMT_CBS_CFS;
3643 break;
3644 }
3645
3646 return format;
3647}
3648EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
3649
Kuninori Morimotoa180e8b2017-05-18 01:39:25 +00003650int snd_soc_get_dai_id(struct device_node *ep)
3651{
3652 struct snd_soc_component *pos;
3653 struct device_node *node;
3654 int ret;
3655
3656 node = of_graph_get_port_parent(ep);
3657
3658 /*
3659 * For example HDMI case, HDMI has video/sound port,
3660 * but ALSA SoC needs sound port number only.
3661 * Thus counting HDMI DT port/endpoint doesn't work.
3662 * Then, it should have .of_xlate_dai_id
3663 */
3664 ret = -ENOTSUPP;
3665 mutex_lock(&client_mutex);
3666 list_for_each_entry(pos, &component_list, list) {
3667 struct device_node *component_of_node = pos->dev->of_node;
3668
3669 if (!component_of_node && pos->dev->parent)
3670 component_of_node = pos->dev->parent->of_node;
3671
3672 if (component_of_node != node)
3673 continue;
3674
3675 if (pos->driver->of_xlate_dai_id)
3676 ret = pos->driver->of_xlate_dai_id(pos, ep);
3677
3678 break;
3679 }
3680 mutex_unlock(&client_mutex);
3681
Tony Lindgrenc0a480d2017-07-28 01:23:15 -07003682 of_node_put(node);
3683
Kuninori Morimotoa180e8b2017-05-18 01:39:25 +00003684 return ret;
3685}
3686EXPORT_SYMBOL_GPL(snd_soc_get_dai_id);
3687
Kuninori Morimoto1ad8ec52016-11-11 01:19:28 +00003688int snd_soc_get_dai_name(struct of_phandle_args *args,
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003689 const char **dai_name)
Kuninori Morimotocb470082013-09-10 17:39:56 -07003690{
3691 struct snd_soc_component *pos;
Jyri Sarha3e0aa8d2015-05-26 21:59:05 +03003692 struct device_node *component_of_node;
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003693 int ret = -EPROBE_DEFER;
Kuninori Morimotocb470082013-09-10 17:39:56 -07003694
3695 mutex_lock(&client_mutex);
3696 list_for_each_entry(pos, &component_list, list) {
Jyri Sarha3e0aa8d2015-05-26 21:59:05 +03003697 component_of_node = pos->dev->of_node;
3698 if (!component_of_node && pos->dev->parent)
3699 component_of_node = pos->dev->parent->of_node;
3700
3701 if (component_of_node != args->np)
Kuninori Morimotocb470082013-09-10 17:39:56 -07003702 continue;
3703
Kuninori Morimoto6833c452013-10-16 22:05:26 -07003704 if (pos->driver->of_xlate_dai_name) {
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003705 ret = pos->driver->of_xlate_dai_name(pos,
3706 args,
3707 dai_name);
Kuninori Morimoto6833c452013-10-16 22:05:26 -07003708 } else {
Kuninori Morimoto58bf4172017-12-20 01:48:29 +00003709 struct snd_soc_dai *dai;
Kuninori Morimoto6833c452013-10-16 22:05:26 -07003710 int id = -1;
3711
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003712 switch (args->args_count) {
Kuninori Morimoto6833c452013-10-16 22:05:26 -07003713 case 0:
3714 id = 0; /* same as dai_drv[0] */
3715 break;
3716 case 1:
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003717 id = args->args[0];
Kuninori Morimoto6833c452013-10-16 22:05:26 -07003718 break;
3719 default:
3720 /* not supported */
3721 break;
3722 }
3723
3724 if (id < 0 || id >= pos->num_dai) {
3725 ret = -EINVAL;
Nicolin Chen3dcba282014-04-21 19:14:46 +08003726 continue;
Kuninori Morimoto6833c452013-10-16 22:05:26 -07003727 }
Xiubo Lie41975e2013-12-20 14:39:51 +08003728
3729 ret = 0;
3730
Kuninori Morimoto58bf4172017-12-20 01:48:29 +00003731 /* find target DAI */
3732 list_for_each_entry(dai, &pos->dai_list, list) {
3733 if (id == 0)
3734 break;
3735 id--;
3736 }
3737
3738 *dai_name = dai->driver->name;
Xiubo Lie41975e2013-12-20 14:39:51 +08003739 if (!*dai_name)
3740 *dai_name = pos->name;
Kuninori Morimotocb470082013-09-10 17:39:56 -07003741 }
3742
Kuninori Morimotocb470082013-09-10 17:39:56 -07003743 break;
3744 }
3745 mutex_unlock(&client_mutex);
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003746 return ret;
3747}
Kuninori Morimoto1ad8ec52016-11-11 01:19:28 +00003748EXPORT_SYMBOL_GPL(snd_soc_get_dai_name);
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003749
3750int snd_soc_of_get_dai_name(struct device_node *of_node,
3751 const char **dai_name)
3752{
3753 struct of_phandle_args args;
3754 int ret;
3755
3756 ret = of_parse_phandle_with_args(of_node, "sound-dai",
3757 "#sound-dai-cells", 0, &args);
3758 if (ret)
3759 return ret;
3760
3761 ret = snd_soc_get_dai_name(&args, dai_name);
Kuninori Morimotocb470082013-09-10 17:39:56 -07003762
3763 of_node_put(args.np);
3764
3765 return ret;
3766}
3767EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name);
3768
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003769/*
Sylwester Nawrocki94685762018-03-09 18:48:54 +01003770 * snd_soc_of_put_dai_link_codecs - Dereference device nodes in the codecs array
3771 * @dai_link: DAI link
3772 *
3773 * Dereference device nodes acquired by snd_soc_of_get_dai_link_codecs().
3774 */
3775void snd_soc_of_put_dai_link_codecs(struct snd_soc_dai_link *dai_link)
3776{
Kuninori Morimoto3db769f2018-09-03 02:12:40 +00003777 struct snd_soc_dai_link_component *component;
Sylwester Nawrocki94685762018-03-09 18:48:54 +01003778 int index;
3779
Kuninori Morimoto3db769f2018-09-03 02:12:40 +00003780 for_each_link_codecs(dai_link, index, component) {
Sylwester Nawrocki94685762018-03-09 18:48:54 +01003781 if (!component->of_node)
3782 break;
3783 of_node_put(component->of_node);
3784 component->of_node = NULL;
3785 }
3786}
3787EXPORT_SYMBOL_GPL(snd_soc_of_put_dai_link_codecs);
3788
3789/*
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003790 * snd_soc_of_get_dai_link_codecs - Parse a list of CODECs in the devicetree
3791 * @dev: Card device
3792 * @of_node: Device node
3793 * @dai_link: DAI link
3794 *
3795 * Builds an array of CODEC DAI components from the DAI link property
3796 * 'sound-dai'.
3797 * The array is set in the DAI link and the number of DAIs is set accordingly.
Sylwester Nawrocki94685762018-03-09 18:48:54 +01003798 * The device nodes in the array (of_node) must be dereferenced by calling
3799 * snd_soc_of_put_dai_link_codecs() on @dai_link.
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003800 *
3801 * Returns 0 for success
3802 */
3803int snd_soc_of_get_dai_link_codecs(struct device *dev,
3804 struct device_node *of_node,
3805 struct snd_soc_dai_link *dai_link)
3806{
3807 struct of_phandle_args args;
3808 struct snd_soc_dai_link_component *component;
3809 char *name;
3810 int index, num_codecs, ret;
3811
3812 /* Count the number of CODECs */
3813 name = "sound-dai";
3814 num_codecs = of_count_phandle_with_args(of_node, name,
3815 "#sound-dai-cells");
3816 if (num_codecs <= 0) {
3817 if (num_codecs == -ENOENT)
3818 dev_err(dev, "No 'sound-dai' property\n");
3819 else
3820 dev_err(dev, "Bad phandle in 'sound-dai'\n");
3821 return num_codecs;
3822 }
Kees Cooka86854d2018-06-12 14:07:58 -07003823 component = devm_kcalloc(dev,
3824 num_codecs, sizeof(*component),
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003825 GFP_KERNEL);
3826 if (!component)
3827 return -ENOMEM;
3828 dai_link->codecs = component;
3829 dai_link->num_codecs = num_codecs;
3830
3831 /* Parse the list */
Kuninori Morimoto3db769f2018-09-03 02:12:40 +00003832 for_each_link_codecs(dai_link, index, component) {
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003833 ret = of_parse_phandle_with_args(of_node, name,
3834 "#sound-dai-cells",
3835 index, &args);
3836 if (ret)
3837 goto err;
3838 component->of_node = args.np;
3839 ret = snd_soc_get_dai_name(&args, &component->dai_name);
3840 if (ret < 0)
3841 goto err;
3842 }
3843 return 0;
3844err:
Sylwester Nawrocki94685762018-03-09 18:48:54 +01003845 snd_soc_of_put_dai_link_codecs(dai_link);
Jean-Francois Moine93b0f3e2014-11-25 13:16:12 +01003846 dai_link->codecs = NULL;
3847 dai_link->num_codecs = 0;
3848 return ret;
3849}
3850EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_link_codecs);
3851
Takashi Iwaic9b3a402008-12-10 07:47:22 +01003852static int __init snd_soc_init(void)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02003853{
Lars-Peter Clausen6553bf062015-04-09 10:52:38 +02003854 snd_soc_debugfs_init();
Mark Brownfb257892011-04-28 10:57:54 +01003855 snd_soc_util_init();
3856
Frank Mandarinodb2a4162006-10-06 18:31:09 +02003857 return platform_driver_register(&soc_driver);
3858}
Mark Brown4abe8e12010-10-12 17:41:03 +01003859module_init(snd_soc_init);
Frank Mandarinodb2a4162006-10-06 18:31:09 +02003860
Mark Brown7d8c16a2008-11-30 22:11:24 +00003861static void __exit snd_soc_exit(void)
Frank Mandarinodb2a4162006-10-06 18:31:09 +02003862{
Mark Brownfb257892011-04-28 10:57:54 +01003863 snd_soc_util_exit();
Lars-Peter Clausen6553bf062015-04-09 10:52:38 +02003864 snd_soc_debugfs_exit();
Mark Brownfb257892011-04-28 10:57:54 +01003865
Frank Mandarinodb2a4162006-10-06 18:31:09 +02003866 platform_driver_unregister(&soc_driver);
3867}
Frank Mandarinodb2a4162006-10-06 18:31:09 +02003868module_exit(snd_soc_exit);
3869
3870/* Module information */
Liam Girdwoodd3311242008-10-12 13:17:36 +01003871MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
Frank Mandarinodb2a4162006-10-06 18:31:09 +02003872MODULE_DESCRIPTION("ALSA SoC Core");
3873MODULE_LICENSE("GPL");
3874MODULE_ALIAS("platform:soc-audio");