diff options
author | Richard Fitzgerald <rf@opensource.wolfsonmicro.com> | 2015-06-11 06:32:32 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-06-11 06:39:39 -0400 |
commit | f9f55e31f8a537b7eaccc4fdb243cff938fa428c (patch) | |
tree | b81ddba619db305382f03242c0084f6fcd4b495c /sound/soc/codecs/wm_adsp.c | |
parent | 218e508784b6d4d047fa25ce45761043c6840fec (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.c | 195 |
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 | ||
253 | static 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 | |||
263 | static 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 | |||
273 | static 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 | |||
283 | static 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 | |||
303 | static 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 | |||
323 | static 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 | |||
343 | static 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 | |||
386 | err: | ||
387 | debugfs_remove_recursive(root); | ||
388 | adsp_err(dsp, "Failed to create debugfs\n"); | ||
389 | } | ||
390 | |||
391 | static 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 | ||
397 | static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp, | ||
398 | struct snd_soc_codec *codec) | ||
399 | { | ||
400 | } | ||
401 | |||
402 | static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) | ||
403 | { | ||
404 | } | ||
405 | |||
406 | static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, | ||
407 | const char *s) | ||
408 | { | ||
409 | } | ||
410 | |||
411 | static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, | ||
412 | const char *s) | ||
413 | { | ||
414 | } | ||
415 | |||
416 | static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp) | ||
417 | { | ||
418 | } | ||
419 | #endif | ||
420 | |||
251 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, | 421 | static 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 | |||
1136 | out_fw: | 1308 | out_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 | |||
1633 | out_fw: | 1808 | out_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 | } |
1648 | EXPORT_SYMBOL_GPL(wm_adsp1_init); | 1826 | EXPORT_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 | ||
1941 | int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec) | 2123 | int 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 | ||
1949 | int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec) | 2133 | int 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 | } |
1953 | EXPORT_SYMBOL_GPL(wm_adsp2_codec_remove); | 2139 | EXPORT_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 | } |
1976 | EXPORT_SYMBOL_GPL(wm_adsp2_init); | 2165 | EXPORT_SYMBOL_GPL(wm_adsp2_init); |