diff --git a/include/sound/core.h b/include/sound/core.h index 36a5934cf4b1..3b8274e74ffb 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -134,6 +134,9 @@ struct snd_card { const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */ bool registered; /* card_dev is registered? */ wait_queue_head_t remove_sleep; + int offline; /* if this sound card is offline */ + unsigned long offline_change; + wait_queue_head_t offline_poll_wait; #ifdef CONFIG_PM unsigned int power_state; /* power state */ @@ -253,6 +256,7 @@ int snd_component_add(struct snd_card *card, const char *component); int snd_card_file_add(struct snd_card *card, struct file *file); int snd_card_file_remove(struct snd_card *card, struct file *file); #define snd_card_unref(card) put_device(&(card)->card_dev) +void snd_card_change_online_state(struct snd_card *card, int online); #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) diff --git a/include/sound/soc.h b/include/sound/soc.h index fb069f1d7666..981ce5bee896 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -556,6 +556,8 @@ static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, } #endif +void snd_soc_card_change_online_state(struct snd_soc_card *soc_card, + int online); struct snd_ac97 *snd_soc_alloc_ac97_component(struct snd_soc_component *component); struct snd_ac97 *snd_soc_new_ac97_component(struct snd_soc_component *component, unsigned int id, unsigned int id_mask); diff --git a/sound/core/init.c b/sound/core/init.c index 16b7cc7aa66b..913c55e2fc2b 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -257,6 +257,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid, #endif init_waitqueue_head(&card->remove_sleep); + init_waitqueue_head(&card->offline_poll_wait); device_initialize(&card->card_dev); card->card_dev.parent = parent; card->card_dev.class = sound_class; @@ -1000,6 +1001,25 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) } EXPORT_SYMBOL(snd_card_file_remove); +/** + * snd_card_change_online_state - mark card's online/offline state + * @card: Card to mark + * @online: whether online of offline + * + * Mutes the DAI DAC. + */ +void snd_card_change_online_state(struct snd_card *card, int online) +{ + snd_printd("snd card %s state change %d -> %d\n", + card->shortname, !card->offline, online); + card->offline = !online; + /* make sure offline is updated prior to wake up */ + wmb(); + xchg(&card->offline_change, 1); + wake_up_interruptible(&card->offline_poll_wait); +} +EXPORT_SYMBOL_GPL(snd_card_change_online_state); + #ifdef CONFIG_PM /** * snd_power_wait - wait until the power-state is changed. diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index afdfc0ec0267..8008dc7098c4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3274,6 +3274,17 @@ struct snd_soc_component *snd_soc_lookup_component(struct device *dev, } EXPORT_SYMBOL_GPL(snd_soc_lookup_component); +/** + * snd_soc_card_change_online_state - Mark if soc card is online/offline + * + * @soc_card : soc_card to mark + */ +void snd_soc_card_change_online_state(struct snd_soc_card *soc_card, int online) +{ + snd_card_change_online_state(soc_card->snd_card, online); +} +EXPORT_SYMBOL_GPL(snd_soc_card_change_online_state); + /* Retrieve a card's name from device tree */ int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname)