--- zzzz-none-000/linux-4.4.271/sound/core/init.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/sound/core/init.c 2023-04-19 10:22:30.000000000 +0000 @@ -34,6 +34,8 @@ #include #include +#define SND_CARD_STATE_MAX_LEN 16 + /* monitor files for graceful shutdown (hotplug) */ struct snd_monitor_file { struct file *file; @@ -107,9 +109,39 @@ snd_iprintf(buffer, "%s\n", entry->card->id); } +static ssize_t snd_card_state_read(struct snd_info_entry *entry, + void *file_private_data, struct file *file, + char __user *buf, size_t count, loff_t pos) +{ + int len; + char buffer[SND_CARD_STATE_MAX_LEN]; + + /* make sure offline is updated prior to wake up */ + rmb(); + len = snprintf(buffer, sizeof(buffer), "%s\n", + entry->card->offline ? "OFFLINE" : "ONLINE"); + return simple_read_from_buffer(buf, count, &pos, buffer, len); +} + +static unsigned int snd_card_state_poll(struct snd_info_entry *entry, + void *private_data, struct file *file, + poll_table *wait) +{ + poll_wait(file, &entry->card->offline_poll_wait, wait); + if (xchg(&entry->card->offline_change, 0)) + return POLLIN | POLLPRI | POLLRDNORM; + else + return 0; +} + +static struct snd_info_entry_ops snd_card_state_proc_ops = { + .read = snd_card_state_read, + .poll = snd_card_state_poll, +}; + static int init_info_for_card(struct snd_card *card) { - struct snd_info_entry *entry; + struct snd_info_entry *entry, *entry_state; entry = snd_info_create_card_entry(card, "id", card->proc_root); if (!entry) { @@ -119,6 +151,17 @@ entry->c.text.read = snd_card_id_read; card->proc_id = entry; + entry_state = snd_info_create_card_entry(card, "state", + card->proc_root); + if (!entry_state) { + dev_dbg(card->dev, "unable to create card entry state\n"); + card->proc_id = NULL; + return -ENOMEM; + } + entry_state->size = SND_CARD_STATE_MAX_LEN; + entry_state->content = SNDRV_INFO_CONTENT_DATA; + entry_state->c.ops = &snd_card_state_proc_ops; + return snd_info_card_register(card); } #else /* !CONFIG_SND_PROC_FS */ @@ -258,6 +301,7 @@ init_waitqueue_head(&card->power_sleep); #endif + init_waitqueue_head(&card->offline_poll_wait); device_initialize(&card->card_dev); card->card_dev.parent = parent; card->card_dev.class = sound_class; @@ -970,6 +1014,35 @@ 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(snd_card_change_online_state); + +/** + * snd_card_is_online_state - return true if card is online state + * @card: Card to query + */ +bool snd_card_is_online_state(struct snd_card *card) +{ + return !card->offline; +} +EXPORT_SYMBOL(snd_card_is_online_state); + #ifdef CONFIG_PM /** * snd_power_wait - wait until the power-state is changed.