diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/max98095.c | 4 | ||||
-rw-r--r-- | sound/soc/omap/Kconfig | 5 | ||||
-rw-r--r-- | sound/soc/omap/omap-twl4030.c | 3 | ||||
-rw-r--r-- | sound/soc/pxa/brownstone.c | 25 | ||||
-rw-r--r-- | sound/soc/pxa/poodle.c | 19 | ||||
-rw-r--r-- | sound/soc/pxa/tosa.c | 13 | ||||
-rw-r--r-- | sound/soc/pxa/z2.c | 9 | ||||
-rw-r--r-- | sound/soc/qcom/Kconfig | 19 | ||||
-rw-r--r-- | sound/soc/qcom/Makefile | 4 | ||||
-rw-r--r-- | sound/soc/qcom/lpass-apq8016.c | 242 | ||||
-rw-r--r-- | sound/soc/qcom/lpass-cpu.c | 240 | ||||
-rw-r--r-- | sound/soc/qcom/lpass-ipq806x.c | 109 | ||||
-rw-r--r-- | sound/soc/qcom/lpass-lpaif-reg.h (renamed from sound/soc/qcom/lpass-lpaif-ipq806x.h) | 92 | ||||
-rw-r--r-- | sound/soc/qcom/lpass-platform.c | 202 | ||||
-rw-r--r-- | sound/soc/qcom/lpass.h | 51 | ||||
-rw-r--r-- | sound/soc/sh/rcar/core.c | 32 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 3 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsrc-card.c | 1 | ||||
-rw-r--r-- | sound/soc/sh/rcar/src.c | 11 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ssi.c | 70 |
20 files changed, 804 insertions, 350 deletions
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 2b8b8a5f385f..9a46d3dcf703 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -2301,8 +2301,8 @@ static int max98095_probe(struct snd_soc_codec *codec) /* register an audio interrupt */ ret = request_threaded_irq(client->irq, NULL, max98095_report_jack, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "max98095", codec); + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | + IRQF_ONESHOT, "max98095", codec); if (ret) { dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); goto err_access; diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 6768e4f7d7d0..30d0109703a9 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -100,12 +100,13 @@ config SND_OMAP_SOC_OMAP_TWL4030 config SND_OMAP_SOC_OMAP_ABE_TWL6040 tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" - depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || SOC_OMAP5 || COMPILE_TEST) + depends on TWL6040_CORE && SND_OMAP_SOC + depends on ARCH_OMAP4 || (SOC_OMAP5 && MFD_PALMAS) || COMPILE_TEST select SND_OMAP_SOC_DMIC select SND_OMAP_SOC_MCPDM select SND_SOC_TWL6040 select SND_SOC_DMIC - select COMMON_CLK_PALMAS if MFD_PALMAS + select COMMON_CLK_PALMAS if (SOC_OMAP5 && MFD_PALMAS) help Say Y if you want to add support for SoC audio on OMAP boards using ABE and twl6040 codec. This driver currently supports: diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c index 3673ada43bfb..743131473056 100644 --- a/sound/soc/omap/omap-twl4030.c +++ b/sound/soc/omap/omap-twl4030.c @@ -159,9 +159,8 @@ static inline void twl4030_disconnect_pin(struct snd_soc_dapm_context *dapm, static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = rtd->card; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_dapm_context *dapm = &card->dapm; struct omap_tw4030_pdata *pdata = dev_get_platdata(card->dev); struct omap_twl4030 *priv = snd_soc_card_get_drvdata(card); int ret = 0; diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c index 79936e3e80e7..2b26318bc200 100644 --- a/sound/soc/pxa/brownstone.c +++ b/sound/soc/pxa/brownstone.c @@ -45,29 +45,6 @@ static const struct snd_soc_dapm_route brownstone_audio_map[] = { {"MICBIAS1", NULL, "Main Mic"}, }; -static int brownstone_wm8994_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - /* set endpoints to not connected */ - snd_soc_dapm_nc_pin(dapm, "HPOUT2P"); - snd_soc_dapm_nc_pin(dapm, "HPOUT2N"); - snd_soc_dapm_nc_pin(dapm, "LINEOUT1N"); - snd_soc_dapm_nc_pin(dapm, "LINEOUT1P"); - snd_soc_dapm_nc_pin(dapm, "LINEOUT2N"); - snd_soc_dapm_nc_pin(dapm, "LINEOUT2P"); - snd_soc_dapm_nc_pin(dapm, "IN1LN"); - snd_soc_dapm_nc_pin(dapm, "IN1LP"); - snd_soc_dapm_nc_pin(dapm, "IN1RP"); - snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN"); - snd_soc_dapm_nc_pin(dapm, "IN2RN"); - snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP"); - snd_soc_dapm_nc_pin(dapm, "IN2LN"); - - return 0; -} - static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -115,7 +92,6 @@ static struct snd_soc_dai_link brownstone_wm8994_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &brownstone_ops, - .init = brownstone_wm8994_init, }, }; @@ -132,6 +108,7 @@ static struct snd_soc_card brownstone = { .num_dapm_widgets = ARRAY_SIZE(brownstone_dapm_widgets), .dapm_routes = brownstone_audio_map, .num_dapm_routes = ARRAY_SIZE(brownstone_audio_map), + .fully_routed = true, }; static int brownstone_probe(struct platform_device *pdev) diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 0fce8c420e96..80b457ac522a 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -192,6 +192,7 @@ static int poodle_amp_event(struct snd_soc_dapm_widget *w, static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event), +SND_SOC_DAPM_MIC("Microphone", NULL), }; /* Corgi machine connections to the codec pins */ @@ -204,6 +205,8 @@ static const struct snd_soc_dapm_route poodle_audio_map[] = { /* speaker connected to LOUT, ROUT */ {"Ext Spk", NULL, "ROUT"}, {"Ext Spk", NULL, "LOUT"}, + + {"MICIN", NULL, "Microphone"}, }; static const char *jack_function[] = {"Off", "Headphone"}; @@ -220,20 +223,6 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = { poodle_set_spk), }; -/* - * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device - */ -static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_nc_pin(dapm, "LLINEIN"); - snd_soc_dapm_nc_pin(dapm, "RLINEIN"); - - return 0; -} - /* poodle digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link poodle_dai = { .name = "WM8731", @@ -242,7 +231,6 @@ static struct snd_soc_dai_link poodle_dai = { .codec_dai_name = "wm8731-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm8731.0-001b", - .init = poodle_wm8731_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &poodle_ops, @@ -261,6 +249,7 @@ static struct snd_soc_card poodle = { .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), .dapm_routes = poodle_audio_map, .num_dapm_routes = ARRAY_SIZE(poodle_audio_map), + .fully_routed = true, }; static int poodle_probe(struct platform_device *pdev) diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index cb49284e853a..f59f566551ef 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -185,17 +185,6 @@ static const struct snd_kcontrol_new tosa_controls[] = { tosa_set_spk), }; -static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_nc_pin(dapm, "OUT3"); - snd_soc_dapm_nc_pin(dapm, "MONOOUT"); - - return 0; -} - static struct snd_soc_dai_link tosa_dai[] = { { .name = "AC97", @@ -204,7 +193,6 @@ static struct snd_soc_dai_link tosa_dai[] = { .codec_dai_name = "wm9712-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm9712-codec", - .init = tosa_ac97_init, .ops = &tosa_ops, }, { @@ -230,6 +218,7 @@ static struct snd_soc_card tosa = { .num_dapm_widgets = ARRAY_SIZE(tosa_dapm_widgets), .dapm_routes = audio_map, .num_dapm_routes = ARRAY_SIZE(audio_map), + .fully_routed = true, }; static int tosa_probe(struct platform_device *pdev) diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index bcbfbe8303f7..990b1aa6d7f6 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c @@ -132,16 +132,8 @@ static const struct snd_soc_dapm_route z2_audio_map[] = { */ static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; - /* NC codec pins */ - snd_soc_dapm_disable_pin(dapm, "LINPUT3"); - snd_soc_dapm_disable_pin(dapm, "RINPUT3"); - snd_soc_dapm_disable_pin(dapm, "OUT3"); - snd_soc_dapm_disable_pin(dapm, "MONO1"); - /* Jack detection API stuff */ ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", SND_JACK_HEADSET, &hs_jack, hs_jack_pins, @@ -189,6 +181,7 @@ static struct snd_soc_card snd_soc_z2 = { .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), .dapm_routes = z2_audio_map, .num_dapm_routes = ARRAY_SIZE(z2_audio_map), + .fully_routed = true, }; static struct platform_device *z2_snd_device; diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 5f58e4f1bca9..938144c59e2b 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -6,19 +6,28 @@ 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 - tristate "ASoC I2S support for Storm boards" - depends on (ARCH_QCOM && SND_SOC_QCOM) || COMPILE_TEST +config SND_SOC_LPASS_IPQ806X + tristate + depends on SND_SOC_QCOM + 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 SND_SOC_QCOM && (ARCH_QCOM || COMPILE_TEST) + 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..ac7630833fe5 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -1,9 +1,13 @@ # 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 +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 <linux/clk.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-dai.h> + +#include <dt-bindings/sound/apq8016-lpass.h> +#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-cpu.c b/sound/soc/qcom/lpass-cpu.c index dc790abaa331..23f3d59e6d09 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -14,21 +14,17 @@ */ #include <linux/clk.h> -#include <linux/compiler.h> -#include <linux/device.h> -#include <linux/err.h> -#include <linux/ioport.h> #include <linux/kernel.h> -#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <linux/regmap.h> #include <sound/soc.h> #include <sound/soc-dai.h> -#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, @@ -37,7 +33,10 @@ 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); + 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", __func__, freq, ret); @@ -51,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); - 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); + 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); + if (!IS_ERR(drvdata->mi2s_osr_clk[dai->driver->id])) + clk_disable_unprepare( + drvdata->mi2s_osr_clk[dai->driver->id]); return ret; } @@ -74,8 +78,10 @@ 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]); + + 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, @@ -142,14 +148,16 @@ 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, dai->driver->id), + regval); if (ret) { dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", __func__, ret); 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); @@ -166,7 +174,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, dai->driver->id), + 0); if (ret) dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", __func__, ret); @@ -181,7 +190,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, 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 +210,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, + dai->driver->id), LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE); if (ret) @@ -212,7 +222,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, + dai->driver->id), LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_DISABLE); if (ret) @@ -224,7 +235,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, @@ -233,41 +244,23 @@ 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, dai->driver->id), 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", @@ -275,27 +268,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; } @@ -304,29 +299,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; } @@ -335,36 +332,41 @@ 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; - int ret; + struct lpass_variant *variant; + struct device *dev = &pdev->dev; + const struct of_device_id *match; + 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) { @@ -379,11 +381,14 @@ 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"); - 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)) { @@ -393,6 +398,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)) { @@ -401,18 +409,38 @@ static int lpass_cpu_platform_probe(struct platform_device *pdev) return PTR_ERR(drvdata->lpaif_map); } - 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); + if (variant->init) |