diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 90a788a0beb1edacbf6bce985f74c1094899772e..44be97769d700d635bda4e3e3c59ee3924c4f8e4 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -85,6 +85,7 @@ config SND_SOC_FSL_RPMSG_I2S config SND_SOC_FSL_DSP tristate "dsp module support" + select SND_SOC_COMPRESS help Say Y if you want to add hifi 4 support for the Freescale CPUs. which is a DSP core for audio processing. diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index dfe7ebe33092b63c1d6cb1dc8b38b1c4435cdbc8..a49f9535025680c0319f625fa67b9e32a7e95070 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -17,7 +17,7 @@ snd-soc-fsl-amix-objs := fsl_amix.o snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o snd-soc-fsl-dma-workaround-objs := fsl_dma_workaround.o snd-soc-fsl-dsp-objs := fsl_dsp.o fsl_dsp_proxy.o fsl_dsp_pool.o \ - fsl_dsp_library_load.o fsl_dsp_xaf_api.o + fsl_dsp_library_load.o fsl_dsp_xaf_api.o fsl_dsp_cpu.o snd-soc-fsl-sai-objs := fsl_sai.o snd-soc-fsl-ssi-y := fsl_ssi.o snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o diff --git a/sound/soc/fsl/fsl_dsp_cpu.c b/sound/soc/fsl/fsl_dsp_cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..2789a090e6852fcfd9c3f5792ae420898d367c5f --- /dev/null +++ b/sound/soc/fsl/fsl_dsp_cpu.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// DSP Audio platform driver +// +// Copyright 2018 NXP + +#include <linux/clk.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <sound/soc.h> +#include <sound/core.h> +#include <sound/compress_driver.h> + +#include "fsl_dsp_cpu.h" + +static int dsp_audio_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + pm_runtime_get_sync(cpu_dai->dev); + return 0; +} + + +static void dsp_audio_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + pm_runtime_put_sync(cpu_dai->dev); +} + +static const struct snd_soc_dai_ops dsp_audio_dai_ops = { + .startup = dsp_audio_startup, + .shutdown = dsp_audio_shutdown, +}; + +static struct snd_soc_dai_driver dsp_audio_dai = { + .name = "dsp-audio-cpu-dai", + .compress_new = snd_soc_new_compress, + .ops = &dsp_audio_dai_ops, + .playback = { + .stream_name = "Compress Playback", + .channels_min = 1, + }, +}; + +static const struct snd_soc_component_driver audio_dsp_component = { + .name = "audio-dsp", +}; + +static int dsp_audio_probe(struct platform_device *pdev) +{ + struct fsl_dsp_audio *dsp_audio; + int ret; + + dsp_audio = devm_kzalloc(&pdev->dev, sizeof(*dsp_audio), GFP_KERNEL); + if (dsp_audio == NULL) + return -ENOMEM; + + dev_dbg(&pdev->dev, "probing DSP device....\n"); + + /* initialise sof device */ + dev_set_drvdata(&pdev->dev, dsp_audio); + + /* No error out for old DTB cases but only mark the clock NULL */ + dsp_audio->bus_clk = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(dsp_audio->bus_clk)) { + dev_err(&pdev->dev, "failed to get bus clock: %ld\n", + PTR_ERR(dsp_audio->bus_clk)); + dsp_audio->bus_clk = NULL; + } + + dsp_audio->m_clk = devm_clk_get(&pdev->dev, "mclk"); + if (IS_ERR(dsp_audio->m_clk)) { + dev_err(&pdev->dev, "failed to get m clock: %ld\n", + PTR_ERR(dsp_audio->m_clk)); + dsp_audio->m_clk = NULL; + } + + pm_runtime_enable(&pdev->dev); + + /* now register audio DSP platform driver */ + ret = snd_soc_register_component(&pdev->dev, &audio_dsp_component, + &dsp_audio_dai, 1); + if (ret < 0) { + dev_err(&pdev->dev, + "error: failed to register DSP DAI driver %d\n", ret); + goto err; + } + + return 0; + +err: + return ret; +} + +static int dsp_audio_remove(struct platform_device *pdev) +{ + snd_soc_unregister_component(&pdev->dev); + return 0; +} + +#ifdef CONFIG_PM +static int dsp_runtime_resume(struct device *dev) +{ + struct fsl_dsp_audio *dsp_audio = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(dsp_audio->bus_clk); + if (ret) { + dev_err(dev, "failed to enable bus clock: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(dsp_audio->m_clk); + if (ret) { + dev_err(dev, "failed to enable m clock: %d\n", ret); + return ret; + } + + return ret; +} + +static int dsp_runtime_suspend(struct device *dev) +{ + struct fsl_dsp_audio *dsp_audio = dev_get_drvdata(dev); + + clk_disable_unprepare(dsp_audio->m_clk); + clk_disable_unprepare(dsp_audio->bus_clk); + + return 0; +} +#endif + +static const struct dev_pm_ops dsp_pm_ops = { + SET_RUNTIME_PM_OPS(dsp_runtime_suspend, + dsp_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static const struct of_device_id dsp_audio_ids[] = { + { .compatible = "fsl,dsp-audio"}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dsp_audio_ids); + +static struct platform_driver dsp_audio_driver = { + .driver = { + .name = "dsp-audio", + .of_match_table = dsp_audio_ids, + .pm = &dsp_pm_ops, + }, + .probe = dsp_audio_probe, + .remove = dsp_audio_remove, +}; +module_platform_driver(dsp_audio_driver); diff --git a/sound/soc/fsl/fsl_dsp_cpu.h b/sound/soc/fsl/fsl_dsp_cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..ef2813868be8ad037115c7292a160f2783493399 --- /dev/null +++ b/sound/soc/fsl/fsl_dsp_cpu.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * DSP Audio DAI header + * + * Copyright 2018 NXP + */ + +#ifndef __FSL_DSP_CPU_H +#define __FSL_DSP_CPU_H + +struct fsl_dsp_audio { + struct platform_device *pdev; + struct clk *bus_clk; + struct clk *m_clk; +}; + +#endif /*__FSL_DSP_CPU_H*/ +