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: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
Mark Brown 2009-08-21 16:38:13 +01:00
parent b8e583f601
commit 79fb9387f8
4 changed files with 96 additions and 0 deletions

View file

@ -283,6 +283,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_device *socdev);
/* dapm sys fs - used by the core */
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 */
int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin);

View file

@ -416,6 +416,7 @@ struct snd_soc_codec {
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_reg;
struct dentry *debugfs_pop_time;
struct dentry *debugfs_dapm;
#endif
};

View file

@ -1267,10 +1267,18 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
if (!codec->debugfs_pop_time)
printk(KERN_WARNING
"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)
{
debugfs_remove_recursive(codec->debugfs_dapm);
debugfs_remove(codec->debugfs_pop_time);
debugfs_remove(codec->debugfs_reg);
}

View file

@ -1081,6 +1081,92 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
}
#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 */
static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kcontrol, int mask,