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

Commit 79fb9387 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: Add DAPM widget power decision debugfs files



Currently when built with DEBUG DAPM will dump information about
the power state decisions it is taking for each widget to dmesg.
This isn't an ideal way of getting the information - it requires
a kernel build to turn it on and off and for large hub CODECs the
volume of information is so large as to be illegible. When the
output goes to the console it can also cause a noticable impact
on performance simply to print it out.

Improve the situation by adding a dapm directory to our debugfs
tree containing a file per widget with the same information in
it. This still requires a decision to build with debugfs support
but is easier to navigate and much less intrusive.

In addition to the previously displayed information active streams
are also shown in these files.

Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent b8e583f6
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -283,6 +283,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_device *socdev);


/* dapm sys fs - used by the core */
/* dapm sys fs - used by the core */
int snd_soc_dapm_sys_add(struct device *dev);
int snd_soc_dapm_sys_add(struct device *dev);
void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec);


/* dapm audio pin control and status */
/* dapm audio pin control and status */
int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin);
int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin);
+1 −0
Original line number Original line Diff line number Diff line
@@ -416,6 +416,7 @@ struct snd_soc_codec {
#ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_DEBUG_FS
	struct dentry *debugfs_reg;
	struct dentry *debugfs_reg;
	struct dentry *debugfs_pop_time;
	struct dentry *debugfs_pop_time;
	struct dentry *debugfs_dapm;
#endif
#endif
};
};


+8 −0
Original line number Original line Diff line number Diff line
@@ -1267,10 +1267,18 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
	if (!codec->debugfs_pop_time)
	if (!codec->debugfs_pop_time)
		printk(KERN_WARNING
		printk(KERN_WARNING
		       "Failed to create pop time debugfs file\n");
		       "Failed to create pop time debugfs file\n");

	codec->debugfs_dapm = debugfs_create_dir("dapm", debugfs_root);
	if (!codec->debugfs_dapm)
		printk(KERN_WARNING
		       "Failed to create DAPM debugfs directory\n");

	snd_soc_dapm_debugfs_init(codec);
}
}


static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
{
{
	debugfs_remove_recursive(codec->debugfs_dapm);
	debugfs_remove(codec->debugfs_pop_time);
	debugfs_remove(codec->debugfs_pop_time);
	debugfs_remove(codec->debugfs_reg);
	debugfs_remove(codec->debugfs_reg);
}
}
+86 −0
Original line number Original line Diff line number Diff line
@@ -1081,6 +1081,92 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
}
}
#endif
#endif


#ifdef CONFIG_DEBUG_FS
static int dapm_widget_power_open_file(struct inode *inode, struct file *file)
{
	file->private_data = inode->i_private;
	return 0;
}

static ssize_t dapm_widget_power_read_file(struct file *file,
					   char __user *user_buf,
					   size_t count, loff_t *ppos)
{
	struct snd_soc_dapm_widget *w = file->private_data;
	char *buf;
	int in, out;
	ssize_t ret;
	struct snd_soc_dapm_path *p = NULL;

	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	in = is_connected_input_ep(w);
	dapm_clear_walk(w->codec);
	out = is_connected_output_ep(w);
	dapm_clear_walk(w->codec);

	ret = snprintf(buf, PAGE_SIZE, "%s: %s  in %d out %d\n",
		       w->name, w->power ? "On" : "Off", in, out);

	if (w->active && w->sname)
		ret += snprintf(buf, PAGE_SIZE - ret, " stream %s active\n",
				w->sname);

	list_for_each_entry(p, &w->sources, list_sink) {
		if (p->connect)
			ret += snprintf(buf + ret, PAGE_SIZE - ret,
					" in  %s %s\n",
					p->name ? p->name : "static",
					p->source->name);
	}
	list_for_each_entry(p, &w->sinks, list_source) {
		if (p->connect)
			ret += snprintf(buf + ret, PAGE_SIZE - ret,
					" out %s %s\n",
					p->name ? p->name : "static",
					p->sink->name);
	}

	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);

	kfree(buf);
	return ret;
}

static const struct file_operations dapm_widget_power_fops = {
	.open = dapm_widget_power_open_file,
	.read = dapm_widget_power_read_file,
};

void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
{
	struct snd_soc_dapm_widget *w;
	struct dentry *d;

	if (!codec->debugfs_dapm)
		return;

	list_for_each_entry(w, &codec->dapm_widgets, list) {
		if (!w->name)
			continue;

		d = debugfs_create_file(w->name, 0444,
					codec->debugfs_dapm, w,
					&dapm_widget_power_fops);
		if (!d)
			printk(KERN_WARNING
			       "ASoC: Failed to create %s debugfs file\n",
			       w->name);
	}
}
#else
void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
{
}
#endif

/* test and update the power status of a mux widget */
/* test and update the power status of a mux widget */
static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
				 struct snd_kcontrol *kcontrol, int mask,
				 struct snd_kcontrol *kcontrol, int mask,