summaryrefslogtreecommitdiff
path: root/sound/core/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/init.c')
-rw-r--r--sound/core/init.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/sound/core/init.c b/sound/core/init.c
index 20f37fb3800e..f413963c414f 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -58,6 +58,8 @@ static char *slots[SNDRV_CARDS];
module_param_array(slots, charp, NULL, 0444);
MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
+#define SND_CARD_STATE_MAX_LEN 16
+
/* return non-zero if the given index is reserved for the given
* module via slots option
*/
@@ -107,9 +109,39 @@ static void snd_card_id_read(struct snd_info_entry *entry,
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 @@ static int init_info_for_card(struct snd_card *card)
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 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
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;
@@ -972,6 +1016,35 @@ 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(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.