From ce883ccfef043257a3d679d389444ea805006587 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 30 Apr 2015 18:16:35 +0100 Subject: ASoC: qcom: Remove redundant error check. This patch remove redundant check after request_resource as ioremap would do the check anyway. Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 6698d058de29..1e284c667aa9 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -380,10 +380,6 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev) platform_set_drvdata(pdev, drvdata); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); - if (!res) { - dev_err(&pdev->dev, "%s() error getting resource\n", __func__); - return -ENODEV; - } drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR((void const __force *)drvdata->lpaif)) { -- cgit From 3c803da266e1a960e0569a154acafb5703ae8b60 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 30 Apr 2015 18:16:44 +0100 Subject: ASoC: qcom: remove unnecessary header files This patch removes unnecessary header files in lpass cpu and platform code. Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 6 +----- sound/soc/qcom/lpass-platform.c | 6 ------ 2 files changed, 1 insertion(+), 11 deletions(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 1e284c667aa9..40842958f423 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -14,12 +14,7 @@ */ #include -#include -#include -#include -#include #include -#include #include #include #include @@ -28,6 +23,7 @@ #include #include #include + #include "lpass-lpaif-ipq806x.h" #include "lpass.h" diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 2fa6280dfb23..ffc09287af7c 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -13,17 +13,11 @@ * lpass-platform.c -- ALSA SoC platform driver for QTi LPASS */ -#include -#include #include -#include #include #include #include -#include #include -#include -#include #include #include #include -- cgit From a7310c496f376b945e7e61f64d69c9c0a93ee1ee Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 21 May 2015 11:07:08 +0200 Subject: ASoC: qcom: remove incorrect dependencies Compile-tests show a warning for the newly added SND_SOC_STORM symbol: warning: (SND_SOC_STORM) selects SND_SOC_LPASS_CPU which has unmet direct dependencies (SOUND && !M68K && !UML && SND && SND_SOC && SND_SOC_QCOM) The problem is that it can be selected for COMPILE_TEST on non-QCOM builds, but the symbols it selects have a dependency. Dropping the dependencies makes it work without warnings and no other side-effects, because these are not user-visible. Signed-off-by: Arnd Bergmann Fixes: f380dd3f3cd ("ASoC: qcom: Add ability to build QCOM drivers") Signed-off-by: Mark Brown --- sound/soc/qcom/Kconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 5f58e4f1bca9..b07f183fc47f 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -6,12 +6,10 @@ config SND_SOC_QCOM config SND_SOC_LPASS_CPU tristate - depends on SND_SOC_QCOM select REGMAP_MMIO config SND_SOC_LPASS_PLATFORM tristate - depends on SND_SOC_QCOM select REGMAP_MMIO config SND_SOC_STORM -- cgit From 9bae4880acee1cd7340d0566b55b927f92de89fb Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Sat, 16 May 2015 13:32:17 +0100 Subject: ASoC: qcom: move ipq806x specific bits out of lpass driver. This patch tries to make the lpass driver more generic by moving the ipq806x specific bits out of the cpu and platform driver, also allows the SOC specific drivers to add the correct register offsets. This patch also renames the register definition header file into more generic header file. Signed-off-by: Srinivas Kandagatla Tested-by: Kenneth Westfield Acked-by: Kenneth Westfield Signed-off-by: Mark Brown --- sound/soc/qcom/Kconfig | 9 +- sound/soc/qcom/Makefile | 2 + sound/soc/qcom/lpass-cpu.c | 157 ++++++++++++++++---------------- sound/soc/qcom/lpass-ipq806x.c | 96 +++++++++++++++++++ sound/soc/qcom/lpass-lpaif-ipq806x.h | 172 ----------------------------------- sound/soc/qcom/lpass-lpaif-reg.h | 126 +++++++++++++++++++++++++ sound/soc/qcom/lpass-platform.c | 49 ++++++---- sound/soc/qcom/lpass.h | 28 ++++++ 8 files changed, 364 insertions(+), 275 deletions(-) create mode 100644 sound/soc/qcom/lpass-ipq806x.c delete mode 100644 sound/soc/qcom/lpass-lpaif-ipq806x.h create mode 100644 sound/soc/qcom/lpass-lpaif-reg.h (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index b07f183fc47f..b30c2baa7501 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -12,11 +12,16 @@ config SND_SOC_LPASS_PLATFORM tristate select REGMAP_MMIO +config SND_SOC_LPASS_IPQ806X + tristate + depends on SND_SOC_QCOM + select SND_SOC_LPASS_CPU + select SND_SOC_LPASS_PLATFORM + config SND_SOC_STORM tristate "ASoC I2S support for Storm boards" depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST - select SND_SOC_LPASS_CPU - select SND_SOC_LPASS_PLATFORM + select SND_SOC_LPASS_IPQ806X select SND_SOC_MAX98357A help Say Y or M if you want add support for SoC audio on the diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index c5ce96c761c4..f8aab91c9117 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -1,9 +1,11 @@ # Platform snd-soc-lpass-cpu-objs := lpass-cpu.o snd-soc-lpass-platform-objs := lpass-platform.o +snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o +obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o # Machine snd-soc-storm-objs := storm.o diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 40842958f423..5544bfc57357 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -17,14 +17,14 @@ #include #include #include +#include #include #include #include #include #include #include - -#include "lpass-lpaif-ipq806x.h" +#include "lpass-lpaif-reg.h" #include "lpass.h" static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, @@ -138,7 +138,9 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, } ret = regmap_write(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), regval); + LPAIF_I2SCTL_REG(drvdata->variant, + LPAIF_I2S_PORT_MI2S), + regval); if (ret) { dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", __func__, ret); @@ -162,7 +164,8 @@ static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream, int ret; ret = regmap_write(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 0); + LPAIF_I2SCTL_REG(drvdata->variant, + LPAIF_I2S_PORT_MI2S), 0); if (ret) dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", __func__, ret); @@ -177,7 +180,7 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream, int ret; ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), + LPAIF_I2SCTL_REG(drvdata->variant, LPAIF_I2S_PORT_MI2S), LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE); if (ret) dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", @@ -197,7 +200,8 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), + LPAIF_I2SCTL_REG(drvdata->variant, + LPAIF_I2S_PORT_MI2S), LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE); if (ret) @@ -208,7 +212,8 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), + LPAIF_I2SCTL_REG(drvdata->variant, + LPAIF_I2S_PORT_MI2S), LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_DISABLE); if (ret) @@ -220,7 +225,7 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, return ret; } -static struct snd_soc_dai_ops lpass_cpu_dai_ops = { +struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = { .set_sysclk = lpass_cpu_daiops_set_sysclk, .startup = lpass_cpu_daiops_startup, .shutdown = lpass_cpu_daiops_shutdown, @@ -229,41 +234,24 @@ static struct snd_soc_dai_ops lpass_cpu_dai_ops = { .prepare = lpass_cpu_daiops_prepare, .trigger = lpass_cpu_daiops_trigger, }; +EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops); -static int lpass_cpu_dai_probe(struct snd_soc_dai *dai) +int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai) { struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); int ret; /* ensure audio hardware is disabled */ ret = regmap_write(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 0); + LPAIF_I2SCTL_REG(drvdata->variant, + LPAIF_I2S_PORT_MI2S), 0); if (ret) dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", __func__, ret); return ret; } - -static struct snd_soc_dai_driver lpass_cpu_dai_driver = { - .playback = { - .stream_name = "lpass-cpu-playback", - .formats = SNDRV_PCM_FMTBIT_S16 | - SNDRV_PCM_FMTBIT_S24 | - SNDRV_PCM_FMTBIT_S32, - .rates = SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_96000, - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - }, - .probe = &lpass_cpu_dai_probe, - .ops = &lpass_cpu_dai_ops, -}; +EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_probe); static const struct snd_soc_component_driver lpass_cpu_comp_driver = { .name = "lpass-cpu", @@ -271,27 +259,29 @@ static const struct snd_soc_component_driver lpass_cpu_comp_driver = { static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg) { + struct lpass_data *drvdata = dev_get_drvdata(dev); + struct lpass_variant *v = drvdata->variant; int i; - for (i = 0; i < LPAIF_I2S_PORT_NUM; ++i) - if (reg == LPAIF_I2SCTL_REG(i)) + for (i = 0; i < v->i2s_ports; ++i) + if (reg == LPAIF_I2SCTL_REG(v, i)) return true; - for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) { - if (reg == LPAIF_IRQEN_REG(i)) + for (i = 0; i < v->irq_ports; ++i) { + if (reg == LPAIF_IRQEN_REG(v, i)) return true; - if (reg == LPAIF_IRQCLEAR_REG(i)) + if (reg == LPAIF_IRQCLEAR_REG(v, i)) return true; } - for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) { - if (reg == LPAIF_RDMACTL_REG(i)) + for (i = 0; i < v->rdma_channels; ++i) { + if (reg == LPAIF_RDMACTL_REG(v, i)) return true; - if (reg == LPAIF_RDMABASE_REG(i)) + if (reg == LPAIF_RDMABASE_REG(v, i)) return true; - if (reg == LPAIF_RDMABUFF_REG(i)) + if (reg == LPAIF_RDMABUFF_REG(v, i)) return true; - if (reg == LPAIF_RDMAPER_REG(i)) + if (reg == LPAIF_RDMAPER_REG(v, i)) return true; } @@ -300,29 +290,31 @@ static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg) static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg) { + struct lpass_data *drvdata = dev_get_drvdata(dev); + struct lpass_variant *v = drvdata->variant; int i; - for (i = 0; i < LPAIF_I2S_PORT_NUM; ++i) - if (reg == LPAIF_I2SCTL_REG(i)) + for (i = 0; i < v->i2s_ports; ++i) + if (reg == LPAIF_I2SCTL_REG(v, i)) return true; - for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) { - if (reg == LPAIF_IRQEN_REG(i)) + for (i = 0; i < v->irq_ports; ++i) { + if (reg == LPAIF_IRQEN_REG(v, i)) return true; - if (reg == LPAIF_IRQSTAT_REG(i)) + if (reg == LPAIF_IRQSTAT_REG(v, i)) return true; } - for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) { - if (reg == LPAIF_RDMACTL_REG(i)) + for (i = 0; i < v->rdma_channels; ++i) { + if (reg == LPAIF_RDMACTL_REG(v, i)) return true; - if (reg == LPAIF_RDMABASE_REG(i)) + if (reg == LPAIF_RDMABASE_REG(v, i)) return true; - if (reg == LPAIF_RDMABUFF_REG(i)) + if (reg == LPAIF_RDMABUFF_REG(v, i)) return true; - if (reg == LPAIF_RDMACURR_REG(i)) + if (reg == LPAIF_RDMACURR_REG(v, i)) return true; - if (reg == LPAIF_RDMAPER_REG(i)) + if (reg == LPAIF_RDMAPER_REG(v, i)) return true; } @@ -331,35 +323,39 @@ static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg) static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) { + struct lpass_data *drvdata = dev_get_drvdata(dev); + struct lpass_variant *v = drvdata->variant; int i; - for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) - if (reg == LPAIF_IRQSTAT_REG(i)) + for (i = 0; i < v->irq_ports; ++i) + if (reg == LPAIF_IRQSTAT_REG(v, i)) return true; - for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) - if (reg == LPAIF_RDMACURR_REG(i)) + for (i = 0; i < v->rdma_channels; ++i) + if (reg == LPAIF_RDMACURR_REG(v, i)) return true; return false; } -static const struct regmap_config lpass_cpu_regmap_config = { +static struct regmap_config lpass_cpu_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = LPAIF_RDMAPER_REG(LPAIF_RDMA_CHAN_MAX), .writeable_reg = lpass_cpu_regmap_writeable, .readable_reg = lpass_cpu_regmap_readable, .volatile_reg = lpass_cpu_regmap_volatile, .cache_type = REGCACHE_FLAT, }; -static int lpass_cpu_platform_probe(struct platform_device *pdev) +int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) { struct lpass_data *drvdata; struct device_node *dsp_of_node; struct resource *res; + struct lpass_variant *variant; + struct device *dev = &pdev->dev; + const struct of_device_id *match; int ret; dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); @@ -375,6 +371,13 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, drvdata); + match = of_match_device(dev->driver->of_match_table, dev); + if (!match || !match->data) + return -EINVAL; + + drvdata->variant = (struct lpass_variant *)match->data; + variant = drvdata->variant; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); @@ -385,6 +388,9 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev) return PTR_ERR((void const __force *)drvdata->lpaif); } + lpass_cpu_regmap_config.max_register = LPAIF_RDMAPER_REG(variant, + variant->rdma_channels); + drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif, &lpass_cpu_regmap_config); if (IS_ERR(drvdata->lpaif_map)) { @@ -393,6 +399,9 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev) return PTR_ERR(drvdata->lpaif_map); } + if (variant->init) + variant->init(pdev); + drvdata->mi2s_osr_clk = devm_clk_get(&pdev->dev, "mi2s-osr-clk"); if (IS_ERR(drvdata->mi2s_osr_clk)) { dev_err(&pdev->dev, "%s() error getting mi2s-osr-clk: %ld\n", @@ -431,7 +440,9 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev) } ret = devm_snd_soc_register_component(&pdev->dev, - &lpass_cpu_comp_driver, &lpass_cpu_dai_driver, 1); + &lpass_cpu_comp_driver, + variant->dai_driver, + variant->num_dai); if (ret) { dev_err(&pdev->dev, "%s() error registering cpu driver: %d\n", __func__, ret); @@ -451,33 +462,17 @@ err_clk: clk_disable_unprepare(drvdata->ahbix_clk); return ret; } +EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_probe); -static int lpass_cpu_platform_remove(struct platform_device *pdev) +int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev) { struct lpass_data *drvdata = platform_get_drvdata(pdev); + if (drvdata->variant->exit) + drvdata->variant->exit(pdev); + clk_disable_unprepare(drvdata->ahbix_clk); return 0; } - -#ifdef CONFIG_OF -static const struct of_device_id lpass_cpu_device_id[] = { - { .compatible = "qcom,lpass-cpu" }, - {} -}; -MODULE_DEVICE_TABLE(of, lpass_cpu_device_id); -#endif - -static struct platform_driver lpass_cpu_platform_driver = { - .driver = { - .name = "lpass-cpu", - .of_match_table = of_match_ptr(lpass_cpu_device_id), - }, - .probe = lpass_cpu_platform_probe, - .remove = lpass_cpu_platform_remove, -}; -module_platform_driver(lpass_cpu_platform_driver); - -MODULE_DESCRIPTION("QTi LPASS CPU Driver"); -MODULE_LICENSE("GPL v2"); +EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove); diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c new file mode 100644 index 000000000000..4a0e3fbb384b --- /dev/null +++ b/sound/soc/qcom/lpass-ipq806x.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * lpass-ipq806x.c -- ALSA SoC CPU DAI driver for QTi LPASS + * Splited out the IPQ8064 soc specific from lpass-cpu.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lpass-lpaif-reg.h" +#include "lpass.h" + +enum lpaif_i2s_ports { + IPQ806X_LPAIF_I2S_PORT_CODEC_SPK, + IPQ806X_LPAIF_I2S_PORT_CODEC_MIC, + IPQ806X_LPAIF_I2S_PORT_SEC_SPK, + IPQ806X_LPAIF_I2S_PORT_SEC_MIC, + IPQ806X_LPAIF_I2S_PORT_MI2S, +}; + +enum lpaif_dma_channels { + IPQ806X_LPAIF_RDMA_CHAN_MI2S, + IPQ806X_LPAIF_RDMA_CHAN_PCM0, + IPQ806X_LPAIF_RDMA_CHAN_PCM1, +}; + +static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = { + .playback = { + .stream_name = "lpass-cpu-playback", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, +}; + +struct lpass_variant ipq806x_data = { + .i2sctrl_reg_base = 0x0010, + .i2sctrl_reg_stride = 0x04, + .i2s_ports = 5, + .irq_reg_base = 0x3000, + .irq_reg_stride = 0x1000, + .irq_ports = 3, + .rdma_reg_base = 0x6000, + .rdma_reg_stride = 0x1000, + .rdma_channels = 4, + .dai_driver = &ipq806x_lpass_cpu_dai_driver, + .num_dai = 1, +}; + +static const struct of_device_id ipq806x_lpass_cpu_device_id[] = { + { .compatible = "qcom,lpass-cpu", .data = &ipq806x_data }, + {} +}; +MODULE_DEVICE_TABLE(of, ipq806x_lpass_cpu_device_id); + +static struct platform_driver ipq806x_lpass_cpu_platform_driver = { + .driver = { + .name = "lpass-cpu", + .of_match_table = of_match_ptr(ipq806x_lpass_cpu_device_id), + }, + .probe = asoc_qcom_lpass_cpu_platform_probe, + .remove = asoc_qcom_lpass_cpu_platform_remove, +}; +module_platform_driver(ipq806x_lpass_cpu_platform_driver); + +MODULE_DESCRIPTION("QTi LPASS CPU Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/lpass-lpaif-ipq806x.h b/sound/soc/qcom/lpass-lpaif-ipq806x.h deleted file mode 100644 index dc423b888842..000000000000 --- a/sound/soc/qcom/lpass-lpaif-ipq806x.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * lpass-lpaif-ipq806x.h -- Definitions for the QTi LPAIF in the ipq806x LPASS - */ - -#ifndef __LPASS_LPAIF_H__ -#define __LPASS_LPAIF_H__ - -#define LPAIF_BANK_OFFSET 0x1000 - -/* LPAIF I2S */ - -#define LPAIF_I2SCTL_REG_BASE 0x0010 -#define LPAIF_I2SCTL_REG_STRIDE 0x4 -#define LPAIF_I2SCTL_REG_ADDR(addr, port) \ - (LPAIF_I2SCTL_REG_BASE + (addr) + (LPAIF_I2SCTL_REG_STRIDE * (port))) - -enum lpaif_i2s_ports { - LPAIF_I2S_PORT_MIN = 0, - - LPAIF_I2S_PORT_CODEC_SPK = 0, - LPAIF_I2S_PORT_CODEC_MIC = 1, - LPAIF_I2S_PORT_SEC_SPK = 2, - LPAIF_I2S_PORT_SEC_MIC = 3, - LPAIF_I2S_PORT_MI2S = 4, - - LPAIF_I2S_PORT_MAX = 4, - LPAIF_I2S_PORT_NUM = 5, -}; - -#define LPAIF_I2SCTL_REG(port) LPAIF_I2SCTL_REG_ADDR(0x0, (port)) - -#define LPAIF_I2SCTL_LOOPBACK_MASK 0x8000 -#define LPAIF_I2SCTL_LOOPBACK_SHIFT 15 -#define LPAIF_I2SCTL_LOOPBACK_DISABLE (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT) -#define LPAIF_I2SCTL_LOOPBACK_ENABLE (1 << LPAIF_I2SCTL_LOOPBACK_SHIFT) - -#define LPAIF_I2SCTL_SPKEN_MASK 0x4000 -#define LPAIF_I2SCTL_SPKEN_SHIFT 14 -#define LPAIF_I2SCTL_SPKEN_DISABLE (0 << LPAIF_I2SCTL_SPKEN_SHIFT) -#define LPAIF_I2SCTL_SPKEN_ENABLE (1 << LPAIF_I2SCTL_SPKEN_SHIFT) - -#define LPAIF_I2SCTL_SPKMODE_MASK 0x3C00 -#define LPAIF_I2SCTL_SPKMODE_SHIFT 10 -#define LPAIF_I2SCTL_SPKMODE_NONE (0 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_SD0 (1 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_SD1 (2 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_SD2 (3 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_SD3 (4 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_QUAD01 (5 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_QUAD23 (6 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_6CH (7 << LPAIF_I2SCTL_SPKMODE_SHIFT) -#define LPAIF_I2SCTL_SPKMODE_8CH (8 << LPAIF_I2SCTL_SPKMODE_SHIFT) - -#define LPAIF_I2SCTL_SPKMONO_MASK 0x0200 -#define LPAIF_I2SCTL_SPKMONO_SHIFT 9 -#define LPAIF_I2SCTL_SPKMONO_STEREO (0 << LPAIF_I2SCTL_SPKMONO_SHIFT) -#define LPAIF_I2SCTL_SPKMONO_MONO (1 << LPAIF_I2SCTL_SPKMONO_SHIFT) - -#define LPAIF_I2SCTL_WSSRC_MASK 0x0004 -#define LPAIF_I2SCTL_WSSRC_SHIFT 2 -#define LPAIF_I2SCTL_WSSRC_INTERNAL (0 << LPAIF_I2SCTL_WSSRC_SHIFT) -#define LPAIF_I2SCTL_WSSRC_EXTERNAL (1 << LPAIF_I2SCTL_WSSRC_SHIFT) - -#define LPAIF_I2SCTL_BITWIDTH_MASK 0x0003 -#define LPAIF_I2SCTL_BITWIDTH_SHIFT 0 -#define LPAIF_I2SCTL_BITWIDTH_16 (0 << LPAIF_I2SCTL_BITWIDTH_SHIFT) -#define LPAIF_I2SCTL_BITWIDTH_24 (1 << LPAIF_I2SCTL_BITWIDTH_SHIFT) -#define LPAIF_I2SCTL_BITWIDTH_32 (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT) - -/* LPAIF IRQ */ - -#define LPAIF_IRQ_REG_BASE 0x3000 -#define LPAIF_IRQ_REG_STRIDE 0x1000 -#define LPAIF_IRQ_REG_ADDR(addr, port) \ - (LPAIF_IRQ_REG_BASE + (addr) + (LPAIF_IRQ_REG_STRIDE * (port))) - -enum lpaif_irq_ports { - LPAIF_IRQ_PORT_MIN = 0, - - LPAIF_IRQ_PORT_HOST = 0, - LPAIF_IRQ_PORT_ADSP = 1, - - LPAIF_IRQ_PORT_MAX = 2, - LPAIF_IRQ_PORT_NUM = 3, -}; - -#define LPAIF_IRQEN_REG(port) LPAIF_IRQ_REG_ADDR(0x0, (port)) -#define LPAIF_IRQSTAT_REG(port) LPAIF_IRQ_REG_ADDR(0x4, (port)) -#define LPAIF_IRQCLEAR_REG(port) LPAIF_IRQ_REG_ADDR(0xC, (port)) - -#define LPAIF_IRQ_BITSTRIDE 3 -#define LPAIF_IRQ_PER(chan) (1 << (LPAIF_IRQ_BITSTRIDE * (chan))) -#define LPAIF_IRQ_XRUN(chan) (2 << (LPAIF_IRQ_BITSTRIDE * (chan))) -#define LPAIF_IRQ_ERR(chan) (4 << (LPAIF_IRQ_BITSTRIDE * (chan))) -#define LPAIF_IRQ_ALL(chan) (7 << (LPAIF_IRQ_BITSTRIDE * (chan))) - -/* LPAIF DMA */ - -#define LPAIF_RDMA_REG_BASE 0x6000 -#define LPAIF_RDMA_REG_STRIDE 0x1000 -#define LPAIF_RDMA_REG_ADDR(addr, chan) \ - (LPAIF_RDMA_REG_BASE + (addr) + (LPAIF_RDMA_REG_STRIDE * (chan))) - -enum lpaif_dma_channels { - LPAIF_RDMA_CHAN_MIN = 0, - - LPAIF_RDMA_CHAN_MI2S = 0, - LPAIF_RDMA_CHAN_PCM0 = 1, - LPAIF_RDMA_CHAN_PCM1 = 2, - - LPAIF_RDMA_CHAN_MAX = 4, - LPAIF_RDMA_CHAN_NUM = 5, -}; - -#define LPAIF_RDMACTL_REG(chan) LPAIF_RDMA_REG_ADDR(0x00, (chan)) -#define LPAIF_RDMABASE_REG(chan) LPAIF_RDMA_REG_ADDR(0x04, (chan)) -#define LPAIF_RDMABUFF_REG(chan) LPAIF_RDMA_REG_ADDR(0x08, (chan)) -#define LPAIF_RDMACURR_REG(chan) LPAIF_RDMA_REG_ADDR(0x0C, (chan)) -#define LPAIF_RDMAPER_REG(chan) LPAIF_RDMA_REG_ADDR(0x10, (chan)) - -#define LPAIF_RDMACTL_BURSTEN_MASK 0x800 -#define LPAIF_RDMACTL_BURSTEN_SHIFT 11 -#define LPAIF_RDMACTL_BURSTEN_SINGLE (0 << LPAIF_RDMACTL_BURSTEN_SHIFT) -#define LPAIF_RDMACTL_BURSTEN_INCR4 (1 << LPAIF_RDMACTL_BURSTEN_SHIFT) - -#define LPAIF_RDMACTL_WPSCNT_MASK 0x700 -#define LPAIF_RDMACTL_WPSCNT_SHIFT 8 -#define LPAIF_RDMACTL_WPSCNT_ONE (0 << LPAIF_RDMACTL_WPSCNT_SHIFT) -#define LPAIF_RDMACTL_WPSCNT_TWO (1 << LPAIF_RDMACTL_WPSCNT_SHIFT) -#define LPAIF_RDMACTL_WPSCNT_THREE (2 << LPAIF_RDMACTL_WPSCNT_SHIFT) -#define LPAIF_RDMACTL_WPSCNT_FOUR (3 << LPAIF_RDMACTL_WPSCNT_SHIFT) -#define LPAIF_RDMACTL_WPSCNT_SIX (5 << LPAIF_RDMACTL_WPSCNT_SHIFT) -#define LPAIF_RDMACTL_WPSCNT_EIGHT (7 << LPAIF_RDMACTL_WPSCNT_SHIFT) - -#define LPAIF_RDMACTL_AUDINTF_MASK 0x0F0 -#define LPAIF_RDMACTL_AUDINTF_SHIFT 4 -#define LPAIF_RDMACTL_AUDINTF_NONE (0 << LPAIF_RDMACTL_AUDINTF_SHIFT) -#define LPAIF_RDMACTL_AUDINTF_CODEC (1 << LPAIF_RDMACTL_AUDINTF_SHIFT) -#define LPAIF_RDMACTL_AUDINTF_PCM (2 << LPAIF_RDMACTL_AUDINTF_SHIFT) -#define LPAIF_RDMACTL_AUDINTF_SEC_I2S (3 << LPAIF_RDMACTL_AUDINTF_SHIFT) -#define LPAIF_RDMACTL_AUDINTF_MI2S (4 << LPAIF_RDMACTL_AUDINTF_SHIFT) -#define LPAIF_RDMACTL_AUDINTF_HDMI (5 << LPAIF_RDMACTL_AUDINTF_SHIFT) -#define LPAIF_RDMACTL_AUDINTF_SEC_PCM (7 << LPAIF_RDMACTL_AUDINTF_SHIFT) - -#define LPAIF_RDMACTL_FIFOWM_MASK 0x00E -#define LPAIF_RDMACTL_FIFOWM_SHIFT 1 -#define LPAIF_RDMACTL_FIFOWM_1 (0 << LPAIF_RDMACTL_FIFOWM_SHIFT) -#define LPAIF_RDMACTL_FIFOWM_2 (1 << LPAIF_RDMACTL_FIFOWM_SHIFT) -#define LPAIF_RDMACTL_FIFOWM_3 (2 << LPAIF_RDMACTL_FIFOWM_SHIFT) -#define LPAIF_RDMACTL_FIFOWM_4 (3 << LPAIF_RDMACTL_FIFOWM_SHIFT) -#define LPAIF_RDMACTL_FIFOWM_5 (4 << LPAIF_RDMACTL_FIFOWM_SHIFT) -#define LPAIF_RDMACTL_FIFOWM_6 (5 << LPAIF_RDMACTL_FIFOWM_SHIFT) -#define LPAIF_RDMACTL_FIFOWM_7 (6 << LPAIF_RDMACTL_FIFOWM_SHIFT) -#define LPAIF_RDMACTL_FIFOWM_8 (7 << LPAIF_RDMACTL_FIFOWM_SHIFT) - -#define LPAIF_RDMACTL_ENABLE_MASK 0x1 -#define LPAIF_RDMACTL_ENABLE_SHIFT 0 -#define LPAIF_RDMACTL_ENABLE_OFF (0 << LPAIF_RDMACTL_ENABLE_SHIFT) -#define LPAIF_RDMACTL_ENABLE_ON (1 << LPAIF_RDMACTL_ENABLE_SHIFT) - -#endif /* __LPASS_LPAIF_H__ */ diff --git a/sound/soc/qcom/lpass-lpaif-reg.h b/sound/soc/qcom/lpass-lpaif-reg.h new file mode 100644 index 000000000000..95e22f131052 --- /dev/null +++ b/sound/soc/qcom/lpass-lpaif-reg.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __LPASS_LPAIF_REG_H__ +#define __LPASS_LPAIF_REG_H__ + +/* LPAIF I2S */ + +#define LPAIF_I2SCTL_REG_ADDR(v, addr, port) \ + (v->i2sctrl_reg_base + (addr) + v->i2sctrl_reg_stride * (port)) + +#define LPAIF_I2SCTL_REG(v, port) LPAIF_I2SCTL_REG_ADDR(v, 0x0, (port)) +#define LPAIF_I2SCTL_LOOPBACK_MASK 0x8000 +#define LPAIF_I2SCTL_LOOPBACK_SHIFT 15 +#define LPAIF_I2SCTL_LOOPBACK_DISABLE (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT) +#define LPAIF_I2SCTL_LOOPBACK_ENABLE (1 << LPAIF_I2SCTL_LOOPBACK_SHIFT) + +#define LPAIF_I2SCTL_SPKEN_MASK 0x4000 +#define LPAIF_I2SCTL_SPKEN_SHIFT 14 +#define LPAIF_I2SCTL_SPKEN_DISABLE (0 << LPAIF_I2SCTL_SPKEN_SHIFT) +#define LPAIF_I2SCTL_SPKEN_ENABLE (1 << LPAIF_I2SCTL_SPKEN_SHIFT) + +#define LPAIF_I2SCTL_SPKMODE_MASK 0x3C00 +#define LPAIF_I2SCTL_SPKMODE_SHIFT 10 +#define LPAIF_I2SCTL_SPKMODE_NONE (0 << LPAIF_I2SCTL_SPKMODE_SHIFT) +#define LPAIF_I2SCTL_SPKMODE_SD0 (1 << LPAIF_I2SCTL_SPKMODE_SHIFT) +#define LPAIF_I2SCTL_SPKMODE_SD1 (2 << LPAIF_I2SCTL_SPKMODE_SHIFT) +#define LPAIF_I2SCTL_SPKMODE_SD2 (3 << LPAIF_I2SCTL_SPKMODE_SHIFT) +#define LPAIF_I2SCTL_SPKMODE_SD3 (4 << LPAIF_I2SCTL_SPKMODE_SHIFT) +#define LPAIF_I2SCTL_SPKMODE_QUAD01 (5 << LPAIF_I2SCTL_SPKMODE_SHIFT) +#define LPAIF_I2SCTL_SPKMODE_QUAD23 (6 << LPAIF_I2SCTL_SPKMODE_SHIFT) +#define LPAIF_I2SCTL_SPKMODE_6CH (7 << LPAIF_I2SCTL_SPKMODE_SHIFT) +#define LPAIF_I2SCTL_SPKMODE_8CH (8 << LPAIF_I2SCTL_SPKMODE_SHIFT) + +#define LPAIF_I2SCTL_SPKMONO_MASK 0x0200 +#define LPAIF_I2SCTL_SPKMONO_SHIFT 9 +#define LPAIF_I2SCTL_SPKMONO_STEREO (0 << LPAIF_I2SCTL_SPKMONO_SHIFT) +#define LPAIF_I2SCTL_SPKMONO_MONO (1 << LPAIF_I2SCTL_SPKMONO_SHIFT) + +#define LPAIF_I2SCTL_WSSRC_MASK 0x0004 +#define LPAIF_I2SCTL_WSSRC_SHIFT 2 +#define LPAIF_I2SCTL_WSSRC_INTERNAL (0 << LPAIF_I2SCTL_WSSRC_SHIFT) +#define LPAIF_I2SCTL_WSSRC_EXTERNAL (1 << LPAIF_I2SCTL_WSSRC_SHIFT) + +#define LPAIF_I2SCTL_BITWIDTH_MASK 0x0003 +#define LPAIF_I2SCTL_BITWIDTH_SHIFT 0 +#define LPAIF_I2SCTL_BITWIDTH_16 (0 << LPAIF_I2SCTL_BITWIDTH_SHIFT) +#define LPAIF_I2SCTL_BITWIDTH_24 (1 << LPAIF_I2SCTL_BITWIDTH_SHIFT) +#define LPAIF_I2SCTL_BITWIDTH_32 (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT) + +/* LPAIF IRQ */ +#define LPAIF_IRQ_REG_ADDR(v, addr, port) \ + (v->irq_reg_base + (addr) + v->irq_reg_stride * (port)) + +#define LPAIF_IRQ_PORT_HOST 0 + +#define LPAIF_IRQEN_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0x0, (port)) +#define LPAIF_IRQSTAT_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0x4, (port)) +#define LPAIF_IRQCLEAR_REG(v, port) LPAIF_IRQ_REG_ADDR(v, 0xC, (port)) + +#define LPAIF_IRQ_BITSTRIDE 3 + +#define LPAIF_IRQ_PER(chan) (1 << (LPAIF_IRQ_BITSTRIDE * (chan))) +#define LPAIF_IRQ_XRUN(chan) (2 << (LPAIF_IRQ_BITSTRIDE * (chan))) +#define LPAIF_IRQ_ERR(chan) (4 << (LPAIF_IRQ_BITSTRIDE * (chan))) + +#define LPAIF_IRQ_ALL(chan) (7 << (LPAIF_IRQ_BITSTRIDE * (chan))) + +/* LPAIF DMA */ + +#define LPAIF_RDMA_REG_ADDR(v, addr, chan) \ + (v->rdma_reg_base + (addr) + v->rdma_reg_stride * (chan)) + +#define LPAIF_RDMACTL_AUDINTF(id) (id << LPAIF_RDMACTL_AUDINTF_SHIFT) + +#define LPAIF_RDMACTL_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x00, (chan)) +#define LPAIF_RDMABASE_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x04, (chan)) +#define LPAIF_RDMABUFF_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x08, (chan)) +#define LPAIF_RDMACURR_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x0C, (chan)) +#define LPAIF_RDMAPER_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x10, (chan)) +#define LPAIF_RDMAPERCNT_REG(v, chan) LPAIF_RDMA_REG_ADDR(v, 0x14, (chan)) + +#define LPAIF_RDMACTL_BURSTEN_MASK 0x800 +#define LPAIF_RDMACTL_BURSTEN_SHIFT 11 +#define LPAIF_RDMACTL_BURSTEN_SINGLE (0 << LPAIF_RDMACTL_BURSTEN_SHIFT) +#define LPAIF_RDMACTL_BURSTEN_INCR4 (1 << LPAIF_RDMACTL_BURSTEN_SHIFT) + +#define LPAIF_RDMACTL_WPSCNT_MASK 0x700 +#define LPAIF_RDMACTL_WPSCNT_SHIFT 8 +#define LPAIF_RDMACTL_WPSCNT_ONE (0 << LPAIF_RDMACTL_WPSCNT_SHIFT) +#define LPAIF_RDMACTL_WPSCNT_TWO (1 << LPAIF_RDMACTL_WPSCNT_SHIFT) +#define LPAIF_RDMACTL_WPSCNT_THREE (2 << LPAIF_RDMACTL_WPSCNT_SHIFT) +#define LPAIF_RDMACTL_WPSCNT_FOUR (3 << LPAIF_RDMACTL_WPSCNT_SHIFT) +#define LPAIF_RDMACTL_WPSCNT_SIX (5 << LPAIF_RDMACTL_WPSCNT_SHIFT) +#define LPAIF_RDMACTL_WPSCNT_EIGHT (7 << LPAIF_RDMACTL_WPSCNT_SHIFT) + +#define LPAIF_RDMACTL_AUDINTF_MASK 0x0F0 +#define LPAIF_RDMACTL_AUDINTF_SHIFT 4 + +#define LPAIF_RDMACTL_FIFOWM_MASK 0x00E +#define LPAIF_RDMACTL_FIFOWM_SHIFT 1 +#define LPAIF_RDMACTL_FIFOWM_1 (0 << LPAIF_RDMACTL_FIFOWM_SHIFT) +#define LPAIF_RDMACTL_FIFOWM_2 (1 << LPAIF_RDMACTL_FIFOWM_SHIFT) +#define LPAIF_RDMACTL_FIFOWM_3 (2 << LPAIF_RDMACTL_FIFOWM_SHIFT) +#define LPAIF_RDMACTL_FIFOWM_4 (3 << LPAIF_RDMACTL_FIFOWM_SHIFT) +#define LPAIF_RDMACTL_FIFOWM_5 (4 << LPAIF_RDMACTL_FIFOWM_SHIFT) +#define LPAIF_RDMACTL_FIFOWM_6 (5 << LPAIF_RDMACTL_FIFOWM_SHIFT) +#define LPAIF_RDMACTL_FIFOWM_7 (6 << LPAIF_RDMACTL_FIFOWM_SHIFT) +#define LPAIF_RDMACTL_FIFOWM_8 (7 << LPAIF_RDMACTL_FIFOWM_SHIFT) + +#define LPAIF_RDMACTL_ENABLE_MASK 0x1 +#define LPAIF_RDMACTL_ENABLE_SHIFT 0 +#define LPAIF_RDMACTL_ENABLE_OFF (0 << LPAIF_RDMACTL_ENABLE_SHIFT) +#define LPAIF_RDMACTL_ENABLE_ON (1 << LPAIF_RDMACTL_ENABLE_SHIFT) + +#endif /* __LPASS_LPAIF_REG_H__ */ diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index ffc09287af7c..a38e7ecf244f 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -21,7 +21,7 @@ #include #include #include -#include "lpass-lpaif-ipq806x.h" +#include "lpass-lpaif-reg.h" #include "lpass.h" #define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024) @@ -80,6 +80,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; snd_pcm_format_t format = params_format(params); unsigned int channels = params_channels(params); unsigned int regval; @@ -150,7 +151,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, } ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), regval); + LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), regval); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", __func__, ret); @@ -165,10 +166,11 @@ static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; int ret; ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 0); + LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 0); if (ret) dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", __func__, ret); @@ -182,10 +184,11 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; int ret; ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMABASE_REG(LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMABASE_REG(v, LPAIF_RDMA_CHAN_MI2S), runtime->dma_addr); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n", @@ -194,7 +197,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) } ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMABUFF_REG(LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMABUFF_REG(v, LPAIF_RDMA_CHAN_MI2S), (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n", @@ -203,7 +206,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) } ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMAPER_REG(LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMAPER_REG(v, LPAIF_RDMA_CHAN_MI2S), (snd_pcm_lib_period_bytes(substream) >> 2) - 1); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n", @@ -212,7 +215,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) } ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", @@ -229,6 +232,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; int ret; switch (cmd) { @@ -237,7 +241,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* clear status before enabling interrupts */ ret = regmap_write(drvdata->lpaif_map, - LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), + LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S)); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", @@ -246,7 +250,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, } ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST), + LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S)); if (ret) { @@ -256,7 +260,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, } ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON); if (ret) { @@ -269,7 +273,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_OFF); if (ret) { @@ -279,7 +283,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, } ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST), + LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), 0); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", @@ -298,11 +302,13 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; unsigned int base_addr, curr_addr; int ret; ret = regmap_read(drvdata->lpaif_map, - LPAIF_RDMABASE_REG(LPAIF_RDMA_CHAN_MI2S), &base_addr); + LPAIF_RDMABASE_REG(v, LPAIF_RDMA_CHAN_MI2S), + &base_addr); if (ret) { dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n", __func__, ret); @@ -310,7 +316,8 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( } ret = regmap_read(drvdata->lpaif_map, - LPAIF_RDMACURR_REG(LPAIF_RDMA_CHAN_MI2S), &curr_addr); + LPAIF_RDMACURR_REG(v, LPAIF_RDMA_CHAN_MI2S), + &curr_addr); if (ret) { dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n", __func__, ret); @@ -347,12 +354,13 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; unsigned int interrupts; irqreturn_t ret = IRQ_NONE; int rv; rv = regmap_read(drvdata->lpaif_map, - LPAIF_IRQSTAT_REG(LPAIF_IRQ_PORT_HOST), &interrupts); + LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &interrupts); if (rv) { dev_err(soc_runtime->dev, "%s() error reading from irqstat reg: %d\n", __func__, rv); @@ -362,7 +370,7 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) if (interrupts & LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)) { rv = regmap_write(drvdata->lpaif_map, - LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), + LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)); if (rv) { dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", @@ -375,7 +383,7 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) if (interrupts & LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)) { rv = regmap_write(drvdata->lpaif_map, - LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), + LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)); if (rv) { dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", @@ -389,7 +397,7 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) if (interrupts & LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)) { rv = regmap_write(drvdata->lpaif_map, - LPAIF_IRQCLEAR_REG(LPAIF_IRQ_PORT_HOST), + LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)); if (rv) { dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", @@ -444,6 +452,7 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_variant *v = drvdata->variant; int ret; soc_runtime->dev->coherent_dma_mask = DMA_BIT_MASK(32); @@ -464,14 +473,14 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) /* ensure audio hardware is disabled */ ret = regmap_write(drvdata->lpaif_map, - LPAIF_IRQEN_REG(LPAIF_IRQ_PORT_HOST), 0); + LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", __func__, ret); return ret; } ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(LPAIF_RDMA_CHAN_MI2S), 0); + LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 0); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", __func__, ret); diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 5c99b3dace86..fa00be43e923 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -43,9 +43,37 @@ struct lpass_data { /* interrupts from the low-power audio interface (LPAIF) */ int lpaif_irq; + + /* SOC specific variations in the LPASS IP integration */ + struct lpass_variant *variant; +}; + +/* Vairant data per each SOC */ +struct lpass_variant { + u32 i2sctrl_reg_base; + u32 i2sctrl_reg_stride; + u32 i2s_ports; + u32 irq_reg_base; + u32 irq_reg_stride; + u32 irq_ports; + u32 rdma_reg_base; + u32 rdma_reg_stride; + u32 rdma_channels; + + /* SOC specific intialization like clocks */ + int (*init)(struct platform_device *pdev); + int (*exit)(struct platform_device *pdev); + + /* SOC specific dais */ + struct snd_soc_dai_driver *dai_driver; + int num_dai; }; /* register the platform driver from the CPU DAI driver */ int asoc_qcom_lpass_platform_register(struct platform_device *); +int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev); +int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev); +int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai); +extern struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops; #endif /* __LPASS_H__ */ -- cgit From 0ae9fd3b2c99099d5a800057b4092fdaa0e973a7 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Sat, 16 May 2015 13:32:25 +0100 Subject: ASoC: qcom: remove hardcoded i2s port number This patch attempts to remove the hardcoded i2s port number in lpass driver. Now the the port number comes from the dai id field. This will allow other SOCs to use different port numbers on the lpass driver. Signed-off-by: Srinivas Kandagatla Tested-by: Kenneth Westfield Acked-by: Kenneth Westfield Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 16 +++++++--------- sound/soc/qcom/lpass-ipq806x.c | 1 + 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 5544bfc57357..fd181330b3ca 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -138,8 +138,7 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, } ret = regmap_write(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, - LPAIF_I2S_PORT_MI2S), + LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), regval); if (ret) { dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", @@ -164,8 +163,8 @@ static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream, int ret; ret = regmap_write(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, - LPAIF_I2S_PORT_MI2S), 0); + LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), + 0); if (ret) dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", __func__, ret); @@ -180,7 +179,7 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream, int ret; ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, LPAIF_I2S_PORT_MI2S), + LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE); if (ret) dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", @@ -201,7 +200,7 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ret = regmap_update_bits(drvdata->lpaif_map, LPAIF_I2SCTL_REG(drvdata->variant, - LPAIF_I2S_PORT_MI2S), + dai->driver->id), LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE); if (ret) @@ -213,7 +212,7 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ret = regmap_update_bits(drvdata->lpaif_map, LPAIF_I2SCTL_REG(drvdata->variant, - LPAIF_I2S_PORT_MI2S), + dai->driver->id), LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_DISABLE); if (ret) @@ -243,8 +242,7 @@ int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai) /* ensure audio hardware is disabled */ ret = regmap_write(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, - LPAIF_I2S_PORT_MI2S), 0); + LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), 0); if (ret) dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", __func__, ret); diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c index 4a0e3fbb384b..cc5f3b4857eb 100644 --- a/sound/soc/qcom/lpass-ipq806x.c +++ b/sound/soc/qcom/lpass-ipq806x.c @@ -43,6 +43,7 @@ enum lpaif_dma_channels { }; static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = { + .id = IPQ806X_LPAIF_I2S_PORT_MI2S, .playback = { .stream_name = "lpass-cpu-playback", .formats = SNDRV_PCM_FMTBIT_S16 | -- cgit From 6db1c6ba9544e99778e0fdebe2d62c917fe1811c Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Sat, 16 May 2015 13:32:34 +0100 Subject: ASoC: qcom: remove hardcoded dma channel This patch removes hardcoded dma channel value in lpass driver, Now the dma channel allocation happens in the SOC specific layer. This will allow different LPASS integrations to use the lpass driver in more generic way. Signed-off-by: Srinivas Kandagatla Tested-by: Kenneth Westfield Acked-by: Kenneth Westfield Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-ipq806x.c | 12 ++++++ sound/soc/qcom/lpass-platform.c | 93 ++++++++++++++++++++++++++++------------- sound/soc/qcom/lpass.h | 2 + 3 files changed, 77 insertions(+), 30 deletions(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c index cc5f3b4857eb..2eab828644e8 100644 --- a/sound/soc/qcom/lpass-ipq806x.c +++ b/sound/soc/qcom/lpass-ipq806x.c @@ -63,6 +63,16 @@ static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = { .ops = &asoc_qcom_lpass_cpu_dai_ops, }; +int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata) +{ + return IPQ806X_LPAIF_RDMA_CHAN_MI2S; +} + +int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) +{ + return 0; +} + struct lpass_variant ipq806x_data = { .i2sctrl_reg_base = 0x0010, .i2sctrl_reg_stride = 0x04, @@ -75,6 +85,8 @@ struct lpass_variant ipq806x_data = { .rdma_channels = 4, .dai_driver = &ipq806x_lpass_cpu_dai_driver, .num_dai = 1, + .alloc_dma_channel = ipq806x_lpass_alloc_dma_channel, + .free_dma_channel = ipq806x_lpass_free_dma_channel, }; static const struct of_device_id ipq806x_lpass_cpu_device_id[] = { diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index a38e7ecf244f..fc0889196e7a 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -24,6 +24,11 @@ #include "lpass-lpaif-reg.h" #include "lpass.h" +struct lpass_pcm_data { + int rdma_ch; + int i2s_port; +}; + #define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024) #define LPASS_PLATFORM_PERIODS 2 @@ -78,6 +83,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); struct lpass_variant *v = drvdata->variant; @@ -85,7 +91,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, unsigned int channels = params_channels(params); unsigned int regval; int bitwidth; - int ret; + int ret, rdma_port = pcm_data->i2s_port; bitwidth = snd_pcm_format_width(format); if (bitwidth < 0) { @@ -95,7 +101,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, } regval = LPAIF_RDMACTL_BURSTEN_INCR4 | - LPAIF_RDMACTL_AUDINTF_MI2S | + LPAIF_RDMACTL_AUDINTF(rdma_port) | LPAIF_RDMACTL_FIFOWM_8; switch (bitwidth) { @@ -151,7 +157,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, } ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), regval); + LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch), regval); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", __func__, ret); @@ -164,13 +170,14 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); struct lpass_variant *v = drvdata->variant; int ret; ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 0); + LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch), 0); if (ret) dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", __func__, ret); @@ -182,13 +189,14 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); struct lpass_variant *v = drvdata->variant; - int ret; + int ret, ch = pcm_data->rdma_ch; ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMABASE_REG(v, LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMABASE_REG(v, ch), runtime->dma_addr); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n", @@ -197,7 +205,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) } ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMABUFF_REG(v, LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMABUFF_REG(v, ch), (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n", @@ -206,7 +214,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) } ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMAPER_REG(v, LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMAPER_REG(v, ch), (snd_pcm_lib_period_bytes(substream) >> 2) - 1); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n", @@ -215,7 +223,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream) } ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMACTL_REG(v, ch), LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", @@ -230,10 +238,11 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); struct lpass_variant *v = drvdata->variant; - int ret; + int ret, ch = pcm_data->rdma_ch; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -242,7 +251,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, /* clear status before enabling interrupts */ ret = regmap_write(drvdata->lpaif_map, LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), - LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S)); + LPAIF_IRQ_ALL(ch)); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", __func__, ret); @@ -251,8 +260,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, ret = regmap_update_bits(drvdata->lpaif_map, LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), - LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), - LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S)); + LPAIF_IRQ_ALL(ch), + LPAIF_IRQ_ALL(ch)); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", __func__, ret); @@ -260,7 +269,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, } ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMACTL_REG(v, ch), LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON); if (ret) { @@ -273,7 +282,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), + LPAIF_RDMACTL_REG(v, ch), LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_OFF); if (ret) { @@ -284,7 +293,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream, ret = regmap_update_bits(drvdata->lpaif_map, LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), - LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), 0); + LPAIF_IRQ_ALL(ch), 0); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", __func__, ret); @@ -300,15 +309,15 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); struct lpass_variant *v = drvdata->variant; unsigned int base_addr, curr_addr; - int ret; + int ret, ch = pcm_data->rdma_ch; ret = regmap_read(drvdata->lpaif_map, - LPAIF_RDMABASE_REG(v, LPAIF_RDMA_CHAN_MI2S), - &base_addr); + LPAIF_RDMABASE_REG(v, ch), &base_addr); if (ret) { dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n", __func__, ret); @@ -316,8 +325,7 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer( } ret = regmap_read(drvdata->lpaif_map, - LPAIF_RDMACURR_REG(v, LPAIF_RDMA_CHAN_MI2S), - &curr_addr); + LPAIF_RDMACURR_REG(v, ch), &curr_addr); if (ret) { dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n", __func__, ret); @@ -355,9 +363,10 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); struct lpass_variant *v = drvdata->variant; + struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); unsigned int interrupts; irqreturn_t ret = IRQ_NONE; - int rv; + int rv, chan = pcm_data->rdma_ch; rv = regmap_read(drvdata->lpaif_map, LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &interrupts); @@ -366,12 +375,13 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) __func__, rv); return IRQ_NONE; } - interrupts &= LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S); - if (interrupts & LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)) { + interrupts &= LPAIF_IRQ_ALL(chan); + + if (interrupts & LPAIF_IRQ_PER(chan)) { rv = regmap_write(drvdata->lpaif_map, LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), - LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)); + LPAIF_IRQ_PER(chan)); if (rv) { dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", __func__, rv); @@ -381,10 +391,10 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) ret = IRQ_HANDLED; } - if (interrupts & LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)) { + if (interrupts & LPAIF_IRQ_XRUN(chan)) { rv = regmap_write(drvdata->lpaif_map, LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), - LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)); + LPAIF_IRQ_XRUN(chan)); if (rv) { dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", __func__, rv); @@ -395,10 +405,10 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) ret = IRQ_HANDLED; } - if (interrupts & LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)) { + if (interrupts & LPAIF_IRQ_ERR(chan)) { rv = regmap_write(drvdata->lpaif_map, LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), - LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)); + LPAIF_IRQ_ERR(chan)); if (rv) { dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", __func__, rv); @@ -450,10 +460,26 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) struct snd_pcm *pcm = soc_runtime->pcm; struct snd_pcm_substream *substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; struct lpass_data *drvdata = snd_soc_platform_get_drvdata(soc_runtime->platform); struct lpass_variant *v = drvdata->variant; int ret; + struct lpass_pcm_data *data; + + data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + if (v->alloc_dma_channel) + data->rdma_ch = v->alloc_dma_channel(drvdata); + + if (IS_ERR_VALUE(data->rdma_ch)) + return data->rdma_ch; + + data->i2s_port = cpu_dai->driver->id; + + snd_soc_pcm_set_drvdata(soc_runtime, data); soc_runtime->dev->coherent_dma_mask = DMA_BIT_MASK(32); soc_runtime->dev->dma_mask = &soc_runtime->dev->coherent_dma_mask; @@ -480,7 +506,7 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) return ret; } ret = regmap_write(drvdata->lpaif_map, - LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 0); + LPAIF_RDMACTL_REG(v, data->rdma_ch), 0); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", __func__, ret); @@ -499,6 +525,13 @@ static void lpass_platform_pcm_free(struct snd_pcm *pcm) struct snd_pcm_substream *substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; + struct lpass_data *drvdata = + snd_soc_platform_get_drvdata(soc_runtime->platform); + struct lpass_pcm_data *data = snd_soc_pcm_get_drvdata(soc_runtime); + struct lpass_variant *v = drvdata->variant; + + if (v->free_dma_channel) + v->free_dma_channel(drvdata, data->rdma_ch); lpass_platform_free_buffer(substream, soc_runtime); } diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index fa00be43e923..caaf17fb0015 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -63,6 +63,8 @@ struct lpass_variant { /* SOC specific intialization like clocks */ int (*init)(struct platform_device *pdev); int (*exit)(struct platform_device *pdev); + int (*alloc_dma_channel)(struct lpass_data *data); + int (*free_dma_channel)(struct lpass_data *data, int ch); /* SOC specific dais */ struct snd_soc_dai_driver *dai_driver; -- cgit From 7cc24b169fa176618c654e50cb27640b75fe68d6 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Fri, 22 May 2015 07:12:27 +0800 Subject: ASoC: qcom: ipq806x_lpass_alloc_dma_channel() can be static Signed-off-by: Fengguang Wu Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-ipq806x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c index 2eab828644e8..7356d3a766d6 100644 --- a/sound/soc/qcom/lpass-ipq806x.c +++ b/sound/soc/qcom/lpass-ipq806x.c @@ -63,12 +63,12 @@ static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = { .ops = &asoc_qcom_lpass_cpu_dai_ops, }; -int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata) +static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata) { return IPQ806X_LPAIF_RDMA_CHAN_MI2S; } -int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) +static int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) { return 0; } -- cgit From 9a127cff91e43af807c96ca4ec7c855d382cc23d Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 21 May 2015 22:52:49 +0100 Subject: ASoC: qcom: support bitclk and osrclk per i2s port This patch adds support to allow bitclk and osrclk per i2s dai port. on APQ8016 there are 4 i2s ports each one has its own bit clks. Without this patch its not possible to support multiple i2s ports in the lpass driver. Tested-by: Kenneth Westfield Acked-by: Kenneth Westfield Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 60 ++++++++++++++++++++++++++++++---------------- sound/soc/qcom/lpass.h | 5 ++-- 2 files changed, 43 insertions(+), 22 deletions(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index fd181330b3ca..96cb4950b2fd 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -33,7 +33,7 @@ static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); int ret; - ret = clk_set_rate(drvdata->mi2s_osr_clk, freq); + ret = clk_set_rate(drvdata->mi2s_osr_clk[dai->driver->id], freq); if (ret) dev_err(dai->dev, "%s() error setting mi2s osrclk to %u: %d\n", __func__, freq, ret); @@ -47,18 +47,18 @@ static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream, struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); int ret; - ret = clk_prepare_enable(drvdata->mi2s_osr_clk); + ret = clk_prepare_enable(drvdata->mi2s_osr_clk[dai->diver->id]); if (ret) { dev_err(dai->dev, "%s() error in enabling mi2s osr clk: %d\n", __func__, ret); return ret; } - ret = clk_prepare_enable(drvdata->mi2s_bit_clk); + ret = clk_prepare_enable(drvdata->mi2s_bit_clk[dai->driver->id]); if (ret) { dev_err(dai->dev, "%s() error in enabling mi2s bit clk: %d\n", __func__, ret); - clk_disable_unprepare(drvdata->mi2s_osr_clk); + clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); return ret; } @@ -70,8 +70,8 @@ static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream, { struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); - clk_disable_unprepare(drvdata->mi2s_bit_clk); - clk_disable_unprepare(drvdata->mi2s_osr_clk); + clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]); + clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); } static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, @@ -146,7 +146,8 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, return ret; } - ret = clk_set_rate(drvdata->mi2s_bit_clk, rate * bitwidth * 2); + ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id], + rate * bitwidth * 2); if (ret) { dev_err(dai->dev, "%s() error setting mi2s bitclk to %u: %d\n", __func__, rate * bitwidth * 2, ret); @@ -354,7 +355,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) struct lpass_variant *variant; struct device *dev = &pdev->dev; const struct of_device_id *match; - int ret; + char clk_name[16]; + int ret, i, dai_id; dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); if (dsp_of_node) { @@ -400,18 +402,36 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) if (variant->init) variant->init(pdev); - drvdata->mi2s_osr_clk = devm_clk_get(&pdev->dev, "mi2s-osr-clk"); - if (IS_ERR(drvdata->mi2s_osr_clk)) { - dev_err(&pdev->dev, "%s() error getting mi2s-osr-clk: %ld\n", - __func__, PTR_ERR(drvdata->mi2s_osr_clk)); - return PTR_ERR(drvdata->mi2s_osr_clk); - } - - drvdata->mi2s_bit_clk = devm_clk_get(&pdev->dev, "mi2s-bit-clk"); - if (IS_ERR(drvdata->mi2s_bit_clk)) { - dev_err(&pdev->dev, "%s() error getting mi2s-bit-clk: %ld\n", - __func__, PTR_ERR(drvdata->mi2s_bit_clk)); - return PTR_ERR(drvdata->mi2s_bit_clk); + for (i = 0; i < variant->num_dai; i++) { + dai_id = variant->dai_driver[i].id; + if (variant->num_dai > 1) + sprintf(clk_name, "mi2s-osr-clk%d", i); + else + sprintf(clk_name, "mi2s-osr-clk"); + + drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(&pdev->dev, + clk_name); + if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) { + dev_err(&pdev->dev, + "%s() error getting mi2s-osr-clk: %ld\n", + __func__, + PTR_ERR(drvdata->mi2s_osr_clk[dai_id])); + return PTR_ERR(drvdata->mi2s_osr_clk[dai_id]); + } + + if (variant->num_dai > 1) + sprintf(clk_name, "mi2s-bit-clk%d", i); + else + sprintf(clk_name, "mi2s-bit-clk"); + + drvdata->mi2s_bit_clk[dai_id] = devm_clk_get(&pdev->dev, + clk_name); + if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) { + dev_err(&pdev->dev, + "%s() error getting mi2s-bit-clk: %ld\n", + __func__, PTR_ERR(drvdata->mi2s_bit_clk[i])); + return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]); + } } drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk"); diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index caaf17fb0015..75e9370cb360 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -22,6 +22,7 @@ #include #define LPASS_AHBIX_CLOCK_FREQUENCY 131072000 +#define LPASS_MAX_MI2S_PORTS (8) /* Both the CPU DAI and platform drivers will access this data */ struct lpass_data { @@ -30,10 +31,10 @@ struct lpass_data { struct clk *ahbix_clk; /* MI2S system clock */ - struct clk *mi2s_osr_clk; + struct clk *mi2s_osr_clk[LPASS_MAX_MI2S_PORTS]; /* MI2S bit clock (derived from system clock by a divider */ - struct clk *mi2s_bit_clk; + struct clk *mi2s_bit_clk[LPASS_MAX_MI2S_PORTS]; /* low-power audio interface (LPAIF) registers */ void __iomem *lpaif; -- cgit From 3e53ac8230c1af075402bb3c1c89777791c2055e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 21 May 2015 22:52:57 +0100 Subject: ASoC: qcom: make osr clock optional Some LPASS integrations like on APQ8016 do not have OSR clk, so making osr clk optional would allow such integrations to use lpass driver. Tested-by: Kenneth Westfield Acked-by: Kenneth Westfield Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 96cb4950b2fd..407e24de494e 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -33,6 +33,9 @@ static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); int ret; + if (IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) + return 0; + ret = clk_set_rate(drvdata->mi2s_osr_clk[dai->driver->id], freq); if (ret) dev_err(dai->dev, "%s() error setting mi2s osrclk to %u: %d\n", @@ -47,18 +50,23 @@ static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream, struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); int ret; - ret = clk_prepare_enable(drvdata->mi2s_osr_clk[dai->diver->id]); - if (ret) { - dev_err(dai->dev, "%s() error in enabling mi2s osr clk: %d\n", - __func__, ret); - return ret; + if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) { + ret = clk_prepare_enable( + drvdata->mi2s_osr_clk[dai->driver->id]); + if (ret) { + dev_err(dai->dev, "%s() error in enabling mi2s osr clk: %d\n", + __func__, ret); + return ret; + } } ret = clk_prepare_enable(drvdata->mi2s_bit_clk[dai->driver->id]); if (ret) { dev_err(dai->dev, "%s() error in enabling mi2s bit clk: %d\n", __func__, ret); - clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); + if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) + clk_disable_unprepare( + drvdata->mi2s_osr_clk[dai->driver->id]); return ret; } @@ -71,7 +79,9 @@ static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream, struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]); - clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); + + if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) + clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); } static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, @@ -412,11 +422,10 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(&pdev->dev, clk_name); if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) { - dev_err(&pdev->dev, + dev_warn(&pdev->dev, "%s() error getting mi2s-osr-clk: %ld\n", __func__, PTR_ERR(drvdata->mi2s_osr_clk[dai_id])); - return PTR_ERR(drvdata->mi2s_osr_clk[dai_id]); } if (variant->num_dai > 1) -- cgit From 0054055c590ae5ca69f027d42cf171493476f6d8 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 21 May 2015 22:53:05 +0100 Subject: ASoC: qcom: add dma channel control offset to variant data This patch adds ability to pass dma channel control bits start offset, which differ in differnet qcom SOCs. On apq8016 dma channel control bits start after an offset of 1. Tested-by: Kenneth Westfield Acked-by: Kenneth Westfield Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-platform.c | 2 +- sound/soc/qcom/lpass.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index fc0889196e7a..8ab0ac1dbedc 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -91,7 +91,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream, unsigned int channels = params_channels(params); unsigned int regval; int bitwidth; - int ret, rdma_port = pcm_data->i2s_port; + int ret, rdma_port = pcm_data->i2s_port + v->rdmactl_audif_start; bitwidth = snd_pcm_format_width(format); if (bitwidth < 0) { diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 75e9370cb360..023170a0943d 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -61,6 +61,11 @@ struct lpass_variant { u32 rdma_reg_stride; u32 rdma_channels; + /** + * on SOCs like APQ8016 the channel control bits start + * at different offset to ipq806x + **/ + u32 rdmactl_audif_start; /* SOC specific intialization like clocks */ int (*init)(struct platform_device *pdev); int (*exit)(struct platform_device *pdev); -- cgit From 4f629e4b8705fb02e9618ca257fb077f0022921b Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 21 May 2015 22:53:14 +0100 Subject: ASoC: qcom: Add ability to handle interrupts per dma channel This patch adds ablity to lpass driver to handle interrupt per dma channel. Without this patch its not possible to use multipl ports on the lpass. Tested-by: Kenneth Westfield Acked-by: Kenneth Westfield Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-platform.c | 94 ++++++++++++++++++++++++++--------------- sound/soc/qcom/lpass.h | 4 ++ 2 files changed, 63 insertions(+), 35 deletions(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 8ab0ac1dbedc..79688aa1941a 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -356,27 +356,15 @@ static struct snd_pcm_ops lpass_platform_pcm_ops = { .mmap = lpass_platform_pcmops_mmap, }; -static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) +static irqreturn_t lpass_dma_interrupt_handler( + struct snd_pcm_substream *substream, + struct lpass_data *drvdata, + int chan, u32 interrupts) { - struct snd_pcm_substream *substream = data; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct lpass_data *drvdata = - snd_soc_platform_get_drvdata(soc_runtime->platform); struct lpass_variant *v = drvdata->variant; - struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime); - unsigned int interrupts; irqreturn_t ret = IRQ_NONE; - int rv, chan = pcm_data->rdma_ch; - - rv = regmap_read(drvdata->lpaif_map, - LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &interrupts); - if (rv) { - dev_err(soc_runtime->dev, "%s() error reading from irqstat reg: %d\n", - __func__, rv); - return IRQ_NONE; - } - - interrupts &= LPAIF_IRQ_ALL(chan); + int rv; if (interrupts & LPAIF_IRQ_PER(chan)) { rv = regmap_write(drvdata->lpaif_map, @@ -422,6 +410,35 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) return ret; } +static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) +{ + struct lpass_data *drvdata = data; + struct lpass_variant *v = drvdata->variant; + unsigned int irqs; + int rv, chan; + + rv = regmap_read(drvdata->lpaif_map, + LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs); + if (rv) { + pr_err("%s() error reading from irqstat reg: %d\n", + __func__, rv); + return IRQ_NONE; + } + + /* Handle per channel interrupts */ + for (chan = 0; chan < LPASS_MAX_DMA_CHANNELS; chan++) { + if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->substream[chan]) { + rv = lpass_dma_interrupt_handler( + drvdata->substream[chan], + drvdata, chan, irqs); + if (rv != IRQ_HANDLED) + return rv; + } + } + + return IRQ_HANDLED; +} + static int lpass_platform_alloc_buffer(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *soc_runtime) { @@ -477,6 +494,7 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) if (IS_ERR_VALUE(data->rdma_ch)) return data->rdma_ch; + drvdata->substream[data->rdma_ch] = substream; data->i2s_port = cpu_dai->driver->id; snd_soc_pcm_set_drvdata(soc_runtime, data); @@ -488,29 +506,12 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) if (ret) return ret; - ret = devm_request_irq(soc_runtime->dev, drvdata->lpaif_irq, - lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, - "lpass-irq-lpaif", substream); - if (ret) { - dev_err(soc_runtime->dev, "%s() irq request failed: %d\n", - __func__, ret); - goto err_buf; - } - - /* ensure audio hardware is disabled */ - ret = regmap_write(drvdata->lpaif_map, - LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0); - if (ret) { - dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", - __func__, ret); - return ret; - } ret = regmap_write(drvdata->lpaif_map, LPAIF_RDMACTL_REG(v, data->rdma_ch), 0); if (ret) { dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", __func__, ret); - return ret; + goto err_buf; } return 0; @@ -530,6 +531,8 @@ static void lpass_platform_pcm_free(struct snd_pcm *pcm) struct lpass_pcm_data *data = snd_soc_pcm_get_drvdata(soc_runtime); struct lpass_variant *v = drvdata->variant; + drvdata->substream[data->rdma_ch] = NULL; + if (v->free_dma_channel) v->free_dma_channel(drvdata, data->rdma_ch); @@ -545,6 +548,8 @@ static struct snd_soc_platform_driver lpass_platform_driver = { int asoc_qcom_lpass_platform_register(struct platform_device *pdev) { struct lpass_data *drvdata = platform_get_drvdata(pdev); + struct lpass_variant *v = drvdata->variant; + int ret; drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); if (drvdata->lpaif_irq < 0) { @@ -553,6 +558,25 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) return -ENODEV; } + /* ensure audio hardware is disabled */ + ret = regmap_write(drvdata->lpaif_map, + LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0); + if (ret) { + dev_err(&pdev->dev, "%s() error writing to irqen reg: %d\n", + __func__, ret); + return ret; + } + + ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq, + lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, + "lpass-irq-lpaif", drvdata); + if (ret) { + dev_err(&pdev->dev, "%s() irq request failed: %d\n", + __func__, ret); + return ret; + } + + return devm_snd_soc_register_platform(&pdev->dev, &lpass_platform_driver); } diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index 023170a0943d..d572e7b8d590 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -23,6 +23,7 @@ #define LPASS_AHBIX_CLOCK_FREQUENCY 131072000 #define LPASS_MAX_MI2S_PORTS (8) +#define LPASS_MAX_DMA_CHANNELS (8) /* Both the CPU DAI and platform drivers will access this data */ struct lpass_data { @@ -47,6 +48,9 @@ struct lpass_data { /* SOC specific variations in the LPASS IP integration */ struct lpass_variant *variant; + + /* used it for handling interrupt per dma channel */ + struct snd_pcm_substream *substream[LPASS_MAX_DMA_CHANNELS]; }; /* Vairant data per each SOC */ -- cgit From 89cdfa06d9fdaa97e8c6c688383e4f38310d1e92 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 21 May 2015 22:53:21 +0100 Subject: ASoC: qcom: add bit map to track static dma channel allocations This patch adds dma channel bit mask to lpass data to keep track of dma channel allocations. This flag would be used in apq8016 lpass driver. Tested-by: Kenneth Westfield Acked-by: Kenneth Westfield Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/lpass.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index d572e7b8d590..deecae9f64f9 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -49,6 +49,9 @@ struct lpass_data { /* SOC specific variations in the LPASS IP integration */ struct lpass_variant *variant; + /* bit map to keep track of static channel allocations */ + unsigned long rdma_ch_bit_map; + /* used it for handling interrupt per dma channel */ struct snd_pcm_substream *substream[LPASS_MAX_DMA_CHANNELS]; }; -- cgit From dc1ebd1811e984301f98f3f9edd192327d2e35e1 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 22 May 2015 16:53:52 +0100 Subject: ASoC: qcom: Add apq8016 lpass driver support This patch adds apq8016 lpass driver support. APQ8016 has 4 MI2S which can be routed to one internal codec and 2 external codec interfaces. Primary, Secondary, Quaternary I2S can do Rx(playback) and Tertiary and Quaternary can do Tx(capture). Tested-by: Kenneth Westfield Acked-by: Kenneth Westfield Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/Kconfig | 6 + sound/soc/qcom/Makefile | 2 + sound/soc/qcom/lpass-apq8016.c | 242 +++++++++++++++++++++++++++++++++++++++++ sound/soc/qcom/lpass.h | 4 + 4 files changed, 254 insertions(+) create mode 100644 sound/soc/qcom/lpass-apq8016.c (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index b30c2baa7501..29fff6d7c633 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -18,6 +18,12 @@ config SND_SOC_LPASS_IPQ806X select SND_SOC_LPASS_CPU select SND_SOC_LPASS_PLATFORM +config SND_SOC_LPASS_APQ8016 + tristate + depends on SND_SOC_QCOM + select SND_SOC_LPASS_CPU + select SND_SOC_LPASS_PLATFORM + config SND_SOC_STORM tristate "ASoC I2S support for Storm boards" depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index f8aab91c9117..ac7630833fe5 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -2,10 +2,12 @@ snd-soc-lpass-cpu-objs := lpass-cpu.o snd-soc-lpass-platform-objs := lpass-platform.o snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o +snd-soc-lpass-apq8016-objs := lpass-apq8016.o obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o +obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o # Machine snd-soc-storm-objs := storm.o diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c new file mode 100644 index 000000000000..94efc01020c4 --- /dev/null +++ b/sound/soc/qcom/lpass-apq8016.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * lpass-apq8016.c -- ALSA SoC CPU DAI driver for APQ8016 LPASS + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "lpass-lpaif-reg.h" +#include "lpass.h" + +static struct snd_soc_dai_driver apq8016_lpass_cpu_dai_driver[] = { + [MI2S_PRIMARY] = { + .id = MI2S_PRIMARY, + .name = "Primary MI2S", + .playback = { + .stream_name = "Primary Playback", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, + [MI2S_SECONDARY] = { + .id = MI2S_SECONDARY, + .name = "Secondary MI2S", + .playback = { + .stream_name = "Secondary Playback", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, + [MI2S_TERTIARY] = { + .id = MI2S_TERTIARY, + .name = "Tertiary MI2S", + .capture = { + .stream_name = "Tertiary Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, + [MI2S_QUATERNARY] = { + .id = MI2S_QUATERNARY, + .name = "Quatenary MI2S", + .playback = { + .stream_name = "Quatenary Playback", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .capture = { + .stream_name = "Quatenary Capture", + .formats = SNDRV_PCM_FMTBIT_S16 | + SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, +}; + +static int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata) +{ + struct lpass_variant *v = drvdata->variant; + int chan = find_first_zero_bit(&drvdata->rdma_ch_bit_map, + v->rdma_channels); + + if (chan >= v->rdma_channels) + return -EBUSY; + + set_bit(chan, &drvdata->rdma_ch_bit_map); + + return chan; +} + +static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) +{ + clear_bit(chan, &drvdata->rdma_ch_bit_map); + + return 0; +} + +static int apq8016_lpass_init(struct platform_device *pdev) +{ + struct lpass_data *drvdata = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + int ret; + + drvdata->pcnoc_mport_clk = devm_clk_get(dev, "pcnoc-mport-clk"); + if (IS_ERR(drvdata->pcnoc_mport_clk)) { + dev_err(&pdev->dev, "%s() error getting pcnoc-mport-clk: %ld\n", + __func__, PTR_ERR(drvdata->pcnoc_mport_clk)); + return PTR_ERR(drvdata->pcnoc_mport_clk); + } + + ret = clk_prepare_enable(drvdata->pcnoc_mport_clk); + if (ret) { + dev_err(&pdev->dev, "%s() Error enabling pcnoc-mport-clk: %d\n", + __func__, ret); + return ret; + } + + drvdata->pcnoc_sway_clk = devm_clk_get(dev, "pcnoc-sway-clk"); + if (IS_ERR(drvdata->pcnoc_sway_clk)) { + dev_err(&pdev->dev, "%s() error getting pcnoc-sway-clk: %ld\n", + __func__, PTR_ERR(drvdata->pcnoc_sway_clk)); + return PTR_ERR(drvdata->pcnoc_sway_clk); + } + + ret = clk_prepare_enable(drvdata->pcnoc_sway_clk); + if (ret) { + dev_err(&pdev->dev, "%s() Error enabling pcnoc_sway_clk: %d\n", + __func__, ret); + return ret; + } + + return 0; +} + +static int apq8016_lpass_exit(struct platform_device *pdev) +{ + struct lpass_data *drvdata = platform_get_drvdata(pdev); + + clk_disable_unprepare(drvdata->pcnoc_mport_clk); + clk_disable_unprepare(drvdata->pcnoc_sway_clk); + + return 0; +} + + +static struct lpass_variant apq8016_data = { + .i2sctrl_reg_base = 0x1000, + .i2sctrl_reg_stride = 0x1000, + .i2s_ports = 4, + .irq_reg_base = 0x6000, + .irq_reg_stride = 0x1000, + .irq_ports = 3, + .rdma_reg_base = 0x8400, + .rdma_reg_stride = 0x1000, + .rdma_channels = 2, + .rdmactl_audif_start = 1, + .dai_driver = apq8016_lpass_cpu_dai_driver, + .num_dai = ARRAY_SIZE(apq8016_lpass_cpu_dai_driver), + .init = apq8016_lpass_init, + .exit = apq8016_lpass_exit, + .alloc_dma_channel = apq8016_lpass_alloc_dma_channel, + .free_dma_channel = apq8016_lpass_free_dma_channel, +}; + +static const struct of_device_id apq8016_lpass_cpu_device_id[] = { + { .compatible = "qcom,lpass-cpu-apq8016", .data = &apq8016_data }, + {} +}; +MODULE_DEVICE_TABLE(of, apq8016_lpass_cpu_device_id); + +static struct platform_driver apq8016_lpass_cpu_platform_driver = { + .driver = { + .name = "apq8016-lpass-cpu", + .of_match_table = of_match_ptr(apq8016_lpass_cpu_device_id), + }, + .probe = asoc_qcom_lpass_cpu_platform_probe, + .remove = asoc_qcom_lpass_cpu_platform_remove, +}; +module_platform_driver(apq8016_lpass_cpu_platform_driver); + +MODULE_DESCRIPTION("APQ8016 LPASS CPU Driver"); +MODULE_LICENSE("GPL v2"); + diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index deecae9f64f9..d6e86c119e74 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -54,6 +54,10 @@ struct lpass_data { /* used it for handling interrupt per dma channel */ struct snd_pcm_substream *substream[LPASS_MAX_DMA_CHANNELS]; + + /* 8016 specific */ + struct clk *pcnoc_mport_clk; + struct clk *pcnoc_sway_clk; }; /* Vairant data per each SOC */ -- cgit From 6cc8ae94813dffe7ff5ba88da0fe25a697e3e8a3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 22 May 2015 16:54:17 +0100 Subject: ASoC: qcom: fix STORM board Kconfig This patch is a fixup to correct dependencies in patch 9bae4880acee ("ASoC: qcom: move ipq806x specific bits out of lpass driver.") Originally this change-set was suggested by Arnd on mailing list. Signed-off-by: Arnd Bergmann Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- sound/soc/qcom/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/qcom') diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 29fff6d7c633..938144c59e2b 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -26,7 +26,7 @@ config SND_SOC_LPASS_APQ8016 config SND_SOC_STORM tristate "ASoC I2S support for Storm boards" - depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST + depends on SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST) select SND_SOC_LPASS_IPQ806X select SND_SOC_MAX98357A help -- cgit