aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm_adsp.c
diff options
context:
space:
mode:
authorRichard Fitzgerald <rf@opensource.wolfsonmicro.com>2015-06-11 06:32:32 -0400
committerMark Brown <broonie@kernel.org>2015-06-11 06:39:39 -0400
commitf9f55e31f8a537b7eaccc4fdb243cff938fa428c (patch)
treeb81ddba619db305382f03242c0084f6fcd4b495c /sound/soc/codecs/wm_adsp.c
parent218e508784b6d4d047fa25ce45761043c6840fec (diff)
ASoC: wm_adsp: Add basic debugfs entries
This patch adds some debugfs nodes to get information about the currently running firmware. Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/wm_adsp.c')
-rw-r--r--sound/soc/codecs/wm_adsp.c195
1 files changed, 192 insertions, 3 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 214b86b8b132..f9f90b0f5db4 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -23,6 +23,7 @@
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
25#include <linux/workqueue.h> 25#include <linux/workqueue.h>
26#include <linux/debugfs.h>
26#include <sound/core.h> 27#include <sound/core.h>
27#include <sound/pcm.h> 28#include <sound/pcm.h>
28#include <sound/pcm_params.h> 29#include <sound/pcm_params.h>
@@ -248,6 +249,175 @@ struct wm_coeff_ctl {
248 unsigned int flags; 249 unsigned int flags;
249}; 250};
250 251
252#ifdef CONFIG_DEBUG_FS
253static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s)
254{
255 char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
256
257 mutex_lock(&dsp->debugfs_lock);
258 kfree(dsp->wmfw_file_name);
259 dsp->wmfw_file_name = tmp;
260 mutex_unlock(&dsp->debugfs_lock);
261}
262
263static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s)
264{
265 char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
266
267 mutex_lock(&dsp->debugfs_lock);
268 kfree(dsp->bin_file_name);
269 dsp->bin_file_name = tmp;
270 mutex_unlock(&dsp->debugfs_lock);
271}
272
273static void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
274{
275 mutex_lock(&dsp->debugfs_lock);
276 kfree(dsp->wmfw_file_name);
277 kfree(dsp->bin_file_name);
278 dsp->wmfw_file_name = NULL;
279 dsp->bin_file_name = NULL;
280 mutex_unlock(&dsp->debugfs_lock);
281}
282
283static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,
284 char __user *user_buf,
285 size_t count, loff_t *ppos)
286{
287 struct wm_adsp *dsp = file->private_data;
288 ssize_t ret;
289
290 mutex_lock(&dsp->debugfs_lock);
291
292 if (!dsp->wmfw_file_name || !dsp->running)
293 ret = 0;
294 else
295 ret = simple_read_from_buffer(user_buf, count, ppos,
296 dsp->wmfw_file_name,
297 strlen(dsp->wmfw_file_name));
298
299 mutex_unlock(&dsp->debugfs_lock);
300 return ret;
301}
302
303static ssize_t wm_adsp_debugfs_bin_read(struct file *file,
304 char __user *user_buf,
305 size_t count, loff_t *ppos)
306{
307 struct wm_adsp *dsp = file->private_data;
308 ssize_t ret;
309
310 mutex_lock(&dsp->debugfs_lock);
311
312 if (!dsp->bin_file_name || !dsp->running)
313 ret = 0;
314 else
315 ret = simple_read_from_buffer(user_buf, count, ppos,
316 dsp->bin_file_name,
317 strlen(dsp->bin_file_name));
318
319 mutex_unlock(&dsp->debugfs_lock);
320 return ret;
321}
322
323static const struct {
324 const char *name;
325 const struct file_operations fops;
326} wm_adsp_debugfs_fops[] = {
327 {
328 .name = "wmfw_file_name",
329 .fops = {
330 .open = simple_open,
331 .read = wm_adsp_debugfs_wmfw_read,
332 },
333 },
334 {
335 .name = "bin_file_name",
336 .fops = {
337 .open = simple_open,
338 .read = wm_adsp_debugfs_bin_read,
339 },
340 },
341};
342
343static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
344 struct snd_soc_codec *codec)
345{
346 struct dentry *root = NULL;
347 char *root_name;
348 int i;
349
350 if (!codec->component.debugfs_root) {
351 adsp_err(dsp, "No codec debugfs root\n");
352 goto err;
353 }
354
355 root_name = kmalloc(PAGE_SIZE, GFP_KERNEL);
356 if (!root_name)
357 goto err;
358
359 snprintf(root_name, PAGE_SIZE, "dsp%d", dsp->num);
360 root = debugfs_create_dir(root_name, codec->component.debugfs_root);
361 kfree(root_name);
362
363 if (!root)
364 goto err;
365
366 if (!debugfs_create_bool("running", S_IRUGO, root, &dsp->running))
367 goto err;
368
369 if (!debugfs_create_x32("fw_id", S_IRUGO, root, &dsp->fw_id))
370 goto err;
371
372 if (!debugfs_create_x32("fw_version", S_IRUGO, root,
373 &dsp->fw_id_version))
374 goto err;
375
376 for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) {
377 if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name,
378 S_IRUGO, root, dsp,
379 &wm_adsp_debugfs_fops[i].fops))
380 goto err;
381 }
382
383 dsp->debugfs_root = root;
384 return;
385
386err:
387 debugfs_remove_recursive(root);
388 adsp_err(dsp, "Failed to create debugfs\n");
389}
390
391static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
392{
393 wm_adsp_debugfs_clear(dsp);
394 debugfs_remove_recursive(dsp->debugfs_root);
395}
396#else
397static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
398 struct snd_soc_codec *codec)
399{
400}
401
402static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
403{
404}
405
406static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp,
407 const char *s)
408{
409}
410
411static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp,
412 const char *s)
413{
414}
415
416static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
417{
418}
419#endif
420
251static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 421static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
252 struct snd_ctl_elem_value *ucontrol) 422 struct snd_ctl_elem_value *ucontrol)
253{ 423{
@@ -1133,6 +1303,8 @@ static int wm_adsp_load(struct wm_adsp *dsp)
1133 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 1303 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
1134 file, regions, pos - firmware->size); 1304 file, regions, pos - firmware->size);
1135 1305
1306 wm_adsp_debugfs_save_wmfwname(dsp, file);
1307
1136out_fw: 1308out_fw:
1137 regmap_async_complete(regmap); 1309 regmap_async_complete(regmap);
1138 wm_adsp_buf_free(&buf_list); 1310 wm_adsp_buf_free(&buf_list);
@@ -1350,11 +1522,12 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
1350 1522
1351 n_algs = be32_to_cpu(adsp2_id.n_algs); 1523 n_algs = be32_to_cpu(adsp2_id.n_algs);
1352 dsp->fw_id = be32_to_cpu(adsp2_id.fw.id); 1524 dsp->fw_id = be32_to_cpu(adsp2_id.fw.id);
1525 dsp->fw_id_version = be32_to_cpu(adsp2_id.fw.ver);
1353 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", 1526 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
1354 dsp->fw_id, 1527 dsp->fw_id,
1355 (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16, 1528 (dsp->fw_id_version & 0xff0000) >> 16,
1356 (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8, 1529 (dsp->fw_id_version & 0xff00) >> 8,
1357 be32_to_cpu(adsp2_id.fw.ver) & 0xff, 1530 dsp->fw_id_version & 0xff,
1358 n_algs); 1531 n_algs);
1359 1532
1360 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, 1533 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM,
@@ -1630,6 +1803,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
1630 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", 1803 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
1631 file, blocks, pos - firmware->size); 1804 file, blocks, pos - firmware->size);
1632 1805
1806 wm_adsp_debugfs_save_binname(dsp, file);
1807
1633out_fw: 1808out_fw:
1634 regmap_async_complete(regmap); 1809 regmap_async_complete(regmap);
1635 release_firmware(firmware); 1810 release_firmware(firmware);
@@ -1643,6 +1818,9 @@ int wm_adsp1_init(struct wm_adsp *dsp)
1643{ 1818{
1644 INIT_LIST_HEAD(&dsp->alg_regions); 1819 INIT_LIST_HEAD(&dsp->alg_regions);
1645 1820
1821#ifdef CONFIG_DEBUG_FS
1822 mutex_init(&dsp->debugfs_lock);
1823#endif
1646 return 0; 1824 return 0;
1647} 1825}
1648EXPORT_SYMBOL_GPL(wm_adsp1_init); 1826EXPORT_SYMBOL_GPL(wm_adsp1_init);
@@ -1901,6 +2079,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1901 /* Log firmware state, it can be useful for analysis */ 2079 /* Log firmware state, it can be useful for analysis */
1902 wm_adsp2_show_fw_status(dsp); 2080 wm_adsp2_show_fw_status(dsp);
1903 2081
2082 wm_adsp_debugfs_clear(dsp);
2083
2084 dsp->fw_id = 0;
2085 dsp->fw_id_version = 0;
1904 dsp->running = false; 2086 dsp->running = false;
1905 2087
1906 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 2088 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
@@ -1940,6 +2122,8 @@ EXPORT_SYMBOL_GPL(wm_adsp2_event);
1940 2122
1941int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec) 2123int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec)
1942{ 2124{
2125 wm_adsp2_init_debugfs(dsp, codec);
2126
1943 return snd_soc_add_codec_controls(codec, 2127 return snd_soc_add_codec_controls(codec,
1944 wm_adsp2_fw_controls[dsp->num - 1], 2128 wm_adsp2_fw_controls[dsp->num - 1],
1945 ARRAY_SIZE(wm_adsp2_fw_controls[0])); 2129 ARRAY_SIZE(wm_adsp2_fw_controls[0]));
@@ -1948,6 +2132,8 @@ EXPORT_SYMBOL_GPL(wm_adsp2_codec_probe);
1948 2132
1949int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec) 2133int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec)
1950{ 2134{
2135 wm_adsp2_cleanup_debugfs(dsp);
2136
1951 return 0; 2137 return 0;
1952} 2138}
1953EXPORT_SYMBOL_GPL(wm_adsp2_codec_remove); 2139EXPORT_SYMBOL_GPL(wm_adsp2_codec_remove);
@@ -1971,6 +2157,9 @@ int wm_adsp2_init(struct wm_adsp *dsp)
1971 INIT_LIST_HEAD(&dsp->ctl_list); 2157 INIT_LIST_HEAD(&dsp->ctl_list);
1972 INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work); 2158 INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work);
1973 2159
2160#ifdef CONFIG_DEBUG_FS
2161 mutex_init(&dsp->debugfs_lock);
2162#endif
1974 return 0; 2163 return 0;
1975} 2164}
1976EXPORT_SYMBOL_GPL(wm_adsp2_init); 2165EXPORT_SYMBOL_GPL(wm_adsp2_init);