.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Initialization routines |
---|
3 | 4 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
---|
4 | | - * |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License as published by |
---|
8 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
9 | | - * (at your option) any later version. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, |
---|
12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | | - * GNU General Public License for more details. |
---|
15 | | - * |
---|
16 | | - * You should have received a copy of the GNU General Public License |
---|
17 | | - * along with this program; if not, write to the Free Software |
---|
18 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
19 | | - * |
---|
20 | 5 | */ |
---|
21 | 6 | |
---|
22 | 7 | #include <linux/init.h> |
---|
.. | .. |
---|
29 | 14 | #include <linux/ctype.h> |
---|
30 | 15 | #include <linux/pm.h> |
---|
31 | 16 | #include <linux/completion.h> |
---|
| 17 | +#include <linux/interrupt.h> |
---|
32 | 18 | |
---|
33 | 19 | #include <sound/core.h> |
---|
34 | 20 | #include <sound/control.h> |
---|
.. | .. |
---|
49 | 35 | |
---|
50 | 36 | /* locked for registering/using */ |
---|
51 | 37 | static DECLARE_BITMAP(snd_cards_lock, SNDRV_CARDS); |
---|
52 | | -struct snd_card *snd_cards[SNDRV_CARDS]; |
---|
53 | | -EXPORT_SYMBOL(snd_cards); |
---|
| 38 | +static struct snd_card *snd_cards[SNDRV_CARDS]; |
---|
54 | 39 | |
---|
55 | 40 | static DEFINE_MUTEX(snd_card_mutex); |
---|
56 | 41 | |
---|
.. | .. |
---|
98 | 83 | #if IS_ENABLED(CONFIG_SND_MIXER_OSS) |
---|
99 | 84 | int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag); |
---|
100 | 85 | EXPORT_SYMBOL(snd_mixer_oss_notify_callback); |
---|
101 | | -#endif |
---|
102 | | - |
---|
103 | | -#ifdef CONFIG_SND_PROC_FS |
---|
104 | | -static void snd_card_id_read(struct snd_info_entry *entry, |
---|
105 | | - struct snd_info_buffer *buffer) |
---|
106 | | -{ |
---|
107 | | - snd_iprintf(buffer, "%s\n", entry->card->id); |
---|
108 | | -} |
---|
109 | | - |
---|
110 | | -static int init_info_for_card(struct snd_card *card) |
---|
111 | | -{ |
---|
112 | | - struct snd_info_entry *entry; |
---|
113 | | - |
---|
114 | | - entry = snd_info_create_card_entry(card, "id", card->proc_root); |
---|
115 | | - if (!entry) { |
---|
116 | | - dev_dbg(card->dev, "unable to create card entry\n"); |
---|
117 | | - return -ENOMEM; |
---|
118 | | - } |
---|
119 | | - entry->c.text.read = snd_card_id_read; |
---|
120 | | - card->proc_id = entry; |
---|
121 | | - |
---|
122 | | - return snd_info_card_register(card); |
---|
123 | | -} |
---|
124 | | -#else /* !CONFIG_SND_PROC_FS */ |
---|
125 | | -#define init_info_for_card(card) |
---|
126 | 86 | #endif |
---|
127 | 87 | |
---|
128 | 88 | static int check_empty_slot(struct module *module, int slot) |
---|
.. | .. |
---|
244 | 204 | mutex_unlock(&snd_card_mutex); |
---|
245 | 205 | card->dev = parent; |
---|
246 | 206 | card->number = idx; |
---|
| 207 | +#ifdef MODULE |
---|
| 208 | + WARN_ON(!module); |
---|
247 | 209 | card->module = module; |
---|
| 210 | +#endif |
---|
248 | 211 | INIT_LIST_HEAD(&card->devices); |
---|
249 | 212 | init_rwsem(&card->controls_rwsem); |
---|
250 | 213 | rwlock_init(&card->ctl_files_rwlock); |
---|
.. | .. |
---|
252 | 215 | INIT_LIST_HEAD(&card->ctl_files); |
---|
253 | 216 | spin_lock_init(&card->files_lock); |
---|
254 | 217 | INIT_LIST_HEAD(&card->files_list); |
---|
| 218 | + mutex_init(&card->memory_mutex); |
---|
255 | 219 | #ifdef CONFIG_PM |
---|
256 | 220 | init_waitqueue_head(&card->power_sleep); |
---|
257 | 221 | #endif |
---|
258 | 222 | init_waitqueue_head(&card->remove_sleep); |
---|
| 223 | + card->sync_irq = -1; |
---|
259 | 224 | |
---|
260 | | - init_waitqueue_head(&card->offline_poll_wait); |
---|
261 | 225 | device_initialize(&card->card_dev); |
---|
262 | 226 | card->card_dev.parent = parent; |
---|
263 | 227 | card->card_dev.class = sound_class; |
---|
.. | .. |
---|
293 | 257 | return err; |
---|
294 | 258 | } |
---|
295 | 259 | EXPORT_SYMBOL(snd_card_new); |
---|
| 260 | + |
---|
| 261 | +/** |
---|
| 262 | + * snd_card_ref - Get the card object from the index |
---|
| 263 | + * @idx: the card index |
---|
| 264 | + * |
---|
| 265 | + * Returns a card object corresponding to the given index or NULL if not found. |
---|
| 266 | + * Release the object via snd_card_unref(). |
---|
| 267 | + */ |
---|
| 268 | +struct snd_card *snd_card_ref(int idx) |
---|
| 269 | +{ |
---|
| 270 | + struct snd_card *card; |
---|
| 271 | + |
---|
| 272 | + mutex_lock(&snd_card_mutex); |
---|
| 273 | + card = snd_cards[idx]; |
---|
| 274 | + if (card) |
---|
| 275 | + get_device(&card->card_dev); |
---|
| 276 | + mutex_unlock(&snd_card_mutex); |
---|
| 277 | + return card; |
---|
| 278 | +} |
---|
| 279 | +EXPORT_SYMBOL_GPL(snd_card_ref); |
---|
296 | 280 | |
---|
297 | 281 | /* return non-zero if a card is already locked */ |
---|
298 | 282 | int snd_card_locked(int card) |
---|
.. | .. |
---|
433 | 417 | /* notify all devices that we are disconnected */ |
---|
434 | 418 | snd_device_disconnect_all(card); |
---|
435 | 419 | |
---|
| 420 | + if (card->sync_irq > 0) |
---|
| 421 | + synchronize_irq(card->sync_irq); |
---|
| 422 | + |
---|
436 | 423 | snd_info_card_disconnect(card); |
---|
437 | 424 | if (card->registered) { |
---|
438 | 425 | device_del(&card->card_dev); |
---|
.. | .. |
---|
490 | 477 | snd_device_free_all(card); |
---|
491 | 478 | if (card->private_free) |
---|
492 | 479 | card->private_free(card); |
---|
493 | | - snd_info_free_entry(card->proc_id); |
---|
494 | 480 | if (snd_info_card_free(card) < 0) { |
---|
495 | 481 | dev_warn(card->dev, "unable to free card info\n"); |
---|
496 | 482 | /* Not fatal error */ |
---|
.. | .. |
---|
535 | 521 | */ |
---|
536 | 522 | int snd_card_free(struct snd_card *card) |
---|
537 | 523 | { |
---|
538 | | - struct completion released; |
---|
| 524 | + DECLARE_COMPLETION_ONSTACK(released); |
---|
539 | 525 | int ret; |
---|
540 | 526 | |
---|
541 | | - init_completion(&released); |
---|
542 | 527 | card->release_completion = &released; |
---|
543 | 528 | ret = snd_card_free_when_closed(card); |
---|
544 | 529 | if (ret) |
---|
.. | .. |
---|
794 | 779 | } |
---|
795 | 780 | snd_cards[card->number] = card; |
---|
796 | 781 | mutex_unlock(&snd_card_mutex); |
---|
797 | | - init_info_for_card(card); |
---|
| 782 | + err = snd_info_card_register(card); |
---|
| 783 | + if (err < 0) |
---|
| 784 | + return err; |
---|
| 785 | + |
---|
798 | 786 | #if IS_ENABLED(CONFIG_SND_MIXER_OSS) |
---|
799 | 787 | if (snd_mixer_oss_notify_callback) |
---|
800 | 788 | snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER); |
---|
.. | .. |
---|
998 | 986 | return 0; |
---|
999 | 987 | } |
---|
1000 | 988 | EXPORT_SYMBOL(snd_card_file_remove); |
---|
1001 | | - |
---|
1002 | | -/** |
---|
1003 | | - * snd_card_change_online_state - mark card's online/offline state |
---|
1004 | | - * @card: Card to mark |
---|
1005 | | - * @online: whether online of offline |
---|
1006 | | - * |
---|
1007 | | - * Mutes the DAI DAC. |
---|
1008 | | - */ |
---|
1009 | | -void snd_card_change_online_state(struct snd_card *card, int online) |
---|
1010 | | -{ |
---|
1011 | | - snd_printd("snd card %s state change %d -> %d\n", |
---|
1012 | | - card->shortname, !card->offline, online); |
---|
1013 | | - card->offline = !online; |
---|
1014 | | - /* make sure offline is updated prior to wake up */ |
---|
1015 | | - wmb(); |
---|
1016 | | - xchg(&card->offline_change, 1); |
---|
1017 | | - wake_up_interruptible(&card->offline_poll_wait); |
---|
1018 | | -} |
---|
1019 | | -EXPORT_SYMBOL_GPL(snd_card_change_online_state); |
---|
1020 | 989 | |
---|
1021 | 990 | #ifdef CONFIG_PM |
---|
1022 | 991 | /** |
---|