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:
parent
b8e583f601
commit
79fb9387f8
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue