Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d654c961 authored by Meng Wang's avatar Meng Wang Committed by Gerrit - the friendly Code Review server
Browse files

ALSA: core: Expose sound card online/offline state



Expose sound card online/offline state to procfs so userspace application
can poll and read sound card's state.

Change-Id: Ie605ad57f4ce5abf62a216e790407029658ac3c9
Signed-off-by: default avatarJoonwoo Park <joonwoop@codeaurora.org>
Signed-off-by: default avatarBanajit Goswami <bgoswami@codeaurora.org>
Signed-off-by: default avatarSudheer Papothi <spapothi@codeaurora.org>
Signed-off-by: default avatarMeng Wang <mwang@codeaurora.org>
parent 26c28048
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -135,6 +135,9 @@ struct snd_card {
	struct device card_dev;		/* cardX object for sysfs */
	struct device card_dev;		/* cardX object for sysfs */
	const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */
	const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */
	bool registered;		/* card_dev is registered? */
	bool registered;		/* card_dev is registered? */
	int offline;			/* if this sound card is offline */
	unsigned long offline_change;
	wait_queue_head_t offline_poll_wait;


#ifdef CONFIG_PM
#ifdef CONFIG_PM
	unsigned int power_state;	/* power state */
	unsigned int power_state;	/* power state */
@@ -266,6 +269,8 @@ 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_add(struct snd_card *card, struct file *file);
int snd_card_file_remove(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)
#define snd_card_unref(card)	put_device(&(card)->card_dev)
void snd_card_change_online_state(struct snd_card *card, int online);
bool snd_card_is_online_state(struct snd_card *card);


#define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
#define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))


+2 −1
Original line number Original line Diff line number Diff line
@@ -584,12 +584,13 @@ int snd_soc_update_bits_locked(struct snd_soc_codec *codec,
int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
				unsigned int mask, unsigned int value);
				unsigned int mask, unsigned int value);


void snd_soc_card_change_online_state(struct snd_soc_card *soc_card,
				      int online);
#ifdef CONFIG_SND_SOC_AC97_BUS
#ifdef CONFIG_SND_SOC_AC97_BUS
struct snd_ac97 *snd_soc_alloc_ac97_codec(struct snd_soc_codec *codec);
struct snd_ac97 *snd_soc_alloc_ac97_codec(struct snd_soc_codec *codec);
struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
	unsigned int id, unsigned int id_mask);
	unsigned int id, unsigned int id_mask);
void snd_soc_free_ac97_codec(struct snd_ac97 *ac97);
void snd_soc_free_ac97_codec(struct snd_ac97 *ac97);

int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops);
int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops,
int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops,
		struct platform_device *pdev);
		struct platform_device *pdev);
+74 −1
Original line number Original line Diff line number Diff line
@@ -58,6 +58,8 @@ static char *slots[SNDRV_CARDS];
module_param_array(slots, charp, NULL, 0444);
module_param_array(slots, charp, NULL, 0444);
MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
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
/* return non-zero if the given index is reserved for the given
 * module via slots option
 * 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);
	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)
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);
	entry = snd_info_create_card_entry(card, "id", card->proc_root);
	if (!entry) {
	if (!entry) {
@@ -119,6 +151,17 @@ static int init_info_for_card(struct snd_card *card)
	entry->c.text.read = snd_card_id_read;
	entry->c.text.read = snd_card_id_read;
	card->proc_id = entry;
	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);
	return snd_info_card_register(card);
}
}
#else /* !CONFIG_SND_PROC_FS */
#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);
	init_waitqueue_head(&card->power_sleep);
#endif
#endif


	init_waitqueue_head(&card->offline_poll_wait);
	device_initialize(&card->card_dev);
	device_initialize(&card->card_dev);
	card->card_dev.parent = parent;
	card->card_dev.parent = parent;
	card->card_dev.class = sound_class;
	card->card_dev.class = sound_class;
@@ -970,6 +1014,35 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
}
}
EXPORT_SYMBOL(snd_card_file_remove);
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
#ifdef CONFIG_PM
/**
/**
 *  snd_power_wait - wait until the power-state is changed.
 *  snd_power_wait - wait until the power-state is changed.
+11 −0
Original line number Original line Diff line number Diff line
@@ -3565,6 +3565,17 @@ static int snd_soc_codec_set_bias_level(struct snd_soc_dapm_context *dapm,
	return codec->driver->set_bias_level(codec, level);
	return codec->driver->set_bias_level(codec, level);
}
}


/**
 * 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(snd_soc_card_change_online_state);

/**
/**
 * snd_soc_register_codec - Register a codec with the ASoC core
 * snd_soc_register_codec - Register a codec with the ASoC core
 *
 *
+11 −0
Original line number Original line Diff line number Diff line
@@ -195,9 +195,14 @@ EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);


unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg)
unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg)
{
{
	struct snd_card *snd_card = codec->component.card->snd_card;
	unsigned int val;
	unsigned int val;
	int ret;
	int ret;


	if (unlikely(!snd_card_is_online_state(snd_card))) {
		dev_err(codec->dev, "read 0x%02x while offline\n", reg);
		return -ENODEV;
	}
	ret = snd_soc_component_read(&codec->component, reg, &val);
	ret = snd_soc_component_read(&codec->component, reg, &val);
	if (ret < 0)
	if (ret < 0)
		return -1;
		return -1;
@@ -209,6 +214,12 @@ EXPORT_SYMBOL_GPL(snd_soc_read);
int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
	unsigned int val)
	unsigned int val)
{
{
	struct snd_card *snd_card = codec->component.card->snd_card;

	if (unlikely(!snd_card_is_online_state(snd_card))) {
		dev_err(codec->dev, "write 0x%02x while offline\n", reg);
		return -ENODEV;
	}
	return snd_soc_component_write(&codec->component, reg, val);
	return snd_soc_component_write(&codec->component, reg, val);
}
}
EXPORT_SYMBOL_GPL(snd_soc_write);
EXPORT_SYMBOL_GPL(snd_soc_write);