Loading sound/soc/atmel/Kconfig +17 −8 Original line number Diff line number Diff line Loading @@ -9,21 +9,32 @@ config SND_ATMEL_SOC if SND_ATMEL_SOC config SND_ATMEL_SOC_PDC bool tristate default m if SND_ATMEL_SOC_SSC_PDC=m && SND_ATMEL_SOC_SSC=m default y if SND_ATMEL_SOC_SSC_PDC=y || (SND_ATMEL_SOC_SSC_PDC=m && SND_ATMEL_SOC_SSC=y) config SND_ATMEL_SOC_SSC_PDC tristate config SND_ATMEL_SOC_DMA bool tristate select SND_SOC_GENERIC_DMAENGINE_PCM default m if SND_ATMEL_SOC_SSC_DMA=m && SND_ATMEL_SOC_SSC=m default y if SND_ATMEL_SOC_SSC_DMA=y || (SND_ATMEL_SOC_SSC_DMA=m && SND_ATMEL_SOC_SSC=y) config SND_ATMEL_SOC_SSC_DMA tristate config SND_ATMEL_SOC_SSC tristate default y if SND_ATMEL_SOC_SSC_DMA=y || SND_ATMEL_SOC_SSC_PDC=y default m if SND_ATMEL_SOC_SSC_DMA=m || SND_ATMEL_SOC_SSC_PDC=m config SND_AT91_SOC_SAM9G20_WM8731 tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" depends on ARCH_AT91 || COMPILE_TEST depends on ATMEL_SSC && SND_SOC_I2C_AND_SPI select SND_ATMEL_SOC_PDC select SND_ATMEL_SOC_SSC select SND_ATMEL_SOC_SSC_PDC select SND_SOC_WM8731 help Say Y if you want to add support for SoC audio on WM8731-based Loading @@ -33,8 +44,7 @@ config SND_ATMEL_SOC_WM8904 tristate "Atmel ASoC driver for boards using WM8904 codec" depends on ARCH_AT91 || COMPILE_TEST depends on ATMEL_SSC && I2C select SND_ATMEL_SOC_SSC select SND_ATMEL_SOC_DMA select SND_ATMEL_SOC_SSC_DMA select SND_SOC_WM8904 help Say Y if you want to add support for Atmel ASoC driver for boards using Loading @@ -44,8 +54,7 @@ config SND_AT91_SOC_SAM9X5_WM8731 tristate "SoC Audio support for WM8731-based at91sam9x5 board" depends on ARCH_AT91 || COMPILE_TEST depends on ATMEL_SSC && SND_SOC_I2C_AND_SPI select SND_ATMEL_SOC_SSC select SND_ATMEL_SOC_DMA select SND_ATMEL_SOC_SSC_DMA select SND_SOC_WM8731 help Say Y if you want to add support for audio SoC on an Loading sound/soc/atmel/Makefile +5 −3 Original line number Diff line number Diff line # AT91 Platform Support snd-soc-atmel-pcm-$(CONFIG_SND_ATMEL_SOC_PDC) := atmel-pcm-pdc.o snd-soc-atmel-pcm-$(CONFIG_SND_ATMEL_SOC_DMA) += atmel-pcm-dma.o snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o $(snd-soc-atmel-pcm-y) snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o # AT91 Machine Support Loading sound/soc/codecs/wm5102.c +4 −2 Original line number Diff line number Diff line Loading @@ -1876,8 +1876,8 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 2); if (ret != 0) ret = wm_adsp2_codec_probe(&priv->core.adsp[0], codec); if (ret) return ret; arizona_init_spk(codec); Loading @@ -1894,6 +1894,8 @@ static int wm5102_codec_remove(struct snd_soc_codec *codec) { struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); wm_adsp2_codec_remove(&priv->core.adsp[0], codec); priv->core.arizona->dapm = NULL; return 0; Loading sound/soc/codecs/wm5110.c +10 −4 Original line number Diff line number Diff line Loading @@ -1600,7 +1600,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; int i, ret; priv->core.arizona->dapm = dapm; Loading @@ -1608,9 +1608,11 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) arizona_init_gpio(codec); arizona_init_mono(codec); ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8); if (ret != 0) for (i = 0; i < WM5110_NUM_ADSP; ++i) { ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec); if (ret) return ret; } snd_soc_dapm_disable_pin(dapm, "HAPTICS"); Loading @@ -1620,6 +1622,10 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) static int wm5110_codec_remove(struct snd_soc_codec *codec) { struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); int i; for (i = 0; i < WM5110_NUM_ADSP; ++i) wm_adsp2_codec_remove(&priv->core.adsp[i], codec); priv->core.arizona->dapm = NULL; Loading sound/soc/codecs/wm_adsp.c +227 −19 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/workqueue.h> #include <linux/debugfs.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> Loading Loading @@ -248,6 +249,175 @@ struct wm_coeff_ctl { unsigned int flags; }; #ifdef CONFIG_DEBUG_FS static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s) { char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); mutex_lock(&dsp->debugfs_lock); kfree(dsp->wmfw_file_name); dsp->wmfw_file_name = tmp; mutex_unlock(&dsp->debugfs_lock); } static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s) { char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); mutex_lock(&dsp->debugfs_lock); kfree(dsp->bin_file_name); dsp->bin_file_name = tmp; mutex_unlock(&dsp->debugfs_lock); } static void wm_adsp_debugfs_clear(struct wm_adsp *dsp) { mutex_lock(&dsp->debugfs_lock); kfree(dsp->wmfw_file_name); kfree(dsp->bin_file_name); dsp->wmfw_file_name = NULL; dsp->bin_file_name = NULL; mutex_unlock(&dsp->debugfs_lock); } static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct wm_adsp *dsp = file->private_data; ssize_t ret; mutex_lock(&dsp->debugfs_lock); if (!dsp->wmfw_file_name || !dsp->running) ret = 0; else ret = simple_read_from_buffer(user_buf, count, ppos, dsp->wmfw_file_name, strlen(dsp->wmfw_file_name)); mutex_unlock(&dsp->debugfs_lock); return ret; } static ssize_t wm_adsp_debugfs_bin_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct wm_adsp *dsp = file->private_data; ssize_t ret; mutex_lock(&dsp->debugfs_lock); if (!dsp->bin_file_name || !dsp->running) ret = 0; else ret = simple_read_from_buffer(user_buf, count, ppos, dsp->bin_file_name, strlen(dsp->bin_file_name)); mutex_unlock(&dsp->debugfs_lock); return ret; } static const struct { const char *name; const struct file_operations fops; } wm_adsp_debugfs_fops[] = { { .name = "wmfw_file_name", .fops = { .open = simple_open, .read = wm_adsp_debugfs_wmfw_read, }, }, { .name = "bin_file_name", .fops = { .open = simple_open, .read = wm_adsp_debugfs_bin_read, }, }, }; static void wm_adsp2_init_debugfs(struct wm_adsp *dsp, struct snd_soc_codec *codec) { struct dentry *root = NULL; char *root_name; int i; if (!codec->component.debugfs_root) { adsp_err(dsp, "No codec debugfs root\n"); goto err; } root_name = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!root_name) goto err; snprintf(root_name, PAGE_SIZE, "dsp%d", dsp->num); root = debugfs_create_dir(root_name, codec->component.debugfs_root); kfree(root_name); if (!root) goto err; if (!debugfs_create_bool("running", S_IRUGO, root, &dsp->running)) goto err; if (!debugfs_create_x32("fw_id", S_IRUGO, root, &dsp->fw_id)) goto err; if (!debugfs_create_x32("fw_version", S_IRUGO, root, &dsp->fw_id_version)) goto err; for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) { if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name, S_IRUGO, root, dsp, &wm_adsp_debugfs_fops[i].fops)) goto err; } dsp->debugfs_root = root; return; err: debugfs_remove_recursive(root); adsp_err(dsp, "Failed to create debugfs\n"); } static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) { wm_adsp_debugfs_clear(dsp); debugfs_remove_recursive(dsp->debugfs_root); } #else static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp, struct snd_soc_codec *codec) { } static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) { } static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s) { } static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s) { } static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp) { } #endif static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading @@ -298,7 +468,6 @@ const struct snd_kcontrol_new wm_adsp1_fw_controls[] = { }; EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls); #if IS_ENABLED(CONFIG_SND_SOC_ARIZONA) static const struct soc_enum wm_adsp2_rate_enum[] = { SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1, ARIZONA_DSP1_RATE_SHIFT, 0xf, Loading @@ -318,22 +487,28 @@ static const struct soc_enum wm_adsp2_rate_enum[] = { arizona_rate_text, arizona_rate_val), }; const struct snd_kcontrol_new wm_adsp2_fw_controls[] = { static const struct snd_kcontrol_new wm_adsp2_fw_controls[4][2] = { { SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], wm_adsp_fw_get, wm_adsp_fw_put), SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]), }, { SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], wm_adsp_fw_get, wm_adsp_fw_put), SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]), }, { SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], wm_adsp_fw_get, wm_adsp_fw_put), SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]), }, { SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], wm_adsp_fw_get, wm_adsp_fw_put), SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]), }, }; EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls); #endif static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, int type) Loading Loading @@ -1128,6 +1303,8 @@ static int wm_adsp_load(struct wm_adsp *dsp) adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", file, regions, pos - firmware->size); wm_adsp_debugfs_save_wmfwname(dsp, file); out_fw: regmap_async_complete(regmap); wm_adsp_buf_free(&buf_list); Loading Loading @@ -1345,11 +1522,12 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp) n_algs = be32_to_cpu(adsp2_id.n_algs); dsp->fw_id = be32_to_cpu(adsp2_id.fw.id); dsp->fw_id_version = be32_to_cpu(adsp2_id.fw.ver); adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", dsp->fw_id, (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16, (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8, be32_to_cpu(adsp2_id.fw.ver) & 0xff, (dsp->fw_id_version & 0xff0000) >> 16, (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff, n_algs); alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, Loading Loading @@ -1625,6 +1803,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", file, blocks, pos - firmware->size); wm_adsp_debugfs_save_binname(dsp, file); out_fw: regmap_async_complete(regmap); release_firmware(firmware); Loading @@ -1638,6 +1818,9 @@ int wm_adsp1_init(struct wm_adsp *dsp) { INIT_LIST_HEAD(&dsp->alg_regions); #ifdef CONFIG_DEBUG_FS mutex_init(&dsp->debugfs_lock); #endif return 0; } EXPORT_SYMBOL_GPL(wm_adsp1_init); Loading Loading @@ -1896,6 +2079,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, /* Log firmware state, it can be useful for analysis */ wm_adsp2_show_fw_status(dsp); wm_adsp_debugfs_clear(dsp); dsp->fw_id = 0; dsp->fw_id_version = 0; dsp->running = false; regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, Loading Loading @@ -1933,6 +2120,24 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, } EXPORT_SYMBOL_GPL(wm_adsp2_event); int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec) { wm_adsp2_init_debugfs(dsp, codec); return snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls[dsp->num - 1], ARRAY_SIZE(wm_adsp2_fw_controls[0])); } EXPORT_SYMBOL_GPL(wm_adsp2_codec_probe); int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec) { wm_adsp2_cleanup_debugfs(dsp); return 0; } EXPORT_SYMBOL_GPL(wm_adsp2_codec_remove); int wm_adsp2_init(struct wm_adsp *dsp) { int ret; Loading @@ -1952,6 +2157,9 @@ int wm_adsp2_init(struct wm_adsp *dsp) INIT_LIST_HEAD(&dsp->ctl_list); INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work); #ifdef CONFIG_DEBUG_FS mutex_init(&dsp->debugfs_lock); #endif return 0; } EXPORT_SYMBOL_GPL(wm_adsp2_init); Loading Loading
sound/soc/atmel/Kconfig +17 −8 Original line number Diff line number Diff line Loading @@ -9,21 +9,32 @@ config SND_ATMEL_SOC if SND_ATMEL_SOC config SND_ATMEL_SOC_PDC bool tristate default m if SND_ATMEL_SOC_SSC_PDC=m && SND_ATMEL_SOC_SSC=m default y if SND_ATMEL_SOC_SSC_PDC=y || (SND_ATMEL_SOC_SSC_PDC=m && SND_ATMEL_SOC_SSC=y) config SND_ATMEL_SOC_SSC_PDC tristate config SND_ATMEL_SOC_DMA bool tristate select SND_SOC_GENERIC_DMAENGINE_PCM default m if SND_ATMEL_SOC_SSC_DMA=m && SND_ATMEL_SOC_SSC=m default y if SND_ATMEL_SOC_SSC_DMA=y || (SND_ATMEL_SOC_SSC_DMA=m && SND_ATMEL_SOC_SSC=y) config SND_ATMEL_SOC_SSC_DMA tristate config SND_ATMEL_SOC_SSC tristate default y if SND_ATMEL_SOC_SSC_DMA=y || SND_ATMEL_SOC_SSC_PDC=y default m if SND_ATMEL_SOC_SSC_DMA=m || SND_ATMEL_SOC_SSC_PDC=m config SND_AT91_SOC_SAM9G20_WM8731 tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" depends on ARCH_AT91 || COMPILE_TEST depends on ATMEL_SSC && SND_SOC_I2C_AND_SPI select SND_ATMEL_SOC_PDC select SND_ATMEL_SOC_SSC select SND_ATMEL_SOC_SSC_PDC select SND_SOC_WM8731 help Say Y if you want to add support for SoC audio on WM8731-based Loading @@ -33,8 +44,7 @@ config SND_ATMEL_SOC_WM8904 tristate "Atmel ASoC driver for boards using WM8904 codec" depends on ARCH_AT91 || COMPILE_TEST depends on ATMEL_SSC && I2C select SND_ATMEL_SOC_SSC select SND_ATMEL_SOC_DMA select SND_ATMEL_SOC_SSC_DMA select SND_SOC_WM8904 help Say Y if you want to add support for Atmel ASoC driver for boards using Loading @@ -44,8 +54,7 @@ config SND_AT91_SOC_SAM9X5_WM8731 tristate "SoC Audio support for WM8731-based at91sam9x5 board" depends on ARCH_AT91 || COMPILE_TEST depends on ATMEL_SSC && SND_SOC_I2C_AND_SPI select SND_ATMEL_SOC_SSC select SND_ATMEL_SOC_DMA select SND_ATMEL_SOC_SSC_DMA select SND_SOC_WM8731 help Say Y if you want to add support for audio SoC on an Loading
sound/soc/atmel/Makefile +5 −3 Original line number Diff line number Diff line # AT91 Platform Support snd-soc-atmel-pcm-$(CONFIG_SND_ATMEL_SOC_PDC) := atmel-pcm-pdc.o snd-soc-atmel-pcm-$(CONFIG_SND_ATMEL_SOC_DMA) += atmel-pcm-dma.o snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o $(snd-soc-atmel-pcm-y) snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o # AT91 Machine Support Loading
sound/soc/codecs/wm5102.c +4 −2 Original line number Diff line number Diff line Loading @@ -1876,8 +1876,8 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 2); if (ret != 0) ret = wm_adsp2_codec_probe(&priv->core.adsp[0], codec); if (ret) return ret; arizona_init_spk(codec); Loading @@ -1894,6 +1894,8 @@ static int wm5102_codec_remove(struct snd_soc_codec *codec) { struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); wm_adsp2_codec_remove(&priv->core.adsp[0], codec); priv->core.arizona->dapm = NULL; return 0; Loading
sound/soc/codecs/wm5110.c +10 −4 Original line number Diff line number Diff line Loading @@ -1600,7 +1600,7 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; int i, ret; priv->core.arizona->dapm = dapm; Loading @@ -1608,9 +1608,11 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) arizona_init_gpio(codec); arizona_init_mono(codec); ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8); if (ret != 0) for (i = 0; i < WM5110_NUM_ADSP; ++i) { ret = wm_adsp2_codec_probe(&priv->core.adsp[i], codec); if (ret) return ret; } snd_soc_dapm_disable_pin(dapm, "HAPTICS"); Loading @@ -1620,6 +1622,10 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) static int wm5110_codec_remove(struct snd_soc_codec *codec) { struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); int i; for (i = 0; i < WM5110_NUM_ADSP; ++i) wm_adsp2_codec_remove(&priv->core.adsp[i], codec); priv->core.arizona->dapm = NULL; Loading
sound/soc/codecs/wm_adsp.c +227 −19 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/workqueue.h> #include <linux/debugfs.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> Loading Loading @@ -248,6 +249,175 @@ struct wm_coeff_ctl { unsigned int flags; }; #ifdef CONFIG_DEBUG_FS static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s) { char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); mutex_lock(&dsp->debugfs_lock); kfree(dsp->wmfw_file_name); dsp->wmfw_file_name = tmp; mutex_unlock(&dsp->debugfs_lock); } static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s) { char *tmp = kasprintf(GFP_KERNEL, "%s\n", s); mutex_lock(&dsp->debugfs_lock); kfree(dsp->bin_file_name); dsp->bin_file_name = tmp; mutex_unlock(&dsp->debugfs_lock); } static void wm_adsp_debugfs_clear(struct wm_adsp *dsp) { mutex_lock(&dsp->debugfs_lock); kfree(dsp->wmfw_file_name); kfree(dsp->bin_file_name); dsp->wmfw_file_name = NULL; dsp->bin_file_name = NULL; mutex_unlock(&dsp->debugfs_lock); } static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct wm_adsp *dsp = file->private_data; ssize_t ret; mutex_lock(&dsp->debugfs_lock); if (!dsp->wmfw_file_name || !dsp->running) ret = 0; else ret = simple_read_from_buffer(user_buf, count, ppos, dsp->wmfw_file_name, strlen(dsp->wmfw_file_name)); mutex_unlock(&dsp->debugfs_lock); return ret; } static ssize_t wm_adsp_debugfs_bin_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct wm_adsp *dsp = file->private_data; ssize_t ret; mutex_lock(&dsp->debugfs_lock); if (!dsp->bin_file_name || !dsp->running) ret = 0; else ret = simple_read_from_buffer(user_buf, count, ppos, dsp->bin_file_name, strlen(dsp->bin_file_name)); mutex_unlock(&dsp->debugfs_lock); return ret; } static const struct { const char *name; const struct file_operations fops; } wm_adsp_debugfs_fops[] = { { .name = "wmfw_file_name", .fops = { .open = simple_open, .read = wm_adsp_debugfs_wmfw_read, }, }, { .name = "bin_file_name", .fops = { .open = simple_open, .read = wm_adsp_debugfs_bin_read, }, }, }; static void wm_adsp2_init_debugfs(struct wm_adsp *dsp, struct snd_soc_codec *codec) { struct dentry *root = NULL; char *root_name; int i; if (!codec->component.debugfs_root) { adsp_err(dsp, "No codec debugfs root\n"); goto err; } root_name = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!root_name) goto err; snprintf(root_name, PAGE_SIZE, "dsp%d", dsp->num); root = debugfs_create_dir(root_name, codec->component.debugfs_root); kfree(root_name); if (!root) goto err; if (!debugfs_create_bool("running", S_IRUGO, root, &dsp->running)) goto err; if (!debugfs_create_x32("fw_id", S_IRUGO, root, &dsp->fw_id)) goto err; if (!debugfs_create_x32("fw_version", S_IRUGO, root, &dsp->fw_id_version)) goto err; for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) { if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name, S_IRUGO, root, dsp, &wm_adsp_debugfs_fops[i].fops)) goto err; } dsp->debugfs_root = root; return; err: debugfs_remove_recursive(root); adsp_err(dsp, "Failed to create debugfs\n"); } static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) { wm_adsp_debugfs_clear(dsp); debugfs_remove_recursive(dsp->debugfs_root); } #else static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp, struct snd_soc_codec *codec) { } static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp) { } static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s) { } static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s) { } static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp) { } #endif static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading @@ -298,7 +468,6 @@ const struct snd_kcontrol_new wm_adsp1_fw_controls[] = { }; EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls); #if IS_ENABLED(CONFIG_SND_SOC_ARIZONA) static const struct soc_enum wm_adsp2_rate_enum[] = { SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1, ARIZONA_DSP1_RATE_SHIFT, 0xf, Loading @@ -318,22 +487,28 @@ static const struct soc_enum wm_adsp2_rate_enum[] = { arizona_rate_text, arizona_rate_val), }; const struct snd_kcontrol_new wm_adsp2_fw_controls[] = { static const struct snd_kcontrol_new wm_adsp2_fw_controls[4][2] = { { SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0], wm_adsp_fw_get, wm_adsp_fw_put), SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]), }, { SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1], wm_adsp_fw_get, wm_adsp_fw_put), SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]), }, { SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2], wm_adsp_fw_get, wm_adsp_fw_put), SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]), }, { SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3], wm_adsp_fw_get, wm_adsp_fw_put), SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]), }, }; EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls); #endif static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, int type) Loading Loading @@ -1128,6 +1303,8 @@ static int wm_adsp_load(struct wm_adsp *dsp) adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", file, regions, pos - firmware->size); wm_adsp_debugfs_save_wmfwname(dsp, file); out_fw: regmap_async_complete(regmap); wm_adsp_buf_free(&buf_list); Loading Loading @@ -1345,11 +1522,12 @@ static int wm_adsp2_setup_algs(struct wm_adsp *dsp) n_algs = be32_to_cpu(adsp2_id.n_algs); dsp->fw_id = be32_to_cpu(adsp2_id.fw.id); dsp->fw_id_version = be32_to_cpu(adsp2_id.fw.ver); adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n", dsp->fw_id, (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16, (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8, be32_to_cpu(adsp2_id.fw.ver) & 0xff, (dsp->fw_id_version & 0xff0000) >> 16, (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff, n_algs); alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM, Loading Loading @@ -1625,6 +1803,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", file, blocks, pos - firmware->size); wm_adsp_debugfs_save_binname(dsp, file); out_fw: regmap_async_complete(regmap); release_firmware(firmware); Loading @@ -1638,6 +1818,9 @@ int wm_adsp1_init(struct wm_adsp *dsp) { INIT_LIST_HEAD(&dsp->alg_regions); #ifdef CONFIG_DEBUG_FS mutex_init(&dsp->debugfs_lock); #endif return 0; } EXPORT_SYMBOL_GPL(wm_adsp1_init); Loading Loading @@ -1896,6 +2079,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, /* Log firmware state, it can be useful for analysis */ wm_adsp2_show_fw_status(dsp); wm_adsp_debugfs_clear(dsp); dsp->fw_id = 0; dsp->fw_id_version = 0; dsp->running = false; regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, Loading Loading @@ -1933,6 +2120,24 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, } EXPORT_SYMBOL_GPL(wm_adsp2_event); int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec) { wm_adsp2_init_debugfs(dsp, codec); return snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls[dsp->num - 1], ARRAY_SIZE(wm_adsp2_fw_controls[0])); } EXPORT_SYMBOL_GPL(wm_adsp2_codec_probe); int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec) { wm_adsp2_cleanup_debugfs(dsp); return 0; } EXPORT_SYMBOL_GPL(wm_adsp2_codec_remove); int wm_adsp2_init(struct wm_adsp *dsp) { int ret; Loading @@ -1952,6 +2157,9 @@ int wm_adsp2_init(struct wm_adsp *dsp) INIT_LIST_HEAD(&dsp->ctl_list); INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work); #ifdef CONFIG_DEBUG_FS mutex_init(&dsp->debugfs_lock); #endif return 0; } EXPORT_SYMBOL_GPL(wm_adsp2_init); Loading