From 1037d567fdfc7ab9d3e2328e27bdc1300d3fdb1e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 21 Nov 2013 12:38:44 -0200 Subject: ASoC: wm8737: Use IS_ENABLED() macro Using the IS_ENABLED() macro can make the code shorter and simpler. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/wm8737.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 2f167a8ca01b..22de2420bec8 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -644,7 +644,7 @@ static const struct regmap_config wm8737_regmap = { .volatile_reg = wm8737_volatile, }; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) static int wm8737_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -758,7 +758,7 @@ static struct spi_driver wm8737_spi_driver = { static int __init wm8737_modinit(void) { int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) ret = i2c_add_driver(&wm8737_i2c_driver); if (ret != 0) { printk(KERN_ERR "Failed to register WM8737 I2C driver: %d\n", @@ -781,7 +781,7 @@ static void __exit wm8737_exit(void) #if defined(CONFIG_SPI_MASTER) spi_unregister_driver(&wm8737_spi_driver); #endif -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) i2c_del_driver(&wm8737_i2c_driver); #endif } -- cgit v1.2.3 From 060ec80a27bf7a00bafb0c7495bbeec92e7903d3 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 21 Nov 2013 12:38:51 -0200 Subject: ASoC: wm8983: Use IS_ENABLED() macro Using the IS_ENABLED() macro can make the code shorter and simpler. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/wm8983.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index aa41ba0dfff4..3bae71d990e6 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -1129,7 +1129,7 @@ static struct spi_driver wm8983_spi_driver = { }; #endif -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) static int wm8983_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -1182,7 +1182,7 @@ static int __init wm8983_modinit(void) { int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) ret = i2c_add_driver(&wm8983_i2c_driver); if (ret) { printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n", @@ -1202,7 +1202,7 @@ module_init(wm8983_modinit); static void __exit wm8983_exit(void) { -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C) i2c_del_driver(&wm8983_i2c_driver); #endif #if defined(CONFIG_SPI_MASTER) -- cgit v1.2.3 From b2cbb6e1c1544fc889ee7d6c6a6c229c20cd03cd Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Thu, 23 Jan 2014 13:02:47 +0800 Subject: ASoC: core: set_tdm_slot() will return -ENOTSUPP if no operation provided Make it easier for generic code to work with set_tdm_slot() by distinguishing between the operation not being supported and an error as is done. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..393ff069af69 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3626,7 +3626,7 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); else - return -EINVAL; + return -ENOTSUPP; } EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); -- cgit v1.2.3 From 5ad8865b009bc8ad35adcbcb60c0679d437e8036 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 27 Jan 2014 17:37:51 +0200 Subject: ASoC: davinci-evm: Add named clock reference to DT bindings The referenced clock is used to get codec clock rate and the clock is disabled and enabled in startup and shutdown snd_soc_ops call backs. The change is also documented in DT bindigs document. Signed-off-by: Jyri Sarha cc: bcousson@baylibre.com Signed-off-by: Mark Brown --- .../bindings/sound/davinci-evm-audio.txt | 9 +++- sound/soc/davinci/davinci-evm.c | 58 +++++++++++++++++++++- 2 files changed, 64 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt index 865178d5cdf3..963e100514c2 100644 --- a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt @@ -5,12 +5,19 @@ Required properties: - ti,model : The user-visible name of this sound complex. - ti,audio-codec : The phandle of the TLV320AIC3x audio codec - ti,mcasp-controller : The phandle of the McASP controller -- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec - ti,audio-routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink, the second being the connection's source. Valid names for sources and sinks are the codec's pins, and the jacks on the board: +Optional properties: +- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec. +- clocks : Reference to the master clock +- clock-names : The clock should be named "mclk" +- Either codec-clock-rate or the codec-clock reference has to be defined. If + the both are defined the driver attempts to set referenced clock to the + defined rate and takes the rate from the clock reference. + Board connectors: * Headphone Jack diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 70ff3772079f..d3e4cb0655d2 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -30,9 +31,34 @@ #include "davinci-i2s.h" struct snd_soc_card_drvdata_davinci { + struct clk *mclk; unsigned sysclk; }; +static int evm_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *soc_card = rtd->codec->card; + struct snd_soc_card_drvdata_davinci *drvdata = + snd_soc_card_get_drvdata(soc_card); + + if (drvdata->mclk) + return clk_prepare_enable(drvdata->mclk); + + return 0; +} + +static void evm_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *soc_card = rtd->codec->card; + struct snd_soc_card_drvdata_davinci *drvdata = + snd_soc_card_get_drvdata(soc_card); + + if (drvdata->mclk) + clk_disable_unprepare(drvdata->mclk); +} + static int evm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -59,6 +85,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream, } static struct snd_soc_ops evm_ops = { + .startup = evm_startup, + .shutdown = evm_shutdown, .hw_params = evm_hw_params, }; @@ -348,6 +376,7 @@ static int davinci_evm_probe(struct platform_device *pdev) of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data; struct snd_soc_card_drvdata_davinci *drvdata = NULL; + struct clk *mclk; int ret = 0; evm_soc_card.dai_link = dai; @@ -367,13 +396,38 @@ static int davinci_evm_probe(struct platform_device *pdev) if (ret) return ret; + mclk = devm_clk_get(&pdev->dev, "mclk"); + if (PTR_ERR(mclk) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (IS_ERR(mclk)) { + dev_dbg(&pdev->dev, "mclk not found.\n"); + mclk = NULL; + } + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; + drvdata->mclk = mclk; + ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk); - if (ret < 0) - return -EINVAL; + + if (ret < 0) { + if (!drvdata->mclk) { + dev_err(&pdev->dev, + "No clock or clock rate defined.\n"); + return -EINVAL; + } + drvdata->sysclk = clk_get_rate(drvdata->mclk); + } else if (drvdata->mclk) { + unsigned int requestd_rate = drvdata->sysclk; + clk_set_rate(drvdata->mclk, drvdata->sysclk); + drvdata->sysclk = clk_get_rate(drvdata->mclk); + if (drvdata->sysclk != requestd_rate) + dev_warn(&pdev->dev, + "Could not get requested rate %u using %u.\n", + requestd_rate, drvdata->sysclk); + } snd_soc_card_set_drvdata(&evm_soc_card, drvdata); ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card); -- cgit v1.2.3 From ab8b14b6d841b314434f5817c107572f923fc43d Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 27 Jan 2014 17:37:52 +0200 Subject: ASoC: davinci-mcasp: Set BCLK divider if McASP is BCLK master Make BCLK divider setting implicite in hw_params call if McASP device is the bit clock master on the audio serial bus. Signed-off-by: Jyri Sarha Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b7858bfa0295..ae328beb676a 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -53,6 +53,9 @@ struct davinci_mcasp { u16 bclk_lrclk_ratio; int streams; + int sysclk_freq; + bool bclk_master; + /* McASP FIFO related */ u8 txnumevt; u8 rxnumevt; @@ -292,6 +295,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); + mcasp->bclk_master = 1; break; case SND_SOC_DAIFMT_CBM_CFS: /* codec is clock master and frame slave */ @@ -303,6 +307,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR); mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR); + mcasp->bclk_master = 0; break; case SND_SOC_DAIFMT_CBM_CFM: /* codec is clock and frame master */ @@ -314,6 +319,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); + mcasp->bclk_master = 0; break; default: @@ -405,6 +411,8 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX); } + mcasp->sysclk_freq = freq; + return 0; } @@ -607,6 +615,18 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, int channels; struct snd_interval *pcm_channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + + /* If mcasp is BCLK master we need to set BCLK divider */ + if (mcasp->bclk_master) { + unsigned int bclk_freq = snd_soc_params_to_bclk(params); + if (mcasp->sysclk_freq % bclk_freq != 0) { + dev_err(mcasp->dev, "Can't produce requred BCLK\n"); + return -EINVAL; + } + davinci_mcasp_set_clkdiv( + cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); + } + channels = pcm_channels->min; active_serializers = (channels + slots - 1) / slots; -- cgit v1.2.3 From 0f7d9a635b7d1b120884b13d8763c9499e8a4aca Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 30 Jan 2014 15:15:24 +0200 Subject: ASoC: davinci-mcasp: Return value handling cleanup for mcasp_common_hw_param() Take the return value from mcasp_common_hw_param() and use that in case of error. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index f662ef22b8ae..f837b0a4f6f4 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -631,8 +631,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, active_serializers = (channels + slots - 1) / slots; - if (mcasp_common_hw_param(mcasp, substream->stream, channels) == -EINVAL) - return -EINVAL; + ret = mcasp_common_hw_param(mcasp, substream->stream, channels); + if (ret) + return ret; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) fifo_level = mcasp->txnumevt * active_serializers; else -- cgit v1.2.3 From 135014adc6ae5a1ab0f2f20abaf81d1860138d38 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 30 Jan 2014 15:21:32 +0200 Subject: ASoC: davinci-mcasp: Move pm callbacks from platform device to soc_dai_driver Handle the PM callbacks via the ASoC core instead of device core. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 74 +++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 37 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index f837b0a4f6f4..0518ff2d960c 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -741,6 +741,41 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .set_sysclk = davinci_mcasp_set_sysclk, }; +#ifdef CONFIG_PM_SLEEP +static int davinci_mcasp_suspend(struct snd_soc_dai *dai) +{ + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + + mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); + mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); + mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); + mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); + mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); + mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); + mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); + + return 0; +} + +static int davinci_mcasp_resume(struct snd_soc_dai *dai) +{ + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt); + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt); + mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir); + + return 0; +} +#else +#define davinci_mcasp_suspend NULL +#define davinci_mcasp_resume NULL +#endif + #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ @@ -757,6 +792,8 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { static struct snd_soc_dai_driver davinci_mcasp_dai[] = { { .name = "davinci-mcasp.0", + .suspend = davinci_mcasp_suspend, + .resume = davinci_mcasp_resume, .playback = { .channels_min = 2, .channels_max = 32 * 16, @@ -1149,49 +1186,12 @@ static int davinci_mcasp_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int davinci_mcasp_suspend(struct device *dev) -{ - struct davinci_mcasp *mcasp = dev_get_drvdata(dev); - - mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); - mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); - mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); - mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); - mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); - mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); - mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); - - return 0; -} - -static int davinci_mcasp_resume(struct device *dev) -{ - struct davinci_mcasp *mcasp = dev_get_drvdata(dev); - - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt); - mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir); - - return 0; -} -#endif - -SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops, - davinci_mcasp_suspend, - davinci_mcasp_resume); - static struct platform_driver davinci_mcasp_driver = { .probe = davinci_mcasp_probe, .remove = davinci_mcasp_remove, .driver = { .name = "davinci-mcasp", .owner = THIS_MODULE, - .pm = &davinci_mcasp_pm_ops, .of_match_table = mcasp_dt_ids, }, }; -- cgit v1.2.3 From 2a67e796da38dff41e5b2aa9352c81189407acb9 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jan 2014 15:58:06 +0000 Subject: ASoC: wm5102: Improve EQ coefficient controls The EQ coefficient binary controls overlapped with the volume controls for the B4 and B5 volumes, which were controllable from either the coefficient control or the volume control itself. This patch adds controls for the mode and moves the coefficient control to only cover the coefficients. Signed-off-by: Charles Keepax Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index ce9c8e14d4bd..5e03a83aecaa 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -685,15 +685,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, - ARIZONA_EQ1_ENA_MASK), -SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, - ARIZONA_EQ2_ENA_MASK), -SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, - ARIZONA_EQ3_ENA_MASK), -SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, - ARIZONA_EQ4_ENA_MASK), - +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, @@ -705,6 +698,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, @@ -716,6 +711,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, @@ -727,6 +724,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, -- cgit v1.2.3 From 552694c65b1c563dbdbda4082527774a373ae720 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jan 2014 15:58:07 +0000 Subject: ASoC: wm5110: Improve EQ coefficient controls The EQ coefficient binary controls overlapped with the volume controls for the B4 and B5 volumes, which were controllable from either the coefficient control or the volume control itself. This patch adds controls for the mode and moves the coefficient control to only cover the coefficients. Signed-off-by: Charles Keepax Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/wm5110.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 2c3c962d9a85..7c2b0d669d29 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -247,15 +247,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, - ARIZONA_EQ1_ENA_MASK), -SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, - ARIZONA_EQ2_ENA_MASK), -SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, - ARIZONA_EQ3_ENA_MASK), -SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, - ARIZONA_EQ4_ENA_MASK), - +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, @@ -267,6 +260,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, @@ -278,6 +273,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, @@ -289,6 +286,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, -- cgit v1.2.3 From fb0def0ceda7b2a79be978093704c1c71e26ba22 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 21 Jan 2014 15:58:08 +0000 Subject: ASoC: wm8997: Improve EQ coefficient controls The EQ coefficient binary controls overlapped with the volume controls for the B4 and B5 volumes, which were controllable from either the coefficient control or the volume control itself. This patch adds controls for the mode and moves the coefficient control to only cover the coefficients. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8997.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 555115ee2159..4a382495976c 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -170,15 +170,8 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES_MASK("EQ1 Coefficients", ARIZONA_EQ1_1, 21, - ARIZONA_EQ1_ENA_MASK), -SND_SOC_BYTES_MASK("EQ2 Coefficients", ARIZONA_EQ2_1, 21, - ARIZONA_EQ2_ENA_MASK), -SND_SOC_BYTES_MASK("EQ3 Coefficients", ARIZONA_EQ3_1, 21, - ARIZONA_EQ3_ENA_MASK), -SND_SOC_BYTES_MASK("EQ4 Coefficients", ARIZONA_EQ4_1, 21, - ARIZONA_EQ4_ENA_MASK), - +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, @@ -190,6 +183,8 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT, @@ -201,6 +196,8 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT, @@ -212,6 +209,8 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT, -- cgit v1.2.3 From ddbc5efed0f9064287acead56bbf0dce3ca28ee2 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 22 Jan 2014 10:09:11 +0000 Subject: ASoC: wm_adsp: Add debug print to note that the DSP has shutdown It can be useful for debugging purposes to see at what point the DSP has powered down, so add a message to inform us of this. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 444626fcab40..f9fd56444a14 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1679,6 +1679,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, list_del(&alg_region->list); kfree(alg_region); } + + adsp_dbg(dsp, "Shutdown complete\n"); break; default: -- cgit v1.2.3 From 1371105731a7c72168d0e464a51203fec829390b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 23 Jan 2014 13:45:34 +0000 Subject: ASoC: wm5102: Correct typo in EQ coefficient sizes Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 5e03a83aecaa..ebffe81daa1d 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -685,7 +685,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -698,7 +698,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -711,7 +711,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -724,7 +724,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), -- cgit v1.2.3 From 3c379ef97e7f6cd305a4873150319c2355b4316d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 23 Jan 2014 13:45:35 +0000 Subject: ASoC: wm5110: Correct type in EQ coefficient sizes Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm5110.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 7c2b0d669d29..4de2bf16dc74 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -247,7 +247,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -260,7 +260,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -273,7 +273,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -286,7 +286,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), -- cgit v1.2.3 From 2b14cd3af9d98ce135e503e91e3973bdd5e4baeb Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 23 Jan 2014 13:45:36 +0000 Subject: ASoC: wm8997: Correct typo in EQ coefficient sizes Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8997.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 4a382495976c..6107108228b6 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -170,7 +170,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), -SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 18), +SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19), SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -183,7 +183,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 18), +SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19), SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -196,7 +196,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 18), +SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19), SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT, 24, 0, eq_tlv), @@ -209,7 +209,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT, SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT, 24, 0, eq_tlv), -SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 18), +SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19), SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0), SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT, 24, 0, eq_tlv), -- cgit v1.2.3 From 05cf482d7e76bb02138d6b04a94375bc9f86e927 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Mon, 20 Jan 2014 15:27:26 +0800 Subject: ASoC: fsl: use snd_soc_dai_init_dma_data() Signed-off-by: Xiubo Li Acked-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_spdif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 4d075f1abe78..8f36f49395dd 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -911,8 +911,8 @@ static int fsl_spdif_dai_probe(struct snd_soc_dai *dai) { struct fsl_spdif_priv *spdif_private = snd_soc_dai_get_drvdata(dai); - dai->playback_dma_data = &spdif_private->dma_params_tx; - dai->capture_dma_data = &spdif_private->dma_params_rx; + snd_soc_dai_init_dma_data(dai, &spdif_private->dma_params_tx, + &spdif_private->dma_params_rx); snd_soc_add_dai_controls(dai, fsl_spdif_ctrls, ARRAY_SIZE(fsl_spdif_ctrls)); -- cgit v1.2.3 From 0290d2a42cb476358303d05fbe2475dd50889907 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:37:39 -0800 Subject: ASoC: rsnd: tidyup register naming of BUSIF_MODE Gen1:SRU has only 1 BUSIF_MODE, but Gen2:SSIU/SCU has SRCm_BUSIF_MODE, and SSIn_BUSIF_MODE. This patch rename current BUSIF_MODE to SRC_BUSIF_MODE. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 2 +- sound/soc/sh/rcar/rsnd.h | 2 +- sound/soc/sh/rcar/scu.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index add088bd4b2a..cbdbbfa322b8 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -317,7 +317,7 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), - RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4), + RSND_GEN1_M_REG(gen, SRU, SRC_BUSIF_MODE, 0x20, 0x4), RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 4ca66cd899c8..f62b9eb274e1 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -39,8 +39,8 @@ enum rsnd_reg { RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, - RSND_REG_BUSIF_MODE, RSND_REG_INT_ENABLE, /* for Gen2 */ + RSND_REG_SRC_BUSIF_MODE, RSND_REG_SRC_ROUTE_MODE0, RSND_REG_SRC_SWRSR, RSND_REG_SRC_SRCIR, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 9bb08bb1d455..9b9daa3821a3 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -211,7 +211,7 @@ static int rsnd_scu_convert_rate_ctrl(struct rsnd_priv *priv, rsnd_mod_write(mod, SRC_SRCIR, 0); /* use DMA transfer */ - rsnd_mod_write(mod, BUSIF_MODE, 1); + rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); return 0; } -- cgit v1.2.3 From 92d9587ede108a7e73f80d0767aedf2c4edb47d8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:08 -0800 Subject: ASoC: rsnd: cleanup debug information method rsnd_mod debug information is implemented in each callback functions now. But, it can be implemented in rsnd_mod_call(), and share this code. This patch adds it Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 11 ++++++++++- sound/soc/sh/rcar/scu.c | 2 -- sound/soc/sh/rcar/ssi.c | 12 ------------ 3 files changed, 10 insertions(+), 15 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index f62b9eb274e1..faacdcb8f05b 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -152,10 +152,19 @@ struct rsnd_mod { #define rsnd_mod_id(mod) ((mod)->id) #define for_each_rsnd_mod(pos, n, io) \ list_for_each_entry_safe(pos, n, &(io)->head, list) +#define __rsnd_mod_call(mod, func, rdai, io) \ +({ \ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ + struct device *dev = rsnd_priv_to_dev(priv); \ + dev_dbg(dev, "%s-%d-%s\n", \ + rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ + (mod)->ops->func(mod, rdai, io); \ +}) + #define rsnd_mod_call(mod, func, rdai, io) \ (!(mod) ? -ENODEV : \ !((mod)->ops->func) ? 0 : \ - (mod)->ops->func(mod, rdai, io)) + __rsnd_mod_call(mod, func, rdai, io)) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 9b9daa3821a3..e4b82ab31dca 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -300,8 +300,6 @@ static int rsnd_scu_start(struct rsnd_mod *mod, if (ret < 0) return ret; - dev_dbg(dev, "%s%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 4b8cf7ca9d19..df775f0c8a2c 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -324,7 +324,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 cr; @@ -371,8 +370,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, rsnd_ssi_mode_set(priv, rdai, ssi); - dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - return 0; } @@ -384,8 +381,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); - dev_dbg(dev, "%s.%d quit\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - if (ssi->err > 0) dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); @@ -450,7 +445,6 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - struct device *dev = rsnd_priv_to_dev(priv); /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; @@ -461,8 +455,6 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, rsnd_ssi_hw_start(ssi, rdai, io); - dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - return 0; } @@ -470,12 +462,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - dev_dbg(dev, "%s.%d stop\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - ssi->cr_etc = 0; rsnd_ssi_hw_stop(ssi, rdai); -- cgit v1.2.3 From 6acef1721c1046be8b5f44b839c28817cfbd66c6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:17 -0800 Subject: ASoC: rsnd: remove meaningless rsnd_ssi_non() rsnd_ssi_non_ops callback functions are never called. remove these meaningless callback Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index df775f0c8a2c..ef3d45045d1f 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -555,24 +555,8 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { /* * Non SSI */ -static int rsnd_ssi_non(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); - - dev_dbg(dev, "%s\n", __func__); - - return 0; -} - static struct rsnd_mod_ops rsnd_ssi_non_ops = { .name = "ssi (non)", - .init = rsnd_ssi_non, - .quit = rsnd_ssi_non, - .start = rsnd_ssi_non, - .stop = rsnd_ssi_non, }; /* -- cgit v1.2.3 From 013f38fe260af6f505ad5da5f6b0db3e42ca1fbb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:26 -0800 Subject: ASoC: rsnd: control SCU ops in probe timing SCU will be used if platform requested to use. Current driver is checking it in runtime, but, it can be decided in probe timing. This patch do it Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index e4b82ab31dca..ab5f1d21731e 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -270,24 +270,10 @@ static int rsnd_scu_start(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct device *dev = rsnd_priv_to_dev(priv); int ret; - /* - * SCU will be used if it has RSND_SCU_USE_HPBIF flags - */ - if (!rsnd_scu_hpbif_is_enable(mod)) { - /* it use PIO transter */ - dev_dbg(dev, "%s%d is not used\n", - rsnd_mod_name(mod), rsnd_mod_id(mod)); - - return 0; - } - clk_enable(scu->clk); - /* it use DMA transter */ - ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io); if (ret < 0) return ret; @@ -310,9 +296,6 @@ static int rsnd_scu_stop(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - if (!rsnd_scu_hpbif_is_enable(mod)) - return 0; - rsnd_scu_transfer_stop(priv, mod, rdai, io); clk_disable(scu->clk); @@ -326,6 +309,10 @@ static struct rsnd_mod_ops rsnd_scu_ops = { .stop = rsnd_scu_stop, }; +static struct rsnd_mod_ops rsnd_scu_non_ops = { + .name = "scu (non)", +}; + struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) { if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) @@ -340,6 +327,7 @@ int rsnd_scu_probe(struct platform_device *pdev, { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_scu *scu; + struct rsnd_mod_ops *ops; struct clk *clk; char name[RSND_SCU_NAME_SIZE]; int i, nr; @@ -364,11 +352,15 @@ int rsnd_scu_probe(struct platform_device *pdev, if (IS_ERR(clk)) return PTR_ERR(clk); - rsnd_mod_init(priv, &scu->mod, - &rsnd_scu_ops, i); scu->info = &info->scu_info[i]; scu->clk = clk; + ops = &rsnd_scu_non_ops; + if (rsnd_scu_hpbif_is_enable(&scu->mod)) + ops = &rsnd_scu_ops; + + rsnd_mod_init(priv, &scu->mod, ops, i); + dev_dbg(dev, "SCU%d probed\n", i); } dev_dbg(dev, "scu probed\n"); -- cgit v1.2.3 From a204d90c91208d9b63ba309a1c44f582751e58c9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:33 -0800 Subject: ASoC: rsnd: add rsnd_scu_init(), and separate init/start Current scu.c has rsnd_scu_start(), and, operation of initialization/start are implemented in this function. This patch adds new rsnd_scu_init() and separates rsnd_scu_start(), since rsnd_mod_ops has .init/.start callbacks. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index ab5f1d21731e..e1e08738b9d4 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -264,7 +264,7 @@ bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) return !!(flags & RSND_SCU_USE_HPBIF); } -static int rsnd_scu_start(struct rsnd_mod *mod, +static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { @@ -282,13 +282,30 @@ static int rsnd_scu_start(struct rsnd_mod *mod, if (ret < 0) return ret; - ret = rsnd_scu_transfer_start(priv, mod, rdai, io); - if (ret < 0) - return ret; + return 0; +} + +static int rsnd_scu_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + clk_disable(scu->clk); return 0; } +static int rsnd_scu_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + return rsnd_scu_transfer_start(priv, mod, rdai, io); +} + static int rsnd_scu_stop(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -298,13 +315,13 @@ static int rsnd_scu_stop(struct rsnd_mod *mod, rsnd_scu_transfer_stop(priv, mod, rdai, io); - clk_disable(scu->clk); - return 0; } static struct rsnd_mod_ops rsnd_scu_ops = { .name = "scu", + .init = rsnd_scu_init, + .quit = rsnd_scu_quit, .start = rsnd_scu_start, .stop = rsnd_scu_stop, }; -- cgit v1.2.3 From 47718dc7d8ca5f5509ac9beb13486642306bb36b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:42 -0800 Subject: ASoC: rsnd: remove meaningless function parameter struct rsnd_priv *priv on rsnd_scu_init/start/stop() are no longer needed Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index e1e08738b9d4..ece539b758d1 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -50,7 +50,7 @@ struct rsnd_scu { i++) /* Gen1 only */ -static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, +static int rsnd_src_set_route_if_gen1( struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -69,6 +69,7 @@ static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, { 0x3, 28, }, /* 7 */ { 0x3, 30, }, /* 8 */ }; + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); u32 mask; u32 val; @@ -149,11 +150,12 @@ unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, return rate; } -static int rsnd_scu_convert_rate_ctrl(struct rsnd_priv *priv, +static int rsnd_scu_convert_rate_ctrl( struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); u32 convert_rate = rsnd_scu_convert_rate(scu); @@ -268,17 +270,16 @@ static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int ret; clk_enable(scu->clk); - ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io); + ret = rsnd_src_set_route_if_gen1(mod, rdai, io); if (ret < 0) return ret; - ret = rsnd_scu_convert_rate_ctrl(priv, mod, rdai, io); + ret = rsnd_scu_convert_rate_ctrl(mod, rdai, io); if (ret < 0) return ret; -- cgit v1.2.3 From e7ce74eaa76591e5a4905d0fc07a278533447b80 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:50 -0800 Subject: ASoC: rsnd: merge rsnd_scu_start/stop() and rsnd_scu_transfer_start/stop() rsnd_scu_transfer_start/stop() are no longer needed. merge into rsnd_scu_start/stop() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 56 +++++++++++++------------------------------------ 1 file changed, 14 insertions(+), 42 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index ece539b758d1..5d2dbbbf9d98 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -218,46 +218,6 @@ static int rsnd_scu_convert_rate_ctrl( return 0; } -static int rsnd_scu_transfer_start(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); - u32 val; - - if (rsnd_is_gen1(priv)) { - val = (1 << id); - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, val, val); - } - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); - - return 0; -} - -static int rsnd_scu_transfer_stop(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); - u32 mask; - - if (rsnd_is_gen1(priv)) { - mask = (1 << id); - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, mask, 0); - } - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); - - return 0; -} - bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) { struct rsnd_scu *scu = rsnd_mod_to_scu(mod); @@ -303,8 +263,15 @@ static int rsnd_scu_start(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int id = rsnd_mod_id(mod); - return rsnd_scu_transfer_start(priv, mod, rdai, io); + if (rsnd_is_gen1(priv)) + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); + + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + + return 0; } static int rsnd_scu_stop(struct rsnd_mod *mod, @@ -313,8 +280,13 @@ static int rsnd_scu_stop(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int id = rsnd_mod_id(mod); + + if (rsnd_is_gen1(priv)) + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); - rsnd_scu_transfer_stop(priv, mod, rdai, io); + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); return 0; } -- cgit v1.2.3 From e779a20da90b12d17af74fe544fafd814b66dc63 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:12 -0800 Subject: ASoC: rsnd: rsnd_dai_is_clk_master() can be shared Current rsnd driver is using ssi local rsnd_rdai_is_clk_master() for checking clock master. But it can be rsnd_dai_is_clk_master(), and share in each file Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 1 + sound/soc/sh/rcar/ssi.c | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index faacdcb8f05b..cd396dda85c5 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -215,6 +215,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); +#define rsnd_dai_is_clk_master(rdai) ((rdai)->clk_master) /* * R-Car Gen1/Gen2 diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index ef3d45045d1f..ddcca067908c 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -95,7 +95,6 @@ struct rsnd_ssiu { #define rsnd_ssi_dma_available(ssi) \ rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod)) #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) -#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master) #define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) #define rsnd_ssi_to_ssiu(ssi)\ @@ -133,7 +132,7 @@ static void rsnd_ssi_mode_set(struct rsnd_priv *priv, #define ssi_parent_set(p, sync, adg, ext) \ do { \ ssi->parent = ssiu->ssi + p; \ - if (rsnd_rdai_is_clk_master(rdai)) \ + if (rsnd_dai_is_clk_master(rdai)) \ val = adg; \ else \ val = ext; \ @@ -252,7 +251,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, if (0 == ssi->usrcnt) { clk_enable(ssi->clk); - if (rsnd_rdai_is_clk_master(rdai)) { + if (rsnd_dai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_start(ssi->parent, rdai, io); else @@ -302,7 +301,7 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */ rsnd_ssi_status_check(&ssi->mod, IIRQ); - if (rsnd_rdai_is_clk_master(rdai)) { + if (rsnd_dai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_stop(ssi->parent, rdai); else @@ -522,7 +521,7 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, rsnd_ssi_hw_start(ssi, ssi->rdai, io); /* enable WS continue */ - if (rsnd_rdai_is_clk_master(rdai)) + if (rsnd_dai_is_clk_master(rdai)) rsnd_mod_write(&ssi->mod, SSIWSR, CONT); return 0; -- cgit v1.2.3 From 6f3ab6c1c022e7a4877d38940cd45ae7804a15e2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:23 -0800 Subject: ASoC: rsnd: remove pin sync option Renesas Chip is supporting multi pin sound, but the HW setting is very difficult and confusable. But driver is supporting it halfway. Remove SYNC option at this point. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 1 + sound/soc/sh/rcar/ssi.c | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 6add6ccc811e..1d19bfc2486d 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -35,6 +35,7 @@ */ #define RSND_SSI_CLK_PIN_SHARE (1 << 31) #define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */ +#define RSND_SSI_CLK_FROM_ADG (1 << 30) /* clock parent is master */ #define RSND_SSI_PLAY (1 << 24) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index ddcca067908c..68393a9f91bf 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -136,8 +136,6 @@ static void rsnd_ssi_mode_set(struct rsnd_priv *priv, val = adg; \ else \ val = ext; \ - if (flags & RSND_SSI_SYNC) \ - val |= sync; \ } while (0) flags = rsnd_ssi_mode_flags(ssi); -- cgit v1.2.3 From 7b5ce9759a60ebdffa1e76224ccb3d85bd06e4ac Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:32 -0800 Subject: ASoC: rsnd: SSI_MODE0/1 settings goes to scu.c SRU (Gen1) / SCU (Gen2) / SSIU (Gen2) are controlled under scu.c. (SCU + SSIU (Gen2) was SRU (Gen1)) And register of SSI_MODE0/1 are mapped on these IP. But these have been implemented under ssi.c on this driver. The naming is very confusable, but it should be implemented under scu.c Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 1 + sound/soc/sh/rcar/scu.c | 45 ++++++++++++++++++++++ sound/soc/sh/rcar/ssi.c | 98 ++++++++++++++---------------------------------- 3 files changed, 74 insertions(+), 70 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index cd396dda85c5..85b926229b81 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -321,5 +321,6 @@ void rsnd_ssi_remove(struct platform_device *pdev, struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play); +int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); #endif diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 5d2dbbbf9d98..ade10474a0cf 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -49,6 +49,46 @@ struct rsnd_scu { ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ i++) +static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + int id = rsnd_mod_id(mod); + + /* + * SSI_MODE0 + */ + rsnd_mod_bset(mod, SSI_MODE0, (1 << id), + rsnd_scu_hpbif_is_enable(mod) ? 0 : (1 << id)); + + /* + * SSI_MODE1 + */ + if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { + int shift = -1; + switch (id) { + case 1: + shift = 0; + break; + case 2: + shift = 2; + break; + case 4: + shift = 16; + break; + } + + if (shift >= 0) + rsnd_mod_bset(mod, SSI_MODE1, + 0x3 << shift, + rsnd_dai_is_clk_master(rdai) ? + 0x2 << shift : 0x1 << shift); + } + + return 0; +} + /* Gen1 only */ static int rsnd_src_set_route_if_gen1( struct rsnd_mod *mod, @@ -235,6 +275,10 @@ static int rsnd_scu_init(struct rsnd_mod *mod, clk_enable(scu->clk); + ret = rsnd_scu_ssi_mode_init(mod, rdai, io); + if (ret < 0) + return ret; + ret = rsnd_src_set_route_if_gen1(mod, rdai, io); if (ret < 0) return ret; @@ -301,6 +345,7 @@ static struct rsnd_mod_ops rsnd_scu_ops = { static struct rsnd_mod_ops rsnd_scu_non_ops = { .name = "scu (non)", + .init = rsnd_scu_ssi_mode_init, }; struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 68393a9f91bf..0f314db8cb50 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -75,9 +75,6 @@ struct rsnd_ssi { }; struct rsnd_ssiu { - u32 ssi_mode0; - u32 ssi_mode1; - int ssi_nr; struct rsnd_ssi *ssi; }; @@ -100,70 +97,6 @@ struct rsnd_ssiu { #define rsnd_ssi_to_ssiu(ssi)\ (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1) -static void rsnd_ssi_mode_set(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_ssi *ssi) -{ - struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_mod *scu; - struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi); - int id = rsnd_mod_id(&ssi->mod); - u32 flags; - u32 val; - - scu = rsnd_scu_mod_get(priv, rsnd_mod_id(&ssi->mod)); - - /* - * SSI_MODE0 - */ - - /* see also BUSIF_MODE */ - if (rsnd_scu_hpbif_is_enable(scu)) { - ssiu->ssi_mode0 &= ~(1 << id); - dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", id); - } else { - ssiu->ssi_mode0 |= (1 << id); - dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", id); - } - - /* - * SSI_MODE1 - */ -#define ssi_parent_set(p, sync, adg, ext) \ - do { \ - ssi->parent = ssiu->ssi + p; \ - if (rsnd_dai_is_clk_master(rdai)) \ - val = adg; \ - else \ - val = ext; \ - } while (0) - - flags = rsnd_ssi_mode_flags(ssi); - if (flags & RSND_SSI_CLK_PIN_SHARE) { - - val = 0; - switch (id) { - case 1: - ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0)); - break; - case 2: - ssi_parent_set(0, (1 << 4), (0x2 << 2), (0x1 << 2)); - break; - case 4: - ssi_parent_set(3, (1 << 20), (0x2 << 16), (0x1 << 16)); - break; - case 8: - ssi_parent_set(7, 0, 0, 0); - break; - } - - ssiu->ssi_mode1 |= val; - } - - rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0); - rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1); -} - static void rsnd_ssi_status_check(struct rsnd_mod *mod, u32 bit) { @@ -320,7 +253,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 cr; @@ -365,8 +297,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ - rsnd_ssi_mode_set(priv, rdai, ssi); - return 0; } @@ -588,6 +518,32 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod; } +int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) +{ + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + + return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); +} + +static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) +{ + if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) + return; + + switch (rsnd_mod_id(&ssi->mod)) { + case 1: + case 2: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 0)); + break; + case 4: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 3)); + break; + case 8: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 7)); + break; + } +} + int rsnd_ssi_probe(struct platform_device *pdev, struct rcar_snd_info *info, struct rsnd_priv *priv) @@ -668,6 +624,8 @@ int rsnd_ssi_probe(struct platform_device *pdev, } rsnd_mod_init(priv, &ssi->mod, ops, i); + + rsnd_ssi_parent_clk_setup(priv, ssi); } dev_dbg(dev, "ssi probed\n"); -- cgit v1.2.3 From dd27d808f9e084e7e9c4719c17f17d1fa35c45a6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:40 -0800 Subject: ASoC: rsnd: remove ssiu from ssi.c Now, SSI_MODE0/1 are controlled under scu.c ssiu is no longer needed on ssi.c Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 3 ++- sound/soc/sh/rcar/ssi.c | 24 +++++++----------------- 2 files changed, 9 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 85b926229b81..e92b1f438f74 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -280,7 +280,8 @@ struct rsnd_priv { /* * below value will be filled on rsnd_ssi_probe() */ - void *ssiu; + void *ssi; + int ssi_nr; /* * below value will be filled on rsnd_dai_probe() diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 0f314db8cb50..dc72439da58d 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -74,18 +74,13 @@ struct rsnd_ssi { unsigned int rate; }; -struct rsnd_ssiu { - int ssi_nr; - struct rsnd_ssi *ssi; -}; - #define for_each_rsnd_ssi(pos, priv, i) \ for (i = 0; \ (i < rsnd_ssi_nr(priv)) && \ - ((pos) = ((struct rsnd_ssiu *)((priv)->ssiu))->ssi + i); \ + ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \ i++) -#define rsnd_ssi_nr(priv) (((struct rsnd_ssiu *)((priv)->ssiu))->ssi_nr) +#define rsnd_ssi_nr(priv) ((priv)->ssi_nr) #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) #define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0) @@ -94,8 +89,6 @@ struct rsnd_ssiu { #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) #define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) -#define rsnd_ssi_to_ssiu(ssi)\ - (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1) static void rsnd_ssi_status_check(struct rsnd_mod *mod, u32 bit) @@ -515,7 +508,7 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv))) id = 0; - return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod; + return &((struct rsnd_ssi *)(priv->ssi) + id)->mod; } int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) @@ -552,7 +545,6 @@ int rsnd_ssi_probe(struct platform_device *pdev, struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod_ops *ops; struct clk *clk; - struct rsnd_ssiu *ssiu; struct rsnd_ssi *ssi; char name[RSND_SSI_NAME_SIZE]; int i, nr, ret; @@ -561,16 +553,14 @@ int rsnd_ssi_probe(struct platform_device *pdev, * init SSI */ nr = info->ssi_info_nr; - ssiu = devm_kzalloc(dev, sizeof(*ssiu) + (sizeof(*ssi) * nr), - GFP_KERNEL); - if (!ssiu) { + ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL); + if (!ssi) { dev_err(dev, "SSI allocate failed\n"); return -ENOMEM; } - priv->ssiu = ssiu; - ssiu->ssi = (struct rsnd_ssi *)(ssiu + 1); - ssiu->ssi_nr = nr; + priv->ssi = ssi; + priv->ssi_nr = nr; for_each_rsnd_ssi(ssi, priv, i) { pinfo = &info->ssi_info[i]; -- cgit v1.2.3 From f80e1c96339a45992b5dded0474288e52bd3b18d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:48 -0800 Subject: ASoC: rsnd: rename rsnd_scu_convert_rate_ctrl() rsnd_scu_convert_rate_ctrl() is unclear naming, and there is "rsnd_scu_convert_rate" variable. These are confusable. it renamed to rsnd_scu_set_convert_rate() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index ade10474a0cf..872a115cd224 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -190,10 +190,9 @@ unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, return rate; } -static int rsnd_scu_convert_rate_ctrl( - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); @@ -283,7 +282,7 @@ static int rsnd_scu_init(struct rsnd_mod *mod, if (ret < 0) return ret; - ret = rsnd_scu_convert_rate_ctrl(mod, rdai, io); + ret = rsnd_scu_set_convert_rate(mod, rdai, io); if (ret < 0) return ret; -- cgit v1.2.3 From 41c6221c39accdc4fe2b0c0fa196b6302b704e57 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:56 -0800 Subject: ASoC: rsnd: explain SRC bypass mode settings in comment SRC bypass mode is useful for debugging. This patch explains SRC bypass mode settings in comment Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 872a115cd224..076aa71bc102 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -40,6 +40,51 @@ struct rsnd_scu { * */ +/* + * How to use SRC bypass mode for debugging + * + * SRC has bypass mode, and it is useful for debugging. + * In Gen2 case, + * SRCm_MODE controls whether SRC is used or not + * SSI_MODE0 controls whether SSIU which receives SRC data + * is used or not. + * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, + * but SRC bypass mode needs SSI_MODE0 only. + * + * This driver request + * struct rsnd_scu_platform_info { + * u32 flags; + * u32 convert_rate; + * } + * + * rsnd_scu_hpbif_is_enable() will be true + * if flags had RSND_SCU_USE_HPBIF, + * and it controls whether SSIU is used or not. + * + * rsnd_scu_convert_rate() indicates + * above convert_rate, and it controls + * whether SRC is used or not. + * + * ex) doesn't use SRC + * struct rsnd_scu_platform_info info = { + * .flags = 0, + * .convert_rate = 0, + * }; + * + * ex) uses SRC + * struct rsnd_scu_platform_info info = { + * .flags = RSND_SCU_USE_HPBIF, + * .convert_rate = 48000, + * }; + * + * ex) uses SRC bypass mode + * struct rsnd_scu_platform_info info = { + * .flags = RSND_SCU_USE_HPBIF, + * .convert_rate = 0, + * }; + * + */ + #define rsnd_mod_to_scu(_mod) \ container_of((_mod), struct rsnd_scu, mod) -- cgit v1.2.3 From 9b5ab573a81b9ac0df90b74d732651fdf8b24525 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:03 -0800 Subject: ASoC: rsnd: remove duplicate *priv from rsnd_dma *priv pointer exists under rsnd_mod, and, it can get rsnd_mod pointer from rsnd_dma. remove duplicate rsnd_dma :: priv Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 5 ++--- sound/soc/sh/rcar/rsnd.h | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 743de5e3b1e1..ed8611f9c64f 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -156,7 +156,7 @@ void rsnd_dma_stop(struct rsnd_dma *dma) static void rsnd_dma_complete(void *data) { struct rsnd_dma *dma = (struct rsnd_dma *)data; - struct rsnd_priv *priv = dma->priv; + struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); unsigned long flags; rsnd_lock(priv, flags); @@ -172,7 +172,7 @@ static void rsnd_dma_complete(void *data) static void rsnd_dma_do_work(struct work_struct *work) { struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); - struct rsnd_priv *priv = dma->priv; + struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; dma_addr_t buf; @@ -246,7 +246,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, goto rsnd_dma_init_err; dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - dma->priv = priv; dma->inquiry = inquiry; dma->complete = complete; INIT_WORK(&dma->work, rsnd_dma_do_work); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index e92b1f438f74..33c01fb9f5fd 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -96,7 +96,6 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, * R-Car DMA */ struct rsnd_dma { - struct rsnd_priv *priv; struct sh_dmae_slave slave; struct work_struct work; struct dma_chan *chan; -- cgit v1.2.3 From 106d2eff563b2abdb34872cb8ec7b19766edaffc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:13 -0800 Subject: ASoC: rsnd: non 0 is error on probe Some xxx_probe() returns not only -Exx, but also PTR_ERR(). Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ed8611f9c64f..4fd57351c54a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -737,23 +737,23 @@ static int rsnd_probe(struct platform_device *pdev) * init each module */ ret = rsnd_gen_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_scu_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_adg_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_ssi_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_dai_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; /* -- cgit v1.2.3 From 64de62b38641dec05905930024133726c540040e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:20 -0800 Subject: ASoC: rsnd: fixup Gen2 module naming Gen2 has SCU, not SRU Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index cbdbbfa322b8..76828c20fb50 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -283,7 +283,7 @@ static int rsnd_gen2_probe(struct platform_device *pdev, return ret; dev_dbg(dev, "Gen2 device probed\n"); - dev_dbg(dev, "SRU : %08x => %p\n", scu_res->start, + dev_dbg(dev, "SCU : %08x => %p\n", scu_res->start, gen->base[RSND_GEN2_SCU]); dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, gen->base[RSND_GEN2_ADG]); -- cgit v1.2.3 From f5cab3b8976d59c6166228874a5af3d87c94c723 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:27 -0800 Subject: ASoC: rsnd: don't use schedule_work() when rsnd_dma_start() rsnd_dma_start() is the function to start DMAEngine. Current code is using schedule_work() for it, but it breaks DMAC/SSI register setting timing. Don't use schedule_work() on it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 4fd57351c54a..11eb0e35b9ce 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -132,6 +132,7 @@ void rsnd_mod_init(struct rsnd_priv *priv, /* * rsnd_dma functions */ +static void __rsnd_dma_start(struct rsnd_dma *dma); static void rsnd_dma_continue(struct rsnd_dma *dma) { /* push next A or B plane */ @@ -143,7 +144,7 @@ void rsnd_dma_start(struct rsnd_dma *dma) { /* push both A and B plane*/ dma->submit_loop = 2; - schedule_work(&dma->work); + __rsnd_dma_start(dma); } void rsnd_dma_stop(struct rsnd_dma *dma) @@ -169,9 +170,8 @@ static void rsnd_dma_complete(void *data) rsnd_unlock(priv, flags); } -static void rsnd_dma_do_work(struct work_struct *work) +static void __rsnd_dma_start(struct rsnd_dma *dma) { - struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; @@ -204,6 +204,13 @@ static void rsnd_dma_do_work(struct work_struct *work) } } +static void rsnd_dma_do_work(struct work_struct *work) +{ + struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); + + __rsnd_dma_start(dma); +} + int rsnd_dma_available(struct rsnd_dma *dma) { return !!dma->chan; -- cgit v1.2.3 From be213ac1af893410eb8256010edf136b4099e827 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:34 -0800 Subject: ASoC: rsnd: SCU should be called before SSI Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 76828c20fb50..db486aae6b8b 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -182,14 +182,14 @@ int rsnd_gen_path_init(struct rsnd_priv *priv, rsnd_dai_is_play(rdai, io)); id = rsnd_mod_id(mod); - /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); + /* SCU */ + mod = rsnd_scu_mod_get(priv, id); ret = rsnd_dai_connect(rdai, mod, io); if (ret < 0) return ret; - /* SCU */ - mod = rsnd_scu_mod_get(priv, id); + /* SSI */ + mod = rsnd_ssi_mod_get(priv, id); ret = rsnd_dai_connect(rdai, mod, io); return ret; -- cgit v1.2.3 From c926b746055adfd915936c67244e635e9c7a3d84 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:41 -0800 Subject: ASoC: rsnd: clarify scu.c area scu.c cares SRU(Gen1) / SCU(Gen2) / SSIU(Gen2) Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 076aa71bc102..1adc85825f4e 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -40,6 +40,20 @@ struct rsnd_scu { * */ +/* + * scu.c is caring... + * + * Gen1 + * + * [mem] -> [SRU] -> [SSI] + * |--------| + * + * Gen2 + * + * [mem] -> [SCU] -> [SSIU] -> [SSI] + * |-----------------| + */ + /* * How to use SRC bypass mode for debugging * -- cgit v1.2.3 From 39cf3c4064b8db25efe501fec8e3c48a578b4b58 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:47 -0800 Subject: ASoC: rsnd: Merge macros in scu.c Merge #define lines, since these are defined in the scattering place Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 1adc85825f4e..8181ec55ad21 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -16,9 +16,6 @@ struct rsnd_scu { struct clk *clk; }; -#define rsnd_scu_mode_flags(p) ((p)->info->flags) -#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) - #define RSND_SCU_NAME_SIZE 16 /* @@ -30,6 +27,18 @@ struct rsnd_scu { #define OTBL_18 (6 << 16) #define OTBL_16 (8 << 16) +#define rsnd_scu_mode_flags(p) ((p)->info->flags) +#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) +#define rsnd_mod_to_scu(_mod) \ + container_of((_mod), struct rsnd_scu, mod) + +#define for_each_rsnd_scu(pos, priv, i) \ + for ((i) = 0; \ + ((i) < rsnd_scu_nr(priv)) && \ + ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ + i++) + + /* * image of SRC (Sampling Rate Converter) * @@ -99,15 +108,6 @@ struct rsnd_scu { * */ -#define rsnd_mod_to_scu(_mod) \ - container_of((_mod), struct rsnd_scu, mod) - -#define for_each_rsnd_scu(pos, priv, i) \ - for ((i) = 0; \ - ((i) < rsnd_scu_nr(priv)) && \ - ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ - i++) - static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) -- cgit v1.2.3 From 96c7c0d6f8c6e09e9123f0518130c047c5de40f6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:54 -0800 Subject: ASoC: rsnd: rsnd_scu_hpbif_is_enable() become macro rsnd_scu_hpbif_is_enable() is used only scu.c now. It can be local macro Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 1 - sound/soc/sh/rcar/scu.c | 15 +++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 33c01fb9f5fd..a9c58305e2f1 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -303,7 +303,6 @@ int rsnd_scu_probe(struct platform_device *pdev, void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv); struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); -bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_mod *ssi_mod, struct snd_pcm_runtime *runtime); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 8181ec55ad21..2f839f72c99c 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -31,6 +31,8 @@ struct rsnd_scu { #define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) #define rsnd_mod_to_scu(_mod) \ container_of((_mod), struct rsnd_scu, mod) +#define rsnd_scu_hpbif_is_enable(scu) \ + (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) #define for_each_rsnd_scu(pos, priv, i) \ for ((i) = 0; \ @@ -113,13 +115,14 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int id = rsnd_mod_id(mod); /* * SSI_MODE0 */ rsnd_mod_bset(mod, SSI_MODE0, (1 << id), - rsnd_scu_hpbif_is_enable(mod) ? 0 : (1 << id)); + rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << id)); /* * SSI_MODE1 @@ -316,14 +319,6 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, return 0; } -bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 flags = rsnd_scu_mode_flags(scu); - - return !!(flags & RSND_SCU_USE_HPBIF); -} - static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -449,7 +444,7 @@ int rsnd_scu_probe(struct platform_device *pdev, scu->clk = clk; ops = &rsnd_scu_non_ops; - if (rsnd_scu_hpbif_is_enable(&scu->mod)) + if (rsnd_scu_hpbif_is_enable(scu)) ops = &rsnd_scu_ops; rsnd_mod_init(priv, &scu->mod, ops, i); -- cgit v1.2.3 From 28dc4b63cdb96f2448a677320fcc0eb112e13e3f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:10 -0800 Subject: ASoC: rsnd: merge SRC clock timing/setting SRC clock and timing setting register exist in SRU and ADG on Gen1. But, these are merged into ADG on Gen2. Current driver is supporting Gen1 SRC only at this point, but, above settings are set as different function. This patch merges these as preparation of Gen2 support. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 20 ++++---------------- sound/soc/sh/rcar/rsnd.h | 8 ++++---- sound/soc/sh/rcar/scu.c | 48 +++++++++++++++++++++++++++++++++++------------- 3 files changed, 43 insertions(+), 33 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index a53235c4d1b0..5bdffa480245 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -30,10 +30,10 @@ struct rsnd_adg { i++, (pos) = adg->clk[i]) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) -static int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate) +int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, + struct rsnd_mod *mod, + unsigned int src_rate, + unsigned int dst_rate) { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); @@ -91,18 +91,6 @@ find_rate: return 0; } -int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate) -{ - if (rsnd_is_gen1(priv)) - return rsnd_adg_set_convert_clk_gen1(priv, mod, - src_rate, dst_rate); - - return -EINVAL; -} - static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) { int id = rsnd_mod_id(mod); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index a9c58305e2f1..39914558e857 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -246,10 +246,10 @@ int rsnd_adg_probe(struct platform_device *pdev, struct rsnd_priv *priv); void rsnd_adg_remove(struct platform_device *pdev, struct rsnd_priv *priv); -int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate); +int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, + struct rsnd_mod *mod, + unsigned int src_rate, + unsigned int dst_rate); /* * R-Car sound priv diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 2f839f72c99c..e2ffcc415057 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -172,10 +172,8 @@ static int rsnd_src_set_route_if_gen1( { 0x3, 30, }, /* 8 */ }; struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); u32 mask; u32 val; - int shift; int id; /* @@ -197,6 +195,23 @@ static int rsnd_src_set_route_if_gen1( rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); + return 0; +} + +static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + u32 convert_rate = rsnd_scu_convert_rate(scu); + u32 mask; + u32 val; + int shift; + int id = rsnd_mod_id(mod); + int ret; + /* * SRC_TIMING_SELECT */ @@ -209,12 +224,23 @@ static int rsnd_src_set_route_if_gen1( * SSI WS is used as source clock if SRC is not used * (when playback, source/destination become reverse when capture) */ - if (rsnd_scu_convert_rate(scu)) /* use ADG */ + ret = 0; + if (convert_rate) { + /* use ADG */ val = 0; - else if (8 == id) /* use SSI WS, but SRU8 is special */ + ret = rsnd_adg_set_convert_clk_gen1(priv, mod, + runtime->rate, + convert_rate); + } else if (8 == id) { + /* use SSI WS, but SRU8 is special */ val = id << shift; - else /* use SSI WS */ + } else { + /* use SSI WS */ val = (id + 1) << shift; + } + + if (ret < 0) + return ret; switch (id / 4) { case 0: @@ -284,7 +310,6 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, if (convert_rate) { u32 fsrate = 0x0400000 / convert_rate * runtime->rate; - int ret; /* Enable the initial value of IFS */ rsnd_mod_write(mod, SRC_IFSCR, 1); @@ -301,13 +326,6 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, if (rsnd_is_gen1(priv)) { /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ } - - /* set convert clock */ - ret = rsnd_adg_set_convert_clk(priv, mod, - runtime->rate, - convert_rate); - if (ret < 0) - return ret; } /* Cancel the initialization and operate the SRC function */ @@ -340,6 +358,10 @@ static int rsnd_scu_init(struct rsnd_mod *mod, if (ret < 0) return ret; + ret = rsnd_scu_set_convert_timing_gen1(mod, rdai, io); + if (ret < 0) + return ret; + return 0; } -- cgit v1.2.3 From 32f27ebf9b625df610c12408ea15bae37be75eaf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:17 -0800 Subject: ASoC: rsnd: add rsnd_ssi_is_play() SCU needs SSI direction if Gen2. Add rsnd_ssi_is_play() function for it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 1 + sound/soc/sh/rcar/ssi.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 39914558e857..b1874eb71436 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -321,5 +321,6 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play); int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); +int rsnd_ssi_is_play(struct rsnd_mod *mod); #endif diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index dc72439da58d..bae309c9f0fb 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -494,7 +494,7 @@ struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, if (rsnd_ssi_dai_id(ssi) != dai_id) continue; - has_play = !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); + has_play = rsnd_ssi_is_play(&ssi->mod); if (is_play == has_play) return &ssi->mod; @@ -518,6 +518,13 @@ int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); } +int rsnd_ssi_is_play(struct rsnd_mod *mod) +{ + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + + return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); +} + static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) { if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) @@ -582,7 +589,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, if (pinfo->dma_id > 0) { ret = rsnd_dma_init( priv, rsnd_mod_to_dma(&ssi->mod), - (rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY), + rsnd_ssi_is_play(&ssi->mod), pinfo->dma_id, rsnd_ssi_dma_inquiry, rsnd_ssi_dma_complete); -- cgit v1.2.3 From 1b7b08efbe7419cc3e082f2b5ec8ae89f7af43d1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:36 -0800 Subject: ASoC: rsnd: extracts Gen1/Gen2 common parts Renesas sound IP Gen1/Gen2 are similar, but different. This patch extracts Gen1/Gen2 common and dependency parts, and create Gen1/Gen2 ops to control it. According to this structure, SSIU setup which has been implemented on ssi.c can be moved to scu.c (SRU/SSIU/SCU should be implemented on scu.c) Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 2 +- sound/soc/sh/rcar/scu.c | 336 ++++++++++++++++++++++++++++------------------- sound/soc/sh/rcar/ssi.c | 5 - 3 files changed, 205 insertions(+), 138 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b1874eb71436..c397dc8edee5 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -48,7 +48,7 @@ enum rsnd_reg { RSND_REG_SRC_IFSCR, RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, - RSND_REG_SRC_MNFSR, + RSND_REG_SRC_MNFSR, /* for Gen1 */ /* ADG */ RSND_REG_BRRA, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index e2ffcc415057..29d8990e3f0f 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -110,6 +110,9 @@ struct rsnd_scu { * */ +/* + * Gen1/Gen2 common functions + */ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -151,11 +154,145 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, return 0; } -/* Gen1 only */ -static int rsnd_src_set_route_if_gen1( - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, + struct rsnd_mod *ssi_mod, + struct snd_pcm_runtime *runtime) +{ + struct rsnd_scu *scu; + unsigned int rate; + + /* this function is assuming SSI id = SCU id here */ + scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); + + /* + * return convert rate if SRC is used, + * otherwise, return runtime->rate as usual + */ + rate = rsnd_scu_convert_rate(scu); + if (!rate) + rate = runtime->rate; + + return rate; +} + +static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + u32 convert_rate = rsnd_scu_convert_rate(scu); + u32 adinr = runtime->channels; + u32 fsrate = 0; + + if (convert_rate) + fsrate = 0x0400000 / convert_rate * runtime->rate; + + /* set/clear soft reset */ + rsnd_mod_write(mod, SRC_SWRSR, 0); + rsnd_mod_write(mod, SRC_SWRSR, 1); + + /* + * Initialize the operation of the SRC internal circuits + * see rsnd_scu_start() + */ + rsnd_mod_write(mod, SRC_SRCIR, 1); + + /* Set channel number and output bit length */ + switch (runtime->sample_bits) { + case 16: + adinr |= OTBL_16; + break; + case 32: + adinr |= OTBL_24; + break; + default: + return -EIO; + } + rsnd_mod_write(mod, SRC_ADINR, adinr); + + /* Enable the initial value of IFS */ + if (fsrate) { + rsnd_mod_write(mod, SRC_IFSCR, 1); + + /* Set initial value of IFS */ + rsnd_mod_write(mod, SRC_IFSVR, fsrate); + } + + /* use DMA transfer */ + rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); + + return 0; +} + +static int rsnd_scu_init(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int ret; + + clk_enable(scu->clk); + + ret = rsnd_scu_ssi_mode_init(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_scu_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + clk_disable(scu->clk); + + return 0; +} + +static int rsnd_scu_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + /* + * Cancel the initialization and operate the SRC function + * see rsnd_scu_set_convert_rate() + */ + rsnd_mod_write(mod, SRC_SRCIR, 0); + + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + + return 0; +} + + +static int rsnd_scu_stop(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); + + return 0; +} + +static struct rsnd_mod_ops rsnd_scu_non_ops = { + .name = "scu (non)", +}; + +/* + * Gen1 functions + */ +static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { struct scu_route_config { u32 mask; @@ -171,17 +308,10 @@ static int rsnd_src_set_route_if_gen1( { 0x3, 28, }, /* 7 */ { 0x3, 30, }, /* 8 */ }; - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); u32 mask; u32 val; int id; - /* - * Gen1 only - */ - if (!rsnd_is_gen1(priv)) - return 0; - id = rsnd_mod_id(mod); if (id < 0 || id >= ARRAY_SIZE(routes)) return -EIO; @@ -257,104 +387,43 @@ static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod, return 0; } -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, - struct snd_pcm_runtime *runtime) -{ - struct rsnd_scu *scu; - unsigned int rate; - - /* this function is assuming SSI id = SCU id here */ - scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); - - /* - * return convert rate if SRC is used, - * otherwise, return runtime->rate as usual - */ - rate = rsnd_scu_convert_rate(scu); - if (!rate) - rate = runtime->rate; - - return rate; -} - -static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_set_convert_rate_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - u32 adinr = runtime->channels; - - /* set/clear soft reset */ - rsnd_mod_write(mod, SRC_SWRSR, 0); - rsnd_mod_write(mod, SRC_SWRSR, 1); - - /* Initialize the operation of the SRC internal circuits */ - rsnd_mod_write(mod, SRC_SRCIR, 1); - - /* Set channel number and output bit length */ - switch (runtime->sample_bits) { - case 16: - adinr |= OTBL_16; - break; - case 32: - adinr |= OTBL_24; - break; - default: - return -EIO; - } - rsnd_mod_write(mod, SRC_ADINR, adinr); - - if (convert_rate) { - u32 fsrate = 0x0400000 / convert_rate * runtime->rate; - - /* Enable the initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSCR, 1); - - /* Set initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSVR, fsrate); - - /* Select SRC mode (fixed value) */ - rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); + int ret; - /* Set the restriction value of the FS ratio (98%) */ - rsnd_mod_write(mod, SRC_MNFSR, fsrate / 100 * 98); + ret = rsnd_scu_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; - if (rsnd_is_gen1(priv)) { - /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ - } - } + /* Select SRC mode (fixed value) */ + rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); - /* Cancel the initialization and operate the SRC function */ - rsnd_mod_write(mod, SRC_SRCIR, 0); + /* Set the restriction value of the FS ratio (98%) */ + rsnd_mod_write(mod, SRC_MNFSR, + rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); - /* use DMA transfer */ - rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); + /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ return 0; } -static int rsnd_scu_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_init_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int ret; - clk_enable(scu->clk); - - ret = rsnd_scu_ssi_mode_init(mod, rdai, io); + ret = rsnd_scu_init(mod, rdai, io); if (ret < 0) return ret; - ret = rsnd_src_set_route_if_gen1(mod, rdai, io); + ret = rsnd_src_set_route_gen1(mod, rdai, io); if (ret < 0) return ret; - ret = rsnd_scu_set_convert_rate(mod, rdai, io); + ret = rsnd_scu_set_convert_rate_gen1(mod, rdai, io); if (ret < 0) return ret; @@ -365,62 +434,58 @@ static int rsnd_scu_init(struct rsnd_mod *mod, return 0; } -static int rsnd_scu_quit(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_start_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int id = rsnd_mod_id(mod); - clk_disable(scu->clk); + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); - return 0; + return rsnd_scu_start(mod, rdai, io); } -static int rsnd_scu_start(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_stop_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int id = rsnd_mod_id(mod); - if (rsnd_is_gen1(priv)) - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); - return 0; + return rsnd_scu_stop(mod, rdai, io); } -static int rsnd_scu_stop(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); +static struct rsnd_mod_ops rsnd_scu_gen1_ops = { + .name = "sru (gen1)", + .init = rsnd_scu_init_gen1, + .quit = rsnd_scu_quit, + .start = rsnd_scu_start_gen1, + .stop = rsnd_scu_stop_gen1, +}; - if (rsnd_is_gen1(priv)) - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); +static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = { + .name = "non-sru (gen1)", + .init = rsnd_scu_ssi_mode_init, +}; - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); +/* + * Gen2 functions + */ +static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + /* enable PIO interrupt */ + rsnd_mod_write(mod, INT_ENABLE, 0x0f000000); return 0; } -static struct rsnd_mod_ops rsnd_scu_ops = { - .name = "scu", - .init = rsnd_scu_init, - .quit = rsnd_scu_quit, - .start = rsnd_scu_start, - .stop = rsnd_scu_stop, -}; - -static struct rsnd_mod_ops rsnd_scu_non_ops = { - .name = "scu (non)", +static struct rsnd_mod_ops rsnd_scu_non_gen2_ops = { + .name = "non-scu (gen2)", .init = rsnd_scu_ssi_mode_init, + .start = rsnd_scu_start_non_gen2, }; struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) @@ -466,8 +531,15 @@ int rsnd_scu_probe(struct platform_device *pdev, scu->clk = clk; ops = &rsnd_scu_non_ops; - if (rsnd_scu_hpbif_is_enable(scu)) - ops = &rsnd_scu_ops; + if (rsnd_scu_hpbif_is_enable(scu)) { + if (rsnd_is_gen1(priv)) + ops = &rsnd_scu_gen1_ops; + } else { + if (rsnd_is_gen1(priv)) + ops = &rsnd_scu_non_gen1_ops; + if (rsnd_is_gen2(priv)) + ops = &rsnd_scu_non_gen2_ops; + } rsnd_mod_init(priv, &scu->mod, ops, i); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index bae309c9f0fb..b7f464ebcdc0 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -363,16 +363,11 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; - /* enable PIO interrupt if gen2 */ - if (rsnd_is_gen2(priv)) - rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000); - rsnd_ssi_hw_start(ssi, rdai, io); return 0; -- cgit v1.2.3 From 4686a0ad9aaee89495f181e5755d153e7fe7ffe6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:44 -0800 Subject: ASoC: rsnd: remove SSI dependent DMAEngine callback Renesas Gen2 sound will use 2 DMAC which are Audio-DMAC, and Audio-DMAC-peri-peri. Current driver has callback function for each DMAC, because it assumed each DMAC needs special settings. But it became clear that these can share settings. This patch removes unnecessary callback Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 38 +++++++++++++++++++++++++++----------- sound/soc/sh/rcar/rsnd.h | 10 +++++----- sound/soc/sh/rcar/ssi.c | 47 ++++++++--------------------------------------- 3 files changed, 40 insertions(+), 55 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 11eb0e35b9ce..b5af6f5145ea 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -143,6 +143,7 @@ static void rsnd_dma_continue(struct rsnd_dma *dma) void rsnd_dma_start(struct rsnd_dma *dma) { /* push both A and B plane*/ + dma->offset = 0; dma->submit_loop = 2; __rsnd_dma_start(dma); } @@ -157,12 +158,26 @@ void rsnd_dma_stop(struct rsnd_dma *dma) static void rsnd_dma_complete(void *data) { struct rsnd_dma *dma = (struct rsnd_dma *)data; + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); unsigned long flags; rsnd_lock(priv, flags); - dma->complete(dma); + /* + * Renesas sound Gen1 needs 1 DMAC, + * Gen2 needs 2 DMAC. + * In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri. + * But, Audio-DMAC-peri-peri doesn't have interrupt, + * and this driver is assuming that here. + * + * If Audio-DMAC-peri-peri has interrpt, + * rsnd_dai_pointer_update() will be called twice, + * ant it will breaks io->byte_pos + */ + + rsnd_dai_pointer_update(io, io->byte_per_period); if (dma->submit_loop) rsnd_dma_continue(dma); @@ -172,17 +187,21 @@ static void rsnd_dma_complete(void *data) static void __rsnd_dma_start(struct rsnd_dma *dma) { - struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; dma_addr_t buf; - size_t len; + size_t len = io->byte_per_period; int i; for (i = 0; i < dma->submit_loop; i++) { - if (dma->inquiry(dma, &buf, &len) < 0) - return; + buf = runtime->dma_addr + + rsnd_dai_pointer_offset(io, dma->offset + len); + dma->offset = len; desc = dmaengine_prep_slave_single( dma->chan, buf, len, dma->dir, @@ -217,10 +236,7 @@ int rsnd_dma_available(struct rsnd_dma *dma) } int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, - int is_play, int id, - int (*inquiry)(struct rsnd_dma *dma, - dma_addr_t *buf, int *len), - int (*complete)(struct rsnd_dma *dma)) + int is_play, int id) { struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg; @@ -253,8 +269,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, goto rsnd_dma_init_err; dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - dma->inquiry = inquiry; - dma->complete = complete; INIT_WORK(&dma->work, rsnd_dma_do_work); return 0; @@ -307,6 +321,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, } list_add_tail(&mod->list, &io->head); + mod->io = io; return 0; } @@ -314,6 +329,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, int rsnd_dai_disconnect(struct rsnd_mod *mod) { list_del_init(&mod->list); + mod->io = NULL; return 0; } diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index c397dc8edee5..b2c717d2ba7e 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -100,19 +100,16 @@ struct rsnd_dma { struct work_struct work; struct dma_chan *chan; enum dma_data_direction dir; - int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len); - int (*complete)(struct rsnd_dma *dma); int submit_loop; + int offset; /* it cares A/B plane */ }; void rsnd_dma_start(struct rsnd_dma *dma); void rsnd_dma_stop(struct rsnd_dma *dma); int rsnd_dma_available(struct rsnd_dma *dma); int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, - int is_play, int id, - int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len), - int (*complete)(struct rsnd_dma *dma)); + int is_play, int id); void rsnd_dma_quit(struct rsnd_priv *priv, struct rsnd_dma *dma); @@ -137,17 +134,20 @@ struct rsnd_mod_ops { struct rsnd_dai_stream *io); }; +struct rsnd_dai_stream; struct rsnd_mod { int id; struct rsnd_priv *priv; struct rsnd_mod_ops *ops; struct list_head list; /* connect to rsnd_dai playback/capture */ struct rsnd_dma dma; + struct rsnd_dai_stream *io; }; #define rsnd_mod_to_priv(mod) ((mod)->priv) #define rsnd_mod_to_dma(mod) (&(mod)->dma) #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) +#define rsnd_mod_to_io(mod) ((mod)->io) #define rsnd_mod_id(mod) ((mod)->id) #define for_each_rsnd_mod(pos, n, io) \ list_for_each_entry_safe(pos, n, &(io)->head, list) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index b7f464ebcdc0..d3371d798d54 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -64,12 +64,10 @@ struct rsnd_ssi { struct rsnd_mod mod; struct rsnd_dai *rdai; - struct rsnd_dai_stream *io; u32 cr_own; u32 cr_clk; u32 cr_etc; int err; - int dma_offset; unsigned int usrcnt; unsigned int rate; }; @@ -286,7 +284,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, * set ssi parameter */ ssi->rdai = rdai; - ssi->io = io; ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ @@ -305,7 +302,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); ssi->rdai = NULL; - ssi->io = NULL; ssi->cr_own = 0; ssi->err = 0; @@ -329,8 +325,9 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) { struct rsnd_ssi *ssi = data; - struct rsnd_dai_stream *io = ssi->io; - u32 status = rsnd_mod_read(&ssi->mod, SSISR); + struct rsnd_mod *mod = &ssi->mod; + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + u32 status = rsnd_mod_read(mod, SSISR); irqreturn_t ret = IRQ_NONE; if (io && (status & DIRQ)) { @@ -347,9 +344,9 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) * see rsnd_ssi_init() */ if (rsnd_dai_is_play(rdai, io)) - rsnd_mod_write(&ssi->mod, SSITDR, *buf); + rsnd_mod_write(mod, SSITDR, *buf); else - *buf = rsnd_mod_read(&ssi->mod, SSIRDR); + *buf = rsnd_mod_read(mod, SSIRDR); rsnd_dai_pointer_update(io, sizeof(*buf)); @@ -394,33 +391,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .stop = rsnd_ssi_pio_stop, }; -static int rsnd_ssi_dma_inquiry(struct rsnd_dma *dma, dma_addr_t *buf, int *len) -{ - struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); - struct rsnd_dai_stream *io = ssi->io; - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - - *len = io->byte_per_period; - *buf = runtime->dma_addr + - rsnd_dai_pointer_offset(io, ssi->dma_offset + *len); - ssi->dma_offset = *len; /* it cares A/B plane */ - - return 0; -} - -static int rsnd_ssi_dma_complete(struct rsnd_dma *dma) -{ - struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); - struct rsnd_dai_stream *io = ssi->io; - u32 status = rsnd_mod_read(&ssi->mod, SSISR); - - rsnd_ssi_record_error(ssi, status); - - rsnd_dai_pointer_update(ssi->io, io->byte_per_period); - - return 0; -} - static int rsnd_ssi_dma_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -430,7 +400,6 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, /* enable DMA transfer */ ssi->cr_etc = DMEN; - ssi->dma_offset = 0; rsnd_dma_start(dma); @@ -452,6 +421,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, ssi->cr_etc = 0; + rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); + rsnd_ssi_hw_stop(ssi, rdai); rsnd_dma_stop(dma); @@ -585,9 +556,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, ret = rsnd_dma_init( priv, rsnd_mod_to_dma(&ssi->mod), rsnd_ssi_is_play(&ssi->mod), - pinfo->dma_id, - rsnd_ssi_dma_inquiry, - rsnd_ssi_dma_complete); + pinfo->dma_id); if (ret < 0) dev_info(dev, "SSI DMA failed. try PIO transter\n"); else -- cgit v1.2.3 From eb854f6dff24a59378acc8d8eda57a3543a25acc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:51 -0800 Subject: ASoC: rsnd: rsnd_ssi_probe() goes forwarder than rsnd_scu_probe() rsnd_ssi_probe() goes forwarder than rsnd_scu_probe(), since scu will need ssi information on Gen2 Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index b5af6f5145ea..f316a663e4d3 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -763,15 +763,15 @@ static int rsnd_probe(struct platform_device *pdev) if (ret) return ret; - ret = rsnd_scu_probe(pdev, info, priv); + ret = rsnd_ssi_probe(pdev, info, priv); if (ret) return ret; - ret = rsnd_adg_probe(pdev, info, priv); + ret = rsnd_scu_probe(pdev, info, priv); if (ret) return ret; - ret = rsnd_ssi_probe(pdev, info, priv); + ret = rsnd_adg_probe(pdev, info, priv); if (ret) return ret; -- cgit v1.2.3 From 629509c5bc478c0343d94c8c70812396f44447fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:42:00 -0800 Subject: ASoC: rsnd: add Gen2 SRC and DMAEngine support Renesas sound Gen2 has SRC (= Sampling Rate Converter) which needs 2 DMAC. The data path image when you use SRC on Gen2 is [mem] -> Audio-DMAC -> SRC -> Audio-DMAC-peri-peri -> SSIU -> SSI This patch support SRC and DMAEnine. It is tested on R-Car H2 Lager board Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 6 +++ sound/soc/sh/rcar/adg.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++ sound/soc/sh/rcar/gen.c | 26 +++++++++ sound/soc/sh/rcar/rsnd.h | 25 +++++++++ sound/soc/sh/rcar/scu.c | 117 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 312 insertions(+) (limited to 'sound/soc') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 1d19bfc2486d..2be05aea54f9 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -56,9 +56,15 @@ struct rsnd_ssi_platform_info { */ #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ +#define RSND_SCU_SET(rate, _dma_id) \ + { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } +#define RSND_SCU_UNUSED \ + { .flags = 0, .convert_rate = 0, .dma_id = 0, } + struct rsnd_scu_platform_info { u32 flags; u32 convert_rate; /* sampling rate convert */ + int dma_id; /* for Gen2 SCU */ }; /* diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 5bdffa480245..821791e15d04 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -30,6 +30,144 @@ struct rsnd_adg { i++, (pos) = adg->clk[i]) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) + +static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_mod *mod) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + int id = rsnd_mod_id(mod); + int ws = id; + + if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { + switch (id) { + case 1: + case 2: + ws = 0; + break; + case 4: + ws = 3; + break; + case 8: + ws = 7; + break; + } + } + + return (0x6 + ws) << 8; +} + +static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, + struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + u32 timsel) +{ + int is_play = rsnd_dai_is_play(rdai, io); + int id = rsnd_mod_id(mod); + int shift = (id % 2) ? 16 : 0; + u32 mask, ws; + u32 in, out; + + ws = rsnd_adg_ssi_ws_timing_gen2(mod); + + in = (is_play) ? timsel : ws; + out = (is_play) ? ws : timsel; + + in = in << shift; + out = out << shift; + mask = 0xffff << shift; + + switch (id / 2) { + case 0: + rsnd_mod_bset(mod, SRCIN_TIMSEL0, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL0, mask, out); + break; + case 1: + rsnd_mod_bset(mod, SRCIN_TIMSEL1, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL1, mask, out); + break; + case 2: + rsnd_mod_bset(mod, SRCIN_TIMSEL2, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL2, mask, out); + break; + case 3: + rsnd_mod_bset(mod, SRCIN_TIMSEL3, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL3, mask, out); + break; + case 4: + rsnd_mod_bset(mod, SRCIN_TIMSEL4, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL4, mask, out); + break; + } + + return 0; +} + +int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io, + unsigned int src_rate, + unsigned int dst_rate) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_adg *adg = rsnd_priv_to_adg(priv); + struct device *dev = rsnd_priv_to_dev(priv); + int idx, sel, div, step; + u32 val; + unsigned int min, diff; + unsigned int sel_rate [] = { + clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ + clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ + clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ + adg->rbga_rate_for_441khz_div_6,/* 0011: RBGA */ + adg->rbgb_rate_for_48khz_div_6, /* 0100: RBGB */ + }; + + min = ~0; + val = 0; + for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { + idx = 0; + step = 2; + + if (!sel_rate[sel]) + continue; + + for (div = 2; div <= 98304; div += step) { + diff = abs(src_rate - sel_rate[sel] / div); + if (min > diff) { + val = (sel << 8) | idx; + min = diff; + } + + /* + * step of 0_0000 / 0_0001 / 0_1101 + * are out of order + */ + if ((idx > 2) && (idx % 2)) + step *= 2; + if (idx == 0x1c) { + div += step; + step *= 2; + } + idx++; + } + } + + if (min == ~0) { + dev_err(dev, "no Input clock\n"); + return -EIO; + } + + return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); +} + +int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + u32 val = rsnd_adg_ssi_ws_timing_gen2(mod); + + return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); +} + int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, unsigned int src_rate, diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index db486aae6b8b..3e03a8bc4f75 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -229,14 +229,40 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), /* FIXME: it needs SSI_MODE2/3 in the future */ + RSND_GEN2_S_REG(gen, SSIU, SSI_CONTROL, 0x810), + RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), + RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), + RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), + RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_IFSCR, 0x21c, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_IFSVR, 0x220, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), + RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL3, 0x40), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL4, 0x44), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL0, 0x48), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL1, 0x4c), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b2c717d2ba7e..8b66dc15fa73 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -37,6 +37,11 @@ enum rsnd_reg { RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ + RSND_REG_SRC_CTRL, /* for Gen2 */ + RSND_REG_SSI_CTRL, /* for Gen2 */ + RSND_REG_SSI_CONTROL, + RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ + RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, RSND_REG_INT_ENABLE, /* for Gen2 */ @@ -49,6 +54,8 @@ enum rsnd_reg { RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, RSND_REG_SRC_MNFSR, /* for Gen1 */ + RSND_REG_SRC_BSDSR, /* for Gen2 */ + RSND_REG_SRC_BSISR, /* for Gen2 */ /* ADG */ RSND_REG_BRRA, @@ -60,6 +67,16 @@ enum rsnd_reg { RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ + RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL3, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL4, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL0, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL1, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL2, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL3, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL4, /* for Gen2 */ /* SSI */ RSND_REG_SSICR, @@ -250,6 +267,14 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, unsigned int src_rate, unsigned int dst_rate); +int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io, + unsigned int src_rate, + unsigned int dst_rate); +int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); /* * R-Car sound priv diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 29d8990e3f0f..6e5c763e1040 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -33,6 +33,8 @@ struct rsnd_scu { container_of((_mod), struct rsnd_scu, mod) #define rsnd_scu_hpbif_is_enable(scu) \ (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) +#define rsnd_scu_dma_available(scu) \ + rsnd_dma_available(rsnd_mod_to_dma(&(scu)->mod)) #define for_each_rsnd_scu(pos, priv, i) \ for ((i) = 0; \ @@ -472,6 +474,103 @@ static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = { /* * Gen2 functions */ +static int rsnd_scu_set_convert_rate_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_scu_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); + rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); + + rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); + + rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); + rsnd_mod_write(mod, SRC_BSISR, 0x00100060); + + return 0; +} + +static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + u32 convert_rate = rsnd_scu_convert_rate(scu); + int ret; + + if (convert_rate) + ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, + runtime->rate, + convert_rate); + else + ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); + + return ret; +} + +static int rsnd_scu_init_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_scu_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_scu_set_convert_rate_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_scu_set_convert_timing_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_scu_start_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + rsnd_dma_start(rsnd_mod_to_dma(&scu->mod)); + + rsnd_mod_write(mod, SSI_CTRL, 0x1); + rsnd_mod_write(mod, SRC_CTRL, 0x11); + + return rsnd_scu_start(mod, rdai, io); +} + +static int rsnd_scu_stop_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + rsnd_mod_write(mod, SSI_CTRL, 0); + rsnd_mod_write(mod, SRC_CTRL, 0); + + rsnd_dma_stop(rsnd_mod_to_dma(&scu->mod)); + + return rsnd_scu_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_scu_gen2_ops = { + .name = "scu (gen2)", + .init = rsnd_scu_init_gen2, + .quit = rsnd_scu_quit, + .start = rsnd_scu_start_gen2, + .stop = rsnd_scu_stop_gen2, +}; + static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -534,6 +633,17 @@ int rsnd_scu_probe(struct platform_device *pdev, if (rsnd_scu_hpbif_is_enable(scu)) { if (rsnd_is_gen1(priv)) ops = &rsnd_scu_gen1_ops; + if (rsnd_is_gen2(priv)) { + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); + int ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(&scu->mod), + rsnd_ssi_is_play(ssi), + scu->info->dma_id); + if (ret < 0) + return ret; + + ops = &rsnd_scu_gen2_ops; + } } else { if (rsnd_is_gen1(priv)) ops = &rsnd_scu_non_gen1_ops; @@ -553,4 +663,11 @@ int rsnd_scu_probe(struct platform_device *pdev, void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv) { + struct rsnd_scu *scu; + int i; + + for_each_rsnd_scu(scu, priv, i) { + if (rsnd_scu_dma_available(scu)) + rsnd_dma_quit(priv, rsnd_mod_to_dma(&scu->mod)); + } } -- cgit v1.2.3 From 3bba4a7889a1d23f34372aecd6de89134fe9ffd8 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Jan 2014 17:30:40 +0530 Subject: ASoC: samsung: h1940_uda1380: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following warning: sound/soc/samsung/h1940_uda1380.c:183:6: warning: unused variable ‘err’ [-Wunused-variable] Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/samsung/h1940_uda1380.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index fbced589d077..3b27cd96570b 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -181,7 +181,6 @@ static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin(dapm, "Speaker"); -- cgit v1.2.3 From 2046d453712faa9cfcc153e28c9f4b25a90ce6ed Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Jan 2014 17:30:41 +0530 Subject: ASoC: samsung: h1940_uda1380: Fix build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following warning: sound/soc/samsung/h1940_uda1380.c:98:4: warning: passing argument 1 of ‘dev_err’ from incompatible pointer type [enabled by default] Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/samsung/h1940_uda1380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 3b27cd96570b..0003b661ab62 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -94,7 +94,7 @@ static int h1940_hw_params(struct snd_pcm_substream *substream, div++; break; default: - dev_err(&rtd->dev, "%s: rate %d is not supported\n", + dev_err(rtd->dev, "%s: rate %d is not supported\n", __func__, rate); return -EINVAL; } -- cgit v1.2.3 From d92bba83c790945ee0954f7a408b6b14418bd976 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Jan 2014 17:30:42 +0530 Subject: ASoC: samsung: rx1950_uda1380: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following warning: sound/soc/samsung/rx1950_uda1380.c:228:6: warning: unused variable ‘err’ [-Wunused-variable] Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/samsung/rx1950_uda1380.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 06ebdc061770..afbfe4aa2cbf 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c @@ -226,7 +226,6 @@ static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin(dapm, "Speaker"); -- cgit v1.2.3 From f227b88f0fce5f9b82aa934f8829a741c2e06d82 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 16 Jan 2014 16:02:10 +0100 Subject: ASoC: core: Add signed register volume control logic Some codecs use signed volume control representation with non standard register sizes, e.g. 6 or 7 bit signed integers. This patch adds generic signed register volume control logic to soc-core. Instead of a fixed width signed register control, this implementation uses a 'min' value and the signed bit location to translate it to an absolute volume. Using the 'sign_bit' we can calculate a correct mask for the register values and translate it back into signed integers of standard size. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- include/sound/soc.h | 1 + sound/soc/soc-core.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 7 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a001472b96a..a25f3ccb3fde 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1067,6 +1067,7 @@ struct soc_mixer_control { int min, max, platform_max; int reg, rreg; unsigned int shift, rshift; + unsigned int sign_bit; unsigned int invert:1; unsigned int autodisable:1; }; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..c1d9d8539ee9 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2715,6 +2715,48 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); +/** + * snd_soc_read_signed - Read a codec register and interprete as signed value + * @codec: codec + * @reg: Register to read + * @mask: Mask to use after shifting the register value + * @shift: Right shift of register value + * @sign_bit: Bit that describes if a number is negative or not. + * + * This functions reads a codec register. The register value is shifted right + * by 'shift' bits and masked with the given 'mask'. Afterwards it translates + * the given registervalue into a signed integer if sign_bit is non-zero. + * + * Returns the register value as signed int. + */ +static int snd_soc_read_signed(struct snd_soc_codec *codec, unsigned int reg, + unsigned int mask, unsigned int shift, unsigned int sign_bit) +{ + int ret; + unsigned int val; + + val = (snd_soc_read(codec, reg) >> shift) & mask; + + if (!sign_bit) + return val; + + /* non-negative number */ + if (!(val & BIT(sign_bit))) + return val; + + ret = val; + + /* + * The register most probably does not contain a full-sized int. + * Instead we have an arbitrary number of bits in a signed + * representation which has to be translated into a full-sized int. + * This is done by filling up all bits above the sign-bit. + */ + ret |= ~((int)(BIT(sign_bit) - 1)); + + return ret; +} + /** * snd_soc_info_volsw - single mixer info callback * @kcontrol: mixer control @@ -2743,7 +2785,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; uinfo->value.integer.min = 0; - uinfo->value.integer.max = platform_max; + uinfo->value.integer.max = platform_max - mc->min; return 0; } EXPORT_SYMBOL_GPL(snd_soc_info_volsw); @@ -2769,11 +2811,16 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max; + int min = mc->min; + int sign_bit = mc->sign_bit; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - ucontrol->value.integer.value[0] = - (snd_soc_read(codec, reg) >> shift) & mask; + if (sign_bit) + mask = BIT(sign_bit + 1) - 1; + + ucontrol->value.integer.value[0] = snd_soc_read_signed(codec, reg, mask, + shift, sign_bit) - min; if (invert) ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0]; @@ -2781,10 +2828,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, if (snd_soc_volsw_is_stereo(mc)) { if (reg == reg2) ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg) >> rshift) & mask; + snd_soc_read_signed(codec, reg, mask, rshift, + sign_bit) - min; else ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg2) >> shift) & mask; + snd_soc_read_signed(codec, reg2, mask, shift, + sign_bit) - min; if (invert) ucontrol->value.integer.value[1] = max - ucontrol->value.integer.value[1]; @@ -2815,6 +2864,8 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max; + int min = mc->min; + unsigned int sign_bit = mc->sign_bit; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; int err; @@ -2822,13 +2873,16 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int val2 = 0; unsigned int val, val_mask; - val = (ucontrol->value.integer.value[0] & mask); + if (sign_bit) + mask = BIT(sign_bit + 1) - 1; + + val = ((ucontrol->value.integer.value[0] + min) & mask); if (invert) val = max - val; val_mask = mask << shift; val = val << shift; if (snd_soc_volsw_is_stereo(mc)) { - val2 = (ucontrol->value.integer.value[1] & mask); + val2 = ((ucontrol->value.integer.value[1] + min) & mask); if (invert) val2 = max - val2; if (reg == reg2) { -- cgit v1.2.3 From 7722f830a45f7fbb8f2f7b23265793980bdf3397 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:33 +0100 Subject: ASoC: simple-card: simplify code The check of the mandatory fields is done for DT in its specific sequence. Move the global check to the non-DT sequence. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 2a1b1b5b5221..f0784ca4d3c8 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -225,16 +225,16 @@ static int asoc_simple_card_probe(struct platform_device *pdev) memcpy(cinfo, dev->platform_data, sizeof(*cinfo)); cinfo->snd_card.dev = dev; - } - if (!cinfo->name || - !cinfo->card || - !cinfo->codec_dai.name || - !(cinfo->codec || of_codec) || - !(cinfo->platform || of_platform) || - !(cinfo->cpu_dai.name || of_cpu)) { - dev_err(dev, "insufficient asoc_simple_card_info settings\n"); - return -EINVAL; + if (!cinfo->name || + !cinfo->card || + !cinfo->codec_dai.name || + !cinfo->codec || + !cinfo->platform || + !cinfo->cpu_dai.name) { + dev_err(dev, "insufficient asoc_simple_card_info settings\n"); + return -EINVAL; + } } /* -- cgit v1.2.3 From 2bee991460a838ee3c8064a6d880c4e7bc41717a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:37 +0100 Subject: ASoC: simple-card: simplify code The DT values are copied to the non-DT structure before being moved to the card structure. Set directly the DT values in the card and move the non-DT copy to the non-DT sequence. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index f0784ca4d3c8..7c5dc7336c0b 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -169,12 +169,13 @@ static int asoc_simple_card_parse_of(struct device_node *node, strlen(info->codec_dai.name) + 2, GFP_KERNEL); sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); - info->name = info->card = name; + info->snd_card.name = name; + info->snd_link.name = info->snd_link.stream_name = name; /* simple-card assumes platform == cpu */ *of_platform = *of_cpu; - dev_dbg(dev, "card-name : %s\n", info->card); + dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "platform : %04x\n", info->daifmt); dev_dbg(dev, "cpu : %s / %04x / %d\n", info->cpu_dai.name, @@ -217,6 +218,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) dev_err(dev, "parse error %d\n", ret); return ret; } + cinfo->snd_link.cpu_of_node = of_cpu; + cinfo->snd_link.codec_of_node = of_codec; + cinfo->snd_link.platform_of_node = of_platform; } else { if (!dev->platform_data) { dev_err(dev, "no info for asoc-simple-card\n"); @@ -235,26 +239,24 @@ static int asoc_simple_card_probe(struct platform_device *pdev) dev_err(dev, "insufficient asoc_simple_card_info settings\n"); return -EINVAL; } + + cinfo->snd_card.name = cinfo->card; + cinfo->snd_link.name = cinfo->name; + cinfo->snd_link.stream_name = cinfo->name; + cinfo->snd_link.platform_name = cinfo->platform; + cinfo->snd_link.codec_name = cinfo->codec; } /* * init snd_soc_dai_link */ - cinfo->snd_link.name = cinfo->name; - cinfo->snd_link.stream_name = cinfo->name; cinfo->snd_link.cpu_dai_name = cinfo->cpu_dai.name; - cinfo->snd_link.platform_name = cinfo->platform; - cinfo->snd_link.codec_name = cinfo->codec; cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; - cinfo->snd_link.cpu_of_node = of_cpu; - cinfo->snd_link.codec_of_node = of_codec; - cinfo->snd_link.platform_of_node = of_platform; cinfo->snd_link.init = asoc_simple_card_dai_init; /* * init snd_soc_card */ - cinfo->snd_card.name = cinfo->card; cinfo->snd_card.owner = THIS_MODULE; cinfo->snd_card.dai_link = &cinfo->snd_link; cinfo->snd_card.num_links = 1; -- cgit v1.2.3 From 201a0eac7fe5e7a8fa33f0742304f885bc344d0d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:41 +0100 Subject: ASoC: simple-card: simplify code The OF pointers are put in the stack and then copied to the card descriptor. Put them directly at their right place. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 55 +++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 7c5dc7336c0b..89f83b32d86d 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -60,8 +60,9 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int asoc_simple_card_sub_parse_of(struct device_node *np, struct asoc_simple_dai *dai, - struct device_node **node) + const struct device_node **p_node) { + struct device_node *node; struct clk *clk; int ret; @@ -69,9 +70,10 @@ asoc_simple_card_sub_parse_of(struct device_node *np, * get node via "sound-dai = <&phandle port>" * it will be used as xxx_of_node on soc_bind_dai_link() */ - *node = of_parse_phandle(np, "sound-dai", 0); - if (!*node) + node = of_parse_phandle(np, "sound-dai", 0); + if (!node) return -ENODEV; + *p_node = node; /* get dai->name */ ret = snd_soc_of_get_dai_name(np, &dai->name); @@ -104,7 +106,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, "system-clock-frequency", &dai->sysclk); } else { - clk = of_clk_get(*node, 0); + clk = of_clk_get(node, 0); if (!IS_ERR(clk)) dai->sysclk = clk_get_rate(clk); } @@ -112,17 +114,14 @@ asoc_simple_card_sub_parse_of(struct device_node *np, ret = 0; parse_error: - of_node_put(*node); + of_node_put(node); return ret; } static int asoc_simple_card_parse_of(struct device_node *node, struct asoc_simple_card_info *info, - struct device *dev, - struct device_node **of_cpu, - struct device_node **of_codec, - struct device_node **of_platform) + struct device *dev) { struct device_node *np; char *name; @@ -146,7 +145,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->cpu_dai, - of_cpu); + &info->snd_link.cpu_of_node); if (ret < 0) return ret; @@ -156,7 +155,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->codec_dai, - of_codec); + &info->snd_link.codec_of_node); if (ret < 0) return ret; @@ -173,7 +172,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, info->snd_link.name = info->snd_link.stream_name = name; /* simple-card assumes platform == cpu */ - *of_platform = *of_cpu; + info->snd_link.platform_of_node = info->snd_link.cpu_of_node; dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "platform : %04x\n", info->daifmt); @@ -193,34 +192,29 @@ static int asoc_simple_card_probe(struct platform_device *pdev) { struct asoc_simple_card_info *cinfo; struct device_node *np = pdev->dev.of_node; - struct device_node *of_cpu, *of_codec, *of_platform; struct device *dev = &pdev->dev; int ret; - cinfo = NULL; - of_cpu = NULL; - of_codec = NULL; - of_platform = NULL; - cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); if (!cinfo) return -ENOMEM; + /* + * init snd_soc_card + */ + cinfo->snd_card.owner = THIS_MODULE; + cinfo->snd_card.dev = dev; + cinfo->snd_card.dai_link = &cinfo->snd_link; + cinfo->snd_card.num_links = 1; + if (np && of_device_is_available(np)) { - cinfo->snd_card.dev = dev; - ret = asoc_simple_card_parse_of(np, cinfo, dev, - &of_cpu, - &of_codec, - &of_platform); + ret = asoc_simple_card_parse_of(np, cinfo, dev); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); return ret; } - cinfo->snd_link.cpu_of_node = of_cpu; - cinfo->snd_link.codec_of_node = of_codec; - cinfo->snd_link.platform_of_node = of_platform; } else { if (!dev->platform_data) { dev_err(dev, "no info for asoc-simple-card\n"); @@ -228,8 +222,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) } memcpy(cinfo, dev->platform_data, sizeof(*cinfo)); - cinfo->snd_card.dev = dev; - if (!cinfo->name || !cinfo->card || !cinfo->codec_dai.name || @@ -254,13 +246,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; cinfo->snd_link.init = asoc_simple_card_dai_init; - /* - * init snd_soc_card - */ - cinfo->snd_card.owner = THIS_MODULE; - cinfo->snd_card.dai_link = &cinfo->snd_link; - cinfo->snd_card.num_links = 1; - snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card); -- cgit v1.2.3 From 5ca8ba4180a6f629d51dba699b4a6428cc5eeba7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:45 +0100 Subject: ASoC: simple-card: simplify code Have a cleaner code using a DAI link pointer. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 89f83b32d86d..797696fc6f12 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -123,6 +123,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, struct asoc_simple_card_info *info, struct device *dev) { + struct snd_soc_dai_link *dai_link = info->snd_card.dai_link; struct device_node *np; char *name; int ret; @@ -145,7 +146,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->cpu_dai, - &info->snd_link.cpu_of_node); + &dai_link->cpu_of_node); if (ret < 0) return ret; @@ -155,7 +156,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->codec_dai, - &info->snd_link.codec_of_node); + &dai_link->codec_of_node); if (ret < 0) return ret; @@ -169,10 +170,10 @@ static int asoc_simple_card_parse_of(struct device_node *node, GFP_KERNEL); sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); info->snd_card.name = name; - info->snd_link.name = info->snd_link.stream_name = name; + dai_link->name = dai_link->stream_name = name; /* simple-card assumes platform == cpu */ - info->snd_link.platform_of_node = info->snd_link.cpu_of_node; + dai_link->platform_of_node = dai_link->cpu_of_node; dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "platform : %04x\n", info->daifmt); @@ -191,6 +192,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_probe(struct platform_device *pdev) { struct asoc_simple_card_info *cinfo; + struct snd_soc_dai_link *dai_link; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; int ret; @@ -204,8 +206,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) */ cinfo->snd_card.owner = THIS_MODULE; cinfo->snd_card.dev = dev; - cinfo->snd_card.dai_link = &cinfo->snd_link; - cinfo->snd_card.num_links = 1; + dai_link = &cinfo->snd_link; + cinfo->snd_card.dai_link = dai_link; + cinfo->snd_card.num_links = 1; if (np && of_device_is_available(np)) { @@ -233,18 +236,18 @@ static int asoc_simple_card_probe(struct platform_device *pdev) } cinfo->snd_card.name = cinfo->card; - cinfo->snd_link.name = cinfo->name; - cinfo->snd_link.stream_name = cinfo->name; - cinfo->snd_link.platform_name = cinfo->platform; - cinfo->snd_link.codec_name = cinfo->codec; + dai_link->name = cinfo->name; + dai_link->stream_name = cinfo->name; + dai_link->platform_name = cinfo->platform; + dai_link->codec_name = cinfo->codec; } /* * init snd_soc_dai_link */ - cinfo->snd_link.cpu_dai_name = cinfo->cpu_dai.name; - cinfo->snd_link.codec_dai_name = cinfo->codec_dai.name; - cinfo->snd_link.init = asoc_simple_card_dai_init; + dai_link->cpu_dai_name = cinfo->cpu_dai.name; + dai_link->codec_dai_name = cinfo->codec_dai.name; + dai_link->init = asoc_simple_card_dai_init; snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); -- cgit v1.2.3 From 520084729267ac8df1651ad2f118a1d4a631a10a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:48 +0100 Subject: ASoC: simple-card: simplify code The CPU and CODEC DAI names are still copied to the user info structure. Put them directly in the DAI links. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 797696fc6f12..9068ab474ab4 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -60,7 +60,8 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int asoc_simple_card_sub_parse_of(struct device_node *np, struct asoc_simple_dai *dai, - const struct device_node **p_node) + const struct device_node **p_node, + const char **name) { struct device_node *node; struct clk *clk; @@ -76,7 +77,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, *p_node = node; /* get dai->name */ - ret = snd_soc_of_get_dai_name(np, &dai->name); + ret = snd_soc_of_get_dai_name(np, name); if (ret < 0) goto parse_error; @@ -146,7 +147,8 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->cpu_dai, - &dai_link->cpu_of_node); + &dai_link->cpu_of_node, + &dai_link->cpu_dai_name); if (ret < 0) return ret; @@ -156,19 +158,21 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (np) ret = asoc_simple_card_sub_parse_of(np, &info->codec_dai, - &dai_link->codec_of_node); + &dai_link->codec_of_node, + &dai_link->codec_dai_name); if (ret < 0) return ret; - if (!info->cpu_dai.name || !info->codec_dai.name) + if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) return -EINVAL; /* card name is created from CPU/CODEC dai name */ name = devm_kzalloc(dev, - strlen(info->cpu_dai.name) + - strlen(info->codec_dai.name) + 2, + strlen(dai_link->cpu_dai_name) + + strlen(dai_link->codec_dai_name) + 2, GFP_KERNEL); - sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name); + sprintf(name, "%s-%s", dai_link->cpu_dai_name, + dai_link->codec_dai_name); info->snd_card.name = name; dai_link->name = dai_link->stream_name = name; @@ -178,11 +182,11 @@ static int asoc_simple_card_parse_of(struct device_node *node, dev_dbg(dev, "card-name : %s\n", name); dev_dbg(dev, "platform : %04x\n", info->daifmt); dev_dbg(dev, "cpu : %s / %04x / %d\n", - info->cpu_dai.name, + dai_link->cpu_dai_name, info->cpu_dai.fmt, info->cpu_dai.sysclk); dev_dbg(dev, "codec : %s / %04x / %d\n", - info->codec_dai.name, + dai_link->codec_dai_name, info->codec_dai.fmt, info->codec_dai.sysclk); @@ -240,13 +244,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) dai_link->stream_name = cinfo->name; dai_link->platform_name = cinfo->platform; dai_link->codec_name = cinfo->codec; + dai_link->cpu_dai_name = cinfo->cpu_dai.name; + dai_link->codec_dai_name = cinfo->codec_dai.name; } /* * init snd_soc_dai_link */ - dai_link->cpu_dai_name = cinfo->cpu_dai.name; - dai_link->codec_dai_name = cinfo->codec_dai.name; dai_link->init = asoc_simple_card_dai_init; snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); -- cgit v1.2.3 From ca65b492c7a265b220f763fd68bf87391213248f Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:52 +0100 Subject: ASoC: simple-card: simplify code In the non-DT sequence, the platform data is copied as a whole to the dynamic card info and the same pointer 'cinfo' is used to copy the platform information to the card. Use 'priv' as the pointer to the dynamic card info and copy only the useful information from the platform data. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 9068ab474ab4..90c6fd5c2c7e 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -195,40 +195,42 @@ static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_probe(struct platform_device *pdev) { - struct asoc_simple_card_info *cinfo; + struct asoc_simple_card_info *priv; struct snd_soc_dai_link *dai_link; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; int ret; - cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL); - if (!cinfo) + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; /* * init snd_soc_card */ - cinfo->snd_card.owner = THIS_MODULE; - cinfo->snd_card.dev = dev; - dai_link = &cinfo->snd_link; - cinfo->snd_card.dai_link = dai_link; - cinfo->snd_card.num_links = 1; + priv->snd_card.owner = THIS_MODULE; + priv->snd_card.dev = dev; + dai_link = &priv->snd_link; + priv->snd_card.dai_link = dai_link; + priv->snd_card.num_links = 1; if (np && of_device_is_available(np)) { - ret = asoc_simple_card_parse_of(np, cinfo, dev); + ret = asoc_simple_card_parse_of(np, priv, dev); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); return ret; } } else { - if (!dev->platform_data) { + struct asoc_simple_card_info *cinfo; + + cinfo = dev->platform_data; + if (!cinfo) { dev_err(dev, "no info for asoc-simple-card\n"); return -EINVAL; } - memcpy(cinfo, dev->platform_data, sizeof(*cinfo)); if (!cinfo->name || !cinfo->card || !cinfo->codec_dai.name || @@ -239,13 +241,17 @@ static int asoc_simple_card_probe(struct platform_device *pdev) return -EINVAL; } - cinfo->snd_card.name = cinfo->card; + priv->snd_card.name = cinfo->card; dai_link->name = cinfo->name; dai_link->stream_name = cinfo->name; dai_link->platform_name = cinfo->platform; dai_link->codec_name = cinfo->codec; dai_link->cpu_dai_name = cinfo->cpu_dai.name; dai_link->codec_dai_name = cinfo->codec_dai.name; + memcpy(&priv->cpu_dai, &cinfo->cpu_dai, + sizeof(priv->cpu_dai)); + memcpy(&priv->codec_dai, &cinfo->codec_dai, + sizeof(priv->codec_dai)); } /* @@ -253,9 +259,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) */ dai_link->init = asoc_simple_card_dai_init; - snd_soc_card_set_drvdata(&cinfo->snd_card, cinfo); + snd_soc_card_set_drvdata(&priv->snd_card, priv); - return devm_snd_soc_register_card(&pdev->dev, &cinfo->snd_card); + return devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); } static const struct of_device_id asoc_simple_of_match[] = { -- cgit v1.2.3 From 45fce59496cbabd46761e6980c05c82d94d08eaa Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:51:56 +0100 Subject: ASoC: simple-card: simplify code The platform data structure contains information which is used only by the driver, and the driver allocates platform information fields which are of no use. Move the driver specific data to a new private structure and cleanup the platform data structure. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- include/sound/simple_card.h | 4 ---- sound/soc/generic/simple-card.c | 14 +++++++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h index 6c74527d4926..e1ac996c8feb 100644 --- a/include/sound/simple_card.h +++ b/include/sound/simple_card.h @@ -29,10 +29,6 @@ struct asoc_simple_card_info { unsigned int daifmt; struct asoc_simple_dai cpu_dai; struct asoc_simple_dai codec_dai; - - /* used in simple-card.c */ - struct snd_soc_dai_link snd_link; - struct snd_soc_card snd_card; }; #endif /* __SIMPLE_CARD_H */ diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 90c6fd5c2c7e..0f11c2808437 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -15,6 +15,14 @@ #include #include +struct simple_card_data { + struct snd_soc_card snd_card; + unsigned int daifmt; + struct asoc_simple_dai cpu_dai; + struct asoc_simple_dai codec_dai; + struct snd_soc_dai_link snd_link; +}; + static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, struct asoc_simple_dai *set, unsigned int daifmt) @@ -39,7 +47,7 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct asoc_simple_card_info *info = + struct simple_card_data *info = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; @@ -121,7 +129,7 @@ parse_error: } static int asoc_simple_card_parse_of(struct device_node *node, - struct asoc_simple_card_info *info, + struct simple_card_data *info, struct device *dev) { struct snd_soc_dai_link *dai_link = info->snd_card.dai_link; @@ -195,7 +203,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_probe(struct platform_device *pdev) { - struct asoc_simple_card_info *priv; + struct simple_card_data *priv; struct snd_soc_dai_link *dai_link; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; -- cgit v1.2.3 From b367a3252b365fd545fc589a40cad3976e73d7d7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 15 Jan 2014 16:52:00 +0100 Subject: ASoC: simple-card: simplify code Rename the pointer to the private data structure to 'priv' to avoid confusion with the platform data pointer. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 0f11c2808437..6443c87e8625 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -47,18 +47,18 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct simple_card_data *info = + struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; - unsigned int daifmt = info->daifmt; + unsigned int daifmt = priv->daifmt; int ret; - ret = __asoc_simple_card_dai_init(codec, &info->codec_dai, daifmt); + ret = __asoc_simple_card_dai_init(codec, &priv->codec_dai, daifmt); if (ret < 0) return ret; - ret = __asoc_simple_card_dai_init(cpu, &info->cpu_dai, daifmt); + ret = __asoc_simple_card_dai_init(cpu, &priv->cpu_dai, daifmt); if (ret < 0) return ret; @@ -129,21 +129,21 @@ parse_error: } static int asoc_simple_card_parse_of(struct device_node *node, - struct simple_card_data *info, + struct simple_card_data *priv, struct device *dev) { - struct snd_soc_dai_link *dai_link = info->snd_card.dai_link; + struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; struct device_node *np; char *name; int ret; /* get CPU/CODEC common format via simple-audio-card,format */ - info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & + priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); /* DAPM routes */ if (of_property_read_bool(node, "simple-audio-card,routing")) { - ret = snd_soc_of_parse_audio_routing(&info->snd_card, + ret = snd_soc_of_parse_audio_routing(&priv->snd_card, "simple-audio-card,routing"); if (ret) return ret; @@ -154,7 +154,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, np = of_get_child_by_name(node, "simple-audio-card,cpu"); if (np) ret = asoc_simple_card_sub_parse_of(np, - &info->cpu_dai, + &priv->cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_dai_name); if (ret < 0) @@ -165,7 +165,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, np = of_get_child_by_name(node, "simple-audio-card,codec"); if (np) ret = asoc_simple_card_sub_parse_of(np, - &info->codec_dai, + &priv->codec_dai, &dai_link->codec_of_node, &dai_link->codec_dai_name); if (ret < 0) @@ -181,22 +181,22 @@ static int asoc_simple_card_parse_of(struct device_node *node, GFP_KERNEL); sprintf(name, "%s-%s", dai_link->cpu_dai_name, dai_link->codec_dai_name); - info->snd_card.name = name; + priv->snd_card.name = name; dai_link->name = dai_link->stream_name = name; /* simple-card assumes platform == cpu */ dai_link->platform_of_node = dai_link->cpu_of_node; dev_dbg(dev, "card-name : %s\n", name); - dev_dbg(dev, "platform : %04x\n", info->daifmt); + dev_dbg(dev, "platform : %04x\n", priv->daifmt); dev_dbg(dev, "cpu : %s / %04x / %d\n", dai_link->cpu_dai_name, - info->cpu_dai.fmt, - info->cpu_dai.sysclk); + priv->cpu_dai.fmt, + priv->cpu_dai.sysclk); dev_dbg(dev, "codec : %s / %04x / %d\n", dai_link->codec_dai_name, - info->codec_dai.fmt, - info->codec_dai.sysclk); + priv->codec_dai.fmt, + priv->codec_dai.sysclk); return 0; } -- cgit v1.2.3 From 4763ebe226156db985fe75bfe930c4069d1f4207 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 24 Jan 2014 15:43:00 +0800 Subject: ASoC: simple-card: fix __asoc_simple_card_dai_init If the CPU/CODEC DAI set_sysclk() is not support, the -ENOTSUPP will returnd. Here do the check like set_fmt(). Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 6443c87e8625..6366f3fa6a37 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -27,21 +27,29 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, struct asoc_simple_dai *set, unsigned int daifmt) { - int ret = 0; + int ret; daifmt |= set->fmt; - if (daifmt) + if (daifmt) { ret = snd_soc_dai_set_fmt(dai, daifmt); - - if (ret == -ENOTSUPP) { - dev_dbg(dai->dev, "ASoC: set_fmt is not supported\n"); - ret = 0; + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_fmt error\n"); + goto err; + } } - if (!ret && set->sysclk) + if (set->sysclk) { ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_sysclk error\n"); + goto err; + } + } + + ret = 0; +err: return ret; } -- cgit v1.2.3 From 30d0341e7da0c012f64fb290dd1153360fb49a8d Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 24 Jan 2014 15:43:01 +0800 Subject: ASoC: simple-card: simplify the daifmt code In the asoc_simple_card_parse_of() will parse the device node's CPU/CODEC DAI commone fmts, and then in asoc_simple_card_sub_parse_of() will parse the CPU/CODEC DAI's sub-node fmts, so we can combine the info->daifmt and info->set.fmt in asoc_simple_card_sub_parse_of() not while just before _set_fmt(). And this will be more easy to add new functions, such as supporting _set_tdm_slot(), etc. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 6366f3fa6a37..65833feb995f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -24,15 +24,12 @@ struct simple_card_data { }; static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, - struct asoc_simple_dai *set, - unsigned int daifmt) + struct asoc_simple_dai *set) { int ret; - daifmt |= set->fmt; - - if (daifmt) { - ret = snd_soc_dai_set_fmt(dai, daifmt); + if (set->fmt) { + ret = snd_soc_dai_set_fmt(dai, set->fmt); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_fmt error\n"); goto err; @@ -59,14 +56,13 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; - unsigned int daifmt = priv->daifmt; int ret; - ret = __asoc_simple_card_dai_init(codec, &priv->codec_dai, daifmt); + ret = __asoc_simple_card_dai_init(codec, &priv->codec_dai); if (ret < 0) return ret; - ret = __asoc_simple_card_dai_init(cpu, &priv->cpu_dai, daifmt); + ret = __asoc_simple_card_dai_init(cpu, &priv->cpu_dai); if (ret < 0) return ret; @@ -75,6 +71,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int asoc_simple_card_sub_parse_of(struct device_node *np, + unsigned int daifmt, struct asoc_simple_dai *dai, const struct device_node **p_node, const char **name) @@ -103,6 +100,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, * and specific "format" if it has */ dai->fmt = snd_soc_of_parse_daifmt(np, NULL); + dai->fmt |= daifmt; /* * dai->sysclk come from @@ -161,7 +159,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,cpu"); if (np) - ret = asoc_simple_card_sub_parse_of(np, + ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, &priv->cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_dai_name); @@ -172,7 +170,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,codec"); if (np) - ret = asoc_simple_card_sub_parse_of(np, + ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, &priv->codec_dai, &dai_link->codec_of_node, &dai_link->codec_dai_name); -- cgit v1.2.3 From 2772555b6c5ba79783c04ea6c60549530d737e2e Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 24 Jan 2014 15:43:02 +0800 Subject: ASoC: simple-card: Add snd_card's name parsing from DT node support If the DT is used and the CPU DAI device has only one DAI, the card name will be like : ALSA device list: 0: 40031000.sai-sgtl5000 And this name maybe a little ugly to some customers, so here the card name parsing from DT node is supported. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 65833feb995f..0890fcdc9251 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -143,6 +143,9 @@ static int asoc_simple_card_parse_of(struct device_node *node, char *name; int ret; + /* parsing the card name from DT */ + snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); + /* get CPU/CODEC common format via simple-audio-card,format */ priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); @@ -187,7 +190,8 @@ static int asoc_simple_card_parse_of(struct device_node *node, GFP_KERNEL); sprintf(name, "%s-%s", dai_link->cpu_dai_name, dai_link->codec_dai_name); - priv->snd_card.name = name; + if (!priv->snd_card.name) + priv->snd_card.name = name; dai_link->name = dai_link->stream_name = name; /* simple-card assumes platform == cpu */ -- cgit v1.2.3 From a74ab5121f8d91fb7f13ac1c86e72e9d35e0bc29 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 16 Jan 2014 16:30:25 +0100 Subject: ASoC: tlv320aic32x4: Use gpio_is_valid Use function gpio_is_valid to check for gpio ports. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 688151ba309a..36a9cb90a585 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -588,7 +588,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec) snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (aic32x4->rstn_gpio >= 0) { + if (gpio_is_valid(aic32x4->rstn_gpio)) { ndelay(10); gpio_set_value(aic32x4->rstn_gpio, 1); } @@ -693,7 +693,7 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->rstn_gpio = -1; } - if (aic32x4->rstn_gpio >= 0) { + if (gpio_is_valid(aic32x4->rstn_gpio)) { ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); if (ret != 0) -- cgit v1.2.3 From c671e79d6c2d5a525496fbf18103841c68fe3305 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 27 Jan 2014 13:03:07 +0100 Subject: ASoC: tlv320aic32x4: Use signed int mixer controls There are a number of mixer controls that support negative values. They use signed values for this with different number of bits for the values. Currently they only support the positive range. This patch replaces the unsigned mixers with signed mixers to support the full range. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 36a9cb90a585..c541213b1edf 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -68,18 +68,24 @@ struct aic32x4_priv { int rstn_gpio; }; -/* 0dB min, 1dB steps */ -static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0); /* 0dB min, 0.5dB steps */ static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0); +/* -63.5dB min, 0.5dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_pcm, -6350, 50, 0); +/* -6dB min, 1dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0); +/* -12dB min, 0.5dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0); static const struct snd_kcontrol_new aic32x4_snd_controls[] = { - SOC_DOUBLE_R_TLV("PCM Playback Volume", AIC32X4_LDACVOL, - AIC32X4_RDACVOL, 0, 0x30, 0, tlv_step_0_5), - SOC_DOUBLE_R_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, - AIC32X4_HPRGAIN, 0, 0x1D, 0, tlv_step_1), - SOC_DOUBLE_R_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, - AIC32X4_LORGAIN, 0, 0x1D, 0, tlv_step_1), + SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL, + AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm), + SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, + AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0, + tlv_driver_gain), + SOC_DOUBLE_R_S_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, + AIC32X4_LORGAIN, 0, -0x6, 0x1d, 5, 0, + tlv_driver_gain), SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, AIC32X4_HPRGAIN, 6, 0x01, 1), SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, @@ -90,8 +96,8 @@ static const struct snd_kcontrol_new aic32x4_snd_controls[] = { SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0), SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0), - SOC_DOUBLE_R_TLV("ADC Level Volume", AIC32X4_LADCVOL, - AIC32X4_RADCVOL, 0, 0x28, 0, tlv_step_0_5), + SOC_DOUBLE_R_S_TLV("ADC Level Volume", AIC32X4_LADCVOL, + AIC32X4_RADCVOL, 0, -0x18, 0x28, 6, 0, tlv_adc_vol), SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL, AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5), -- cgit v1.2.3 From 4d16700dd926d4c4a66a91a138c34eef4fd342b4 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 27 Jan 2014 13:03:08 +0100 Subject: ASoC: tlv320aic32x4: DT support Add DT support for this codec. The bindings differ a bit from the aic3x codec bindings, so I created a new binding documentation. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tlv320aic32x4.txt | 18 ++++++++++++++++ sound/soc/codecs/tlv320aic32x4.c | 25 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/tlv320aic32x4.txt (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt new file mode 100644 index 000000000000..db0551088cc4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -0,0 +1,18 @@ +Texas Instruments - tlv320aic32x4 Codec module + +The tlv320aic32x4 serial control bus communicates through I2C protocols + +Required properties: + - compatible: Should be "ti,tlv320aic32x4" + - reg: I2C slave address + +Optional properties: + - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt + + +Example: + +codec: tlv320aic32x4@18 { + compatible = "ti,tlv320aic32x4"; + reg = <0x18>; +}; diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index c541213b1edf..1dd50e48934c 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -669,11 +670,22 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), }; +static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, + struct device_node *np) +{ + aic32x4->swapdacs = false; + aic32x4->micpga_routing = 0; + aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0); + + return 0; +} + static int aic32x4_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct aic32x4_pdata *pdata = i2c->dev.platform_data; struct aic32x4_priv *aic32x4; + struct device_node *np = i2c->dev.of_node; int ret; aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), @@ -692,6 +704,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->swapdacs = pdata->swapdacs; aic32x4->micpga_routing = pdata->micpga_routing; aic32x4->rstn_gpio = pdata->rstn_gpio; + } else if (np) { + ret = aic32x4_parse_dt(aic32x4, np); + if (ret) { + dev_err(&i2c->dev, "Failed to parse DT node\n"); + return ret; + } } else { aic32x4->power_cfg = 0; aic32x4->swapdacs = false; @@ -723,10 +741,17 @@ static const struct i2c_device_id aic32x4_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); +static const struct of_device_id aic32x4_of_id[] = { + { .compatible = "ti,tlv320aic32x4", }, + { /* senitel */ } +}; +MODULE_DEVICE_TABLE(of, aic32x4_of_id); + static struct i2c_driver aic32x4_i2c_driver = { .driver = { .name = "tlv320aic32x4", .owner = THIS_MODULE, + .of_match_table = aic32x4_of_id, }, .probe = aic32x4_i2c_probe, .remove = aic32x4_i2c_remove, -- cgit v1.2.3 From 7e9614ebcf4d74edba864cc91e1e8a3ec6b32fc2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 19:55:45 +0000 Subject: ASoC: wm8962: Hold a runtime PM reference while handling interrupts If the device is runtime suspended then we can't interact with it as it may have been powered off and the register map will be in cache only mode. Signed-off-by: Mark Brown Acked-by: Charles Keepax --- sound/soc/codecs/wm8962.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 97db3b45b411..1996567346c6 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3003,9 +3003,16 @@ static irqreturn_t wm8962_irq(int irq, void *data) unsigned int active; int reg, ret; + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "Failed to resume: %d\n", ret); + return IRQ_NONE; + } + ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK, &mask); if (ret != 0) { + pm_runtime_put(dev); dev_err(dev, "Failed to read interrupt mask: %d\n", ret); return IRQ_NONE; @@ -3013,14 +3020,17 @@ static irqreturn_t wm8962_irq(int irq, void *data) ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active); if (ret != 0) { + pm_runtime_put(dev); dev_err(dev, "Failed to read interrupt: %d\n", ret); return IRQ_NONE; } active &= ~mask; - if (!active) + if (!active) { + pm_runtime_put(dev); return IRQ_NONE; + } /* Acknowledge the interrupts */ ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active); @@ -3070,6 +3080,8 @@ static irqreturn_t wm8962_irq(int irq, void *data) msecs_to_jiffies(250)); } + pm_runtime_put(dev); + return IRQ_HANDLED; } -- cgit v1.2.3 From df6ab65f2fef3d7b769f3ba87c7bb265ace80b4e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 19:59:31 +0000 Subject: ASoC: wm8962: Check if we runtime resume the device when starting FLL Signed-off-by: Mark Brown Acked-by: Charles Keepax --- sound/soc/codecs/wm8962.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 1996567346c6..d7d43c9371f4 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2886,7 +2886,11 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, try_wait_for_completion(&wm8962->fll_lock); - pm_runtime_get_sync(codec->dev); + ret = pm_runtime_get_sync(codec->dev); + if (ret < 0) { + dev_err(codec->dev, "Failed to resume device: %d\n", ret); + return ret; + } snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK | -- cgit v1.2.3 From d6f95e5407674d2f7d61feef81fef96b364d9188 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 20:04:34 +0000 Subject: ASoC: wm8962: Clean up error handling for failed FLL start Don't record the FLL as having started and leave the hardware disabled ensuring we are in a better state if this does happen to be a transient error and making debugging easier. Signed-off-by: Mark Brown Acked-by: Charles Keepax --- sound/soc/codecs/wm8962.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index d7d43c9371f4..cd96d463a505 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2898,8 +2898,6 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); - ret = 0; - /* This should be a massive overestimate but go even * higher if we'll error out */ @@ -2913,14 +2911,17 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, if (timeout == 0 && wm8962->irq) { dev_err(codec->dev, "FLL lock timed out"); - ret = -ETIMEDOUT; + snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, + WM8962_FLL_ENA, 0); + pm_runtime_put(codec->dev); + return -ETIMEDOUT; } wm8962->fll_fref = Fref; wm8962->fll_fout = Fout; wm8962->fll_src = source; - return ret; + return 0; } static int wm8962_mute(struct snd_soc_dai *dai, int mute) -- cgit v1.2.3 From 9d7433b064a6349aae8a266e8243ef75637bec45 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 20:32:06 +0000 Subject: ASoC: wm8962: Reinitialise the IRQ completion rather than just trying it This is better practice. Signed-off-by: Mark Brown Acked-by: Charles Keepax --- sound/soc/codecs/wm8962.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index cd96d463a505..c06bb5088e60 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2884,7 +2884,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda); snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n); - try_wait_for_completion(&wm8962->fll_lock); + reinit_completion(&wm8962->fll_lock); ret = pm_runtime_get_sync(codec->dev); if (ret < 0) { -- cgit v1.2.3 From 0d724f8a3bbc9b0ffd658732714d23694ff4abca Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Jan 2014 12:50:51 +0000 Subject: ASoC: ak4554: Add to SND_SOC_ALL_CODECS For build coverage. Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..034130b336aa 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -25,6 +25,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_ADS117X select SND_SOC_AK4104 if SPI_MASTER select SND_SOC_AK4535 if I2C + select SND_SOC_AK4554 select SND_SOC_AK4641 if I2C select SND_SOC_AK4642 if I2C select SND_SOC_AK4671 if I2C -- cgit v1.2.3 From 50a68fb4bc2516f593ceffa6617c93090d335f31 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 24 Jan 2014 16:07:05 +0000 Subject: ASoC: pcm1681: Convert to params_width() This will help support future enhancements in the way we negotiate parameters in the core. Signed-off-by: Mark Brown --- sound/soc/codecs/pcm1681.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 73f9c3630e2c..e427544183d7 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -172,16 +172,21 @@ static int pcm1681_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); int val = 0, ret; - int pcm_format = params_format(params); priv->rate = params_rate(params); switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_RIGHT_J: - if (pcm_format == SNDRV_PCM_FORMAT_S24_LE) - val = 0x00; - else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) - val = 0x03; + switch (params_width(params)) { + case 24: + val = 0; + break; + case 16: + val = 3; + break; + default: + return -EINVAL; + } break; case SND_SOC_DAIFMT_I2S: val = 0x04; -- cgit v1.2.3 From e48c6d7f01032c42907dc2cd81b73f95490c81a1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 24 Jan 2014 16:07:16 +0000 Subject: ASoC: pcm1792a: Convert to params_width() This will help support future enhancements in the way we negotiate parameters in the core. Signed-off-by: Mark Brown Acked-by: Michael Trimarchi --- sound/soc/codecs/pcm1792a.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c index 7146653a8e16..3a80ba4452df 100644 --- a/sound/soc/codecs/pcm1792a.c +++ b/sound/soc/codecs/pcm1792a.c @@ -107,24 +107,35 @@ static int pcm1792a_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct pcm1792a_private *priv = snd_soc_codec_get_drvdata(codec); int val = 0, ret; - int pcm_format = params_format(params); priv->rate = params_rate(params); switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_RIGHT_J: - if (pcm_format == SNDRV_PCM_FORMAT_S24_LE || - pcm_format == SNDRV_PCM_FORMAT_S32_LE) - val = 0x02; - else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) - val = 0x00; + switch (params_width(params)) { + case 24: + case 32: + val = 2; + break; + case 16: + val = 0; + break; + default: + return -EINVAL; + } break; case SND_SOC_DAIFMT_I2S: - if (pcm_format == SNDRV_PCM_FORMAT_S24_LE || - pcm_format == SNDRV_PCM_FORMAT_S32_LE) - val = 0x05; - else if (pcm_format == SNDRV_PCM_FORMAT_S16_LE) - val = 0x04; + switch (params_width(params)) { + case 24: + case 32: + val = 5; + break; + case 16: + val = 4; + break; + default: + return -EINVAL; + } break; default: dev_err(codec->dev, "Invalid DAI format\n"); -- cgit v1.2.3 From a7e46bd9a19c1e0058c7c8c0b4cc3e6cf101e12a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 3 Feb 2014 14:51:50 +0200 Subject: ASoC: davinci-mcasp: Code cleanup in davinci_mcasp_hw_params() Rearrange the code in the function for readability. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 0518ff2d960c..63b1ecc97cb1 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -611,10 +611,8 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, u8 fifo_level; u8 slots = mcasp->tdm_slots; u8 active_serializers; - int channels; + int channels = params_channels(params); int ret; - struct snd_interval *pcm_channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); /* If mcasp is BCLK master we need to set BCLK divider */ if (mcasp->bclk_master) { @@ -627,19 +625,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); } - channels = pcm_channels->min; - - active_serializers = (channels + slots - 1) / slots; - ret = mcasp_common_hw_param(mcasp, substream->stream, channels); if (ret) return ret; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - fifo_level = mcasp->txnumevt * active_serializers; - else - fifo_level = mcasp->rxnumevt * active_serializers; - if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) ret = mcasp_dit_hw_param(mcasp); else @@ -680,6 +669,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + /* Calculate FIFO level */ + active_serializers = (channels + slots - 1) / slots; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + fifo_level = mcasp->txnumevt * active_serializers; + else + fifo_level = mcasp->rxnumevt * active_serializers; + if (mcasp->version == MCASP_VERSION_2 && !fifo_level) dma_params->acnt = 4; else -- cgit v1.2.3 From d1debafc381cb1fa340b5d0dc79637ad1d523770 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 3 Feb 2014 14:51:51 +0200 Subject: ASoC: davinci-mcasp: Rename platform data struct Rename the struct for the platform data: snd_platform_data -> davinci_mcasp_pdata Since we have users under arch/arm/mach-davinci/ for this struct add temporary define to avoid breakage. The arch code can be updated later to use the new struct name. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- include/linux/platform_data/davinci_asp.h | 4 +++- sound/soc/davinci/davinci-mcasp.c | 16 ++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index 5245992b0367..85ad68f9206a 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -18,7 +18,7 @@ #include -struct snd_platform_data { +struct davinci_mcasp_pdata { u32 tx_dma_offset; u32 rx_dma_offset; int asp_chan_q; /* event queue number for ASP channel */ @@ -87,6 +87,8 @@ struct snd_platform_data { int tx_dma_channel; int rx_dma_channel; }; +/* TODO: Fix arch/arm/mach-davinci/ users and remove this define */ +#define snd_platform_data davinci_mcasp_pdata enum { MCASP_VERSION_1 = 0, /* DM646x */ diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 63b1ecc97cb1..e5fce2ed4dc6 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -823,28 +823,28 @@ static const struct snd_soc_component_driver davinci_mcasp_component = { }; /* Some HW specific values and defaults. The rest is filled in from DT. */ -static struct snd_platform_data dm646x_mcasp_pdata = { +static struct davinci_mcasp_pdata dm646x_mcasp_pdata = { .tx_dma_offset = 0x400, .rx_dma_offset = 0x400, .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_1, }; -static struct snd_platform_data da830_mcasp_pdata = { +static struct davinci_mcasp_pdata da830_mcasp_pdata = { .tx_dma_offset = 0x2000, .rx_dma_offset = 0x2000, .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_2, }; -static struct snd_platform_data am33xx_mcasp_pdata = { +static struct davinci_mcasp_pdata am33xx_mcasp_pdata = { .tx_dma_offset = 0, .rx_dma_offset = 0, .asp_chan_q = EVENTQ_0, .version = MCASP_VERSION_3, }; -static struct snd_platform_data dra7_mcasp_pdata = { +static struct davinci_mcasp_pdata dra7_mcasp_pdata = { .tx_dma_offset = 0x200, .rx_dma_offset = 0x284, .asp_chan_q = EVENTQ_0, @@ -912,11 +912,11 @@ err1: return ret; } -static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( +static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct snd_platform_data *pdata = NULL; + struct davinci_mcasp_pdata *pdata = NULL; const struct of_device_id *match = of_match_device(mcasp_dt_ids, &pdev->dev); struct of_phandle_args dma_spec; @@ -929,7 +929,7 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( pdata = pdev->dev.platform_data; return pdata; } else if (match) { - pdata = (struct snd_platform_data *) match->data; + pdata = (struct davinci_mcasp_pdata*) match->data; } else { /* control shouldn't reach here. something is wrong */ ret = -EINVAL; @@ -1023,7 +1023,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) { struct davinci_pcm_dma_params *dma_data; struct resource *mem, *ioarea, *res, *dat; - struct snd_platform_data *pdata; + struct davinci_mcasp_pdata *pdata; struct davinci_mcasp *mcasp; int ret; -- cgit v1.2.3 From 790bb94b56249b2f40907a0cbf959ca50b4430d2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 3 Feb 2014 14:51:52 +0200 Subject: ASoC: davinci-mcasp: Remove long lines from suspend/resume callbacks Move the context register storage behind of a struct and use a pointer to it in the suspend/resume callbacks to remove the long lines. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 52 +++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index e5fce2ed4dc6..35b9b5505f07 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -37,6 +37,16 @@ #include "davinci-pcm.h" #include "davinci-mcasp.h" +struct davinci_mcasp_context { + u32 txfmtctl; + u32 rxfmtctl; + u32 txfmt; + u32 rxfmt; + u32 aclkxctl; + u32 aclkrctl; + u32 pdir; +}; + struct davinci_mcasp { struct davinci_pcm_dma_params dma_params[2]; struct snd_dmaengine_dai_dma_data dma_data[2]; @@ -63,15 +73,7 @@ struct davinci_mcasp { bool dat_port; #ifdef CONFIG_PM_SLEEP - struct { - u32 txfmtctl; - u32 rxfmtctl; - u32 txfmt; - u32 rxfmt; - u32 aclkxctl; - u32 aclkrctl; - u32 pdir; - } context; + struct davinci_mcasp_context context; #endif }; @@ -741,14 +743,15 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { static int davinci_mcasp_suspend(struct snd_soc_dai *dai) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + struct davinci_mcasp_context *context = &mcasp->context; - mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); - mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); - mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); - mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); - mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); - mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); - mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); + context->txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG); + context->rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); + context->txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG); + context->rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG); + context->aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); + context->aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG); + context->pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG); return 0; } @@ -756,14 +759,15 @@ static int davinci_mcasp_suspend(struct snd_soc_dai *dai) static int davinci_mcasp_resume(struct snd_soc_dai *dai) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt); - mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl); - mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir); + struct davinci_mcasp_context *context = &mcasp->context; + + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, context->txfmtctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, context->rxfmtctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, context->txfmt); + mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, context->rxfmt); + mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, context->aclkxctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, context->aclkrctl); + mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, context->pdir); return 0; } -- cgit v1.2.3 From 1659b84312617fe846def362f6ccdc73ec452d44 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Feb 2014 17:24:21 +0100 Subject: ASoC: h1940_uda1380: Don't modify runtime->hw Individual components are not supposed to modify the runtime->hw struct itself as it is manged by the ASoC core. If a component wants to limit the list of supported rates it should set a rate constraint. The h1940_uda1380 already does this, so it is safe to just remove the code that modifies runtime->hw. Signed-off-by: Lars-Peter Clausen Acked-by: Vasily Khoruzhick Signed-off-by: Mark Brown --- sound/soc/samsung/h1940_uda1380.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 0003b661ab62..88b09e022503 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -66,10 +66,6 @@ static int h1940_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - runtime->hw.rate_min = hw_rates.list[0]; - runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates); -- cgit v1.2.3 From 4f6136fa0d6200f1c6eebfb1f12572ca6b770927 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Feb 2014 17:24:22 +0100 Subject: ASoC: rx1950_uda1380: Don't modify runtime->hw Individual components are not supposed to modify the runtime->hw struct itself as it is manged by the ASoC core. If a component wants to limit the list of supported rates it should set a rate constraint. The rx1950_uda1380 already does this, so it is safe to just remove the code that modifies runtime->hw. Signed-off-by: Lars-Peter Clausen Acked-by: Vasily Khoruzhick Signed-off-by: Mark Brown --- sound/soc/samsung/rx1950_uda1380.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index afbfe4aa2cbf..2982d9e7f268 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c @@ -131,10 +131,6 @@ static int rx1950_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - runtime->hw.rate_min = hw_rates.list[0]; - runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates); -- cgit v1.2.3 From 1291e14175e6b83efe1464f32189acb21bc4be09 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 23 Jan 2014 12:58:16 +0000 Subject: ASoC: codecs: Make OF supported CODECs visible in Kconfig Now that we have a generic card driver we can't rely on the card driver selecting the CODECs for us so make the CODECs that can be enabled with OF directly selectable in Kconfig. For the platforms not using OF it's not clear that we don't still want to have some board specific selection since the kernel needs to contain code to register the devices; ACPI could provide this from firmware does not yet support any kind of generic card. It may also be desirable to hide these if OF is not enabled to reduce noise. Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 97 +++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 34 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 034130b336aa..f0bdcc5abe83 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -190,8 +190,9 @@ config SND_SOC_AD73311 tristate config SND_SOC_ADAU1701 + tristate "Analog Devices ADAU1701 CODEC" + depends on I2C select SND_SOC_SIGMADSP - tristate config SND_SOC_ADAU1373 tristate @@ -203,28 +204,31 @@ config SND_SOC_ADS117X tristate config SND_SOC_AK4104 - tristate + tristate "AKM AK4104 CODEC" + depends on SPI_MASTER config SND_SOC_AK4535 tristate config SND_SOC_AK4554 - tristate + tristate "AKM AK4554 CODEC" config SND_SOC_AK4641 tristate config SND_SOC_AK4642 - tristate + tristate "AKM AK4642 CODEC" + depends on I2C config SND_SOC_AK4671 tristate config SND_SOC_AK5386 - tristate + tristate "AKM AK5638 CODEC" config SND_SOC_ALC5623 tristate + config SND_SOC_ALC5632 tristate @@ -235,14 +239,17 @@ config SND_SOC_CS42L51 tristate config SND_SOC_CS42L52 - tristate + tristate "Cirrus Logic CS42L52 CODEC" + depends on I2C config SND_SOC_CS42L73 - tristate + tristate "Cirrus Logic CS42L73 CODEC" + depends on I2C # Cirrus Logic CS4270 Codec config SND_SOC_CS4270 - tristate + tristate "Cirrus Logic CS4270 CODEC" + depends on I2C # Cirrus Logic CS4270 Codec VD = 3.3V Errata # Select if you are affected by the errata where the part will not function @@ -253,7 +260,8 @@ config SND_SOC_CS4270_VD33_ERRATA depends on SND_SOC_CS4270 config SND_SOC_CS4271 - tristate + tristate "Cirrus Logic CS4271 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_CX20442 tristate @@ -284,6 +292,9 @@ config SND_SOC_BT_SCO config SND_SOC_DMIC tristate +config SND_SOC_HDMI_CODEC + tristate "HDMI stub CODEC" + config SND_SOC_ISABELLE tristate @@ -302,14 +313,13 @@ config SND_SOC_MAX98095 config SND_SOC_MAX9850 tristate -config SND_SOC_HDMI_CODEC - tristate - config SND_SOC_PCM1681 - tristate + tristate "Texas Instruments PCM1681 CODEC" + depends on I2C config SND_SOC_PCM1792A - tristate + tristate "Texas Instruments PCM1792A CODEC" + depends on SPI_MASTER config SND_SOC_PCM3008 tristate @@ -322,7 +332,8 @@ config SND_SOC_RT5640 #Freescale sgtl5000 codec config SND_SOC_SGTL5000 - tristate + tristate "Freescale SGTL5000 CODEC" + depends on I2C config SND_SOC_SI476X tristate @@ -335,7 +346,7 @@ config SND_SOC_SN95031 tristate config SND_SOC_SPDIF - tristate + tristate "S/PDIF CODEC" config SND_SOC_SSM2518 tristate @@ -353,7 +364,8 @@ config SND_SOC_STAC9766 tristate config SND_SOC_TAS5086 - tristate + tristate "Texas Instruments TAS5086 speaker amplifier" + depends on I2C config SND_SOC_TLV320AIC23 tristate @@ -366,7 +378,8 @@ config SND_SOC_TLV320AIC32X4 tristate config SND_SOC_TLV320AIC3X - tristate + tristate "Texas Instruments TLV320AIC3x CODECs" + depends on I2C config SND_SOC_TLV320DAC33 tristate @@ -415,55 +428,69 @@ config SND_SOC_WM8400 tristate config SND_SOC_WM8510 - tristate + tristate "Wolfson Microelectronics WM8510 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8523 - tristate + tristate "Wolfson Microelectronics WM8523 DAC" + depends on I2C config SND_SOC_WM8580 - tristate + tristate "Wolfson Microelectronics WM8523 CODEC" + depends on I2C config SND_SOC_WM8711 - tristate + tristate "Wolfson Microelectronics WM8711 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8727 tristate config SND_SOC_WM8728 - tristate + tristate "Wolfson Microelectronics WM8728 DAC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8731 - tristate + tristate "Wolfson Microelectronics WM8731 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8737 - tristate + tristate "Wolfson Microelectronics WM8737 ADC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8741 - tristate + tristate "Wolfson Microelectronics WM8737 DAC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8750 - tristate + tristate "Wolfson Microelectronics WM8750 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8753 - tristate + tristate "Wolfson Microelectronics WM8753 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8770 - tristate + tristate "Wolfson Microelectronics WM8770 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8776 - tristate + tristate "Wolfson Microelectronics WM8776 CODEC" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8782 tristate config SND_SOC_WM8804 - tristate + tristate "Wolfson Microelectronics WM8804 S/PDIF transceiver" + depends on SND_SOC_I2C_AND_SPI config SND_SOC_WM8900 tristate config SND_SOC_WM8903 - tristate + tristate "Wolfson Microelectronics WM8903 CODEC" + depends on I2C config SND_SOC_WM8904 tristate @@ -481,7 +508,8 @@ config SND_SOC_WM8961 tristate config SND_SOC_WM8962 - tristate + tristate "Wolfson Microelectronics WM8962 CODEC" + depends on I2C config SND_SOC_WM8971 tristate @@ -554,4 +582,5 @@ config SND_SOC_ML26124 tristate config SND_SOC_TPA6130A2 - tristate + tristate "Texas Instruments TPA6130A2 headphone amplifier" + depends on I2C -- cgit v1.2.3 From b224e9b857438afbd802f47008ab36863f71d8d1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Feb 2014 14:48:22 +0100 Subject: ASoC: cs4271: Remove outdated comment Commit 1b1861ead ("ASoC: cs4271: convert to direct regmap API usage") removed the bus_type field from the cs4271_private struct, but left the comment that described the field in there. This patch removes the comment. Signed-off-by: Lars-Peter Clausen Acked-by: Daniel Mack Signed-off-by: Mark Brown --- sound/soc/codecs/cs4271.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index ce05fd93dc74..f7bbe6fdba67 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -159,7 +159,6 @@ static bool cs4271_volatile_reg(struct device *dev, unsigned int reg) } struct cs4271_private { - /* SND_SOC_I2C or SND_SOC_SPI */ unsigned int mclk; bool master; bool deemph; -- cgit v1.2.3 From 6e84b9768dfb299a9881895b331e3e532041fae4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Feb 2014 20:55:31 +0100 Subject: ASoC: cs42l73: Don't mix SNDRV_PCM_RATE_KNOT with specific rates SNDRV_PCM_RATE_KNOT means that the device can support rates that can not be expressed using the rate bits. The driver will provide a list of those rates specified through constraints. Any rate bits that are set in the rates mask will be ignored. So setting other rate bits besides SNDRV_PCM_RATE_KNOT wont have any effect, but might be confusing to the casual reader, so remove them. Signed-off-by: Lars-Peter Clausen Acked-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l73.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 549d5d6a3fef..7cae046c7dd0 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1255,9 +1255,6 @@ static int cs42l73_pcm_startup(struct snd_pcm_substream *substream, return 0; } -/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */ -#define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT) - #define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) @@ -1278,14 +1275,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .stream_name = "XSP Playback", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .capture = { .stream_name = "XSP Capture", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, @@ -1298,14 +1295,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .stream_name = "ASP Playback", .channels_min = 2, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .capture = { .stream_name = "ASP Capture", .channels_min = 2, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, @@ -1318,14 +1315,14 @@ static struct snd_soc_dai_driver cs42l73_dai[] = { .stream_name = "VSP Playback", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .capture = { .stream_name = "VSP Capture", .channels_min = 1, .channels_max = 2, - .rates = CS42L73_RATES, + .rates = SNDRV_PCM_RATE_KNOT, .formats = CS42L73_FORMATS, }, .ops = &cs42l73_ops, -- cgit v1.2.3 From 5a3af1293194d07610fd7fdf680b3e7f916dca84 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 6 Feb 2014 12:03:27 +0000 Subject: ASoC: pcm512x: Add PCM512x driver The PCM512x devices are a family of monolithic CMOS integrated circuits that include a stereo digital-to-analog converter and additional support circuitry. This is an initial driver which supports some core functionality for the device which covers common use cases but does not cover all features. Currently only slave clocking modes with automatic clock configuration are supported and most of the DSP configuration for the device is not enabled. Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/pcm512x.txt | 30 + sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/pcm512x.c | 672 +++++++++++++++++++++ sound/soc/codecs/pcm512x.h | 142 +++++ 5 files changed, 850 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/pcm512x.txt create mode 100644 sound/soc/codecs/pcm512x.c create mode 100644 sound/soc/codecs/pcm512x.h (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/pcm512x.txt b/Documentation/devicetree/bindings/sound/pcm512x.txt new file mode 100644 index 000000000000..faff75e64573 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/pcm512x.txt @@ -0,0 +1,30 @@ +PCM512x audio CODECs + +These devices support both I2C and SPI (configured with pin strapping +on the board). + +Required properties: + + - compatible : One of "ti,pcm5121" or "ti,pcm5122" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. + + - AVDD-supply, DVDD-supply, and CPVDD-supply : power supplies for the + device, as covered in bindings/regulator/regulator.txt + +Optional properties: + + - clocks : A clock specifier for the clock connected as SCLK. If this + is absent the device will be configured to clock from BCLK. + +Example: + + pcm5122: pcm5122@4c { + compatible = "ti,pcm5122"; + reg = <0x4c>; + + AVDD-supply = <®_3v3_analog>; + DVDD-supply = <®_1v8>; + CPVDD-supply = <®_3v3>; + }; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..56d0c2845680 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -59,6 +59,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM1681 if I2C select SND_SOC_PCM1792A if SPI_MASTER select SND_SOC_PCM3008 + select SND_SOC_PCM512x if SND_SOC_I2C_AND_SPI select SND_SOC_RT5631 if I2C select SND_SOC_RT5640 if I2C select SND_SOC_SGTL5000 if I2C @@ -313,6 +314,9 @@ config SND_SOC_PCM1792A config SND_SOC_PCM3008 tristate +config SND_SOC_PCM512x + tristate "Texas Instruments PCM512x CODECs" + config SND_SOC_RT5631 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..d3b536fc075d 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -46,6 +46,7 @@ snd-soc-hdmi-codec-objs := hdmi.o snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm1792a-codec-objs := pcm1792a.o snd-soc-pcm3008-objs := pcm3008.o +snd-soc-pcm512x-objs := pcm512x.o snd-soc-rt5631-objs := rt5631.o snd-soc-rt5640-objs := rt5640.o snd-soc-sgtl5000-objs := sgtl5000.o @@ -179,6 +180,7 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o +obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c new file mode 100644 index 000000000000..5ad3e9aa3cb4 --- /dev/null +++ b/sound/soc/codecs/pcm512x.c @@ -0,0 +1,672 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcm512x.h" + +#define PCM512x_NUM_SUPPLIES 3 +static const char *pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { + "AVDD", + "DVDD", + "CPVDD", +}; + +struct pcm512x_priv { + struct regmap *regmap; + struct clk *sclk; + struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES]; + struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES]; +}; + +/* + * We can't use the same notifier block for more than one supply and + * there's no way I can see to get from a callback to the caller + * except container_of(). + */ +#define PCM512x_REGULATOR_EVENT(n) \ +static int pcm512x_regulator_event_##n(struct notifier_block *nb, \ + unsigned long event, void *data) \ +{ \ + struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \ + supply_nb[n]); \ + if (event & REGULATOR_EVENT_DISABLE) { \ + regcache_mark_dirty(pcm512x->regmap); \ + regcache_cache_only(pcm512x->regmap, true); \ + } \ + return 0; \ +} + +PCM512x_REGULATOR_EVENT(0) +PCM512x_REGULATOR_EVENT(1) +PCM512x_REGULATOR_EVENT(2) + +static const struct reg_default pcm512x_reg_defaults[] = { + { PCM512x_RESET, 0x00 }, + { PCM512x_POWER, 0x00 }, + { PCM512x_MUTE, 0x00 }, + { PCM512x_DSP, 0x00 }, + { PCM512x_PLL_REF, 0x00 }, + { PCM512x_DAC_ROUTING, 0x11 }, + { PCM512x_DSP_PROGRAM, 0x01 }, + { PCM512x_CLKDET, 0x00 }, + { PCM512x_AUTO_MUTE, 0x00 }, + { PCM512x_ERROR_DETECT, 0x00 }, + { PCM512x_DIGITAL_VOLUME_1, 0x00 }, + { PCM512x_DIGITAL_VOLUME_2, 0x30 }, + { PCM512x_DIGITAL_VOLUME_3, 0x30 }, + { PCM512x_DIGITAL_MUTE_1, 0x22 }, + { PCM512x_DIGITAL_MUTE_2, 0x00 }, + { PCM512x_DIGITAL_MUTE_3, 0x07 }, +}; + +static bool pcm512x_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PCM512x_RESET: + case PCM512x_POWER: + case PCM512x_MUTE: + case PCM512x_PLL_EN: + case PCM512x_SPI_MISO_FUNCTION: + case PCM512x_DSP: + case PCM512x_GPIO_EN: + case PCM512x_BCLK_LRCLK_CFG: + case PCM512x_DSP_GPIO_INPUT: + case PCM512x_MASTER_MODE: + case PCM512x_PLL_REF: + case PCM512x_PLL_COEFF_0: + case PCM512x_PLL_COEFF_1: + case PCM512x_PLL_COEFF_2: + case PCM512x_PLL_COEFF_3: + case PCM512x_PLL_COEFF_4: + case PCM512x_DSP_CLKDIV: + case PCM512x_DAC_CLKDIV: + case PCM512x_NCP_CLKDIV: + case PCM512x_OSR_CLKDIV: + case PCM512x_MASTER_CLKDIV_1: + case PCM512x_MASTER_CLKDIV_2: + case PCM512x_FS_SPEED_MODE: + case PCM512x_IDAC_1: + case PCM512x_IDAC_2: + case PCM512x_ERROR_DETECT: + case PCM512x_I2S_1: + case PCM512x_I2S_2: + case PCM512x_DAC_ROUTING: + case PCM512x_DSP_PROGRAM: + case PCM512x_CLKDET: + case PCM512x_AUTO_MUTE: + case PCM512x_DIGITAL_VOLUME_1: + case PCM512x_DIGITAL_VOLUME_2: + case PCM512x_DIGITAL_VOLUME_3: + case PCM512x_DIGITAL_MUTE_1: + case PCM512x_DIGITAL_MUTE_2: + case PCM512x_DIGITAL_MUTE_3: + case PCM512x_GPIO_OUTPUT_1: + case PCM512x_GPIO_OUTPUT_2: + case PCM512x_GPIO_OUTPUT_3: + case PCM512x_GPIO_OUTPUT_4: + case PCM512x_GPIO_OUTPUT_5: + case PCM512x_GPIO_OUTPUT_6: + case PCM512x_GPIO_CONTROL_1: + case PCM512x_GPIO_CONTROL_2: + case PCM512x_OVERFLOW: + case PCM512x_RATE_DET_1: + case PCM512x_RATE_DET_2: + case PCM512x_RATE_DET_3: + case PCM512x_RATE_DET_4: + case PCM512x_ANALOG_MUTE_DET: + case PCM512x_GPIN: + case PCM512x_DIGITAL_MUTE_DET: + return true; + default: + return false; + } +} + +static bool pcm512x_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PCM512x_PLL_EN: + case PCM512x_OVERFLOW: + case PCM512x_RATE_DET_1: + case PCM512x_RATE_DET_2: + case PCM512x_RATE_DET_3: + case PCM512x_RATE_DET_4: + case PCM512x_ANALOG_MUTE_DET: + case PCM512x_GPIN: + case PCM512x_DIGITAL_MUTE_DET: + return true; + default: + return false; + } +} + +static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); + +static const char *pcm512x_dsp_program_texts[] = { + "FIR interpolation with de-emphasis", + "Low latency IIR with de-emphasis", + "Fixed process flow", + "High attenuation with de-emphasis", + "Ringing-less low latency FIR", +}; + +static const unsigned int pcm512x_dsp_program_values[] = { + 1, + 2, + 3, + 5, + 7, +}; + +static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, + PCM512x_DSP_PROGRAM, 0, 0x1f, + pcm512x_dsp_program_texts, + pcm512x_dsp_program_values); + +static const char *pcm512x_clk_missing_text[] = { + "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s" +}; + +static const struct soc_enum pcm512x_clk_missing = + SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text); + +static const char *pcm512x_autom_text[] = { + "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s" +}; + +static const struct soc_enum pcm512x_autom_l = + SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8, + pcm512x_autom_text); + +static const struct soc_enum pcm512x_autom_r = + SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8, + pcm512x_autom_text); + +static const char *pcm512x_ramp_rate_text[] = { + "1 sample/update", "2 samples/update", "4 samples/update", + "Immediate" +}; + +static const struct soc_enum pcm512x_vndf = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4, + pcm512x_ramp_rate_text); + +static const struct soc_enum pcm512x_vnuf = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4, + pcm512x_ramp_rate_text); + +static const struct soc_enum pcm512x_vedf = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4, + pcm512x_ramp_rate_text); + +static const char *pcm512x_ramp_step_text[] = { + "4dB/step", "2dB/step", "1dB/step", "0.5dB/step" +}; + +static const struct soc_enum pcm512x_vnds = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4, + pcm512x_ramp_step_text); + +static const struct soc_enum pcm512x_vnus = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4, + pcm512x_ramp_step_text); + +static const struct soc_enum pcm512x_veds = + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4, + pcm512x_ramp_step_text); + +static const struct snd_kcontrol_new pcm512x_controls[] = { +SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2, + PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv), +SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT, + PCM512x_RQMR_SHIFT, 1, 1), + +SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1), +SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program), + +SOC_ENUM("Clock Missing Period", pcm512x_clk_missing), +SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l), +SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r), +SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3, + PCM512x_ACTL_SHIFT, 1, 0), +SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT, + PCM512x_AMLR_SHIFT, 1, 0), + +SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf), +SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds), +SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf), +SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus), +SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf), +SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds), +}; + +static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = { +SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), +SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), + +SND_SOC_DAPM_OUTPUT("OUTL"), +SND_SOC_DAPM_OUTPUT("OUTR"), +}; + +static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = { + { "DACL", NULL, "Playback" }, + { "DACR", NULL, "Playback" }, + + { "OUTL", NULL, "DACL" }, + { "OUTR", NULL, "DACR" }, +}; + +static int pcm512x_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev); + int ret; + + switch (level) { + case SND_SOC_BIAS_ON: + case SND_SOC_BIAS_PREPARE: + break; + + case SND_SOC_BIAS_STANDBY: + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQST, 0); + if (ret != 0) { + dev_err(codec->dev, "Failed to remove standby: %d\n", + ret); + return ret; + } + break; + + case SND_SOC_BIAS_OFF: + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQST, PCM512x_RQST); + if (ret != 0) { + dev_err(codec->dev, "Failed to request standby: %d\n", + ret); + return ret; + } + break; + } + + codec->dapm.bias_level = level; + + return 0; +} + +static struct snd_soc_dai_driver pcm512x_dai = { + .name = "pcm512x-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE + }, +}; + +static struct snd_soc_codec_driver pcm512x_codec_driver = { + .set_bias_level = pcm512x_set_bias_level, + .idle_bias_off = true, + + .controls = pcm512x_controls, + .num_controls = ARRAY_SIZE(pcm512x_controls), + .dapm_widgets = pcm512x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets), + .dapm_routes = pcm512x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), +}; + +static const struct regmap_config pcm512x_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .readable_reg = pcm512x_readable, + .volatile_reg = pcm512x_volatile, + + .max_register = PCM512x_MAX_REGISTER, + .reg_defaults = pcm512x_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + +static const struct of_device_id pcm512x_of_match[] = { + { .compatible = "ti,pcm5121", }, + { .compatible = "ti,pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm512x_of_match); + +static int pcm512x_probe(struct device *dev, struct regmap *regmap) +{ + struct pcm512x_priv *pcm512x; + int i, ret; + + pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL); + if (!pcm512x) + return -ENOMEM; + + dev_set_drvdata(dev, pcm512x); + pcm512x->regmap = regmap; + + for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) + pcm512x->supplies[i].supply = pcm512x_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to get supplies: %d\n", ret); + return ret; + } + + pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0; + pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1; + pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2; + + for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) { + ret = regulator_register_notifier(pcm512x->supplies[i].consumer, + &pcm512x->supply_nb[i]); + if (ret != 0) { + dev_err(dev, + "Failed to register regulator notifier: %d\n", + ret); + } + } + + ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + /* Reset the device, verifying I/O in the process for I2C */ + ret = regmap_write(regmap, PCM512x_RESET, + PCM512x_RSTM | PCM512x_RSTR); + if (ret != 0) { + dev_err(dev, "Failed to reset device: %d\n", ret); + goto err; + } + + ret = regmap_write(regmap, PCM512x_RESET, 0); + if (ret != 0) { + dev_err(dev, "Failed to reset device: %d\n", ret); + goto err; + } + + pcm512x->sclk = devm_clk_get(dev, NULL); + if (IS_ERR(pcm512x->sclk)) { + if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_info(dev, "No SCLK, using BCLK: %ld\n", + PTR_ERR(pcm512x->sclk)); + + /* Disable reporting of missing SCLK as an error */ + regmap_update_bits(regmap, PCM512x_ERROR_DETECT, + PCM512x_IDCH, PCM512x_IDCH); + + /* Switch PLL input to BCLK */ + regmap_update_bits(regmap, PCM512x_PLL_REF, + PCM512x_SREF, PCM512x_SREF); + } else { + ret = clk_prepare_enable(pcm512x->sclk); + if (ret != 0) { + dev_err(dev, "Failed to enable SCLK: %d\n", ret); + return ret; + } + } + + /* Default to standby mode */ + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQST, PCM512x_RQST); + if (ret != 0) { + dev_err(dev, "Failed to request standby: %d\n", + ret); + goto err_clk; + } + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + ret = snd_soc_register_codec(dev, &pcm512x_codec_driver, + &pcm512x_dai, 1); + if (ret != 0) { + dev_err(dev, "Failed to register CODEC: %d\n", ret); + goto err_pm; + } + + return 0; + +err_pm: + pm_runtime_disable(dev); +err_clk: + if (!IS_ERR(pcm512x->sclk)) + clk_disable_unprepare(pcm512x->sclk); +err: + regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + return ret; +} + +static void pcm512x_remove(struct device *dev) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); + + snd_soc_unregister_codec(dev); + pm_runtime_disable(dev); + if (!IS_ERR(pcm512x->sclk)) + clk_disable_unprepare(pcm512x->sclk); + regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); +} + +static int pcm512x_suspend(struct device *dev) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); + int ret; + + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQPD, PCM512x_RQPD); + if (ret != 0) { + dev_err(dev, "Failed to request power down: %d\n", ret); + return ret; + } + + ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to disable supplies: %d\n", ret); + return ret; + } + + if (!IS_ERR(pcm512x->sclk)) + clk_disable_unprepare(pcm512x->sclk); + + return 0; +} + +static int pcm512x_resume(struct device *dev) +{ + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); + int ret; + + if (!IS_ERR(pcm512x->sclk)) { + ret = clk_prepare_enable(pcm512x->sclk); + if (ret != 0) { + dev_err(dev, "Failed to enable SCLK: %d\n", ret); + return ret; + } + } + + ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies), + pcm512x->supplies); + if (ret != 0) { + dev_err(dev, "Failed to enable supplies: %d\n", ret); + return ret; + } + + regcache_cache_only(pcm512x->regmap, false); + ret = regcache_sync(pcm512x->regmap); + if (ret != 0) { + dev_err(dev, "Failed to sync cache: %d\n", ret); + return ret; + } + + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER, + PCM512x_RQPD, 0); + if (ret != 0) { + dev_err(dev, "Failed to remove power down: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct dev_pm_ops pcm512x_pm_ops = { + SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL) +}; + +#if IS_ENABLED(CONFIG_I2C) +static int pcm512x_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return pcm512x_probe(&i2c->dev, regmap); +} + +static int pcm512x_i2c_remove(struct i2c_client *i2c) +{ + pcm512x_remove(&i2c->dev); + return 0; +} + +static const struct i2c_device_id pcm512x_i2c_id[] = { + { "pcm5121", }, + { "pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); + +static struct i2c_driver pcm512x_i2c_driver = { + .probe = pcm512x_i2c_probe, + .remove = pcm512x_i2c_remove, + .id_table = pcm512x_i2c_id, + .driver = { + .name = "pcm512x", + .owner = THIS_MODULE, + .of_match_table = pcm512x_of_match, + .pm = &pcm512x_pm_ops, + }, +}; +#endif + +#if defined(CONFIG_SPI_MASTER) +static int pcm512x_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + int ret; + + regmap = devm_regmap_init_spi(spi, &pcm512x_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + return ret; + } + + return pcm512x_probe(&spi->dev, regmap); +} + +static int pcm512x_spi_remove(struct spi_device *spi) +{ + pcm512x_remove(&spi->dev); + return 0; +} + +static const struct spi_device_id pcm512x_spi_id[] = { + { "pcm5121", }, + { "pcm5122", }, + { }, +}; +MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); + +static struct spi_driver pcm512x_spi_driver = { + .probe = pcm512x_spi_probe, + .remove = pcm512x_spi_remove, + .id_table = pcm512x_spi_id, + .driver = { + .name = "pcm512x", + .owner = THIS_MODULE, + .of_match_table = pcm512x_of_match, + .pm = &pcm512x_pm_ops, + }, +}; +#endif + +static int __init pcm512x_modinit(void) +{ + int ret = 0; + +#if IS_ENABLED(CONFIG_I2C) + ret = i2c_add_driver(&pcm512x_i2c_driver); + if (ret) { + printk(KERN_ERR "Failed to register pcm512x I2C driver: %d\n", + ret); + } +#endif +#if defined(CONFIG_SPI_MASTER) + ret = spi_register_driver(&pcm512x_spi_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register pcm512x SPI driver: %d\n", + ret); + } +#endif + return ret; +} +module_init(pcm512x_modinit); + +static void __exit pcm512x_exit(void) +{ +#if IS_ENABLED(CONFIG_I2C) + i2c_del_driver(&pcm512x_i2c_driver); +#endif +#if defined(CONFIG_SPI_MASTER) + spi_unregister_driver(&pcm512x_spi_driver); +#endif +} +module_exit(pcm512x_exit); + +MODULE_DESCRIPTION("ASoC PCM512x codec driver"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h new file mode 100644 index 000000000000..b2f518ecb35c --- /dev/null +++ b/sound/soc/codecs/pcm512x.h @@ -0,0 +1,142 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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 _SND_SOC_PCM512X +#define _SND_SOC_PCM512X + +#define PCM512x_PAGE_0_BASE 0 + +#define PCM512x_PAGE 0 + +#define PCM512x_RESET (PCM512x_PAGE_0_BASE + 1) +#define PCM512x_POWER (PCM512x_PAGE_0_BASE + 2) +#define PCM512x_MUTE (PCM512x_PAGE_0_BASE + 3) +#define PCM512x_PLL_EN (PCM512x_PAGE_0_BASE + 4) +#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_0_BASE + 6) +#define PCM512x_DSP (PCM512x_PAGE_0_BASE + 7) +#define PCM512x_GPIO_EN (PCM512x_PAGE_0_BASE + 8) +#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_0_BASE + 9) +#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_0_BASE + 10) +#define PCM512x_MASTER_MODE (PCM512x_PAGE_0_BASE + 12) +#define PCM512x_PLL_REF (PCM512x_PAGE_0_BASE + 13) +#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_0_BASE + 20) +#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_0_BASE + 21) +#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_0_BASE + 22) +#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_0_BASE + 23) +#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_0_BASE + 24) +#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_0_BASE + 27) +#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_0_BASE + 28) +#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_0_BASE + 29) +#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_0_BASE + 30) +#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_0_BASE + 32) +#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_0_BASE + 33) +#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_0_BASE + 34) +#define PCM512x_IDAC_1 (PCM512x_PAGE_0_BASE + 35) +#define PCM512x_IDAC_2 (PCM512x_PAGE_0_BASE + 36) +#define PCM512x_ERROR_DETECT (PCM512x_PAGE_0_BASE + 37) +#define PCM512x_I2S_1 (PCM512x_PAGE_0_BASE + 40) +#define PCM512x_I2S_2 (PCM512x_PAGE_0_BASE + 41) +#define PCM512x_DAC_ROUTING (PCM512x_PAGE_0_BASE + 42) +#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_0_BASE + 43) +#define PCM512x_CLKDET (PCM512x_PAGE_0_BASE + 44) +#define PCM512x_AUTO_MUTE (PCM512x_PAGE_0_BASE + 59) +#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_0_BASE + 60) +#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_0_BASE + 61) +#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_0_BASE + 62) +#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_0_BASE + 63) +#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_0_BASE + 64) +#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_0_BASE + 65) +#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_0_BASE + 80) +#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_0_BASE + 81) +#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_0_BASE + 82) +#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_0_BASE + 83) +#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_0_BASE + 84) +#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_0_BASE + 85) +#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_0_BASE + 86) +#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_0_BASE + 87) +#define PCM512x_OVERFLOW (PCM512x_PAGE_0_BASE + 90) +#define PCM512x_RATE_DET_1 (PCM512x_PAGE_0_BASE + 91) +#define PCM512x_RATE_DET_2 (PCM512x_PAGE_0_BASE + 92) +#define PCM512x_RATE_DET_3 (PCM512x_PAGE_0_BASE + 93) +#define PCM512x_RATE_DET_4 (PCM512x_PAGE_0_BASE + 94) +#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_0_BASE + 108) +#define PCM512x_GPIN (PCM512x_PAGE_0_BASE + 119) +#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_0_BASE + 120) + +#define PCM512x_MAX_REGISTER (PCM512x_PAGE_0_BASE + 120) + +/* Page 0, Register 1 - reset */ +#define PCM512x_RSTR (1 << 0) +#define PCM512x_RSTM (1 << 4) + +/* Page 0, Register 2 - power */ +#define PCM512x_RQPD (1 << 0) +#define PCM512x_RQPD_SHIFT 0 +#define PCM512x_RQST (1 << 4) +#define PCM512x_RQST_SHIFT 4 + +/* Page 0, Register 3 - mute */ +#define PCM512x_RQMR_SHIFT 0 +#define PCM512x_RQML_SHIFT 4 + +/* Page 0, Register 4 - PLL */ +#define PCM512x_PLCE (1 << 0) +#define PCM512x_RLCE_SHIFT 0 +#define PCM512x_PLCK (1 << 4) +#define PCM512x_PLCK_SHIFT 4 + +/* Page 0, Register 7 - DSP */ +#define PCM512x_SDSL (1 << 0) +#define PCM512x_SDSL_SHIFT 0 +#define PCM512x_DEMP (1 << 4) +#define PCM512x_DEMP_SHIFT 4 + +/* Page 0, Register 13 - PLL reference */ +#define PCM512x_SREF (1 << 4) + +/* Page 0, Register 37 - Error detection */ +#define PCM512x_IPLK (1 << 0) +#define PCM512x_DCAS (1 << 1) +#define PCM512x_IDCM (1 << 2) +#define PCM512x_IDCH (1 << 3) +#define PCM512x_IDSK (1 << 4) +#define PCM512x_IDBK (1 << 5) +#define PCM512x_IDFS (1 << 6) + +/* Page 0, Register 42 - DAC routing */ +#define PCM512x_AUPR_SHIFT 0 +#define PCM512x_AUPL_SHIFT 4 + +/* Page 0, Register 59 - auto mute */ +#define PCM512x_ATMR_SHIFT 0 +#define PCM512x_ATML_SHIFT 4 + +/* Page 0, Register 63 - ramp rates */ +#define PCM512x_VNDF_SHIFT 6 +#define PCM512x_VNDS_SHIFT 4 +#define PCM512x_VNUF_SHIFT 2 +#define PCM512x_VNUS_SHIFT 0 + +/* Page 0, Register 64 - emergency ramp rates */ +#define PCM512x_VEDF_SHIFT 6 +#define PCM512x_VEDS_SHIFT 4 + +/* Page 0, Register 65 - Digital mute enables */ +#define PCM512x_ACTL_SHIFT 2 +#define PCM512x_AMLE_SHIFT 1 +#define PCM512x_AMLR_SHIFT 0 + +#endif -- cgit v1.2.3 From 06d0ffcc5c12ad49786141fa9768da38485a8a61 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 6 Feb 2014 14:33:52 +0000 Subject: ASoC: pcm512x: More constification Since the core now takes const strings for enums we should be constifying them (and the regulator supplies while we're at it). Reported-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/pcm512x.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 5ad3e9aa3cb4..1150381fc373 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -30,7 +30,7 @@ #include "pcm512x.h" #define PCM512x_NUM_SUPPLIES 3 -static const char *pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { +static const char * const pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = { "AVDD", "DVDD", "CPVDD", @@ -167,7 +167,7 @@ static bool pcm512x_volatile(struct device *dev, unsigned int reg) static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); -static const char *pcm512x_dsp_program_texts[] = { +static const char * const pcm512x_dsp_program_texts[] = { "FIR interpolation with de-emphasis", "Low latency IIR with de-emphasis", "Fixed process flow", @@ -188,14 +188,14 @@ static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, pcm512x_dsp_program_texts, pcm512x_dsp_program_values); -static const char *pcm512x_clk_missing_text[] = { +static const char * const pcm512x_clk_missing_text[] = { "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s" }; static const struct soc_enum pcm512x_clk_missing = SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text); -static const char *pcm512x_autom_text[] = { +static const char * const pcm512x_autom_text[] = { "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s" }; @@ -207,7 +207,7 @@ static const struct soc_enum pcm512x_autom_r = SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8, pcm512x_autom_text); -static const char *pcm512x_ramp_rate_text[] = { +static const char * const pcm512x_ramp_rate_text[] = { "1 sample/update", "2 samples/update", "4 samples/update", "Immediate" }; @@ -224,7 +224,7 @@ static const struct soc_enum pcm512x_vedf = SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4, pcm512x_ramp_rate_text); -static const char *pcm512x_ramp_step_text[] = { +static const char * const pcm512x_ramp_step_text[] = { "4dB/step", "2dB/step", "1dB/step", "0.5dB/step" }; -- cgit v1.2.3 From 096ae5444b8600bbee0501b01987094657a1458e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Feb 2014 21:54:32 +0100 Subject: ASoC: cs42l73: Constify rate constraints The rate constraints in this driver are shared between all device instances. It should not be (and is not) modified at runtime, so make them const. While we are at it also change the type for the rates array from u32 to unsigned int. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l73.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 7cae046c7dd0..69c8e2de7d0e 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1108,7 +1108,7 @@ static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return 0; } -static u32 cs42l73_asrc_rates[] = { +static const unsigned int cs42l73_asrc_rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }; @@ -1241,7 +1241,7 @@ static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate) 0x7F, tristate << 7); } -static struct snd_pcm_hw_constraint_list constraints_12_24 = { +static const struct snd_pcm_hw_constraint_list constraints_12_24 = { .count = ARRAY_SIZE(cs42l73_asrc_rates), .list = cs42l73_asrc_rates, }; -- cgit v1.2.3 From f75ac2d9bd8211c1890ad591046aef0783ad6416 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Feb 2014 21:54:33 +0100 Subject: ASoC: ssm2602: Constify rate constraints The rate constraints in this driver are shared between all device instances. It should not be (and is not) modified at runtime, so make them const. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ssm2602.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index af76bbd1b24f..f444d585b916 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -52,7 +52,7 @@ enum ssm2602_type { /* codec private data */ struct ssm2602_priv { unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; + const struct snd_pcm_hw_constraint_list *sysclk_constraints; struct regmap *regmap; @@ -197,7 +197,7 @@ static const unsigned int ssm2602_rates_12288000[] = { 8000, 16000, 32000, 48000, 96000, }; -static struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { +static const struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = { .list = ssm2602_rates_12288000, .count = ARRAY_SIZE(ssm2602_rates_12288000), }; @@ -206,7 +206,7 @@ static const unsigned int ssm2602_rates_11289600[] = { 8000, 44100, 88200, }; -static struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { +static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = { .list = ssm2602_rates_11289600, .count = ARRAY_SIZE(ssm2602_rates_11289600), }; -- cgit v1.2.3 From 0d76fc6a47b183d519c47e40971e74cfd96cca85 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Feb 2014 21:54:34 +0100 Subject: ASoC: twl6040: Constify rate constraints The rate constraints in this driver are shared between all device instances. It should not be (and is not) modified at runtime, so make them const. Signed-off-by: Lars-Peter Clausen Acked-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 0afe8bef6765..cb642c927dc8 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -81,7 +81,7 @@ struct twl6040_data { }; /* set of rates for each pll: low-power and high-performance */ -static unsigned int lp_rates[] = { +static const unsigned int lp_rates[] = { 8000, 11250, 16000, @@ -93,7 +93,7 @@ static unsigned int lp_rates[] = { 96000, }; -static unsigned int hp_rates[] = { +static const unsigned int hp_rates[] = { 8000, 16000, 32000, @@ -101,7 +101,7 @@ static unsigned int hp_rates[] = { 96000, }; -static struct snd_pcm_hw_constraint_list sysclk_constraints[] = { +static const struct snd_pcm_hw_constraint_list sysclk_constraints[] = { { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, }, { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, }; -- cgit v1.2.3 From 70bad2c780abc6744ab2ab5832b0c9f3de608dad Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Feb 2014 21:54:35 +0100 Subject: ASoC: wm8741: Constify rate constraints The rate constraints in this driver are shared between all device instances. It should not be (and is not) modified at runtime, so make them const. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8741.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 2895c8d3b5e4..dd02ebf88015 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -44,7 +44,7 @@ struct wm8741_priv { struct regmap *regmap; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; + const struct snd_pcm_hw_constraint_list *sysclk_constraints; }; static const struct reg_default wm8741_reg_defaults[] = { @@ -122,74 +122,74 @@ static struct { { 6, 768 }, }; -static unsigned int rates_11289[] = { +static const unsigned int rates_11289[] = { 44100, 88235, }; -static struct snd_pcm_hw_constraint_list constraints_11289 = { +static const struct snd_pcm_hw_constraint_list constraints_11289 = { .count = ARRAY_SIZE(rates_11289), .list = rates_11289, }; -static unsigned int rates_12288[] = { +static const unsigned int rates_12288[] = { 32000, 48000, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_12288 = { +static const struct snd_pcm_hw_constraint_list constraints_12288 = { .count = ARRAY_SIZE(rates_12288), .list = rates_12288, }; -static unsigned int rates_16384[] = { +static const unsigned int rates_16384[] = { 32000, }; -static struct snd_pcm_hw_constraint_list constraints_16384 = { +static const struct snd_pcm_hw_constraint_list constraints_16384 = { .count = ARRAY_SIZE(rates_16384), .list = rates_16384, }; -static unsigned int rates_16934[] = { +static const unsigned int rates_16934[] = { 44100, 88235, }; -static struct snd_pcm_hw_constraint_list constraints_16934 = { +static const struct snd_pcm_hw_constraint_list constraints_16934 = { .count = ARRAY_SIZE(rates_16934), .list = rates_16934, }; -static unsigned int rates_18432[] = { +static const unsigned int rates_18432[] = { 48000, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_18432 = { +static const struct snd_pcm_hw_constraint_list constraints_18432 = { .count = ARRAY_SIZE(rates_18432), .list = rates_18432, }; -static unsigned int rates_22579[] = { +static const unsigned int rates_22579[] = { 44100, 88235, 1764000 }; -static struct snd_pcm_hw_constraint_list constraints_22579 = { +static const struct snd_pcm_hw_constraint_list constraints_22579 = { .count = ARRAY_SIZE(rates_22579), .list = rates_22579, }; -static unsigned int rates_24576[] = { +static const unsigned int rates_24576[] = { 32000, 48000, 96000, 192000 }; -static struct snd_pcm_hw_constraint_list constraints_24576 = { +static const struct snd_pcm_hw_constraint_list constraints_24576 = { .count = ARRAY_SIZE(rates_24576), .list = rates_24576, }; -static unsigned int rates_36864[] = { +static const unsigned int rates_36864[] = { 48000, 96000, 19200 }; -static struct snd_pcm_hw_constraint_list constraints_36864 = { +static const struct snd_pcm_hw_constraint_list constraints_36864 = { .count = ARRAY_SIZE(rates_36864), .list = rates_36864, }; -- cgit v1.2.3 From b57efda1f0372d6107ced5a255384be9fd449260 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Feb 2014 21:54:36 +0100 Subject: ASoC: wm8988: Constify rate constraints The rate constraints in this driver are shared between all device instances. It should not be (and is not) modified at runtime, so make them const. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8988.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index a55e1c2c382e..c6e4aba25b77 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -116,7 +116,7 @@ static bool wm8988_writeable(struct device *dev, unsigned int reg) struct wm8988_priv { struct regmap *regmap; unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; + const struct snd_pcm_hw_constraint_list *sysclk_constraints; }; #define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0) @@ -521,30 +521,30 @@ static inline int get_coeff(int mclk, int rate) /* The set of rates we can generate from the above for each SYSCLK */ -static unsigned int rates_12288[] = { +static const unsigned int rates_12288[] = { 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_12288 = { +static const struct snd_pcm_hw_constraint_list constraints_12288 = { .count = ARRAY_SIZE(rates_12288), .list = rates_12288, }; -static unsigned int rates_112896[] = { +static const unsigned int rates_112896[] = { 8000, 11025, 22050, 44100, }; -static struct snd_pcm_hw_constraint_list constraints_112896 = { +static const struct snd_pcm_hw_constraint_list constraints_112896 = { .count = ARRAY_SIZE(rates_112896), .list = rates_112896, }; -static unsigned int rates_12[] = { +static const unsigned int rates_12[] = { 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000, 48000, 88235, 96000, }; -static struct snd_pcm_hw_constraint_list constraints_12 = { +static const struct snd_pcm_hw_constraint_list constraints_12 = { .count = ARRAY_SIZE(rates_12), .list = rates_12, }; -- cgit v1.2.3 From 4d1a77224bac47c994ecdc776f0c09c9a0ed9d49 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Feb 2014 15:40:35 +0000 Subject: ASoC: codecs: Put the CODEC drivers in a menu Now they're visible they get a bit noisy. Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f0bdcc5abe83..7da528a2c1c5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -8,6 +8,8 @@ config SND_SOC_I2C_AND_SPI default y if I2C=y default y if SPI_MASTER=y +menu "CODEC drivers" + config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" depends on COMPILE_TEST @@ -584,3 +586,5 @@ config SND_SOC_ML26124 config SND_SOC_TPA6130A2 tristate "Texas Instruments TPA6130A2 headphone amplifier" depends on I2C + +endmenu -- cgit v1.2.3 From e479d85ced01ea7f85c7dd21dc858af25f1493b4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Feb 2014 15:57:50 +0000 Subject: ASoC: wm8770: Depend on SPI only The device has no I2C support so it shouldn't be buildable if only I2C is enabled. Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 7da528a2c1c5..a6afdf5004cb 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -474,7 +474,7 @@ config SND_SOC_WM8753 config SND_SOC_WM8770 tristate "Wolfson Microelectronics WM8770 CODEC" - depends on SND_SOC_I2C_AND_SPI + depends on SPI_MASTER config SND_SOC_WM8776 tristate "Wolfson Microelectronics WM8776 CODEC" -- cgit v1.2.3 From 8691d0748e566f8708f7a9139e760134f5dc3130 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 7 Feb 2014 00:53:06 -0800 Subject: ASoC: rsnd: use device dependency clock Current R-Car sound driver is using device independent audio clock, but it is not good design for DT support. This patch adds device dependent clock support. But, there are some platform which is using independent audio clock. It is still supported at this point, but it will be removed soon. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 821791e15d04..8d3a82ef2db5 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -385,8 +385,9 @@ int rsnd_adg_probe(struct platform_device *pdev, { struct rsnd_adg *adg; struct device *dev = rsnd_priv_to_dev(priv); - struct clk *clk; + struct clk *clk, *clk_orig; int i; + bool use_old_style = false; adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); if (!adg) { @@ -394,10 +395,39 @@ int rsnd_adg_probe(struct platform_device *pdev, return -ENOMEM; } - adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); - adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); - adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); - adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); + clk_orig = clk_get(dev, NULL); + adg->clk[CLKA] = clk_get(dev, "clk_a"); + adg->clk[CLKB] = clk_get(dev, "clk_b"); + adg->clk[CLKC] = clk_get(dev, "clk_c"); + adg->clk[CLKI] = clk_get(dev, "clk_i"); + + /* + * It request device dependent audio clock. + * But above all clks will indicate rsnd module clock + * if platform doesn't it + */ + for_each_rsnd_clk(clk, adg, i) { + if (clk_orig == clk) { + dev_warn(dev, + "doesn't have device dependent clock, use independent clock\n"); + use_old_style = true; + break; + } + } + + /* + * note: + * these exist in order to keep compatible with + * platform which has device independent audio clock, + * but will be removed soon + */ + if (use_old_style) { + adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); + adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); + adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); + adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); + } + for_each_rsnd_clk(clk, adg, i) { if (IS_ERR(clk)) { dev_err(dev, "Audio clock failed\n"); -- cgit v1.2.3 From 806d6466076a0aebbe0a9c17294d1a13e93fabcf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Feb 2014 19:08:11 +0000 Subject: ASoC: pcm512x: Implement paging support The PCM512x devices use a paged register map covering the entire register range. Implement support for this, mapping pages in at addresses starting at 0x100 for ease of use (though since the pages are numbered from 0 there is going to be an off by one when looking at the first byte as a page number). Also mark the new registers as accessible with the exception of the coefficient RAM which is a bit fiddly and may benefit from some extra handling to linearise the blocks. Signed-off-by: Mark Brown --- sound/soc/codecs/pcm512x.c | 65 ++++++++++++++++------- sound/soc/codecs/pcm512x.h | 126 +++++++++++++++++++++++++-------------------- 2 files changed, 116 insertions(+), 75 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 1150381fc373..cdcb51e4c86f 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -66,22 +66,29 @@ PCM512x_REGULATOR_EVENT(1) PCM512x_REGULATOR_EVENT(2) static const struct reg_default pcm512x_reg_defaults[] = { - { PCM512x_RESET, 0x00 }, - { PCM512x_POWER, 0x00 }, - { PCM512x_MUTE, 0x00 }, - { PCM512x_DSP, 0x00 }, - { PCM512x_PLL_REF, 0x00 }, - { PCM512x_DAC_ROUTING, 0x11 }, - { PCM512x_DSP_PROGRAM, 0x01 }, - { PCM512x_CLKDET, 0x00 }, - { PCM512x_AUTO_MUTE, 0x00 }, - { PCM512x_ERROR_DETECT, 0x00 }, - { PCM512x_DIGITAL_VOLUME_1, 0x00 }, - { PCM512x_DIGITAL_VOLUME_2, 0x30 }, - { PCM512x_DIGITAL_VOLUME_3, 0x30 }, - { PCM512x_DIGITAL_MUTE_1, 0x22 }, - { PCM512x_DIGITAL_MUTE_2, 0x00 }, - { PCM512x_DIGITAL_MUTE_3, 0x07 }, + { PCM512x_RESET, 0x00 }, + { PCM512x_POWER, 0x00 }, + { PCM512x_MUTE, 0x00 }, + { PCM512x_DSP, 0x00 }, + { PCM512x_PLL_REF, 0x00 }, + { PCM512x_DAC_ROUTING, 0x11 }, + { PCM512x_DSP_PROGRAM, 0x01 }, + { PCM512x_CLKDET, 0x00 }, + { PCM512x_AUTO_MUTE, 0x00 }, + { PCM512x_ERROR_DETECT, 0x00 }, + { PCM512x_DIGITAL_VOLUME_1, 0x00 }, + { PCM512x_DIGITAL_VOLUME_2, 0x30 }, + { PCM512x_DIGITAL_VOLUME_3, 0x30 }, + { PCM512x_DIGITAL_MUTE_1, 0x22 }, + { PCM512x_DIGITAL_MUTE_2, 0x00 }, + { PCM512x_DIGITAL_MUTE_3, 0x07 }, + { PCM512x_OUTPUT_AMPLITUDE, 0x00 }, + { PCM512x_ANALOG_GAIN_CTRL, 0x00 }, + { PCM512x_UNDERVOLTAGE_PROT, 0x00 }, + { PCM512x_ANALOG_MUTE_CTRL, 0x00 }, + { PCM512x_ANALOG_GAIN_BOOST, 0x00 }, + { PCM512x_VCOM_CTRL_1, 0x00 }, + { PCM512x_VCOM_CTRL_2, 0x01 }, }; static bool pcm512x_readable(struct device *dev, unsigned int reg) @@ -141,9 +148,18 @@ static bool pcm512x_readable(struct device *dev, unsigned int reg) case PCM512x_ANALOG_MUTE_DET: case PCM512x_GPIN: case PCM512x_DIGITAL_MUTE_DET: + case PCM512x_OUTPUT_AMPLITUDE: + case PCM512x_ANALOG_GAIN_CTRL: + case PCM512x_UNDERVOLTAGE_PROT: + case PCM512x_ANALOG_MUTE_CTRL: + case PCM512x_ANALOG_GAIN_BOOST: + case PCM512x_VCOM_CTRL_1: + case PCM512x_VCOM_CTRL_2: + case PCM512x_CRAM_CTRL: return true; default: - return false; + /* There are 256 raw register addresses */ + return reg < 0xff; } } @@ -159,9 +175,11 @@ static bool pcm512x_volatile(struct device *dev, unsigned int reg) case PCM512x_ANALOG_MUTE_DET: case PCM512x_GPIN: case PCM512x_DIGITAL_MUTE_DET: + case PCM512x_CRAM_CTRL: return true; default: - return false; + /* There are 256 raw register addresses */ + return reg < 0xff; } } @@ -343,6 +361,14 @@ static struct snd_soc_codec_driver pcm512x_codec_driver = { .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes), }; +static const struct regmap_range_cfg pcm512x_range = { + .name = "Pages", .range_min = PCM512x_VIRT_BASE, + .range_max = PCM512x_MAX_REGISTER, + .selector_reg = PCM512x_PAGE, + .selector_mask = 0xff, + .window_start = 0, .window_len = 0x100, +}; + static const struct regmap_config pcm512x_regmap = { .reg_bits = 8, .val_bits = 8, @@ -350,6 +376,9 @@ static const struct regmap_config pcm512x_regmap = { .readable_reg = pcm512x_readable, .volatile_reg = pcm512x_volatile, + .ranges = &pcm512x_range, + .num_ranges = 1, + .max_register = PCM512x_MAX_REGISTER, .reg_defaults = pcm512x_reg_defaults, .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults), diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h index b2f518ecb35c..e58743c965d6 100644 --- a/sound/soc/codecs/pcm512x.h +++ b/sound/soc/codecs/pcm512x.h @@ -17,66 +17,78 @@ #ifndef _SND_SOC_PCM512X #define _SND_SOC_PCM512X -#define PCM512x_PAGE_0_BASE 0 +#define PCM512x_VIRT_BASE 0x100 +#define PCM512x_PAGE_LEN 0x100 +#define PCM512x_PAGE_BASE(n) (PCM512x_VIRT_BASE + (PCM512x_PAGE_LEN * n)) #define PCM512x_PAGE 0 -#define PCM512x_RESET (PCM512x_PAGE_0_BASE + 1) -#define PCM512x_POWER (PCM512x_PAGE_0_BASE + 2) -#define PCM512x_MUTE (PCM512x_PAGE_0_BASE + 3) -#define PCM512x_PLL_EN (PCM512x_PAGE_0_BASE + 4) -#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_0_BASE + 6) -#define PCM512x_DSP (PCM512x_PAGE_0_BASE + 7) -#define PCM512x_GPIO_EN (PCM512x_PAGE_0_BASE + 8) -#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_0_BASE + 9) -#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_0_BASE + 10) -#define PCM512x_MASTER_MODE (PCM512x_PAGE_0_BASE + 12) -#define PCM512x_PLL_REF (PCM512x_PAGE_0_BASE + 13) -#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_0_BASE + 20) -#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_0_BASE + 21) -#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_0_BASE + 22) -#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_0_BASE + 23) -#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_0_BASE + 24) -#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_0_BASE + 27) -#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_0_BASE + 28) -#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_0_BASE + 29) -#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_0_BASE + 30) -#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_0_BASE + 32) -#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_0_BASE + 33) -#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_0_BASE + 34) -#define PCM512x_IDAC_1 (PCM512x_PAGE_0_BASE + 35) -#define PCM512x_IDAC_2 (PCM512x_PAGE_0_BASE + 36) -#define PCM512x_ERROR_DETECT (PCM512x_PAGE_0_BASE + 37) -#define PCM512x_I2S_1 (PCM512x_PAGE_0_BASE + 40) -#define PCM512x_I2S_2 (PCM512x_PAGE_0_BASE + 41) -#define PCM512x_DAC_ROUTING (PCM512x_PAGE_0_BASE + 42) -#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_0_BASE + 43) -#define PCM512x_CLKDET (PCM512x_PAGE_0_BASE + 44) -#define PCM512x_AUTO_MUTE (PCM512x_PAGE_0_BASE + 59) -#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_0_BASE + 60) -#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_0_BASE + 61) -#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_0_BASE + 62) -#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_0_BASE + 63) -#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_0_BASE + 64) -#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_0_BASE + 65) -#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_0_BASE + 80) -#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_0_BASE + 81) -#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_0_BASE + 82) -#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_0_BASE + 83) -#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_0_BASE + 84) -#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_0_BASE + 85) -#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_0_BASE + 86) -#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_0_BASE + 87) -#define PCM512x_OVERFLOW (PCM512x_PAGE_0_BASE + 90) -#define PCM512x_RATE_DET_1 (PCM512x_PAGE_0_BASE + 91) -#define PCM512x_RATE_DET_2 (PCM512x_PAGE_0_BASE + 92) -#define PCM512x_RATE_DET_3 (PCM512x_PAGE_0_BASE + 93) -#define PCM512x_RATE_DET_4 (PCM512x_PAGE_0_BASE + 94) -#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_0_BASE + 108) -#define PCM512x_GPIN (PCM512x_PAGE_0_BASE + 119) -#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_0_BASE + 120) - -#define PCM512x_MAX_REGISTER (PCM512x_PAGE_0_BASE + 120) +#define PCM512x_RESET (PCM512x_PAGE_BASE(0) + 1) +#define PCM512x_POWER (PCM512x_PAGE_BASE(0) + 2) +#define PCM512x_MUTE (PCM512x_PAGE_BASE(0) + 3) +#define PCM512x_PLL_EN (PCM512x_PAGE_BASE(0) + 4) +#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_BASE(0) + 6) +#define PCM512x_DSP (PCM512x_PAGE_BASE(0) + 7) +#define PCM512x_GPIO_EN (PCM512x_PAGE_BASE(0) + 8) +#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_BASE(0) + 9) +#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_BASE(0) + 10) +#define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12) +#define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13) +#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20) +#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_BASE(0) + 21) +#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_BASE(0) + 22) +#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_BASE(0) + 23) +#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_BASE(0) + 24) +#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_BASE(0) + 27) +#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_BASE(0) + 28) +#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_BASE(0) + 29) +#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_BASE(0) + 30) +#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_BASE(0) + 32) +#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_BASE(0) + 33) +#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_BASE(0) + 34) +#define PCM512x_IDAC_1 (PCM512x_PAGE_BASE(0) + 35) +#define PCM512x_IDAC_2 (PCM512x_PAGE_BASE(0) + 36) +#define PCM512x_ERROR_DETECT (PCM512x_PAGE_BASE(0) + 37) +#define PCM512x_I2S_1 (PCM512x_PAGE_BASE(0) + 40) +#define PCM512x_I2S_2 (PCM512x_PAGE_BASE(0) + 41) +#define PCM512x_DAC_ROUTING (PCM512x_PAGE_BASE(0) + 42) +#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_BASE(0) + 43) +#define PCM512x_CLKDET (PCM512x_PAGE_BASE(0) + 44) +#define PCM512x_AUTO_MUTE (PCM512x_PAGE_BASE(0) + 59) +#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_BASE(0) + 60) +#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_BASE(0) + 61) +#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_BASE(0) + 62) +#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_BASE(0) + 63) +#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_BASE(0) + 64) +#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_BASE(0) + 65) +#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_BASE(0) + 80) +#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_BASE(0) + 81) +#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_BASE(0) + 82) +#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_BASE(0) + 83) +#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_BASE(0) + 84) +#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_BASE(0) + 85) +#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_BASE(0) + 86) +#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_BASE(0) + 87) +#define PCM512x_OVERFLOW (PCM512x_PAGE_BASE(0) + 90) +#define PCM512x_RATE_DET_1 (PCM512x_PAGE_BASE(0) + 91) +#define PCM512x_RATE_DET_2 (PCM512x_PAGE_BASE(0) + 92) +#define PCM512x_RATE_DET_3 (PCM512x_PAGE_BASE(0) + 93) +#define PCM512x_RATE_DET_4 (PCM512x_PAGE_BASE(0) + 94) +#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_BASE(0) + 108) +#define PCM512x_GPIN (PCM512x_PAGE_BASE(0) + 119) +#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_BASE(0) + 120) + +#define PCM512x_OUTPUT_AMPLITUDE (PCM512x_PAGE_BASE(1) + 1) +#define PCM512x_ANALOG_GAIN_CTRL (PCM512x_PAGE_BASE(1) + 2) +#define PCM512x_UNDERVOLTAGE_PROT (PCM512x_PAGE_BASE(1) + 5) +#define PCM512x_ANALOG_MUTE_CTRL (PCM512x_PAGE_BASE(1) + 6) +#define PCM512x_ANALOG_GAIN_BOOST (PCM512x_PAGE_BASE(1) + 7) +#define PCM512x_VCOM_CTRL_1 (PCM512x_PAGE_BASE(1) + 8) +#define PCM512x_VCOM_CTRL_2 (PCM512x_PAGE_BASE(1) + 9) + +#define PCM512x_CRAM_CTRL (PCM512x_PAGE_BASE(44) + 1) + +#define PCM512x_MAX_REGISTER (PCM512x_PAGE_BASE(44) + 1) /* Page 0, Register 1 - reset */ #define PCM512x_RSTR (1 << 0) -- cgit v1.2.3 From 5be2fc20b101b5138c4f54a584dc11790ef16598 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Feb 2014 19:16:56 +0000 Subject: ASoC: pcm512x: Implement analogue volume control There are some analogue volume controls in page 1 of the register map so implement support for them now that we can access the registers. Signed-off-by: Mark Brown --- sound/soc/codecs/pcm512x.c | 6 ++++++ sound/soc/codecs/pcm512x.h | 8 ++++++++ 2 files changed, 14 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index cdcb51e4c86f..3a0bbb6ab242 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -184,6 +184,8 @@ static bool pcm512x_volatile(struct device *dev, unsigned int reg) } static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1); +static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0); +static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0); static const char * const pcm512x_dsp_program_texts[] = { "FIR interpolation with de-emphasis", @@ -261,6 +263,10 @@ static const struct soc_enum pcm512x_veds = static const struct snd_kcontrol_new pcm512x_controls[] = { SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2, PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv), +SOC_DOUBLE_TLV("Playback Volume", PCM512x_ANALOG_GAIN_CTRL, + PCM512x_LAGN_SHIFT, PCM512x_RAGN_SHIFT, 1, 1, analog_tlv), +SOC_DOUBLE_TLV("Playback Boost Volume", PCM512x_ANALOG_GAIN_BOOST, + PCM512x_AGBL_SHIFT, PCM512x_AGBR_SHIFT, 1, 0, boost_tlv), SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT, PCM512x_RQMR_SHIFT, 1, 1), diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h index e58743c965d6..ac4a52c9ccf4 100644 --- a/sound/soc/codecs/pcm512x.h +++ b/sound/soc/codecs/pcm512x.h @@ -151,4 +151,12 @@ #define PCM512x_AMLE_SHIFT 1 #define PCM512x_AMLR_SHIFT 0 +/* Page 1, Register 2 - analog volume control */ +#define PCM512x_RAGN_SHIFT 0 +#define PCM512x_LAGN_SHIFT 4 + +/* Page 1, Register 7 - analog boost control */ +#define PCM512x_AGBR_SHIFT 0 +#define PCM512x_AGBL_SHIFT 4 + #endif -- cgit v1.2.3 From e156291c7bab1771df34acd583c3c1b1ad71231c Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Fri, 7 Feb 2014 19:43:19 +0100 Subject: ASoC: wm8991: Remove unused pointer in wm8991_probe() Remove unused pointer 'wm8991' in function wm8991_probe(). The last user vanished with a86652e5 (ASoC: wm8991: Convert to direct regmap API usage) Detected by Coverity: CID 1162831 Signed-off-by: Christian Engelmayer Signed-off-by: Mark Brown --- sound/soc/codecs/wm8991.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index dba0306c42a5..244eb09ffa43 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1251,11 +1251,8 @@ static int wm8991_remove(struct snd_soc_codec *codec) static int wm8991_probe(struct snd_soc_codec *codec) { - struct wm8991_priv *wm8991; int ret; - wm8991 = snd_soc_codec_get_drvdata(codec); - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); -- cgit v1.2.3 From 78957fc349bcf29d415a649601581a993ff25e4d Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Sat, 8 Feb 2014 14:38:28 +0800 Subject: ASoC: fsl-sai: convert to use regmap API for Freeacale SAI Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 255 +++++++++++++++++++++++++++--------------------- sound/soc/fsl/fsl_sai.h | 47 +++++---- 2 files changed, 166 insertions(+), 136 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index cdd3fa830704..faa65afb6951 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -22,34 +23,6 @@ #include "fsl_sai.h" -static inline u32 sai_readl(struct fsl_sai *sai, - const void __iomem *addr) -{ - u32 val; - - val = __raw_readl(addr); - - if (likely(sai->big_endian_regs)) - val = be32_to_cpu(val); - else - val = le32_to_cpu(val); - rmb(); - - return val; -} - -static inline void sai_writel(struct fsl_sai *sai, - u32 val, void __iomem *addr) -{ - wmb(); - if (likely(sai->big_endian_regs)) - val = cpu_to_be32(val); - else - val = cpu_to_le32(val); - - __raw_writel(val, addr); -} - static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int fsl_dir) { @@ -61,7 +34,8 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, else reg_cr2 = FSL_SAI_RCR2; - val_cr2 = sai_readl(sai, sai->base + reg_cr2); + regmap_read(sai->regmap, reg_cr2, &val_cr2); + val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK; switch (clk_id) { @@ -81,7 +55,7 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, return -EINVAL; } - sai_writel(sai, val_cr2, sai->base + reg_cr2); + regmap_write(sai->regmap, reg_cr2, val_cr2); return 0; } @@ -89,32 +63,22 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai, static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); int ret; if (dir == SND_SOC_CLOCK_IN) return 0; - ret = clk_prepare_enable(sai->clk); - if (ret) - return ret; - ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, FSL_FMT_TRANSMITTER); if (ret) { dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret); - goto err_clk; + return ret; } ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq, FSL_FMT_RECEIVER); - if (ret) { + if (ret) dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret); - goto err_clk; - } - -err_clk: - clk_disable_unprepare(sai->clk); return ret; } @@ -133,8 +97,8 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, reg_cr4 = FSL_SAI_RCR4; } - val_cr2 = sai_readl(sai, sai->base + reg_cr2); - val_cr4 = sai_readl(sai, sai->base + reg_cr4); + regmap_read(sai->regmap, reg_cr2, &val_cr2); + regmap_read(sai->regmap, reg_cr4, &val_cr4); if (sai->big_endian_data) val_cr4 &= ~FSL_SAI_CR4_MF; @@ -183,35 +147,25 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, return -EINVAL; } - sai_writel(sai, val_cr2, sai->base + reg_cr2); - sai_writel(sai, val_cr4, sai->base + reg_cr4); + regmap_write(sai->regmap, reg_cr2, val_cr2); + regmap_write(sai->regmap, reg_cr4, val_cr4); return 0; } static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { - struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); int ret; - ret = clk_prepare_enable(sai->clk); - if (ret) - return ret; - ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER); if (ret) { dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret); - goto err_clk; + return ret; } ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER); - if (ret) { + if (ret) dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret); - goto err_clk; - } - -err_clk: - clk_disable_unprepare(sai->clk); return ret; } @@ -235,11 +189,12 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, reg_mr = FSL_SAI_RMR; } - val_cr4 = sai_readl(sai, sai->base + reg_cr4); + regmap_read(sai->regmap, reg_cr4, &val_cr4); + regmap_read(sai->regmap, reg_cr4, &val_cr5); + val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK; val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK; - val_cr5 = sai_readl(sai, sai->base + reg_cr5); val_cr5 &= ~FSL_SAI_CR5_WNW_MASK; val_cr5 &= ~FSL_SAI_CR5_W0W_MASK; val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; @@ -257,9 +212,9 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, val_cr4 |= FSL_SAI_CR4_FRSZ(channels); val_mr = ~0UL - ((1 << channels) - 1); - sai_writel(sai, val_cr4, sai->base + reg_cr4); - sai_writel(sai, val_cr5, sai->base + reg_cr5); - sai_writel(sai, val_mr, sai->base + reg_mr); + regmap_write(sai->regmap, reg_cr4, val_cr4); + regmap_write(sai->regmap, reg_cr5, val_cr5); + regmap_write(sai->regmap, reg_mr, val_mr); return 0; } @@ -268,44 +223,34 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); - u32 tcsr, rcsr, val_cr2, val_cr3, reg_cr3; - - val_cr2 = sai_readl(sai, sai->base + FSL_SAI_TCR2); - val_cr2 &= ~FSL_SAI_CR2_SYNC; - sai_writel(sai, val_cr2, sai->base + FSL_SAI_TCR2); + u32 tcsr, rcsr; - val_cr2 = sai_readl(sai, sai->base + FSL_SAI_RCR2); - val_cr2 |= FSL_SAI_CR2_SYNC; - sai_writel(sai, val_cr2, sai->base + FSL_SAI_RCR2); + regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, + ~FSL_SAI_CR2_SYNC); + regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, + FSL_SAI_CR2_SYNC); - tcsr = sai_readl(sai, sai->base + FSL_SAI_TCSR); - rcsr = sai_readl(sai, sai->base + FSL_SAI_RCSR); + regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr); + regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { tcsr |= FSL_SAI_CSR_FRDE; rcsr &= ~FSL_SAI_CSR_FRDE; - reg_cr3 = FSL_SAI_TCR3; } else { rcsr |= FSL_SAI_CSR_FRDE; tcsr &= ~FSL_SAI_CSR_FRDE; - reg_cr3 = FSL_SAI_RCR3; } - val_cr3 = sai_readl(sai, sai->base + reg_cr3); - switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: tcsr |= FSL_SAI_CSR_TERE; rcsr |= FSL_SAI_CSR_TERE; - val_cr3 |= FSL_SAI_CR3_TRCE; - sai_writel(sai, val_cr3, sai->base + reg_cr3); - sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); - sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); + regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr); + regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr); break; - case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -314,11 +259,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, rcsr &= ~FSL_SAI_CSR_TERE; } - val_cr3 &= ~FSL_SAI_CR3_TRCE; - - sai_writel(sai, tcsr, sai->base + FSL_SAI_TCSR); - sai_writel(sai, rcsr, sai->base + FSL_SAI_RCSR); - sai_writel(sai, val_cr3, sai->base + reg_cr3); + regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr); + regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr); break; default: return -EINVAL; @@ -331,16 +273,32 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + u32 reg; - return clk_prepare_enable(sai->clk); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + reg = FSL_SAI_TCR3; + else + reg = FSL_SAI_RCR3; + + regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE, + FSL_SAI_CR3_TRCE); + + return 0; } static void fsl_sai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); + u32 reg; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + reg = FSL_SAI_TCR3; + else + reg = FSL_SAI_RCR3; - clk_disable_unprepare(sai->clk); + regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE, + ~FSL_SAI_CR3_TRCE); } static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { @@ -355,18 +313,13 @@ static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) { struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev); - int ret; - - ret = clk_prepare_enable(sai->clk); - if (ret) - return ret; - sai_writel(sai, 0x0, sai->base + FSL_SAI_RCSR); - sai_writel(sai, 0x0, sai->base + FSL_SAI_TCSR); - sai_writel(sai, FSL_SAI_MAXBURST_TX * 2, sai->base + FSL_SAI_TCR1); - sai_writel(sai, FSL_SAI_MAXBURST_RX - 1, sai->base + FSL_SAI_RCR1); - - clk_disable_unprepare(sai->clk); + regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, 0x0); + regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, 0x0); + regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK, + FSL_SAI_MAXBURST_TX * 2); + regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK, + FSL_SAI_MAXBURST_RX - 1); snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, &sai->dma_params_rx); @@ -397,26 +350,109 @@ static const struct snd_soc_component_driver fsl_component = { .name = "fsl-sai", }; +static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case FSL_SAI_TCSR: + case FSL_SAI_TCR1: + case FSL_SAI_TCR2: + case FSL_SAI_TCR3: + case FSL_SAI_TCR4: + case FSL_SAI_TCR5: + case FSL_SAI_TFR: + case FSL_SAI_TMR: + case FSL_SAI_RCSR: + case FSL_SAI_RCR1: + case FSL_SAI_RCR2: + case FSL_SAI_RCR3: + case FSL_SAI_RCR4: + case FSL_SAI_RCR5: + case FSL_SAI_RDR: + case FSL_SAI_RFR: + case FSL_SAI_RMR: + return true; + default: + return false; + } +} + +static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case FSL_SAI_TFR: + case FSL_SAI_RFR: + case FSL_SAI_TDR: + case FSL_SAI_RDR: + return true; + default: + return false; + } + +} + +static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case FSL_SAI_TCSR: + case FSL_SAI_TCR1: + case FSL_SAI_TCR2: + case FSL_SAI_TCR3: + case FSL_SAI_TCR4: + case FSL_SAI_TCR5: + case FSL_SAI_TDR: + case FSL_SAI_TMR: + case FSL_SAI_RCSR: + case FSL_SAI_RCR1: + case FSL_SAI_RCR2: + case FSL_SAI_RCR3: + case FSL_SAI_RCR4: + case FSL_SAI_RCR5: + case FSL_SAI_RMR: + return true; + default: + return false; + } +} + +static struct regmap_config fsl_sai_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + + .max_register = FSL_SAI_RMR, + .readable_reg = fsl_sai_readable_reg, + .volatile_reg = fsl_sai_volatile_reg, + .writeable_reg = fsl_sai_writeable_reg, +}; + static int fsl_sai_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct fsl_sai *sai; struct resource *res; + void __iomem *base; int ret; sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); if (!sai) return -ENOMEM; + sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); + if (sai->big_endian_regs) + fsl_sai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; + + sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sai->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(sai->base)) - return PTR_ERR(sai->base); - - sai->clk = devm_clk_get(&pdev->dev, "sai"); - if (IS_ERR(sai->clk)) { - dev_err(&pdev->dev, "Cannot get SAI's clock\n"); - return PTR_ERR(sai->clk); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, + "sai", base, &fsl_sai_regmap_config); + if (IS_ERR(sai->regmap)) { + dev_err(&pdev->dev, "regmap init failed\n"); + return PTR_ERR(sai->regmap); } sai->dma_params_rx.addr = res->start + FSL_SAI_RDR; @@ -424,9 +460,6 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX; sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; - sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs"); - sai->big_endian_data = of_property_read_bool(np, "big-endian-data"); - platform_set_drvdata(pdev, sai); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 41bb62e69361..1571459d13ec 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -15,31 +15,36 @@ SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) +/* SAI Register Map Register */ +#define FSL_SAI_TCSR 0x00 /* SAI Transmit Control */ +#define FSL_SAI_TCR1 0x04 /* SAI Transmit Configuration 1 */ +#define FSL_SAI_TCR2 0x08 /* SAI Transmit Configuration 2 */ +#define FSL_SAI_TCR3 0x0c /* SAI Transmit Configuration 3 */ +#define FSL_SAI_TCR4 0x10 /* SAI Transmit Configuration 4 */ +#define FSL_SAI_TCR5 0x14 /* SAI Transmit Configuration 5 */ +#define FSL_SAI_TDR 0x20 /* SAI Transmit Data */ +#define FSL_SAI_TFR 0x40 /* SAI Transmit FIFO */ +#define FSL_SAI_TMR 0x60 /* SAI Transmit Mask */ +#define FSL_SAI_RCSR 0x80 /* SAI Receive Control */ +#define FSL_SAI_RCR1 0x84 /* SAI Receive Configuration 1 */ +#define FSL_SAI_RCR2 0x88 /* SAI Receive Configuration 2 */ +#define FSL_SAI_RCR3 0x8c /* SAI Receive Configuration 3 */ +#define FSL_SAI_RCR4 0x90 /* SAI Receive Configuration 4 */ +#define FSL_SAI_RCR5 0x94 /* SAI Receive Configuration 5 */ +#define FSL_SAI_RDR 0xa0 /* SAI Receive Data */ +#define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */ +#define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */ + /* SAI Transmit/Recieve Control Register */ -#define FSL_SAI_TCSR 0x00 -#define FSL_SAI_RCSR 0x80 #define FSL_SAI_CSR_TERE BIT(31) #define FSL_SAI_CSR_FWF BIT(17) #define FSL_SAI_CSR_FRIE BIT(8) #define FSL_SAI_CSR_FRDE BIT(0) -/* SAI Transmit Data/FIFO/MASK Register */ -#define FSL_SAI_TDR 0x20 -#define FSL_SAI_TFR 0x40 -#define FSL_SAI_TMR 0x60 - -/* SAI Recieve Data/FIFO/MASK Register */ -#define FSL_SAI_RDR 0xa0 -#define FSL_SAI_RFR 0xc0 -#define FSL_SAI_RMR 0xe0 - /* SAI Transmit and Recieve Configuration 1 Register */ -#define FSL_SAI_TCR1 0x04 -#define FSL_SAI_RCR1 0x84 +#define FSL_SAI_CR1_RFW_MASK 0x1f /* SAI Transmit and Recieve Configuration 2 Register */ -#define FSL_SAI_TCR2 0x08 -#define FSL_SAI_RCR2 0x88 #define FSL_SAI_CR2_SYNC BIT(30) #define FSL_SAI_CR2_MSEL_MASK (0xff << 26) #define FSL_SAI_CR2_MSEL_BUS 0 @@ -50,15 +55,11 @@ #define FSL_SAI_CR2_BCD_MSTR BIT(24) /* SAI Transmit and Recieve Configuration 3 Register */ -#define FSL_SAI_TCR3 0x0c -#define FSL_SAI_RCR3 0x8c #define FSL_SAI_CR3_TRCE BIT(16) #define FSL_SAI_CR3_WDFL(x) (x) #define FSL_SAI_CR3_WDFL_MASK 0x1f /* SAI Transmit and Recieve Configuration 4 Register */ -#define FSL_SAI_TCR4 0x10 -#define FSL_SAI_RCR4 0x90 #define FSL_SAI_CR4_FRSZ(x) (((x) - 1) << 16) #define FSL_SAI_CR4_FRSZ_MASK (0x1f << 16) #define FSL_SAI_CR4_SYWD(x) (((x) - 1) << 8) @@ -69,8 +70,6 @@ #define FSL_SAI_CR4_FSD_MSTR BIT(0) /* SAI Transmit and Recieve Configuration 5 Register */ -#define FSL_SAI_TCR5 0x14 -#define FSL_SAI_RCR5 0x94 #define FSL_SAI_CR5_WNW(x) (((x) - 1) << 24) #define FSL_SAI_CR5_WNW_MASK (0x1f << 24) #define FSL_SAI_CR5_W0W(x) (((x) - 1) << 16) @@ -100,9 +99,7 @@ #define FSL_SAI_MAXBURST_RX 6 struct fsl_sai { - struct clk *clk; - - void __iomem *base; + struct regmap *regmap; bool big_endian_regs; bool big_endian_data; -- cgit v1.2.3 From 9a6d48605e632e84db2895cf752c65b3c908cd09 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Sat, 8 Feb 2014 15:59:52 +0800 Subject: ASoC: add snd_soc_of_parse_audio_simple_widgets for DT This patch adds snd_soc_of_parse_audio_simple_widgets() and supports below style of widgets name on DT: "template-wname", "user supplied wname" For instance: simple-audio-widgets = "Microphone", "Microphone Jack", "Line", "Line In Jack", "Line", "Line Out Jack", "Headphone", "Headphone Jack", "Speaker", "Speaker External"; The "template-wname" currently includes: "Microphone", "Line", "Headphone" and "Speaker". Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- include/sound/soc.h | 2 ++ sound/soc/soc-core.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a001472b96a..465dc6e0674d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1173,6 +1173,8 @@ void snd_soc_util_exit(void); int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, + const char *propname); int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..0540cb08e0ea 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4417,6 +4417,93 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name); +static const struct snd_soc_dapm_widget simple_widgets[] = { + SND_SOC_DAPM_MIC("Microphone", NULL), + SND_SOC_DAPM_LINE("Line", NULL), + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, + const char *propname) +{ + struct device_node *np = card->dev->of_node; + struct snd_soc_dapm_widget *widgets; + const char *template, *wname; + int i, j, num_widgets, ret; + + num_widgets = of_property_count_strings(np, propname); + if (num_widgets < 0) { + dev_err(card->dev, + "ASoC: Property '%s' does not exist\n", propname); + return -EINVAL; + } + if (num_widgets & 1) { + dev_err(card->dev, + "ASoC: Property '%s' length is not even\n", propname); + return -EINVAL; + } + + num_widgets /= 2; + if (!num_widgets) { + dev_err(card->dev, "ASoC: Property '%s's length is zero\n", + propname); + return -EINVAL; + } + + widgets = devm_kcalloc(card->dev, num_widgets, sizeof(*widgets), + GFP_KERNEL); + if (!widgets) { + dev_err(card->dev, + "ASoC: Could not allocate memory for widgets\n"); + return -ENOMEM; + } + + for (i = 0; i < num_widgets; i++) { + ret = of_property_read_string_index(np, propname, + 2 * i, &template); + if (ret) { + dev_err(card->dev, + "ASoC: Property '%s' index %d read error:%d\n", + propname, 2 * i, ret); + return -EINVAL; + } + + for (j = 0; j < ARRAY_SIZE(simple_widgets); j++) { + if (!strncmp(template, simple_widgets[j].name, + strlen(simple_widgets[j].name))) { + widgets[i] = simple_widgets[j]; + break; + } + } + + if (j >= ARRAY_SIZE(simple_widgets)) { + dev_err(card->dev, + "ASoC: DAPM widget '%s' is not supported\n", + template); + return -EINVAL; + } + + ret = of_property_read_string_index(np, propname, + (2 * i) + 1, + &wname); + if (ret) { + dev_err(card->dev, + "ASoC: Property '%s' index %d read error:%d\n", + propname, (2 * i) + 1, ret); + return -EINVAL; + } + + widgets[i].name = wname; + } + + card->dapm_widgets = widgets; + card->num_dapm_widgets = num_widgets; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); + int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname) { -- cgit v1.2.3 From 9d681f5bfc85515a7b4a4af09337ed5e74f39ad9 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Sat, 8 Feb 2014 15:59:53 +0800 Subject: ASoC: simple-card: add off-codec widgets supports. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 0890fcdc9251..4fe8abc6e216 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -150,6 +150,14 @@ static int asoc_simple_card_parse_of(struct device_node *node, priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); + /* off-codec widgets */ + if (of_property_read_bool(node, "simple-audio-card,widgets")) { + ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, + "simple-audio-card,widgets"); + if (ret) + return ret; + } + /* DAPM routes */ if (of_property_read_bool(node, "simple-audio-card,routing")) { ret = snd_soc_of_parse_audio_routing(&priv->snd_card, -- cgit v1.2.3 From 9f10b36ffde2b732def037c1e764a0c71745a372 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Thu, 6 Feb 2014 18:03:09 +0000 Subject: ASoC: da9055: Add DT support for CODEC Signed-off-by: Adam Thomson Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/da9055.txt | 22 ++++++++++++++++++++++ sound/soc/codecs/da9055.c | 8 ++++++++ 2 files changed, 30 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/da9055.txt (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/da9055.txt b/Documentation/devicetree/bindings/sound/da9055.txt new file mode 100644 index 000000000000..ed1b7cc6f249 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/da9055.txt @@ -0,0 +1,22 @@ +* Dialog DA9055 Audio CODEC + +DA9055 provides Audio CODEC support (I2C only). + +The Audio CODEC device in DA9055 has it's own I2C address which is configurable, +so the device is instantiated separately from the PMIC (MFD) device. + +For details on accompanying PMIC I2C device, see the following: +Documentation/devicetree/bindings/mfd/da9055.txt + +Required properties: + + - compatible: "dlg,da9055-codec" + - reg: Specifies the I2C slave address + + +Example: + + codec: da9055-codec@1a { + compatible = "dlg,da9055-codec"; + reg = <0x1a>; + }; diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 422812613a28..be31f3cfd46e 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -1536,11 +1538,17 @@ static const struct i2c_device_id da9055_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); +static const struct of_device_id da9055_of_match[] = { + { .compatible = "dlg,da9055-codec", }, + { } +}; + /* I2C codec control layer */ static struct i2c_driver da9055_i2c_driver = { .driver = { .name = "da9055-codec", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(da9055_of_match), }, .probe = da9055_i2c_probe, .remove = da9055_remove, -- cgit v1.2.3 From 7d150c60f1a29c62e115e0ee2a5678400e724873 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 11 Feb 2014 10:47:04 +0800 Subject: ASoC: fsl: make sure the regmap-mmio is actually enabled Since the Freescale SAI, ESAI and SPDIF are using the regmap-mmio, there needs a select of REGMAP_MMIO in the Kconfig to ensure that regmap-mmio is actually enabled. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 07f8f141727d..d0914c065a74 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -1,5 +1,6 @@ config SND_SOC_FSL_SAI tristate + select REGMAP_MMIO select SND_SOC_GENERIC_DMAENGINE_PCM config SND_SOC_FSL_SSI @@ -7,9 +8,11 @@ config SND_SOC_FSL_SSI config SND_SOC_FSL_SPDIF tristate + select REGMAP_MMIO config SND_SOC_FSL_ESAI tristate + select REGMAP_MMIO config SND_SOC_FSL_UTILS tristate @@ -204,7 +207,6 @@ config SND_SOC_IMX_SPDIF tristate "SoC Audio support for i.MX boards with S/PDIF" select SND_SOC_IMX_PCM_DMA select SND_SOC_FSL_SPDIF - select REGMAP_MMIO help SoC Audio support for i.MX boards with S/PDIF Say Y if you want to add support for SoC audio on an i.MX board with -- cgit v1.2.3 From 8955f28dba9edb04305504a06d7f395ca3b32904 Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Fri, 7 Feb 2014 23:37:16 +0100 Subject: ASoC: wm8995: Remove unused pointer in hp_supply_event() Remove unused driver data pointer 'wm8995' in function hp_supply_event(). Detected by Coverity: CID 141181. Signed-off-by: Christian Engelmayer Signed-off-by: Mark Brown --- sound/soc/codecs/wm8995.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 4300caff1783..403e1db6870f 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -561,10 +561,8 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec; - struct wm8995_priv *wm8995; codec = w->codec; - wm8995 = snd_soc_codec_get_drvdata(codec); switch (event) { case SND_SOC_DAPM_PRE_PMU: -- cgit v1.2.3 From dfd72a68aa0f6cf87575f3181319bde8a2d4c01b Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 30 Jan 2014 18:14:05 +0100 Subject: ASoC: cs42l51: add Device Tree binding to cs42l51 This commit adds a trivial Device Tree binding to the I2C-based cs42l51 sound codec, so that it can be used from Device Tree based platforms. Signed-off-by: Thomas Petazzoni Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/i2c/trivial-devices.txt | 1 + sound/soc/codecs/cs42l51.c | 7 +++++++ 2 files changed, 8 insertions(+) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 1a1ac2e560e9..f47e56bcf78d 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -18,6 +18,7 @@ atmel,24c02 i2c serial eeprom (24cxx) atmel,at97sc3204t i2c trusted platform module (TPM) capella,cm32181 CM32181: Ambient Light Sensor catalyst,24c32 i2c serial eeprom +cirrus,cs42l51 Cirrus Logic CS42L51 audio codec dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock dallas,ds1338 I2C RTC with 56-Byte NV RAM dallas,ds1339 I2C Serial Real-Time Clock diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 6e9ea8379a91..824cdf4d4974 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -600,10 +600,17 @@ static const struct i2c_device_id cs42l51_id[] = { }; MODULE_DEVICE_TABLE(i2c, cs42l51_id); +static const struct of_device_id cs42l51_of_match[] = { + { .compatible = "cirrus,cs42l51", }, + { } +}; +MODULE_DEVICE_TABLE(of, cs42l51_of_match); + static struct i2c_driver cs42l51_i2c_driver = { .driver = { .name = "cs42l51-codec", .owner = THIS_MODULE, + .of_match_table = cs42l51_of_match, }, .id_table = cs42l51_id, .probe = cs42l51_i2c_probe, -- cgit v1.2.3 From 9a0d5113ac0ee513224ca2e5011b3a566de16207 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 30 Jan 2014 18:14:06 +0100 Subject: ASoC: kirkwood: enable Kirkwood driver for mvebu platforms The audio unit found in the Armada 370 SoC is similar to the one used in the Marvell Kirkwood and Marvell Dove SoCs. Therefore, this commit allows the Kirkwood audio driver to be built on mvebu platforms, and adds an additional compatible string to identify the Armada 370 variant of the audio unit. Signed-off-by: Thomas Petazzoni Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/mvebu-audio.txt | 1 + sound/soc/kirkwood/Kconfig | 2 +- sound/soc/kirkwood/kirkwood-i2s.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/mvebu-audio.txt b/Documentation/devicetree/bindings/sound/mvebu-audio.txt index f0062c5871b4..cb8c07c81ce4 100644 --- a/Documentation/devicetree/bindings/sound/mvebu-audio.txt +++ b/Documentation/devicetree/bindings/sound/mvebu-audio.txt @@ -5,6 +5,7 @@ Required properties: - compatible: "marvell,kirkwood-audio" for Kirkwood platforms "marvell,dove-audio" for Dove platforms + "marvell,armada370-audio" for Armada 370 platforms - reg: physical base address of the controller and length of memory mapped region. diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 78ed4a42ad21..764a0ef6b268 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig @@ -1,6 +1,6 @@ config SND_KIRKWOOD_SOC tristate "SoC Audio for the Marvell Kirkwood and Dove chips" - depends on ARCH_KIRKWOOD || ARCH_DOVE || COMPILE_TEST + depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST help Say Y or M if you want to add support for codecs attached to the Kirkwood I2S interface. You will also need to select the diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 3920a5e8125f..9f842222e798 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -633,6 +633,7 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev) static struct of_device_id mvebu_audio_of_match[] = { { .compatible = "marvell,kirkwood-audio" }, { .compatible = "marvell,dove-audio" }, + { .compatible = "marvell,armada370-audio" }, { } }; MODULE_DEVICE_TABLE(of, mvebu_audio_of_match); -- cgit v1.2.3 From 33529ec94f7cb25f6c98908eefde42a1e8d4e67a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Feb 2014 16:01:28 -0200 Subject: ASoC: fsl_esai: Check the return value from clk_prepare_enable() clk_prepare_enable() may fail, so let's check its return value and propagate it in the case of error. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index d0c72ed261e7..f55341e52970 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -431,17 +431,26 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) static int fsl_esai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + int ret; struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); /* * Some platforms might use the same bit to gate all three or two of * clocks, so keep all clocks open/close at the same time for safety */ - clk_prepare_enable(esai_priv->coreclk); - if (!IS_ERR(esai_priv->extalclk)) - clk_prepare_enable(esai_priv->extalclk); - if (!IS_ERR(esai_priv->fsysclk)) - clk_prepare_enable(esai_priv->fsysclk); + ret = clk_prepare_enable(esai_priv->coreclk); + if (ret) + return ret; + if (!IS_ERR(esai_priv->extalclk)) { + ret = clk_prepare_enable(esai_priv->extalclk); + if (ret) + goto err_extalck; + } + if (!IS_ERR(esai_priv->fsysclk)) { + ret = clk_prepare_enable(esai_priv->fsysclk); + if (ret) + goto err_fsysclk; + } if (!dai->active) { /* Reset Port C */ @@ -463,6 +472,14 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, } return 0; + +err_fsysclk: + if (!IS_ERR(esai_priv->extalclk)) + clk_disable_unprepare(esai_priv->extalclk); +err_extalck: + clk_disable_unprepare(esai_priv->coreclk); + + return ret; } static int fsl_esai_hw_params(struct snd_pcm_substream *substream, -- cgit v1.2.3 From 631f8e94700ac776432826400403703f0bfe063b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 30 Jan 2014 18:26:07 +0000 Subject: ASoC: tobermory: Stop the FLL if we fail to switch SYSCLK to it Signed-off-by: Mark Brown --- sound/soc/samsung/tobermory.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index f21ff608a819..1807b75ccc12 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c @@ -44,6 +44,8 @@ static int tobermory_set_bias_level(struct snd_soc_card *card, SND_SOC_CLOCK_IN); if (ret < 0) { pr_err("Failed to set SYSCLK: %d\n", ret); + snd_soc_dai_set_pll(codec_dai, WM8962_FLL, + 0, 0, 0); return ret; } } -- cgit v1.2.3 From 0b166d8ef686ea990f830e23f7de0590c01ed860 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 10 Feb 2014 22:25:31 +0100 Subject: ASoC: smdk_wm8994: Fix typo "wm8894" Signed-off-by: Paul Bolle Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8994.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index d38ae98e2f32..682eb4f7ba0c 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -202,7 +202,7 @@ static int smdk_audio_probe(struct platform_device *pdev) static struct platform_driver smdk_audio_driver = { .driver = { - .name = "smdk-audio-wm8894", + .name = "smdk-audio-wm8994", .owner = THIS_MODULE, .of_match_table = of_match_ptr(samsung_wm8994_of_match), .pm = &snd_soc_pm_ops, -- cgit v1.2.3 From 5be736442ed94217c6521ae0c948abab995f281f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Feb 2014 19:21:16 +0000 Subject: ASoC: cs42l51: Don't log if we fail to allocate memory The VM subsystem already logs quite loudly if we run out of memory so don't bother here. Signed-off-by: Mark Brown Acked-by: Brian Austin --- sound/soc/codecs/cs42l51.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 824cdf4d4974..b11079b38f15 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -574,10 +574,8 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c_client, cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), GFP_KERNEL); - if (!cs42l51) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); + if (!cs42l51) return -ENOMEM; - } i2c_set_clientdata(i2c_client, cs42l51); cs42l51->control_type = SND_SOC_I2C; -- cgit v1.2.3 From da071489762499a3635cb3563d32792cea20c087 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Feb 2014 19:24:31 +0000 Subject: ASoC: cs42l51: Convert to direct regmap API usage As part of phasing out the ASoC level register I/O code (which is now just a thin wrapper around regmap anyway) convert the cs42l51 driver to use the regmap API directly. We now no longer initialise the cache from hardware at startup, the regmap caches are smart enough to understand which registers are actually cached and read on demand. This should have no visible effect on the system. Signed-off-by: Mark Brown Acked-by: Brian Austin --- sound/soc/codecs/cs42l51.c | 59 ++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 34 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index b11079b38f15..e53c8714591f 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "cs42l51.h" @@ -40,7 +41,6 @@ enum master_slave_mode { }; struct cs42l51_private { - enum snd_soc_control_type control_type; unsigned int mclk; unsigned int audio_mode; /* The mode (I2S or left-justified) */ enum master_slave_mode func; @@ -52,24 +52,6 @@ struct cs42l51_private { SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) -static int cs42l51_fill_cache(struct snd_soc_codec *codec) -{ - u8 *cache = codec->reg_cache + 1; - struct i2c_client *i2c_client = to_i2c_client(codec->dev); - s32 length; - - length = i2c_smbus_read_i2c_block_data(i2c_client, - CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache); - if (length != CS42L51_NUMREGS) { - dev_err(&i2c_client->dev, - "I2C read failure, addr=0x%x (ret=%d vs %d)\n", - i2c_client->addr, length, CS42L51_NUMREGS); - return -EIO; - } - - return 0; -} - static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -508,13 +490,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec) struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); int ret, reg; - ret = cs42l51_fill_cache(codec); - if (ret < 0) { - dev_err(codec->dev, "failed to fill register cache\n"); - return ret; - } - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type); + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -538,8 +514,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .probe = cs42l51_probe, - .reg_cache_size = CS42L51_NUMREGS + 1, - .reg_word_size = sizeof(u8), .controls = cs42l51_snd_controls, .num_controls = ARRAY_SIZE(cs42l51_snd_controls), @@ -549,28 +523,46 @@ static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), }; +static const struct regmap_config cs42l51_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = CS42L51_CHARGE_FREQ, + .cache_type = REGCACHE_RBTREE, +}; + static int cs42l51_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { struct cs42l51_private *cs42l51; + struct regmap *regmap; + unsigned int val; int ret; + regmap = devm_regmap_init_i2c(i2c_client, &cs42l51_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&i2c_client->dev, "Failed to create regmap: %d\n", + ret); + return ret; + } + /* Verify that we have a CS42L51 */ - ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); + ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val); if (ret < 0) { dev_err(&i2c_client->dev, "failed to read I2C\n"); goto error; } - if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && - (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { - dev_err(&i2c_client->dev, "Invalid chip id\n"); + if ((val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && + (val != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { + dev_err(&i2c_client->dev, "Invalid chip id: %x\n", val); ret = -ENODEV; goto error; } dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", - ret & 7); + val & 7); cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), GFP_KERNEL); @@ -578,7 +570,6 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c_client, return -ENOMEM; i2c_set_clientdata(i2c_client, cs42l51); - cs42l51->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c_client->dev, &soc_codec_device_cs42l51, &cs42l51_dai, 1); -- cgit v1.2.3 From 78c51bc6475982a843947a556853affd2c360b19 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Feb 2014 19:51:58 +0000 Subject: ASoC: ak4671: Convert to table based control init Saves code and adds error handling. Signed-off-by: Mark Brown --- sound/soc/codecs/ak4671.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 25bdf6ad4a54..456bd0a065b1 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -628,9 +628,6 @@ static int ak4671_probe(struct snd_soc_codec *codec) return ret; } - snd_soc_add_codec_controls(codec, ak4671_snd_controls, - ARRAY_SIZE(ak4671_snd_controls)); - ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return ret; @@ -646,6 +643,8 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { .probe = ak4671_probe, .remove = ak4671_remove, .set_bias_level = ak4671_set_bias_level, + .controls = ak4671_snd_controls, + .num_controls = ARRAY_SIZE(ak4671_snd_controls), .reg_cache_size = AK4671_CACHEREGNUM, .reg_word_size = sizeof(u8), .reg_cache_default = ak4671_reg, -- cgit v1.2.3 From 7ac5a47886ae4b211f08657d0d06027285eda2d0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 11 Feb 2014 19:53:25 +0000 Subject: ASoC: ak4671: Convert to direct regmap API usage This helps us remove the ASoC level I/O functionality which is now just a thin wrapper around regmap. Signed-off-by: Mark Brown --- sound/soc/codecs/ak4671.c | 221 +++++++++++++++++++++++----------------------- sound/soc/codecs/ak4671.h | 2 - 2 files changed, 111 insertions(+), 112 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 456bd0a065b1..743bbe31bc08 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -23,104 +24,99 @@ #include "ak4671.h" -/* codec private data */ -struct ak4671_priv { - enum snd_soc_control_type control_type; -}; - /* ak4671 register cache & default register settings */ -static const u8 ak4671_reg[AK4671_CACHEREGNUM] = { - 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ - 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */ - 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */ - 0x02, /* AK4671_FORMAT_SELECT (0x03) */ - 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ - 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */ - 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ - 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ - 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ - 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ - 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ - 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ - 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ - 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ - 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ - 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ - 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ - 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ - 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ - 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ - 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ - 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ - 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */ - 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */ - 0x02, /* AK4671_MODE_CONTROL1 (0x18) */ - 0x01, /* AK4671_MODE_CONTROL2 (0x19) */ - 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ - 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ - 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ - 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ - 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ - 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ - 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ - 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ - 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */ - 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */ - 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */ - 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */ - 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */ - 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */ - 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ - 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ - 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ - 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ - 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ - 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ - 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ - 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ - 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ - 0x00, /* this register not used */ - 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */ - 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */ - 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */ - 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */ - 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */ - 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */ - 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */ - 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */ - 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */ - 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */ - 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */ - 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */ - 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */ - 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */ - 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */ - 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */ - 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */ - 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */ - 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */ - 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */ - 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */ - 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */ - 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */ - 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */ - 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */ - 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */ - 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */ - 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */ - 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */ - 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */ - 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ - 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ - 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ - 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */ - 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */ - 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */ - 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ - 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ - 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ - 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ - 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */ +static const struct reg_default ak4671_reg_defaults[] = { + { 0x00, 0x00 }, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ + { 0x01, 0xf6 }, /* AK4671_PLL_MODE_SELECT0 (0x01) */ + { 0x02, 0x00 }, /* AK4671_PLL_MODE_SELECT1 (0x02) */ + { 0x03, 0x02 }, /* AK4671_FORMAT_SELECT (0x03) */ + { 0x04, 0x00 }, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ + { 0x05, 0x55 }, /* AK4671_MIC_AMP_GAIN (0x05) */ + { 0x06, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ + { 0x07, 0x00 }, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ + { 0x08, 0xb5 }, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ + { 0x09, 0x00 }, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ + { 0x0a, 0x00 }, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ + { 0x0b, 0x00 }, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ + { 0x0c, 0x00 }, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ + { 0x0d, 0x00 }, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ + { 0x0e, 0x00 }, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ + { 0x0f, 0x00 }, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ + { 0x10, 0x00 }, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ + { 0x11, 0x80 }, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ + { 0x12, 0x91 }, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ + { 0x13, 0x91 }, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ + { 0x14, 0xe1 }, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ + { 0x15, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ + { 0x16, 0x00 }, /* AK4671_ALC_TIMER_SELECT (0x16) */ + { 0x17, 0x00 }, /* AK4671_ALC_MODE_CONTROL (0x17) */ + { 0x18, 0x02 }, /* AK4671_MODE_CONTROL1 (0x18) */ + { 0x19, 0x01 }, /* AK4671_MODE_CONTROL2 (0x19) */ + { 0x1a, 0x18 }, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ + { 0x1b, 0x18 }, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ + { 0x1c, 0x00 }, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ + { 0x1d, 0x02 }, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ + { 0x1e, 0x00 }, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ + { 0x1f, 0x00 }, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ + { 0x20, 0x00 }, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ + { 0x21, 0x00 }, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ + { 0x22, 0x00 }, /* AK4671_EQ_COEFFICIENT0 (0x22) */ + { 0x23, 0x00 }, /* AK4671_EQ_COEFFICIENT1 (0x23) */ + { 0x24, 0x00 }, /* AK4671_EQ_COEFFICIENT2 (0x24) */ + { 0x25, 0x00 }, /* AK4671_EQ_COEFFICIENT3 (0x25) */ + { 0x26, 0x00 }, /* AK4671_EQ_COEFFICIENT4 (0x26) */ + { 0x27, 0x00 }, /* AK4671_EQ_COEFFICIENT5 (0x27) */ + { 0x28, 0xa9 }, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ + { 0x29, 0x1f }, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ + { 0x2a, 0xad }, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ + { 0x2b, 0x20 }, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ + { 0x2c, 0x00 }, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ + { 0x2d, 0x00 }, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ + { 0x2e, 0x00 }, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ + { 0x2f, 0x00 }, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ + { 0x30, 0x00 }, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ + + { 0x32, 0x00 }, /* AK4671_E1_COEFFICIENT0 (0x32) */ + { 0x33, 0x00 }, /* AK4671_E1_COEFFICIENT1 (0x33) */ + { 0x34, 0x00 }, /* AK4671_E1_COEFFICIENT2 (0x34) */ + { 0x35, 0x00 }, /* AK4671_E1_COEFFICIENT3 (0x35) */ + { 0x36, 0x00 }, /* AK4671_E1_COEFFICIENT4 (0x36) */ + { 0x37, 0x00 }, /* AK4671_E1_COEFFICIENT5 (0x37) */ + { 0x38, 0x00 }, /* AK4671_E2_COEFFICIENT0 (0x38) */ + { 0x39, 0x00 }, /* AK4671_E2_COEFFICIENT1 (0x39) */ + { 0x3a, 0x00 }, /* AK4671_E2_COEFFICIENT2 (0x3a) */ + { 0x3b, 0x00 }, /* AK4671_E2_COEFFICIENT3 (0x3b) */ + { 0x3c, 0x00 }, /* AK4671_E2_COEFFICIENT4 (0x3c) */ + { 0x3d, 0x00 }, /* AK4671_E2_COEFFICIENT5 (0x3d) */ + { 0x3e, 0x00 }, /* AK4671_E3_COEFFICIENT0 (0x3e) */ + { 0x3f, 0x00 }, /* AK4671_E3_COEFFICIENT1 (0x3f) */ + { 0x40, 0x00 }, /* AK4671_E3_COEFFICIENT2 (0x40) */ + { 0x41, 0x00 }, /* AK4671_E3_COEFFICIENT3 (0x41) */ + { 0x42, 0x00 }, /* AK4671_E3_COEFFICIENT4 (0x42) */ + { 0x43, 0x00 }, /* AK4671_E3_COEFFICIENT5 (0x43) */ + { 0x44, 0x00 }, /* AK4671_E4_COEFFICIENT0 (0x44) */ + { 0x45, 0x00 }, /* AK4671_E4_COEFFICIENT1 (0x45) */ + { 0x46, 0x00 }, /* AK4671_E4_COEFFICIENT2 (0x46) */ + { 0x47, 0x00 }, /* AK4671_E4_COEFFICIENT3 (0x47) */ + { 0x48, 0x00 }, /* AK4671_E4_COEFFICIENT4 (0x48) */ + { 0x49, 0x00 }, /* AK4671_E4_COEFFICIENT5 (0x49) */ + { 0x4a, 0x00 }, /* AK4671_E5_COEFFICIENT0 (0x4a) */ + { 0x4b, 0x00 }, /* AK4671_E5_COEFFICIENT1 (0x4b) */ + { 0x4c, 0x00 }, /* AK4671_E5_COEFFICIENT2 (0x4c) */ + { 0x4d, 0x00 }, /* AK4671_E5_COEFFICIENT3 (0x4d) */ + { 0x4e, 0x00 }, /* AK4671_E5_COEFFICIENT4 (0x4e) */ + { 0x4f, 0x00 }, /* AK4671_E5_COEFFICIENT5 (0x4f) */ + { 0x50, 0x88 }, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ + { 0x51, 0x88 }, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ + { 0x52, 0x08 }, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ + { 0x53, 0x00 }, /* AK4671_PCM_IF_CONTROL0 (0x53) */ + { 0x54, 0x00 }, /* AK4671_PCM_IF_CONTROL1 (0x54) */ + { 0x55, 0x00 }, /* AK4671_PCM_IF_CONTROL2 (0x55) */ + { 0x56, 0x18 }, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ + { 0x57, 0x18 }, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ + { 0x58, 0x00 }, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ + { 0x59, 0x00 }, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ + { 0x5a, 0x00 }, /* AK4671_SAR_ADC_CONTROL (0x5a) */ }; /* @@ -619,10 +615,9 @@ static struct snd_soc_dai_driver ak4671_dai = { static int ak4671_probe(struct snd_soc_codec *codec) { - struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type); + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; @@ -645,28 +640,34 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { .set_bias_level = ak4671_set_bias_level, .controls = ak4671_snd_controls, .num_controls = ARRAY_SIZE(ak4671_snd_controls), - .reg_cache_size = AK4671_CACHEREGNUM, - .reg_word_size = sizeof(u8), - .reg_cache_default = ak4671_reg, .dapm_widgets = ak4671_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), .dapm_routes = ak4671_intercon, .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), }; +static const struct regmap_config ak4671_regmap = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = AK4671_SAR_ADC_CONTROL, + .reg_defaults = ak4671_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(ak4671_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + static int ak4671_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct ak4671_priv *ak4671; + struct regmap *regmap; int ret; - ak4671 = devm_kzalloc(&client->dev, sizeof(struct ak4671_priv), - GFP_KERNEL); - if (ak4671 == NULL) - return -ENOMEM; - - i2c_set_clientdata(client, ak4671); - ak4671->control_type = SND_SOC_I2C; + regmap = devm_regmap_init_i2c(client, &ak4671_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&client->dev, "Failed to create regmap: %d\n", ret); + return ret; + } ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_ak4671, &ak4671_dai, 1); diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h index 61cb7ab7552c..394a34d3f50a 100644 --- a/sound/soc/codecs/ak4671.h +++ b/sound/soc/codecs/ak4671.h @@ -105,8 +105,6 @@ #define AK4671_DIGITAL_MIXING_CONTROL2 0x59 #define AK4671_SAR_ADC_CONTROL 0x5a -#define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1) - /* Bitfield Definitions */ /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */ -- cgit v1.2.3 From 00463c113b6ba6506b4f1ebb9b3c5dd249f8750f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 17:15:51 -0800 Subject: ASoC: rsnd: tidyup original for_each_rsnd_xxx macro Current for_each_rsnd_xxx macro will read out-of-array's memory after last loop operation. It was not good C language operation, and the binary which was compiled by (at least) gcc 4.8.1 is broken This patch tidyup these issues Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 7 ++++--- sound/soc/sh/rcar/rsnd.h | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 8d3a82ef2db5..bc8961c5e986 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -25,9 +25,10 @@ struct rsnd_adg { }; #define for_each_rsnd_clk(pos, adg, i) \ - for (i = 0, (pos) = adg->clk[i]; \ - i < CLKMAX; \ - i++, (pos) = adg->clk[i]) + for (i = 0; \ + (i < CLKMAX) && \ + ((pos) = adg->clk[i]); \ + i++) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 8b66dc15fa73..9e4efb40416b 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -216,9 +216,10 @@ struct rsnd_dai { #define rsnd_dai_nr(priv) ((priv)->dai_nr) #define for_each_rsnd_dai(rdai, priv, i) \ - for (i = 0, (rdai) = rsnd_dai_get(priv, i); \ - i < rsnd_dai_nr(priv); \ - i++, (rdai) = rsnd_dai_get(priv, i)) + for (i = 0; \ + (i < rsnd_dai_nr(priv)) && \ + ((rdai) = rsnd_dai_get(priv, i)); \ + i++) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); int rsnd_dai_disconnect(struct rsnd_mod *mod); -- cgit v1.2.3 From ee2c828d21b2381c813df257235d3c635269e435 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 21:04:12 -0800 Subject: ASoC: rsnd: set DIV_EN register on rsnd_adg_set_convert_clk_gen2() DIV_EN register enable bit is required when you use Gen2 SRC Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 16 +++++++++++++--- sound/soc/sh/rcar/gen.c | 1 + sound/soc/sh/rcar/rsnd.h | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index bc8961c5e986..af9e4407aa89 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -111,8 +111,8 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); - int idx, sel, div, step; - u32 val; + int idx, sel, div, step, ret; + u32 val, en; unsigned int min, diff; unsigned int sel_rate [] = { clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ @@ -124,6 +124,7 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, min = ~0; val = 0; + en = 0; for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { idx = 0; step = 2; @@ -136,6 +137,7 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, if (min > diff) { val = (sel << 8) | idx; min = diff; + en = 1 << (sel + 1); /* fixme */ } /* @@ -157,7 +159,15 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, return -EIO; } - return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); + ret = rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); + if (ret < 0) { + dev_err(dev, "timsel error\n"); + return ret; + } + + rsnd_mod_bset(mod, DIV_EN, en, en); + + return 0; } int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 3e03a8bc4f75..0a43b906ffdf 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -253,6 +253,7 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), + RSND_GEN2_S_REG(gen, ADG, DIV_EN, 0x30), RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 9e4efb40416b..d4093907dfd8 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -67,6 +67,7 @@ enum rsnd_reg { RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ + RSND_REG_DIV_EN, /* for Gen2 */ RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ -- cgit v1.2.3 From a2070feede404484296aace813b6c518582a3f8e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 21:05:26 -0800 Subject: ASoC: rsnd: print error if there is SRC settings mismatch rsnd request clock master if SRC is used Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 6e5c763e1040..3984d4b4f2df 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -122,6 +122,14 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int id = rsnd_mod_id(mod); + u32 convert_rate = rsnd_scu_convert_rate(scu); + + if (convert_rate && !rsnd_dai_is_clk_master(rdai)) { + struct device *dev = rsnd_priv_to_dev(priv); + + dev_err(dev, "rsnd should be clk master when you rate convert\n"); + return -EINVAL; + } /* * SSI_MODE0 -- cgit v1.2.3 From a355d67817eccdbe869020f8f5a3123f21f8106f Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 12 Feb 2014 13:42:50 +0000 Subject: ASoC: Intel: Add a mfld prefix to Intel SST drivers. Resent with correct email for Mark. In order to differentiate the different Intel SST audio core drivers we need to rename the current drivers with a mfld prefix. This also includes renaming in the Makefile and Kconfig Acked-by: Vinod Koul Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 4 +- sound/soc/intel/Makefile | 4 +- sound/soc/intel/sst-mfld-dsp.h | 134 +++++++ sound/soc/intel/sst-mfld-platform.c | 725 ++++++++++++++++++++++++++++++++++++ sound/soc/intel/sst-mfld-platform.h | 153 ++++++++ sound/soc/intel/sst_dsp.h | 134 ------- sound/soc/intel/sst_platform.c | 725 ------------------------------------ sound/soc/intel/sst_platform.h | 153 -------- 8 files changed, 1016 insertions(+), 1016 deletions(-) create mode 100644 sound/soc/intel/sst-mfld-dsp.h create mode 100644 sound/soc/intel/sst-mfld-platform.c create mode 100644 sound/soc/intel/sst-mfld-platform.h delete mode 100644 sound/soc/intel/sst_dsp.h delete mode 100644 sound/soc/intel/sst_platform.c delete mode 100644 sound/soc/intel/sst_platform.h (limited to 'sound/soc') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 61c10bf503d2..4d9d0a546cb1 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -2,12 +2,12 @@ config SND_MFLD_MACHINE tristate "SOC Machine Audio driver for Intel Medfield MID platform" depends on INTEL_SCU_IPC select SND_SOC_SN95031 - select SND_SST_PLATFORM + select SND_SST_MFLD_PLATFORM help This adds support for ASoC machine driver for Intel(R) MID Medfield platform used as alsa device in audio substem in Intel(R) MID devices Say Y if you have such a device If unsure select "N". -config SND_SST_PLATFORM +config SND_SST_MFLD_PLATFORM tristate diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 639883339465..eb899fc90d92 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -1,5 +1,5 @@ -snd-soc-sst-platform-objs := sst_platform.o +snd-soc-sst-mfld-platform-objs := sst-mfld-platform.o snd-soc-mfld-machine-objs := mfld_machine.o -obj-$(CONFIG_SND_SST_PLATFORM) += snd-soc-sst-platform.o +obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o diff --git a/sound/soc/intel/sst-mfld-dsp.h b/sound/soc/intel/sst-mfld-dsp.h new file mode 100644 index 000000000000..3b63edc04b7f --- /dev/null +++ b/sound/soc/intel/sst-mfld-dsp.h @@ -0,0 +1,134 @@ +#ifndef __SST_MFLD_DSP_H__ +#define __SST_MFLD_DSP_H__ +/* + * sst_mfld_dsp.h - Intel SST Driver for audio engine + * + * Copyright (C) 2008-12 Intel Corporation + * Authors: Vinod Koul + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +enum sst_codec_types { + /* AUDIO/MUSIC CODEC Type Definitions */ + SST_CODEC_TYPE_UNKNOWN = 0, + SST_CODEC_TYPE_PCM, /* Pass through Audio codec */ + SST_CODEC_TYPE_MP3, + SST_CODEC_TYPE_MP24, + SST_CODEC_TYPE_AAC, + SST_CODEC_TYPE_AACP, + SST_CODEC_TYPE_eAACP, +}; + +enum stream_type { + SST_STREAM_TYPE_NONE = 0, + SST_STREAM_TYPE_MUSIC = 1, +}; + +struct snd_pcm_params { + u16 codec; /* codec type */ + u8 num_chan; /* 1=Mono, 2=Stereo */ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u32 reserved; /* Bitrate in bits per second */ + u32 sfreq; /* Sampling rate in Hz */ + u8 use_offload_path; + u8 reserved2; + u16 reserved3; + u8 channel_map[8]; +} __packed; + +/* MP3 Music Parameters Message */ +struct snd_mp3_params { + u16 codec; + u8 num_chan; /* 1=Mono, 2=Stereo */ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u8 crc_check; /* crc_check - disable (0) or enable (1) */ + u8 reserved1; /* unused*/ + u16 reserved2; /* Unused */ +} __packed; + +#define AAC_BIT_STREAM_ADTS 0 +#define AAC_BIT_STREAM_ADIF 1 +#define AAC_BIT_STREAM_RAW 2 + +/* AAC Music Parameters Message */ +struct snd_aac_params { + u16 codec; + u8 num_chan; /* 1=Mono, 2=Stereo*/ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u8 bdownsample; /*SBR downsampling 0 - disable 1 -enabled AAC+ only */ + u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */ + u16 reser2; + u32 externalsr; /*sampling rate of basic AAC raw bit stream*/ + u8 sbr_signalling;/*disable/enable/set automode the SBR tool.AAC+*/ + u8 reser1; + u16 reser3; +} __packed; + +/* WMA Music Parameters Message */ +struct snd_wma_params { + u16 codec; + u8 num_chan; /* 1=Mono, 2=Stereo */ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u32 brate; /* Use the hard coded value. */ + u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ + u32 channel_mask; /* Channel Mask */ + u16 format_tag; /* Format Tag */ + u16 block_align; /* packet size */ + u16 wma_encode_opt;/* Encoder option */ + u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB */ + u8 reserved; /* reserved */ +} __packed; + +/* Codec params struture */ +union snd_sst_codec_params { + struct snd_pcm_params pcm_params; + struct snd_mp3_params mp3_params; + struct snd_aac_params aac_params; + struct snd_wma_params wma_params; +} __packed; + +/* Address and size info of a frame buffer */ +struct sst_address_info { + u32 addr; /* Address at IA */ + u32 size; /* Size of the buffer */ +}; + +struct snd_sst_alloc_params_ext { + struct sst_address_info ring_buf_info[8]; + u8 sg_count; + u8 reserved; + u16 reserved2; + u32 frag_size; /*Number of samples after which period elapsed + message is sent valid only if path = 0*/ +} __packed; + +struct snd_sst_stream_params { + union snd_sst_codec_params uc; +} __packed; + +struct snd_sst_params { + u32 stream_id; + u8 codec; + u8 ops; + u8 stream_type; + u8 device_type; + struct snd_sst_stream_params sparams; + struct snd_sst_alloc_params_ext aparams; +}; + +#endif /* __SST_MFLD_DSP_H__ */ diff --git a/sound/soc/intel/sst-mfld-platform.c b/sound/soc/intel/sst-mfld-platform.c new file mode 100644 index 000000000000..840306c2ef14 --- /dev/null +++ b/sound/soc/intel/sst-mfld-platform.c @@ -0,0 +1,725 @@ +/* + * sst_mfld_platform.c - Intel MID Platform driver + * + * Copyright (C) 2010-2013 Intel Corp + * Author: Vinod Koul + * Author: Harsha Priya + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sst-mfld-platform.h" + +static struct sst_device *sst; +static DEFINE_MUTEX(sst_lock); + +int sst_register_dsp(struct sst_device *dev) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (!try_module_get(dev->dev->driver->owner)) + return -ENODEV; + mutex_lock(&sst_lock); + if (sst) { + pr_err("we already have a device %s\n", sst->name); + module_put(dev->dev->driver->owner); + mutex_unlock(&sst_lock); + return -EEXIST; + } + pr_debug("registering device %s\n", dev->name); + sst = dev; + mutex_unlock(&sst_lock); + return 0; +} +EXPORT_SYMBOL_GPL(sst_register_dsp); + +int sst_unregister_dsp(struct sst_device *dev) +{ + if (WARN_ON(!dev)) + return -EINVAL; + if (dev != sst) + return -EINVAL; + + mutex_lock(&sst_lock); + + if (!sst) { + mutex_unlock(&sst_lock); + return -EIO; + } + + module_put(sst->dev->driver->owner); + pr_debug("unreg %s\n", sst->name); + sst = NULL; + mutex_unlock(&sst_lock); + return 0; +} +EXPORT_SYMBOL_GPL(sst_unregister_dsp); + +static struct snd_pcm_hardware sst_platform_pcm_hw = { + .info = (SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_DOUBLE | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_MMAP| + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_SYNC_START), + .buffer_bytes_max = SST_MAX_BUFFER, + .period_bytes_min = SST_MIN_PERIOD_BYTES, + .period_bytes_max = SST_MAX_PERIOD_BYTES, + .periods_min = SST_MIN_PERIODS, + .periods_max = SST_MAX_PERIODS, + .fifo_size = SST_FIFO_SIZE, +}; + +/* MFLD - MSIC */ +static struct snd_soc_dai_driver sst_platform_dai[] = { +{ + .name = "Headset-cpu-dai", + .id = 0, + .playback = { + .channels_min = SST_STEREO, + .channels_max = SST_STEREO, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 5, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_LE, + }, +}, +{ + .name = "Speaker-cpu-dai", + .id = 1, + .playback = { + .channels_min = SST_MONO, + .channels_max = SST_STEREO, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_LE, + }, +}, +{ + .name = "Vibra1-cpu-dai", + .id = 2, + .playback = { + .channels_min = SST_MONO, + .channels_max = SST_MONO, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_LE, + }, +}, +{ + .name = "Vibra2-cpu-dai", + .id = 3, + .playback = { + .channels_min = SST_MONO, + .channels_max = SST_STEREO, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_LE, + }, +}, +{ + .name = "Compress-cpu-dai", + .compress_dai = 1, + .playback = { + .channels_min = SST_STEREO, + .channels_max = SST_STEREO, + .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, +}, +}; + +static const struct snd_soc_component_driver sst_component = { + .name = "sst", +}; + +/* helper functions */ +static inline void sst_set_stream_status(struct sst_runtime_stream *stream, + int state) +{ + unsigned long flags; + spin_lock_irqsave(&stream->status_lock, flags); + stream->stream_status = state; + spin_unlock_irqrestore(&stream->status_lock, flags); +} + +static inline int sst_get_stream_status(struct sst_runtime_stream *stream) +{ + int state; + unsigned long flags; + + spin_lock_irqsave(&stream->status_lock, flags); + state = stream->stream_status; + spin_unlock_irqrestore(&stream->status_lock, flags); + return state; +} + +static void sst_fill_pcm_params(struct snd_pcm_substream *substream, + struct sst_pcm_params *param) +{ + + param->codec = SST_CODEC_TYPE_PCM; + param->num_chan = (u8) substream->runtime->channels; + param->pcm_wd_sz = substream->runtime->sample_bits; + param->reserved = 0; + param->sfreq = substream->runtime->rate; + param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream); + param->period_count = substream->runtime->period_size; + param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area); + pr_debug("period_cnt = %d\n", param->period_count); + pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz); +} + +static int sst_platform_alloc_stream(struct snd_pcm_substream *substream) +{ + struct sst_runtime_stream *stream = + substream->runtime->private_data; + struct sst_pcm_params param = {0}; + struct sst_stream_params str_params = {0}; + int ret_val; + + /* set codec params and inform SST driver the same */ + sst_fill_pcm_params(substream, ¶m); + substream->runtime->dma_area = substream->dma_buffer.area; + str_params.sparams = param; + str_params.codec = param.codec; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + str_params.ops = STREAM_OPS_PLAYBACK; + str_params.device_type = substream->pcm->device + 1; + pr_debug("Playbck stream,Device %d\n", + substream->pcm->device); + } else { + str_params.ops = STREAM_OPS_CAPTURE; + str_params.device_type = SND_SST_DEVICE_CAPTURE; + pr_debug("Capture stream,Device %d\n", + substream->pcm->device); + } + ret_val = stream->ops->open(&str_params); + pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val); + if (ret_val < 0) + return ret_val; + + stream->stream_info.str_id = ret_val; + pr_debug("str id : %d\n", stream->stream_info.str_id); + return ret_val; +} + +static void sst_period_elapsed(void *mad_substream) +{ + struct snd_pcm_substream *substream = mad_substream; + struct sst_runtime_stream *stream; + int status; + + if (!substream || !substream->runtime) + return; + stream = substream->runtime->private_data; + if (!stream) + return; + status = sst_get_stream_status(stream); + if (status != SST_PLATFORM_RUNNING) + return; + snd_pcm_period_elapsed(substream); +} + +static int sst_platform_init_stream(struct snd_pcm_substream *substream) +{ + struct sst_runtime_stream *stream = + substream->runtime->private_data; + int ret_val; + + pr_debug("setting buffer ptr param\n"); + sst_set_stream_status(stream, SST_PLATFORM_INIT); + stream->stream_info.period_elapsed = sst_period_elapsed; + stream->stream_info.mad_substream = substream; + stream->stream_info.buffer_ptr = 0; + stream->stream_info.sfreq = substream->runtime->rate; + ret_val = stream->ops->device_control( + SST_SND_STREAM_INIT, &stream->stream_info); + if (ret_val) + pr_err("control_set ret error %d\n", ret_val); + return ret_val; + +} +/* end -- helper functions */ + +static int sst_platform_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct sst_runtime_stream *stream; + int ret_val; + + pr_debug("sst_platform_open called\n"); + + snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw); + ret_val = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret_val < 0) + return ret_val; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + spin_lock_init(&stream->status_lock); + + /* get the sst ops */ + mutex_lock(&sst_lock); + if (!sst) { + pr_err("no device available to run\n"); + mutex_unlock(&sst_lock); + kfree(stream); + return -ENODEV; + } + if (!try_module_get(sst->dev->driver->owner)) { + mutex_unlock(&sst_lock); + kfree(stream); + return -ENODEV; + } + stream->ops = sst->ops; + mutex_unlock(&sst_lock); + + stream->stream_info.str_id = 0; + sst_set_stream_status(stream, SST_PLATFORM_INIT); + stream->stream_info.mad_substream = substream; + /* allocate memory for SST API set */ + runtime->private_data = stream; + + return 0; +} + +static int sst_platform_close(struct snd_pcm_substream *substream) +{ + struct sst_runtime_stream *stream; + int ret_val = 0, str_id; + + pr_debug("sst_platform_close called\n"); + stream = substream->runtime->private_data; + str_id = stream->stream_info.str_id; + if (str_id) + ret_val = stream->ops->close(str_id); + module_put(sst->dev->driver->owner); + kfree(stream); + return ret_val; +} + +static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct sst_runtime_stream *stream; + int ret_val = 0, str_id; + + pr_debug("sst_platform_pcm_prepare called\n"); + stream = substream->runtime->private_data; + str_id = stream->stream_info.str_id; + if (stream->stream_info.str_id) { + ret_val = stream->ops->device_control( + SST_SND_DROP, &str_id); + return ret_val; + } + + ret_val = sst_platform_alloc_stream(substream); + if (ret_val < 0) + return ret_val; + snprintf(substream->pcm->id, sizeof(substream->pcm->id), + "%d", stream->stream_info.str_id); + + ret_val = sst_platform_init_stream(substream); + if (ret_val) + return ret_val; + substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER; + return ret_val; +} + +static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, + int cmd) +{ + int ret_val = 0, str_id; + struct sst_runtime_stream *stream; + int str_cmd, status; + + pr_debug("sst_platform_pcm_trigger called\n"); + stream = substream->runtime->private_data; + str_id = stream->stream_info.str_id; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + pr_debug("sst: Trigger Start\n"); + str_cmd = SST_SND_START; + status = SST_PLATFORM_RUNNING; + stream->stream_info.mad_substream = substream; + break; + case SNDRV_PCM_TRIGGER_STOP: + pr_debug("sst: in stop\n"); + str_cmd = SST_SND_DROP; + status = SST_PLATFORM_DROPPED; + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + pr_debug("sst: in pause\n"); + str_cmd = SST_SND_PAUSE; + status = SST_PLATFORM_PAUSED; + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + pr_debug("sst: in pause release\n"); + str_cmd = SST_SND_RESUME; + status = SST_PLATFORM_RUNNING; + break; + default: + return -EINVAL; + } + ret_val = stream->ops->device_control(str_cmd, &str_id); + if (!ret_val) + sst_set_stream_status(stream, status); + + return ret_val; +} + + +static snd_pcm_uframes_t sst_platform_pcm_pointer + (struct snd_pcm_substream *substream) +{ + struct sst_runtime_stream *stream; + int ret_val, status; + struct pcm_stream_info *str_info; + + stream = substream->runtime->private_data; + status = sst_get_stream_status(stream); + if (status == SST_PLATFORM_INIT) + return 0; + str_info = &stream->stream_info; + ret_val = stream->ops->device_control( + SST_SND_BUFFER_POINTER, str_info); + if (ret_val) { + pr_err("sst: error code = %d\n", ret_val); + return ret_val; + } + return stream->stream_info.buffer_ptr; +} + +static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); + memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); + + return 0; +} + +static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream) +{ + return snd_pcm_lib_free_pages(substream); +} + +static struct snd_pcm_ops sst_platform_ops = { + .open = sst_platform_open, + .close = sst_platform_close, + .ioctl = snd_pcm_lib_ioctl, + .prepare = sst_platform_pcm_prepare, + .trigger = sst_platform_pcm_trigger, + .pointer = sst_platform_pcm_pointer, + .hw_params = sst_platform_pcm_hw_params, + .hw_free = sst_platform_pcm_hw_free, +}; + +static void sst_pcm_free(struct snd_pcm *pcm) +{ + pr_debug("sst_pcm_free called\n"); + snd_pcm_lib_preallocate_free_for_all(pcm); +} + +static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm; + int retval = 0; + + pr_debug("sst_pcm_new called\n"); + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || + pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + retval = snd_pcm_lib_preallocate_pages_for_all(pcm, + SNDRV_DMA_TYPE_CONTINUOUS, + snd_dma_continuous_data(GFP_KERNEL), + SST_MIN_BUFFER, SST_MAX_BUFFER); + if (retval) { + pr_err("dma buffer allocationf fail\n"); + return retval; + } + } + return retval; +} + +/* compress stream operations */ +static void sst_compr_fragment_elapsed(void *arg) +{ + struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg; + + pr_debug("fragment elapsed by driver\n"); + if (cstream) + snd_compr_fragment_elapsed(cstream); +} + +static int sst_platform_compr_open(struct snd_compr_stream *cstream) +{ + + int ret_val = 0; + struct snd_compr_runtime *runtime = cstream->runtime; + struct sst_runtime_stream *stream; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + spin_lock_init(&stream->status_lock); + + /* get the sst ops */ + if (!sst || !try_module_get(sst->dev->driver->owner)) { + pr_err("no device available to run\n"); + ret_val = -ENODEV; + goto out_ops; + } + stream->compr_ops = sst->compr_ops; + + stream->id = 0; + sst_set_stream_status(stream, SST_PLATFORM_INIT); + runtime->private_data = stream; + return 0; +out_ops: + kfree(stream); + return ret_val; +} + +static int sst_platform_compr_free(struct snd_compr_stream *cstream) +{ + struct sst_runtime_stream *stream; + int ret_val = 0, str_id; + + stream = cstream->runtime->private_data; + /*need to check*/ + str_id = stream->id; + if (str_id) + ret_val = stream->compr_ops->close(str_id); + module_put(sst->dev->driver->owner); + kfree(stream); + pr_debug("%s: %d\n", __func__, ret_val); + return 0; +} + +static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, + struct snd_compr_params *params) +{ + struct sst_runtime_stream *stream; + int retval; + struct snd_sst_params str_params; + struct sst_compress_cb cb; + + stream = cstream->runtime->private_data; + /* construct fw structure for this*/ + memset(&str_params, 0, sizeof(str_params)); + + str_params.ops = STREAM_OPS_PLAYBACK; + str_params.stream_type = SST_STREAM_TYPE_MUSIC; + str_params.device_type = SND_SST_DEVICE_COMPRESS; + + switch (params->codec.id) { + case SND_AUDIOCODEC_MP3: { + str_params.codec = SST_CODEC_TYPE_MP3; + str_params.sparams.uc.mp3_params.codec = SST_CODEC_TYPE_MP3; + str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in; + str_params.sparams.uc.mp3_params.pcm_wd_sz = 16; + break; + } + + case SND_AUDIOCODEC_AAC: { + str_params.codec = SST_CODEC_TYPE_AAC; + str_params.sparams.uc.aac_params.codec = SST_CODEC_TYPE_AAC; + str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in; + str_params.sparams.uc.aac_params.pcm_wd_sz = 16; + if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS) + str_params.sparams.uc.aac_params.bs_format = + AAC_BIT_STREAM_ADTS; + else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW) + str_params.sparams.uc.aac_params.bs_format = + AAC_BIT_STREAM_RAW; + else { + pr_err("Undefined format%d\n", params->codec.format); + return -EINVAL; + } + str_params.sparams.uc.aac_params.externalsr = + params->codec.sample_rate; + break; + } + + default: + pr_err("codec not supported, id =%d\n", params->codec.id); + return -EINVAL; + } + + str_params.aparams.ring_buf_info[0].addr = + virt_to_phys(cstream->runtime->buffer); + str_params.aparams.ring_buf_info[0].size = + cstream->runtime->buffer_size; + str_params.aparams.sg_count = 1; + str_params.aparams.frag_size = cstream->runtime->fragment_size; + + cb.param = cstream; + cb.compr_cb = sst_compr_fragment_elapsed; + + retval = stream->compr_ops->open(&str_params, &cb); + if (retval < 0) { + pr_err("stream allocation failed %d\n", retval); + return retval; + } + + stream->id = retval; + return 0; +} + +static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) +{ + struct sst_runtime_stream *stream = + cstream->runtime->private_data; + + return stream->compr_ops->control(cmd, stream->id); +} + +static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp) +{ + struct sst_runtime_stream *stream; + + stream = cstream->runtime->private_data; + stream->compr_ops->tstamp(stream->id, tstamp); + tstamp->byte_offset = tstamp->copied_total % + (u32)cstream->runtime->buffer_size; + pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); + return 0; +} + +static int sst_platform_compr_ack(struct snd_compr_stream *cstream, + size_t bytes) +{ + struct sst_runtime_stream *stream; + + stream = cstream->runtime->private_data; + stream->compr_ops->ack(stream->id, (unsigned long)bytes); + stream->bytes_written += bytes; + + return 0; +} + +static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream, + struct snd_compr_caps *caps) +{ + struct sst_runtime_stream *stream = + cstream->runtime->private_data; + + return stream->compr_ops->get_caps(caps); +} + +static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, + struct snd_compr_codec_caps *codec) +{ + struct sst_runtime_stream *stream = + cstream->runtime->private_data; + + return stream->compr_ops->get_codec_caps(codec); +} + +static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata) +{ + struct sst_runtime_stream *stream = + cstream->runtime->private_data; + + return stream->compr_ops->set_metadata(stream->id, metadata); +} + +static struct snd_compr_ops sst_platform_compr_ops = { + + .open = sst_platform_compr_open, + .free = sst_platform_compr_free, + .set_params = sst_platform_compr_set_params, + .set_metadata = sst_platform_compr_set_metadata, + .trigger = sst_platform_compr_trigger, + .pointer = sst_platform_compr_pointer, + .ack = sst_platform_compr_ack, + .get_caps = sst_platform_compr_get_caps, + .get_codec_caps = sst_platform_compr_get_codec_caps, +}; + +static struct snd_soc_platform_driver sst_soc_platform_drv = { + .ops = &sst_platform_ops, + .compr_ops = &sst_platform_compr_ops, + .pcm_new = sst_pcm_new, + .pcm_free = sst_pcm_free, +}; + +static int sst_platform_probe(struct platform_device *pdev) +{ + int ret; + + pr_debug("sst_platform_probe called\n"); + sst = NULL; + ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); + if (ret) { + pr_err("registering soc platform failed\n"); + return ret; + } + + ret = snd_soc_register_component(&pdev->dev, &sst_component, + sst_platform_dai, ARRAY_SIZE(sst_platform_dai)); + if (ret) { + pr_err("registering cpu dais failed\n"); + snd_soc_unregister_platform(&pdev->dev); + } + return ret; +} + +static int sst_platform_remove(struct platform_device *pdev) +{ + + snd_soc_unregister_component(&pdev->dev); + snd_soc_unregister_platform(&pdev->dev); + pr_debug("sst_platform_remove success\n"); + return 0; +} + +static struct platform_driver sst_platform_driver = { + .driver = { + .name = "sst-mfld-platform", + .owner = THIS_MODULE, + }, + .probe = sst_platform_probe, + .remove = sst_platform_remove, +}; + +module_platform_driver(sst_platform_driver); + +MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver"); +MODULE_AUTHOR("Vinod Koul "); +MODULE_AUTHOR("Harsha Priya "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sst-mfld-platform"); diff --git a/sound/soc/intel/sst-mfld-platform.h b/sound/soc/intel/sst-mfld-platform.h new file mode 100644 index 000000000000..0c4e2ddcecb1 --- /dev/null +++ b/sound/soc/intel/sst-mfld-platform.h @@ -0,0 +1,153 @@ +/* + * sst_mfld_platform.h - Intel MID Platform driver header file + * + * Copyright (C) 2010 Intel Corp + * Author: Vinod Koul + * Author: Harsha Priya + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * + */ + +#ifndef __SST_PLATFORMDRV_H__ +#define __SST_PLATFORMDRV_H__ + +#include "sst-mfld-dsp.h" + +#define SST_MONO 1 +#define SST_STEREO 2 +#define SST_MAX_CAP 5 + +#define SST_MAX_BUFFER (800*1024) +#define SST_MIN_BUFFER (800*1024) +#define SST_MIN_PERIOD_BYTES 32 +#define SST_MAX_PERIOD_BYTES SST_MAX_BUFFER +#define SST_MIN_PERIODS 2 +#define SST_MAX_PERIODS (1024*2) +#define SST_FIFO_SIZE 0 + +struct pcm_stream_info { + int str_id; + void *mad_substream; + void (*period_elapsed) (void *mad_substream); + unsigned long long buffer_ptr; + int sfreq; +}; + +enum sst_drv_status { + SST_PLATFORM_INIT = 1, + SST_PLATFORM_STARTED, + SST_PLATFORM_RUNNING, + SST_PLATFORM_PAUSED, + SST_PLATFORM_DROPPED, +}; + +enum sst_controls { + SST_SND_ALLOC = 0x00, + SST_SND_PAUSE = 0x01, + SST_SND_RESUME = 0x02, + SST_SND_DROP = 0x03, + SST_SND_FREE = 0x04, + SST_SND_BUFFER_POINTER = 0x05, + SST_SND_STREAM_INIT = 0x06, + SST_SND_START = 0x07, + SST_MAX_CONTROLS = 0x07, +}; + +enum sst_stream_ops { + STREAM_OPS_PLAYBACK = 0, + STREAM_OPS_CAPTURE, +}; + +enum sst_audio_device_type { + SND_SST_DEVICE_HEADSET = 1, + SND_SST_DEVICE_IHF, + SND_SST_DEVICE_VIBRA, + SND_SST_DEVICE_HAPTIC, + SND_SST_DEVICE_CAPTURE, + SND_SST_DEVICE_COMPRESS, +}; + +/* PCM Parameters */ +struct sst_pcm_params { + u16 codec; /* codec type */ + u8 num_chan; /* 1=Mono, 2=Stereo */ + u8 pcm_wd_sz; /* 16/24 - bit*/ + u32 reserved; /* Bitrate in bits per second */ + u32 sfreq; /* Sampling rate in Hz */ + u32 ring_buffer_size; + u32 period_count; /* period elapsed in samples*/ + u32 ring_buffer_addr; +}; + +struct sst_stream_params { + u32 result; + u32 stream_id; + u8 codec; + u8 ops; + u8 stream_type; + u8 device_type; + struct sst_pcm_params sparams; +}; + +struct sst_compress_cb { + void *param; + void (*compr_cb)(void *param); +}; + +struct compress_sst_ops { + const char *name; + int (*open) (struct snd_sst_params *str_params, + struct sst_compress_cb *cb); + int (*control) (unsigned int cmd, unsigned int str_id); + int (*tstamp) (unsigned int str_id, struct snd_compr_tstamp *tstamp); + int (*ack) (unsigned int str_id, unsigned long bytes); + int (*close) (unsigned int str_id); + int (*get_caps) (struct snd_compr_caps *caps); + int (*get_codec_caps) (struct snd_compr_codec_caps *codec); + int (*set_metadata) (unsigned int str_id, + struct snd_compr_metadata *mdata); + +}; + +struct sst_ops { + int (*open) (struct sst_stream_params *str_param); + int (*device_control) (int cmd, void *arg); + int (*close) (unsigned int str_id); +}; + +struct sst_runtime_stream { + int stream_status; + unsigned int id; + size_t bytes_written; + struct pcm_stream_info stream_info; + struct sst_ops *ops; + struct compress_sst_ops *compr_ops; + spinlock_t status_lock; +}; + +struct sst_device { + char *name; + struct device *dev; + struct sst_ops *ops; + struct compress_sst_ops *compr_ops; +}; + +int sst_register_dsp(struct sst_device *sst); +int sst_unregister_dsp(struct sst_device *sst); +#endif diff --git a/sound/soc/intel/sst_dsp.h b/sound/soc/intel/sst_dsp.h deleted file mode 100644 index 0fce1de284ff..000000000000 --- a/sound/soc/intel/sst_dsp.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef __SST_DSP_H__ -#define __SST_DSP_H__ -/* - * sst_dsp.h - Intel SST Driver for audio engine - * - * Copyright (C) 2008-12 Intel Corporation - * Authors: Vinod Koul - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -enum sst_codec_types { - /* AUDIO/MUSIC CODEC Type Definitions */ - SST_CODEC_TYPE_UNKNOWN = 0, - SST_CODEC_TYPE_PCM, /* Pass through Audio codec */ - SST_CODEC_TYPE_MP3, - SST_CODEC_TYPE_MP24, - SST_CODEC_TYPE_AAC, - SST_CODEC_TYPE_AACP, - SST_CODEC_TYPE_eAACP, -}; - -enum stream_type { - SST_STREAM_TYPE_NONE = 0, - SST_STREAM_TYPE_MUSIC = 1, -}; - -struct snd_pcm_params { - u16 codec; /* codec type */ - u8 num_chan; /* 1=Mono, 2=Stereo */ - u8 pcm_wd_sz; /* 16/24 - bit*/ - u32 reserved; /* Bitrate in bits per second */ - u32 sfreq; /* Sampling rate in Hz */ - u8 use_offload_path; - u8 reserved2; - u16 reserved3; - u8 channel_map[8]; -} __packed; - -/* MP3 Music Parameters Message */ -struct snd_mp3_params { - u16 codec; - u8 num_chan; /* 1=Mono, 2=Stereo */ - u8 pcm_wd_sz; /* 16/24 - bit*/ - u8 crc_check; /* crc_check - disable (0) or enable (1) */ - u8 reserved1; /* unused*/ - u16 reserved2; /* Unused */ -} __packed; - -#define AAC_BIT_STREAM_ADTS 0 -#define AAC_BIT_STREAM_ADIF 1 -#define AAC_BIT_STREAM_RAW 2 - -/* AAC Music Parameters Message */ -struct snd_aac_params { - u16 codec; - u8 num_chan; /* 1=Mono, 2=Stereo*/ - u8 pcm_wd_sz; /* 16/24 - bit*/ - u8 bdownsample; /*SBR downsampling 0 - disable 1 -enabled AAC+ only */ - u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */ - u16 reser2; - u32 externalsr; /*sampling rate of basic AAC raw bit stream*/ - u8 sbr_signalling;/*disable/enable/set automode the SBR tool.AAC+*/ - u8 reser1; - u16 reser3; -} __packed; - -/* WMA Music Parameters Message */ -struct snd_wma_params { - u16 codec; - u8 num_chan; /* 1=Mono, 2=Stereo */ - u8 pcm_wd_sz; /* 16/24 - bit*/ - u32 brate; /* Use the hard coded value. */ - u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ - u32 channel_mask; /* Channel Mask */ - u16 format_tag; /* Format Tag */ - u16 block_align; /* packet size */ - u16 wma_encode_opt;/* Encoder option */ - u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB */ - u8 reserved; /* reserved */ -} __packed; - -/* Codec params struture */ -union snd_sst_codec_params { - struct snd_pcm_params pcm_params; - struct snd_mp3_params mp3_params; - struct snd_aac_params aac_params; - struct snd_wma_params wma_params; -} __packed; - -/* Address and size info of a frame buffer */ -struct sst_address_info { - u32 addr; /* Address at IA */ - u32 size; /* Size of the buffer */ -}; - -struct snd_sst_alloc_params_ext { - struct sst_address_info ring_buf_info[8]; - u8 sg_count; - u8 reserved; - u16 reserved2; - u32 frag_size; /*Number of samples after which period elapsed - message is sent valid only if path = 0*/ -} __packed; - -struct snd_sst_stream_params { - union snd_sst_codec_params uc; -} __packed; - -struct snd_sst_params { - u32 stream_id; - u8 codec; - u8 ops; - u8 stream_type; - u8 device_type; - struct snd_sst_stream_params sparams; - struct snd_sst_alloc_params_ext aparams; -}; - -#endif /* __SST_DSP_H__ */ diff --git a/sound/soc/intel/sst_platform.c b/sound/soc/intel/sst_platform.c deleted file mode 100644 index f465a8180863..000000000000 --- a/sound/soc/intel/sst_platform.c +++ /dev/null @@ -1,725 +0,0 @@ -/* - * sst_platform.c - Intel MID Platform driver - * - * Copyright (C) 2010-2013 Intel Corp - * Author: Vinod Koul - * Author: Harsha Priya - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include "sst_platform.h" - -static struct sst_device *sst; -static DEFINE_MUTEX(sst_lock); - -int sst_register_dsp(struct sst_device *dev) -{ - if (WARN_ON(!dev)) - return -EINVAL; - if (!try_module_get(dev->dev->driver->owner)) - return -ENODEV; - mutex_lock(&sst_lock); - if (sst) { - pr_err("we already have a device %s\n", sst->name); - module_put(dev->dev->driver->owner); - mutex_unlock(&sst_lock); - return -EEXIST; - } - pr_debug("registering device %s\n", dev->name); - sst = dev; - mutex_unlock(&sst_lock); - return 0; -} -EXPORT_SYMBOL_GPL(sst_register_dsp); - -int sst_unregister_dsp(struct sst_device *dev) -{ - if (WARN_ON(!dev)) - return -EINVAL; - if (dev != sst) - return -EINVAL; - - mutex_lock(&sst_lock); - - if (!sst) { - mutex_unlock(&sst_lock); - return -EIO; - } - - module_put(sst->dev->driver->owner); - pr_debug("unreg %s\n", sst->name); - sst = NULL; - mutex_unlock(&sst_lock); - return 0; -} -EXPORT_SYMBOL_GPL(sst_unregister_dsp); - -static struct snd_pcm_hardware sst_platform_pcm_hw = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_DOUBLE | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP| - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_SYNC_START), - .buffer_bytes_max = SST_MAX_BUFFER, - .period_bytes_min = SST_MIN_PERIOD_BYTES, - .period_bytes_max = SST_MAX_PERIOD_BYTES, - .periods_min = SST_MIN_PERIODS, - .periods_max = SST_MAX_PERIODS, - .fifo_size = SST_FIFO_SIZE, -}; - -/* MFLD - MSIC */ -static struct snd_soc_dai_driver sst_platform_dai[] = { -{ - .name = "Headset-cpu-dai", - .id = 0, - .playback = { - .channels_min = SST_STEREO, - .channels_max = SST_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, - }, - .capture = { - .channels_min = 1, - .channels_max = 5, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "Speaker-cpu-dai", - .id = 1, - .playback = { - .channels_min = SST_MONO, - .channels_max = SST_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "Vibra1-cpu-dai", - .id = 2, - .playback = { - .channels_min = SST_MONO, - .channels_max = SST_MONO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "Vibra2-cpu-dai", - .id = 3, - .playback = { - .channels_min = SST_MONO, - .channels_max = SST_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "Compress-cpu-dai", - .compress_dai = 1, - .playback = { - .channels_min = SST_STEREO, - .channels_max = SST_STEREO, - .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}, -}; - -static const struct snd_soc_component_driver sst_component = { - .name = "sst", -}; - -/* helper functions */ -static inline void sst_set_stream_status(struct sst_runtime_stream *stream, - int state) -{ - unsigned long flags; - spin_lock_irqsave(&stream->status_lock, flags); - stream->stream_status = state; - spin_unlock_irqrestore(&stream->status_lock, flags); -} - -static inline int sst_get_stream_status(struct sst_runtime_stream *stream) -{ - int state; - unsigned long flags; - - spin_lock_irqsave(&stream->status_lock, flags); - state = stream->stream_status; - spin_unlock_irqrestore(&stream->status_lock, flags); - return state; -} - -static void sst_fill_pcm_params(struct snd_pcm_substream *substream, - struct sst_pcm_params *param) -{ - - param->codec = SST_CODEC_TYPE_PCM; - param->num_chan = (u8) substream->runtime->channels; - param->pcm_wd_sz = substream->runtime->sample_bits; - param->reserved = 0; - param->sfreq = substream->runtime->rate; - param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream); - param->period_count = substream->runtime->period_size; - param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area); - pr_debug("period_cnt = %d\n", param->period_count); - pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz); -} - -static int sst_platform_alloc_stream(struct snd_pcm_substream *substream) -{ - struct sst_runtime_stream *stream = - substream->runtime->private_data; - struct sst_pcm_params param = {0}; - struct sst_stream_params str_params = {0}; - int ret_val; - - /* set codec params and inform SST driver the same */ - sst_fill_pcm_params(substream, ¶m); - substream->runtime->dma_area = substream->dma_buffer.area; - str_params.sparams = param; - str_params.codec = param.codec; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - str_params.ops = STREAM_OPS_PLAYBACK; - str_params.device_type = substream->pcm->device + 1; - pr_debug("Playbck stream,Device %d\n", - substream->pcm->device); - } else { - str_params.ops = STREAM_OPS_CAPTURE; - str_params.device_type = SND_SST_DEVICE_CAPTURE; - pr_debug("Capture stream,Device %d\n", - substream->pcm->device); - } - ret_val = stream->ops->open(&str_params); - pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val); - if (ret_val < 0) - return ret_val; - - stream->stream_info.str_id = ret_val; - pr_debug("str id : %d\n", stream->stream_info.str_id); - return ret_val; -} - -static void sst_period_elapsed(void *mad_substream) -{ - struct snd_pcm_substream *substream = mad_substream; - struct sst_runtime_stream *stream; - int status; - - if (!substream || !substream->runtime) - return; - stream = substream->runtime->private_data; - if (!stream) - return; - status = sst_get_stream_status(stream); - if (status != SST_PLATFORM_RUNNING) - return; - snd_pcm_period_elapsed(substream); -} - -static int sst_platform_init_stream(struct snd_pcm_substream *substream) -{ - struct sst_runtime_stream *stream = - substream->runtime->private_data; - int ret_val; - - pr_debug("setting buffer ptr param\n"); - sst_set_stream_status(stream, SST_PLATFORM_INIT); - stream->stream_info.period_elapsed = sst_period_elapsed; - stream->stream_info.mad_substream = substream; - stream->stream_info.buffer_ptr = 0; - stream->stream_info.sfreq = substream->runtime->rate; - ret_val = stream->ops->device_control( - SST_SND_STREAM_INIT, &stream->stream_info); - if (ret_val) - pr_err("control_set ret error %d\n", ret_val); - return ret_val; - -} -/* end -- helper functions */ - -static int sst_platform_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sst_runtime_stream *stream; - int ret_val; - - pr_debug("sst_platform_open called\n"); - - snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw); - ret_val = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret_val < 0) - return ret_val; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - spin_lock_init(&stream->status_lock); - - /* get the sst ops */ - mutex_lock(&sst_lock); - if (!sst) { - pr_err("no device available to run\n"); - mutex_unlock(&sst_lock); - kfree(stream); - return -ENODEV; - } - if (!try_module_get(sst->dev->driver->owner)) { - mutex_unlock(&sst_lock); - kfree(stream); - return -ENODEV; - } - stream->ops = sst->ops; - mutex_unlock(&sst_lock); - - stream->stream_info.str_id = 0; - sst_set_stream_status(stream, SST_PLATFORM_INIT); - stream->stream_info.mad_substream = substream; - /* allocate memory for SST API set */ - runtime->private_data = stream; - - return 0; -} - -static int sst_platform_close(struct snd_pcm_substream *substream) -{ - struct sst_runtime_stream *stream; - int ret_val = 0, str_id; - - pr_debug("sst_platform_close called\n"); - stream = substream->runtime->private_data; - str_id = stream->stream_info.str_id; - if (str_id) - ret_val = stream->ops->close(str_id); - module_put(sst->dev->driver->owner); - kfree(stream); - return ret_val; -} - -static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct sst_runtime_stream *stream; - int ret_val = 0, str_id; - - pr_debug("sst_platform_pcm_prepare called\n"); - stream = substream->runtime->private_data; - str_id = stream->stream_info.str_id; - if (stream->stream_info.str_id) { - ret_val = stream->ops->device_control( - SST_SND_DROP, &str_id); - return ret_val; - } - - ret_val = sst_platform_alloc_stream(substream); - if (ret_val < 0) - return ret_val; - snprintf(substream->pcm->id, sizeof(substream->pcm->id), - "%d", stream->stream_info.str_id); - - ret_val = sst_platform_init_stream(substream); - if (ret_val) - return ret_val; - substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER; - return ret_val; -} - -static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - int ret_val = 0, str_id; - struct sst_runtime_stream *stream; - int str_cmd, status; - - pr_debug("sst_platform_pcm_trigger called\n"); - stream = substream->runtime->private_data; - str_id = stream->stream_info.str_id; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - pr_debug("sst: Trigger Start\n"); - str_cmd = SST_SND_START; - status = SST_PLATFORM_RUNNING; - stream->stream_info.mad_substream = substream; - break; - case SNDRV_PCM_TRIGGER_STOP: - pr_debug("sst: in stop\n"); - str_cmd = SST_SND_DROP; - status = SST_PLATFORM_DROPPED; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - pr_debug("sst: in pause\n"); - str_cmd = SST_SND_PAUSE; - status = SST_PLATFORM_PAUSED; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - pr_debug("sst: in pause release\n"); - str_cmd = SST_SND_RESUME; - status = SST_PLATFORM_RUNNING; - break; - default: - return -EINVAL; - } - ret_val = stream->ops->device_control(str_cmd, &str_id); - if (!ret_val) - sst_set_stream_status(stream, status); - - return ret_val; -} - - -static snd_pcm_uframes_t sst_platform_pcm_pointer - (struct snd_pcm_substream *substream) -{ - struct sst_runtime_stream *stream; - int ret_val, status; - struct pcm_stream_info *str_info; - - stream = substream->runtime->private_data; - status = sst_get_stream_status(stream); - if (status == SST_PLATFORM_INIT) - return 0; - str_info = &stream->stream_info; - ret_val = stream->ops->device_control( - SST_SND_BUFFER_POINTER, str_info); - if (ret_val) { - pr_err("sst: error code = %d\n", ret_val); - return ret_val; - } - return stream->stream_info.buffer_ptr; -} - -static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); - - return 0; -} - -static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static struct snd_pcm_ops sst_platform_ops = { - .open = sst_platform_open, - .close = sst_platform_close, - .ioctl = snd_pcm_lib_ioctl, - .prepare = sst_platform_pcm_prepare, - .trigger = sst_platform_pcm_trigger, - .pointer = sst_platform_pcm_pointer, - .hw_params = sst_platform_pcm_hw_params, - .hw_free = sst_platform_pcm_hw_free, -}; - -static void sst_pcm_free(struct snd_pcm *pcm) -{ - pr_debug("sst_pcm_free called\n"); - snd_pcm_lib_preallocate_free_for_all(pcm); -} - -static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_pcm *pcm = rtd->pcm; - int retval = 0; - - pr_debug("sst_pcm_new called\n"); - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || - pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - retval = snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - SST_MIN_BUFFER, SST_MAX_BUFFER); - if (retval) { - pr_err("dma buffer allocationf fail\n"); - return retval; - } - } - return retval; -} - -/* compress stream operations */ -static void sst_compr_fragment_elapsed(void *arg) -{ - struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg; - - pr_debug("fragment elapsed by driver\n"); - if (cstream) - snd_compr_fragment_elapsed(cstream); -} - -static int sst_platform_compr_open(struct snd_compr_stream *cstream) -{ - - int ret_val = 0; - struct snd_compr_runtime *runtime = cstream->runtime; - struct sst_runtime_stream *stream; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - - spin_lock_init(&stream->status_lock); - - /* get the sst ops */ - if (!sst || !try_module_get(sst->dev->driver->owner)) { - pr_err("no device available to run\n"); - ret_val = -ENODEV; - goto out_ops; - } - stream->compr_ops = sst->compr_ops; - - stream->id = 0; - sst_set_stream_status(stream, SST_PLATFORM_INIT); - runtime->private_data = stream; - return 0; -out_ops: - kfree(stream); - return ret_val; -} - -static int sst_platform_compr_free(struct snd_compr_stream *cstream) -{ - struct sst_runtime_stream *stream; - int ret_val = 0, str_id; - - stream = cstream->runtime->private_data; - /*need to check*/ - str_id = stream->id; - if (str_id) - ret_val = stream->compr_ops->close(str_id); - module_put(sst->dev->driver->owner); - kfree(stream); - pr_debug("%s: %d\n", __func__, ret_val); - return 0; -} - -static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, - struct snd_compr_params *params) -{ - struct sst_runtime_stream *stream; - int retval; - struct snd_sst_params str_params; - struct sst_compress_cb cb; - - stream = cstream->runtime->private_data; - /* construct fw structure for this*/ - memset(&str_params, 0, sizeof(str_params)); - - str_params.ops = STREAM_OPS_PLAYBACK; - str_params.stream_type = SST_STREAM_TYPE_MUSIC; - str_params.device_type = SND_SST_DEVICE_COMPRESS; - - switch (params->codec.id) { - case SND_AUDIOCODEC_MP3: { - str_params.codec = SST_CODEC_TYPE_MP3; - str_params.sparams.uc.mp3_params.codec = SST_CODEC_TYPE_MP3; - str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in; - str_params.sparams.uc.mp3_params.pcm_wd_sz = 16; - break; - } - - case SND_AUDIOCODEC_AAC: { - str_params.codec = SST_CODEC_TYPE_AAC; - str_params.sparams.uc.aac_params.codec = SST_CODEC_TYPE_AAC; - str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in; - str_params.sparams.uc.aac_params.pcm_wd_sz = 16; - if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS) - str_params.sparams.uc.aac_params.bs_format = - AAC_BIT_STREAM_ADTS; - else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW) - str_params.sparams.uc.aac_params.bs_format = - AAC_BIT_STREAM_RAW; - else { - pr_err("Undefined format%d\n", params->codec.format); - return -EINVAL; - } - str_params.sparams.uc.aac_params.externalsr = - params->codec.sample_rate; - break; - } - - default: - pr_err("codec not supported, id =%d\n", params->codec.id); - return -EINVAL; - } - - str_params.aparams.ring_buf_info[0].addr = - virt_to_phys(cstream->runtime->buffer); - str_params.aparams.ring_buf_info[0].size = - cstream->runtime->buffer_size; - str_params.aparams.sg_count = 1; - str_params.aparams.frag_size = cstream->runtime->fragment_size; - - cb.param = cstream; - cb.compr_cb = sst_compr_fragment_elapsed; - - retval = stream->compr_ops->open(&str_params, &cb); - if (retval < 0) { - pr_err("stream allocation failed %d\n", retval); - return retval; - } - - stream->id = retval; - return 0; -} - -static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) -{ - struct sst_runtime_stream *stream = - cstream->runtime->private_data; - - return stream->compr_ops->control(cmd, stream->id); -} - -static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp) -{ - struct sst_runtime_stream *stream; - - stream = cstream->runtime->private_data; - stream->compr_ops->tstamp(stream->id, tstamp); - tstamp->byte_offset = tstamp->copied_total % - (u32)cstream->runtime->buffer_size; - pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); - return 0; -} - -static int sst_platform_compr_ack(struct snd_compr_stream *cstream, - size_t bytes) -{ - struct sst_runtime_stream *stream; - - stream = cstream->runtime->private_data; - stream->compr_ops->ack(stream->id, (unsigned long)bytes); - stream->bytes_written += bytes; - - return 0; -} - -static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream, - struct snd_compr_caps *caps) -{ - struct sst_runtime_stream *stream = - cstream->runtime->private_data; - - return stream->compr_ops->get_caps(caps); -} - -static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, - struct snd_compr_codec_caps *codec) -{ - struct sst_runtime_stream *stream = - cstream->runtime->private_data; - - return stream->compr_ops->get_codec_caps(codec); -} - -static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream, - struct snd_compr_metadata *metadata) -{ - struct sst_runtime_stream *stream = - cstream->runtime->private_data; - - return stream->compr_ops->set_metadata(stream->id, metadata); -} - -static struct snd_compr_ops sst_platform_compr_ops = { - - .open = sst_platform_compr_open, - .free = sst_platform_compr_free, - .set_params = sst_platform_compr_set_params, - .set_metadata = sst_platform_compr_set_metadata, - .trigger = sst_platform_compr_trigger, - .pointer = sst_platform_compr_pointer, - .ack = sst_platform_compr_ack, - .get_caps = sst_platform_compr_get_caps, - .get_codec_caps = sst_platform_compr_get_codec_caps, -}; - -static struct snd_soc_platform_driver sst_soc_platform_drv = { - .ops = &sst_platform_ops, - .compr_ops = &sst_platform_compr_ops, - .pcm_new = sst_pcm_new, - .pcm_free = sst_pcm_free, -}; - -static int sst_platform_probe(struct platform_device *pdev) -{ - int ret; - - pr_debug("sst_platform_probe called\n"); - sst = NULL; - ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); - if (ret) { - pr_err("registering soc platform failed\n"); - return ret; - } - - ret = snd_soc_register_component(&pdev->dev, &sst_component, - sst_platform_dai, ARRAY_SIZE(sst_platform_dai)); - if (ret) { - pr_err("registering cpu dais failed\n"); - snd_soc_unregister_platform(&pdev->dev); - } - return ret; -} - -static int sst_platform_remove(struct platform_device *pdev) -{ - - snd_soc_unregister_component(&pdev->dev); - snd_soc_unregister_platform(&pdev->dev); - pr_debug("sst_platform_remove success\n"); - return 0; -} - -static struct platform_driver sst_platform_driver = { - .driver = { - .name = "sst-platform", - .owner = THIS_MODULE, - }, - .probe = sst_platform_probe, - .remove = sst_platform_remove, -}; - -module_platform_driver(sst_platform_driver); - -MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver"); -MODULE_AUTHOR("Vinod Koul "); -MODULE_AUTHOR("Harsha Priya "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:sst-platform"); diff --git a/sound/soc/intel/sst_platform.h b/sound/soc/intel/sst_platform.h deleted file mode 100644 index bee64fb7d2ef..000000000000 --- a/sound/soc/intel/sst_platform.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * sst_platform.h - Intel MID Platform driver header file - * - * Copyright (C) 2010 Intel Corp - * Author: Vinod Koul - * Author: Harsha Priya - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * - */ - -#ifndef __SST_PLATFORMDRV_H__ -#define __SST_PLATFORMDRV_H__ - -#include "sst_dsp.h" - -#define SST_MONO 1 -#define SST_STEREO 2 -#define SST_MAX_CAP 5 - -#define SST_MAX_BUFFER (800*1024) -#define SST_MIN_BUFFER (800*1024) -#define SST_MIN_PERIOD_BYTES 32 -#define SST_MAX_PERIOD_BYTES SST_MAX_BUFFER -#define SST_MIN_PERIODS 2 -#define SST_MAX_PERIODS (1024*2) -#define SST_FIFO_SIZE 0 - -struct pcm_stream_info { - int str_id; - void *mad_substream; - void (*period_elapsed) (void *mad_substream); - unsigned long long buffer_ptr; - int sfreq; -}; - -enum sst_drv_status { - SST_PLATFORM_INIT = 1, - SST_PLATFORM_STARTED, - SST_PLATFORM_RUNNING, - SST_PLATFORM_PAUSED, - SST_PLATFORM_DROPPED, -}; - -enum sst_controls { - SST_SND_ALLOC = 0x00, - SST_SND_PAUSE = 0x01, - SST_SND_RESUME = 0x02, - SST_SND_DROP = 0x03, - SST_SND_FREE = 0x04, - SST_SND_BUFFER_POINTER = 0x05, - SST_SND_STREAM_INIT = 0x06, - SST_SND_START = 0x07, - SST_MAX_CONTROLS = 0x07, -}; - -enum sst_stream_ops { - STREAM_OPS_PLAYBACK = 0, - STREAM_OPS_CAPTURE, -}; - -enum sst_audio_device_type { - SND_SST_DEVICE_HEADSET = 1, - SND_SST_DEVICE_IHF, - SND_SST_DEVICE_VIBRA, - SND_SST_DEVICE_HAPTIC, - SND_SST_DEVICE_CAPTURE, - SND_SST_DEVICE_COMPRESS, -}; - -/* PCM Parameters */ -struct sst_pcm_params { - u16 codec; /* codec type */ - u8 num_chan; /* 1=Mono, 2=Stereo */ - u8 pcm_wd_sz; /* 16/24 - bit*/ - u32 reserved; /* Bitrate in bits per second */ - u32 sfreq; /* Sampling rate in Hz */ - u32 ring_buffer_size; - u32 period_count; /* period elapsed in samples*/ - u32 ring_buffer_addr; -}; - -struct sst_stream_params { - u32 result; - u32 stream_id; - u8 codec; - u8 ops; - u8 stream_type; - u8 device_type; - struct sst_pcm_params sparams; -}; - -struct sst_compress_cb { - void *param; - void (*compr_cb)(void *param); -}; - -struct compress_sst_ops { - const char *name; - int (*open) (struct snd_sst_params *str_params, - struct sst_compress_cb *cb); - int (*control) (unsigned int cmd, unsigned int str_id); - int (*tstamp) (unsigned int str_id, struct snd_compr_tstamp *tstamp); - int (*ack) (unsigned int str_id, unsigned long bytes); - int (*close) (unsigned int str_id); - int (*get_caps) (struct snd_compr_caps *caps); - int (*get_codec_caps) (struct snd_compr_codec_caps *codec); - int (*set_metadata) (unsigned int str_id, - struct snd_compr_metadata *mdata); - -}; - -struct sst_ops { - int (*open) (struct sst_stream_params *str_param); - int (*device_control) (int cmd, void *arg); - int (*close) (unsigned int str_id); -}; - -struct sst_runtime_stream { - int stream_status; - unsigned int id; - size_t bytes_written; - struct pcm_stream_info stream_info; - struct sst_ops *ops; - struct compress_sst_ops *compr_ops; - spinlock_t status_lock; -}; - -struct sst_device { - char *name; - struct device *dev; - struct sst_ops *ops; - struct compress_sst_ops *compr_ops; -}; - -int sst_register_dsp(struct sst_device *sst); -int sst_unregister_dsp(struct sst_device *sst); -#endif -- cgit v1.2.3 From 86f28d76435b619bd0bc5f6fde2803a5bc27ca24 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 11 Feb 2014 15:42:48 +0800 Subject: ASoC: fsl-spdif: big-endian support For most platforms, the CPU and SPDIF device is in the same endianess mode. While for the LS1 platform, the CPU is in LE mode and the SPDIF is in BE mode. Signed-off-by: Xiubo Li Acked-by: Nicolin Chen Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,spdif.txt | 5 +++++ sound/soc/fsl/fsl_spdif.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt index f2ae335670f5..3e9e82c8eab3 100644 --- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt @@ -29,6 +29,10 @@ Required properties: can also be referred to TxClk_Source bit of register SPDIF_STC. + - big-endian : If this property is absent, the native endian mode will + be in use as default, or the big endian mode will be in use for all the + device registers. + Example: spdif: spdif@02004000 { @@ -50,5 +54,6 @@ spdif: spdif@02004000 { "rxtx5", "rxtx6", "rxtx7"; + big-endian; status = "okay"; }; diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 4d075f1abe78..73ceb2f9b90d 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -985,7 +985,7 @@ static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg) } } -static const struct regmap_config fsl_spdif_regmap_config = { +static struct regmap_config fsl_spdif_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, @@ -1105,6 +1105,9 @@ static int fsl_spdif_probe(struct platform_device *pdev) memcpy(&spdif_priv->cpu_dai_drv, &fsl_spdif_dai, sizeof(fsl_spdif_dai)); spdif_priv->cpu_dai_drv.name = spdif_priv->name; + if (of_property_read_bool(np, "big-endian")) + fsl_spdif_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; + /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); -- cgit v1.2.3 From eaba603fc7c6281908c316d9e58de688943d58be Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 11 Feb 2014 15:42:49 +0800 Subject: ASoC: fsl-esai: big-endian support For most platforms, the CPU and ESAI device is in the same endianess mode. While for the LS1 platform, the CPU is in LE mode and the ESAI is in BE mode. Signed-off-by: Xiubo Li Acked-by: Nicolin Chen Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,esai.txt | 5 +++++ sound/soc/fsl/fsl_esai.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt index d7b99fa637b5..aeb8c4a0b88d 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.txt +++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt @@ -34,6 +34,10 @@ Required properties: that ESAI would work in the synchronous mode, which means all the settings for Receiving would be duplicated from Transmition related registers. + - big-endian : If this property is absent, the native endian mode will + be in use as default, or the big endian mode will be in use for all the + device registers. + Example: esai: esai@02024000 { @@ -46,5 +50,6 @@ esai: esai@02024000 { dma-names = "rx", "tx"; fsl,fifo-depth = <128>; fsl,esai-synchronous; + big-endian; status = "disabled"; }; diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index f55341e52970..d8e13abd1bca 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -678,7 +678,7 @@ static bool fsl_esai_writeable_reg(struct device *dev, unsigned int reg) } } -static const struct regmap_config fsl_esai_regmap_config = { +static struct regmap_config fsl_esai_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, @@ -704,6 +704,9 @@ static int fsl_esai_probe(struct platform_device *pdev) esai_priv->pdev = pdev; strcpy(esai_priv->name, np->name); + if (of_property_read_bool(np, "big-endian")) + fsl_esai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; + /* Get the addresses and IRQ */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); -- cgit v1.2.3 From 048d4ff81f1cf26b3f3627a9a69d35aff7898bb3 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Mon, 10 Feb 2014 14:09:45 +0800 Subject: ASoC: atmel_ssc_dai: make option to choose clock When SSC works in slave mode, according to the hardware design, the clock can get from TK pin, also can get from RK pin. So, add one parameter to choose where the clock from. Signed-off-by: Bo Shen Acked-by: Nicolas Ferre Signed-off-by: Mark Brown --- drivers/misc/atmel-ssc.c | 6 ++++++ include/linux/atmel-ssc.h | 1 + sound/soc/atmel/atmel_ssc_dai.c | 13 +++++++++---- 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 5be808406edc..22de13727641 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -150,6 +150,12 @@ static int ssc_probe(struct platform_device *pdev) return -ENODEV; ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat; + if (pdev->dev.of_node) { + struct device_node *np = pdev->dev.of_node; + ssc->clk_from_rk_pin = + of_property_read_bool(np, "atmel,clk-from-rk-pin"); + } + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ssc->regs = devm_ioremap_resource(&pdev->dev, regs); if (IS_ERR(ssc->regs)) diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h index 66a0e5384edd..571a12ebb018 100644 --- a/include/linux/atmel-ssc.h +++ b/include/linux/atmel-ssc.h @@ -18,6 +18,7 @@ struct ssc_device { struct clk *clk; int user; int irq; + bool clk_from_rk_pin; }; struct ssc_device * __must_check ssc_request(unsigned int ssc_num); diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 1ead3c977a51..de433cfd044c 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -341,6 +341,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, { int id = dai->id; struct atmel_ssc_info *ssc_p = &ssc_info[id]; + struct ssc_device *ssc = ssc_p->ssc; struct atmel_pcm_dma_params *dma_params; int dir, channels, bits; u32 tfmr, rfmr, tcmr, rcmr; @@ -466,7 +467,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(RCMR_START, start_event) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) - | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK); + | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_PIN : SSC_CKS_CLOCK); rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) @@ -481,7 +483,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(TCMR_START, start_event) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_NONE) - | SSC_BF(TCMR_CKS, SSC_CKS_PIN); + | SSC_BF(TCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_CLOCK : SSC_CKS_PIN); tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSDEN, 0) @@ -550,7 +553,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(RCMR_START, SSC_START_RISING_RF) | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | SSC_BF(RCMR_CKO, SSC_CKO_NONE) - | SSC_BF(RCMR_CKS, SSC_CKS_PIN); + | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_PIN : SSC_CKS_CLOCK); rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) @@ -565,7 +569,8 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | SSC_BF(TCMR_START, SSC_START_RISING_RF) | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | SSC_BF(TCMR_CKO, SSC_CKO_NONE) - | SSC_BF(TCMR_CKS, SSC_CKS_PIN); + | SSC_BF(RCMR_CKS, ssc->clk_from_rk_pin ? + SSC_CKS_CLOCK : SSC_CKS_PIN); tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | SSC_BF(TFMR_FSDEN, 0) -- cgit v1.2.3 From 30ac6b6ebd175eaf5db7e0d7c015cd1460548b98 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 13 Feb 2014 14:14:21 +0100 Subject: ASoC: dapm: Consistently use unsigned int for register values Commit f7d3c1709 ("ASoC: dapm: Change prototype of soc_widget_read") changed the signature of soc_widget_read() so that it, instead of return the register value as a int, takes a pointer to a unsigned int and stores the register value in that pointer. There are still a few places that pass a int type value to that function though. Change these to unsigned int. For more consistency also change the signature of soc_widget_write() to take a unsigned int instead of an int for the register value. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dc8ff13187f7..2c2d751c6d54 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -386,7 +386,8 @@ static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg, return -1; } -static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val) +static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, + unsigned int val) { if (w->codec) return snd_soc_write(w->codec, reg, val); @@ -506,7 +507,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_switch: case snd_soc_dapm_mixer: case snd_soc_dapm_mixer_named_ctl: { - int val; + unsigned int val; struct soc_mixer_control *mc = (struct soc_mixer_control *) w->kcontrol_news[i].private_value; int reg = mc->reg; @@ -530,7 +531,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_mux: { struct soc_enum *e = (struct soc_enum *) w->kcontrol_news[i].private_value; - int val, item; + unsigned int val, item; soc_widget_read(w, e->reg, &val); item = (val >> e->shift_l) & e->mask; @@ -559,7 +560,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_value_mux: { struct soc_enum *e = (struct soc_enum *) w->kcontrol_news[i].private_value; - int val, item; + unsigned int val, item; soc_widget_read(w, e->reg, &val); val = (val >> e->shift_l) & e->mask; -- cgit v1.2.3 From 102b5a8d4ac62d8ff4920b64da8b4b488ce67261 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 29 Jan 2014 14:42:55 +0100 Subject: ASoC: core: Convert to snd_card_new() with a device pointer Also remove superfluous card->dev assignment. Reviewed-by: Mark Brown Signed-off-by: Takashi Iwai --- sound/soc/soc-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..135ddb01aadb 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1654,7 +1654,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) } /* card bind complete so register a sound card */ - ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + ret = snd_card_new(card->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, card->owner, 0, &card->snd_card); if (ret < 0) { dev_err(card->dev, @@ -1662,7 +1662,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) card->name, ret); goto base_error; } - card->snd_card->dev = card->dev; card->dapm.bias_level = SND_SOC_BIAS_OFF; card->dapm.dev = card->dev; -- cgit v1.2.3 From 74d04c3efbc4f10990e5c4218ad3f65bfdcf3c75 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 12 Feb 2014 18:20:56 +0100 Subject: sound: ASoC: add ASoC board driver for Armada 370 DB This commit adds a simple ASoC board driver fo the Armada 370 Development Board, which connects the audio unit of the Armada 370 SoC to the I2C-based CS42L51. For now, only the analog audio input and output through the CS42L51 are supported, but a followup patch adds S/PDIF support to this driver. Signed-off-by: Thomas Petazzoni Signed-off-by: Mark Brown --- .../bindings/sound/armada-370db-audio.txt | 24 +++++ sound/soc/kirkwood/Kconfig | 8 ++ sound/soc/kirkwood/Makefile | 2 + sound/soc/kirkwood/armada-370-db.c | 120 +++++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/armada-370db-audio.txt create mode 100644 sound/soc/kirkwood/armada-370-db.c (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/armada-370db-audio.txt b/Documentation/devicetree/bindings/sound/armada-370db-audio.txt new file mode 100644 index 000000000000..3893b4d15a20 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/armada-370db-audio.txt @@ -0,0 +1,24 @@ +Device Tree bindings for the Armada 370 DB audio +================================================ + +These Device Tree bindings are used to describe the audio complex +found on the Armada 370 DB platform. + +Mandatory properties: + + * compatible: must be "marvell,a370db-audio" + + * marvell,audio-controller: a phandle that points to the audio + controller of the Armada 370 SoC. + + * marvell,audio-codec: a phandle that points to the analog audio + codec connected to the Armada 370 SoC. + +Example: + + sound { + compatible = "marvell,a370db-audio"; + marvell,audio-controller = <&audio_controller>; + marvell,audio-codec = <&audio_codec>; + status = "okay"; + }; diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 764a0ef6b268..2dc3ecf34801 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig @@ -6,6 +6,14 @@ config SND_KIRKWOOD_SOC the Kirkwood I2S interface. You will also need to select the audio interfaces to support below. +config SND_KIRKWOOD_SOC_ARMADA370_DB + tristate "SoC Audio support for Armada 370 DB" + depends on SND_KIRKWOOD_SOC && (ARCH_MVEBU || COMPILE_TEST) && I2C + select SND_SOC_CS42L51 + help + Say Y if you want to add support for SoC audio on + the Armada 370 Development Board. + config SND_KIRKWOOD_SOC_OPENRD tristate "SoC Audio support for Kirkwood Openrd Client" depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE || COMPILE_TEST) diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile index 9e781385cb88..7c1d8fe09e6b 100644 --- a/sound/soc/kirkwood/Makefile +++ b/sound/soc/kirkwood/Makefile @@ -4,6 +4,8 @@ obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o snd-soc-openrd-objs := kirkwood-openrd.o snd-soc-t5325-objs := kirkwood-t5325.o +snd-soc-armada-370-db-objs := armada-370-db.o +obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c new file mode 100644 index 000000000000..977639b3ffde --- /dev/null +++ b/sound/soc/kirkwood/armada-370-db.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2014 Marvell + * + * Thomas Petazzoni + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../codecs/cs42l51.h" + +static int a370db_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + unsigned int freq; + + switch (params_rate(params)) { + default: + case 44100: + freq = 11289600; + break; + case 48000: + freq = 12288000; + break; + case 96000: + freq = 24576000; + break; + } + + return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); +} + +static struct snd_soc_ops a370db_ops = { + .hw_params = a370db_hw_params, +}; + +static const struct snd_soc_dapm_widget a370db_dapm_widgets[] = { + SND_SOC_DAPM_HP("Out Jack", NULL), + SND_SOC_DAPM_LINE("In Jack", NULL), +}; + +static const struct snd_soc_dapm_route a370db_route[] = { + { "Out Jack", NULL, "HPL" }, + { "Out Jack", NULL, "HPR" }, + { "AIN1L", NULL, "In Jack" }, + { "AIN1L", NULL, "In Jack" }, +}; + +static struct snd_soc_dai_link a370db_dai[] = { +{ + .name = "CS42L51", + .stream_name = "analog", + .cpu_dai_name = "i2s", + .codec_dai_name = "cs42l51-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, + .ops = &a370db_ops, +}, +}; + +static struct snd_soc_card a370db = { + .name = "a370db", + .owner = THIS_MODULE, + .dai_link = a370db_dai, + .num_links = ARRAY_SIZE(a370db_dai), + .dapm_widgets = a370db_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(a370db_dapm_widgets), + .dapm_routes = a370db_route, + .num_dapm_routes = ARRAY_SIZE(a370db_route), +}; + +static int a370db_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &a370db; + + card->dev = &pdev->dev; + + a370db_dai[0].cpu_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-controller", 0); + a370db_dai[0].platform_of_node = a370db_dai[0].cpu_of_node; + + a370db_dai[0].codec_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-codec", 0); + + return devm_snd_soc_register_card(card->dev, card); +} + +static const struct of_device_id a370db_dt_ids[] = { + { .compatible = "marvell,a370db-audio" }, + { }, +}; + +static struct platform_driver a370db_driver = { + .driver = { + .name = "a370db-audio", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(a370db_dt_ids), + }, + .probe = a370db_probe, +}; + +module_platform_driver(a370db_driver); + +MODULE_AUTHOR("Thomas Petazzoni "); +MODULE_DESCRIPTION("ALSA SoC a370db audio client"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:a370db-audio"); -- cgit v1.2.3 From f951f835a9719996e08e5c2932afc65ebfdbf47a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 16 Feb 2014 08:29:21 +0800 Subject: ASoC: pcm512x: Add regmap select We need at least the core regmap code to build. Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 56d0c2845680..fa47a8336be3 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -316,6 +316,7 @@ config SND_SOC_PCM3008 config SND_SOC_PCM512x tristate "Texas Instruments PCM512x CODECs" + select REGMAP config SND_SOC_RT5631 tristate -- cgit v1.2.3 From 7b80300e749c2865fbfc23870d3b8f3186956fc0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 16 Feb 2014 10:04:43 +0800 Subject: ASoC: io: Remove SPI support All ASoC CODEC drivers that use SPI have now been converted to use regmap so we can delete SND_SOC_SPI, preventing any new users being added. Signed-off-by: Mark Brown --- include/sound/soc.h | 1 - sound/soc/soc-io.c | 7 ------- 2 files changed, 8 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a001472b96a..6197ba0642cc 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -342,7 +342,6 @@ extern struct snd_ac97_bus_ops *soc_ac97_ops; enum snd_soc_control_type { SND_SOC_I2C = 1, - SND_SOC_SPI, SND_SOC_REGMAP, }; diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index aa886cca3ecf..3a0d99edf030 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -106,13 +106,6 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, break; #endif -#if IS_ENABLED(CONFIG_REGMAP_SPI) - case SND_SOC_SPI: - codec->control_data = regmap_init_spi(to_spi_device(codec->dev), - &config); - break; -#endif - case SND_SOC_REGMAP: /* Device has made its own regmap arrangements */ codec->using_regmap = true; -- cgit v1.2.3 From 6c3d713e6d32706999689e379a9098afb4cd8a2c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Feb 2014 13:16:54 +0100 Subject: ASoC: ad193x: Split SPI and I2C code into different modules There are a few known (minor) problems with having the support code for both I2C and SPI in the same module: * We need to be extra careful to make sure to not build the driver into the kernel if one of the subsystems is build as a module (Currently only I2C can be build as a module). * The module init path error handling is rather ugly. E.g. what should be done if either the SPI or the I2C driver fails to register? Most drivers that implement SPI and I2C in the same module currently fallback to undefined behavior in that case. Splitting the the driver into two modules, one for each bus, allows the registration of the other bus driver to continue without problems if one of them fails. This patch splits the AD193X driver into 3 modules. One core module that implements the device logic, but is independent of the bus method used. And one module for SPI and I2C each that registers the drivers and sets up the regmap struct for the bus. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/blackfin/Kconfig | 3 +- sound/soc/codecs/Kconfig | 11 +++- sound/soc/codecs/Makefile | 4 ++ sound/soc/codecs/ad193x-i2c.c | 54 ++++++++++++++++ sound/soc/codecs/ad193x-spi.c | 48 +++++++++++++++ sound/soc/codecs/ad193x.c | 140 +++++------------------------------------- sound/soc/codecs/ad193x.h | 7 +++ 7 files changed, 140 insertions(+), 127 deletions(-) create mode 100644 sound/soc/codecs/ad193x-i2c.c create mode 100644 sound/soc/codecs/ad193x-spi.c (limited to 'sound/soc') diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 54f74f8cbb75..359136777c4d 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -68,7 +68,8 @@ config SND_BF5XX_SOC_AD193X tristate "SoC AD193X Audio support for Blackfin" depends on SND_BF5XX_I2S select SND_BF5XX_SOC_I2S - select SND_SOC_AD193X + select SND_SOC_AD193X_I2C if I2C + select SND_SOC_AD193X_SPI if SPI_MASTER help Say Y if you want to add support for AD193X codec on Blackfin. This driver supports AD1936, AD1937, AD1938 and AD1939. diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..d7da6191fc55 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -16,7 +16,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_AB8500_CODEC if ABX500_CORE select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS select SND_SOC_AD1836 if SPI_MASTER - select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI + select SND_SOC_AD193X_SPI if SPI_MASTER + select SND_SOC_AD193X_I2C if I2C select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 select SND_SOC_ADAU1373 if I2C @@ -182,6 +183,14 @@ config SND_SOC_AD1836 config SND_SOC_AD193X tristate +config SND_SOC_AD193X_SPI + tristate + select SND_SOC_AD193X + +config SND_SOC_AD193X_I2C + tristate + select SND_SOC_AD193X + config SND_SOC_AD1980 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..7795e37d313f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -3,6 +3,8 @@ snd-soc-ab8500-codec-objs := ab8500-codec.o snd-soc-ac97-objs := ac97.o snd-soc-ad1836-objs := ad1836.o snd-soc-ad193x-objs := ad193x.o +snd-soc-ad193x-spi-objs := ad193x-spi.o +snd-soc-ad193x-i2c-objs := ad193x-i2c.o snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o @@ -134,6 +136,8 @@ obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o +obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o +obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c new file mode 100644 index 000000000000..df3a1a415825 --- /dev/null +++ b/sound/soc/codecs/ad193x-i2c.c @@ -0,0 +1,54 @@ +/* + * AD1936/AD1937 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "ad193x.h" + +static const struct i2c_device_id ad193x_id[] = { + { "ad1936", 0 }, + { "ad1937", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ad193x_id); + +static int ad193x_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap_config config; + + config = ad193x_regmap_config; + config.val_bits = 8; + config.reg_bits = 8; + + return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config)); +} + +static int ad193x_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static struct i2c_driver ad193x_i2c_driver = { + .driver = { + .name = "ad193x", + }, + .probe = ad193x_i2c_probe, + .remove = ad193x_i2c_remove, + .id_table = ad193x_id, +}; +module_i2c_driver(ad193x_i2c_driver); + +MODULE_DESCRIPTION("ASoC AD1936/AD1937 audio CODEC driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c new file mode 100644 index 000000000000..390cef9b9dc2 --- /dev/null +++ b/sound/soc/codecs/ad193x-spi.c @@ -0,0 +1,48 @@ +/* + * AD1938/AD1939 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "ad193x.h" + +static int ad193x_spi_probe(struct spi_device *spi) +{ + struct regmap_config config; + + config = ad193x_regmap_config; + config.val_bits = 8; + config.reg_bits = 16; + config.read_flag_mask = 0x09; + config.write_flag_mask = 0x08; + + return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); +} + +static int ad193x_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver ad193x_spi_driver = { + .driver = { + .name = "ad193x", + .owner = THIS_MODULE, + }, + .probe = ad193x_spi_probe, + .remove = ad193x_spi_remove, +}; +module_spi_driver(ad193x_spi_driver); + +MODULE_DESCRIPTION("ASoC AD1938/AD1939 audio CODEC driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 5a42dca535b7..f644a34a28de 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -6,12 +6,10 @@ * Licensed under the GPL-2 or later. */ -#include #include #include #include -#include -#include +#include #include #include #include @@ -19,6 +17,7 @@ #include #include #include + #include "ad193x.h" /* codec private data */ @@ -320,7 +319,7 @@ static struct snd_soc_dai_driver ad193x_dai = { .ops = &ad193x_dai_ops, }; -static int ad193x_probe(struct snd_soc_codec *codec) +static int ad193x_codec_probe(struct snd_soc_codec *codec) { struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); int ret; @@ -352,7 +351,7 @@ static int ad193x_probe(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_ad193x = { - .probe = ad193x_probe, + .probe = ad193x_codec_probe, .controls = ad193x_snd_controls, .num_controls = ARRAY_SIZE(ad193x_snd_controls), .dapm_widgets = ad193x_dapm_widgets, @@ -366,140 +365,31 @@ static bool adau193x_reg_volatile(struct device *dev, unsigned int reg) return false; } -#if defined(CONFIG_SPI_MASTER) - -static const struct regmap_config ad193x_spi_regmap_config = { - .val_bits = 8, - .reg_bits = 16, - .read_flag_mask = 0x09, - .write_flag_mask = 0x08, - +const struct regmap_config ad193x_regmap_config = { .max_register = AD193X_NUM_REGS - 1, .volatile_reg = adau193x_reg_volatile, }; +EXPORT_SYMBOL_GPL(ad193x_regmap_config); -static int ad193x_spi_probe(struct spi_device *spi) +int ad193x_probe(struct device *dev, struct regmap *regmap) { struct ad193x_priv *ad193x; - ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), - GFP_KERNEL); - if (ad193x == NULL) - return -ENOMEM; - - ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config); - if (IS_ERR(ad193x->regmap)) - return PTR_ERR(ad193x->regmap); - - spi_set_drvdata(spi, ad193x); - - return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, - &ad193x_dai, 1); -} - -static int ad193x_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver ad193x_spi_driver = { - .driver = { - .name = "ad193x", - .owner = THIS_MODULE, - }, - .probe = ad193x_spi_probe, - .remove = ad193x_spi_remove, -}; -#endif - -#if IS_ENABLED(CONFIG_I2C) - -static const struct regmap_config ad193x_i2c_regmap_config = { - .val_bits = 8, - .reg_bits = 8, - - .max_register = AD193X_NUM_REGS - 1, - .volatile_reg = adau193x_reg_volatile, -}; - -static const struct i2c_device_id ad193x_id[] = { - { "ad1936", 0 }, - { "ad1937", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ad193x_id); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); -static int ad193x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ad193x_priv *ad193x; - - ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), - GFP_KERNEL); + ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL); if (ad193x == NULL) return -ENOMEM; - ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config); - if (IS_ERR(ad193x->regmap)) - return PTR_ERR(ad193x->regmap); - - i2c_set_clientdata(client, ad193x); - - return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, - &ad193x_dai, 1); -} - -static int ad193x_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} + ad193x->regmap = regmap; -static struct i2c_driver ad193x_i2c_driver = { - .driver = { - .name = "ad193x", - }, - .probe = ad193x_i2c_probe, - .remove = ad193x_i2c_remove, - .id_table = ad193x_id, -}; -#endif - -static int __init ad193x_modinit(void) -{ - int ret; - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&ad193x_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n", - ret); - } -#endif - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&ad193x_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(ad193x_modinit); - -static void __exit ad193x_modexit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&ad193x_spi_driver); -#endif + dev_set_drvdata(dev, ad193x); -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&ad193x_i2c_driver); -#endif + return snd_soc_register_codec(dev, &soc_codec_dev_ad193x, + &ad193x_dai, 1); } -module_exit(ad193x_modexit); +EXPORT_SYMBOL_GPL(ad193x_probe); MODULE_DESCRIPTION("ASoC ad193x driver"); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 473388049992..ab9a998f15be 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h @@ -9,6 +9,13 @@ #ifndef __AD193X_H__ #define __AD193X_H__ +#include + +struct device; + +extern const struct regmap_config ad193x_regmap_config; +int ad193x_probe(struct device *dev, struct regmap *regmap); + #define AD193X_PLL_CLK_CTRL0 0x00 #define AD193X_PLL_POWERDOWN 0x01 #define AD193X_PLL_INPUT_MASK 0x6 -- cgit v1.2.3 From c924dc68f7371582cb420c003faadb700cd4f76c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Feb 2014 13:16:53 +0100 Subject: ASoC: ssm2602: Split SPI and I2C code into different modules There are a few known (minor) problems with having the support code for both I2C and SPI in the same module: * We need to be extra careful to make sure to not build the driver into the kernel if one of the subsystems is build as a module (Currently only I2C can be build as a module). * The module init path error handling is rather ugly. E.g. what should be done if either the SPI or the I2C driver fails to register? Most drivers that implement SPI and I2C in the same module currently fallback to undefined behavior in that case. Splitting the the driver into two modules, one for each bus allows the registration of the other bus driver to continue without problems if one of them fails. This patch splits the ssm2602 driver into 3 modules. One core module that implements the device logic, but is independent of the bus method used. And one module for SPI and I2C each that registers the drivers and sets up the regmap struct for the bus. While we are at it also cleanup the include section of the ssm2602 driver and remove unneeded includes. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/blackfin/Kconfig | 3 +- sound/soc/codecs/Kconfig | 11 ++- sound/soc/codecs/Makefile | 4 ++ sound/soc/codecs/ssm2602-i2c.c | 57 +++++++++++++++ sound/soc/codecs/ssm2602-spi.c | 41 +++++++++++ sound/soc/codecs/ssm2602.c | 158 ++++++----------------------------------- sound/soc/codecs/ssm2602.h | 14 ++++ 7 files changed, 148 insertions(+), 140 deletions(-) create mode 100644 sound/soc/codecs/ssm2602-i2c.c create mode 100644 sound/soc/codecs/ssm2602-spi.c (limited to 'sound/soc') diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 54f74f8cbb75..f9118dc98853 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -14,7 +14,8 @@ config SND_BF5XX_SOC_SSM2602 depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) select SND_BF5XX_SOC_I2S if !BF60x select SND_BF6XX_SOC_I2S if BF60x - select SND_SOC_SSM2602 + select SND_SOC_SSM2602_SPI if SPI_MASTER + select SND_SOC_SSM2602_I2C if I2C help Say Y if you want to add support for the Analog Devices SSM2602 Audio Codec Add-On Card. diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..f17e6da53ce7 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -66,7 +66,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_SN95031 if INTEL_SCU_IPC select SND_SOC_SPDIF select SND_SOC_SSM2518 if I2C - select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI + select SND_SOC_SSM2602_SPI if SPI_MASTER + select SND_SOC_SSM2602_I2C if I2C select SND_SOC_STA32X if I2C select SND_SOC_STA529 if I2C select SND_SOC_STAC9766 if SND_SOC_AC97_BUS @@ -342,6 +343,14 @@ config SND_SOC_SSM2518 config SND_SOC_SSM2602 tristate +config SND_SOC_SSM2602_SPI + select SND_SOC_SSM2602 + tristate + +config SND_SOC_SSM2602_I2C + select SND_SOC_SSM2602 + tristate + config SND_SOC_STA32X tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..e7a2fb91148f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -58,6 +58,8 @@ snd-soc-spdif-tx-objs := spdif_transmitter.o snd-soc-spdif-rx-objs := spdif_receiver.o snd-soc-ssm2518-objs := ssm2518.o snd-soc-ssm2602-objs := ssm2602.o +snd-soc-ssm2602-spi-objs := ssm2602-spi.o +snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o snd-soc-sta32x-objs := sta32x.o snd-soc-sta529-objs := sta529.o snd-soc-stac9766-objs := stac9766.o @@ -188,6 +190,8 @@ obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o +obj-$(CONFIG_SND_SOC_SSM2602_SPI) += snd-soc-ssm2602-spi.o +obj-$(CONFIG_SND_SOC_SSM2602_I2C) += snd-soc-ssm2602-i2c.o obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c new file mode 100644 index 000000000000..abd63d537173 --- /dev/null +++ b/sound/soc/codecs/ssm2602-i2c.c @@ -0,0 +1,57 @@ +/* + * SSM2602/SSM2603/SSM2604 I2C audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "ssm2602.h" + +/* + * ssm2602 2 wire address is determined by GPIO5 + * state during powerup. + * low = 0x1a + * high = 0x1b + */ +static int ssm2602_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + return ssm2602_probe(&client->dev, id->driver_data, + devm_regmap_init_i2c(client, &ssm2602_regmap_config)); +} + +static int ssm2602_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static const struct i2c_device_id ssm2602_i2c_id[] = { + { "ssm2602", SSM2602 }, + { "ssm2603", SSM2602 }, + { "ssm2604", SSM2604 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); + +static struct i2c_driver ssm2602_i2c_driver = { + .driver = { + .name = "ssm2602", + .owner = THIS_MODULE, + }, + .probe = ssm2602_i2c_probe, + .remove = ssm2602_i2c_remove, + .id_table = ssm2602_i2c_id, +}; +module_i2c_driver(ssm2602_i2c_driver); + +MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 I2C driver"); +MODULE_AUTHOR("Cliff Cai"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ssm2602-spi.c b/sound/soc/codecs/ssm2602-spi.c new file mode 100644 index 000000000000..2bf55e24a7bb --- /dev/null +++ b/sound/soc/codecs/ssm2602-spi.c @@ -0,0 +1,41 @@ +/* + * SSM2602 SPI audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "ssm2602.h" + +static int ssm2602_spi_probe(struct spi_device *spi) +{ + return ssm2602_probe(&spi->dev, SSM2602, + devm_regmap_init_spi(spi, &ssm2602_regmap_config)); +} + +static int ssm2602_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver ssm2602_spi_driver = { + .driver = { + .name = "ssm2602", + .owner = THIS_MODULE, + }, + .probe = ssm2602_spi_probe, + .remove = ssm2602_spi_remove, +}; +module_spi_driver(ssm2602_spi_driver); + +MODULE_DESCRIPTION("ASoC SSM2602 SPI driver"); +MODULE_AUTHOR("Cliff Cai"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index f444d585b916..49d28eaa6d73 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -27,28 +27,16 @@ */ #include -#include -#include -#include -#include -#include -#include #include #include -#include + #include #include #include -#include #include #include "ssm2602.h" -enum ssm2602_type { - SSM2602, - SSM2604, -}; - /* codec private data */ struct ssm2602_priv { unsigned int sysclk; @@ -529,7 +517,7 @@ static int ssm2602_resume(struct snd_soc_codec *codec) return 0; } -static int ssm2602_probe(struct snd_soc_codec *codec) +static int ssm2602_codec_probe(struct snd_soc_codec *codec) { struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; @@ -554,7 +542,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec) ARRAY_SIZE(ssm2602_routes)); } -static int ssm2604_probe(struct snd_soc_codec *codec) +static int ssm2604_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; @@ -568,7 +556,7 @@ static int ssm2604_probe(struct snd_soc_codec *codec) ARRAY_SIZE(ssm2604_routes)); } -static int ssm260x_probe(struct snd_soc_codec *codec) +static int ssm260x_codec_probe(struct snd_soc_codec *codec) { struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); int ret; @@ -597,10 +585,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec) switch (ssm2602->type) { case SSM2602: - ret = ssm2602_probe(codec); + ret = ssm2602_codec_probe(codec); break; case SSM2604: - ret = ssm2604_probe(codec); + ret = ssm2604_codec_probe(codec); break; } @@ -620,7 +608,7 @@ static int ssm2602_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { - .probe = ssm260x_probe, + .probe = ssm260x_codec_probe, .remove = ssm2602_remove, .suspend = ssm2602_suspend, .resume = ssm2602_resume, @@ -639,7 +627,7 @@ static bool ssm2602_register_volatile(struct device *dev, unsigned int reg) return reg == SSM2602_RESET; } -static const struct regmap_config ssm2602_regmap_config = { +const struct regmap_config ssm2602_regmap_config = { .val_bits = 9, .reg_bits = 7, @@ -650,134 +638,28 @@ static const struct regmap_config ssm2602_regmap_config = { .reg_defaults_raw = ssm2602_reg, .num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg), }; +EXPORT_SYMBOL_GPL(ssm2602_regmap_config); -#if defined(CONFIG_SPI_MASTER) -static int ssm2602_spi_probe(struct spi_device *spi) +int ssm2602_probe(struct device *dev, enum ssm2602_type type, + struct regmap *regmap) { struct ssm2602_priv *ssm2602; - int ret; - - ssm2602 = devm_kzalloc(&spi->dev, sizeof(struct ssm2602_priv), - GFP_KERNEL); - if (ssm2602 == NULL) - return -ENOMEM; - - spi_set_drvdata(spi, ssm2602); - ssm2602->type = SSM2602; - - ssm2602->regmap = devm_regmap_init_spi(spi, &ssm2602_regmap_config); - if (IS_ERR(ssm2602->regmap)) - return PTR_ERR(ssm2602->regmap); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_ssm2602, &ssm2602_dai, 1); - return ret; -} -static int ssm2602_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver ssm2602_spi_driver = { - .driver = { - .name = "ssm2602", - .owner = THIS_MODULE, - }, - .probe = ssm2602_spi_probe, - .remove = ssm2602_spi_remove, -}; -#endif - -#if IS_ENABLED(CONFIG_I2C) -/* - * ssm2602 2 wire address is determined by GPIO5 - * state during powerup. - * low = 0x1a - * high = 0x1b - */ -static int ssm2602_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct ssm2602_priv *ssm2602; - int ret; + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - ssm2602 = devm_kzalloc(&i2c->dev, sizeof(struct ssm2602_priv), - GFP_KERNEL); + ssm2602 = devm_kzalloc(dev, sizeof(*ssm2602), GFP_KERNEL); if (ssm2602 == NULL) return -ENOMEM; - i2c_set_clientdata(i2c, ssm2602); - ssm2602->type = id->driver_data; - - ssm2602->regmap = devm_regmap_init_i2c(i2c, &ssm2602_regmap_config); - if (IS_ERR(ssm2602->regmap)) - return PTR_ERR(ssm2602->regmap); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_ssm2602, &ssm2602_dai, 1); - return ret; -} - -static int ssm2602_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id ssm2602_i2c_id[] = { - { "ssm2602", SSM2602 }, - { "ssm2603", SSM2602 }, - { "ssm2604", SSM2604 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); - -/* corgi i2c codec control layer */ -static struct i2c_driver ssm2602_i2c_driver = { - .driver = { - .name = "ssm2602", - .owner = THIS_MODULE, - }, - .probe = ssm2602_i2c_probe, - .remove = ssm2602_i2c_remove, - .id_table = ssm2602_i2c_id, -}; -#endif - - -static int __init ssm2602_modinit(void) -{ - int ret = 0; - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&ssm2602_spi_driver); - if (ret) - return ret; -#endif - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&ssm2602_i2c_driver); - if (ret) - return ret; -#endif - - return ret; -} -module_init(ssm2602_modinit); - -static void __exit ssm2602_exit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&ssm2602_spi_driver); -#endif + dev_set_drvdata(dev, ssm2602); + ssm2602->type = SSM2602; + ssm2602->regmap = regmap; -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&ssm2602_i2c_driver); -#endif + return snd_soc_register_codec(dev, &soc_codec_dev_ssm2602, + &ssm2602_dai, 1); } -module_exit(ssm2602_exit); +EXPORT_SYMBOL_GPL(ssm2602_probe); MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver"); MODULE_AUTHOR("Cliff Cai"); diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h index fbd07d7b73ca..747538847689 100644 --- a/sound/soc/codecs/ssm2602.h +++ b/sound/soc/codecs/ssm2602.h @@ -28,6 +28,20 @@ #ifndef _SSM2602_H #define _SSM2602_H +#include + +struct device; + +enum ssm2602_type { + SSM2602, + SSM2604, +}; + +extern const struct regmap_config ssm2602_regmap_config; + +int ssm2602_probe(struct device *dev, enum ssm2602_type type, + struct regmap *regmap); + /* SSM2602 Codec Register definitions */ #define SSM2602_LINVOL 0x00 -- cgit v1.2.3 From f96a5d3f1c09ce85ac1a90d733ca3585b9f2f70a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Feb 2014 13:16:55 +0100 Subject: ASoC: adav80x: Use devm_kzalloc() Use devm_kzalloc() to allocate the device state struct. Saves use from having to free it manually on the error path and in the remove callback. Now that the adav80x_bus_probe() function is only a call to snd_soc_unregister_codec() also inline that. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/adav80x.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index f78b27a7c461..a4bd051c5430 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -872,27 +872,15 @@ static int adav80x_bus_probe(struct device *dev, struct regmap *regmap) if (IS_ERR(regmap)) return PTR_ERR(regmap); - adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL); + adav80x = devm_kzalloc(dev, sizeof(*adav80x), GFP_KERNEL); if (!adav80x) return -ENOMEM; - dev_set_drvdata(dev, adav80x); adav80x->regmap = regmap; - ret = snd_soc_register_codec(dev, &adav80x_codec_driver, + return snd_soc_register_codec(dev, &adav80x_codec_driver, adav80x_dais, ARRAY_SIZE(adav80x_dais)); - if (ret) - kfree(adav80x); - - return ret; -} - -static int adav80x_bus_remove(struct device *dev) -{ - snd_soc_unregister_codec(dev); - kfree(dev_get_drvdata(dev)); - return 0; } #if defined(CONFIG_SPI_MASTER) @@ -923,7 +911,8 @@ static int adav80x_spi_probe(struct spi_device *spi) static int adav80x_spi_remove(struct spi_device *spi) { - return adav80x_bus_remove(&spi->dev); + snd_soc_unregister_codec(dev); + return 0; } static struct spi_driver adav80x_spi_driver = { @@ -965,7 +954,8 @@ static int adav80x_i2c_probe(struct i2c_client *client, static int adav80x_i2c_remove(struct i2c_client *client) { - return adav80x_bus_remove(&client->dev); + snd_soc_unregister_codec(dev); + return 0; } static struct i2c_driver adav80x_i2c_driver = { -- cgit v1.2.3 From 0c2d6964562835501280409cac5d4ee28e07e8c2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Feb 2014 13:16:56 +0100 Subject: ASoC: adav80x: Split SPI and I2C code into different modules There are a few known (minor) problems with having the support code for both I2C and SPI in the same module: * We need to be extra careful to make sure to not build the driver into the kernel if one of the subsystems is build as a module (Currently only I2C can be build as a module). * The module init path error handling is rather ugly. E.g. what should be done if either the SPI or the I2C driver fails to register. Most drivers that implement SPI and I2C in the same module currently fallback to undefined behavior in that case. Splitting the the driver into two modules, one for each bus, allows the registration of the other bus drive to continue without problems if one of them fails. This patch splits the ADAV80X driver into 3 modules. One core module that implements the device logic, but is independent of the bus method used. And one module for SPI and I2C each that registers the drivers and sets up the regmap struct for the bus. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/blackfin/Kconfig | 3 +- sound/soc/codecs/Kconfig | 11 ++++- sound/soc/codecs/Makefile | 4 ++ sound/soc/codecs/adav801.c | 53 ++++++++++++++++++++ sound/soc/codecs/adav803.c | 50 +++++++++++++++++++ sound/soc/codecs/adav80x.c | 117 +++------------------------------------------ sound/soc/codecs/adav80x.h | 7 +++ 7 files changed, 133 insertions(+), 112 deletions(-) create mode 100644 sound/soc/codecs/adav801.c create mode 100644 sound/soc/codecs/adav803.c (limited to 'sound/soc') diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 54f74f8cbb75..18abd884d84f 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -47,7 +47,8 @@ config SND_SOC_BFIN_EVAL_ADAV80X tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards" depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) select SND_BF5XX_SOC_I2S - select SND_SOC_ADAV80X + select SND_SOC_ADAV801 if SPI_MASTER + select SND_SOC_ADAV803 if I2C help Say Y if you want to add support for the Analog Devices EVAL-ADAV801 or EVAL-ADAV803 board connected to one of the Blackfin evaluation boards diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..9556321c7b8b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -20,7 +20,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 select SND_SOC_ADAU1373 if I2C - select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI + select SND_SOC_ADAV801 if SPI_MASTER + select SND_SOC_ADAV803 if I2C select SND_SOC_ADAU1701 if I2C select SND_SOC_ADS117X select SND_SOC_AK4104 if SPI_MASTER @@ -198,6 +199,14 @@ config SND_SOC_ADAU1373 config SND_SOC_ADAV80X tristate +config SND_SOC_ADAV801 + tristate + select SND_SOC_ADAV80X + +config SND_SOC_ADAV803 + tristate + select SND_SOC_ADAV80X + config SND_SOC_ADS117X tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..1b2c6eca863f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -8,6 +8,8 @@ snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o snd-soc-adau1373-objs := adau1373.o snd-soc-adav80x-objs := adav80x.o +snd-soc-adav801-objs := adav801.o +snd-soc-adav803-objs := adav803.o snd-soc-ads117x-objs := ads117x.o snd-soc-ak4104-objs := ak4104.o snd-soc-ak4535-objs := ak4535.o @@ -139,6 +141,8 @@ obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o +obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o +obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o diff --git a/sound/soc/codecs/adav801.c b/sound/soc/codecs/adav801.c new file mode 100644 index 000000000000..790fce33ab10 --- /dev/null +++ b/sound/soc/codecs/adav801.c @@ -0,0 +1,53 @@ +/* + * ADAV801 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "adav80x.h" + +static const struct spi_device_id adav80x_spi_id[] = { + { "adav801", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adav80x_spi_id); + +static int adav80x_spi_probe(struct spi_device *spi) +{ + struct regmap_config config; + + config = adav80x_regmap_config; + config.read_flag_mask = 0x01; + + return adav80x_bus_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); +} + +static int adav80x_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver adav80x_spi_driver = { + .driver = { + .name = "adav801", + .owner = THIS_MODULE, + }, + .probe = adav80x_spi_probe, + .remove = adav80x_spi_remove, + .id_table = adav80x_spi_id, +}; +module_spi_driver(adav80x_spi_driver); + +MODULE_DESCRIPTION("ASoC ADAV801 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_AUTHOR("Yi Li >"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adav803.c b/sound/soc/codecs/adav803.c new file mode 100644 index 000000000000..66d9fce34e62 --- /dev/null +++ b/sound/soc/codecs/adav803.c @@ -0,0 +1,50 @@ +/* + * ADAV803 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "adav80x.h" + +static const struct i2c_device_id adav803_id[] = { + { "adav803", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adav803_id); + +static int adav803_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + return adav80x_bus_probe(&client->dev, + devm_regmap_init_i2c(client, &adav80x_regmap_config)); +} + +static int adav803_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static struct i2c_driver adav803_driver = { + .driver = { + .name = "adav803", + .owner = THIS_MODULE, + }, + .probe = adav803_probe, + .remove = adav803_remove, + .id_table = adav803_id, +}; +module_i2c_driver(adav803_driver); + +MODULE_DESCRIPTION("ASoC ADAV803 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_AUTHOR("Yi Li >"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index a4bd051c5430..09d560962e8d 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -8,17 +8,15 @@ * Licensed under the GPL-2 or later. */ -#include #include #include -#include -#include +#include #include -#include + #include #include -#include #include +#include #include "adav80x.h" @@ -864,10 +862,9 @@ static struct snd_soc_codec_driver adav80x_codec_driver = { .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), }; -static int adav80x_bus_probe(struct device *dev, struct regmap *regmap) +int adav80x_bus_probe(struct device *dev, struct regmap *regmap) { struct adav80x *adav80x; - int ret; if (IS_ERR(regmap)) return PTR_ERR(regmap); @@ -882,9 +879,9 @@ static int adav80x_bus_probe(struct device *dev, struct regmap *regmap) return snd_soc_register_codec(dev, &adav80x_codec_driver, adav80x_dais, ARRAY_SIZE(adav80x_dais)); } +EXPORT_SYMBOL_GPL(adav80x_bus_probe); -#if defined(CONFIG_SPI_MASTER) -static const struct regmap_config adav80x_spi_regmap_config = { +const struct regmap_config adav80x_regmap_config = { .val_bits = 8, .pad_bits = 1, .reg_bits = 7, @@ -896,107 +893,7 @@ static const struct regmap_config adav80x_spi_regmap_config = { .reg_defaults = adav80x_reg_defaults, .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), }; - -static const struct spi_device_id adav80x_spi_id[] = { - { "adav801", 0 }, - { } -}; -MODULE_DEVICE_TABLE(spi, adav80x_spi_id); - -static int adav80x_spi_probe(struct spi_device *spi) -{ - return adav80x_bus_probe(&spi->dev, - devm_regmap_init_spi(spi, &adav80x_spi_regmap_config)); -} - -static int adav80x_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(dev); - return 0; -} - -static struct spi_driver adav80x_spi_driver = { - .driver = { - .name = "adav801", - .owner = THIS_MODULE, - }, - .probe = adav80x_spi_probe, - .remove = adav80x_spi_remove, - .id_table = adav80x_spi_id, -}; -#endif - -#if IS_ENABLED(CONFIG_I2C) -static const struct regmap_config adav80x_i2c_regmap_config = { - .val_bits = 8, - .pad_bits = 1, - .reg_bits = 7, - - .max_register = ADAV80X_PLL_OUTE, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = adav80x_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults), -}; - -static const struct i2c_device_id adav80x_i2c_id[] = { - { "adav803", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adav80x_i2c_id); - -static int adav80x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - return adav80x_bus_probe(&client->dev, - devm_regmap_init_i2c(client, &adav80x_i2c_regmap_config)); -} - -static int adav80x_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(dev); - return 0; -} - -static struct i2c_driver adav80x_i2c_driver = { - .driver = { - .name = "adav803", - .owner = THIS_MODULE, - }, - .probe = adav80x_i2c_probe, - .remove = adav80x_i2c_remove, - .id_table = adav80x_i2c_id, -}; -#endif - -static int __init adav80x_init(void) -{ - int ret = 0; - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&adav80x_i2c_driver); - if (ret) - return ret; -#endif - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&adav80x_spi_driver); -#endif - - return ret; -} -module_init(adav80x_init); - -static void __exit adav80x_exit(void) -{ -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&adav80x_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&adav80x_spi_driver); -#endif -} -module_exit(adav80x_exit); +EXPORT_SYMBOL_GPL(adav80x_regmap_config); MODULE_DESCRIPTION("ASoC ADAV80x driver"); MODULE_AUTHOR("Lars-Peter Clausen "); diff --git a/sound/soc/codecs/adav80x.h b/sound/soc/codecs/adav80x.h index adb0fc76d4e3..8a1d7c09dca5 100644 --- a/sound/soc/codecs/adav80x.h +++ b/sound/soc/codecs/adav80x.h @@ -9,6 +9,13 @@ #ifndef _ADAV80X_H #define _ADAV80X_H +#include + +struct device; + +extern const struct regmap_config adav80x_regmap_config; +int adav80x_bus_probe(struct device *dev, struct regmap *regmap); + enum adav80x_pll_src { ADAV80X_PLL_SRC_XIN, ADAV80X_PLL_SRC_XTAL, -- cgit v1.2.3 From 790aff62291eade029755713fb41c1143d4ddbc7 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Mon, 17 Feb 2014 13:32:06 +0000 Subject: ASoC: Intel: Add Intel SST audio DSP low level shim driver. Add support for Intel Smart Sound Technology (SST) audio DSPs. This driver provides the low level IO, reset, boot and IRQ management for Intel audio DSPs. These files make up the low level part of the SST audio driver stack and will be used by many Intel SST cores like Haswell, Broadwell and Baytrail. SST DSPs expose a memory mapped region (shim) for config and control. The shim layout is mostly shared without much modification across cores and this driver provides a uniform API to access the shim and to enable basic shim functions. It also provides functionality to abstract some shim functions for cores with different shim features. Signed-off-by: Liam Girdwood Acked-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/sst-dsp-priv.h | 305 ++++++++++++++++++++++++++++++++++++++ sound/soc/intel/sst-dsp.c | 324 +++++++++++++++++++++++++++++++++++++++++ sound/soc/intel/sst-dsp.h | 212 +++++++++++++++++++++++++++ 3 files changed, 841 insertions(+) create mode 100644 sound/soc/intel/sst-dsp-priv.h create mode 100644 sound/soc/intel/sst-dsp.c create mode 100644 sound/soc/intel/sst-dsp.h (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-dsp-priv.h b/sound/soc/intel/sst-dsp-priv.h new file mode 100644 index 000000000000..35de547f1744 --- /dev/null +++ b/sound/soc/intel/sst-dsp-priv.h @@ -0,0 +1,305 @@ +/* + * Intel Smart Sound Technology + * + * Copyright (C) 2013, Intel Corporation. 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 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 __SOUND_SOC_SST_DSP_PRIV_H +#define __SOUND_SOC_SST_DSP_PRIV_H + +#include +#include +#include +#include + +struct sst_mem_block; +struct sst_module; +struct sst_fw; + +/* + * DSP Operations exported by platform Audio DSP driver. + */ +struct sst_ops { + /* DSP core boot / reset */ + void (*boot)(struct sst_dsp *); + void (*reset)(struct sst_dsp *); + + /* Shim IO */ + void (*write)(void __iomem *addr, u32 offset, u32 value); + u32 (*read)(void __iomem *addr, u32 offset); + void (*write64)(void __iomem *addr, u32 offset, u64 value); + u64 (*read64)(void __iomem *addr, u32 offset); + + /* DSP I/DRAM IO */ + void (*ram_read)(struct sst_dsp *sst, void *dest, void *src, size_t bytes); + void (*ram_write)(struct sst_dsp *sst, void *dest, void *src, size_t bytes); + + void (*dump)(struct sst_dsp *); + + /* IRQ handlers */ + irqreturn_t (*irq_handler)(int irq, void *context); + + /* SST init and free */ + int (*init)(struct sst_dsp *sst, struct sst_pdata *pdata); + void (*free)(struct sst_dsp *sst); + + /* FW module parser/loader */ + int (*parse_fw)(struct sst_fw *sst_fw); +}; + +/* + * Audio DSP memory offsets and addresses. + */ +struct sst_addr { + u32 lpe_base; + u32 shim_offset; + u32 iram_offset; + void __iomem *lpe; + void __iomem *shim; + void __iomem *pci_cfg; + void __iomem *fw_ext; +}; + +/* + * Audio DSP Mailbox configuration. + */ +struct sst_mailbox { + void __iomem *in_base; + void __iomem *out_base; + size_t in_size; + size_t out_size; +}; + +/* + * Audio DSP Firmware data types. + */ +enum sst_data_type { + SST_DATA_M = 0, /* module block data */ + SST_DATA_P = 1, /* peristant data (text, data) */ + SST_DATA_S = 2, /* scratch data (usually buffers) */ +}; + +/* + * Audio DSP memory block types. + */ +enum sst_mem_type { + SST_MEM_IRAM = 0, + SST_MEM_DRAM = 1, + SST_MEM_ANY = 2, + SST_MEM_CACHE= 3, +}; + +/* + * Audio DSP Generic Firmware File. + * + * SST Firmware files can consist of 1..N modules. This generic structure is + * used to manage each firmware file and it's modules regardless of SST firmware + * type. A SST driver may load multiple FW files. + */ +struct sst_fw { + struct sst_dsp *dsp; + + /* base addresses of FW file data */ + dma_addr_t dmable_fw_paddr; /* physical address of fw data */ + void *dma_buf; /* virtual address of fw data */ + u32 size; /* size of fw data */ + + /* lists */ + struct list_head list; /* DSP list of FW */ + struct list_head module_list; /* FW list of modules */ + + void *private; /* core doesn't touch this */ +}; + +/* + * Audio DSP Generic Module data. + * + * This is used to dsecribe any sections of persistent (text and data) and + * scratch (buffers) of module data in ADSP memory space. + */ +struct sst_module_data { + + enum sst_mem_type type; /* destination memory type */ + enum sst_data_type data_type; /* type of module data */ + + u32 size; /* size in bytes */ + u32 offset; /* offset in FW file */ + u32 data_offset; /* offset in ADSP memory space */ + void *data; /* module data */ +}; + +/* + * Audio DSP Generic Module Template. + * + * Used to define and register a new FW module. This data is extracted from + * FW module header information. + */ +struct sst_module_template { + u32 id; + u32 entry; /* entry point */ + struct sst_module_data s; /* scratch data */ + struct sst_module_data p; /* peristant data */ +}; + +/* + * Audio DSP Generic Module. + * + * Each Firmware file can consist of 1..N modules. A module can span multiple + * ADSP memory blocks. The simplest FW will be a file with 1 module. + */ +struct sst_module { + struct sst_dsp *dsp; + struct sst_fw *sst_fw; /* parent FW we belong too */ + + /* module configuration */ + u32 id; + u32 entry; /* module entry point */ + u32 offset; /* module offset in firmware file */ + u32 size; /* module size */ + struct sst_module_data s; /* scratch data */ + struct sst_module_data p; /* peristant data */ + + /* runtime */ + u32 usage_count; /* can be unloaded if count == 0 */ + void *private; /* core doesn't touch this */ + + /* lists */ + struct list_head block_list; /* Module list of blocks in use */ + struct list_head list; /* DSP list of modules */ + struct list_head list_fw; /* FW list of modules */ +}; + +/* + * SST Memory Block operations. + */ +struct sst_block_ops { + int (*enable)(struct sst_mem_block *block); + int (*disable)(struct sst_mem_block *block); +}; + +/* + * SST Generic Memory Block. + * + * SST ADP memory has multiple IRAM and DRAM blocks. Some ADSP blocks can be + * power gated. + */ +struct sst_mem_block { + struct sst_dsp *dsp; + struct sst_module *module; /* module that uses this block */ + + /* block config */ + u32 offset; /* offset from base */ + u32 size; /* block size */ + u32 index; /* block index 0..N */ + enum sst_mem_type type; /* block memory type IRAM/DRAM */ + struct sst_block_ops *ops; /* block operations, if any */ + + /* block status */ + enum sst_data_type data_type; /* data type held in this block */ + u32 bytes_used; /* bytes in use by modules */ + void *private; /* generic core does not touch this */ + int users; /* number of modules using this block */ + + /* block lists */ + struct list_head module_list; /* Module list of blocks */ + struct list_head list; /* Map list of free/used blocks */ +}; + +/* + * Generic SST Shim Interface. + */ +struct sst_dsp { + + /* runtime */ + struct sst_dsp_device *sst_dev; + spinlock_t spinlock; /* IPC locking */ + struct mutex mutex; /* DSP FW lock */ + struct device *dev; + void *thread_context; + int irq; + u32 id; + + /* list of free and used ADSP memory blocks */ + struct list_head used_block_list; + struct list_head free_block_list; + + /* operations */ + struct sst_ops *ops; + + /* debug FS */ + struct dentry *debugfs_root; + + /* base addresses */ + struct sst_addr addr; + + /* mailbox */ + struct sst_mailbox mailbox; + + /* SST FW files loaded and their modules */ + struct list_head module_list; + struct list_head fw_list; + + /* platform data */ + struct sst_pdata *pdata; + + /* DMA FW loading */ + struct sst_dma *dma; + bool fw_use_dma; +}; + +/* Size optimised DRAM/IRAM memcpy */ +static inline void sst_dsp_write(struct sst_dsp *sst, void *src, + u32 dest_offset, size_t bytes) +{ + sst->ops->ram_write(sst, sst->addr.lpe + dest_offset, src, bytes); +} + +static inline void sst_dsp_read(struct sst_dsp *sst, void *dest, + u32 src_offset, size_t bytes) +{ + sst->ops->ram_read(sst, dest, sst->addr.lpe + src_offset, bytes); +} + +static inline void *sst_dsp_get_thread_context(struct sst_dsp *sst) +{ + return sst->thread_context; +} + +/* Create/Free FW files - can contain multiple modules */ +struct sst_fw *sst_fw_new(struct sst_dsp *dsp, + const struct firmware *fw, void *private); +void sst_fw_free(struct sst_fw *sst_fw); +void sst_fw_free_all(struct sst_dsp *dsp); + +/* Create/Free firmware modules */ +struct sst_module *sst_module_new(struct sst_fw *sst_fw, + struct sst_module_template *template, void *private); +void sst_module_free(struct sst_module *sst_module); +int sst_module_insert(struct sst_module *sst_module); +int sst_module_remove(struct sst_module *sst_module); +int sst_module_insert_fixed_block(struct sst_module *module, + struct sst_module_data *data); +struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id); + +/* allocate/free pesistent/scratch memory regions managed by drv */ +struct sst_module *sst_mem_block_alloc_scratch(struct sst_dsp *dsp); +void sst_mem_block_free_scratch(struct sst_dsp *dsp, + struct sst_module *scratch); + +/* Register the DSPs memory blocks - would be nice to read from ACPI */ +struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset, + u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index, + void *private); +void sst_mem_block_unregister_all(struct sst_dsp *dsp); + +#endif diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c new file mode 100644 index 000000000000..1888de54d079 --- /dev/null +++ b/sound/soc/intel/sst-dsp.c @@ -0,0 +1,324 @@ +/* + * Intel Smart Sound Technology (SST) DSP Core Driver + * + * Copyright (C) 2013, Intel Corporation. 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 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. + * + */ + +#include +#include +#include +#include +#include + +#include "sst-dsp.h" +#include "sst-dsp-priv.h" + +#define CREATE_TRACE_POINTS +#include + +/* Public API */ +void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value) +{ + unsigned long flags; + + spin_lock_irqsave(&sst->spinlock, flags); + sst->ops->write(sst->addr.shim, offset, value); + spin_unlock_irqrestore(&sst->spinlock, flags); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_write); + +u32 sst_dsp_shim_read(struct sst_dsp *sst, u32 offset) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(&sst->spinlock, flags); + val = sst->ops->read(sst->addr.shim, offset); + spin_unlock_irqrestore(&sst->spinlock, flags); + + return val; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_read); + +void sst_dsp_shim_write64(struct sst_dsp *sst, u32 offset, u64 value) +{ + unsigned long flags; + + spin_lock_irqsave(&sst->spinlock, flags); + sst->ops->write64(sst->addr.shim, offset, value); + spin_unlock_irqrestore(&sst->spinlock, flags); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_write64); + +u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset) +{ + unsigned long flags; + u64 val; + + spin_lock_irqsave(&sst->spinlock, flags); + val = sst->ops->read64(sst->addr.shim, offset); + spin_unlock_irqrestore(&sst->spinlock, flags); + + return val; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_read64); + +void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value) +{ + sst->ops->write(sst->addr.shim, offset, value); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_write_unlocked); + +u32 sst_dsp_shim_read_unlocked(struct sst_dsp *sst, u32 offset) +{ + return sst->ops->read(sst->addr.shim, offset); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_read_unlocked); + +void sst_dsp_shim_write64_unlocked(struct sst_dsp *sst, u32 offset, u64 value) +{ + sst->ops->write64(sst->addr.shim, offset, value); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_write64_unlocked); + +u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset) +{ + return sst->ops->read64(sst->addr.shim, offset); +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_read64_unlocked); + +int sst_dsp_shim_update_bits_unlocked(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value) +{ + bool change; + unsigned int old, new; + u32 ret; + + ret = sst_dsp_shim_read_unlocked(sst, offset); + + old = ret; + new = (old & (~mask)) | (value & mask); + + change = (old != new); + if (change) + sst_dsp_shim_write_unlocked(sst, offset, new); + + return change; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_unlocked); + +int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, + u64 mask, u64 value) +{ + bool change; + u64 old, new; + + old = sst_dsp_shim_read64_unlocked(sst, offset); + + new = (old & (~mask)) | (value & mask); + + change = (old != new); + if (change) + sst_dsp_shim_write64_unlocked(sst, offset, new); + + return change; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64_unlocked); + +int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value) +{ + unsigned long flags; + bool change; + + spin_lock_irqsave(&sst->spinlock, flags); + change = sst_dsp_shim_update_bits_unlocked(sst, offset, mask, value); + spin_unlock_irqrestore(&sst->spinlock, flags); + return change; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits); + +int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, + u64 mask, u64 value) +{ + unsigned long flags; + bool change; + + spin_lock_irqsave(&sst->spinlock, flags); + change = sst_dsp_shim_update_bits64_unlocked(sst, offset, mask, value); + spin_unlock_irqrestore(&sst->spinlock, flags); + return change; +} +EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64); + +void sst_dsp_dump(struct sst_dsp *sst) +{ + sst->ops->dump(sst); +} +EXPORT_SYMBOL_GPL(sst_dsp_dump); + +void sst_dsp_reset(struct sst_dsp *sst) +{ + sst->ops->reset(sst); +} +EXPORT_SYMBOL_GPL(sst_dsp_reset); + +int sst_dsp_boot(struct sst_dsp *sst) +{ + sst->ops->boot(sst); + return 0; +} +EXPORT_SYMBOL_GPL(sst_dsp_boot); + +void sst_dsp_ipc_msg_tx(struct sst_dsp *dsp, u32 msg) +{ + sst_dsp_shim_write_unlocked(dsp, SST_IPCX, msg | SST_IPCX_BUSY); + trace_sst_ipc_msg_tx(msg); +} +EXPORT_SYMBOL_GPL(sst_dsp_ipc_msg_tx); + +u32 sst_dsp_ipc_msg_rx(struct sst_dsp *dsp) +{ + u32 msg; + + msg = sst_dsp_shim_read_unlocked(dsp, SST_IPCX); + trace_sst_ipc_msg_rx(msg); + + return msg; +} +EXPORT_SYMBOL_GPL(sst_dsp_ipc_msg_rx); + +int sst_dsp_mailbox_init(struct sst_dsp *sst, u32 inbox_offset, size_t inbox_size, + u32 outbox_offset, size_t outbox_size) +{ + sst->mailbox.in_base = sst->addr.lpe + inbox_offset; + sst->mailbox.out_base = sst->addr.lpe + outbox_offset; + sst->mailbox.in_size = inbox_size; + sst->mailbox.out_size = outbox_size; + return 0; +} +EXPORT_SYMBOL_GPL(sst_dsp_mailbox_init); + +void sst_dsp_outbox_write(struct sst_dsp *sst, void *message, size_t bytes) +{ + u32 i; + + trace_sst_ipc_outbox_write(bytes); + + memcpy_toio(sst->mailbox.out_base, message, bytes); + + for (i = 0; i < bytes; i += 4) + trace_sst_ipc_outbox_wdata(i, *(u32 *)(message + i)); +} +EXPORT_SYMBOL_GPL(sst_dsp_outbox_write); + +void sst_dsp_outbox_read(struct sst_dsp *sst, void *message, size_t bytes) +{ + u32 i; + + trace_sst_ipc_outbox_read(bytes); + + memcpy_fromio(message, sst->mailbox.out_base, bytes); + + for (i = 0; i < bytes; i += 4) + trace_sst_ipc_outbox_rdata(i, *(u32 *)(message + i)); +} +EXPORT_SYMBOL_GPL(sst_dsp_outbox_read); + +void sst_dsp_inbox_write(struct sst_dsp *sst, void *message, size_t bytes) +{ + u32 i; + + trace_sst_ipc_inbox_write(bytes); + + memcpy_toio(sst->mailbox.in_base, message, bytes); + + for (i = 0; i < bytes; i += 4) + trace_sst_ipc_inbox_wdata(i, *(u32 *)(message + i)); +} +EXPORT_SYMBOL_GPL(sst_dsp_inbox_write); + +void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes) +{ + u32 i; + + trace_sst_ipc_inbox_read(bytes); + + memcpy_fromio(message, sst->mailbox.in_base, bytes); + + for (i = 0; i < bytes; i += 4) + trace_sst_ipc_inbox_rdata(i, *(u32 *)(message + i)); +} +EXPORT_SYMBOL_GPL(sst_dsp_inbox_read); + +struct sst_dsp *sst_dsp_new(struct device *dev, + struct sst_dsp_device *sst_dev, struct sst_pdata *pdata) +{ + struct sst_dsp *sst; + int err; + + dev_dbg(dev, "initialising audio DSP id 0x%x\n", pdata->id); + + sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); + if (sst == NULL) + return NULL; + + spin_lock_init(&sst->spinlock); + mutex_init(&sst->mutex); + sst->dev = dev; + sst->thread_context = sst_dev->thread_context; + sst->sst_dev = sst_dev; + sst->id = pdata->id; + sst->irq = pdata->irq; + sst->ops = sst_dev->ops; + sst->pdata = pdata; + INIT_LIST_HEAD(&sst->used_block_list); + INIT_LIST_HEAD(&sst->free_block_list); + INIT_LIST_HEAD(&sst->module_list); + INIT_LIST_HEAD(&sst->fw_list); + + /* Initialise SST Audio DSP */ + if (sst->ops->init) { + err = sst->ops->init(sst, pdata); + if (err < 0) + return NULL; + } + + /* Register the ISR */ + err = request_threaded_irq(sst->irq, sst->ops->irq_handler, + sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); + if (err) + goto irq_err; + + return sst; + +irq_err: + if (sst->ops->free) + sst->ops->free(sst); + + return NULL; +} +EXPORT_SYMBOL_GPL(sst_dsp_new); + +void sst_dsp_free(struct sst_dsp *sst) +{ + free_irq(sst->irq, sst); + if (sst->ops->free) + sst->ops->free(sst); +} +EXPORT_SYMBOL_GPL(sst_dsp_free); + +/* Module information */ +MODULE_AUTHOR("Liam Girdwood"); +MODULE_DESCRIPTION("Intel SST Core"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h new file mode 100644 index 000000000000..0ce5c8d91794 --- /dev/null +++ b/sound/soc/intel/sst-dsp.h @@ -0,0 +1,212 @@ +/* + * Intel Smart Sound Technology (SST) Core + * + * Copyright (C) 2013, Intel Corporation. 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 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 __SOUND_SOC_SST_DSP_H +#define __SOUND_SOC_SST_DSP_H + +#include +#include +#include + +/* SST Device IDs */ +#define SST_DEV_ID_LYNX_POINT 0x33C8 +#define SST_DEV_ID_WILDCAT_POINT 0x3438 + +/* Supported SST DMA Devices */ +#define SST_DMA_TYPE_DW 1 +#define SST_DMA_TYPE_MID 2 + +/* SST Shim register map + * The register naming can differ between products. Some products also + * contain extra functionality. + */ +#define SST_CSR 0x00 +#define SST_PISR 0x08 +#define SST_PIMR 0x10 +#define SST_ISRX 0x18 +#define SST_ISRD 0x20 +#define SST_IMRX 0x28 +#define SST_IMRD 0x30 +#define SST_IPCX 0x38 /* IPC IA -> SST */ +#define SST_IPCD 0x40 /* IPC SST -> IA */ +#define SST_ISRSC 0x48 +#define SST_ISRLPESC 0x50 +#define SST_IMRSC 0x58 +#define SST_IMRLPESC 0x60 +#define SST_IPCSC 0x68 +#define SST_IPCLPESC 0x70 +#define SST_CLKCTL 0x78 +#define SST_CSR2 0x80 +#define SST_LTRC 0xE0 +#define SST_HDMC 0xE8 +#define SST_DBGO 0xF0 + +#define SST_SHIM_SIZE 0x100 +#define SST_PWMCTRL 0x1000 + +/* SST Shim Register bits + * The register bit naming can differ between products. Some products also + * contain extra functionality. + */ + +/* CSR / CS */ +#define SST_CSR_RST (0x1 << 1) +#define SST_CSR_SBCS0 (0x1 << 2) +#define SST_CSR_SBCS1 (0x1 << 3) +#define SST_CSR_DCS(x) (x << 4) +#define SST_CSR_DCS_MASK (0x7 << 4) +#define SST_CSR_STALL (0x1 << 10) +#define SST_CSR_S0IOCS (0x1 << 21) +#define SST_CSR_S1IOCS (0x1 << 23) +#define SST_CSR_LPCS (0x1 << 31) + +/* ISRX / ISC */ +#define SST_ISRX_BUSY (0x1 << 1) +#define SST_ISRX_DONE (0x1 << 0) + +/* ISRD / ISD */ +#define SST_ISRD_BUSY (0x1 << 1) +#define SST_ISRD_DONE (0x1 << 0) + +/* IMRX / IMC */ +#define SST_IMRX_BUSY (0x1 << 1) +#define SST_IMRX_DONE (0x1 << 0) + +/* IPCX / IPCC */ +#define SST_IPCX_DONE (0x1 << 30) +#define SST_IPCX_BUSY (0x1 << 31) + +/* IPCD */ +#define SST_IPCD_DONE (0x1 << 30) +#define SST_IPCD_BUSY (0x1 << 31) + +/* CLKCTL */ +#define SST_CLKCTL_SMOS(x) (x << 24) +#define SST_CLKCTL_MASK (3 << 24) +#define SST_CLKCTL_DCPLCG (1 << 18) +#define SST_CLKCTL_SCOE1 (1 << 17) +#define SST_CLKCTL_SCOE0 (1 << 16) + +/* CSR2 / CS2 */ +#define SST_CSR2_SDFD_SSP0 (1 << 1) +#define SST_CSR2_SDFD_SSP1 (1 << 2) + +/* LTRC */ +#define SST_LTRC_VAL(x) (x << 0) + +/* HDMC */ +#define SST_HDMC_HDDA0(x) (x << 0) +#define SST_HDMC_HDDA1(x) (x << 7) + + +/* SST Vendor Defined Registers and bits */ +#define SST_VDRTCTL0 0xa0 +#define SST_VDRTCTL1 0xa4 +#define SST_VDRTCTL2 0xa8 +#define SST_VDRTCTL3 0xaC + +/* VDRTCTL0 */ +#define SST_VDRTCL0_DSRAMPGE_SHIFT 16 +#define SST_VDRTCL0_DSRAMPGE_MASK (0xffff << SST_VDRTCL0_DSRAMPGE_SHIFT) +#define SST_VDRTCL0_ISRAMPGE_SHIFT 6 +#define SST_VDRTCL0_ISRAMPGE_MASK (0x3ff << SST_VDRTCL0_ISRAMPGE_SHIFT) + +struct sst_dsp; + +/* + * SST Device. + * + * This structure is populated by the SST core driver. + */ +struct sst_dsp_device { + /* Mandatory fields */ + struct sst_ops *ops; + irqreturn_t (*thread)(int irq, void *context); + void *thread_context; +}; + +/* + * SST Platform Data. + */ +struct sst_pdata { + /* ACPI data */ + u32 lpe_base; + u32 lpe_size; + u32 pcicfg_base; + u32 pcicfg_size; + int irq; + + /* Firmware */ + const char *fw_filename; + u32 fw_base; + u32 fw_size; + + /* DMA */ + u32 dma_base; + u32 dma_size; + int dma_engine; + + /* DSP */ + u32 id; + void *dsp; +}; + +/* Initialization */ +struct sst_dsp *sst_dsp_new(struct device *dev, + struct sst_dsp_device *sst_dev, struct sst_pdata *pdata); +void sst_dsp_free(struct sst_dsp *sst); + +/* SHIM Read / Write */ +void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value); +u32 sst_dsp_shim_read(struct sst_dsp *sst, u32 offset); +int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value); +void sst_dsp_shim_write64(struct sst_dsp *sst, u32 offset, u64 value); +u64 sst_dsp_shim_read64(struct sst_dsp *sst, u32 offset); +int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset, + u64 mask, u64 value); + +/* SHIM Read / Write Unlocked for callers already holding sst lock */ +void sst_dsp_shim_write_unlocked(struct sst_dsp *sst, u32 offset, u32 value); +u32 sst_dsp_shim_read_unlocked(struct sst_dsp *sst, u32 offset); +int sst_dsp_shim_update_bits_unlocked(struct sst_dsp *sst, u32 offset, + u32 mask, u32 value); +void sst_dsp_shim_write64_unlocked(struct sst_dsp *sst, u32 offset, u64 value); +u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset); +int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, + u64 mask, u64 value); + +/* DSP reset & boot */ +void sst_dsp_reset(struct sst_dsp *sst); +int sst_dsp_boot(struct sst_dsp *sst); + +/* Msg IO */ +void sst_dsp_ipc_msg_tx(struct sst_dsp *dsp, u32 msg); +u32 sst_dsp_ipc_msg_rx(struct sst_dsp *dsp); + +/* Mailbox management */ +int sst_dsp_mailbox_init(struct sst_dsp *dsp, u32 inbox_offset, + size_t inbox_size, u32 outbox_offset, size_t outbox_size); +void sst_dsp_inbox_write(struct sst_dsp *dsp, void *message, size_t bytes); +void sst_dsp_inbox_read(struct sst_dsp *dsp, void *message, size_t bytes); +void sst_dsp_outbox_write(struct sst_dsp *dsp, void *message, size_t bytes); +void sst_dsp_outbox_read(struct sst_dsp *dsp, void *message, size_t bytes); +void sst_dsp_mailbox_dump(struct sst_dsp *dsp, size_t bytes); + +/* Debug */ +void sst_dsp_dump(struct sst_dsp *sst); + +#endif -- cgit v1.2.3 From c2f8783fa2d053a61059f6b784c917129fb3064b Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 17 Feb 2014 13:32:07 +0000 Subject: ASoC: Intel: Add common SST driver loader on ACPI systems Most of the SST devices will be exposed as ACPI devices. It makes sense to avoid duplication of the driver enumeration logic and concentrate the functionality into a single ACPI SST enumeration file. Idea of this loader is to parse data we get from ACPI and to be able to load needed other SST drivers and ASoC machine driver runtime based on single ACPI ID what BIOS gives to us. Signed-off-by: Jarkko Nikula Signed-off-by: Liam Girdwood Acked-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/sst-acpi.c | 212 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 sound/soc/intel/sst-acpi.c (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c new file mode 100644 index 000000000000..aba73ca8a923 --- /dev/null +++ b/sound/soc/intel/sst-acpi.c @@ -0,0 +1,212 @@ +/* + * Intel SST loader on ACPI systems + * + * Copyright (C) 2013, Intel Corporation. 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 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. + * + */ + +#include +#include +#include +#include + +#include "sst-dsp.h" + +#define SST_LPT_DSP_DMA_ADDR_OFFSET 0x0F0000 +#define SST_WPT_DSP_DMA_ADDR_OFFSET 0x0FE000 +#define SST_LPT_DSP_DMA_SIZE (1024 - 1) + +/* Descriptor for setting up SST platform data */ +struct sst_acpi_desc { + const char *drv_name; + /* Platform resource indexes. Must set to -1 if not used */ + int resindex_lpe_base; + int resindex_pcicfg_base; + int resindex_fw_base; + int irqindex_host_ipc; + int resindex_dma_base; + /* Unique number identifying the SST core on platform */ + int sst_id; + /* firmware file name */ + const char *fw_filename; + /* DMA only valid when resindex_dma_base != -1*/ + int dma_engine; + int dma_size; +}; + +/* Descriptor for SST ASoC machine driver */ +struct sst_acpi_mach { + const char *drv_name; + struct sst_acpi_desc *res_desc; +}; + +struct sst_acpi_priv { + struct platform_device *pdev_mach; + struct platform_device *pdev_pcm; + struct sst_pdata sst_pdata; + struct sst_acpi_desc *desc; +}; + +static int sst_acpi_probe(struct platform_device *pdev) +{ + const struct acpi_device_id *id; + struct device *dev = &pdev->dev; + struct sst_acpi_priv *sst_acpi; + struct sst_pdata *sst_pdata; + struct sst_acpi_mach *mach; + struct sst_acpi_desc *desc; + struct resource *mmio; + int ret = 0; + + sst_acpi = devm_kzalloc(dev, sizeof(*sst_acpi), GFP_KERNEL); + if (sst_acpi == NULL) + return -ENOMEM; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return -ENODEV; + + mach = (struct sst_acpi_mach *)id->driver_data; + desc = mach->res_desc; + sst_pdata = &sst_acpi->sst_pdata; + sst_pdata->id = desc->sst_id; + sst_pdata->fw_filename = desc->fw_filename; + sst_acpi->desc = desc; + + if (desc->resindex_dma_base >= 0) { + sst_pdata->dma_engine = desc->dma_engine; + sst_pdata->dma_base = desc->resindex_dma_base; + sst_pdata->dma_size = desc->dma_size; + } + + if (desc->irqindex_host_ipc >= 0) + sst_pdata->irq = platform_get_irq(pdev, desc->irqindex_host_ipc); + + if (desc->resindex_lpe_base >= 0) { + mmio = platform_get_resource(pdev, IORESOURCE_MEM, + desc->resindex_lpe_base); + if (mmio) { + sst_pdata->lpe_base = mmio->start; + sst_pdata->lpe_size = resource_size(mmio); + } + } + + if (desc->resindex_pcicfg_base >= 0) { + mmio = platform_get_resource(pdev, IORESOURCE_MEM, + desc->resindex_pcicfg_base); + if (mmio) { + sst_pdata->pcicfg_base = mmio->start; + sst_pdata->pcicfg_size = resource_size(mmio); + } + } + + if (desc->resindex_fw_base >= 0) { + mmio = platform_get_resource(pdev, IORESOURCE_MEM, + desc->resindex_fw_base); + if (mmio) { + sst_pdata->fw_base = mmio->start; + sst_pdata->fw_size = resource_size(mmio); + } + } + + /* register PCM and DAI driver */ + sst_acpi->pdev_pcm = + platform_device_register_data(dev, desc->drv_name, -1, + sst_pdata, sizeof(*sst_pdata)); + if (IS_ERR(sst_acpi->pdev_pcm)) + return PTR_ERR(sst_acpi->pdev_pcm); + + /* register machine driver */ + platform_set_drvdata(pdev, sst_acpi); + + sst_acpi->pdev_mach = + platform_device_register_data(dev, mach->drv_name, -1, + sst_pdata, sizeof(*sst_pdata)); + if (IS_ERR(sst_acpi->pdev_mach)) { + ret = PTR_ERR(sst_acpi->pdev_mach); + goto sst_err; + } + + return ret; + +sst_err: + platform_device_unregister(sst_acpi->pdev_pcm); + return ret; +} + +static int sst_acpi_remove(struct platform_device *pdev) +{ + struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev); + + platform_device_unregister(sst_acpi->pdev_mach); + platform_device_unregister(sst_acpi->pdev_pcm); + + return 0; +} + +static struct sst_acpi_desc sst_acpi_haswell_desc = { + .drv_name = "haswell-pcm-audio", + .resindex_lpe_base = 0, + .resindex_pcicfg_base = 1, + .resindex_fw_base = -1, + .irqindex_host_ipc = 0, + .sst_id = SST_DEV_ID_LYNX_POINT, + .fw_filename = "intel/IntcSST1.bin", + .dma_engine = SST_DMA_TYPE_DW, + .resindex_dma_base = SST_LPT_DSP_DMA_ADDR_OFFSET, + .dma_size = SST_LPT_DSP_DMA_SIZE, +}; + +static struct sst_acpi_desc sst_acpi_broadwell_desc = { + .drv_name = "haswell-pcm-audio", + .resindex_lpe_base = 0, + .resindex_pcicfg_base = 1, + .resindex_fw_base = -1, + .irqindex_host_ipc = 0, + .sst_id = SST_DEV_ID_WILDCAT_POINT, + .fw_filename = "intel/IntcSST2.bin", + .dma_engine = SST_DMA_TYPE_DW, + .resindex_dma_base = SST_WPT_DSP_DMA_ADDR_OFFSET, + .dma_size = SST_LPT_DSP_DMA_SIZE, +}; + +static struct sst_acpi_mach haswell_mach = { + .drv_name = "haswell-audio", + .res_desc = &sst_acpi_haswell_desc, +}; + +static struct sst_acpi_mach broadwell_mach = { + .drv_name = "broadwell-audio", + .res_desc = &sst_acpi_broadwell_desc, +}; + +static struct acpi_device_id sst_acpi_match[] = { + { "INT33C8", (unsigned long)&haswell_mach }, + { "INT3438", (unsigned long)&broadwell_mach }, + { } +}; +MODULE_DEVICE_TABLE(acpi, sst_acpi_match); + +static struct platform_driver sst_acpi_driver = { + .probe = sst_acpi_probe, + .remove = sst_acpi_remove, + .driver = { + .name = "sst-acpi", + .owner = THIS_MODULE, + .acpi_match_table = ACPI_PTR(sst_acpi_match), + }, +}; +module_platform_driver(sst_acpi_driver); + +MODULE_AUTHOR("Jarkko Nikula "); +MODULE_DESCRIPTION("Intel SST loader on ACPI systems"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 30020472c354fbe4352b4b4d59bbc9a30aacf5c3 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Mon, 17 Feb 2014 13:32:08 +0000 Subject: ASoC: Intel: Add Intel SST audio DSP Firmware loader. Provide services for Intel SST drivers to load SST modular firmware. SST Firmware can be made up of several modules. These modules can exist within any of the compatible SST memory blocks. Provide a generic memory block and firmware module manager that can be used with any SST firmware and core. Signed-off-by: Liam Girdwood Acked-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/sst-firmware.c | 586 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 586 insertions(+) create mode 100644 sound/soc/intel/sst-firmware.c (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c new file mode 100644 index 000000000000..b6f9b5ecb66a --- /dev/null +++ b/sound/soc/intel/sst-firmware.c @@ -0,0 +1,586 @@ +/* + * Intel SST Firmware Loader + * + * Copyright (C) 2013, Intel Corporation. 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 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "sst-dsp.h" +#include "sst-dsp-priv.h" + +static void sst_memcpy32(void *dest, void *src, u32 bytes) +{ + u32 i; + + /* copy one 32 bit word at a time as 64 bit access is not supported */ + for (i = 0; i < bytes; i += 4) + memcpy_toio(dest + i, src + i, 4); +} + +/* create new generic firmware object */ +struct sst_fw *sst_fw_new(struct sst_dsp *dsp, + const struct firmware *fw, void *private) +{ + struct sst_fw *sst_fw; + int err; + + if (!dsp->ops->parse_fw) + return NULL; + + sst_fw = kzalloc(sizeof(*sst_fw), GFP_KERNEL); + if (sst_fw == NULL) + return NULL; + + sst_fw->dsp = dsp; + sst_fw->private = private; + sst_fw->size = fw->size; + + err = dma_coerce_mask_and_coherent(dsp->dev, DMA_BIT_MASK(32)); + if (err < 0) { + kfree(sst_fw); + return NULL; + } + + /* allocate DMA buffer to store FW data */ + sst_fw->dma_buf = dma_alloc_coherent(dsp->dev, sst_fw->size, + &sst_fw->dmable_fw_paddr, GFP_DMA); + if (!sst_fw->dma_buf) { + dev_err(dsp->dev, "error: DMA alloc failed\n"); + kfree(sst_fw); + return NULL; + } + + /* copy FW data to DMA-able memory */ + memcpy((void *)sst_fw->dma_buf, (void *)fw->data, fw->size); + + /* call core specific FW paser to load FW data into DSP */ + err = dsp->ops->parse_fw(sst_fw); + if (err < 0) { + dev_err(dsp->dev, "error: parse fw failed %d\n", err); + goto parse_err; + } + + mutex_lock(&dsp->mutex); + list_add(&sst_fw->list, &dsp->fw_list); + mutex_unlock(&dsp->mutex); + + return sst_fw; + +parse_err: + dma_free_coherent(dsp->dev, sst_fw->size, + sst_fw->dma_buf, + sst_fw->dmable_fw_paddr); + kfree(sst_fw); + return NULL; +} +EXPORT_SYMBOL_GPL(sst_fw_new); + +/* free single firmware object */ +void sst_fw_free(struct sst_fw *sst_fw) +{ + struct sst_dsp *dsp = sst_fw->dsp; + + mutex_lock(&dsp->mutex); + list_del(&sst_fw->list); + mutex_unlock(&dsp->mutex); + + dma_free_coherent(dsp->dev, sst_fw->size, sst_fw->dma_buf, + sst_fw->dmable_fw_paddr); + kfree(sst_fw); +} +EXPORT_SYMBOL_GPL(sst_fw_free); + +/* free all firmware objects */ +void sst_fw_free_all(struct sst_dsp *dsp) +{ + struct sst_fw *sst_fw, *t; + + mutex_lock(&dsp->mutex); + list_for_each_entry_safe(sst_fw, t, &dsp->fw_list, list) { + + list_del(&sst_fw->list); + dma_free_coherent(dsp->dev, sst_fw->size, sst_fw->dma_buf, + sst_fw->dmable_fw_paddr); + kfree(sst_fw); + } + mutex_unlock(&dsp->mutex); +} +EXPORT_SYMBOL_GPL(sst_fw_free_all); + +/* create a new SST generic module from FW template */ +struct sst_module *sst_module_new(struct sst_fw *sst_fw, + struct sst_module_template *template, void *private) +{ + struct sst_dsp *dsp = sst_fw->dsp; + struct sst_module *sst_module; + + sst_module = kzalloc(sizeof(*sst_module), GFP_KERNEL); + if (sst_module == NULL) + return NULL; + + sst_module->id = template->id; + sst_module->dsp = dsp; + sst_module->sst_fw = sst_fw; + + memcpy(&sst_module->s, &template->s, sizeof(struct sst_module_data)); + memcpy(&sst_module->p, &template->p, sizeof(struct sst_module_data)); + + INIT_LIST_HEAD(&sst_module->block_list); + + mutex_lock(&dsp->mutex); + list_add(&sst_module->list, &dsp->module_list); + mutex_unlock(&dsp->mutex); + + return sst_module; +} +EXPORT_SYMBOL_GPL(sst_module_new); + +/* free firmware module and remove from available list */ +void sst_module_free(struct sst_module *sst_module) +{ + struct sst_dsp *dsp = sst_module->dsp; + + mutex_lock(&dsp->mutex); + list_del(&sst_module->list); + mutex_unlock(&dsp->mutex); + + kfree(sst_module); +} +EXPORT_SYMBOL_GPL(sst_module_free); + +static struct sst_mem_block *find_block(struct sst_dsp *dsp, int type, + u32 offset) +{ + struct sst_mem_block *block; + + list_for_each_entry(block, &dsp->free_block_list, list) { + if (block->type == type && block->offset == offset) + return block; + } + + return NULL; +} + +static int block_alloc_contiguous(struct sst_module *module, + struct sst_module_data *data, u32 offset, int size) +{ + struct list_head tmp = LIST_HEAD_INIT(tmp); + struct sst_dsp *dsp = module->dsp; + struct sst_mem_block *block; + + while (size > 0) { + block = find_block(dsp, data->type, offset); + if (!block) { + list_splice(&tmp, &dsp->free_block_list); + return -ENOMEM; + } + + list_move_tail(&block->list, &tmp); + offset += block->size; + size -= block->size; + } + + list_splice(&tmp, &dsp->used_block_list); + return 0; +} + +/* allocate free DSP blocks for module data - callers hold locks */ +static int block_alloc(struct sst_module *module, + struct sst_module_data *data) +{ + struct sst_dsp *dsp = module->dsp; + struct sst_mem_block *block, *tmp; + int ret = 0; + + if (data->size == 0) + return 0; + + /* find first free whole blocks that can hold module */ + list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { + + /* ignore blocks with wrong type */ + if (block->type != data->type) + continue; + + if (data->size > block->size) + continue; + + data->offset = block->offset; + block->data_type = data->data_type; + block->bytes_used = data->size % block->size; + list_add(&block->module_list, &module->block_list); + list_move(&block->list, &dsp->used_block_list); + dev_dbg(dsp->dev, " *module %d added block %d:%d\n", + module->id, block->type, block->index); + return 0; + } + + /* then find free multiple blocks that can hold module */ + list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { + + /* ignore blocks with wrong type */ + if (block->type != data->type) + continue; + + /* do we span > 1 blocks */ + if (data->size > block->size) { + ret = block_alloc_contiguous(module, data, + block->offset + block->size, + data->size - block->size); + if (ret == 0) + return ret; + } + } + + /* not enough free block space */ + return -ENOMEM; +} + +/* remove module from memory - callers hold locks */ +static void block_module_remove(struct sst_module *module) +{ + struct sst_mem_block *block, *tmp; + struct sst_dsp *dsp = module->dsp; + int err; + + /* disable each block */ + list_for_each_entry(block, &module->block_list, module_list) { + + if (block->ops && block->ops->disable) { + err = block->ops->disable(block); + if (err < 0) + dev_err(dsp->dev, + "error: cant disable block %d:%d\n", + block->type, block->index); + } + } + + /* mark each block as free */ + list_for_each_entry_safe(block, tmp, &module->block_list, module_list) { + list_del(&block->module_list); + list_move(&block->list, &dsp->free_block_list); + } +} + +/* prepare the memory block to receive data from host - callers hold locks */ +static int block_module_prepare(struct sst_module *module) +{ + struct sst_mem_block *block; + int ret = 0; + + /* enable each block so that's it'e ready for module P/S data */ + list_for_each_entry(block, &module->block_list, module_list) { + + if (block->ops && block->ops->enable) + ret = block->ops->enable(block); + if (ret < 0) { + dev_err(module->dsp->dev, + "error: cant disable block %d:%d\n", + block->type, block->index); + goto err; + } + } + return ret; + +err: + list_for_each_entry(block, &module->block_list, module_list) { + if (block->ops && block->ops->disable) + block->ops->disable(block); + } + return ret; +} + +/* allocate memory blocks for static module addresses - callers hold locks */ +static int block_alloc_fixed(struct sst_module *module, + struct sst_module_data *data) +{ + struct sst_dsp *dsp = module->dsp; + struct sst_mem_block *block, *tmp; + u32 end = data->offset + data->size, block_end; + int err; + + /* only IRAM/DRAM blocks are managed */ + if (data->type != SST_MEM_IRAM && data->type != SST_MEM_DRAM) + return 0; + + /* are blocks already attached to this module */ + list_for_each_entry_safe(block, tmp, &module->block_list, module_list) { + + /* force compacting mem blocks of the same data_type */ + if (block->data_type != data->data_type) + continue; + + block_end = block->offset + block->size; + + /* find block that holds section */ + if (data->offset >= block->offset && end < block_end) + return 0; + + /* does block span more than 1 section */ + if (data->offset >= block->offset && data->offset < block_end) { + + err = block_alloc_contiguous(module, data, + block->offset + block->size, + data->size - block->size + data->offset - block->offset); + if (err < 0) + return -ENOMEM; + + /* module already owns blocks */ + return 0; + } + } + + /* find first free blocks that can hold section in free list */ + list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { + block_end = block->offset + block->size; + + /* find block that holds section */ + if (data->offset >= block->offset && end < block_end) { + + /* add block */ + block->data_type = data->data_type; + list_move(&block->list, &dsp->used_block_list); + list_add(&block->module_list, &module->block_list); + return 0; + } + + /* does block span more than 1 section */ + if (data->offset >= block->offset && data->offset < block_end) { + + err = block_alloc_contiguous(module, data, + block->offset + block->size, + data->size - block->size); + if (err < 0) + return -ENOMEM; + + /* add block */ + block->data_type = data->data_type; + list_move(&block->list, &dsp->used_block_list); + list_add(&block->module_list, &module->block_list); + return 0; + } + + } + + return -ENOMEM; +} + +/* Load fixed module data into DSP memory blocks */ +int sst_module_insert_fixed_block(struct sst_module *module, + struct sst_module_data *data) +{ + struct sst_dsp *dsp = module->dsp; + int ret; + + mutex_lock(&dsp->mutex); + + /* alloc blocks that includes this section */ + ret = block_alloc_fixed(module, data); + if (ret < 0) { + dev_err(dsp->dev, + "error: no free blocks for section at offset 0x%x size 0x%x\n", + data->offset, data->size); + mutex_unlock(&dsp->mutex); + return -ENOMEM; + } + + /* prepare DSP blocks for module copy */ + ret = block_module_prepare(module); + if (ret < 0) { + dev_err(dsp->dev, "error: fw module prepare failed\n"); + goto err; + } + + /* copy partial module data to blocks */ + sst_memcpy32(dsp->addr.lpe + data->offset, data->data, data->size); + + mutex_unlock(&dsp->mutex); + return ret; + +err: + block_module_remove(module); + mutex_unlock(&dsp->mutex); + return ret; +} +EXPORT_SYMBOL_GPL(sst_module_insert_fixed_block); + +/* Unload entire module from DSP memory */ +int sst_block_module_remove(struct sst_module *module) +{ + struct sst_dsp *dsp = module->dsp; + + mutex_lock(&dsp->mutex); + block_module_remove(module); + mutex_unlock(&dsp->mutex); + return 0; +} +EXPORT_SYMBOL_GPL(sst_block_module_remove); + +/* register a DSP memory block for use with FW based modules */ +struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset, + u32 size, enum sst_mem_type type, struct sst_block_ops *ops, u32 index, + void *private) +{ + struct sst_mem_block *block; + + block = kzalloc(sizeof(*block), GFP_KERNEL); + if (block == NULL) + return NULL; + + block->offset = offset; + block->size = size; + block->index = index; + block->type = type; + block->dsp = dsp; + block->private = private; + block->ops = ops; + + mutex_lock(&dsp->mutex); + list_add(&block->list, &dsp->free_block_list); + mutex_unlock(&dsp->mutex); + + return block; +} +EXPORT_SYMBOL_GPL(sst_mem_block_register); + +/* unregister all DSP memory blocks */ +void sst_mem_block_unregister_all(struct sst_dsp *dsp) +{ + struct sst_mem_block *block, *tmp; + + mutex_lock(&dsp->mutex); + + /* unregister used blocks */ + list_for_each_entry_safe(block, tmp, &dsp->used_block_list, list) { + list_del(&block->list); + kfree(block); + } + + /* unregister free blocks */ + list_for_each_entry_safe(block, tmp, &dsp->free_block_list, list) { + list_del(&block->list); + kfree(block); + } + + mutex_unlock(&dsp->mutex); +} +EXPORT_SYMBOL_GPL(sst_mem_block_unregister_all); + +/* allocate scratch buffer blocks */ +struct sst_module *sst_mem_block_alloc_scratch(struct sst_dsp *dsp) +{ + struct sst_module *sst_module, *scratch; + struct sst_mem_block *block, *tmp; + u32 block_size; + int ret = 0; + + scratch = kzalloc(sizeof(struct sst_module), GFP_KERNEL); + if (scratch == NULL) + return NULL; + + mutex_lock(&dsp->mutex); + + /* calculate required scratch size */ + list_for_each_entry(sst_module, &dsp->module_list, list) { + if (scratch->s.size > sst_module->s.size) + scratch->s.size = scratch->s.size; + else + scratch->s.size = sst_module->s.size; + } + + dev_dbg(dsp->dev, "scratch buffer required is %d bytes\n", + scratch->s.size); + + /* init scratch module */ + scratch->dsp = dsp; + scratch->s.type = SST_MEM_DRAM; + scratch->s.data_type = SST_DATA_S; + INIT_LIST_HEAD(&scratch->block_list); + + /* check free blocks before looking at used blocks for space */ + if (!list_empty(&dsp->free_block_list)) + block = list_first_entry(&dsp->free_block_list, + struct sst_mem_block, list); + else + block = list_first_entry(&dsp->used_block_list, + struct sst_mem_block, list); + block_size = block->size; + + /* allocate blocks for module scratch buffers */ + dev_dbg(dsp->dev, "allocating scratch blocks\n"); + ret = block_alloc(scratch, &scratch->s); + if (ret < 0) { + dev_err(dsp->dev, "error: can't alloc scratch blocks\n"); + goto err; + } + + /* assign the same offset of scratch to each module */ + list_for_each_entry(sst_module, &dsp->module_list, list) + sst_module->s.offset = scratch->s.offset; + + mutex_unlock(&dsp->mutex); + return scratch; + +err: + list_for_each_entry_safe(block, tmp, &scratch->block_list, module_list) + list_del(&block->module_list); + mutex_unlock(&dsp->mutex); + return NULL; +} +EXPORT_SYMBOL_GPL(sst_mem_block_alloc_scratch); + +/* free all scratch blocks */ +void sst_mem_block_free_scratch(struct sst_dsp *dsp, + struct sst_module *scratch) +{ + struct sst_mem_block *block, *tmp; + + mutex_lock(&dsp->mutex); + + list_for_each_entry_safe(block, tmp, &scratch->block_list, module_list) + list_del(&block->module_list); + + mutex_unlock(&dsp->mutex); +} +EXPORT_SYMBOL_GPL(sst_mem_block_free_scratch); + +/* get a module from it's unique ID */ +struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id) +{ + struct sst_module *module; + + mutex_lock(&dsp->mutex); + + list_for_each_entry(module, &dsp->module_list, list) { + if (module->id == id) { + mutex_unlock(&dsp->mutex); + return module; + } + } + + mutex_unlock(&dsp->mutex); + return NULL; +} +EXPORT_SYMBOL_GPL(sst_module_get_from_id); -- cgit v1.2.3 From ddfa40b1586f8c7c6bb8bb9dd398cf656c98e6ee Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Mon, 17 Feb 2014 13:32:10 +0000 Subject: ASoC: Intel: Add build support for Intel SST DSP core. This adds kernel build support for Intel SST core audio. Signed-off-by: Liam Girdwood Acked-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 12 ++++++++++++ sound/soc/intel/Makefile | 7 +++++++ 2 files changed, 19 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 4d9d0a546cb1..b0a07e4cc919 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -11,3 +11,15 @@ config SND_MFLD_MACHINE config SND_SST_MFLD_PLATFORM tristate + +config SND_SOC_INTEL_SST + tristate "ASoC support for Intel(R) Smart Sound Technology" + select SND_SOC_INTEL_SST_ACPI if ACPI + help + This adds support for Intel(R) Smart Sound Technology (SST). + Say Y if you have such a device + If unsure select "N". + +config SND_SOC_INTEL_SST_ACPI + tristate + diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index eb899fc90d92..cf47100661e9 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -1,5 +1,12 @@ +# Core support +snd-soc-sst-dsp-objs := sst-dsp.o sst-firmware.o +snd-soc-sst-acpi-objs := sst-acpi.o + snd-soc-sst-mfld-platform-objs := sst-mfld-platform.o snd-soc-mfld-machine-objs := mfld_machine.o obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += snd-soc-sst-mfld-platform.o obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o + +obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o +obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o -- cgit v1.2.3 From 423f0c4a3d32cc83dff204324f59aecb4516f3cf Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 18 Feb 2014 14:32:48 +0530 Subject: ASoC: cs42l51: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ‘cs42l51’ is not used. Remove it. Signed-off-by: Sachin Kamat Acked-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l51.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index e53c8714591f..3eab46020a30 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -487,7 +487,6 @@ static struct snd_soc_dai_driver cs42l51_dai = { static int cs42l51_probe(struct snd_soc_codec *codec) { - struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); int ret, reg; ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); -- cgit v1.2.3 From 2280e90efae92060f6fa717fb1afa9861bd2b520 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 18 Feb 2014 10:41:50 +0000 Subject: ASoC: Intel: Add GFP_KERNEL flag to firmware DMA buffer. Add GFP_KERNEL when allocating firmware DMA buffer. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index b6f9b5ecb66a..31cd15430e9a 100644 --- a/sound/soc/intel/sst-firmware.c +++ b/sound/soc/intel/sst-firmware.c @@ -65,7 +65,7 @@ struct sst_fw *sst_fw_new(struct sst_dsp *dsp, /* allocate DMA buffer to store FW data */ sst_fw->dma_buf = dma_alloc_coherent(dsp->dev, sst_fw->size, - &sst_fw->dmable_fw_paddr, GFP_DMA); + &sst_fw->dmable_fw_paddr, GFP_DMA | GFP_KERNEL); if (!sst_fw->dma_buf) { dev_err(dsp->dev, "error: DMA alloc failed\n"); kfree(sst_fw); -- cgit v1.2.3 From b47bd099fbb3412e34e8915c7a06bc3dbe73bc01 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 18 Feb 2014 11:43:16 +0000 Subject: ASoC: Intel: Rename SST trace event header to be less generic. The Intel audio DSP SST trace event header has been renamed from sst.h to intel-sst.h in order to avoid any confusion with any future Samoa Standard Time drivers ;) Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- include/trace/events/intel-sst.h | 148 +++++++++++++++++++++++++++++++++++++++ include/trace/events/sst.h | 148 --------------------------------------- sound/soc/intel/sst-dsp.c | 2 +- 3 files changed, 149 insertions(+), 149 deletions(-) create mode 100644 include/trace/events/intel-sst.h delete mode 100644 include/trace/events/sst.h (limited to 'sound/soc') diff --git a/include/trace/events/intel-sst.h b/include/trace/events/intel-sst.h new file mode 100644 index 000000000000..76c72d3f1902 --- /dev/null +++ b/include/trace/events/intel-sst.h @@ -0,0 +1,148 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM intel-sst + +#if !defined(_TRACE_INTEL_SST_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_INTEL_SST_H + +#include +#include +#include + +DECLARE_EVENT_CLASS(sst_ipc_msg, + + TP_PROTO(unsigned int val), + + TP_ARGS(val), + + TP_STRUCT__entry( + __field( unsigned int, val ) + ), + + TP_fast_assign( + __entry->val = val; + ), + + TP_printk("0x%8.8x", (unsigned int)__entry->val) +); + +DEFINE_EVENT(sst_ipc_msg, sst_ipc_msg_tx, + + TP_PROTO(unsigned int val), + + TP_ARGS(val) + +); + +DEFINE_EVENT(sst_ipc_msg, sst_ipc_msg_rx, + + TP_PROTO(unsigned int val), + + TP_ARGS(val) + +); + +DECLARE_EVENT_CLASS(sst_ipc_mailbox, + + TP_PROTO(unsigned int offset, unsigned int val), + + TP_ARGS(offset, val), + + TP_STRUCT__entry( + __field( unsigned int, offset ) + __field( unsigned int, val ) + ), + + TP_fast_assign( + __entry->offset = offset; + __entry->val = val; + ), + + TP_printk(" 0x%4.4x = 0x%8.8x", + (unsigned int)__entry->offset, (unsigned int)__entry->val) +); + +DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_inbox_rdata, + + TP_PROTO(unsigned int offset, unsigned int val), + + TP_ARGS(offset, val) + +); + +DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_inbox_wdata, + + TP_PROTO(unsigned int offset, unsigned int val), + + TP_ARGS(offset, val) + +); + +DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_outbox_rdata, + + TP_PROTO(unsigned int offset, unsigned int val), + + TP_ARGS(offset, val) + +); + +DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_outbox_wdata, + + TP_PROTO(unsigned int offset, unsigned int val), + + TP_ARGS(offset, val) + +); + +DECLARE_EVENT_CLASS(sst_ipc_mailbox_info, + + TP_PROTO(unsigned int size), + + TP_ARGS(size), + + TP_STRUCT__entry( + __field( unsigned int, size ) + ), + + TP_fast_assign( + __entry->size = size; + ), + + TP_printk("Mailbox bytes 0x%8.8x", (unsigned int)__entry->size) +); + +DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_inbox_read, + + TP_PROTO(unsigned int size), + + TP_ARGS(size) + +); + +DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_inbox_write, + + TP_PROTO(unsigned int size), + + TP_ARGS(size) + +); + +DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_outbox_read, + + TP_PROTO(unsigned int size), + + TP_ARGS(size) + +); + +DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_outbox_write, + + TP_PROTO(unsigned int size), + + TP_ARGS(size) + +); + +#endif /* _TRACE_SST_H */ + +/* This part must be outside protection */ +#include diff --git a/include/trace/events/sst.h b/include/trace/events/sst.h deleted file mode 100644 index 1a0d6b3b1ae1..000000000000 --- a/include/trace/events/sst.h +++ /dev/null @@ -1,148 +0,0 @@ -#undef TRACE_SYSTEM -#define TRACE_SYSTEM sst - -#if !defined(_TRACE_SST_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_SST_H - -#include -#include -#include - -DECLARE_EVENT_CLASS(sst_ipc_msg, - - TP_PROTO(unsigned int val), - - TP_ARGS(val), - - TP_STRUCT__entry( - __field( unsigned int, val ) - ), - - TP_fast_assign( - __entry->val = val; - ), - - TP_printk("0x%8.8x", (unsigned int)__entry->val) -); - -DEFINE_EVENT(sst_ipc_msg, sst_ipc_msg_tx, - - TP_PROTO(unsigned int val), - - TP_ARGS(val) - -); - -DEFINE_EVENT(sst_ipc_msg, sst_ipc_msg_rx, - - TP_PROTO(unsigned int val), - - TP_ARGS(val) - -); - -DECLARE_EVENT_CLASS(sst_ipc_mailbox, - - TP_PROTO(unsigned int offset, unsigned int val), - - TP_ARGS(offset, val), - - TP_STRUCT__entry( - __field( unsigned int, offset ) - __field( unsigned int, val ) - ), - - TP_fast_assign( - __entry->offset = offset; - __entry->val = val; - ), - - TP_printk(" 0x%4.4x = 0x%8.8x", - (unsigned int)__entry->offset, (unsigned int)__entry->val) -); - -DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_inbox_rdata, - - TP_PROTO(unsigned int offset, unsigned int val), - - TP_ARGS(offset, val) - -); - -DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_inbox_wdata, - - TP_PROTO(unsigned int offset, unsigned int val), - - TP_ARGS(offset, val) - -); - -DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_outbox_rdata, - - TP_PROTO(unsigned int offset, unsigned int val), - - TP_ARGS(offset, val) - -); - -DEFINE_EVENT(sst_ipc_mailbox, sst_ipc_outbox_wdata, - - TP_PROTO(unsigned int offset, unsigned int val), - - TP_ARGS(offset, val) - -); - -DECLARE_EVENT_CLASS(sst_ipc_mailbox_info, - - TP_PROTO(unsigned int size), - - TP_ARGS(size), - - TP_STRUCT__entry( - __field( unsigned int, size ) - ), - - TP_fast_assign( - __entry->size = size; - ), - - TP_printk("Mailbox bytes 0x%8.8x", (unsigned int)__entry->size) -); - -DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_inbox_read, - - TP_PROTO(unsigned int size), - - TP_ARGS(size) - -); - -DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_inbox_write, - - TP_PROTO(unsigned int size), - - TP_ARGS(size) - -); - -DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_outbox_read, - - TP_PROTO(unsigned int size), - - TP_ARGS(size) - -); - -DEFINE_EVENT(sst_ipc_mailbox_info, sst_ipc_outbox_write, - - TP_PROTO(unsigned int size), - - TP_ARGS(size) - -); - -#endif /* _TRACE_SST_H */ - -/* This part must be outside protection */ -#include diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c index 1888de54d079..e0ad2e50be52 100644 --- a/sound/soc/intel/sst-dsp.c +++ b/sound/soc/intel/sst-dsp.c @@ -24,7 +24,7 @@ #include "sst-dsp-priv.h" #define CREATE_TRACE_POINTS -#include +#include /* Public API */ void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value) -- cgit v1.2.3 From 603597c9375b8162edae3231dd4cc7f1f500de79 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 18 Feb 2014 15:57:35 +0100 Subject: ASoC: Add ADAU1977 CODEC driver This patch adds support for the ADAU1977, ADAU1978 and ADAU1979 audio CODEC devices. They are a family of 4-channel differential input audio ADC devices. They can be connected to either a SPI or I2C bus. The driver is implemented in three modules, one main module (adau1977.ko) which implements the device logic and one module each for SPI (adau1977-spi.ko) and I2C (adau1977-i2c.ko) bus access. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/linux/platform_data/adau1977.h | 45 ++ sound/soc/codecs/Kconfig | 15 + sound/soc/codecs/Makefile | 6 + sound/soc/codecs/adau1977-i2c.c | 59 ++ sound/soc/codecs/adau1977-spi.c | 76 +++ sound/soc/codecs/adau1977.c | 1018 ++++++++++++++++++++++++++++++++ sound/soc/codecs/adau1977.h | 37 ++ 7 files changed, 1256 insertions(+) create mode 100644 include/linux/platform_data/adau1977.h create mode 100644 sound/soc/codecs/adau1977-i2c.c create mode 100644 sound/soc/codecs/adau1977-spi.c create mode 100644 sound/soc/codecs/adau1977.c create mode 100644 sound/soc/codecs/adau1977.h (limited to 'sound/soc') diff --git a/include/linux/platform_data/adau1977.h b/include/linux/platform_data/adau1977.h new file mode 100644 index 000000000000..bed11d908f92 --- /dev/null +++ b/include/linux/platform_data/adau1977.h @@ -0,0 +1,45 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#ifndef __LINUX_PLATFORM_DATA_ADAU1977_H__ +#define __LINUX_PLATFORM_DATA_ADAU1977_H__ + +/** + * enum adau1977_micbias - ADAU1977 MICBIAS pin voltage setting + * @ADAU1977_MICBIAS_5V0: MICBIAS is set to 5.0 V + * @ADAU1977_MICBIAS_5V5: MICBIAS is set to 5.5 V + * @ADAU1977_MICBIAS_6V0: MICBIAS is set to 6.0 V + * @ADAU1977_MICBIAS_6V5: MICBIAS is set to 6.5 V + * @ADAU1977_MICBIAS_7V0: MICBIAS is set to 7.0 V + * @ADAU1977_MICBIAS_7V5: MICBIAS is set to 7.5 V + * @ADAU1977_MICBIAS_8V0: MICBIAS is set to 8.0 V + * @ADAU1977_MICBIAS_8V5: MICBIAS is set to 8.5 V + * @ADAU1977_MICBIAS_9V0: MICBIAS is set to 9.0 V + */ +enum adau1977_micbias { + ADAU1977_MICBIAS_5V0 = 0x0, + ADAU1977_MICBIAS_5V5 = 0x1, + ADAU1977_MICBIAS_6V0 = 0x2, + ADAU1977_MICBIAS_6V5 = 0x3, + ADAU1977_MICBIAS_7V0 = 0x4, + ADAU1977_MICBIAS_7V5 = 0x5, + ADAU1977_MICBIAS_8V0 = 0x6, + ADAU1977_MICBIAS_8V5 = 0x7, + ADAU1977_MICBIAS_9V0 = 0x8, +}; + +/** + * struct adau1977_platform_data - Platform configuration data for the ADAU1977 + * @micbias: Specifies the voltage for the MICBIAS pin + */ +struct adau1977_platform_data { + enum adau1977_micbias micbias; +}; + +#endif diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9ea428bdd872..4535674f6eba 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -24,6 +24,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_ADAU1373 if I2C select SND_SOC_ADAV801 if SPI_MASTER select SND_SOC_ADAV803 if I2C + select SND_SOC_ADAU1977_SPI if SPI_MASTER + select SND_SOC_ADAU1977_I2C if I2C select SND_SOC_ADAU1701 if I2C select SND_SOC_ADS117X select SND_SOC_AK4104 if SPI_MASTER @@ -200,6 +202,19 @@ config SND_SOC_ADAU1701 config SND_SOC_ADAU1373 tristate +config SND_SOC_ADAU1977 + tristate + +config SND_SOC_ADAU1977_SPI + tristate + select SND_SOC_ADAU1977 + select REGMAP_SPI + +config SND_SOC_ADAU1977_I2C + tristate + select SND_SOC_ADAU1977 + select REGMAP_I2C + config SND_SOC_ADAV80X tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 1b2c6eca863f..bfd85ec2dfa8 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -7,6 +7,9 @@ snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o snd-soc-adau1373-objs := adau1373.o +snd-soc-adau1977-objs := adau1977.o +snd-soc-adau1977-spi-objs := adau1977-spi.o +snd-soc-adau1977-i2c-objs := adau1977-i2c.o snd-soc-adav80x-objs := adav80x.o snd-soc-adav801-objs := adav801.o snd-soc-adav803-objs := adav803.o @@ -139,6 +142,9 @@ obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o +obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o +obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o +obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o diff --git a/sound/soc/codecs/adau1977-i2c.c b/sound/soc/codecs/adau1977-i2c.c new file mode 100644 index 000000000000..9700e8c838c9 --- /dev/null +++ b/sound/soc/codecs/adau1977-i2c.c @@ -0,0 +1,59 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include + +#include "adau1977.h" + +static int adau1977_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap_config config; + + config = adau1977_regmap_config; + config.val_bits = 8; + config.reg_bits = 8; + + return adau1977_probe(&client->dev, + devm_regmap_init_i2c(client, &config), + id->driver_data, NULL); +} + +static int adau1977_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static const struct i2c_device_id adau1977_i2c_ids[] = { + { "adau1977", ADAU1977 }, + { "adau1978", ADAU1978 }, + { "adau1979", ADAU1978 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids); + +static struct i2c_driver adau1977_i2c_driver = { + .driver = { + .name = "adau1977", + .owner = THIS_MODULE, + }, + .probe = adau1977_i2c_probe, + .remove = adau1977_i2c_remove, + .id_table = adau1977_i2c_ids, +}; +module_i2c_driver(adau1977_i2c_driver); + +MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau1977-spi.c b/sound/soc/codecs/adau1977-spi.c new file mode 100644 index 000000000000..b05cf5da3a94 --- /dev/null +++ b/sound/soc/codecs/adau1977-spi.c @@ -0,0 +1,76 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include + +#include "adau1977.h" + +static void adau1977_spi_switch_mode(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + + /* + * To get the device into SPI mode CLATCH has to be pulled low three + * times. Do this by issuing three dummy reads. + */ + spi_w8r8(spi, 0x00); + spi_w8r8(spi, 0x00); + spi_w8r8(spi, 0x00); +} + +static int adau1977_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct regmap_config config; + + if (!id) + return -EINVAL; + + config = adau1977_regmap_config; + config.val_bits = 8; + config.reg_bits = 16; + config.read_flag_mask = 0x1; + + return adau1977_probe(&spi->dev, + devm_regmap_init_spi(spi, &config), + id->driver_data, adau1977_spi_switch_mode); +} + +static int adau1977_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static const struct spi_device_id adau1977_spi_ids[] = { + { "adau1977", ADAU1977 }, + { "adau1978", ADAU1978 }, + { "adau1979", ADAU1978 }, + { } +}; +MODULE_DEVICE_TABLE(spi, adau1977_spi_ids); + +static struct spi_driver adau1977_spi_driver = { + .driver = { + .name = "adau1977", + .owner = THIS_MODULE, + }, + .probe = adau1977_spi_probe, + .remove = adau1977_spi_remove, + .id_table = adau1977_spi_ids, +}; +module_spi_driver(adau1977_spi_driver); + +MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c new file mode 100644 index 000000000000..fd55da7cb9d4 --- /dev/null +++ b/sound/soc/codecs/adau1977.c @@ -0,0 +1,1018 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "adau1977.h" + +#define ADAU1977_REG_POWER 0x00 +#define ADAU1977_REG_PLL 0x01 +#define ADAU1977_REG_BOOST 0x02 +#define ADAU1977_REG_MICBIAS 0x03 +#define ADAU1977_REG_BLOCK_POWER_SAI 0x04 +#define ADAU1977_REG_SAI_CTRL0 0x05 +#define ADAU1977_REG_SAI_CTRL1 0x06 +#define ADAU1977_REG_CMAP12 0x07 +#define ADAU1977_REG_CMAP34 0x08 +#define ADAU1977_REG_SAI_OVERTEMP 0x09 +#define ADAU1977_REG_POST_ADC_GAIN(x) (0x0a + (x)) +#define ADAU1977_REG_MISC_CONTROL 0x0e +#define ADAU1977_REG_DIAG_CONTROL 0x10 +#define ADAU1977_REG_STATUS(x) (0x11 + (x)) +#define ADAU1977_REG_DIAG_IRQ1 0x15 +#define ADAU1977_REG_DIAG_IRQ2 0x16 +#define ADAU1977_REG_ADJUST1 0x17 +#define ADAU1977_REG_ADJUST2 0x18 +#define ADAU1977_REG_ADC_CLIP 0x19 +#define ADAU1977_REG_DC_HPF_CAL 0x1a + +#define ADAU1977_POWER_RESET BIT(7) +#define ADAU1977_POWER_PWUP BIT(0) + +#define ADAU1977_PLL_CLK_S BIT(4) +#define ADAU1977_PLL_MCS_MASK 0x7 + +#define ADAU1977_MICBIAS_MB_VOLTS_MASK 0xf0 +#define ADAU1977_MICBIAS_MB_VOLTS_OFFSET 4 + +#define ADAU1977_BLOCK_POWER_SAI_LR_POL BIT(7) +#define ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE BIT(6) +#define ADAU1977_BLOCK_POWER_SAI_LDO_EN BIT(5) + +#define ADAU1977_SAI_CTRL0_FMT_MASK (0x3 << 6) +#define ADAU1977_SAI_CTRL0_FMT_I2S (0x0 << 6) +#define ADAU1977_SAI_CTRL0_FMT_LJ (0x1 << 6) +#define ADAU1977_SAI_CTRL0_FMT_RJ_24BIT (0x2 << 6) +#define ADAU1977_SAI_CTRL0_FMT_RJ_16BIT (0x3 << 6) + +#define ADAU1977_SAI_CTRL0_SAI_MASK (0x7 << 3) +#define ADAU1977_SAI_CTRL0_SAI_I2S (0x0 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_2 (0x1 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_4 (0x2 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_8 (0x3 << 3) +#define ADAU1977_SAI_CTRL0_SAI_TDM_16 (0x4 << 3) + +#define ADAU1977_SAI_CTRL0_FS_MASK (0x7) +#define ADAU1977_SAI_CTRL0_FS_8000_12000 (0x0) +#define ADAU1977_SAI_CTRL0_FS_16000_24000 (0x1) +#define ADAU1977_SAI_CTRL0_FS_32000_48000 (0x2) +#define ADAU1977_SAI_CTRL0_FS_64000_96000 (0x3) +#define ADAU1977_SAI_CTRL0_FS_128000_192000 (0x4) + +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK (0x3 << 5) +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_32 (0x0 << 5) +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_24 (0x1 << 5) +#define ADAU1977_SAI_CTRL1_SLOT_WIDTH_16 (0x2 << 5) +#define ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK (0x1 << 4) +#define ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT (0x1 << 4) +#define ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT (0x0 << 4) +#define ADAU1977_SAI_CTRL1_LRCLK_PULSE BIT(3) +#define ADAU1977_SAI_CTRL1_MSB BIT(2) +#define ADAU1977_SAI_CTRL1_BCLKRATE_16 (0x1 << 1) +#define ADAU1977_SAI_CTRL1_BCLKRATE_32 (0x0 << 1) +#define ADAU1977_SAI_CTRL1_BCLKRATE_MASK (0x1 << 1) +#define ADAU1977_SAI_CTRL1_MASTER BIT(0) + +#define ADAU1977_SAI_OVERTEMP_DRV_C(x) BIT(4 + (x)) +#define ADAU1977_SAI_OVERTEMP_DRV_HIZ BIT(3) + +#define ADAU1977_MISC_CONTROL_SUM_MODE_MASK (0x3 << 6) +#define ADAU1977_MISC_CONTROL_SUM_MODE_1CH (0x2 << 6) +#define ADAU1977_MISC_CONTROL_SUM_MODE_2CH (0x1 << 6) +#define ADAU1977_MISC_CONTROL_SUM_MODE_4CH (0x0 << 6) +#define ADAU1977_MISC_CONTROL_MMUTE BIT(4) +#define ADAU1977_MISC_CONTROL_DC_CAL BIT(0) + +#define ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET 4 +#define ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET 0 + +struct adau1977 { + struct regmap *regmap; + bool right_j; + unsigned int sysclk; + enum adau1977_sysclk_src sysclk_src; + struct gpio_desc *reset_gpio; + enum adau1977_type type; + + struct regulator *avdd_reg; + struct regulator *dvdd_reg; + + struct snd_pcm_hw_constraint_list constraints; + + struct device *dev; + void (*switch_mode)(struct device *dev); + + unsigned int max_master_fs; + unsigned int slot_width; + bool enabled; + bool master; +}; + +static const struct reg_default adau1977_reg_defaults[] = { + { 0x00, 0x00 }, + { 0x01, 0x41 }, + { 0x02, 0x4a }, + { 0x03, 0x7d }, + { 0x04, 0x3d }, + { 0x05, 0x02 }, + { 0x06, 0x00 }, + { 0x07, 0x10 }, + { 0x08, 0x32 }, + { 0x09, 0xf0 }, + { 0x0a, 0xa0 }, + { 0x0b, 0xa0 }, + { 0x0c, 0xa0 }, + { 0x0d, 0xa0 }, + { 0x0e, 0x02 }, + { 0x10, 0x0f }, + { 0x15, 0x20 }, + { 0x16, 0x00 }, + { 0x17, 0x00 }, + { 0x18, 0x00 }, + { 0x1a, 0x00 }, +}; + +static const DECLARE_TLV_DB_MINMAX_MUTE(adau1977_adc_gain, -3562, 6000); + +static const struct snd_soc_dapm_widget adau1977_micbias_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("MICBIAS", ADAU1977_REG_MICBIAS, + 3, 0, NULL, 0) +}; + +static const struct snd_soc_dapm_widget adau1977_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("Vref", ADAU1977_REG_BLOCK_POWER_SAI, + 4, 0, NULL, 0), + + SND_SOC_DAPM_ADC("ADC1", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 0, 0), + SND_SOC_DAPM_ADC("ADC2", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 1, 0), + SND_SOC_DAPM_ADC("ADC3", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 2, 0), + SND_SOC_DAPM_ADC("ADC4", "Capture", ADAU1977_REG_BLOCK_POWER_SAI, 3, 0), + + SND_SOC_DAPM_INPUT("AIN1"), + SND_SOC_DAPM_INPUT("AIN2"), + SND_SOC_DAPM_INPUT("AIN3"), + SND_SOC_DAPM_INPUT("AIN4"), + + SND_SOC_DAPM_OUTPUT("VREF"), +}; + +static const struct snd_soc_dapm_route adau1977_dapm_routes[] = { + { "ADC1", NULL, "AIN1" }, + { "ADC2", NULL, "AIN2" }, + { "ADC3", NULL, "AIN3" }, + { "ADC4", NULL, "AIN4" }, + + { "ADC1", NULL, "Vref" }, + { "ADC2", NULL, "Vref" }, + { "ADC3", NULL, "Vref" }, + { "ADC4", NULL, "Vref" }, + + { "VREF", NULL, "Vref" }, +}; + +#define ADAU1977_VOLUME(x) \ + SOC_SINGLE_TLV("ADC" #x " Capture Volume", \ + ADAU1977_REG_POST_ADC_GAIN((x) - 1), \ + 0, 255, 1, adau1977_adc_gain) + +#define ADAU1977_HPF_SWITCH(x) \ + SOC_SINGLE("ADC" #x " Highpass-Filter Capture Switch", \ + ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0) + +#define ADAU1977_DC_SUB_SWITCH(x) \ + SOC_SINGLE("ADC" #x " DC Substraction Capture Switch", \ + ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0) + +static const struct snd_kcontrol_new adau1977_snd_controls[] = { + ADAU1977_VOLUME(1), + ADAU1977_VOLUME(2), + ADAU1977_VOLUME(3), + ADAU1977_VOLUME(4), + + ADAU1977_HPF_SWITCH(1), + ADAU1977_HPF_SWITCH(2), + ADAU1977_HPF_SWITCH(3), + ADAU1977_HPF_SWITCH(4), + + ADAU1977_DC_SUB_SWITCH(1), + ADAU1977_DC_SUB_SWITCH(2), + ADAU1977_DC_SUB_SWITCH(3), + ADAU1977_DC_SUB_SWITCH(4), +}; + +static int adau1977_reset(struct adau1977 *adau1977) +{ + int ret; + + /* + * The reset bit is obviously volatile, but we need to be able to cache + * the other bits in the register, so we can't just mark the whole + * register as volatile. Since this is the only place where we'll ever + * touch the reset bit just bypass the cache for this operation. + */ + regcache_cache_bypass(adau1977->regmap, true); + ret = regmap_write(adau1977->regmap, ADAU1977_REG_POWER, + ADAU1977_POWER_RESET); + regcache_cache_bypass(adau1977->regmap, false); + if (ret) + return ret; + + return ret; +} + +/* + * Returns the appropriate setting for ths FS field in the CTRL0 register + * depending on the rate. + */ +static int adau1977_lookup_fs(unsigned int rate) +{ + if (rate >= 8000 && rate <= 12000) + return ADAU1977_SAI_CTRL0_FS_8000_12000; + else if (rate >= 16000 && rate <= 24000) + return ADAU1977_SAI_CTRL0_FS_16000_24000; + else if (rate >= 32000 && rate <= 48000) + return ADAU1977_SAI_CTRL0_FS_32000_48000; + else if (rate >= 64000 && rate <= 96000) + return ADAU1977_SAI_CTRL0_FS_64000_96000; + else if (rate >= 128000 && rate <= 192000) + return ADAU1977_SAI_CTRL0_FS_128000_192000; + else + return -EINVAL; +} + +static int adau1977_lookup_mcs(struct adau1977 *adau1977, unsigned int rate, + unsigned int fs) +{ + unsigned int mcs; + + /* + * rate = sysclk / (512 * mcs_lut[mcs]) * 2**fs + * => mcs_lut[mcs] = sysclk / (512 * rate) * 2**fs + * => mcs_lut[mcs] = sysclk / ((512 / 2**fs) * rate) + */ + + rate *= 512 >> fs; + + if (adau1977->sysclk % rate != 0) + return -EINVAL; + + mcs = adau1977->sysclk / rate; + + /* The factors configured by MCS are 1, 2, 3, 4, 6 */ + if (mcs < 1 || mcs > 6 || mcs == 5) + return -EINVAL; + + mcs = mcs - 1; + if (mcs == 5) + mcs = 4; + + return mcs; +} + +static int adau1977_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + unsigned int rate = params_rate(params); + unsigned int slot_width; + unsigned int ctrl0, ctrl0_mask; + unsigned int ctrl1; + int mcs, fs; + int ret; + + fs = adau1977_lookup_fs(rate); + if (fs < 0) + return fs; + + if (adau1977->sysclk_src == ADAU1977_SYSCLK_SRC_MCLK) { + mcs = adau1977_lookup_mcs(adau1977, rate, fs); + if (mcs < 0) + return mcs; + } else { + mcs = 0; + } + + ctrl0_mask = ADAU1977_SAI_CTRL0_FS_MASK; + ctrl0 = fs; + + if (adau1977->right_j) { + switch (params_width(params)) { + case 16: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_16BIT; + break; + case 24: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; + break; + default: + return -EINVAL; + } + ctrl0_mask |= ADAU1977_SAI_CTRL0_FMT_MASK; + } + + if (adau1977->master) { + switch (params_width(params)) { + case 16: + ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT; + slot_width = 16; + break; + case 24: + case 32: + ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT; + slot_width = 32; + break; + default: + return -EINVAL; + } + + /* In TDM mode there is a fixed slot width */ + if (adau1977->slot_width) + slot_width = adau1977->slot_width; + + if (slot_width == 16) + ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_16; + else + ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_32; + + ret = regmap_update_bits(adau1977->regmap, + ADAU1977_REG_SAI_CTRL1, + ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK | + ADAU1977_SAI_CTRL1_BCLKRATE_MASK, + ctrl1); + if (ret < 0) + return ret; + } + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, + ctrl0_mask, ctrl0); + if (ret < 0) + return ret; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL, + ADAU1977_PLL_MCS_MASK, mcs); +} + +static int adau1977_power_disable(struct adau1977 *adau1977) +{ + int ret = 0; + + if (!adau1977->enabled) + return 0; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER, + ADAU1977_POWER_PWUP, 0); + if (ret) + return ret; + + regcache_mark_dirty(adau1977->regmap); + + if (adau1977->reset_gpio) + gpiod_set_value_cansleep(adau1977->reset_gpio, 0); + + regcache_cache_only(adau1977->regmap, true); + + regulator_disable(adau1977->avdd_reg); + if (adau1977->dvdd_reg) + regulator_disable(adau1977->dvdd_reg); + + adau1977->enabled = false; + + return 0; +} + +static int adau1977_power_enable(struct adau1977 *adau1977) +{ + unsigned int val; + int ret = 0; + + if (adau1977->enabled) + return 0; + + ret = regulator_enable(adau1977->avdd_reg); + if (ret) + return ret; + + if (adau1977->dvdd_reg) { + ret = regulator_enable(adau1977->dvdd_reg); + if (ret) + goto err_disable_avdd; + } + + if (adau1977->reset_gpio) + gpiod_set_value_cansleep(adau1977->reset_gpio, 1); + + regcache_cache_only(adau1977->regmap, false); + + if (adau1977->switch_mode) + adau1977->switch_mode(adau1977->dev); + + ret = adau1977_reset(adau1977); + if (ret) + goto err_disable_dvdd; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_POWER, + ADAU1977_POWER_PWUP, ADAU1977_POWER_PWUP); + if (ret) + goto err_disable_dvdd; + + ret = regcache_sync(adau1977->regmap); + if (ret) + goto err_disable_dvdd; + + /* + * The PLL register is not affected by the software reset. It is + * possible that the value of the register was changed to the + * default value while we were in cache only mode. In this case + * regcache_sync will skip over it and we have to manually sync + * it. + */ + ret = regmap_read(adau1977->regmap, ADAU1977_REG_PLL, &val); + if (ret) + goto err_disable_dvdd; + + if (val == 0x41) { + regcache_cache_bypass(adau1977->regmap, true); + ret = regmap_write(adau1977->regmap, ADAU1977_REG_PLL, + 0x41); + if (ret) + goto err_disable_dvdd; + regcache_cache_bypass(adau1977->regmap, false); + } + + adau1977->enabled = true; + + return ret; + +err_disable_dvdd: + if (adau1977->dvdd_reg) + regulator_disable(adau1977->dvdd_reg); +err_disable_avdd: + regulator_disable(adau1977->avdd_reg); + return ret; +} + +static int adau1977_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) + ret = adau1977_power_enable(adau1977); + break; + case SND_SOC_BIAS_OFF: + ret = adau1977_power_disable(adau1977); + break; + } + + if (ret) + return ret; + + codec->dapm.bias_level = level; + + return 0; +} + +static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int width) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int ctrl0, ctrl1, drv; + unsigned int slot[4]; + unsigned int i; + int ret; + + if (slots == 0) { + /* 0 = No fixed slot width */ + adau1977->slot_width = 0; + adau1977->max_master_fs = 192000; + return regmap_update_bits(adau1977->regmap, + ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_SAI_MASK, + ADAU1977_SAI_CTRL0_SAI_I2S); + } + + if (rx_mask == 0 || tx_mask != 0) + return -EINVAL; + + drv = 0; + for (i = 0; i < 4; i++) { + slot[i] = __ffs(rx_mask); + drv |= ADAU1977_SAI_OVERTEMP_DRV_C(i); + rx_mask &= ~(1 << slot[i]); + if (slot[i] >= slots) + return -EINVAL; + if (rx_mask == 0) + break; + } + + if (rx_mask != 0) + return -EINVAL; + + switch (width) { + case 16: + ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_16; + break; + case 24: + /* We can only generate 16 bit or 32 bit wide slots */ + if (adau1977->master) + return -EINVAL; + ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_24; + break; + case 32: + ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_32; + break; + default: + return -EINVAL; + } + + switch (slots) { + case 2: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_2; + break; + case 4: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_4; + break; + case 8: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_8; + break; + case 16: + ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_16; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, + ADAU1977_SAI_OVERTEMP_DRV_C(0) | + ADAU1977_SAI_OVERTEMP_DRV_C(1) | + ADAU1977_SAI_OVERTEMP_DRV_C(2) | + ADAU1977_SAI_OVERTEMP_DRV_C(3), drv); + if (ret) + return ret; + + ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP12, + (slot[1] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | + (slot[0] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); + if (ret) + return ret; + + ret = regmap_write(adau1977->regmap, ADAU1977_REG_CMAP34, + (slot[3] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | + (slot[2] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); + if (ret) + return ret; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, + ADAU1977_SAI_CTRL0_SAI_MASK, ctrl0); + if (ret) + return ret; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, + ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK, ctrl1); + if (ret) + return ret; + + adau1977->slot_width = width; + + /* In master mode the maximum bitclock is 24.576 MHz */ + adau1977->max_master_fs = min(192000, 24576000 / width / slots); + + return 0; +} + +static int adau1977_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int val; + + if (mute) + val = ADAU1977_MISC_CONTROL_MMUTE; + else + val = 0; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MISC_CONTROL, + ADAU1977_MISC_CONTROL_MMUTE, val); +} + +static int adau1977_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int ctrl0 = 0, ctrl1 = 0, block_power = 0; + bool invert_lrclk; + int ret; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + adau1977->master = false; + break; + case SND_SOC_DAIFMT_CBM_CFM: + ctrl1 |= ADAU1977_SAI_CTRL1_MASTER; + adau1977->master = true; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + invert_lrclk = false; + break; + case SND_SOC_DAIFMT_IB_NF: + block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; + invert_lrclk = false; + break; + case SND_SOC_DAIFMT_NB_IF: + invert_lrclk = true; + break; + case SND_SOC_DAIFMT_IB_IF: + block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; + invert_lrclk = true; + break; + default: + return -EINVAL; + } + + adau1977->right_j = false; + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; + invert_lrclk = !invert_lrclk; + break; + case SND_SOC_DAIFMT_RIGHT_J: + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; + adau1977->right_j = true; + invert_lrclk = !invert_lrclk; + break; + case SND_SOC_DAIFMT_DSP_A: + ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; + invert_lrclk = false; + break; + case SND_SOC_DAIFMT_DSP_B: + ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; + ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; + invert_lrclk = false; + break; + default: + return -EINVAL; + } + + if (invert_lrclk) + block_power |= ADAU1977_BLOCK_POWER_SAI_LR_POL; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, + ADAU1977_BLOCK_POWER_SAI_LR_POL | + ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE, block_power); + if (ret) + return ret; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, + ADAU1977_SAI_CTRL0_FMT_MASK, + ctrl0); + if (ret) + return ret; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, + ADAU1977_SAI_CTRL1_MASTER | ADAU1977_SAI_CTRL1_LRCLK_PULSE, + ctrl1); +} + +static int adau1977_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + u64 formats = 0; + + if (adau1977->slot_width == 16) + formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE; + else if (adau1977->right_j || adau1977->slot_width == 24) + formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE; + + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &adau1977->constraints); + + if (adau1977->master) + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, 8000, adau1977->max_master_fs); + + if (formats != 0) + snd_pcm_hw_constraint_mask64(substream->runtime, + SNDRV_PCM_HW_PARAM_FORMAT, formats); + + return 0; +} + +static int adau1977_set_tristate(struct snd_soc_dai *dai, int tristate) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(dai->codec); + unsigned int val; + + if (tristate) + val = ADAU1977_SAI_OVERTEMP_DRV_HIZ; + else + val = 0; + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, + ADAU1977_SAI_OVERTEMP_DRV_HIZ, val); +} + +static const struct snd_soc_dai_ops adau1977_dai_ops = { + .startup = adau1977_startup, + .hw_params = adau1977_hw_params, + .mute_stream = adau1977_mute, + .set_fmt = adau1977_set_dai_fmt, + .set_tdm_slot = adau1977_set_tdm_slot, + .set_tristate = adau1977_set_tristate, +}; + +static struct snd_soc_dai_driver adau1977_dai = { + .name = "adau1977-hifi", + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 4, + .rates = SNDRV_PCM_RATE_KNOT, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .sig_bits = 24, + }, + .ops = &adau1977_dai_ops, +}; + +static const unsigned int adau1977_rates[] = { + 8000, 16000, 32000, 64000, 128000, + 11025, 22050, 44100, 88200, 172400, + 12000, 24000, 48000, 96000, 192000, +}; + +#define ADAU1977_RATE_CONSTRAINT_MASK_32000 0x001f +#define ADAU1977_RATE_CONSTRAINT_MASK_44100 0x03e0 +#define ADAU1977_RATE_CONSTRAINT_MASK_48000 0x7c00 +/* All rates >= 32000 */ +#define ADAU1977_RATE_CONSTRAINT_MASK_LRCLK 0x739c + +static bool adau1977_check_sysclk(unsigned int mclk, unsigned int base_freq) +{ + unsigned int mcs; + + if (mclk % (base_freq * 128) != 0) + return false; + + mcs = mclk / (128 * base_freq); + if (mcs < 1 || mcs > 6 || mcs == 5) + return false; + + return true; +} + +static int adau1977_set_sysclk(struct snd_soc_codec *codec, + int clk_id, int source, unsigned int freq, int dir) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + unsigned int mask = 0; + unsigned int clk_src; + unsigned int ret; + + if (dir != SND_SOC_CLOCK_IN) + return -EINVAL; + + if (clk_id != ADAU1977_SYSCLK) + return -EINVAL; + + switch (source) { + case ADAU1977_SYSCLK_SRC_MCLK: + clk_src = 0; + break; + case ADAU1977_SYSCLK_SRC_LRCLK: + clk_src = ADAU1977_PLL_CLK_S; + break; + default: + return -EINVAL; + } + + if (freq != 0 && source == ADAU1977_SYSCLK_SRC_MCLK) { + if (freq < 4000000 || freq > 36864000) + return -EINVAL; + + if (adau1977_check_sysclk(freq, 32000)) + mask |= ADAU1977_RATE_CONSTRAINT_MASK_32000; + if (adau1977_check_sysclk(freq, 44100)) + mask |= ADAU1977_RATE_CONSTRAINT_MASK_44100; + if (adau1977_check_sysclk(freq, 48000)) + mask |= ADAU1977_RATE_CONSTRAINT_MASK_48000; + + if (mask == 0) + return -EINVAL; + } else if (source == ADAU1977_SYSCLK_SRC_LRCLK) { + mask = ADAU1977_RATE_CONSTRAINT_MASK_LRCLK; + } + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL, + ADAU1977_PLL_CLK_S, clk_src); + if (ret) + return ret; + + adau1977->constraints.mask = mask; + adau1977->sysclk_src = source; + adau1977->sysclk = freq; + + return 0; +} + +static int adau1977_codec_probe(struct snd_soc_codec *codec) +{ + struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); + int ret; + + switch (adau1977->type) { + case ADAU1977: + ret = snd_soc_dapm_new_controls(&codec->dapm, + adau1977_micbias_dapm_widgets, + ARRAY_SIZE(adau1977_micbias_dapm_widgets)); + if (ret < 0) + return ret; + break; + default: + break; + } + + return 0; +} + +static struct snd_soc_codec_driver adau1977_codec_driver = { + .probe = adau1977_codec_probe, + .set_bias_level = adau1977_set_bias_level, + .set_sysclk = adau1977_set_sysclk, + .idle_bias_off = true, + + .controls = adau1977_snd_controls, + .num_controls = ARRAY_SIZE(adau1977_snd_controls), + .dapm_widgets = adau1977_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets), + .dapm_routes = adau1977_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes), +}; + +static int adau1977_setup_micbias(struct adau1977 *adau1977) +{ + struct adau1977_platform_data *pdata = adau1977->dev->platform_data; + unsigned int micbias; + + if (pdata) { + micbias = pdata->micbias; + if (micbias > ADAU1977_MICBIAS_9V0) + return -EINVAL; + + } else { + micbias = ADAU1977_MICBIAS_8V5; + } + + return regmap_update_bits(adau1977->regmap, ADAU1977_REG_MICBIAS, + ADAU1977_MICBIAS_MB_VOLTS_MASK, + micbias << ADAU1977_MICBIAS_MB_VOLTS_OFFSET); +} + +int adau1977_probe(struct device *dev, struct regmap *regmap, + enum adau1977_type type, void (*switch_mode)(struct device *dev)) +{ + unsigned int power_off_mask; + struct adau1977 *adau1977; + int ret; + + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + adau1977 = devm_kzalloc(dev, sizeof(*adau1977), GFP_KERNEL); + if (adau1977 == NULL) + return -ENOMEM; + + adau1977->dev = dev; + adau1977->type = type; + adau1977->regmap = regmap; + adau1977->switch_mode = switch_mode; + adau1977->max_master_fs = 192000; + + adau1977->constraints.list = adau1977_rates; + adau1977->constraints.count = ARRAY_SIZE(adau1977_rates); + + adau1977->avdd_reg = devm_regulator_get(dev, "AVDD"); + if (IS_ERR(adau1977->avdd_reg)) + return PTR_ERR(adau1977->avdd_reg); + + adau1977->dvdd_reg = devm_regulator_get_optional(dev, "DVDD"); + if (IS_ERR(adau1977->dvdd_reg)) { + if (PTR_ERR(adau1977->dvdd_reg) != -ENODEV) + return PTR_ERR(adau1977->dvdd_reg); + adau1977->dvdd_reg = NULL; + } + + adau1977->reset_gpio = devm_gpiod_get(dev, "reset"); + if (IS_ERR(adau1977->reset_gpio)) { + ret = PTR_ERR(adau1977->reset_gpio); + if (ret != -ENOENT && ret != -ENOSYS) + return PTR_ERR(adau1977->reset_gpio); + adau1977->reset_gpio = NULL; + } + + dev_set_drvdata(dev, adau1977); + + if (adau1977->reset_gpio) { + ret = gpiod_direction_output(adau1977->reset_gpio, 0); + if (ret) + return ret; + ndelay(100); + } + + ret = adau1977_power_enable(adau1977); + if (ret) + return ret; + + if (type == ADAU1977) { + ret = adau1977_setup_micbias(adau1977); + if (ret) + goto err_poweroff; + } + + if (adau1977->dvdd_reg) + power_off_mask = ~0; + else + power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN; + + ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, + power_off_mask, 0x00); + if (ret) + goto err_poweroff; + + ret = adau1977_power_disable(adau1977); + if (ret) + return ret; + + return snd_soc_register_codec(dev, &adau1977_codec_driver, + &adau1977_dai, 1); + +err_poweroff: + adau1977_power_disable(adau1977); + return ret; + +} +EXPORT_SYMBOL_GPL(adau1977_probe); + +static bool adau1977_register_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ADAU1977_REG_STATUS(0): + case ADAU1977_REG_STATUS(1): + case ADAU1977_REG_STATUS(2): + case ADAU1977_REG_STATUS(3): + case ADAU1977_REG_ADC_CLIP: + return true; + } + + return false; +} + +const struct regmap_config adau1977_regmap_config = { + .max_register = ADAU1977_REG_DC_HPF_CAL, + .volatile_reg = adau1977_register_volatile, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = adau1977_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(adau1977_reg_defaults), +}; +EXPORT_SYMBOL_GPL(adau1977_regmap_config); + +MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver"); +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/adau1977.h b/sound/soc/codecs/adau1977.h new file mode 100644 index 000000000000..95e714345a86 --- /dev/null +++ b/sound/soc/codecs/adau1977.h @@ -0,0 +1,37 @@ +/* + * ADAU1977/ADAU1978/ADAU1979 driver + * + * Copyright 2014 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#ifndef __SOUND_SOC_CODECS_ADAU1977_H__ +#define __SOUND_SOC_CODECS_ADAU1977_H__ + +#include + +struct device; + +enum adau1977_type { + ADAU1977, + ADAU1978, + ADAU1979, +}; + +int adau1977_probe(struct device *dev, struct regmap *regmap, + enum adau1977_type type, void (*switch_mode)(struct device *dev)); + +extern const struct regmap_config adau1977_regmap_config; + +enum adau1977_clk_id { + ADAU1977_SYSCLK, +}; + +enum adau1977_sysclk_src { + ADAU1977_SYSCLK_SRC_MCLK, + ADAU1977_SYSCLK_SRC_LRCLK, +}; + +#endif -- cgit v1.2.3 From 0c49a8c9f9fafdf4345259b9b50513905afcf860 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 18 Feb 2014 16:42:02 +0200 Subject: ASoC: Intel: Move extended fw base and size fields in struct sst_pdata Move fw_base and fw_size fields in struct sst_pdata under ACPI data for clarifying that these are not related to firmware file but for platform specific extended firmware area reserved by the BIOS. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-dsp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h index 0ce5c8d91794..d134359fecac 100644 --- a/sound/soc/intel/sst-dsp.h +++ b/sound/soc/intel/sst-dsp.h @@ -147,12 +147,12 @@ struct sst_pdata { u32 lpe_size; u32 pcicfg_base; u32 pcicfg_size; + u32 fw_base; + u32 fw_size; int irq; /* Firmware */ const char *fw_filename; - u32 fw_base; - u32 fw_size; /* DMA */ u32 dma_base; -- cgit v1.2.3 From e5161d7987f14338ad0a3cf376b9bb6838416183 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 19 Feb 2014 10:30:38 +0200 Subject: ASoC: Intel: sst-acpi: Request firmware before SST platform driver probing We originally thought to request SST audio DSP firmware during the SST platform driver initialization. However plain request_firmware doesn't work in driver probe paths if userspace is not ready to handle it. For instance when drivers are built-in. Implementing asynchronous firmware request in SST platform driver initialization complicates code needlessly since it anyway will fail if firmware is missing. This is more simple to handle by requesting firmware asynchronously in sst_acpi_probe() and register SST platform only after firmware is loaded. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-acpi.c | 56 ++++++++++++++++++++++++++++++++-------------- sound/soc/intel/sst-dsp.h | 2 +- 2 files changed, 40 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c index aba73ca8a923..64154a77d904 100644 --- a/sound/soc/intel/sst-acpi.c +++ b/sound/soc/intel/sst-acpi.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -56,6 +57,32 @@ struct sst_acpi_priv { struct sst_acpi_desc *desc; }; +static void sst_acpi_fw_cb(const struct firmware *fw, void *context) +{ + struct platform_device *pdev = context; + struct device *dev = &pdev->dev; + struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev); + struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata; + struct sst_acpi_desc *desc = sst_acpi->desc; + + sst_pdata->fw = fw; + if (!fw) { + dev_err(dev, "Cannot load firmware %s\n", desc->fw_filename); + return; + } + + /* register PCM and DAI driver */ + sst_acpi->pdev_pcm = + platform_device_register_data(dev, desc->drv_name, -1, + sst_pdata, sizeof(*sst_pdata)); + if (IS_ERR(sst_acpi->pdev_pcm)) { + dev_err(dev, "Cannot register device %s. Error %d\n", + desc->drv_name, (int)PTR_ERR(sst_acpi->pdev_pcm)); + } + + return; +} + static int sst_acpi_probe(struct platform_device *pdev) { const struct acpi_device_id *id; @@ -79,7 +106,6 @@ static int sst_acpi_probe(struct platform_device *pdev) desc = mach->res_desc; sst_pdata = &sst_acpi->sst_pdata; sst_pdata->id = desc->sst_id; - sst_pdata->fw_filename = desc->fw_filename; sst_acpi->desc = desc; if (desc->resindex_dma_base >= 0) { @@ -118,37 +144,33 @@ static int sst_acpi_probe(struct platform_device *pdev) } } - /* register PCM and DAI driver */ - sst_acpi->pdev_pcm = - platform_device_register_data(dev, desc->drv_name, -1, - sst_pdata, sizeof(*sst_pdata)); - if (IS_ERR(sst_acpi->pdev_pcm)) - return PTR_ERR(sst_acpi->pdev_pcm); - - /* register machine driver */ platform_set_drvdata(pdev, sst_acpi); + /* register machine driver */ sst_acpi->pdev_mach = platform_device_register_data(dev, mach->drv_name, -1, sst_pdata, sizeof(*sst_pdata)); - if (IS_ERR(sst_acpi->pdev_mach)) { - ret = PTR_ERR(sst_acpi->pdev_mach); - goto sst_err; - } + if (IS_ERR(sst_acpi->pdev_mach)) + return PTR_ERR(sst_acpi->pdev_mach); - return ret; + /* continue SST probing after firmware is loaded */ + ret = request_firmware_nowait(THIS_MODULE, true, desc->fw_filename, + dev, GFP_KERNEL, pdev, sst_acpi_fw_cb); + if (ret) + platform_device_unregister(sst_acpi->pdev_mach); -sst_err: - platform_device_unregister(sst_acpi->pdev_pcm); return ret; } static int sst_acpi_remove(struct platform_device *pdev) { struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev); + struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata; platform_device_unregister(sst_acpi->pdev_mach); - platform_device_unregister(sst_acpi->pdev_pcm); + if (!IS_ERR_OR_NULL(sst_acpi->pdev_pcm)) + platform_device_unregister(sst_acpi->pdev_pcm); + release_firmware(sst_pdata->fw); return 0; } diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h index d134359fecac..3730fd324455 100644 --- a/sound/soc/intel/sst-dsp.h +++ b/sound/soc/intel/sst-dsp.h @@ -152,7 +152,7 @@ struct sst_pdata { int irq; /* Firmware */ - const char *fw_filename; + const struct firmware *fw; /* DMA */ u32 dma_base; -- cgit v1.2.3 From 7bcd84878ebd87168682b117e1cb9dd8a55a1a8b Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 19 Feb 2014 14:06:23 +0000 Subject: ASoC: Intel: Fix sparse warnings for firmware loader Sparse gives us the following warnings on sst-firmware.c CHECK sound/soc/intel/sst-firmware.c sound/soc/intel/sst-firmware.c:39:34: warning: incorrect type in argument 1 (different address spaces) sound/soc/intel/sst-firmware.c:39:34: expected void volatile [noderef] *dst sound/soc/intel/sst-firmware.c:39:34: got void * sound/soc/intel/sst-firmware.c:417:36: warning: incorrect type in argument 1 (different address spaces) sound/soc/intel/sst-firmware.c:417:36: expected void *dest sound/soc/intel/sst-firmware.c:417:36: got void [noderef] * sound/soc/intel/sst-firmware.c:430:5: warning: symbol 'sst_block_module_remove' was not declared. Should it be static? and CC [M] sound/soc/intel/sst-dsp.o sound/soc/intel/sst-dsp-priv.h:271:53: warning: incorrect type in argument 3 (different address spaces) sound/soc/intel/sst-dsp-priv.h:271:53: expected void *src sound/soc/intel/sst-dsp-priv.h:271:53: got void [noderef] * sound/soc/intel/sst-dsp-priv.h:271:53: warning: incorrect type in argument 3 (different address spaces) sound/soc/intel/sst-dsp-priv.h:271:53: expected void *src sound/soc/intel/sst-dsp-priv.h:271:53: got void [noderef] * sound/soc/intel/sst-dsp-priv.h:271:53: warning: incorrect type in argument 3 (different address spaces) sound/soc/intel/sst-dsp-priv.h:271:53: expected void *src sound/soc/intel/sst-dsp-priv.h:271:53: got void [noderef] * This patch removes these warnings Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-dsp-priv.h | 7 +++++-- sound/soc/intel/sst-firmware.c | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-dsp-priv.h b/sound/soc/intel/sst-dsp-priv.h index 35de547f1744..fa2c780c888b 100644 --- a/sound/soc/intel/sst-dsp-priv.h +++ b/sound/soc/intel/sst-dsp-priv.h @@ -41,8 +41,10 @@ struct sst_ops { u64 (*read64)(void __iomem *addr, u32 offset); /* DSP I/DRAM IO */ - void (*ram_read)(struct sst_dsp *sst, void *dest, void *src, size_t bytes); - void (*ram_write)(struct sst_dsp *sst, void *dest, void *src, size_t bytes); + void (*ram_read)(struct sst_dsp *sst, void *dest, void __iomem *src, + size_t bytes); + void (*ram_write)(struct sst_dsp *sst, void __iomem *dest, void *src, + size_t bytes); void (*dump)(struct sst_dsp *); @@ -295,6 +297,7 @@ struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id); struct sst_module *sst_mem_block_alloc_scratch(struct sst_dsp *dsp); void sst_mem_block_free_scratch(struct sst_dsp *dsp, struct sst_module *scratch); +int sst_block_module_remove(struct sst_module *module); /* Register the DSPs memory blocks - would be nice to read from ACPI */ struct sst_mem_block *sst_mem_block_register(struct sst_dsp *dsp, u32 offset, diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index 31cd15430e9a..dee7eb5befb7 100644 --- a/sound/soc/intel/sst-firmware.c +++ b/sound/soc/intel/sst-firmware.c @@ -30,7 +30,7 @@ #include "sst-dsp.h" #include "sst-dsp-priv.h" -static void sst_memcpy32(void *dest, void *src, u32 bytes) +static void sst_memcpy32(volatile void __iomem *dest, void *src, u32 bytes) { u32 i; -- cgit v1.2.3 From d6cf89ee07cbfd980f189cc12ae924c811b00ee4 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 19 Feb 2014 14:05:54 +0100 Subject: ASoC: cs4271: claim reset GPIO in bus probe function Move the GPIO acquisition from the codec to the bus probe functions. Signed-off-by: Daniel Mack Acked-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/cs4271.c | 60 +++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 20 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index f7bbe6fdba67..96c309777208 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -539,14 +539,10 @@ static int cs4271_probe(struct snd_soc_codec *codec) struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; int ret; - int gpio_nreset = -EINVAL; bool amutec_eq_bmutec = false; #ifdef CONFIG_OF if (of_match_device(cs4271_dt_ids, codec->dev)) { - gpio_nreset = of_get_named_gpio(codec->dev->of_node, - "reset-gpio", 0); - if (of_get_property(codec->dev->of_node, "cirrus,amutec-eq-bmutec", NULL)) amutec_eq_bmutec = true; @@ -558,27 +554,19 @@ static int cs4271_probe(struct snd_soc_codec *codec) #endif if (cs4271plat) { - if (gpio_is_valid(cs4271plat->gpio_nreset)) - gpio_nreset = cs4271plat->gpio_nreset; - amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; cs4271->enable_soft_reset = cs4271plat->enable_soft_reset; } - if (gpio_nreset >= 0) - if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset")) - gpio_nreset = -EINVAL; - if (gpio_nreset >= 0) { + if (gpio_is_valid(cs4271->gpio_nreset)) { /* Reset codec */ - gpio_direction_output(gpio_nreset, 0); + gpio_direction_output(cs4271->gpio_nreset, 0); udelay(1); - gpio_set_value(gpio_nreset, 1); + gpio_set_value(cs4271->gpio_nreset, 1); /* Give the codec time to wake up */ udelay(1); } - cs4271->gpio_nreset = gpio_nreset; - ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, CS4271_MODE2_PDN | CS4271_MODE2_CPEN, CS4271_MODE2_PDN | CS4271_MODE2_CPEN); @@ -640,14 +628,45 @@ static const struct regmap_config cs4271_spi_regmap = { .volatile_reg = cs4271_volatile_reg, }; -static int cs4271_spi_probe(struct spi_device *spi) +static int cs4271_common_probe(struct device *dev, + struct cs4271_private **c) { + struct cs4271_platform_data *cs4271plat = dev->platform_data; struct cs4271_private *cs4271; - cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL); + cs4271 = devm_kzalloc(dev, sizeof(*cs4271), GFP_KERNEL); if (!cs4271) return -ENOMEM; + if (of_match_device(cs4271_dt_ids, dev)) + cs4271->gpio_nreset = + of_get_named_gpio(dev->of_node, "reset-gpio", 0); + + if (cs4271plat) + cs4271->gpio_nreset = cs4271plat->gpio_nreset; + + if (gpio_is_valid(cs4271->gpio_nreset)) { + int ret; + + ret = devm_gpio_request(dev, cs4271->gpio_nreset, + "CS4271 Reset"); + if (ret < 0) + return ret; + } + + *c = cs4271; + return 0; +} + +static int cs4271_spi_probe(struct spi_device *spi) +{ + struct cs4271_private *cs4271; + int ret; + + ret = cs4271_common_probe(&spi->dev, &cs4271); + if (ret < 0) + return ret; + spi_set_drvdata(spi, cs4271); cs4271->regmap = devm_regmap_init_spi(spi, &cs4271_spi_regmap); if (IS_ERR(cs4271->regmap)) @@ -697,10 +716,11 @@ static int cs4271_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct cs4271_private *cs4271; + int ret; - cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL); - if (!cs4271) - return -ENOMEM; + ret = cs4271_common_probe(&client->dev, &cs4271); + if (ret < 0) + return ret; i2c_set_clientdata(client, cs4271); cs4271->regmap = devm_regmap_init_i2c(client, &cs4271_i2c_regmap); -- cgit v1.2.3 From 6dda27cbbd1d2d2ac4833236f5fd8a81c14d200a Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 19 Feb 2014 16:35:58 +0200 Subject: ASoC: Intel: sst-acpi: Add support for multiple machine drivers per platform Initial implementation of this driver focused only matching SST ACPI ID with single machine driver and same firmware file per platform. It was known restriction to be improved incrementally. This patch is now changing this that SST ACPI ID refers purely to platform specific data which refers to machine drivers on this platform, not vice versa. Matching machine driver is found by looking at ACPI ID which would best match with the driver. Typically this would be the ACPI ID of audio codec but is not tied to it. This patch also changes that DSP firmware name is machine not platform specific. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-acpi.c | 84 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 26 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c index 64154a77d904..c7e36c9ee52f 100644 --- a/sound/soc/intel/sst-acpi.c +++ b/sound/soc/intel/sst-acpi.c @@ -26,9 +26,20 @@ #define SST_WPT_DSP_DMA_ADDR_OFFSET 0x0FE000 #define SST_LPT_DSP_DMA_SIZE (1024 - 1) +/* Descriptor for SST ASoC machine driver */ +struct sst_acpi_mach { + /* ACPI ID for the matching machine driver. Audio codec for instance */ + const u8 id[ACPI_ID_LEN]; + /* machine driver name */ + const char *drv_name; + /* firmware file name */ + const char *fw_filename; +}; + /* Descriptor for setting up SST platform data */ struct sst_acpi_desc { const char *drv_name; + struct sst_acpi_mach *machines; /* Platform resource indexes. Must set to -1 if not used */ int resindex_lpe_base; int resindex_pcicfg_base; @@ -37,24 +48,17 @@ struct sst_acpi_desc { int resindex_dma_base; /* Unique number identifying the SST core on platform */ int sst_id; - /* firmware file name */ - const char *fw_filename; /* DMA only valid when resindex_dma_base != -1*/ int dma_engine; int dma_size; }; -/* Descriptor for SST ASoC machine driver */ -struct sst_acpi_mach { - const char *drv_name; - struct sst_acpi_desc *res_desc; -}; - struct sst_acpi_priv { struct platform_device *pdev_mach; struct platform_device *pdev_pcm; struct sst_pdata sst_pdata; struct sst_acpi_desc *desc; + struct sst_acpi_mach *mach; }; static void sst_acpi_fw_cb(const struct firmware *fw, void *context) @@ -64,10 +68,11 @@ static void sst_acpi_fw_cb(const struct firmware *fw, void *context) struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev); struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata; struct sst_acpi_desc *desc = sst_acpi->desc; + struct sst_acpi_mach *mach = sst_acpi->mach; sst_pdata->fw = fw; if (!fw) { - dev_err(dev, "Cannot load firmware %s\n", desc->fw_filename); + dev_err(dev, "Cannot load firmware %s\n", mach->fw_filename); return; } @@ -83,6 +88,28 @@ static void sst_acpi_fw_cb(const struct firmware *fw, void *context) return; } +static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level, + void *context, void **ret) +{ + *(bool *)context = true; + return AE_OK; +} + +static struct sst_acpi_mach *sst_acpi_find_machine( + struct sst_acpi_mach *machines) +{ + struct sst_acpi_mach *mach; + bool found = false; + + for (mach = machines; mach->id[0]; mach++) + if (ACPI_SUCCESS(acpi_get_devices(mach->id, + sst_acpi_mach_match, + &found, NULL)) && found) + return mach; + + return NULL; +} + static int sst_acpi_probe(struct platform_device *pdev) { const struct acpi_device_id *id; @@ -102,8 +129,13 @@ static int sst_acpi_probe(struct platform_device *pdev) if (!id) return -ENODEV; - mach = (struct sst_acpi_mach *)id->driver_data; - desc = mach->res_desc; + desc = (struct sst_acpi_desc *)id->driver_data; + mach = sst_acpi_find_machine(desc->machines); + if (mach == NULL) { + dev_err(dev, "No matching ASoC machine driver found\n"); + return -ENODEV; + } + sst_pdata = &sst_acpi->sst_pdata; sst_pdata->id = desc->sst_id; sst_acpi->desc = desc; @@ -154,7 +186,7 @@ static int sst_acpi_probe(struct platform_device *pdev) return PTR_ERR(sst_acpi->pdev_mach); /* continue SST probing after firmware is loaded */ - ret = request_firmware_nowait(THIS_MODULE, true, desc->fw_filename, + ret = request_firmware_nowait(THIS_MODULE, true, mach->fw_filename, dev, GFP_KERNEL, pdev, sst_acpi_fw_cb); if (ret) platform_device_unregister(sst_acpi->pdev_mach); @@ -175,45 +207,45 @@ static int sst_acpi_remove(struct platform_device *pdev) return 0; } +static struct sst_acpi_mach haswell_machines[] = { + { "INT33CA", "haswell-audio", "intel/IntcSST1.bin" }, + {} +}; + static struct sst_acpi_desc sst_acpi_haswell_desc = { .drv_name = "haswell-pcm-audio", + .machines = haswell_machines, .resindex_lpe_base = 0, .resindex_pcicfg_base = 1, .resindex_fw_base = -1, .irqindex_host_ipc = 0, .sst_id = SST_DEV_ID_LYNX_POINT, - .fw_filename = "intel/IntcSST1.bin", .dma_engine = SST_DMA_TYPE_DW, .resindex_dma_base = SST_LPT_DSP_DMA_ADDR_OFFSET, .dma_size = SST_LPT_DSP_DMA_SIZE, }; +static struct sst_acpi_mach broadwell_machines[] = { + { "INT343A", "broadwell-audio", "intel/IntcSST2.bin" }, + {} +}; + static struct sst_acpi_desc sst_acpi_broadwell_desc = { .drv_name = "haswell-pcm-audio", + .machines = broadwell_machines, .resindex_lpe_base = 0, .resindex_pcicfg_base = 1, .resindex_fw_base = -1, .irqindex_host_ipc = 0, .sst_id = SST_DEV_ID_WILDCAT_POINT, - .fw_filename = "intel/IntcSST2.bin", .dma_engine = SST_DMA_TYPE_DW, .resindex_dma_base = SST_WPT_DSP_DMA_ADDR_OFFSET, .dma_size = SST_LPT_DSP_DMA_SIZE, }; -static struct sst_acpi_mach haswell_mach = { - .drv_name = "haswell-audio", - .res_desc = &sst_acpi_haswell_desc, -}; - -static struct sst_acpi_mach broadwell_mach = { - .drv_name = "broadwell-audio", - .res_desc = &sst_acpi_broadwell_desc, -}; - static struct acpi_device_id sst_acpi_match[] = { - { "INT33C8", (unsigned long)&haswell_mach }, - { "INT3438", (unsigned long)&broadwell_mach }, + { "INT33C8", (unsigned long)&sst_acpi_haswell_desc }, + { "INT3438", (unsigned long)&sst_acpi_broadwell_desc }, { } }; MODULE_DEVICE_TABLE(acpi, sst_acpi_match); -- cgit v1.2.3 From 7ec02609739d82f7786e5a169e5a900dbaf0d1a1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 08:59:39 +0100 Subject: ASoC: da732x: Remove superfluous DA732X_SOC_ENUM_DOUBLE_R() It's nowhere used. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/da732x.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h index c8ce5475de22..1dceafeec415 100644 --- a/sound/soc/codecs/da732x.h +++ b/sound/soc/codecs/da732x.h @@ -113,9 +113,6 @@ #define DA732X_EQ_OVERALL_VOL_DB_MIN -1800 #define DA732X_EQ_OVERALL_VOL_DB_INC 600 -#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \ - {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext} - enum da732x_sysctl { DA732X_SR_8KHZ = 0x1, DA732X_SR_11_025KHZ = 0x2, -- cgit v1.2.3 From afd954900af84bf66a0dd72b2648a2c15fb68f25 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Wed, 19 Feb 2014 16:45:57 +0000 Subject: ASoC: Intel: Fix build for sst-dsp.c on PPC architecture Disable build on non X86 architectures except for compile testing. This fixes the following build errors on PPC and adds an option for testing the build on other architectures as suggested by Mark Brown :- sound/soc/intel/sst-dsp.c: In function 'sst_dsp_outbox_write': sound/soc/intel/sst-dsp.c:218:2: error: implicit declaration of function 'memcpy_toio' [-Werror=implicit-function-declaration] memcpy_toio(sst->mailbox.out_base, message, bytes); ^ sound/soc/intel/sst-dsp.c: In function 'sst_dsp_outbox_read': sound/soc/intel/sst-dsp.c:231:2: error: implicit declaration of function 'memcpy_fromio' [-Werror=implicit-function-declaration] memcpy_fromio(message, sst->mailbox.out_base, bytes); ^ Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 1 + sound/soc/intel/sst-dsp.c | 1 + 2 files changed, 2 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index b0a07e4cc919..dd048fef7248 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -15,6 +15,7 @@ config SND_SST_MFLD_PLATFORM config SND_SOC_INTEL_SST tristate "ASoC support for Intel(R) Smart Sound Technology" select SND_SOC_INTEL_SST_ACPI if ACPI + depends on (X86 || COMPILE_TEST) help This adds support for Intel(R) Smart Sound Technology (SST). Say Y if you have such a device diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c index e0ad2e50be52..6e22c1201959 100644 --- a/sound/soc/intel/sst-dsp.c +++ b/sound/soc/intel/sst-dsp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "sst-dsp.h" #include "sst-dsp-priv.h" -- cgit v1.2.3 From b38fbe30739afa83695c4969c8e966d919d828b0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:17:44 +0100 Subject: ASoC: ssm2602: Omit superfluous elements in input select array The array contains too many elements although it should have only two. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ssm2602.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 49d28eaa6d73..12947096897c 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -63,15 +63,16 @@ static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { /*Appending several "None"s just for OSS mixer use*/ static const char *ssm2602_input_select[] = { - "Line", "Mic", "None", "None", "None", - "None", "None", "None", + "Line", "Mic", }; static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; static const struct soc_enum ssm2602_enum[] = { - SOC_ENUM_SINGLE(SSM2602_APANA, 2, 2, ssm2602_input_select), - SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph), + SOC_ENUM_SINGLE(SSM2602_APANA, 2, ARRAY_SIZE(ssm2602_input_select), + ssm2602_input_select), + SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, ARRAY_SIZE(ssm2602_deemph), + ssm2602_deemph), }; static const unsigned int ssm260x_outmix_tlv[] = { -- cgit v1.2.3 From 830b501138ab50dd413143dce47d1ae6dd1e39a5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:43:49 +0100 Subject: ASoC: wm8990: Fix the wrong number of enum items wm8990 codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8990.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 0ccd4d8d043b..33f53ab1e7b0 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -157,26 +157,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, static const char *wm8990_digital_sidetone[] = {"None", "Left ADC", "Right ADC", "Reserved"}; -static const struct soc_enum wm8990_left_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, - WM8990_ADC_TO_DACL_SHIFT, - WM8990_ADC_TO_DACL_MASK, - wm8990_digital_sidetone); - -static const struct soc_enum wm8990_right_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, - WM8990_ADC_TO_DACR_SHIFT, - WM8990_ADC_TO_DACR_MASK, - wm8990_digital_sidetone); +static SOC_ENUM_SINGLE_DECL(wm8990_left_digital_sidetone_enum, + WM8990_DIGITAL_SIDE_TONE, + WM8990_ADC_TO_DACL_SHIFT, + wm8990_digital_sidetone); + +static SOC_ENUM_SINGLE_DECL(wm8990_right_digital_sidetone_enum, + WM8990_DIGITAL_SIDE_TONE, + WM8990_ADC_TO_DACR_SHIFT, + wm8990_digital_sidetone); static const char *wm8990_adcmode[] = {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; -static const struct soc_enum wm8990_right_adcmode_enum = -SOC_ENUM_SINGLE(WM8990_ADC_CTRL, - WM8990_ADC_HPF_CUT_SHIFT, - WM8990_ADC_HPF_CUT_MASK, - wm8990_adcmode); +static SOC_ENUM_SINGLE_DECL(wm8990_right_adcmode_enum, + WM8990_ADC_CTRL, + WM8990_ADC_HPF_CUT_SHIFT, + wm8990_adcmode); static const struct snd_kcontrol_new wm8990_snd_controls[] = { /* INMIXL */ @@ -475,9 +472,9 @@ SOC_DAPM_SINGLE("RINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT, static const char *wm8990_ainlmux[] = {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; -static const struct soc_enum wm8990_ainlmux_enum = -SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT, - ARRAY_SIZE(wm8990_ainlmux), wm8990_ainlmux); +static SOC_ENUM_SINGLE_DECL(wm8990_ainlmux_enum, + WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT, + wm8990_ainlmux); static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls = SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); @@ -488,9 +485,9 @@ SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); static const char *wm8990_ainrmux[] = {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; -static const struct soc_enum wm8990_ainrmux_enum = -SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT, - ARRAY_SIZE(wm8990_ainrmux), wm8990_ainrmux); +static SOC_ENUM_SINGLE_DECL(wm8990_ainrmux_enum, + WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT, + wm8990_ainrmux); static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum); -- cgit v1.2.3 From d07338b0f2e1697c99fcd52bf1895227ce5e1a14 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:44:23 +0100 Subject: ASoC: wm8991: Fix the wrong number of enum items wm8991 codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8991.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 244eb09ffa43..32d219570cca 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -171,26 +171,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, static const char *wm8991_digital_sidetone[] = {"None", "Left ADC", "Right ADC", "Reserved"}; -static const struct soc_enum wm8991_left_digital_sidetone_enum = - SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, - WM8991_ADC_TO_DACL_SHIFT, - WM8991_ADC_TO_DACL_MASK, - wm8991_digital_sidetone); - -static const struct soc_enum wm8991_right_digital_sidetone_enum = - SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, - WM8991_ADC_TO_DACR_SHIFT, - WM8991_ADC_TO_DACR_MASK, - wm8991_digital_sidetone); +static SOC_ENUM_SINGLE_DECL(wm8991_left_digital_sidetone_enum, + WM8991_DIGITAL_SIDE_TONE, + WM8991_ADC_TO_DACL_SHIFT, + wm8991_digital_sidetone); + +static SOC_ENUM_SINGLE_DECL(wm8991_right_digital_sidetone_enum, + WM8991_DIGITAL_SIDE_TONE, + WM8991_ADC_TO_DACR_SHIFT, + wm8991_digital_sidetone); static const char *wm8991_adcmode[] = {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; -static const struct soc_enum wm8991_right_adcmode_enum = - SOC_ENUM_SINGLE(WM8991_ADC_CTRL, - WM8991_ADC_HPF_CUT_SHIFT, - WM8991_ADC_HPF_CUT_MASK, - wm8991_adcmode); +static SOC_ENUM_SINGLE_DECL(wm8991_right_adcmode_enum, + WM8991_ADC_CTRL, + WM8991_ADC_HPF_CUT_SHIFT, + wm8991_adcmode); static const struct snd_kcontrol_new wm8991_snd_controls[] = { /* INMIXL */ @@ -486,9 +483,9 @@ static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = { static const char *wm8991_ainlmux[] = {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; -static const struct soc_enum wm8991_ainlmux_enum = - SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, - ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux); +static SOC_ENUM_SINGLE_DECL(wm8991_ainlmux_enum, + WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, + wm8991_ainlmux); static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum); @@ -499,9 +496,9 @@ static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = static const char *wm8991_ainrmux[] = {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; -static const struct soc_enum wm8991_ainrmux_enum = - SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, - ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux); +static SOC_ENUM_SINGLE_DECL(wm8991_ainrmux_enum, + WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, + wm8991_ainrmux); static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); -- cgit v1.2.3 From b6592d88ec37440c88cc3bc2c9c08a61d0de3eec Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:55:27 +0100 Subject: ASoC: ad193x: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index f644a34a28de..9381a767e75f 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -31,8 +31,8 @@ struct ad193x_priv { */ static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; -static const struct soc_enum ad193x_deemp_enum = - SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp); +static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1, + ad193x_deemp); static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); -- cgit v1.2.3 From 9a8d38db030f016bee45b927af02d9b46398ed46 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 08:11:42 +0100 Subject: ASoC: Rename soc_enum.max field with items The name "max" in struct soc_enum is rather confusing since it actually takes the number of items. With "max", one might try to assign (nitems - 1) value. Rename the field to a more appropriate one, "items", which is also used in struct snd_ctl_elem_info, too. This patch also rewrites some code like "if (x > e->nitems - 1)" with "if (x >= e->nitems)". Not only the latter improves the readability, it also fixes a potential bug when e->items is zero. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 24 ++++++++++++------------ sound/soc/codecs/max98088.c | 2 +- sound/soc/codecs/max98095.c | 4 ++-- sound/soc/codecs/twl4030.c | 4 ++-- sound/soc/codecs/wm8904.c | 4 ++-- sound/soc/codecs/wm8958-dsp2.c | 8 ++++---- sound/soc/codecs/wm8994.c | 4 ++-- sound/soc/codecs/wm8996.c | 2 +- sound/soc/omap/ams-delta.c | 2 +- sound/soc/soc-core.c | 18 +++++++++--------- sound/soc/soc-dapm.c | 22 +++++++++++----------- 11 files changed, 47 insertions(+), 47 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a001472b96a..66de6a70581e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -162,19 +162,19 @@ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .min = xmin, .max = xmax, \ .platform_max = xmax} } -#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ +#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xitems, xtexts) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .max = xmax, .texts = xtexts, \ - .mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0} -#define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \ - SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts) -#define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \ -{ .max = xmax, .texts = xtexts } -#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xmax, xtexts, xvalues) \ + .items = xitems, .texts = xtexts, \ + .mask = xitems ? roundup_pow_of_two(xitems) - 1 : 0} +#define SOC_ENUM_SINGLE(xreg, xshift, xitems, xtexts) \ + SOC_ENUM_DOUBLE(xreg, xshift, xshift, xitems, xtexts) +#define SOC_ENUM_SINGLE_EXT(xitems, xtexts) \ +{ .items = xitems, .texts = xtexts } +#define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xitems, xtexts, xvalues) \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .mask = xmask, .max = xmax, .texts = xtexts, .values = xvalues} -#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xmax, xtexts, xvalues) \ - SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xmax, xtexts, xvalues) + .mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues} +#define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xnitmes, xtexts, xvalues) \ + SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xnitmes, xtexts, xvalues) #define SOC_ENUM(xname, xenum) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ .info = snd_soc_info_enum_double, \ @@ -1089,7 +1089,7 @@ struct soc_enum { unsigned short reg2; unsigned char shift_l; unsigned char shift_r; - unsigned int max; + unsigned int items; unsigned int mask; const char * const *texts; const unsigned int *values; diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index ee660e2d3df3..bb1ecfc4459b 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -1849,7 +1849,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec) /* Now point the soc_enum to .texts array items */ max98088->eq_enum.texts = max98088->eq_texts; - max98088->eq_enum.max = max98088->eq_textcnt; + max98088->eq_enum.items = max98088->eq_textcnt; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); if (ret != 0) diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 3ba1170ebb53..5bce9cde4a6d 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -1861,7 +1861,7 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec) /* Now point the soc_enum to .texts array items */ max98095->eq_enum.texts = max98095->eq_texts; - max98095->eq_enum.max = max98095->eq_textcnt; + max98095->eq_enum.items = max98095->eq_textcnt; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); if (ret != 0) @@ -2016,7 +2016,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec) /* Now point the soc_enum to .texts array items */ max98095->bq_enum.texts = max98095->bq_texts; - max98095->bq_enum.max = max98095->bq_textcnt; + max98095->bq_enum.items = max98095->bq_textcnt; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); if (ret != 0) diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 00665ada23e2..1eb13d586309 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -975,13 +975,13 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, return -EBUSY; } - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; val = ucontrol->value.enumerated.item[0] << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] >= e->items) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; mask |= e->mask << e->shift_r; diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 53bbfac6a83a..b2664ec901b9 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1981,7 +1981,7 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", wm8904->num_retune_mobile_texts); - wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; + wm8904->retune_mobile_enum.items = wm8904->num_retune_mobile_texts; wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; ret = snd_soc_add_codec_controls(codec, &control, 1); @@ -2022,7 +2022,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_drc_cfgs; i++) wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; - wm8904->drc_enum.max = pdata->num_drc_cfgs; + wm8904->drc_enum.items = pdata->num_drc_cfgs; wm8904->drc_enum.texts = wm8904->drc_texts; ret = snd_soc_add_codec_controls(codec, &control, 1); diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index b7488f190d2b..19743779bf4d 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -944,7 +944,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_mbc_cfgs; i++) wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; - wm8994->mbc_enum.max = pdata->num_mbc_cfgs; + wm8994->mbc_enum.items = pdata->num_mbc_cfgs; wm8994->mbc_enum.texts = wm8994->mbc_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, @@ -973,7 +973,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_vss_cfgs; i++) wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; - wm8994->vss_enum.max = pdata->num_vss_cfgs; + wm8994->vss_enum.items = pdata->num_vss_cfgs; wm8994->vss_enum.texts = wm8994->vss_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, @@ -1003,7 +1003,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; - wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; + wm8994->vss_hpf_enum.items = pdata->num_vss_hpf_cfgs; wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, @@ -1034,7 +1034,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) for (i = 0; i < pdata->num_enh_eq_cfgs; i++) wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; - wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; + wm8994->enh_eq_enum.items = pdata->num_enh_eq_cfgs; wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b9be9cbc4603..8253c3c6db0e 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3237,7 +3237,7 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", wm8994->num_retune_mobile_texts); - wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; + wm8994->retune_mobile_enum.items = wm8994->num_retune_mobile_texts; wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, @@ -3293,7 +3293,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) for (i = 0; i < pdata->num_drc_cfgs; i++) wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; - wm8994->drc_enum.max = pdata->num_drc_cfgs; + wm8994->drc_enum.items = pdata->num_drc_cfgs; wm8994->drc_enum.texts = wm8994->drc_texts; ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1a7655b0aa22..ea6b587f65c1 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2595,7 +2595,7 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec) dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", wm8996->num_retune_mobile_texts); - wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts; + wm8996->retune_mobile_enum.items = wm8996->num_retune_mobile_texts; wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts; ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 629446482a91..2eca91a51f51 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -103,7 +103,7 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, if (!codec->hw_write) return -EUNATCH; - if (ucontrol->value.enumerated.item[0] >= control->max) + if (ucontrol->value.enumerated.item[0] >= control->items) return -EINVAL; mutex_lock(&codec->mutex); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..4372efb4e033 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2571,10 +2571,10 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = e->shift_l == e->shift_r ? 1 : 2; - uinfo->value.enumerated.items = e->max; + uinfo->value.enumerated.items = e->items; - if (uinfo->value.enumerated.item > e->max - 1) - uinfo->value.enumerated.item = e->max - 1; + if (uinfo->value.enumerated.item >= e->items) + uinfo->value.enumerated.item = e->items - 1; strlcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item], sizeof(uinfo->value.enumerated.name)); @@ -2626,12 +2626,12 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, unsigned int val; unsigned int mask; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; val = ucontrol->value.enumerated.item[0] << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] >= e->items) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; mask |= e->mask << e->shift_r; @@ -2662,14 +2662,14 @@ int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, reg_val = snd_soc_read(codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; - for (mux = 0; mux < e->max; mux++) { + for (mux = 0; mux < e->items; mux++) { if (val == e->values[mux]) break; } ucontrol->value.enumerated.item[0] = mux; if (e->shift_l != e->shift_r) { val = (reg_val >> e->shift_r) & e->mask; - for (mux = 0; mux < e->max; mux++) { + for (mux = 0; mux < e->items; mux++) { if (val == e->values[mux]) break; } @@ -2700,12 +2700,12 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, unsigned int val; unsigned int mask; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] >= e->items) return -EINVAL; val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; mask |= e->mask << e->shift_r; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index dc8ff13187f7..2026a64a0afb 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -535,7 +535,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, soc_widget_read(w, e->reg, &val); item = (val >> e->shift_l) & e->mask; - if (item < e->max && !strcmp(p->name, e->texts[item])) + if (item < e->items && !strcmp(p->name, e->texts[item])) p->connect = 1; else p->connect = 0; @@ -563,12 +563,12 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, soc_widget_read(w, e->reg, &val); val = (val >> e->shift_l) & e->mask; - for (item = 0; item < e->max; item++) { + for (item = 0; item < e->items; item++) { if (val == e->values[item]) break; } - if (item < e->max && !strcmp(p->name, e->texts[item])) + if (item < e->items && !strcmp(p->name, e->texts[item])) p->connect = 1; else p->connect = 0; @@ -616,7 +616,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int i; - for (i = 0; i < e->max; i++) { + for (i = 0; i < e->items; i++) { if (!(strcmp(control_name, e->texts[i]))) { list_add(&path->list, &dapm->card->paths); list_add(&path->list_sink, &dest->sources); @@ -2967,13 +2967,13 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_update update; int ret = 0; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; mux = ucontrol->value.enumerated.item[0]; val = mux << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] >= e->items) return -EINVAL; val |= ucontrol->value.enumerated.item[1] << e->shift_r; mask |= e->mask << e->shift_r; @@ -3036,7 +3036,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, int change; int ret = 0; - if (ucontrol->value.enumerated.item[0] >= e->max) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); @@ -3077,14 +3077,14 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, reg_val = snd_soc_read(codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; - for (mux = 0; mux < e->max; mux++) { + for (mux = 0; mux < e->items; mux++) { if (val == e->values[mux]) break; } ucontrol->value.enumerated.item[0] = mux; if (e->shift_l != e->shift_r) { val = (reg_val >> e->shift_r) & e->mask; - for (mux = 0; mux < e->max; mux++) { + for (mux = 0; mux < e->items; mux++) { if (val == e->values[mux]) break; } @@ -3119,13 +3119,13 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_update update; int ret = 0; - if (ucontrol->value.enumerated.item[0] > e->max - 1) + if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; mux = ucontrol->value.enumerated.item[0]; val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) + if (ucontrol->value.enumerated.item[1] >= e->items) return -EINVAL; val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; mask |= e->mask << e->shift_r; -- cgit v1.2.3 From 6b207c0f166e7f19c9d9dc48feb25e276e36c43f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 08:56:39 +0100 Subject: ASoC: twl4030: Clean up duplicated code Remove the open code in snd_soc_put_twl4030_opmode_enum_double() but just call snd_soc_put_enum_double() instead, which does the very same thing (even correctly with a lock). Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 1eb13d586309..682e4ac88939 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -965,9 +965,6 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned short val; - unsigned short mask; if (twl4030->configured) { dev_err(codec->dev, @@ -975,19 +972,7 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, return -EBUSY; } - if (ucontrol->value.enumerated.item[0] >= e->items) - return -EINVAL; - - val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = e->mask << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] >= e->items) - return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= e->mask << e->shift_r; - } - - return snd_soc_update_bits(codec, e->reg, mask, val); + return snd_soc_put_enum_double(kcontrol, ucontrol); } /* -- cgit v1.2.3 From c28b14f49978af2fc864dd2faeb89f517746f9f9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 08:59:39 +0100 Subject: ALSA: da732x: Remove superfluous DA732X_SOC_ENUM_DOUBLE_R() It's nowhere used. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/da732x.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h index c8ce5475de22..1dceafeec415 100644 --- a/sound/soc/codecs/da732x.h +++ b/sound/soc/codecs/da732x.h @@ -113,9 +113,6 @@ #define DA732X_EQ_OVERALL_VOL_DB_MIN -1800 #define DA732X_EQ_OVERALL_VOL_DB_INC 600 -#define DA732X_SOC_ENUM_DOUBLE_R(xreg, xrreg, xmax, xtext) \ - {.reg = xreg, .reg2 = xrreg, .max = xmax, .texts = xtext} - enum da732x_sysctl { DA732X_SR_8KHZ = 0x1, DA732X_SR_11_025KHZ = 0x2, -- cgit v1.2.3 From 4988aff78bfd7c97cc67f0390555a9c2b6825f40 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:40:51 +0100 Subject: ASoC: adau1373: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/adau1373.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index eb836ed5271f..46b1595d7c50 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -345,15 +345,15 @@ static const char *adau1373_fdsp_sel_text[] = { "Channel 5", }; -static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text); static const char *adau1373_hpf_cutoff_text[] = { @@ -362,7 +362,7 @@ static const char *adau1373_hpf_cutoff_text[] = { "800Hz", }; -static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text); static const char *adau1373_bass_lpf_cutoff_text[] = { @@ -388,14 +388,14 @@ static const unsigned int adau1373_bass_tlv[] = { 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), }; -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); -static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, +static SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text, adau1373_bass_clip_level_values); -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text); static const char *adau1373_3d_level_text[] = { @@ -409,9 +409,9 @@ static const char *adau1373_3d_cutoff_text[] = { "0.16875 fs", "0.27083 fs" }; -static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); static const unsigned int adau1373_3d_tlv[] = { @@ -427,11 +427,11 @@ static const char *adau1373_lr_mux_text[] = { "Stereo", }; -static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, +static SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text); static const struct snd_kcontrol_new adau1373_controls[] = { -- cgit v1.2.3 From 51e5b59c3559e63e8a943350714a8c070fba8cbf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:42:16 +0100 Subject: ASoC: lm49453: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/lm49453.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index e19490cfb3a8..6b7fe5e54881 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -195,18 +195,18 @@ struct lm49453_priv { static const char *lm49453_mic2mode_text[] = {"Single Ended", "Differential"}; -static const SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5, - lm49453_mic2mode_text); +static SOC_ENUM_SINGLE_DECL(lm49453_mic2mode_enum, LM49453_P0_MICR_REG, 5, + lm49453_mic2mode_text); static const char *lm49453_dmic_cfg_text[] = {"DMICDAT1", "DMICDAT2"}; -static const SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum, - LM49453_P0_DIGITAL_MIC1_CONFIG_REG, - 7, lm49453_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(lm49453_dmic12_cfg_enum, + LM49453_P0_DIGITAL_MIC1_CONFIG_REG, 7, + lm49453_dmic_cfg_text); -static const SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum, - LM49453_P0_DIGITAL_MIC2_CONFIG_REG, - 7, lm49453_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(lm49453_dmic34_cfg_enum, + LM49453_P0_DIGITAL_MIC2_CONFIG_REG, 7, + lm49453_dmic_cfg_text); /* MUX Controls */ static const char *lm49453_adcl_mux_text[] = { "MIC1", "Aux_L" }; -- cgit v1.2.3 From a750987443cd4239c2b4dd742a59474aea10b179 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:42:50 +0100 Subject: ASoC: mc13783: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/mc13783.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 582c2bbd42cb..147c2e53797b 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -430,8 +430,8 @@ static const struct snd_kcontrol_new samp_ctl = static const char * const speaker_amp_source_text[] = { "CODEC", "Right" }; -static const SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4, - speaker_amp_source_text); +static SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4, + speaker_amp_source_text); static const struct snd_kcontrol_new speaker_amp_source_mux = SOC_DAPM_ENUM("Speaker Amp Source MUX", speaker_amp_source); @@ -439,8 +439,8 @@ static const char * const headset_amp_source_text[] = { "CODEC", "Mixer" }; -static const SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11, - headset_amp_source_text); +static SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11, + headset_amp_source_text); static const struct snd_kcontrol_new headset_amp_source_mux = SOC_DAPM_ENUM("Headset Amp Source MUX", headset_amp_source); -- cgit v1.2.3 From f843cdf2f767a88e7cfe9300f37e1c02b97cc389 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:43:08 +0100 Subject: ASoC: rt5631: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/rt5631.c | 75 +++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 45 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 912c9cbc2724..ce199d375209 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -210,26 +210,22 @@ static int rt5631_dmic_put(struct snd_kcontrol *kcontrol, static const char *rt5631_input_mode[] = { "Single ended", "Differential"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1, - RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode); +static SOC_ENUM_SINGLE_DECL(rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1, + RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode); -static const SOC_ENUM_SINGLE_DECL( - rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1, - RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode); +static SOC_ENUM_SINGLE_DECL(rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1, + RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode); /* MONO Input Type */ -static const SOC_ENUM_SINGLE_DECL( - rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL, - RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode); +static SOC_ENUM_SINGLE_DECL(rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL, + RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode); /* SPK Ratio Gain Control */ static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x", "1.56x", "1.68x", "1.99x", "2.34x"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, - RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio); +static SOC_ENUM_SINGLE_DECL(rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, + RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio); static const struct snd_kcontrol_new rt5631_snd_controls[] = { /* MIC */ @@ -759,9 +755,8 @@ static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = { /* Left SPK Volume Input */ static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL, - RT5631_L_EN_SHIFT, rt5631_spkvoll_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL, + RT5631_L_EN_SHIFT, rt5631_spkvoll_sel); static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum); @@ -769,9 +764,8 @@ static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = /* Left HP Volume Input */ static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpvoll_enum, RT5631_HP_OUT_VOL, - RT5631_L_EN_SHIFT, rt5631_hpvoll_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpvoll_enum, RT5631_HP_OUT_VOL, + RT5631_L_EN_SHIFT, rt5631_hpvoll_sel); static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum); @@ -779,9 +773,8 @@ static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = /* Left Out Volume Input */ static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL, - RT5631_L_EN_SHIFT, rt5631_outvoll_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL, + RT5631_L_EN_SHIFT, rt5631_outvoll_sel); static const struct snd_kcontrol_new rt5631_outvoll_mux_control = SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum); @@ -789,9 +782,8 @@ static const struct snd_kcontrol_new rt5631_outvoll_mux_control = /* Right Out Volume Input */ static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL, - RT5631_R_EN_SHIFT, rt5631_outvolr_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL, + RT5631_R_EN_SHIFT, rt5631_outvolr_sel); static const struct snd_kcontrol_new rt5631_outvolr_mux_control = SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum); @@ -799,9 +791,8 @@ static const struct snd_kcontrol_new rt5631_outvolr_mux_control = /* Right HP Volume Input */ static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpvolr_enum, RT5631_HP_OUT_VOL, - RT5631_R_EN_SHIFT, rt5631_hpvolr_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpvolr_enum, RT5631_HP_OUT_VOL, + RT5631_R_EN_SHIFT, rt5631_hpvolr_sel); static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum); @@ -809,9 +800,8 @@ static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = /* Right SPK Volume Input */ static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL, - RT5631_R_EN_SHIFT, rt5631_spkvolr_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL, + RT5631_R_EN_SHIFT, rt5631_spkvolr_sel); static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum); @@ -820,9 +810,8 @@ static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = static const char *rt5631_spol_src_sel[] = { "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel); static const struct snd_kcontrol_new rt5631_spol_mux_control = SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum); @@ -831,9 +820,8 @@ static const struct snd_kcontrol_new rt5631_spol_mux_control = static const char *rt5631_spor_src_sel[] = { "SPORMIX", "MONOIN_RX", "VDAC", "DACR"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel); static const struct snd_kcontrol_new rt5631_spor_mux_control = SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum); @@ -841,9 +829,8 @@ static const struct snd_kcontrol_new rt5631_spor_mux_control = /* MONO Input */ static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel); static const struct snd_kcontrol_new rt5631_mono_mux_control = SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum); @@ -851,9 +838,8 @@ static const struct snd_kcontrol_new rt5631_mono_mux_control = /* Left HPO Input */ static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel); static const struct snd_kcontrol_new rt5631_hpl_mux_control = SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum); @@ -861,9 +847,8 @@ static const struct snd_kcontrol_new rt5631_hpl_mux_control = /* Right HPO Input */ static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"}; -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel); +static SOC_ENUM_SINGLE_DECL(rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, + RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel); static const struct snd_kcontrol_new rt5631_hpr_mux_control = SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum); -- cgit v1.2.3 From 4c03cb6f86c1e171c3b277c207a6b9003402fbb6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:43:21 +0100 Subject: ASoC: rt5640: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/rt5640.c | 75 +++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 41 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index a3fb41179636..fe4a5c2d4845 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -361,25 +361,24 @@ static unsigned int bst_tlv[] = { static const char * const rt5640_data_select[] = { "Normal", "left copy to right", "right copy to left", "Swap"}; -static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, - RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA, + RT5640_IF1_DAC_SEL_SFT, rt5640_data_select); -static const SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA, - RT5640_IF1_ADC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA, + RT5640_IF1_ADC_SEL_SFT, rt5640_data_select); -static const SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA, - RT5640_IF2_DAC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA, + RT5640_IF2_DAC_SEL_SFT, rt5640_data_select); -static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA, - RT5640_IF2_ADC_SEL_SFT, rt5640_data_select); +static SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA, + RT5640_IF2_ADC_SEL_SFT, rt5640_data_select); /* Class D speaker gain ratio */ static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x", "2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"}; -static const SOC_ENUM_SINGLE_DECL( - rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT, - RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio); +static SOC_ENUM_SINGLE_DECL(rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT, + RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio); static const struct snd_kcontrol_new rt5640_snd_controls[] = { /* Speaker Output Volume */ @@ -753,9 +752,8 @@ static const char * const rt5640_stereo_adc1_src[] = { "DIG MIX", "ADC" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER, - RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src); +static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER, + RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src); static const struct snd_kcontrol_new rt5640_sto_adc_1_mux = SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum); @@ -764,9 +762,8 @@ static const char * const rt5640_stereo_adc2_src[] = { "DMIC1", "DMIC2", "DIG MIX" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER, - RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src); +static SOC_ENUM_SINGLE_DECL(rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER, + RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src); static const struct snd_kcontrol_new rt5640_sto_adc_2_mux = SOC_DAPM_ENUM("Stereo ADC2 Mux", rt5640_stereo_adc2_enum); @@ -776,9 +773,8 @@ static const char * const rt5640_mono_adc_l1_src[] = { "Mono DAC MIXL", "ADCL" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src); static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux = SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum); @@ -787,9 +783,8 @@ static const char * const rt5640_mono_adc_l2_src[] = { "DMIC L1", "DMIC L2", "Mono DAC MIXL" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src); static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux = SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum); @@ -798,9 +793,8 @@ static const char * const rt5640_mono_adc_r1_src[] = { "Mono DAC MIXR", "ADCR" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src); static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux = SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum); @@ -809,9 +803,8 @@ static const char * const rt5640_mono_adc_r2_src[] = { "DMIC R1", "DMIC R2", "Mono DAC MIXR" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER, - RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src); +static SOC_ENUM_SINGLE_DECL(rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER, + RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src); static const struct snd_kcontrol_new rt5640_mono_adc_r2_mux = SOC_DAPM_ENUM("Mono ADC2 right source", rt5640_mono_adc_r2_enum); @@ -826,9 +819,9 @@ static int rt5640_dac_l2_values[] = { 3, }; -static const SOC_VALUE_ENUM_SINGLE_DECL( - rt5640_dac_l2_enum, RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT, - 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values); +static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_l2_enum, + RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT, + 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values); static const struct snd_kcontrol_new rt5640_dac_l2_mux = SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum); @@ -841,9 +834,9 @@ static int rt5640_dac_r2_values[] = { 0, }; -static const SOC_VALUE_ENUM_SINGLE_DECL( - rt5640_dac_r2_enum, RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT, - 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values); +static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dac_r2_enum, + RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT, + 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values); static const struct snd_kcontrol_new rt5640_dac_r2_mux = SOC_DAPM_ENUM("DAC2 right channel source", rt5640_dac_r2_enum); @@ -860,9 +853,10 @@ static int rt5640_dai_iis_map_values[] = { 7, }; -static const SOC_VALUE_ENUM_SINGLE_DECL( - rt5640_dai_iis_map_enum, RT5640_I2S1_SDP, RT5640_I2S_IF_SFT, - 0x7, rt5640_dai_iis_map, rt5640_dai_iis_map_values); +static SOC_VALUE_ENUM_SINGLE_DECL(rt5640_dai_iis_map_enum, + RT5640_I2S1_SDP, RT5640_I2S_IF_SFT, + 0x7, rt5640_dai_iis_map, + rt5640_dai_iis_map_values); static const struct snd_kcontrol_new rt5640_dai_mux = SOC_DAPM_VALUE_ENUM("DAI select", rt5640_dai_iis_map_enum); @@ -872,9 +866,8 @@ static const char * const rt5640_sdi_sel[] = { "IF1", "IF2" }; -static const SOC_ENUM_SINGLE_DECL( - rt5640_sdi_sel_enum, RT5640_I2S2_SDP, - RT5640_I2S2_SDI_SFT, rt5640_sdi_sel); +static SOC_ENUM_SINGLE_DECL(rt5640_sdi_sel_enum, RT5640_I2S2_SDP, + RT5640_I2S2_SDI_SFT, rt5640_sdi_sel); static const struct snd_kcontrol_new rt5640_sdi_mux = SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum); -- cgit v1.2.3 From 655e3652db7c5fd73d8b7949f24e9d7432cdb806 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:43:35 +0100 Subject: ASoC: ssm2518: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ssm2518.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index cc8debce752f..806f3d826ffb 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -169,19 +169,19 @@ static const char * const ssm2518_drc_hold_time_text[] = { "682.24 ms", "1364 ms", }; -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_attack_time_enum, SSM2518_REG_DRC_2, 4, ssm2518_drc_peak_detector_attack_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_peak_detector_release_time_enum, SSM2518_REG_DRC_2, 0, ssm2518_drc_peak_detector_release_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_attack_time_enum, SSM2518_REG_DRC_6, 4, ssm2518_drc_peak_detector_attack_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_decay_time_enum, SSM2518_REG_DRC_6, 0, ssm2518_drc_peak_detector_release_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_hold_time_enum, SSM2518_REG_DRC_7, 4, ssm2518_drc_hold_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_noise_gate_hold_time_enum, SSM2518_REG_DRC_7, 0, ssm2518_drc_hold_time_text); -static const SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum, +static SOC_ENUM_SINGLE_DECL(ssm2518_drc_rms_averaging_time_enum, SSM2518_REG_DRC_9, 0, ssm2518_drc_peak_detector_release_time_text); static const struct snd_kcontrol_new ssm2518_snd_controls[] = { -- cgit v1.2.3 From f281205422d8924bee025af79f222d0c79646ae7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:43:49 +0100 Subject: ASoC: sta529: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/sta529.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 40c07be9b581..f15b0e37274c 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -141,7 +141,7 @@ static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary", static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0); static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0); -static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); +static SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); static const struct snd_kcontrol_new sta529_snd_controls[] = { SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0, -- cgit v1.2.3 From da9f39f512eb2ac322d0ee340479d2739759919e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:44:00 +0100 Subject: ASoC: wm8804: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8804.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 9bc8206a6807..72d12bbe1a56 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -92,7 +92,7 @@ WM8804_REGULATOR_EVENT(0) WM8804_REGULATOR_EVENT(1) static const char *txsrc_text[] = { "S/PDIF RX", "AIF" }; -static const SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text); +static SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text); static const struct snd_kcontrol_new wm8804_snd_controls[] = { SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put), -- cgit v1.2.3 From 11a544bb2fe5bcacd20d2cdb9b792e035bd82eb2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:44:10 +0100 Subject: ASoC: wm8978: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8978.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index d8fc531c0e59..a9e2f465c331 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -117,21 +117,21 @@ static const char *wm8978_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"}; static const char *wm8978_alc3[] = {"ALC", "Limiter"}; static const char *wm8978_alc1[] = {"Off", "Right", "Left", "Both"}; -static const SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1, - wm8978_companding); -static const SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3, - wm8978_companding); -static const SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode); -static const SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1); -static const SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2); -static const SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3); -static const SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4); -static const SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5); -static const SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3); -static const SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1); +static SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1, + wm8978_companding); +static SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3, + wm8978_companding); +static SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode); +static SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1); +static SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw); +static SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2); +static SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw); +static SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3); +static SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw); +static SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4); +static SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5); +static SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3); +static SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1); static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -- cgit v1.2.3 From ae170688da955e9fb0536a117be63ee031cd1f6d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:44:56 +0100 Subject: ASoC: wm8983: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8983.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index aa41ba0dfff4..770e5a705851 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -205,49 +205,44 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; -static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, - alc_sel_text); +static SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, alc_sel_text); static const char *alc_mode_text[] = { "ALC", "Limiter" }; -static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, - alc_mode_text); +static SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, alc_mode_text); static const char *filter_mode_text[] = { "Audio", "Application" }; -static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, - filter_mode_text); +static SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, + filter_mode_text); static const char *eq_bw_text[] = { "Narrow", "Wide" }; static const char *eqmode_text[] = { "Capture", "Playback" }; -static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); +static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); static const char *eq1_cutoff_text[] = { "80Hz", "105Hz", "135Hz", "175Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, - eq1_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, + eq1_cutoff_text); static const char *eq2_cutoff_text[] = { "230Hz", "300Hz", "385Hz", "500Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, - eq2_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, eq2_cutoff_text); static const char *eq3_cutoff_text[] = { "650Hz", "850Hz", "1.1kHz", "1.4kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, - eq3_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, eq3_cutoff_text); static const char *eq4_cutoff_text[] = { "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, - eq4_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, eq4_cutoff_text); static const char *eq5_cutoff_text[] = { "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, - eq5_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, + eq5_cutoff_text); static const char *depth_3d_text[] = { "Off", @@ -267,8 +262,8 @@ static const char *depth_3d_text[] = { "93.3%", "100%" }; -static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, - depth_3d_text); +static SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, + depth_3d_text); static const struct snd_kcontrol_new wm8983_snd_controls[] = { SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL, -- cgit v1.2.3 From d0a4eec16adf3a528dbd1b52c3fc653a2bfee8c4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:45:08 +0100 Subject: ASoC: wm8985: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8985.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 271b517911a4..d786f2b39764 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -226,52 +226,48 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; -static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7, - alc_sel_text); +static SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7, alc_sel_text); static const char *alc_mode_text[] = { "ALC", "Limiter" }; -static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8, - alc_mode_text); +static SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8, alc_mode_text); static const char *filter_mode_text[] = { "Audio", "Application" }; -static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7, - filter_mode_text); +static SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7, + filter_mode_text); static const char *eq_bw_text[] = { "Narrow", "Wide" }; static const char *eqmode_text[] = { "Capture", "Playback" }; -static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); +static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); static const char *eq1_cutoff_text[] = { "80Hz", "105Hz", "135Hz", "175Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5, - eq1_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5, + eq1_cutoff_text); static const char *eq2_cutoff_text[] = { "230Hz", "300Hz", "385Hz", "500Hz" }; -static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5, - eq2_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5, eq2_cutoff_text); static const char *eq3_cutoff_text[] = { "650Hz", "850Hz", "1.1kHz", "1.4kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5, - eq3_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5, + eq3_cutoff_text); static const char *eq4_cutoff_text[] = { "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5, - eq4_cutoff_text); +static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text); +static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5, eq4_cutoff_text); static const char *eq5_cutoff_text[] = { "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" }; -static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5, +static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5, eq5_cutoff_text); static const char *speaker_mode_text[] = { "Class A/B", "Class D" }; -static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); +static SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); static const char *depth_3d_text[] = { "Off", @@ -291,8 +287,7 @@ static const char *depth_3d_text[] = { "93.3%", "100%" }; -static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, - depth_3d_text); +static SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, depth_3d_text); static const struct snd_kcontrol_new wm8985_snd_controls[] = { SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL, -- cgit v1.2.3 From 48e50ce37fcf4c376845d1c42177eeb1601f99ad Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:45:18 +0100 Subject: ASoC: wm8995: Remove superfluous const As SOC_ENUM_SINGLE_DECL() itself contains const modifier now, we can reduce const from its users. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8995.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 4300caff1783..dcd1e72c19cf 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -423,24 +423,24 @@ static const char *in1l_text[] = { "Differential", "Single-ended IN1LN", "Single-ended IN1LP" }; -static const SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL, - 2, in1l_text); +static SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL, + 2, in1l_text); static const char *in1r_text[] = { "Differential", "Single-ended IN1RN", "Single-ended IN1RP" }; -static const SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL, - 0, in1r_text); +static SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL, + 0, in1r_text); static const char *dmic_src_text[] = { "DMICDAT1", "DMICDAT2", "DMICDAT3" }; -static const SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5, - 8, dmic_src_text); -static const SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5, - 6, dmic_src_text); +static SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5, + 8, dmic_src_text); +static SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5, + 6, dmic_src_text); static const struct snd_kcontrol_new wm8995_snd_controls[] = { SOC_DOUBLE_R_TLV("DAC1 Volume", WM8995_DAC1_LEFT_VOLUME, @@ -899,14 +899,14 @@ static const char *spk_src_text[] = { "DAC1L", "DAC1R", "DAC2L", "DAC2R" }; -static const SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2, - 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1, + 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1, + 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2, + 0, spk_src_text); +static SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2, + 0, spk_src_text); static const struct snd_kcontrol_new spk1l_mux = SOC_DAPM_ENUM("SPK1L SRC", spk1l_src_enum); -- cgit v1.2.3 From 27ca2c30f4fec73d53f727fe2fe729e16d9a43b2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:01:43 +0100 Subject: ASoC: arizona: Fix wrong number of items in enum ctls arizona codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 71 ++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 31 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index e4295fee8f13..a32b84ac03f6 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -542,67 +542,76 @@ static const char *arizona_vol_ramp_text[] = { "15ms/6dB", "30ms/6dB", }; -const struct soc_enum arizona_in_vd_ramp = - SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, - ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_in_vd_ramp, + ARIZONA_INPUT_VOLUME_RAMP, + ARIZONA_IN_VD_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_in_vd_ramp); -const struct soc_enum arizona_in_vi_ramp = - SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, - ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_in_vi_ramp, + ARIZONA_INPUT_VOLUME_RAMP, + ARIZONA_IN_VI_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_in_vi_ramp); -const struct soc_enum arizona_out_vd_ramp = - SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, - ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_out_vd_ramp, + ARIZONA_OUTPUT_VOLUME_RAMP, + ARIZONA_OUT_VD_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_out_vd_ramp); -const struct soc_enum arizona_out_vi_ramp = - SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, - ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); +SOC_ENUM_SINGLE_DECL(arizona_out_vi_ramp, + ARIZONA_OUTPUT_VOLUME_RAMP, + ARIZONA_OUT_VI_RAMP_SHIFT, + arizona_vol_ramp_text); EXPORT_SYMBOL_GPL(arizona_out_vi_ramp); static const char *arizona_lhpf_mode_text[] = { "Low-pass", "High-pass" }; -const struct soc_enum arizona_lhpf1_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF1_1, ARIZONA_LHPF1_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf1_mode, + ARIZONA_HPLPF1_1, + ARIZONA_LHPF1_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf1_mode); -const struct soc_enum arizona_lhpf2_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF2_1, ARIZONA_LHPF2_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf2_mode, + ARIZONA_HPLPF2_1, + ARIZONA_LHPF2_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf2_mode); -const struct soc_enum arizona_lhpf3_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF3_1, ARIZONA_LHPF3_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf3_mode, + ARIZONA_HPLPF3_1, + ARIZONA_LHPF3_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf3_mode); -const struct soc_enum arizona_lhpf4_mode = - SOC_ENUM_SINGLE(ARIZONA_HPLPF4_1, ARIZONA_LHPF4_MODE_SHIFT, 2, - arizona_lhpf_mode_text); +SOC_ENUM_SINGLE_DECL(arizona_lhpf4_mode, + ARIZONA_HPLPF4_1, + ARIZONA_LHPF4_MODE_SHIFT, + arizona_lhpf_mode_text); EXPORT_SYMBOL_GPL(arizona_lhpf4_mode); static const char *arizona_ng_hold_text[] = { "30ms", "120ms", "250ms", "500ms", }; -const struct soc_enum arizona_ng_hold = - SOC_ENUM_SINGLE(ARIZONA_NOISE_GATE_CONTROL, ARIZONA_NGATE_HOLD_SHIFT, - 4, arizona_ng_hold_text); +SOC_ENUM_SINGLE_DECL(arizona_ng_hold, + ARIZONA_NOISE_GATE_CONTROL, + ARIZONA_NGATE_HOLD_SHIFT, + arizona_ng_hold_text); EXPORT_SYMBOL_GPL(arizona_ng_hold); static const char * const arizona_in_hpf_cut_text[] = { "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz" }; -const struct soc_enum arizona_in_hpf_cut_enum = - SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT, - ARRAY_SIZE(arizona_in_hpf_cut_text), - arizona_in_hpf_cut_text); +SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum, + ARIZONA_HPF_CONTROL, + ARIZONA_IN_HPF_CUT_SHIFT, + arizona_in_hpf_cut_text); EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum); static const char * const arizona_in_dmic_osr_text[] = { -- cgit v1.2.3 From 1c38450b9fe52a86da7f4fd2a2c97935b71f2b62 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:58:45 +0100 Subject: ASoC: adau1373: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/adau1373.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index eb836ed5271f..83c0acd5f67d 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -576,8 +576,8 @@ static const char *adau1373_decimator_text[] = { "DMIC1", }; -static const struct soc_enum adau1373_decimator_enum = - SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text); +static SOC_ENUM_SINGLE_DECL(adau1373_decimator_enum, + 0, 0, adau1373_decimator_text); static const struct snd_kcontrol_new adau1373_decimator_mux = SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); -- cgit v1.2.3 From 98bf1b5e788e63536705dcc418cc97b36481067e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:00:29 +0100 Subject: ASoC: alc5623: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/alc5623.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index d3036283482a..ba61c07ebbb2 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -228,32 +228,37 @@ static const char *alc5623_aux_out_input_sel[] = { "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"}; /* auxout output mux */ -static const struct soc_enum alc5623_aux_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_aux_out_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 6, + alc5623_aux_out_input_sel); static const struct snd_kcontrol_new alc5623_auxout_mux_controls = SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum); /* speaker output mux */ -static const struct soc_enum alc5623_spkout_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_spkout_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 10, + alc5623_spkout_input_sel); static const struct snd_kcontrol_new alc5623_spkout_mux_controls = SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum); /* headphone left output mux */ -static const struct soc_enum alc5623_hpl_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_hpl_out_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 9, + alc5623_hpl_out_input_sel); static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls = SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum); /* headphone right output mux */ -static const struct soc_enum alc5623_hpr_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_hpr_out_input_enum, + ALC5623_OUTPUT_MIXER_CTRL, 8, + alc5623_hpr_out_input_sel); static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls = SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum); /* speaker output N select */ -static const struct soc_enum alc5623_spk_n_sour_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel); +static SOC_ENUM_SINGLE_DECL(alc5623_spk_n_sour_enum, + ALC5623_OUTPUT_MIXER_CTRL, 14, + alc5623_spk_n_sour_sel); static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls = SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum); @@ -338,8 +343,9 @@ SND_SOC_DAPM_VMID("Vmid"), }; static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"}; -static const struct soc_enum alc5623_amp_enum = - SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names); +static SOC_ENUM_SINGLE_DECL(alc5623_amp_enum, + ALC5623_OUTPUT_MIXER_CTRL, 13, + alc5623_amp_names); static const struct snd_kcontrol_new alc5623_amp_mux_controls = SOC_DAPM_ENUM("Route", alc5623_amp_enum); -- cgit v1.2.3 From 4682a0a2b8e5d9633727276455f445e0b402767c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:05:01 +0100 Subject: ASoC: cs42l52: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Acked-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l52.c | 92 ++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 49 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 0bac6d5a4ac8..be455ea5f2fe 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -210,13 +210,11 @@ static const char * const cs42l52_adca_text[] = { static const char * const cs42l52_adcb_text[] = { "Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"}; -static const struct soc_enum adca_enum = - SOC_ENUM_SINGLE(CS42L52_ADC_PGA_A, 5, - ARRAY_SIZE(cs42l52_adca_text), cs42l52_adca_text); +static SOC_ENUM_SINGLE_DECL(adca_enum, + CS42L52_ADC_PGA_A, 5, cs42l52_adca_text); -static const struct soc_enum adcb_enum = - SOC_ENUM_SINGLE(CS42L52_ADC_PGA_B, 5, - ARRAY_SIZE(cs42l52_adcb_text), cs42l52_adcb_text); +static SOC_ENUM_SINGLE_DECL(adcb_enum, + CS42L52_ADC_PGA_B, 5, cs42l52_adcb_text); static const struct snd_kcontrol_new adca_mux = SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum); @@ -229,26 +227,22 @@ static const char * const mic_bias_level_text[] = { "0.8 +VA", "0.83 +VA", "0.91 +VA" }; -static const struct soc_enum mic_bias_level_enum = - SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0, - ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text); +static SOC_ENUM_SINGLE_DECL(mic_bias_level_enum, + CS42L52_IFACE_CTL2, 0, mic_bias_level_text); static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" }; -static const struct soc_enum mica_enum = - SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5, - ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); +static SOC_ENUM_SINGLE_DECL(mica_enum, + CS42L52_MICA_CTL, 5, cs42l52_mic_text); -static const struct soc_enum micb_enum = - SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5, - ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text); +static SOC_ENUM_SINGLE_DECL(micb_enum, + CS42L52_MICB_CTL, 5, cs42l52_mic_text); static const char * const digital_output_mux_text[] = {"ADC", "DSP"}; -static const struct soc_enum digital_output_mux_enum = - SOC_ENUM_SINGLE(CS42L52_ADC_MISC_CTL, 6, - ARRAY_SIZE(digital_output_mux_text), - digital_output_mux_text); +static SOC_ENUM_SINGLE_DECL(digital_output_mux_enum, + CS42L52_ADC_MISC_CTL, 6, + digital_output_mux_text); static const struct snd_kcontrol_new digital_output_mux = SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum); @@ -258,18 +252,18 @@ static const char * const hp_gain_num_text[] = { "0.7099", "0.8399", "1.000", "1.1430" }; -static const struct soc_enum hp_gain_enum = - SOC_ENUM_SINGLE(CS42L52_PB_CTL1, 5, - ARRAY_SIZE(hp_gain_num_text), hp_gain_num_text); +static SOC_ENUM_SINGLE_DECL(hp_gain_enum, + CS42L52_PB_CTL1, 5, + hp_gain_num_text); static const char * const beep_pitch_text[] = { "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5", "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7" }; -static const struct soc_enum beep_pitch_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 4, - ARRAY_SIZE(beep_pitch_text), beep_pitch_text); +static SOC_ENUM_SINGLE_DECL(beep_pitch_enum, + CS42L52_BEEP_FREQ, 4, + beep_pitch_text); static const char * const beep_ontime_text[] = { "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s", @@ -277,66 +271,66 @@ static const char * const beep_ontime_text[] = { "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s" }; -static const struct soc_enum beep_ontime_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_FREQ, 0, - ARRAY_SIZE(beep_ontime_text), beep_ontime_text); +static SOC_ENUM_SINGLE_DECL(beep_ontime_enum, + CS42L52_BEEP_FREQ, 0, + beep_ontime_text); static const char * const beep_offtime_text[] = { "1.23 s", "2.58 s", "3.90 s", "5.20 s", "6.60 s", "8.05 s", "9.35 s", "10.80 s" }; -static const struct soc_enum beep_offtime_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_VOL, 5, - ARRAY_SIZE(beep_offtime_text), beep_offtime_text); +static SOC_ENUM_SINGLE_DECL(beep_offtime_enum, + CS42L52_BEEP_VOL, 5, + beep_offtime_text); static const char * const beep_config_text[] = { "Off", "Single", "Multiple", "Continuous" }; -static const struct soc_enum beep_config_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 6, - ARRAY_SIZE(beep_config_text), beep_config_text); +static SOC_ENUM_SINGLE_DECL(beep_config_enum, + CS42L52_BEEP_TONE_CTL, 6, + beep_config_text); static const char * const beep_bass_text[] = { "50 Hz", "100 Hz", "200 Hz", "250 Hz" }; -static const struct soc_enum beep_bass_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 1, - ARRAY_SIZE(beep_bass_text), beep_bass_text); +static SOC_ENUM_SINGLE_DECL(beep_bass_enum, + CS42L52_BEEP_TONE_CTL, 1, + beep_bass_text); static const char * const beep_treble_text[] = { "5 kHz", "7 kHz", "10 kHz", " 15 kHz" }; -static const struct soc_enum beep_treble_enum = - SOC_ENUM_SINGLE(CS42L52_BEEP_TONE_CTL, 3, - ARRAY_SIZE(beep_treble_text), beep_treble_text); +static SOC_ENUM_SINGLE_DECL(beep_treble_enum, + CS42L52_BEEP_TONE_CTL, 3, + beep_treble_text); static const char * const ng_threshold_text[] = { "-34dB", "-37dB", "-40dB", "-43dB", "-46dB", "-52dB", "-58dB", "-64dB" }; -static const struct soc_enum ng_threshold_enum = - SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 2, - ARRAY_SIZE(ng_threshold_text), ng_threshold_text); +static SOC_ENUM_SINGLE_DECL(ng_threshold_enum, + CS42L52_NOISE_GATE_CTL, 2, + ng_threshold_text); static const char * const cs42l52_ng_delay_text[] = { "50ms", "100ms", "150ms", "200ms"}; -static const struct soc_enum ng_delay_enum = - SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 0, - ARRAY_SIZE(cs42l52_ng_delay_text), cs42l52_ng_delay_text); +static SOC_ENUM_SINGLE_DECL(ng_delay_enum, + CS42L52_NOISE_GATE_CTL, 0, + cs42l52_ng_delay_text); static const char * const cs42l52_ng_type_text[] = { "Apply Specific", "Apply All" }; -static const struct soc_enum ng_type_enum = - SOC_ENUM_SINGLE(CS42L52_NOISE_GATE_CTL, 6, - ARRAY_SIZE(cs42l52_ng_type_text), cs42l52_ng_type_text); +static SOC_ENUM_SINGLE_DECL(ng_type_enum, + CS42L52_NOISE_GATE_CTL, 6, + cs42l52_ng_type_text); static const char * const left_swap_text[] = { "Left", "LR 2", "Right"}; -- cgit v1.2.3 From e34042d850a7117b9acafeabd50287d5d8e61849 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:06:00 +0100 Subject: ASoC: da7210: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/da7210.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index e62e294a8033..01e55fc72307 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -307,29 +307,29 @@ static const char * const da7210_hpf_cutoff_txt[] = { "Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi" }; -static const struct soc_enum da7210_dac_hpf_cutoff = - SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_dac_hpf_cutoff, + DA7210_DAC_HPF, 0, da7210_hpf_cutoff_txt); -static const struct soc_enum da7210_adc_hpf_cutoff = - SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_adc_hpf_cutoff, + DA7210_ADC_HPF, 0, da7210_hpf_cutoff_txt); /* ADC and DAC voice (8kHz) high pass cutoff value */ static const char * const da7210_vf_cutoff_txt[] = { "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da7210_dac_vf_cutoff = - SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_dac_vf_cutoff, + DA7210_DAC_HPF, 4, da7210_vf_cutoff_txt); -static const struct soc_enum da7210_adc_vf_cutoff = - SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da7210_adc_vf_cutoff, + DA7210_ADC_HPF, 4, da7210_vf_cutoff_txt); static const char *da7210_hp_mode_txt[] = { "Class H", "Class G" }; -static const struct soc_enum da7210_hp_mode_sel = - SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt); +static SOC_ENUM_SINGLE_DECL(da7210_hp_mode_sel, + DA7210_HP_CFG, 0, da7210_hp_mode_txt); /* ALC can be enabled only if noise suppression is disabled */ static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol, -- cgit v1.2.3 From c99f8b216c39b1fbeb8b6830b95e461db551afa9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:06:47 +0100 Subject: ASoC: da7213: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/da7213.c | 151 ++++++++++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 71 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 0c77e7ad7423..439d10387f10 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -63,30 +63,30 @@ static const char * const da7213_voice_hpf_corner_txt[] = { "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da7213_dac_voice_hpf_corner = - SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT, - DA7213_VOICE_HPF_CORNER_MAX, - da7213_voice_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_voice_hpf_corner, + DA7213_DAC_FILTERS1, + DA7213_VOICE_HPF_CORNER_SHIFT, + da7213_voice_hpf_corner_txt); -static const struct soc_enum da7213_adc_voice_hpf_corner = - SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_VOICE_HPF_CORNER_SHIFT, - DA7213_VOICE_HPF_CORNER_MAX, - da7213_voice_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_adc_voice_hpf_corner, + DA7213_ADC_FILTERS1, + DA7213_VOICE_HPF_CORNER_SHIFT, + da7213_voice_hpf_corner_txt); /* ADC and DAC high pass filter cutoff value */ static const char * const da7213_audio_hpf_corner_txt[] = { "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" }; -static const struct soc_enum da7213_dac_audio_hpf_corner = - SOC_ENUM_SINGLE(DA7213_DAC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT, - DA7213_AUDIO_HPF_CORNER_MAX, - da7213_audio_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_audio_hpf_corner, + DA7213_DAC_FILTERS1 + , DA7213_AUDIO_HPF_CORNER_SHIFT, + da7213_audio_hpf_corner_txt); -static const struct soc_enum da7213_adc_audio_hpf_corner = - SOC_ENUM_SINGLE(DA7213_ADC_FILTERS1, DA7213_AUDIO_HPF_CORNER_SHIFT, - DA7213_AUDIO_HPF_CORNER_MAX, - da7213_audio_hpf_corner_txt); +static SOC_ENUM_SINGLE_DECL(da7213_adc_audio_hpf_corner, + DA7213_ADC_FILTERS1, + DA7213_AUDIO_HPF_CORNER_SHIFT, + da7213_audio_hpf_corner_txt); /* Gain ramping rate value */ static const char * const da7213_gain_ramp_rate_txt[] = { @@ -94,52 +94,50 @@ static const char * const da7213_gain_ramp_rate_txt[] = { "nominal rate / 32" }; -static const struct soc_enum da7213_gain_ramp_rate = - SOC_ENUM_SINGLE(DA7213_GAIN_RAMP_CTRL, DA7213_GAIN_RAMP_RATE_SHIFT, - DA7213_GAIN_RAMP_RATE_MAX, da7213_gain_ramp_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_gain_ramp_rate, + DA7213_GAIN_RAMP_CTRL, + DA7213_GAIN_RAMP_RATE_SHIFT, + da7213_gain_ramp_rate_txt); /* DAC noise gate setup time value */ static const char * const da7213_dac_ng_setup_time_txt[] = { "256 samples", "512 samples", "1024 samples", "2048 samples" }; -static const struct soc_enum da7213_dac_ng_setup_time = - SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, - DA7213_DAC_NG_SETUP_TIME_SHIFT, - DA7213_DAC_NG_SETUP_TIME_MAX, - da7213_dac_ng_setup_time_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_setup_time, + DA7213_DAC_NG_SETUP_TIME, + DA7213_DAC_NG_SETUP_TIME_SHIFT, + da7213_dac_ng_setup_time_txt); /* DAC noise gate rampup rate value */ static const char * const da7213_dac_ng_rampup_txt[] = { "0.02 ms/dB", "0.16 ms/dB" }; -static const struct soc_enum da7213_dac_ng_rampup_rate = - SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, - DA7213_DAC_NG_RAMPUP_RATE_SHIFT, - DA7213_DAC_NG_RAMP_RATE_MAX, - da7213_dac_ng_rampup_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampup_rate, + DA7213_DAC_NG_SETUP_TIME, + DA7213_DAC_NG_RAMPUP_RATE_SHIFT, + da7213_dac_ng_rampup_txt); /* DAC noise gate rampdown rate value */ static const char * const da7213_dac_ng_rampdown_txt[] = { "0.64 ms/dB", "20.48 ms/dB" }; -static const struct soc_enum da7213_dac_ng_rampdown_rate = - SOC_ENUM_SINGLE(DA7213_DAC_NG_SETUP_TIME, - DA7213_DAC_NG_RAMPDN_RATE_SHIFT, - DA7213_DAC_NG_RAMP_RATE_MAX, - da7213_dac_ng_rampdown_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_ng_rampdown_rate, + DA7213_DAC_NG_SETUP_TIME, + DA7213_DAC_NG_RAMPDN_RATE_SHIFT, + da7213_dac_ng_rampdown_txt); /* DAC soft mute rate value */ static const char * const da7213_dac_soft_mute_rate_txt[] = { "1", "2", "4", "8", "16", "32", "64" }; -static const struct soc_enum da7213_dac_soft_mute_rate = - SOC_ENUM_SINGLE(DA7213_DAC_FILTERS5, DA7213_DAC_SOFTMUTE_RATE_SHIFT, - DA7213_DAC_SOFTMUTE_RATE_MAX, - da7213_dac_soft_mute_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_soft_mute_rate, + DA7213_DAC_FILTERS5, + DA7213_DAC_SOFTMUTE_RATE_SHIFT, + da7213_dac_soft_mute_rate_txt); /* ALC Attack Rate select */ static const char * const da7213_alc_attack_rate_txt[] = { @@ -147,9 +145,10 @@ static const char * const da7213_alc_attack_rate_txt[] = { "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da7213_alc_attack_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_ATTACK_SHIFT, - DA7213_ALC_ATTACK_MAX, da7213_alc_attack_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_attack_rate, + DA7213_ALC_CTRL2, + DA7213_ALC_ATTACK_SHIFT, + da7213_alc_attack_rate_txt); /* ALC Release Rate select */ static const char * const da7213_alc_release_rate_txt[] = { @@ -157,9 +156,10 @@ static const char * const da7213_alc_release_rate_txt[] = { "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da7213_alc_release_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL2, DA7213_ALC_RELEASE_SHIFT, - DA7213_ALC_RELEASE_MAX, da7213_alc_release_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_release_rate, + DA7213_ALC_CTRL2, + DA7213_ALC_RELEASE_SHIFT, + da7213_alc_release_rate_txt); /* ALC Hold Time select */ static const char * const da7213_alc_hold_time_txt[] = { @@ -168,22 +168,25 @@ static const char * const da7213_alc_hold_time_txt[] = { "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" }; -static const struct soc_enum da7213_alc_hold_time = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_HOLD_SHIFT, - DA7213_ALC_HOLD_MAX, da7213_alc_hold_time_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_hold_time, + DA7213_ALC_CTRL3, + DA7213_ALC_HOLD_SHIFT, + da7213_alc_hold_time_txt); /* ALC Input Signal Tracking rate select */ static const char * const da7213_alc_integ_rate_txt[] = { "1/4", "1/16", "1/256", "1/65536" }; -static const struct soc_enum da7213_alc_integ_attack_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_ATTACK_SHIFT, - DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_attack_rate, + DA7213_ALC_CTRL3, + DA7213_ALC_INTEG_ATTACK_SHIFT, + da7213_alc_integ_rate_txt); -static const struct soc_enum da7213_alc_integ_release_rate = - SOC_ENUM_SINGLE(DA7213_ALC_CTRL3, DA7213_ALC_INTEG_RELEASE_SHIFT, - DA7213_ALC_INTEG_MAX, da7213_alc_integ_rate_txt); +static SOC_ENUM_SINGLE_DECL(da7213_alc_integ_release_rate, + DA7213_ALC_CTRL3, + DA7213_ALC_INTEG_RELEASE_SHIFT, + da7213_alc_integ_rate_txt); /* @@ -584,15 +587,17 @@ static const char * const da7213_mic_amp_in_sel_txt[] = { "Differential", "MIC_P", "MIC_N" }; -static const struct soc_enum da7213_mic_1_amp_in_sel = - SOC_ENUM_SINGLE(DA7213_MIC_1_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT, - DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt); +static SOC_ENUM_SINGLE_DECL(da7213_mic_1_amp_in_sel, + DA7213_MIC_1_CTRL, + DA7213_MIC_AMP_IN_SEL_SHIFT, + da7213_mic_amp_in_sel_txt); static const struct snd_kcontrol_new da7213_mic_1_amp_in_sel_mux = SOC_DAPM_ENUM("Mic 1 Amp Source MUX", da7213_mic_1_amp_in_sel); -static const struct soc_enum da7213_mic_2_amp_in_sel = - SOC_ENUM_SINGLE(DA7213_MIC_2_CTRL, DA7213_MIC_AMP_IN_SEL_SHIFT, - DA7213_MIC_AMP_IN_SEL_MAX, da7213_mic_amp_in_sel_txt); +static SOC_ENUM_SINGLE_DECL(da7213_mic_2_amp_in_sel, + DA7213_MIC_2_CTRL, + DA7213_MIC_AMP_IN_SEL_SHIFT, + da7213_mic_amp_in_sel_txt); static const struct snd_kcontrol_new da7213_mic_2_amp_in_sel_mux = SOC_DAPM_ENUM("Mic 2 Amp Source MUX", da7213_mic_2_amp_in_sel); @@ -601,15 +606,17 @@ static const char * const da7213_dai_src_txt[] = { "ADC Left", "ADC Right", "DAI Input Left", "DAI Input Right" }; -static const struct soc_enum da7213_dai_l_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_L_SRC_SHIFT, - DA7213_DAI_SRC_MAX, da7213_dai_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dai_l_src, + DA7213_DIG_ROUTING_DAI, + DA7213_DAI_L_SRC_SHIFT, + da7213_dai_src_txt); static const struct snd_kcontrol_new da7213_dai_l_src_mux = SOC_DAPM_ENUM("DAI Left Source MUX", da7213_dai_l_src); -static const struct soc_enum da7213_dai_r_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAI, DA7213_DAI_R_SRC_SHIFT, - DA7213_DAI_SRC_MAX, da7213_dai_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dai_r_src, + DA7213_DIG_ROUTING_DAI, + DA7213_DAI_R_SRC_SHIFT, + da7213_dai_src_txt); static const struct snd_kcontrol_new da7213_dai_r_src_mux = SOC_DAPM_ENUM("DAI Right Source MUX", da7213_dai_r_src); @@ -619,15 +626,17 @@ static const char * const da7213_dac_src_txt[] = { "DAI Input Right" }; -static const struct soc_enum da7213_dac_l_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_L_SRC_SHIFT, - DA7213_DAC_SRC_MAX, da7213_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_l_src, + DA7213_DIG_ROUTING_DAC, + DA7213_DAC_L_SRC_SHIFT, + da7213_dac_src_txt); static const struct snd_kcontrol_new da7213_dac_l_src_mux = SOC_DAPM_ENUM("DAC Left Source MUX", da7213_dac_l_src); -static const struct soc_enum da7213_dac_r_src = - SOC_ENUM_SINGLE(DA7213_DIG_ROUTING_DAC, DA7213_DAC_R_SRC_SHIFT, - DA7213_DAC_SRC_MAX, da7213_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da7213_dac_r_src, + DA7213_DIG_ROUTING_DAC, + DA7213_DAC_R_SRC_SHIFT, + da7213_dac_src_txt); static const struct snd_kcontrol_new da7213_dac_r_src_mux = SOC_DAPM_ENUM("DAC Right Source MUX", da7213_dac_r_src); -- cgit v1.2.3 From 6415e307b1d270e4e5f7ee7bd9aac4ac4f1daf65 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:09:52 +0100 Subject: ASoC: lm4857: Use SOC_ENUM_SINGLE_EXT_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/lm4857.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index 0e5743ea79df..4f048db9f55f 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c @@ -101,8 +101,7 @@ static const char *lm4857_mode[] = { "Headphone", }; -static const struct soc_enum lm4857_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode); +static SOC_ENUM_SINGLE_EXT_DECL(lm4857_mode_enum, lm4857_mode); static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = { SND_SOC_DAPM_INPUT("IN"), -- cgit v1.2.3 From 9839ce9360c4410bdf30d2670a2329c444160f02 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:07:25 +0100 Subject: ASoC: da9055: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/da9055.c | 84 +++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index be31f3cfd46e..f118daa91234 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -323,22 +323,22 @@ static const char * const da9055_hpf_cutoff_txt[] = { "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" }; -static const struct soc_enum da9055_dac_hpf_cutoff = - SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_hpf_cutoff, + DA9055_DAC_FILTERS1, 4, da9055_hpf_cutoff_txt); -static const struct soc_enum da9055_adc_hpf_cutoff = - SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_adc_hpf_cutoff, + DA9055_ADC_FILTERS1, 4, da9055_hpf_cutoff_txt); /* ADC and DAC voice mode (8kHz) high pass cutoff value */ static const char * const da9055_vf_cutoff_txt[] = { "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da9055_dac_vf_cutoff = - SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_vf_cutoff, + DA9055_DAC_FILTERS1, 0, da9055_vf_cutoff_txt); -static const struct soc_enum da9055_adc_vf_cutoff = - SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); +static SOC_ENUM_SINGLE_DECL(da9055_adc_vf_cutoff, + DA9055_ADC_FILTERS1, 0, da9055_vf_cutoff_txt); /* Gain ramping rate value */ static const char * const da9055_gain_ramping_txt[] = { @@ -346,44 +346,44 @@ static const char * const da9055_gain_ramping_txt[] = { "nominal rate / 8" }; -static const struct soc_enum da9055_gain_ramping_rate = - SOC_ENUM_SINGLE(DA9055_GAIN_RAMP_CTRL, 0, 4, da9055_gain_ramping_txt); +static SOC_ENUM_SINGLE_DECL(da9055_gain_ramping_rate, + DA9055_GAIN_RAMP_CTRL, 0, da9055_gain_ramping_txt); /* DAC noise gate setup time value */ static const char * const da9055_dac_ng_setup_time_txt[] = { "256 samples", "512 samples", "1024 samples", "2048 samples" }; -static const struct soc_enum da9055_dac_ng_setup_time = - SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 0, 4, - da9055_dac_ng_setup_time_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_setup_time, + DA9055_DAC_NG_SETUP_TIME, 0, + da9055_dac_ng_setup_time_txt); /* DAC noise gate rampup rate value */ static const char * const da9055_dac_ng_rampup_txt[] = { "0.02 ms/dB", "0.16 ms/dB" }; -static const struct soc_enum da9055_dac_ng_rampup_rate = - SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 2, 2, - da9055_dac_ng_rampup_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampup_rate, + DA9055_DAC_NG_SETUP_TIME, 2, + da9055_dac_ng_rampup_txt); /* DAC noise gate rampdown rate value */ static const char * const da9055_dac_ng_rampdown_txt[] = { "0.64 ms/dB", "20.48 ms/dB" }; -static const struct soc_enum da9055_dac_ng_rampdown_rate = - SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 3, 2, - da9055_dac_ng_rampdown_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_ng_rampdown_rate, + DA9055_DAC_NG_SETUP_TIME, 3, + da9055_dac_ng_rampdown_txt); /* DAC soft mute rate value */ static const char * const da9055_dac_soft_mute_rate_txt[] = { "1", "2", "4", "8", "16", "32", "64" }; -static const struct soc_enum da9055_dac_soft_mute_rate = - SOC_ENUM_SINGLE(DA9055_DAC_FILTERS5, 4, 7, - da9055_dac_soft_mute_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_soft_mute_rate, + DA9055_DAC_FILTERS5, 4, + da9055_dac_soft_mute_rate_txt); /* DAC routing select */ static const char * const da9055_dac_src_txt[] = { @@ -391,40 +391,40 @@ static const char * const da9055_dac_src_txt[] = { "AIF input right" }; -static const struct soc_enum da9055_dac_l_src = - SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 0, 4, da9055_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_l_src, + DA9055_DIG_ROUTING_DAC, 0, da9055_dac_src_txt); -static const struct soc_enum da9055_dac_r_src = - SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 4, 4, da9055_dac_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_dac_r_src, + DA9055_DIG_ROUTING_DAC, 4, da9055_dac_src_txt); /* MIC PGA Left source select */ static const char * const da9055_mic_l_src_txt[] = { "MIC1_P_N", "MIC1_P", "MIC1_N", "MIC2_L" }; -static const struct soc_enum da9055_mic_l_src = - SOC_ENUM_SINGLE(DA9055_MIXIN_L_SELECT, 4, 4, da9055_mic_l_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_mic_l_src, + DA9055_MIXIN_L_SELECT, 4, da9055_mic_l_src_txt); /* MIC PGA Right source select */ static const char * const da9055_mic_r_src_txt[] = { "MIC2_R_L", "MIC2_R", "MIC2_L" }; -static const struct soc_enum da9055_mic_r_src = - SOC_ENUM_SINGLE(DA9055_MIXIN_R_SELECT, 4, 3, da9055_mic_r_src_txt); +static SOC_ENUM_SINGLE_DECL(da9055_mic_r_src, + DA9055_MIXIN_R_SELECT, 4, da9055_mic_r_src_txt); /* ALC Input Signal Tracking rate select */ static const char * const da9055_signal_tracking_rate_txt[] = { "1/4", "1/16", "1/256", "1/65536" }; -static const struct soc_enum da9055_integ_attack_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 4, 4, - da9055_signal_tracking_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_integ_attack_rate, + DA9055_ALC_CTRL3, 4, + da9055_signal_tracking_rate_txt); -static const struct soc_enum da9055_integ_release_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 6, 4, - da9055_signal_tracking_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_integ_release_rate, + DA9055_ALC_CTRL3, 6, + da9055_signal_tracking_rate_txt); /* ALC Attack Rate select */ static const char * const da9055_attack_rate_txt[] = { @@ -432,8 +432,8 @@ static const char * const da9055_attack_rate_txt[] = { "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da9055_attack_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 0, 13, da9055_attack_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_attack_rate, + DA9055_ALC_CTRL2, 0, da9055_attack_rate_txt); /* ALC Release Rate select */ static const char * const da9055_release_rate_txt[] = { @@ -441,8 +441,8 @@ static const char * const da9055_release_rate_txt[] = { "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" }; -static const struct soc_enum da9055_release_rate = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 4, 11, da9055_release_rate_txt); +static SOC_ENUM_SINGLE_DECL(da9055_release_rate, + DA9055_ALC_CTRL2, 4, da9055_release_rate_txt); /* ALC Hold Time select */ static const char * const da9055_hold_time_txt[] = { @@ -451,8 +451,8 @@ static const char * const da9055_hold_time_txt[] = { "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" }; -static const struct soc_enum da9055_hold_time = - SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 0, 16, da9055_hold_time_txt); +static SOC_ENUM_SINGLE_DECL(da9055_hold_time, + DA9055_ALC_CTRL3, 0, da9055_hold_time_txt); static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val) { -- cgit v1.2.3 From a0628934d6d3fcca5588fd9617270f63c5387f1b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:12:32 +0100 Subject: ASoC: max98088: Use SOC_*_ENUM_SINGLE_DECL() Just replace with the helper macros. No functional change at all. Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/max98088.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index ee660e2d3df3..25ce1355b8fb 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -597,28 +597,27 @@ static const unsigned int max98088_exmode_values[] = { 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32 }; -static const struct soc_enum max98088_exmode_enum = - SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127, - ARRAY_SIZE(max98088_exmode_texts), - max98088_exmode_texts, - max98088_exmode_values); +static SOC_VALUE_ENUM_SINGLE_DECL(max98088_exmode_enum, + M98088_REG_41_SPKDHP, 0, 127, + max98088_exmode_texts, + max98088_exmode_values); static const char *max98088_ex_thresh[] = { /* volts PP */ "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; -static const struct soc_enum max98088_ex_thresh_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8, - max98088_ex_thresh), -}; +static SOC_ENUM_SINGLE_DECL(max98088_ex_thresh_enum, + M98088_REG_42_SPKDHP_THRESH, 0, + max98088_ex_thresh); static const char *max98088_fltr_mode[] = {"Voice", "Music" }; -static const struct soc_enum max98088_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode), -}; +static SOC_ENUM_SINGLE_DECL(max98088_filter_mode_enum, + M98088_REG_18_DAI1_FILTERS, 7, + max98088_fltr_mode); static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" }; -static const struct soc_enum max98088_extmic_enum = - SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text); +static SOC_ENUM_SINGLE_DECL(max98088_extmic_enum, + M98088_REG_48_CFG_MIC, 0, + max98088_extmic_text); static const struct snd_kcontrol_new max98088_extmic_mux = SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum); @@ -626,12 +625,12 @@ static const struct snd_kcontrol_new max98088_extmic_mux = static const char *max98088_dai1_fltr[] = { "Off", "fc=258/fs=16k", "fc=500/fs=16k", "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"}; -static const struct soc_enum max98088_dai1_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr), -}; -static const struct soc_enum max98088_dai1_adc_filter_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr), -}; +static SOC_ENUM_SINGLE_DECL(max98088_dai1_dac_filter_enum, + M98088_REG_18_DAI1_FILTERS, 0, + max98088_dai1_fltr); +static SOC_ENUM_SINGLE_DECL(max98088_dai1_adc_filter_enum, + M98088_REG_18_DAI1_FILTERS, 4, + max98088_dai1_fltr); static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -- cgit v1.2.3 From 2907cbcc120e0c388df499fcb1be7d093ade3993 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:14:13 +0100 Subject: ASoC: max98090: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/max98090.c | 172 +++++++++++++++++++++++++------------------- 1 file changed, 97 insertions(+), 75 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 51f9b3d16b41..c7b9e901bdac 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -512,65 +512,75 @@ static const char *max98090_perf_pwr_text[] = static const char *max98090_pwr_perf_text[] = { "Low Power", "High Performance" }; -static const struct soc_enum max98090_vcmbandgap_enum = - SOC_ENUM_SINGLE(M98090_REG_BIAS_CONTROL, M98090_VCM_MODE_SHIFT, - ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); +static SOC_ENUM_SINGLE_DECL(max98090_vcmbandgap_enum, + M98090_REG_BIAS_CONTROL, + M98090_VCM_MODE_SHIFT, + max98090_pwr_perf_text); static const char *max98090_osr128_text[] = { "64*fs", "128*fs" }; -static const struct soc_enum max98090_osr128_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_OSR128_SHIFT, - ARRAY_SIZE(max98090_osr128_text), max98090_osr128_text); +static SOC_ENUM_SINGLE_DECL(max98090_osr128_enum, + M98090_REG_ADC_CONTROL, + M98090_OSR128_SHIFT, + max98090_osr128_text); static const char *max98090_mode_text[] = { "Voice", "Music" }; -static const struct soc_enum max98090_mode_enum = - SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG, M98090_MODE_SHIFT, - ARRAY_SIZE(max98090_mode_text), max98090_mode_text); +static SOC_ENUM_SINGLE_DECL(max98090_mode_enum, + M98090_REG_FILTER_CONFIG, + M98090_MODE_SHIFT, + max98090_mode_text); -static const struct soc_enum max98090_filter_dmic34mode_enum = - SOC_ENUM_SINGLE(M98090_REG_FILTER_CONFIG, - M98090_FLT_DMIC34MODE_SHIFT, - ARRAY_SIZE(max98090_mode_text), max98090_mode_text); +static SOC_ENUM_SINGLE_DECL(max98090_filter_dmic34mode_enum, + M98090_REG_FILTER_CONFIG, + M98090_FLT_DMIC34MODE_SHIFT, + max98090_mode_text); static const char *max98090_drcatk_text[] = { "0.5ms", "1ms", "5ms", "10ms", "25ms", "50ms", "100ms", "200ms" }; -static const struct soc_enum max98090_drcatk_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCATK_SHIFT, - ARRAY_SIZE(max98090_drcatk_text), max98090_drcatk_text); +static SOC_ENUM_SINGLE_DECL(max98090_drcatk_enum, + M98090_REG_DRC_TIMING, + M98090_DRCATK_SHIFT, + max98090_drcatk_text); static const char *max98090_drcrls_text[] = { "8s", "4s", "2s", "1s", "0.5s", "0.25s", "0.125s", "0.0625s" }; -static const struct soc_enum max98090_drcrls_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_TIMING, M98090_DRCRLS_SHIFT, - ARRAY_SIZE(max98090_drcrls_text), max98090_drcrls_text); +static SOC_ENUM_SINGLE_DECL(max98090_drcrls_enum, + M98090_REG_DRC_TIMING, + M98090_DRCRLS_SHIFT, + max98090_drcrls_text); static const char *max98090_alccmp_text[] = { "1:1", "1:1.5", "1:2", "1:4", "1:INF" }; -static const struct soc_enum max98090_alccmp_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_COMPRESSOR, M98090_DRCCMP_SHIFT, - ARRAY_SIZE(max98090_alccmp_text), max98090_alccmp_text); +static SOC_ENUM_SINGLE_DECL(max98090_alccmp_enum, + M98090_REG_DRC_COMPRESSOR, + M98090_DRCCMP_SHIFT, + max98090_alccmp_text); static const char *max98090_drcexp_text[] = { "1:1", "2:1", "3:1" }; -static const struct soc_enum max98090_drcexp_enum = - SOC_ENUM_SINGLE(M98090_REG_DRC_EXPANDER, M98090_DRCEXP_SHIFT, - ARRAY_SIZE(max98090_drcexp_text), max98090_drcexp_text); +static SOC_ENUM_SINGLE_DECL(max98090_drcexp_enum, + M98090_REG_DRC_EXPANDER, + M98090_DRCEXP_SHIFT, + max98090_drcexp_text); -static const struct soc_enum max98090_dac_perfmode_enum = - SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_PERFMODE_SHIFT, - ARRAY_SIZE(max98090_perf_pwr_text), max98090_perf_pwr_text); +static SOC_ENUM_SINGLE_DECL(max98090_dac_perfmode_enum, + M98090_REG_DAC_CONTROL, + M98090_PERFMODE_SHIFT, + max98090_perf_pwr_text); -static const struct soc_enum max98090_dachp_enum = - SOC_ENUM_SINGLE(M98090_REG_DAC_CONTROL, M98090_DACHP_SHIFT, - ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); +static SOC_ENUM_SINGLE_DECL(max98090_dachp_enum, + M98090_REG_DAC_CONTROL, + M98090_DACHP_SHIFT, + max98090_pwr_perf_text); -static const struct soc_enum max98090_adchp_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_CONTROL, M98090_ADCHP_SHIFT, - ARRAY_SIZE(max98090_pwr_perf_text), max98090_pwr_perf_text); +static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum, + M98090_REG_ADC_CONTROL, + M98090_ADCHP_SHIFT, + max98090_pwr_perf_text); static const struct snd_kcontrol_new max98090_snd_controls[] = { SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum), @@ -841,39 +851,42 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w, static const char *mic1_mux_text[] = { "IN12", "IN56" }; -static const struct soc_enum mic1_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC1_SHIFT, - ARRAY_SIZE(mic1_mux_text), mic1_mux_text); +static SOC_ENUM_SINGLE_DECL(mic1_mux_enum, + M98090_REG_INPUT_MODE, + M98090_EXTMIC1_SHIFT, + mic1_mux_text); static const struct snd_kcontrol_new max98090_mic1_mux = SOC_DAPM_ENUM("MIC1 Mux", mic1_mux_enum); static const char *mic2_mux_text[] = { "IN34", "IN56" }; -static const struct soc_enum mic2_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_INPUT_MODE, M98090_EXTMIC2_SHIFT, - ARRAY_SIZE(mic2_mux_text), mic2_mux_text); +static SOC_ENUM_SINGLE_DECL(mic2_mux_enum, + M98090_REG_INPUT_MODE, + M98090_EXTMIC2_SHIFT, + mic2_mux_text); static const struct snd_kcontrol_new max98090_mic2_mux = SOC_DAPM_ENUM("MIC2 Mux", mic2_mux_enum); static const char *dmic_mux_text[] = { "ADC", "DMIC" }; -static const struct soc_enum dmic_mux_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_mux_text), dmic_mux_text); +static SOC_ENUM_SINGLE_EXT_DECL(dmic_mux_enum, dmic_mux_text); static const struct snd_kcontrol_new max98090_dmic_mux = SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum); static const char *max98090_micpre_text[] = { "Off", "On" }; -static const struct soc_enum max98090_pa1en_enum = - SOC_ENUM_SINGLE(M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT, - ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text); +static SOC_ENUM_SINGLE_DECL(max98090_pa1en_enum, + M98090_REG_MIC1_INPUT_LEVEL, + M98090_MIC_PA1EN_SHIFT, + max98090_micpre_text); -static const struct soc_enum max98090_pa2en_enum = - SOC_ENUM_SINGLE(M98090_REG_MIC2_INPUT_LEVEL, M98090_MIC_PA2EN_SHIFT, - ARRAY_SIZE(max98090_micpre_text), max98090_micpre_text); +static SOC_ENUM_SINGLE_DECL(max98090_pa2en_enum, + M98090_REG_MIC2_INPUT_LEVEL, + M98090_MIC_PA2EN_SHIFT, + max98090_micpre_text); /* LINEA mixer switch */ static const struct snd_kcontrol_new max98090_linea_mixer_controls[] = { @@ -937,13 +950,15 @@ static const struct snd_kcontrol_new max98090_right_adc_mixer_controls[] = { static const char *lten_mux_text[] = { "Normal", "Loopthrough" }; -static const struct soc_enum ltenl_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT, - ARRAY_SIZE(lten_mux_text), lten_mux_text); +static SOC_ENUM_SINGLE_DECL(ltenl_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LTEN_SHIFT, + lten_mux_text); -static const struct soc_enum ltenr_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LTEN_SHIFT, - ARRAY_SIZE(lten_mux_text), lten_mux_text); +static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LTEN_SHIFT, + lten_mux_text); static const struct snd_kcontrol_new max98090_ltenl_mux = SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum); @@ -953,13 +968,15 @@ static const struct snd_kcontrol_new max98090_ltenr_mux = static const char *lben_mux_text[] = { "Normal", "Loopback" }; -static const struct soc_enum lbenl_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT, - ARRAY_SIZE(lben_mux_text), lben_mux_text); +static SOC_ENUM_SINGLE_DECL(lbenl_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LBEN_SHIFT, + lben_mux_text); -static const struct soc_enum lbenr_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_IO_CONFIGURATION, M98090_LBEN_SHIFT, - ARRAY_SIZE(lben_mux_text), lben_mux_text); +static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum, + M98090_REG_IO_CONFIGURATION, + M98090_LBEN_SHIFT, + lben_mux_text); static const struct snd_kcontrol_new max98090_lbenl_mux = SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum); @@ -971,13 +988,15 @@ static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" }; static const char *stenr_mux_text[] = { "Normal", "Sidetone Right" }; -static const struct soc_enum stenl_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSL_SHIFT, - ARRAY_SIZE(stenl_mux_text), stenl_mux_text); +static SOC_ENUM_SINGLE_DECL(stenl_mux_enum, + M98090_REG_ADC_SIDETONE, + M98090_DSTSL_SHIFT, + stenl_mux_text); -static const struct soc_enum stenr_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_ADC_SIDETONE, M98090_DSTSR_SHIFT, - ARRAY_SIZE(stenr_mux_text), stenr_mux_text); +static SOC_ENUM_SINGLE_DECL(stenr_mux_enum, + M98090_REG_ADC_SIDETONE, + M98090_DSTSR_SHIFT, + stenr_mux_text); static const struct snd_kcontrol_new max98090_stenl_mux = SOC_DAPM_ENUM("STENL Mux", stenl_mux_enum); @@ -1085,9 +1104,10 @@ static const struct snd_kcontrol_new max98090_right_rcv_mixer_controls[] = { static const char *linmod_mux_text[] = { "Left Only", "Left and Right" }; -static const struct soc_enum linmod_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_LOUTR_MIXER, M98090_LINMOD_SHIFT, - ARRAY_SIZE(linmod_mux_text), linmod_mux_text); +static SOC_ENUM_SINGLE_DECL(linmod_mux_enum, + M98090_REG_LOUTR_MIXER, + M98090_LINMOD_SHIFT, + linmod_mux_text); static const struct snd_kcontrol_new max98090_linmod_mux = SOC_DAPM_ENUM("LINMOD Mux", linmod_mux_enum); @@ -1097,16 +1117,18 @@ static const char *mixhpsel_mux_text[] = { "DAC Only", "HP Mixer" }; /* * This is a mux as it selects the HP output, but to DAPM it is a Mixer enable */ -static const struct soc_enum mixhplsel_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPLSEL_SHIFT, - ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text); +static SOC_ENUM_SINGLE_DECL(mixhplsel_mux_enum, + M98090_REG_HP_CONTROL, + M98090_MIXHPLSEL_SHIFT, + mixhpsel_mux_text); static const struct snd_kcontrol_new max98090_mixhplsel_mux = SOC_DAPM_ENUM("MIXHPLSEL Mux", mixhplsel_mux_enum); -static const struct soc_enum mixhprsel_mux_enum = - SOC_ENUM_SINGLE(M98090_REG_HP_CONTROL, M98090_MIXHPRSEL_SHIFT, - ARRAY_SIZE(mixhpsel_mux_text), mixhpsel_mux_text); +static SOC_ENUM_SINGLE_DECL(mixhprsel_mux_enum, + M98090_REG_HP_CONTROL, + M98090_MIXHPRSEL_SHIFT, + mixhpsel_mux_text); static const struct snd_kcontrol_new max98090_mixhprsel_mux = SOC_DAPM_ENUM("MIXHPRSEL Mux", mixhprsel_mux_enum); -- cgit v1.2.3 From af1f0a50823a3eb8bb7a11731c02b77d145fff70 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:15:26 +0100 Subject: ASoC: max98095: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/max98095.c | 50 ++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 23 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 3ba1170ebb53..ddbb4164e8d2 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -560,25 +560,27 @@ static void m98095_biquad_band(struct snd_soc_codec *codec, unsigned int dai, } static const char * const max98095_fltr_mode[] = { "Voice", "Music" }; -static const struct soc_enum max98095_dai1_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 7, 2, max98095_fltr_mode), -}; -static const struct soc_enum max98095_dai2_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 7, 2, max98095_fltr_mode), -}; +static SOC_ENUM_SINGLE_DECL(max98095_dai1_filter_mode_enum, + M98095_02E_DAI1_FILTERS, 7, + max98095_fltr_mode); +static SOC_ENUM_SINGLE_DECL(max98095_dai2_filter_mode_enum, + M98095_038_DAI2_FILTERS, 7, + max98095_fltr_mode); static const char * const max98095_extmic_text[] = { "None", "MIC1", "MIC2" }; -static const struct soc_enum max98095_extmic_enum = - SOC_ENUM_SINGLE(M98095_087_CFG_MIC, 0, 3, max98095_extmic_text); +static SOC_ENUM_SINGLE_DECL(max98095_extmic_enum, + M98095_087_CFG_MIC, 0, + max98095_extmic_text); static const struct snd_kcontrol_new max98095_extmic_mux = SOC_DAPM_ENUM("External MIC Mux", max98095_extmic_enum); static const char * const max98095_linein_text[] = { "INA", "INB" }; -static const struct soc_enum max98095_linein_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 6, 2, max98095_linein_text); +static SOC_ENUM_SINGLE_DECL(max98095_linein_enum, + M98095_086_CFG_LINE, 6, + max98095_linein_text); static const struct snd_kcontrol_new max98095_linein_mux = SOC_DAPM_ENUM("Linein Input Mux", max98095_linein_enum); @@ -586,24 +588,26 @@ static const struct snd_kcontrol_new max98095_linein_mux = static const char * const max98095_line_mode_text[] = { "Stereo", "Differential"}; -static const struct soc_enum max98095_linein_mode_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 7, 2, max98095_line_mode_text); +static SOC_ENUM_SINGLE_DECL(max98095_linein_mode_enum, + M98095_086_CFG_LINE, 7, + max98095_line_mode_text); -static const struct soc_enum max98095_lineout_mode_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 4, 2, max98095_line_mode_text); +static SOC_ENUM_SINGLE_DECL(max98095_lineout_mode_enum, + M98095_086_CFG_LINE, 4, + max98095_line_mode_text); static const char * const max98095_dai_fltr[] = { "Off", "Elliptical-HPF-16k", "Butterworth-HPF-16k", "Elliptical-HPF-8k", "Butterworth-HPF-8k", "Butterworth-HPF-Fs/240"}; -static const struct soc_enum max98095_dai1_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 0, 6, max98095_dai_fltr), -}; -static const struct soc_enum max98095_dai2_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 0, 6, max98095_dai_fltr), -}; -static const struct soc_enum max98095_dai3_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_042_DAI3_FILTERS, 0, 6, max98095_dai_fltr), -}; +static SOC_ENUM_SINGLE_DECL(max98095_dai1_dac_filter_enum, + M98095_02E_DAI1_FILTERS, 0, + max98095_dai_fltr); +static SOC_ENUM_SINGLE_DECL(max98095_dai2_dac_filter_enum, + M98095_038_DAI2_FILTERS, 0, + max98095_dai_fltr); +static SOC_ENUM_SINGLE_DECL(max98095_dai3_dac_filter_enum, + M98095_042_DAI3_FILTERS, 0, + max98095_dai_fltr); static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -- cgit v1.2.3 From 3eb29dfb3d3bd4b600370007b96c3c675fb97aa7 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:15 +0000 Subject: ASoC: dapm: Add unlocked version of snd_soc_dapm_sync We will often call sync after several functions that require the DAPM mutex to be held. Rather than release and immediately relock the mutex provide an unlocked function for this situation. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 1 + sound/soc/soc-dapm.c | 27 ++++++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 6e89ef6c11c1..3b991766a8f2 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -461,6 +461,7 @@ int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm); +int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm); int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 48a4eeb05192..4200f96a1483 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2342,18 +2342,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, } /** - * snd_soc_dapm_sync - scan and power dapm paths + * snd_soc_dapm_sync_unlocked - scan and power dapm paths * @dapm: DAPM context * * Walks all dapm audio paths and powers widgets according to their * stream or path usage. * + * Requires external locking. + * * Returns 0 for success. */ -int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) +int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm) { - int ret; - /* * Suppress early reports (eg, jacks syncing their state) to avoid * silly DAPM runs during card startup. @@ -2361,8 +2361,25 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) if (!dapm->card || !dapm->card->instantiated) return 0; + return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked); + +/** + * snd_soc_dapm_sync - scan and power dapm paths + * @dapm: DAPM context + * + * Walks all dapm audio paths and powers widgets according to their + * stream or path usage. + * + * Returns 0 for success. + */ +int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm) +{ + int ret; + mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - ret = dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP); + ret = snd_soc_dapm_sync_unlocked(dapm); mutex_unlock(&dapm->card->dapm_mutex); return ret; } -- cgit v1.2.3 From 1bf1b8cf4faf279c3643c5c8045bec53b047ca9a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:16 +0000 Subject: ASoC: adav80x: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/adav80x.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index f78b27a7c461..ab790d5fe53d 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -541,6 +541,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, unsigned int freq, int dir) { struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; if (dir == SND_SOC_CLOCK_IN) { switch (clk_id) { @@ -573,7 +574,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2, iclk_ctrl2); - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync(dapm); } } else { unsigned int mask; @@ -600,17 +601,21 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec, adav80x->sysclk_pd[clk_id] = false; } + snd_soc_dapm_mutex_lock(dapm); + if (adav80x->sysclk_pd[0]) - snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); + snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1"); else - snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1"); if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) - snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); + snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2"); else - snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2"); - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } return 0; -- cgit v1.2.3 From e951f267fd042ce6ca66449dd6d537b6126a10d7 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:17 +0000 Subject: ASoC: wm5100: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm5100.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 4e3e31aaf509..492fe846ae68 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2100,6 +2100,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100) int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) { struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; if (jack) { wm5100->jack = jack; @@ -2117,9 +2118,14 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) WM5100_ACCDET_RATE_MASK); /* We need the charge pump to power MICBIAS */ - snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_force_enable_pin_unlocked(dapm, "CP2"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); /* We start off just enabling microphone detection - even a * plain headphone will trigger detection. -- cgit v1.2.3 From f1a3b8d9d4818b88cd7de369da3bb1804c2ad7da Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:18 +0000 Subject: ASoC: wm8962: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 97db3b45b411..9e6233633c44 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3089,6 +3089,7 @@ static irqreturn_t wm8962_irq(int irq, void *data) int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) { struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; int irq_mask, enable; wm8962->jack = jack; @@ -3109,14 +3110,18 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) snd_soc_jack_report(wm8962->jack, 0, SND_JACK_MICROPHONE | SND_JACK_BTN_0); + snd_soc_dapm_mutex_lock(dapm); + if (jack) { - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS"); } else { - snd_soc_dapm_disable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS"); + snd_soc_dapm_disable_pin_unlocked(dapm, "SYSCLK"); + snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS"); } + snd_soc_dapm_mutex_unlock(dapm); + return 0; } EXPORT_SYMBOL_GPL(wm8962_mic_detect); -- cgit v1.2.3 From babce8211b194acdc41bc47975b50969a48b84ab Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:19 +0000 Subject: ASoC: wm8994: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b9be9cbc4603..e8daf55d37e3 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2549,43 +2549,52 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode) { struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; switch (mode) { case WM8994_VMID_NORMAL: + snd_soc_dapm_mutex_lock(dapm); + if (wm8994->hubs.lineout1_se) { - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT1N Driver"); - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT1P Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT1N Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT1P Driver"); } if (wm8994->hubs.lineout2_se) { - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT2N Driver"); - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT2P Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT2N Driver"); + snd_soc_dapm_disable_pin_unlocked(dapm, + "LINEOUT2P Driver"); } /* Do the sync with the old mode to allow it to clean up */ - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync_unlocked(dapm); wm8994->vmid_mode = mode; + + snd_soc_dapm_mutex_unlock(dapm); break; case WM8994_VMID_FORCE: + snd_soc_dapm_mutex_lock(dapm); + if (wm8994->hubs.lineout1_se) { - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT1N Driver"); - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT1P Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT1N Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT1P Driver"); } if (wm8994->hubs.lineout2_se) { - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT2N Driver"); - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT2P Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT2N Driver"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, + "LINEOUT2P Driver"); } wm8994->vmid_mode = mode; - snd_soc_dapm_sync(&codec->dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); break; default: -- cgit v1.2.3 From 02afc6a23863367f59a3c792567cf1c9bb9d626c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:20 +0000 Subject: ASoC: wm8996: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1a7655b0aa22..d565d0ac7a11 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2251,6 +2251,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, wm8996_polarity_fn polarity_cb) { struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; wm8996->jack = jack; wm8996->detecting = true; @@ -2267,8 +2268,12 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, WM8996_MICB2_DISCH, 0); /* LDO2 powers the microphones, SYSCLK clocks detection */ - snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO2"); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "SYSCLK"); + + snd_soc_dapm_mutex_unlock(dapm); /* We start off just enabling microphone detection - even a * plain headphone will trigger detection. -- cgit v1.2.3 From 121df681da21cebd8915c8ad62b33b7c90d4b395 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:21 +0000 Subject: ASoC: mfld_machine: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/intel/mfld_machine.c | 65 ++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 24 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/mfld_machine.c b/sound/soc/intel/mfld_machine.c index d3d4c32434f7..0cef32e9d402 100644 --- a/sound/soc/intel/mfld_machine.c +++ b/sound/soc/intel/mfld_machine.c @@ -101,20 +101,27 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = &codec->dapm; if (ucontrol->value.integer.value[0] == hs_switch) return 0; + snd_soc_dapm_mutex_lock(dapm); + if (ucontrol->value.integer.value[0]) { pr_debug("hs_set HS path\n"); - snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); } else { pr_debug("hs_set EP path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT"); } - snd_soc_dapm_sync(&codec->dapm); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); + hs_switch = ucontrol->value.integer.value[0]; return 0; @@ -122,18 +129,20 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol, static void lo_enable_out_pins(struct snd_soc_codec *codec) { - snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL"); - snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR"); - snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL"); - snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR"); - snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT"); - snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT"); + struct snd_soc_dapm_context *dapm = &codec->dapm; + + snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTL"); + snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTR"); + snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTL"); + snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTR"); + snd_soc_dapm_enable_pin_unlocked(dapm, "VIB1OUT"); + snd_soc_dapm_enable_pin_unlocked(dapm, "VIB2OUT"); if (hs_switch) { - snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); } else { - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_enable_pin_unlocked(dapm, "EPOUT"); } } @@ -148,44 +157,52 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = &codec->dapm; if (ucontrol->value.integer.value[0] == lo_dac) return 0; + snd_soc_dapm_mutex_lock(dapm); + /* we dont want to work with last state of lineout so just enable all * pins and then disable pins not required */ lo_enable_out_pins(codec); + switch (ucontrol->value.integer.value[0]) { case 0: pr_debug("set vibra path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT"); - snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "VIB1OUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "VIB2OUT"); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0); break; case 1: pr_debug("set hs path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); + snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22); break; case 2: pr_debug("set spkr path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL"); - snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR"); + snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTL"); + snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTR"); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44); break; case 3: pr_debug("set null path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL"); - snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR"); + snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTL"); + snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTR"); snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66); break; } - snd_soc_dapm_sync(&codec->dapm); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); + lo_dac = ucontrol->value.integer.value[0]; return 0; } -- cgit v1.2.3 From 03510ca07ad48941072d673321d2b009be6dfcd4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:22 +0000 Subject: ASoC: ams-delta: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. It looks like these were originally locked with the CODEC mutex and not updated since the patch "ASoC: dapm: Use DAPM mutex for DAPM ops instead of codec mutex", so remove the original CODEC mutex locking as well. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/omap/ams-delta.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 629446482a91..5750de197d0d 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -106,57 +106,59 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, if (ucontrol->value.enumerated.item[0] >= control->max) return -EINVAL; - mutex_lock(&codec->mutex); + snd_soc_dapm_mutex_lock(dapm); /* Translate selection to bitmap */ pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]]; /* Setup pins after corresponding bits if changed */ pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE)); + if (pin != snd_soc_dapm_get_pin_status(dapm, "Mouthpiece")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Mouthpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mouthpiece"); else - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece"); } pin = !!(pins & (1 << AMS_DELTA_EARPIECE)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Earpiece")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Earpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece"); else - snd_soc_dapm_disable_pin(dapm, "Earpiece"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Earpiece"); } pin = !!(pins & (1 << AMS_DELTA_MICROPHONE)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Microphone")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Microphone"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone"); else - snd_soc_dapm_disable_pin(dapm, "Microphone"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Microphone"); } pin = !!(pins & (1 << AMS_DELTA_SPEAKER)); if (pin != snd_soc_dapm_get_pin_status(dapm, "Speaker")) { changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); else - snd_soc_dapm_disable_pin(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); } pin = !!(pins & (1 << AMS_DELTA_AGC)); if (pin != ams_delta_audio_agc) { ams_delta_audio_agc = pin; changed = 1; if (pin) - snd_soc_dapm_enable_pin(dapm, "AGCIN"); + snd_soc_dapm_enable_pin_unlocked(dapm, "AGCIN"); else - snd_soc_dapm_disable_pin(dapm, "AGCIN"); + snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN"); } + if (changed) - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); - mutex_unlock(&codec->mutex); + snd_soc_dapm_mutex_unlock(dapm); return changed; } @@ -315,12 +317,17 @@ static void cx81801_close(struct tty_struct *tty) v253_ops.close(tty); /* Revert back to default audio input/output constellation */ - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); - snd_soc_dapm_enable_pin(dapm, "Earpiece"); - snd_soc_dapm_enable_pin(dapm, "Microphone"); - snd_soc_dapm_disable_pin(dapm, "Speaker"); - snd_soc_dapm_disable_pin(dapm, "AGCIN"); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_lock(dapm); + + snd_soc_dapm_disable_pin_unlocked(dapm, "Mouthpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Earpiece"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Microphone"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "AGCIN"); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(codec); } /* Line discipline .hangup() */ -- cgit v1.2.3 From 43cbbc398f027483e129c3ed4634769ca60ed264 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:23 +0000 Subject: ASoC: omap: n810: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/omap/n810.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 3fde9e402710..480a39ce02bc 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -68,26 +68,30 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) break; } + snd_soc_dapm_mutex_lock(dapm); + if (n810_spk_func) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); if (hp) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); if (line1l) - snd_soc_dapm_enable_pin(dapm, "LINE1L"); + snd_soc_dapm_enable_pin_unlocked(dapm, "LINE1L"); else - snd_soc_dapm_disable_pin(dapm, "LINE1L"); + snd_soc_dapm_disable_pin_unlocked(dapm, "LINE1L"); if (n810_dmic_func) - snd_soc_dapm_enable_pin(dapm, "DMic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); else - snd_soc_dapm_disable_pin(dapm, "DMic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); + + snd_soc_dapm_sync_unlocked(dapm); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_unlock(dapm); } static int n810_startup(struct snd_pcm_substream *substream) -- cgit v1.2.3 From 9dd2bb3fdb38c47ce3f1be624c9e6dcba3d61898 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:24 +0000 Subject: ASoC: omap: rx51: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/omap/rx51.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 611179c3bca4..7fb3d4b10370 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -74,26 +74,30 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) break; } + snd_soc_dapm_mutex_lock(dapm); + if (rx51_spk_func) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); if (rx51_dmic_func) - snd_soc_dapm_enable_pin(dapm, "DMic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); else - snd_soc_dapm_disable_pin(dapm, "DMic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); if (hp) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); if (hs) - snd_soc_dapm_enable_pin(dapm, "HS Mic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "HS Mic"); else - snd_soc_dapm_disable_pin(dapm, "HS Mic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic"); gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int rx51_startup(struct snd_pcm_substream *substream) -- cgit v1.2.3 From 4d9e73488d4e97b6019d178e53f8ec0a94c4e926 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:25 +0000 Subject: ASoC: pxa: corgi: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/pxa/corgi.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 1853d41034bf..9d9c8ad57f0e 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -47,51 +47,55 @@ static int corgi_spk_func; static void corgi_ext_control(struct snd_soc_dapm_context *dapm) { + snd_soc_dapm_mutex_lock(dapm); + /* set up jack connection */ switch (corgi_jack_func) { case CORGI_HP: /* set = unmute headphone */ gpio_set_value(CORGI_GPIO_MUTE_L, 1); gpio_set_value(CORGI_GPIO_MUTE_R, 1); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_MIC: /* reset = mute headphone */ gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 0); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_LINE: gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 0); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Line Jack"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_HEADSET: gpio_set_value(CORGI_GPIO_MUTE_L, 0); gpio_set_value(CORGI_GPIO_MUTE_R, 1); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); break; } if (corgi_spk_func == CORGI_SPK_ON) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); /* signal a DAPM event */ - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int corgi_startup(struct snd_pcm_substream *substream) -- cgit v1.2.3 From f71b0fbe52f816649ab39ff329b7e4091276208a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:26 +0000 Subject: ASoC: pxa: magician: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/pxa/magician.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index aace19e0fe2c..31242be08823 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -45,27 +45,31 @@ static void magician_ext_control(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; + snd_soc_dapm_mutex_lock(dapm); + if (magician_spk_switch) - snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); else - snd_soc_dapm_disable_pin(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); if (magician_hp_switch) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); switch (magician_in_sel) { case MAGICIAN_MIC: - snd_soc_dapm_disable_pin(dapm, "Headset Mic"); - snd_soc_dapm_enable_pin(dapm, "Call Mic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Mic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Call Mic"); break; case MAGICIAN_MIC_EXT: - snd_soc_dapm_disable_pin(dapm, "Call Mic"); - snd_soc_dapm_enable_pin(dapm, "Headset Mic"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Call Mic"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Mic"); break; } - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int magician_startup(struct snd_pcm_substream *substream) -- cgit v1.2.3 From 1845a7255a308da0c32714a2d57d79225037ed5b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:27 +0000 Subject: ASoC: pxa: spitz: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/pxa/spitz.c | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index fc052d8247ff..04dbb5a38fa4 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -46,61 +46,66 @@ static int spitz_mic_gpio; static void spitz_ext_control(struct snd_soc_dapm_context *dapm) { + snd_soc_dapm_mutex_lock(dapm); + if (spitz_spk_func == SPITZ_SPK_ON) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); /* set up jack connection */ switch (spitz_jack_func) { case SPITZ_HP: /* enable and unmute hp jack, disable mic bias */ - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 1); gpio_set_value(SPITZ_GPIO_MUTE_R, 1); break; case SPITZ_MIC: /* enable mic jack and bias, mute hp */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; case SPITZ_LINE: /* enable line jack, disable mic bias and mute hp */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; case SPITZ_HEADSET: /* enable and unmute headset jack enable mic bias, mute L hp */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 1); break; case SPITZ_HP_OFF: /* jack removed, everything off */ - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); - snd_soc_dapm_disable_pin(dapm, "Mic Jack"); - snd_soc_dapm_disable_pin(dapm, "Line Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); gpio_set_value(SPITZ_GPIO_MUTE_L, 0); gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; } - snd_soc_dapm_sync(dapm); + + snd_soc_dapm_sync_unlocked(dapm); + + snd_soc_dapm_mutex_unlock(dapm); } static int spitz_startup(struct snd_pcm_substream *substream) -- cgit v1.2.3 From 26e24ddce755cd6fb4b05a87ae37f7e10faa0c4b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 18 Feb 2014 15:22:28 +0000 Subject: ASoC: pxa: tosa: Update locking around use of DAPM pin API The pin updates in this driver look like they are intended to be done atomically, update to do so. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/pxa/tosa.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 1d9c2ed223bc..2a4b438ce97c 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -48,31 +48,35 @@ static void tosa_ext_control(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; + snd_soc_dapm_mutex_lock(dapm); + /* set up jack connection */ switch (tosa_jack_func) { case TOSA_HP: - snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic (Internal)"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case TOSA_MIC_INT: - snd_soc_dapm_enable_pin(dapm, "Mic (Internal)"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_disable_pin(dapm, "Headset Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Mic (Internal)"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case TOSA_HEADSET: - snd_soc_dapm_disable_pin(dapm, "Mic (Internal)"); - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Headset Jack"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Mic (Internal)"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); break; } if (tosa_spk_func == TOSA_SPK_ON) - snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin_unlocked(dapm, "Speaker"); else - snd_soc_dapm_disable_pin(dapm, "Speaker"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Speaker"); + + snd_soc_dapm_sync_unlocked(dapm); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_mutex_unlock(dapm); } static int tosa_startup(struct snd_pcm_substream *substream) -- cgit v1.2.3 From 1e42c3e426b3f7bc61ba338dd6507a293108117c Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 20 Feb 2014 21:48:42 +0000 Subject: ASoC: Intel: Add support for Haswell/Broadwell DSP Add support for low level differentiation functions for Haswell and Broadwell SST DSPs. This includes suppoprt for DSP boot and reset, DSP firmware module parsing and DSP memory block map initialisation. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-dsp.c | 60 +++++ sound/soc/intel/sst-dsp.h | 10 + sound/soc/intel/sst-haswell-dsp.c | 517 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 587 insertions(+) create mode 100644 sound/soc/intel/sst-haswell-dsp.c (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-dsp.c b/sound/soc/intel/sst-dsp.c index 6e22c1201959..0c129fd85ecf 100644 --- a/sound/soc/intel/sst-dsp.c +++ b/sound/soc/intel/sst-dsp.c @@ -27,6 +27,66 @@ #define CREATE_TRACE_POINTS #include +/* Internal generic low-level SST IO functions - can be overidden */ +void sst_shim32_write(void __iomem *addr, u32 offset, u32 value) +{ + writel(value, addr + offset); +} +EXPORT_SYMBOL_GPL(sst_shim32_write); + +u32 sst_shim32_read(void __iomem *addr, u32 offset) +{ + return readl(addr + offset); +} +EXPORT_SYMBOL_GPL(sst_shim32_read); + +void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value) +{ + memcpy_toio(addr + offset, &value, sizeof(value)); +} +EXPORT_SYMBOL_GPL(sst_shim32_write64); + +u64 sst_shim32_read64(void __iomem *addr, u32 offset) +{ + u64 val; + + memcpy_fromio(&val, addr + offset, sizeof(val)); + return val; +} +EXPORT_SYMBOL_GPL(sst_shim32_read64); + +static inline void _sst_memcpy_toio_32(volatile u32 __iomem *dest, + u32 *src, size_t bytes) +{ + int i, words = bytes >> 2; + + for (i = 0; i < words; i++) + writel(src[i], dest + i); +} + +static inline void _sst_memcpy_fromio_32(u32 *dest, + const volatile __iomem u32 *src, size_t bytes) +{ + int i, words = bytes >> 2; + + for (i = 0; i < words; i++) + dest[i] = readl(src + i); +} + +void sst_memcpy_toio_32(struct sst_dsp *sst, + void __iomem *dest, void *src, size_t bytes) +{ + _sst_memcpy_toio_32(dest, src, bytes); +} +EXPORT_SYMBOL_GPL(sst_memcpy_toio_32); + +void sst_memcpy_fromio_32(struct sst_dsp *sst, void *dest, + void __iomem *src, size_t bytes) +{ + _sst_memcpy_fromio_32(dest, src, bytes); +} +EXPORT_SYMBOL_GPL(sst_memcpy_fromio_32); + /* Public API */ void sst_dsp_shim_write(struct sst_dsp *sst, u32 offset, u32 value) { diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h index 3730fd324455..608418c1181a 100644 --- a/sound/soc/intel/sst-dsp.h +++ b/sound/soc/intel/sst-dsp.h @@ -189,6 +189,16 @@ u64 sst_dsp_shim_read64_unlocked(struct sst_dsp *sst, u32 offset); int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset, u64 mask, u64 value); +/* Internal generic low-level SST IO functions - can be overidden */ +void sst_shim32_write(void __iomem *addr, u32 offset, u32 value); +u32 sst_shim32_read(void __iomem *addr, u32 offset); +void sst_shim32_write64(void __iomem *addr, u32 offset, u64 value); +u64 sst_shim32_read64(void __iomem *addr, u32 offset); +void sst_memcpy_toio_32(struct sst_dsp *sst, + void __iomem *dest, void *src, size_t bytes); +void sst_memcpy_fromio_32(struct sst_dsp *sst, + void *dest, void __iomem *src, size_t bytes); + /* DSP reset & boot */ void sst_dsp_reset(struct sst_dsp *sst); int sst_dsp_boot(struct sst_dsp *sst); diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c new file mode 100644 index 000000000000..12f73173a792 --- /dev/null +++ b/sound/soc/intel/sst-haswell-dsp.c @@ -0,0 +1,517 @@ +/* + * Intel Haswell SST DSP driver + * + * Copyright (C) 2013, Intel Corporation. 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 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "sst-dsp.h" +#include "sst-dsp-priv.h" +#include "sst-haswell-ipc.h" + +#include + +#define SST_HSW_FW_SIGNATURE_SIZE 4 +#define SST_HSW_FW_SIGN "$SST" +#define SST_HSW_FW_LIB_SIGN "$LIB" + +#define SST_WPT_SHIM_OFFSET 0xFB000 +#define SST_LP_SHIM_OFFSET 0xE7000 +#define SST_WPT_IRAM_OFFSET 0xA0000 +#define SST_LP_IRAM_OFFSET 0x80000 + +#define SST_SHIM_PM_REG 0x84 + +#define SST_HSW_IRAM 1 +#define SST_HSW_DRAM 2 +#define SST_HSW_REGS 3 + +struct dma_block_info { + __le32 type; /* IRAM/DRAM */ + __le32 size; /* Bytes */ + __le32 ram_offset; /* Offset in I/DRAM */ + __le32 rsvd; /* Reserved field */ +} __attribute__((packed)); + +struct fw_module_info { + __le32 persistent_size; + __le32 scratch_size; +} __attribute__((packed)); + +struct fw_header { + unsigned char signature[SST_HSW_FW_SIGNATURE_SIZE]; /* FW signature */ + __le32 file_size; /* size of fw minus this header */ + __le32 modules; /* # of modules */ + __le32 file_format; /* version of header format */ + __le32 reserved[4]; +} __attribute__((packed)); + +struct fw_module_header { + unsigned char signature[SST_HSW_FW_SIGNATURE_SIZE]; /* module signature */ + __le32 mod_size; /* size of module */ + __le32 blocks; /* # of blocks */ + __le16 padding; + __le16 type; /* codec type, pp lib */ + __le32 entry_point; + struct fw_module_info info; +} __attribute__((packed)); + +static void hsw_free(struct sst_dsp *sst); + +static int hsw_parse_module(struct sst_dsp *dsp, struct sst_fw *fw, + struct fw_module_header *module) +{ + struct dma_block_info *block; + struct sst_module *mod; + struct sst_module_data block_data; + struct sst_module_template template; + int count; + void __iomem *ram; + + /* TODO: allowed module types need to be configurable */ + if (module->type != SST_HSW_MODULE_BASE_FW + && module->type != SST_HSW_MODULE_PCM_SYSTEM + && module->type != SST_HSW_MODULE_PCM + && module->type != SST_HSW_MODULE_PCM_REFERENCE + && module->type != SST_HSW_MODULE_PCM_CAPTURE + && module->type != SST_HSW_MODULE_LPAL) + return 0; + + dev_dbg(dsp->dev, "new module sign 0x%s size 0x%x blocks 0x%x type 0x%x\n", + module->signature, module->mod_size, + module->blocks, module->type); + dev_dbg(dsp->dev, " entrypoint 0x%x\n", module->entry_point); + dev_dbg(dsp->dev, " persistent 0x%x scratch 0x%x\n", + module->info.persistent_size, module->info.scratch_size); + + memset(&template, 0, sizeof(template)); + template.id = module->type; + template.entry = module->entry_point; + template.p.size = module->info.persistent_size; + template.p.type = SST_MEM_DRAM; + template.p.data_type = SST_DATA_P; + template.s.size = module->info.scratch_size; + template.s.type = SST_MEM_DRAM; + template.s.data_type = SST_DATA_S; + + mod = sst_module_new(fw, &template, NULL); + if (mod == NULL) + return -ENOMEM; + + block = (void *)module + sizeof(*module); + + for (count = 0; count < module->blocks; count++) { + + if (block->size <= 0) { + dev_err(dsp->dev, + "error: block %d size invalid\n", count); + sst_module_free(mod); + return -EINVAL; + } + + switch (block->type) { + case SST_HSW_IRAM: + ram = dsp->addr.lpe; + block_data.offset = + block->ram_offset + dsp->addr.iram_offset; + block_data.type = SST_MEM_IRAM; + break; + case SST_HSW_DRAM: + ram = dsp->addr.lpe; + block_data.offset = block->ram_offset; + block_data.type = SST_MEM_DRAM; + break; + default: + dev_err(dsp->dev, "error: bad type 0x%x for block 0x%x\n", + block->type, count); + sst_module_free(mod); + return -EINVAL; + } + + block_data.size = block->size; + block_data.data_type = SST_DATA_M; + block_data.data = (void *)block + sizeof(*block); + block_data.data_offset = block_data.data - fw->dma_buf; + + dev_dbg(dsp->dev, "copy firmware block %d type 0x%x " + "size 0x%x ==> ram %p offset 0x%x\n", + count, block->type, block->size, ram, + block->ram_offset); + + sst_module_insert_fixed_block(mod, &block_data); + + block = (void *)block + sizeof(*block) + block->size; + } + return 0; +} + +static int hsw_parse_fw_image(struct sst_fw *sst_fw) +{ + struct fw_header *header; + struct sst_module *scratch; + struct fw_module_header *module; + struct sst_dsp *dsp = sst_fw->dsp; + struct sst_hsw *hsw = sst_fw->private; + int ret, count; + + /* Read the header information from the data pointer */ + header = (struct fw_header *)sst_fw->dma_buf; + + /* verify FW */ + if ((strncmp(header->signature, SST_HSW_FW_SIGN, 4) != 0) || + (sst_fw->size != header->file_size + sizeof(*header))) { + dev_err(dsp->dev, "error: invalid fw sign/filesize mismatch\n"); + return -EINVAL; + } + + dev_dbg(dsp->dev, "header size=0x%x modules=0x%x fmt=0x%x size=%zu\n", + header->file_size, header->modules, + header->file_format, sizeof(*header)); + + /* parse each module */ + module = (void *)sst_fw->dma_buf + sizeof(*header); + for (count = 0; count < header->modules; count++) { + + /* module */ + ret = hsw_parse_module(dsp, sst_fw, module); + if (ret < 0) { + dev_err(dsp->dev, "error: invalid module %d\n", count); + return ret; + } + module = (void *)module + sizeof(*module) + module->mod_size; + } + + /* allocate persistent/scratch mem regions */ + scratch = sst_mem_block_alloc_scratch(dsp); + if (scratch == NULL) + return -ENOMEM; + + sst_hsw_set_scratch_module(hsw, scratch); + + return 0; +} + +static irqreturn_t hsw_irq(int irq, void *context) +{ + struct sst_dsp *sst = (struct sst_dsp *) context; + u32 isr; + int ret = IRQ_NONE; + + spin_lock(&sst->spinlock); + + /* Interrupt arrived, check src */ + isr = sst_dsp_shim_read_unlocked(sst, SST_ISRX); + if (isr & SST_ISRX_DONE) { + trace_sst_irq_done(isr, + sst_dsp_shim_read_unlocked(sst, SST_IMRX)); + + /* Mask Done interrupt before return */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, + SST_IMRX_DONE, SST_IMRX_DONE); + ret = IRQ_WAKE_THREAD; + } + + if (isr & SST_ISRX_BUSY) { + trace_sst_irq_busy(isr, + sst_dsp_shim_read_unlocked(sst, SST_IMRX)); + + /* Mask Busy interrupt before return */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, + SST_IMRX_BUSY, SST_IMRX_BUSY); + ret = IRQ_WAKE_THREAD; + } + + spin_unlock(&sst->spinlock); + return ret; +} + +static void hsw_boot(struct sst_dsp *sst) +{ + /* select SSP1 19.2MHz base clock, SSP clock 0, turn off Low Power Clock */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, + SST_CSR_S1IOCS | SST_CSR_SBCS1 | SST_CSR_LPCS, 0x0); + + /* stall DSP core, set clk to 192/96Mhz */ + sst_dsp_shim_update_bits_unlocked(sst, + SST_CSR, SST_CSR_STALL | SST_CSR_DCS_MASK, + SST_CSR_STALL | SST_CSR_DCS(4)); + + /* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CLKCTL, + SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0, + SST_CLKCTL_MASK | SST_CLKCTL_DCPLCG | SST_CLKCTL_SCOE0); + + /* disable DMA finish function for SSP0 & SSP1 */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR2, SST_CSR2_SDFD_SSP1, + SST_CSR2_SDFD_SSP1); + + /* enable DMA engine 0,1 all channels to access host memory */ + sst_dsp_shim_update_bits_unlocked(sst, SST_HDMC, + SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff), + SST_HDMC_HDDA1(0xff) | SST_HDMC_HDDA0(0xff)); + + /* disable all clock gating */ + writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL2); + + /* set DSP to RUN */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, SST_CSR_STALL, 0x0); +} + +static void hsw_reset(struct sst_dsp *sst) +{ + /* put DSP into reset and stall */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, + SST_CSR_RST | SST_CSR_STALL, SST_CSR_RST | SST_CSR_STALL); + + /* keep in reset for 10ms */ + mdelay(10); + + /* take DSP out of reset and keep stalled for FW loading */ + sst_dsp_shim_update_bits_unlocked(sst, SST_CSR, + SST_CSR_RST | SST_CSR_STALL, SST_CSR_STALL); +} + +struct sst_adsp_memregion { + u32 start; + u32 end; + int blocks; + enum sst_mem_type type; +}; + +/* lynx point ADSP mem regions */ +static const struct sst_adsp_memregion lp_region[] = { + {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ + {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */ + {0x80000, 0xE0000, 12, SST_MEM_IRAM}, /* I-SRAM - 12 * 32kB */ +}; + +/* wild cat point ADSP mem regions */ +static const struct sst_adsp_memregion wpt_region[] = { + {0x00000, 0x40000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ + {0x40000, 0x80000, 8, SST_MEM_DRAM}, /* D-SRAM1 - 8 * 32kB */ + {0x80000, 0xA0000, 4, SST_MEM_DRAM}, /* D-SRAM2 - 4 * 32kB */ + {0xA0000, 0xF0000, 10, SST_MEM_IRAM}, /* I-SRAM - 10 * 32kB */ +}; + +static int hsw_acpi_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata) +{ + /* ADSP DRAM & IRAM */ + sst->addr.lpe_base = pdata->lpe_base; + sst->addr.lpe = ioremap(pdata->lpe_base, pdata->lpe_size); + if (!sst->addr.lpe) + return -ENODEV; + + /* ADSP PCI MMIO config space */ + sst->addr.pci_cfg = ioremap(pdata->pcicfg_base, pdata->pcicfg_size); + if (!sst->addr.pci_cfg) { + iounmap(sst->addr.lpe); + return -ENODEV; + } + + /* SST Shim */ + sst->addr.shim = sst->addr.lpe + sst->addr.shim_offset; + return 0; +} + +static u32 hsw_block_get_bit(struct sst_mem_block *block) +{ + u32 bit = 0, shift = 0; + + switch (block->type) { + case SST_MEM_DRAM: + shift = 16; + break; + case SST_MEM_IRAM: + shift = 6; + break; + default: + return 0; + } + + bit = 1 << (block->index + shift); + + return bit; +} + +/* enable 32kB memory block - locks held by caller */ +static int hsw_block_enable(struct sst_mem_block *block) +{ + struct sst_dsp *sst = block->dsp; + u32 bit, val; + + if (block->users++ > 0) + return 0; + + dev_dbg(block->dsp->dev, " enabled block %d:%d at offset 0x%x\n", + block->type, block->index, block->offset); + + val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); + bit = hsw_block_get_bit(block); + writel(val & ~bit, sst->addr.pci_cfg + SST_VDRTCTL0); + + /* wait 18 DSP clock ticks */ + udelay(10); + + return 0; +} + +/* disable 32kB memory block - locks held by caller */ +static int hsw_block_disable(struct sst_mem_block *block) +{ + struct sst_dsp *sst = block->dsp; + u32 bit, val; + + if (--block->users > 0) + return 0; + + dev_dbg(block->dsp->dev, " disabled block %d:%d at offset 0x%x\n", + block->type, block->index, block->offset); + + val = readl(sst->addr.pci_cfg + SST_VDRTCTL0); + bit = hsw_block_get_bit(block); + writel(val | bit, sst->addr.pci_cfg + SST_VDRTCTL0); + + return 0; +} + +static struct sst_block_ops sst_hsw_ops = { + .enable = hsw_block_enable, + .disable = hsw_block_disable, +}; + +static int hsw_enable_shim(struct sst_dsp *sst) +{ + int tries = 10; + u32 reg; + + /* enable shim */ + reg = readl(sst->addr.pci_cfg + SST_SHIM_PM_REG); + writel(reg & ~0x3, sst->addr.pci_cfg + SST_SHIM_PM_REG); + + /* check that ADSP shim is enabled */ + while (tries--) { + reg = sst_dsp_shim_read_unlocked(sst, SST_CSR); + if (reg != 0xffffffff) + return 0; + + msleep(1); + } + + return -ENODEV; +} + +static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata) +{ + const struct sst_adsp_memregion *region; + struct device *dev; + int ret = -ENODEV, i, j, region_count; + u32 offset, size; + + dev = sst->dev; + + switch (sst->id) { + case SST_DEV_ID_LYNX_POINT: + region = lp_region; + region_count = ARRAY_SIZE(lp_region); + sst->addr.iram_offset = SST_LP_IRAM_OFFSET; + sst->addr.shim_offset = SST_LP_SHIM_OFFSET; + break; + case SST_DEV_ID_WILDCAT_POINT: + region = wpt_region; + region_count = ARRAY_SIZE(wpt_region); + sst->addr.iram_offset = SST_WPT_IRAM_OFFSET; + sst->addr.shim_offset = SST_WPT_SHIM_OFFSET; + break; + default: + dev_err(dev, "error: failed to get mem resources\n"); + return ret; + } + + ret = hsw_acpi_resource_map(sst, pdata); + if (ret < 0) { + dev_err(dev, "error: failed to map resources\n"); + return ret; + } + + /* enable the DSP SHIM */ + ret = hsw_enable_shim(sst); + if (ret < 0) { + dev_err(dev, "error: failed to set DSP D0 and reset SHIM\n"); + return ret; + } + + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + /* Enable Interrupt from both sides */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, 0x3, 0x0); + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRD, + (0x3 | 0x1 << 16 | 0x3 << 21), 0x0); + + /* register DSP memory blocks - ideally we should get this from ACPI */ + for (i = 0; i < region_count; i++) { + offset = region[i].start; + size = (region[i].end - region[i].start) / region[i].blocks; + + /* register individual memory blocks */ + for (j = 0; j < region[i].blocks; j++) { + sst_mem_block_register(sst, offset, size, + region[i].type, &sst_hsw_ops, j, sst); + offset += size; + } + } + + /* set default power gating mask */ + writel(0x0, sst->addr.pci_cfg + SST_VDRTCTL0); + + return 0; +} + +static void hsw_free(struct sst_dsp *sst) +{ + sst_mem_block_unregister_all(sst); + iounmap(sst->addr.lpe); + iounmap(sst->addr.pci_cfg); +} + +struct sst_ops haswell_ops = { + .reset = hsw_reset, + .boot = hsw_boot, + .write = sst_shim32_write, + .read = sst_shim32_read, + .write64 = sst_shim32_write64, + .read64 = sst_shim32_read64, + .ram_read = sst_memcpy_fromio_32, + .ram_write = sst_memcpy_toio_32, + .irq_handler = hsw_irq, + .init = hsw_init, + .free = hsw_free, + .parse_fw = hsw_parse_fw_image, +}; -- cgit v1.2.3 From 22981243589c3468481f5cfd04176233d2c7be4b Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 20 Feb 2014 21:48:43 +0000 Subject: ASoC: Intel: Add Haswell/Broadwell IPC Add support for Haswell and Broadwell DSP IPC. This is used by the DSP platform PCM driver to configure the DSP for audio operations. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-ipc.c | 1785 +++++++++++++++++++++++++++++++++++++ sound/soc/intel/sst-haswell-ipc.h | 488 ++++++++++ 2 files changed, 2273 insertions(+) create mode 100644 sound/soc/intel/sst-haswell-ipc.c create mode 100644 sound/soc/intel/sst-haswell-ipc.h (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c new file mode 100644 index 000000000000..668d486520ae --- /dev/null +++ b/sound/soc/intel/sst-haswell-ipc.c @@ -0,0 +1,1785 @@ +/* + * Intel SST Haswell/Broadwell IPC Support + * + * Copyright (C) 2013, Intel Corporation. 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 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sst-haswell-ipc.h" +#include "sst-dsp.h" +#include "sst-dsp-priv.h" + +/* Global Message - Generic */ +#define IPC_GLB_TYPE_SHIFT 24 +#define IPC_GLB_TYPE_MASK (0x1f << IPC_GLB_TYPE_SHIFT) +#define IPC_GLB_TYPE(x) (x << IPC_GLB_TYPE_SHIFT) + +/* Global Message - Reply */ +#define IPC_GLB_REPLY_SHIFT 0 +#define IPC_GLB_REPLY_MASK (0x1f << IPC_GLB_REPLY_SHIFT) +#define IPC_GLB_REPLY_TYPE(x) (x << IPC_GLB_REPLY_TYPE_SHIFT) + +/* Stream Message - Generic */ +#define IPC_STR_TYPE_SHIFT 20 +#define IPC_STR_TYPE_MASK (0xf << IPC_STR_TYPE_SHIFT) +#define IPC_STR_TYPE(x) (x << IPC_STR_TYPE_SHIFT) +#define IPC_STR_ID_SHIFT 16 +#define IPC_STR_ID_MASK (0xf << IPC_STR_ID_SHIFT) +#define IPC_STR_ID(x) (x << IPC_STR_ID_SHIFT) + +/* Stream Message - Reply */ +#define IPC_STR_REPLY_SHIFT 0 +#define IPC_STR_REPLY_MASK (0x1f << IPC_STR_REPLY_SHIFT) + +/* Stream Stage Message - Generic */ +#define IPC_STG_TYPE_SHIFT 12 +#define IPC_STG_TYPE_MASK (0xf << IPC_STG_TYPE_SHIFT) +#define IPC_STG_TYPE(x) (x << IPC_STG_TYPE_SHIFT) +#define IPC_STG_ID_SHIFT 10 +#define IPC_STG_ID_MASK (0x3 << IPC_STG_ID_SHIFT) +#define IPC_STG_ID(x) (x << IPC_STG_ID_SHIFT) + +/* Stream Stage Message - Reply */ +#define IPC_STG_REPLY_SHIFT 0 +#define IPC_STG_REPLY_MASK (0x1f << IPC_STG_REPLY_SHIFT) + +/* Debug Log Message - Generic */ +#define IPC_LOG_OP_SHIFT 20 +#define IPC_LOG_OP_MASK (0xf << IPC_LOG_OP_SHIFT) +#define IPC_LOG_OP_TYPE(x) (x << IPC_LOG_OP_SHIFT) +#define IPC_LOG_ID_SHIFT 16 +#define IPC_LOG_ID_MASK (0xf << IPC_LOG_ID_SHIFT) +#define IPC_LOG_ID(x) (x << IPC_LOG_ID_SHIFT) + +/* IPC message timeout (msecs) */ +#define IPC_TIMEOUT_MSECS 300 +#define IPC_BOOT_MSECS 200 +#define IPC_MSG_WAIT 0 +#define IPC_MSG_NOWAIT 1 + +/* Firmware Ready Message */ +#define IPC_FW_READY (0x1 << 29) +#define IPC_STATUS_MASK (0x3 << 30) + +#define IPC_EMPTY_LIST_SIZE 8 +#define IPC_MAX_STREAMS 4 + +/* Mailbox */ +#define IPC_MAX_MAILBOX_BYTES 256 + +/* Global Message - Types and Replies */ +enum ipc_glb_type { + IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */ + IPC_GLB_PERFORMANCE_MONITOR = 1, /* Performance monitoring actions */ + IPC_GLB_ALLOCATE_STREAM = 3, /* Request to allocate new stream */ + IPC_GLB_FREE_STREAM = 4, /* Request to free stream */ + IPC_GLB_GET_FW_CAPABILITIES = 5, /* Retrieves firmware capabilities */ + IPC_GLB_STREAM_MESSAGE = 6, /* Message directed to stream or its stages */ + /* Request to store firmware context during D0->D3 transition */ + IPC_GLB_REQUEST_DUMP = 7, + /* Request to restore firmware context during D3->D0 transition */ + IPC_GLB_RESTORE_CONTEXT = 8, + IPC_GLB_GET_DEVICE_FORMATS = 9, /* Set device format */ + IPC_GLB_SET_DEVICE_FORMATS = 10, /* Get device format */ + IPC_GLB_SHORT_REPLY = 11, + IPC_GLB_ENTER_DX_STATE = 12, + IPC_GLB_GET_MIXER_STREAM_INFO = 13, /* Request mixer stream params */ + IPC_GLB_DEBUG_LOG_MESSAGE = 14, /* Message to or from the debug logger. */ + IPC_GLB_REQUEST_TRANSFER = 16, /* < Request Transfer for host */ + IPC_GLB_MAX_IPC_MESSAGE_TYPE = 17, /* Maximum message number */ +}; + +enum ipc_glb_reply { + IPC_GLB_REPLY_SUCCESS = 0, /* The operation was successful. */ + IPC_GLB_REPLY_ERROR_INVALID_PARAM = 1, /* Invalid parameter was passed. */ + IPC_GLB_REPLY_UNKNOWN_MESSAGE_TYPE = 2, /* Uknown message type was resceived. */ + IPC_GLB_REPLY_OUT_OF_RESOURCES = 3, /* No resources to satisfy the request. */ + IPC_GLB_REPLY_BUSY = 4, /* The system or resource is busy. */ + IPC_GLB_REPLY_PENDING = 5, /* The action was scheduled for processing. */ + IPC_GLB_REPLY_FAILURE = 6, /* Critical error happened. */ + IPC_GLB_REPLY_INVALID_REQUEST = 7, /* Request can not be completed. */ + IPC_GLB_REPLY_STAGE_UNINITIALIZED = 8, /* Processing stage was uninitialized. */ + IPC_GLB_REPLY_NOT_FOUND = 9, /* Required resource can not be found. */ + IPC_GLB_REPLY_SOURCE_NOT_STARTED = 10, /* Source was not started. */ +}; + +/* Stream Message - Types */ +enum ipc_str_operation { + IPC_STR_RESET = 0, + IPC_STR_PAUSE = 1, + IPC_STR_RESUME = 2, + IPC_STR_STAGE_MESSAGE = 3, + IPC_STR_NOTIFICATION = 4, + IPC_STR_MAX_MESSAGE +}; + +/* Stream Stage Message Types */ +enum ipc_stg_operation { + IPC_STG_GET_VOLUME = 0, + IPC_STG_SET_VOLUME, + IPC_STG_SET_WRITE_POSITION, + IPC_STG_SET_FX_ENABLE, + IPC_STG_SET_FX_DISABLE, + IPC_STG_SET_FX_GET_PARAM, + IPC_STG_SET_FX_SET_PARAM, + IPC_STG_SET_FX_GET_INFO, + IPC_STG_MUTE_LOOPBACK, + IPC_STG_MAX_MESSAGE +}; + +/* Stream Stage Message Types For Notification*/ +enum ipc_stg_operation_notify { + IPC_POSITION_CHANGED = 0, + IPC_STG_GLITCH, + IPC_STG_MAX_NOTIFY +}; + +enum ipc_glitch_type { + IPC_GLITCH_UNDERRUN = 1, + IPC_GLITCH_DECODER_ERROR, + IPC_GLITCH_DOUBLED_WRITE_POS, + IPC_GLITCH_MAX +}; + +/* Debug Control */ +enum ipc_debug_operation { + IPC_DEBUG_ENABLE_LOG = 0, + IPC_DEBUG_DISABLE_LOG = 1, + IPC_DEBUG_REQUEST_LOG_DUMP = 2, + IPC_DEBUG_NOTIFY_LOG_DUMP = 3, + IPC_DEBUG_MAX_DEBUG_LOG +}; + +/* Firmware Ready */ +struct sst_hsw_ipc_fw_ready { + u32 inbox_offset; + u32 outbox_offset; + u32 inbox_size; + u32 outbox_size; + u32 fw_info_size; + u8 fw_info[1]; +} __attribute__((packed)); + +struct ipc_message { + struct list_head list; + u32 header; + + /* direction wrt host CPU */ + char tx_data[IPC_MAX_MAILBOX_BYTES]; + size_t tx_size; + char rx_data[IPC_MAX_MAILBOX_BYTES]; + size_t rx_size; + + wait_queue_head_t waitq; + bool pending; + bool complete; + bool wait; + int errno; +}; + +struct sst_hsw_stream; +struct sst_hsw; + +/* Stream infomation */ +struct sst_hsw_stream { + /* configuration */ + struct sst_hsw_ipc_stream_alloc_req request; + struct sst_hsw_ipc_stream_alloc_reply reply; + struct sst_hsw_ipc_stream_free_req free_req; + + /* Mixer info */ + u32 mute_volume[SST_HSW_NO_CHANNELS]; + u32 mute[SST_HSW_NO_CHANNELS]; + + /* runtime info */ + struct sst_hsw *hsw; + int host_id; + bool commited; + bool running; + + /* Notification work */ + struct work_struct notify_work; + u32 header; + + /* Position info from DSP */ + struct sst_hsw_ipc_stream_set_position wpos; + struct sst_hsw_ipc_stream_get_position rpos; + struct sst_hsw_ipc_stream_glitch_position glitch; + + /* Volume info */ + struct sst_hsw_ipc_volume_req vol_req; + + /* driver callback */ + u32 (*notify_position)(struct sst_hsw_stream *stream, void *data); + void *pdata; + + struct list_head node; +}; + +/* FW log ring information */ +struct sst_hsw_log_stream { + dma_addr_t dma_addr; + unsigned char *dma_area; + unsigned char *ring_descr; + int pages; + int size; + + /* Notification work */ + struct work_struct notify_work; + wait_queue_head_t readers_wait_q; + struct mutex rw_mutex; + + u32 last_pos; + u32 curr_pos; + u32 reader_pos; + + /* fw log config */ + u32 config[SST_HSW_FW_LOG_CONFIG_DWORDS]; + + struct sst_hsw *hsw; +}; + +/* SST Haswell IPC data */ +struct sst_hsw { + struct device *dev; + struct sst_dsp *dsp; + struct platform_device *pdev_pcm; + + /* FW config */ + struct sst_hsw_ipc_fw_ready fw_ready; + struct sst_hsw_ipc_fw_version version; + struct sst_module *scratch; + bool fw_done; + + /* stream */ + struct list_head stream_list; + + /* global mixer */ + struct sst_hsw_ipc_stream_info_reply mixer_info; + enum sst_hsw_volume_curve curve_type; + u32 curve_duration; + u32 mute[SST_HSW_NO_CHANNELS]; + u32 mute_volume[SST_HSW_NO_CHANNELS]; + + /* DX */ + struct sst_hsw_ipc_dx_reply dx; + + /* boot */ + wait_queue_head_t boot_wait; + bool boot_complete; + bool shutdown; + + /* IPC messaging */ + struct list_head tx_list; + struct list_head rx_list; + struct list_head empty_list; + wait_queue_head_t wait_txq; + struct task_struct *tx_thread; + struct kthread_worker kworker; + struct kthread_work kwork; + bool pending; + struct ipc_message *msg; + + /* FW log stream */ + struct sst_hsw_log_stream log_stream; +}; + +#define CREATE_TRACE_POINTS +#include + +static inline u32 msg_get_global_type(u32 msg) +{ + return (msg & IPC_GLB_TYPE_MASK) >> IPC_GLB_TYPE_SHIFT; +} + +static inline u32 msg_get_global_reply(u32 msg) +{ + return (msg & IPC_GLB_REPLY_MASK) >> IPC_GLB_REPLY_SHIFT; +} + +static inline u32 msg_get_stream_type(u32 msg) +{ + return (msg & IPC_STR_TYPE_MASK) >> IPC_STR_TYPE_SHIFT; +} + +static inline u32 msg_get_stage_type(u32 msg) +{ + return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; +} + +static inline u32 msg_set_stage_type(u32 msg, u32 type) +{ + return (msg & ~IPC_STG_TYPE_MASK) + + (type << IPC_STG_TYPE_SHIFT); +} + +static inline u32 msg_get_stream_id(u32 msg) +{ + return (msg & IPC_STR_ID_MASK) >> IPC_STR_ID_SHIFT; +} + +static inline u32 msg_get_notify_reason(u32 msg) +{ + return (msg & IPC_STG_TYPE_MASK) >> IPC_STG_TYPE_SHIFT; +} + +u32 create_channel_map(enum sst_hsw_channel_config config) +{ + switch (config) { + case SST_HSW_CHANNEL_CONFIG_MONO: + return (0xFFFFFFF0 | SST_HSW_CHANNEL_CENTER); + case SST_HSW_CHANNEL_CONFIG_STEREO: + return (0xFFFFFF00 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_RIGHT << 4)); + case SST_HSW_CHANNEL_CONFIG_2_POINT_1: + return (0xFFFFF000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_RIGHT << 4) + | (SST_HSW_CHANNEL_LFE << 8 )); + case SST_HSW_CHANNEL_CONFIG_3_POINT_0: + return (0xFFFFF000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_CENTER << 4) + | (SST_HSW_CHANNEL_RIGHT << 8)); + case SST_HSW_CHANNEL_CONFIG_3_POINT_1: + return (0xFFFF0000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_CENTER << 4) + | (SST_HSW_CHANNEL_RIGHT << 8) + | (SST_HSW_CHANNEL_LFE << 12)); + case SST_HSW_CHANNEL_CONFIG_QUATRO: + return (0xFFFF0000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_RIGHT << 4) + | (SST_HSW_CHANNEL_LEFT_SURROUND << 8) + | (SST_HSW_CHANNEL_RIGHT_SURROUND << 12)); + case SST_HSW_CHANNEL_CONFIG_4_POINT_0: + return (0xFFFF0000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_CENTER << 4) + | (SST_HSW_CHANNEL_RIGHT << 8) + | (SST_HSW_CHANNEL_CENTER_SURROUND << 12)); + case SST_HSW_CHANNEL_CONFIG_5_POINT_0: + return (0xFFF00000 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_CENTER << 4) + | (SST_HSW_CHANNEL_RIGHT << 8) + | (SST_HSW_CHANNEL_LEFT_SURROUND << 12) + | (SST_HSW_CHANNEL_RIGHT_SURROUND << 16)); + case SST_HSW_CHANNEL_CONFIG_5_POINT_1: + return (0xFF000000 | SST_HSW_CHANNEL_CENTER + | (SST_HSW_CHANNEL_LEFT << 4) + | (SST_HSW_CHANNEL_RIGHT << 8) + | (SST_HSW_CHANNEL_LEFT_SURROUND << 12) + | (SST_HSW_CHANNEL_RIGHT_SURROUND << 16) + | (SST_HSW_CHANNEL_LFE << 20)); + case SST_HSW_CHANNEL_CONFIG_DUAL_MONO: + return (0xFFFFFF00 | SST_HSW_CHANNEL_LEFT + | (SST_HSW_CHANNEL_LEFT << 4)); + default: + return 0xFFFFFFFF; + } +} + +static struct sst_hsw_stream *get_stream_by_id(struct sst_hsw *hsw, + int stream_id) +{ + struct sst_hsw_stream *stream; + + list_for_each_entry(stream, &hsw->stream_list, node) { + if (stream->reply.stream_hw_id == stream_id) + return stream; + } + + return NULL; +} + +static void ipc_shim_dbg(struct sst_hsw *hsw, const char *text) +{ + struct sst_dsp *sst = hsw->dsp; + u32 isr, ipcd, imrx, ipcx; + + ipcx = sst_dsp_shim_read_unlocked(sst, SST_IPCX); + isr = sst_dsp_shim_read_unlocked(sst, SST_ISRX); + ipcd = sst_dsp_shim_read_unlocked(sst, SST_IPCD); + imrx = sst_dsp_shim_read_unlocked(sst, SST_IMRX); + + dev_err(hsw->dev, "ipc: --%s-- ipcx 0x%8.8x isr 0x%8.8x ipcd 0x%8.8x imrx 0x%8.8x\n", + text, ipcx, isr, ipcd, imrx); +} + +/* locks held by caller */ +static struct ipc_message *msg_get_empty(struct sst_hsw *hsw) +{ + struct ipc_message *msg = NULL; + + if (!list_empty(&hsw->empty_list)) { + msg = list_first_entry(&hsw->empty_list, struct ipc_message, + list); + list_del(&msg->list); + } + + return msg; +} + +static void ipc_tx_msgs(struct kthread_work *work) +{ + struct sst_hsw *hsw = + container_of(work, struct sst_hsw, kwork); + struct ipc_message *msg; + unsigned long flags; + u32 ipcx; + + spin_lock_irqsave(&hsw->dsp->spinlock, flags); + + if (list_empty(&hsw->tx_list) || hsw->pending) { + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); + return; + } + + /* if the DSP is busy we will TX messages after IRQ */ + ipcx = sst_dsp_shim_read_unlocked(hsw->dsp, SST_IPCX); + if (ipcx & SST_IPCX_BUSY) { + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); + return; + } + + msg = list_first_entry(&hsw->tx_list, struct ipc_message, list); + + list_move(&msg->list, &hsw->rx_list); + + /* send the message */ + sst_dsp_outbox_write(hsw->dsp, msg->tx_data, msg->tx_size); + sst_dsp_ipc_msg_tx(hsw->dsp, msg->header | SST_IPCX_BUSY); + + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); +} + +/* locks held by caller */ +static void tx_msg_reply_complete(struct sst_hsw *hsw, struct ipc_message *msg) +{ + msg->complete = true; + trace_ipc_reply("completed", msg->header); + + if (!msg->wait) + list_add_tail(&msg->list, &hsw->empty_list); + else + wake_up(&msg->waitq); +} + +static int tx_wait_done(struct sst_hsw *hsw, struct ipc_message *msg, + void *rx_data) +{ + unsigned long flags; + int ret; + + /* wait for DSP completion (in all cases atm inc pending) */ + ret = wait_event_timeout(msg->waitq, msg->complete, + msecs_to_jiffies(IPC_TIMEOUT_MSECS)); + + spin_lock_irqsave(&hsw->dsp->spinlock, flags); + if (ret == 0) { + ipc_shim_dbg(hsw, "message timeout"); + + trace_ipc_error("error message timeout for", msg->header); + ret = -ETIMEDOUT; + } else { + + /* copy the data returned from DSP */ + if (msg->rx_size) + memcpy(rx_data, msg->rx_data, msg->rx_size); + ret = msg->errno; + } + + list_add_tail(&msg->list, &hsw->empty_list); + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); + return ret; +} + +static int ipc_tx_message(struct sst_hsw *hsw, u32 header, void *tx_data, + size_t tx_bytes, void *rx_data, size_t rx_bytes, int wait) +{ + struct ipc_message *msg; + unsigned long flags; + + spin_lock_irqsave(&hsw->dsp->spinlock, flags); + + msg = msg_get_empty(hsw); + if (msg == NULL) { + spin_unlock(&hsw->dsp->spinlock); + return -EBUSY; + } + + if (tx_bytes) + memcpy(msg->tx_data, tx_data, tx_bytes); + + msg->header = header; + msg->tx_size = tx_bytes; + msg->rx_size = rx_bytes; + msg->wait = wait; + msg->errno = 0; + msg->pending = false; + msg->complete = false; + + list_add_tail(&msg->list, &hsw->tx_list); + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); + + queue_kthread_work(&hsw->kworker, &hsw->kwork); + + if (wait) + return tx_wait_done(hsw, msg, rx_data); + else + return 0; +} + +static inline int ipc_tx_message_wait(struct sst_hsw *hsw, u32 header, + void *tx_data, size_t tx_bytes, void *rx_data, size_t rx_bytes) +{ + return ipc_tx_message(hsw, header, tx_data, tx_bytes, rx_data, + rx_bytes, 1); +} + +static inline int ipc_tx_message_nowait(struct sst_hsw *hsw, u32 header, + void *tx_data, size_t tx_bytes) +{ + return ipc_tx_message(hsw, header, tx_data, tx_bytes, NULL, 0, 0); +} + +static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) +{ + struct sst_hsw_ipc_fw_ready fw_ready; + u32 offset; + + offset = (header & 0x1FFFFFFF) << 3; + + dev_dbg(hsw->dev, "ipc: DSP is ready 0x%8.8x offset %d\n", + header, offset); + + /* copy data from the DSP FW ready offset */ + sst_dsp_read(hsw->dsp, &fw_ready, offset, sizeof(fw_ready)); + + sst_dsp_mailbox_init(hsw->dsp, fw_ready.inbox_offset, + fw_ready.inbox_size, fw_ready.outbox_offset, + fw_ready.outbox_size); + + hsw->boot_complete = true; + wake_up(&hsw->boot_wait); + + dev_dbg(hsw->dev, " mailbox upstream 0x%x - size 0x%x\n", + fw_ready.inbox_offset, fw_ready.inbox_size); + dev_dbg(hsw->dev, " mailbox downstream 0x%x - size 0x%x\n", + fw_ready.outbox_offset, fw_ready.outbox_size); +} + +static void hsw_notification_work(struct work_struct *work) +{ + struct sst_hsw_stream *stream = container_of(work, + struct sst_hsw_stream, notify_work); + struct sst_hsw_ipc_stream_glitch_position *glitch = &stream->glitch; + struct sst_hsw_ipc_stream_get_position *pos = &stream->rpos; + struct sst_hsw *hsw = stream->hsw; + u32 reason; + + reason = msg_get_notify_reason(stream->header); + + switch (reason) { + case IPC_STG_GLITCH: + trace_ipc_notification("DSP stream under/overrun", + stream->reply.stream_hw_id); + sst_dsp_inbox_read(hsw->dsp, glitch, sizeof(*glitch)); + + dev_err(hsw->dev, "glitch %d pos 0x%x write pos 0x%x\n", + glitch->glitch_type, glitch->present_pos, + glitch->write_pos); + break; + + case IPC_POSITION_CHANGED: + trace_ipc_notification("DSP stream position changed for", + stream->reply.stream_hw_id); + sst_dsp_inbox_read(hsw->dsp, pos, sizeof(&pos)); + + if (stream->notify_position) + stream->notify_position(stream, stream->pdata); + + break; + default: + dev_err(hsw->dev, "error: unknown notification 0x%x\n", + stream->header); + break; + } + + /* tell DSP that notification has been handled */ + sst_dsp_shim_update_bits_unlocked(hsw->dsp, SST_IPCD, + SST_IPCD_BUSY | SST_IPCD_DONE, SST_IPCD_DONE); + + /* unmask busy interrupt */ + sst_dsp_shim_update_bits_unlocked(hsw->dsp, SST_IMRX, SST_IMRX_BUSY, 0); +} + +static struct ipc_message *reply_find_msg(struct sst_hsw *hsw, u32 header) +{ + struct ipc_message *msg; + + /* clear reply bits & status bits */ + header &= ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK); + + if (list_empty(&hsw->rx_list)) { + dev_err(hsw->dev, "error: rx list empty but received 0x%x\n", + header); + return NULL; + } + + list_for_each_entry(msg, &hsw->rx_list, list) { + if (msg->header == header) + return msg; + } + + return NULL; +} + +static void hsw_stream_update(struct sst_hsw *hsw, struct ipc_message *msg) +{ + struct sst_hsw_stream *stream; + u32 header = msg->header & ~(IPC_STATUS_MASK | IPC_GLB_REPLY_MASK); + u32 stream_id = msg_get_stream_id(header); + u32 stream_msg = msg_get_stream_type(header); + + stream = get_stream_by_id(hsw, stream_id); + if (stream == NULL) + return; + + switch (stream_msg) { + case IPC_STR_STAGE_MESSAGE: + case IPC_STR_NOTIFICATION: + case IPC_STR_RESET: + break; + case IPC_STR_PAUSE: + stream->running = false; + trace_ipc_notification("stream paused", + stream->reply.stream_hw_id); + break; + case IPC_STR_RESUME: + stream->running = true; + trace_ipc_notification("stream running", + stream->reply.stream_hw_id); + break; + } +} + +static int hsw_process_reply(struct sst_hsw *hsw, u32 header) +{ + struct ipc_message *msg; + u32 reply = msg_get_global_reply(header); + + trace_ipc_reply("processing -->", header); + + msg = reply_find_msg(hsw, header); + if (msg == NULL) { + trace_ipc_error("error: can't find message header", header); + return -EIO; + } + + /* first process the header */ + switch (reply) { + case IPC_GLB_REPLY_PENDING: + trace_ipc_pending_reply("received", header); + msg->pending = true; + hsw->pending = true; + return 1; + case IPC_GLB_REPLY_SUCCESS: + if (msg->pending) { + trace_ipc_pending_reply("completed", header); + sst_dsp_inbox_read(hsw->dsp, msg->rx_data, + msg->rx_size); + hsw->pending = false; + } else { + /* copy data from the DSP */ + sst_dsp_outbox_read(hsw->dsp, msg->rx_data, + msg->rx_size); + } + break; + /* these will be rare - but useful for debug */ + case IPC_GLB_REPLY_UNKNOWN_MESSAGE_TYPE: + trace_ipc_error("error: unknown message type", header); + msg->errno = -EBADMSG; + break; + case IPC_GLB_REPLY_OUT_OF_RESOURCES: + trace_ipc_error("error: out of resources", header); + msg->errno = -ENOMEM; + break; + case IPC_GLB_REPLY_BUSY: + trace_ipc_error("error: reply busy", header); + msg->errno = -EBUSY; + break; + case IPC_GLB_REPLY_FAILURE: + trace_ipc_error("error: reply failure", header); + msg->errno = -EINVAL; + break; + case IPC_GLB_REPLY_STAGE_UNINITIALIZED: + trace_ipc_error("error: stage uninitialized", header); + msg->errno = -EINVAL; + break; + case IPC_GLB_REPLY_NOT_FOUND: + trace_ipc_error("error: reply not found", header); + msg->errno = -EINVAL; + break; + case IPC_GLB_REPLY_SOURCE_NOT_STARTED: + trace_ipc_error("error: source not started", header); + msg->errno = -EINVAL; + break; + case IPC_GLB_REPLY_INVALID_REQUEST: + trace_ipc_error("error: invalid request", header); + msg->errno = -EINVAL; + break; + case IPC_GLB_REPLY_ERROR_INVALID_PARAM: + trace_ipc_error("error: invalid parameter", header); + msg->errno = -EINVAL; + break; + default: + trace_ipc_error("error: unknown reply", header); + msg->errno = -EINVAL; + break; + } + + /* update any stream states */ + hsw_stream_update(hsw, msg); + + /* wake up and return the error if we have waiters on this message ? */ + list_del(&msg->list); + tx_msg_reply_complete(hsw, msg); + + return 1; +} + +static int hsw_stream_message(struct sst_hsw *hsw, u32 header) +{ + u32 stream_msg, stream_id, stage_type; + struct sst_hsw_stream *stream; + int handled = 0; + + stream_msg = msg_get_stream_type(header); + stream_id = msg_get_stream_id(header); + stage_type = msg_get_stage_type(header); + + stream = get_stream_by_id(hsw, stream_id); + if (stream == NULL) + return handled; + + stream->header = header; + + switch (stream_msg) { + case IPC_STR_STAGE_MESSAGE: + dev_err(hsw->dev, "error: stage msg not implemented 0x%8.8x\n", + header); + break; + case IPC_STR_NOTIFICATION: + schedule_work(&stream->notify_work); + break; + default: + /* handle pending message complete request */ + handled = hsw_process_reply(hsw, header); + break; + } + + return handled; +} + +static int hsw_log_message(struct sst_hsw *hsw, u32 header) +{ + u32 operation = (header & IPC_LOG_OP_MASK) >> IPC_LOG_OP_SHIFT; + struct sst_hsw_log_stream *stream = &hsw->log_stream; + int ret = 1; + + if (operation != IPC_DEBUG_REQUEST_LOG_DUMP) { + dev_err(hsw->dev, + "error: log msg not implemented 0x%8.8x\n", header); + return 0; + } + + mutex_lock(&stream->rw_mutex); + stream->last_pos = stream->curr_pos; + sst_dsp_inbox_read( + hsw->dsp, &stream->curr_pos, sizeof(stream->curr_pos)); + mutex_unlock(&stream->rw_mutex); + + schedule_work(&stream->notify_work); + + return ret; +} + +static int hsw_process_notification(struct sst_hsw *hsw) +{ + struct sst_dsp *sst = hsw->dsp; + u32 type, header; + int handled = 1; + + header = sst_dsp_shim_read_unlocked(sst, SST_IPCD); + type = msg_get_global_type(header); + + trace_ipc_request("processing -->", header); + + /* FW Ready is a special case */ + if (!hsw->boot_complete && header & IPC_FW_READY) { + hsw_fw_ready(hsw, header); + return handled; + } + + switch (type) { + case IPC_GLB_GET_FW_VERSION: + case IPC_GLB_ALLOCATE_STREAM: + case IPC_GLB_FREE_STREAM: + case IPC_GLB_GET_FW_CAPABILITIES: + case IPC_GLB_REQUEST_DUMP: + case IPC_GLB_GET_DEVICE_FORMATS: + case IPC_GLB_SET_DEVICE_FORMATS: + case IPC_GLB_ENTER_DX_STATE: + case IPC_GLB_GET_MIXER_STREAM_INFO: + case IPC_GLB_MAX_IPC_MESSAGE_TYPE: + case IPC_GLB_RESTORE_CONTEXT: + case IPC_GLB_SHORT_REPLY: + dev_err(hsw->dev, "error: message type %d header 0x%x\n", + type, header); + break; + case IPC_GLB_STREAM_MESSAGE: + handled = hsw_stream_message(hsw, header); + break; + case IPC_GLB_DEBUG_LOG_MESSAGE: + handled = hsw_log_message(hsw, header); + break; + default: + dev_err(hsw->dev, "error: unexpected type %d hdr 0x%8.8x\n", + type, header); + break; + } + + return handled; +} + +static irqreturn_t hsw_irq_thread(int irq, void *context) +{ + struct sst_dsp *sst = (struct sst_dsp *) context; + struct sst_hsw *hsw = sst_dsp_get_thread_context(sst); + u32 ipcx, ipcd; + int handled; + unsigned long flags; + + spin_lock_irqsave(&sst->spinlock, flags); + + ipcx = sst_dsp_ipc_msg_rx(hsw->dsp); + ipcd = sst_dsp_shim_read_unlocked(sst, SST_IPCD); + + /* reply message from DSP */ + if (ipcx & SST_IPCX_DONE) { + + /* Handle Immediate reply from DSP Core */ + handled = hsw_process_reply(hsw, ipcx); + + if (handled) { + /* clear DONE bit - tell DSP we have completed */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IPCX, + SST_IPCX_DONE, 0); + + /* unmask Done interrupt */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, + SST_IMRX_DONE, 0); + } + } + + /* new message from DSP */ + if (ipcd & SST_IPCD_BUSY) { + + /* Handle Notification and Delayed reply from DSP Core */ + handled = hsw_process_notification(hsw); + + /* clear BUSY bit and set DONE bit - accept new messages */ + if (handled) { + sst_dsp_shim_update_bits_unlocked(sst, SST_IPCD, + SST_IPCD_BUSY | SST_IPCD_DONE, SST_IPCD_DONE); + + /* unmask busy interrupt */ + sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, + SST_IMRX_BUSY, 0); + } + } + + spin_unlock_irqrestore(&sst->spinlock, flags); + + /* continue to send any remaining messages... */ + queue_kthread_work(&hsw->kworker, &hsw->kwork); + + return IRQ_HANDLED; +} + +int sst_hsw_fw_get_version(struct sst_hsw *hsw, + struct sst_hsw_ipc_fw_version *version) +{ + int ret; + + ret = ipc_tx_message_wait(hsw, IPC_GLB_TYPE(IPC_GLB_GET_FW_VERSION), + NULL, 0, version, sizeof(*version)); + if (ret < 0) + dev_err(hsw->dev, "error: get version failed\n"); + + return ret; +} + +/* Mixer Controls */ +int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 stage_id, u32 channel) +{ + int ret; + + ret = sst_hsw_stream_get_volume(hsw, stream, stage_id, channel, + &stream->mute_volume[channel]); + if (ret < 0) + return ret; + + ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, 0); + if (ret < 0) { + dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n", + stream->reply.stream_hw_id, channel); + return ret; + } + + stream->mute[channel] = 1; + return 0; +} + +int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 stage_id, u32 channel) + +{ + int ret; + + stream->mute[channel] = 0; + ret = sst_hsw_stream_set_volume(hsw, stream, stage_id, channel, + stream->mute_volume[channel]); + if (ret < 0) { + dev_err(hsw->dev, "error: can't unmute stream %d channel %d\n", + stream->reply.stream_hw_id, channel); + return ret; + } + + return 0; +} + +int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 stage_id, u32 channel, u32 *volume) +{ + if (channel > 1) + return -EINVAL; + + sst_dsp_read(hsw->dsp, volume, + stream->reply.volume_register_address[channel], sizeof(volume)); + + return 0; +} + +int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u64 curve_duration, + enum sst_hsw_volume_curve curve) +{ + /* curve duration in steps of 100ns */ + stream->vol_req.curve_duration = curve_duration; + stream->vol_req.curve_type = curve; + + return 0; +} + +/* stream volume */ +int sst_hsw_stream_set_volume(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume) +{ + struct sst_hsw_ipc_volume_req *req; + u32 header; + int ret; + + trace_ipc_request("set stream volume", stream->reply.stream_hw_id); + + if (channel > 1) + return -EINVAL; + + if (stream->mute[channel]) { + stream->mute_volume[channel] = volume; + return 0; + } + + header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | + IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); + header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); + header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); + header |= (stage_id << IPC_STG_ID_SHIFT); + + req = &stream->vol_req; + req->channel = channel; + req->target_volume = volume; + + ret = ipc_tx_message_wait(hsw, header, req, sizeof(*req), NULL, 0); + if (ret < 0) { + dev_err(hsw->dev, "error: set stream volume failed\n"); + return ret; + } + + return 0; +} + +int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel) +{ + int ret; + + ret = sst_hsw_mixer_get_volume(hsw, stage_id, channel, + &hsw->mute_volume[channel]); + if (ret < 0) + return ret; + + ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, 0); + if (ret < 0) { + dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n", + channel); + return ret; + } + + hsw->mute[channel] = 1; + return 0; +} + +int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel) +{ + int ret; + + ret = sst_hsw_mixer_set_volume(hsw, stage_id, channel, + hsw->mixer_info.volume_register_address[channel]); + if (ret < 0) { + dev_err(hsw->dev, "error: failed to unmute mixer channel %d\n", + channel); + return ret; + } + + hsw->mute[channel] = 0; + return 0; +} + +int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, + u32 *volume) +{ + if (channel > 1) + return -EINVAL; + + sst_dsp_read(hsw->dsp, volume, + hsw->mixer_info.volume_register_address[channel], + sizeof(*volume)); + + return 0; +} + +int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw, + u64 curve_duration, enum sst_hsw_volume_curve curve) +{ + /* curve duration in steps of 100ns */ + hsw->curve_duration = curve_duration; + hsw->curve_type = curve; + + return 0; +} + +/* global mixer volume */ +int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, + u32 volume) +{ + struct sst_hsw_ipc_volume_req req; + u32 header; + int ret; + + trace_ipc_request("set mixer volume", volume); + + /* set both at same time ? */ + if (channel == 2) { + if (hsw->mute[0] && hsw->mute[1]) { + hsw->mute_volume[0] = hsw->mute_volume[1] = volume; + return 0; + } else if (hsw->mute[0]) + req.channel = 1; + else if (hsw->mute[1]) + req.channel = 0; + else + req.channel = 0xffffffff; + } else { + /* set only 1 channel */ + if (hsw->mute[channel]) { + hsw->mute_volume[channel] = volume; + return 0; + } + req.channel = channel; + } + + header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | + IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); + header |= (hsw->mixer_info.mixer_hw_id << IPC_STR_ID_SHIFT); + header |= (IPC_STG_SET_VOLUME << IPC_STG_TYPE_SHIFT); + header |= (stage_id << IPC_STG_ID_SHIFT); + + req.curve_duration = hsw->curve_duration; + req.curve_type = hsw->curve_type; + req.target_volume = volume; + + ret = ipc_tx_message_wait(hsw, header, &req, sizeof(req), NULL, 0); + if (ret < 0) { + dev_err(hsw->dev, "error: set mixer volume failed\n"); + return ret; + } + + return 0; +} + +/* Stream API */ +struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, + u32 (*notify_position)(struct sst_hsw_stream *stream, void *data), + void *data) +{ + struct sst_hsw_stream *stream; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (stream == NULL) + return NULL; + + list_add(&stream->node, &hsw->stream_list); + stream->notify_position = notify_position; + stream->pdata = data; + stream->hsw = hsw; + stream->host_id = id; + + /* work to process notification messages */ + INIT_WORK(&stream->notify_work, hsw_notification_work); + + return stream; +} + +int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream) +{ + u32 header; + int ret = 0; + + /* dont free DSP streams that are not commited */ + if (!stream->commited) + goto out; + + trace_ipc_request("stream free", stream->host_id); + + stream->free_req.stream_id = stream->reply.stream_hw_id; + header = IPC_GLB_TYPE(IPC_GLB_FREE_STREAM); + + ret = ipc_tx_message_wait(hsw, header, &stream->free_req, + sizeof(stream->free_req), NULL, 0); + if (ret < 0) { + dev_err(hsw->dev, "error: free stream %d failed\n", + stream->free_req.stream_id); + return -EAGAIN; + } + + trace_hsw_stream_free_req(stream, &stream->free_req); + +out: + list_del(&stream->node); + kfree(stream); + + return ret; +} + +int sst_hsw_stream_set_bits(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, enum sst_hsw_bitdepth bits) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set bits\n"); + return -EINVAL; + } + + stream->request.format.bitdepth = bits; + return 0; +} + +int sst_hsw_stream_set_channels(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, int channels) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set channels\n"); + return -EINVAL; + } + + /* stereo is only supported atm */ + if (channels != 2) + return -EINVAL; + + stream->request.format.ch_num = channels; + return 0; +} + +int sst_hsw_stream_set_rate(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, int rate) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set rate\n"); + return -EINVAL; + } + + stream->request.format.frequency = rate; + return 0; +} + +int sst_hsw_stream_set_map_config(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 map, + enum sst_hsw_channel_config config) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set map\n"); + return -EINVAL; + } + + stream->request.format.map = map; + stream->request.format.config = config; + return 0; +} + +int sst_hsw_stream_set_style(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, enum sst_hsw_interleaving style) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set style\n"); + return -EINVAL; + } + + stream->request.format.style = style; + return 0; +} + +int sst_hsw_stream_set_valid(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 bits) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set valid bits\n"); + return -EINVAL; + } + + stream->request.format.valid_bit = bits; + return 0; +} + +/* Stream Configuration */ +int sst_hsw_stream_format(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + enum sst_hsw_stream_path_id path_id, + enum sst_hsw_stream_type stream_type, + enum sst_hsw_stream_format format_id) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set format\n"); + return -EINVAL; + } + + stream->request.path_id = path_id; + stream->request.stream_type = stream_type; + stream->request.format_id = format_id; + + trace_hsw_stream_alloc_request(stream, &stream->request); + + return 0; +} + +int sst_hsw_stream_buffer(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 ring_pt_address, u32 num_pages, + u32 ring_size, u32 ring_offset, u32 ring_first_pfn) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for buffer\n"); + return -EINVAL; + } + + stream->request.ringinfo.ring_pt_address = ring_pt_address; + stream->request.ringinfo.num_pages = num_pages; + stream->request.ringinfo.ring_size = ring_size; + stream->request.ringinfo.ring_offset = ring_offset; + stream->request.ringinfo.ring_first_pfn = ring_first_pfn; + + trace_hsw_stream_buffer(stream); + + return 0; +} + +int sst_hsw_stream_set_module_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, enum sst_hsw_module_id module_id, + u32 entry_point) +{ + struct sst_hsw_module_map *map = &stream->request.map; + + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set module\n"); + return -EINVAL; + } + + /* only support initial module atm */ + map->module_entries_count = 1; + map->module_entries[0].module_id = module_id; + map->module_entries[0].entry_point = entry_point; + + return 0; +} + +int sst_hsw_stream_set_pmemory_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 offset, u32 size) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set pmem\n"); + return -EINVAL; + } + + stream->request.persistent_mem.offset = offset; + stream->request.persistent_mem.size = size; + + return 0; +} + +int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 offset, u32 size) +{ + if (stream->commited) { + dev_err(hsw->dev, "error: stream committed for set smem\n"); + return -EINVAL; + } + + stream->request.scratch_mem.offset = offset; + stream->request.scratch_mem.size = size; + + return 0; +} + +int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream) +{ + struct sst_hsw_ipc_stream_alloc_req *str_req = &stream->request; + struct sst_hsw_ipc_stream_alloc_reply *reply = &stream->reply; + u32 header; + int ret; + + trace_ipc_request("stream alloc", stream->host_id); + + header = IPC_GLB_TYPE(IPC_GLB_ALLOCATE_STREAM); + + ret = ipc_tx_message_wait(hsw, header, str_req, sizeof(*str_req), + reply, sizeof(*reply)); + if (ret < 0) { + dev_err(hsw->dev, "error: stream commit failed\n"); + return ret; + } + + stream->commited = 1; + trace_hsw_stream_alloc_reply(stream); + + return 0; +} + +/* Stream Information - these calls could be inline but we want the IPC + ABI to be opaque to client PCM drivers to cope with any future ABI changes */ +int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + return stream->reply.stream_hw_id; +} + +int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + return stream->reply.mixer_hw_id; +} + +u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + return stream->reply.read_position_register_address; +} + +u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + return stream->reply.presentation_position_register_address; +} + +u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 channel) +{ + if (channel >= 2) + return 0; + + return stream->reply.peak_meter_register_address[channel]; +} + +u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 channel) +{ + if (channel >= 2) + return 0; + + return stream->reply.volume_register_address[channel]; +} + +int sst_hsw_mixer_get_info(struct sst_hsw *hsw) +{ + struct sst_hsw_ipc_stream_info_reply *reply; + u32 header; + int ret; + + reply = &hsw->mixer_info; + header = IPC_GLB_TYPE(IPC_GLB_GET_MIXER_STREAM_INFO); + + trace_ipc_request("get global mixer info", 0); + + ret = ipc_tx_message_wait(hsw, header, NULL, 0, reply, sizeof(*reply)); + if (ret < 0) { + dev_err(hsw->dev, "error: get stream info failed\n"); + return ret; + } + + trace_hsw_mixer_info_reply(reply); + + return 0; +} + +/* Send stream command */ +static int sst_hsw_stream_operations(struct sst_hsw *hsw, int type, + int stream_id, int wait) +{ + u32 header; + + header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | IPC_STR_TYPE(type); + header |= (stream_id << IPC_STR_ID_SHIFT); + + if (wait) + return ipc_tx_message_wait(hsw, header, NULL, 0, NULL, 0); + else + return ipc_tx_message_nowait(hsw, header, NULL, 0); +} + +/* Stream ALSA trigger operations */ +int sst_hsw_stream_pause(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + int wait) +{ + int ret; + + trace_ipc_request("stream pause", stream->reply.stream_hw_id); + + ret = sst_hsw_stream_operations(hsw, IPC_STR_PAUSE, + stream->reply.stream_hw_id, wait); + if (ret < 0) + dev_err(hsw->dev, "error: failed to pause stream %d\n", + stream->reply.stream_hw_id); + + return ret; +} + +int sst_hsw_stream_resume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + int wait) +{ + int ret; + + trace_ipc_request("stream resume", stream->reply.stream_hw_id); + + ret = sst_hsw_stream_operations(hsw, IPC_STR_RESUME, + stream->reply.stream_hw_id, wait); + if (ret < 0) + dev_err(hsw->dev, "error: failed to resume stream %d\n", + stream->reply.stream_hw_id); + + return ret; +} + +int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream) +{ + int ret, tries = 10; + + /* dont reset streams that are not commited */ + if (!stream->commited) + return 0; + + /* wait for pause to complete before we reset the stream */ + while (stream->running && tries--) + msleep(1); + if (!tries) { + dev_err(hsw->dev, "error: reset stream %d still running\n", + stream->reply.stream_hw_id); + return -EINVAL; + } + + trace_ipc_request("stream reset", stream->reply.stream_hw_id); + + ret = sst_hsw_stream_operations(hsw, IPC_STR_RESET, + stream->reply.stream_hw_id, 1); + if (ret < 0) + dev_err(hsw->dev, "error: failed to reset stream %d\n", + stream->reply.stream_hw_id); + return ret; +} + +/* Stream pointer positions */ +int sst_hsw_get_dsp_position(struct sst_hsw *hsw, + struct sst_hsw_stream *stream) +{ + return stream->rpos.position; +} + +int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 stage_id, u32 position) +{ + u32 header; + int ret; + + trace_stream_write_position(stream->reply.stream_hw_id, position); + + header = IPC_GLB_TYPE(IPC_GLB_STREAM_MESSAGE) | + IPC_STR_TYPE(IPC_STR_STAGE_MESSAGE); + header |= (stream->reply.stream_hw_id << IPC_STR_ID_SHIFT); + header |= (IPC_STG_SET_WRITE_POSITION << IPC_STG_TYPE_SHIFT); + header |= (stage_id << IPC_STG_ID_SHIFT); + stream->wpos.position = position; + + ret = ipc_tx_message_nowait(hsw, header, &stream->wpos, + sizeof(stream->wpos)); + if (ret < 0) + dev_err(hsw->dev, "error: stream %d set position %d failed\n", + stream->reply.stream_hw_id, position); + + return ret; +} + +/* physical BE config */ +int sst_hsw_device_set_config(struct sst_hsw *hsw, + enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, + enum sst_hsw_device_mode mode, u32 clock_divider) +{ + struct sst_hsw_ipc_device_config_req config; + u32 header; + int ret; + + trace_ipc_request("set device config", dev); + + config.ssp_interface = dev; + config.clock_frequency = mclk; + config.mode = mode; + config.clock_divider = clock_divider; + + trace_hsw_device_config_req(&config); + + header = IPC_GLB_TYPE(IPC_GLB_SET_DEVICE_FORMATS); + + ret = ipc_tx_message_wait(hsw, header, &config, sizeof(config), + NULL, 0); + if (ret < 0) + dev_err(hsw->dev, "error: set device formats failed\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(sst_hsw_device_set_config); + +/* DX Config */ +int sst_hsw_dx_set_state(struct sst_hsw *hsw, + enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx) +{ + u32 header, state_; + int ret; + + header = IPC_GLB_TYPE(IPC_GLB_ENTER_DX_STATE); + state_ = state; + + trace_ipc_request("PM enter Dx state", state); + + ret = ipc_tx_message_wait(hsw, header, &state_, sizeof(state_), + dx, sizeof(dx)); + if (ret < 0) { + dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state); + return ret; + } + + dev_dbg(hsw->dev, "ipc: got %d entry numbers for state %d\n", + dx->entries_no, state); + + memcpy(&hsw->dx, dx, sizeof(*dx)); + return 0; +} + +/* Used to save state into hsw->dx_reply */ +int sst_hsw_dx_get_state(struct sst_hsw *hsw, u32 item, + u32 *offset, u32 *size, u32 *source) +{ + struct sst_hsw_ipc_dx_memory_item *dx_mem; + struct sst_hsw_ipc_dx_reply *dx_reply; + int entry_no; + + dx_reply = &hsw->dx; + entry_no = dx_reply->entries_no; + + trace_ipc_request("PM get Dx state", entry_no); + + if (item >= entry_no) + return -EINVAL; + + dx_mem = &dx_reply->mem_info[item]; + *offset = dx_mem->offset; + *size = dx_mem->size; + *source = dx_mem->source; + + return 0; +} + +static int msg_empty_list_init(struct sst_hsw *hsw) +{ + int i; + + hsw->msg = kzalloc(sizeof(struct ipc_message) * + IPC_EMPTY_LIST_SIZE, GFP_KERNEL); + if (hsw->msg == NULL) + return -ENOMEM; + + for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { + init_waitqueue_head(&hsw->msg[i].waitq); + list_add(&hsw->msg[i].list, &hsw->empty_list); + } + + return 0; +} + +void sst_hsw_set_scratch_module(struct sst_hsw *hsw, + struct sst_module *scratch) +{ + hsw->scratch = scratch; +} + +struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw) +{ + return hsw->dsp; +} + +static struct sst_dsp_device hsw_dev = { + .thread = hsw_irq_thread, + .ops = &haswell_ops, +}; + +int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_hsw_ipc_fw_version version; + struct sst_hsw *hsw; + struct sst_fw *hsw_sst_fw; + int ret; + + dev_dbg(dev, "initialising Audio DSP IPC\n"); + + hsw = devm_kzalloc(dev, sizeof(*hsw), GFP_KERNEL); + if (hsw == NULL) + return -ENOMEM; + + hsw->dev = dev; + INIT_LIST_HEAD(&hsw->stream_list); + INIT_LIST_HEAD(&hsw->tx_list); + INIT_LIST_HEAD(&hsw->rx_list); + INIT_LIST_HEAD(&hsw->empty_list); + init_waitqueue_head(&hsw->boot_wait); + init_waitqueue_head(&hsw->wait_txq); + + ret = msg_empty_list_init(hsw); + if (ret < 0) + goto list_err; + + /* start the IPC message thread */ + init_kthread_worker(&hsw->kworker); + hsw->tx_thread = kthread_run(kthread_worker_fn, + &hsw->kworker, + dev_name(hsw->dev)); + if (IS_ERR(hsw->tx_thread)) { + ret = PTR_ERR(hsw->tx_thread); + dev_err(hsw->dev, "error: failed to create message TX task\n"); + goto list_err; + } + init_kthread_work(&hsw->kwork, ipc_tx_msgs); + + hsw_dev.thread_context = hsw; + + /* init SST shim */ + hsw->dsp = sst_dsp_new(dev, &hsw_dev, pdata); + if (hsw->dsp == NULL) { + ret = -ENODEV; + goto list_err; + } + + /* keep the DSP in reset state for base FW loading */ + sst_dsp_reset(hsw->dsp); + + hsw_sst_fw = sst_fw_new(hsw->dsp, pdata->fw, hsw); + + if (hsw_sst_fw == NULL) { + ret = -ENODEV; + dev_err(dev, "error: failed to load firmware\n"); + goto fw_err; + } + + /* wait for DSP boot completion */ + sst_dsp_boot(hsw->dsp); + ret = wait_event_timeout(hsw->boot_wait, hsw->boot_complete, + msecs_to_jiffies(IPC_BOOT_MSECS)); + if (ret == 0) { + ret = -EIO; + dev_err(hsw->dev, "error: ADSP boot timeout\n"); + goto boot_err; + } + + /* get the FW version */ + sst_hsw_fw_get_version(hsw, &version); + dev_info(hsw->dev, "FW loaded: type %d - version: %d.%d build %d\n", + version.type, version.major, version.minor, version.build); + + /* get the globalmixer */ + ret = sst_hsw_mixer_get_info(hsw); + if (ret < 0) { + dev_err(hsw->dev, "error: failed to get stream info\n"); + goto boot_err; + } + + pdata->dsp = hsw; + return 0; + +boot_err: + sst_dsp_reset(hsw->dsp); + sst_fw_free(hsw_sst_fw); +fw_err: + sst_dsp_free(hsw->dsp); + kfree(hsw->msg); +list_err: + return ret; +} +EXPORT_SYMBOL_GPL(sst_hsw_dsp_init); + +void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_hsw *hsw = pdata->dsp; + + sst_dsp_reset(hsw->dsp); + sst_fw_free_all(hsw->dsp); + sst_dsp_free(hsw->dsp); + kfree(hsw->scratch); + kfree(hsw->msg); +} +EXPORT_SYMBOL_GPL(sst_hsw_dsp_free); diff --git a/sound/soc/intel/sst-haswell-ipc.h b/sound/soc/intel/sst-haswell-ipc.h new file mode 100644 index 000000000000..d517929ccc38 --- /dev/null +++ b/sound/soc/intel/sst-haswell-ipc.h @@ -0,0 +1,488 @@ +/* + * Intel SST Haswell/Broadwell IPC Support + * + * Copyright (C) 2013, Intel Corporation. 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 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 __SST_HASWELL_IPC_H +#define __SST_HASWELL_IPC_H + +#include +#include +#include + +#define SST_HSW_NO_CHANNELS 2 +#define SST_HSW_MAX_DX_REGIONS 14 + +#define SST_HSW_FW_LOG_CONFIG_DWORDS 12 +#define SST_HSW_GLOBAL_LOG 15 + +/** + * Upfront defined maximum message size that is + * expected by the in/out communication pipes in FW. + */ +#define SST_HSW_IPC_MAX_PAYLOAD_SIZE 400 +#define SST_HSW_MAX_INFO_SIZE 64 +#define SST_HSW_BUILD_HASH_LENGTH 40 + +struct sst_hsw; +struct sst_hsw_stream; +struct sst_hsw_log_stream; +struct sst_pdata; +struct sst_module; +extern struct sst_ops haswell_ops; + +/* Stream Allocate Path ID */ +enum sst_hsw_stream_path_id { + SST_HSW_STREAM_PATH_SSP0_OUT = 0, + SST_HSW_STREAM_PATH_SSP0_IN = 1, + SST_HSW_STREAM_PATH_MAX_PATH_ID = 2, +}; + +/* Stream Allocate Stream Type */ +enum sst_hsw_stream_type { + SST_HSW_STREAM_TYPE_RENDER = 0, + SST_HSW_STREAM_TYPE_SYSTEM = 1, + SST_HSW_STREAM_TYPE_CAPTURE = 2, + SST_HSW_STREAM_TYPE_LOOPBACK = 3, + SST_HSW_STREAM_TYPE_MAX_STREAM_TYPE = 4, +}; + +/* Stream Allocate Stream Format */ +enum sst_hsw_stream_format { + SST_HSW_STREAM_FORMAT_PCM_FORMAT = 0, + SST_HSW_STREAM_FORMAT_MP3_FORMAT = 1, + SST_HSW_STREAM_FORMAT_AAC_FORMAT = 2, + SST_HSW_STREAM_FORMAT_MAX_FORMAT_ID = 3, +}; + +/* Device ID */ +enum sst_hsw_device_id { + SST_HSW_DEVICE_SSP_0 = 0, + SST_HSW_DEVICE_SSP_1 = 1, +}; + +/* Device Master Clock Frequency */ +enum sst_hsw_device_mclk { + SST_HSW_DEVICE_MCLK_OFF = 0, + SST_HSW_DEVICE_MCLK_FREQ_6_MHZ = 1, + SST_HSW_DEVICE_MCLK_FREQ_12_MHZ = 2, + SST_HSW_DEVICE_MCLK_FREQ_24_MHZ = 3, +}; + +/* Device Clock Master */ +enum sst_hsw_device_mode { + SST_HSW_DEVICE_CLOCK_SLAVE = 0, + SST_HSW_DEVICE_CLOCK_MASTER = 1, +}; + +/* DX Power State */ +enum sst_hsw_dx_state { + SST_HSW_DX_STATE_D0 = 0, + SST_HSW_DX_STATE_D1 = 1, + SST_HSW_DX_STATE_D3 = 3, + SST_HSW_DX_STATE_MAX = 3, +}; + +/* Audio stream stage IDs */ +enum sst_hsw_fx_stage_id { + SST_HSW_STAGE_ID_WAVES = 0, + SST_HSW_STAGE_ID_DTS = 1, + SST_HSW_STAGE_ID_DOLBY = 2, + SST_HSW_STAGE_ID_BOOST = 3, + SST_HSW_STAGE_ID_MAX_FX_ID +}; + +/* DX State Type */ +enum sst_hsw_dx_type { + SST_HSW_DX_TYPE_FW_IMAGE = 0, + SST_HSW_DX_TYPE_MEMORY_DUMP = 1 +}; + +/* Volume Curve Type*/ +enum sst_hsw_volume_curve { + SST_HSW_VOLUME_CURVE_NONE = 0, + SST_HSW_VOLUME_CURVE_FADE = 1 +}; + +/* Sample ordering */ +enum sst_hsw_interleaving { + SST_HSW_INTERLEAVING_PER_CHANNEL = 0, + SST_HSW_INTERLEAVING_PER_SAMPLE = 1, +}; + +/* Channel indices */ +enum sst_hsw_channel_index { + SST_HSW_CHANNEL_LEFT = 0, + SST_HSW_CHANNEL_CENTER = 1, + SST_HSW_CHANNEL_RIGHT = 2, + SST_HSW_CHANNEL_LEFT_SURROUND = 3, + SST_HSW_CHANNEL_CENTER_SURROUND = 3, + SST_HSW_CHANNEL_RIGHT_SURROUND = 4, + SST_HSW_CHANNEL_LFE = 7, + SST_HSW_CHANNEL_INVALID = 0xF, +}; + +/* List of supported channel maps. */ +enum sst_hsw_channel_config { + SST_HSW_CHANNEL_CONFIG_MONO = 0, /* mono only. */ + SST_HSW_CHANNEL_CONFIG_STEREO = 1, /* L & R. */ + SST_HSW_CHANNEL_CONFIG_2_POINT_1 = 2, /* L, R & LFE; PCM only. */ + SST_HSW_CHANNEL_CONFIG_3_POINT_0 = 3, /* L, C & R; MP3 & AAC only. */ + SST_HSW_CHANNEL_CONFIG_3_POINT_1 = 4, /* L, C, R & LFE; PCM only. */ + SST_HSW_CHANNEL_CONFIG_QUATRO = 5, /* L, R, Ls & Rs; PCM only. */ + SST_HSW_CHANNEL_CONFIG_4_POINT_0 = 6, /* L, C, R & Cs; MP3 & AAC only. */ + SST_HSW_CHANNEL_CONFIG_5_POINT_0 = 7, /* L, C, R, Ls & Rs. */ + SST_HSW_CHANNEL_CONFIG_5_POINT_1 = 8, /* L, C, R, Ls, Rs & LFE. */ + SST_HSW_CHANNEL_CONFIG_DUAL_MONO = 9, /* One channel replicated in two. */ + SST_HSW_CHANNEL_CONFIG_INVALID, +}; + +/* List of supported bit depths. */ +enum sst_hsw_bitdepth { + SST_HSW_DEPTH_8BIT = 8, + SST_HSW_DEPTH_16BIT = 16, + SST_HSW_DEPTH_24BIT = 24, /* Default. */ + SST_HSW_DEPTH_32BIT = 32, + SST_HSW_DEPTH_INVALID = 33, +}; + +enum sst_hsw_module_id { + SST_HSW_MODULE_BASE_FW = 0x0, + SST_HSW_MODULE_MP3 = 0x1, + SST_HSW_MODULE_AAC_5_1 = 0x2, + SST_HSW_MODULE_AAC_2_0 = 0x3, + SST_HSW_MODULE_SRC = 0x4, + SST_HSW_MODULE_WAVES = 0x5, + SST_HSW_MODULE_DOLBY = 0x6, + SST_HSW_MODULE_BOOST = 0x7, + SST_HSW_MODULE_LPAL = 0x8, + SST_HSW_MODULE_DTS = 0x9, + SST_HSW_MODULE_PCM_CAPTURE = 0xA, + SST_HSW_MODULE_PCM_SYSTEM = 0xB, + SST_HSW_MODULE_PCM_REFERENCE = 0xC, + SST_HSW_MODULE_PCM = 0xD, + SST_HSW_MODULE_BLUETOOTH_RENDER_MODULE = 0xE, + SST_HSW_MODULE_BLUETOOTH_CAPTURE_MODULE = 0xF, + SST_HSW_MAX_MODULE_ID, +}; + +enum sst_hsw_performance_action { + SST_HSW_PERF_START = 0, + SST_HSW_PERF_STOP = 1, +}; + +/* SST firmware module info */ +struct sst_hsw_module_info { + u8 name[SST_HSW_MAX_INFO_SIZE]; + u8 version[SST_HSW_MAX_INFO_SIZE]; +} __attribute__((packed)); + +/* Module entry point */ +struct sst_hsw_module_entry { + enum sst_hsw_module_id module_id; + u32 entry_point; +} __attribute__((packed)); + +/* Module map - alignement matches DSP */ +struct sst_hsw_module_map { + u8 module_entries_count; + struct sst_hsw_module_entry module_entries[1]; +} __attribute__((packed)); + +struct sst_hsw_memory_info { + u32 offset; + u32 size; +} __attribute__((packed)); + +struct sst_hsw_fx_enable { + struct sst_hsw_module_map module_map; + struct sst_hsw_memory_info persistent_mem; +} __attribute__((packed)); + +struct sst_hsw_get_fx_param { + u32 parameter_id; + u32 param_size; +} __attribute__((packed)); + +struct sst_hsw_perf_action { + u32 action; +} __attribute__((packed)); + +struct sst_hsw_perf_data { + u64 timestamp; + u64 cycles; + u64 datatime; +} __attribute__((packed)); + +/* FW version */ +struct sst_hsw_ipc_fw_version { + u8 build; + u8 minor; + u8 major; + u8 type; + u8 fw_build_hash[SST_HSW_BUILD_HASH_LENGTH]; + u32 fw_log_providers_hash; +} __attribute__((packed)); + +/* Stream ring info */ +struct sst_hsw_ipc_stream_ring { + u32 ring_pt_address; + u32 num_pages; + u32 ring_size; + u32 ring_offset; + u32 ring_first_pfn; +} __attribute__((packed)); + +/* Debug Dump Log Enable Request */ +struct sst_hsw_ipc_debug_log_enable_req { + struct sst_hsw_ipc_stream_ring ringinfo; + u32 config[SST_HSW_FW_LOG_CONFIG_DWORDS]; +} __attribute__((packed)); + +/* Debug Dump Log Reply */ +struct sst_hsw_ipc_debug_log_reply { + u32 log_buffer_begining; + u32 log_buffer_size; +} __attribute__((packed)); + +/* Stream glitch position */ +struct sst_hsw_ipc_stream_glitch_position { + u32 glitch_type; + u32 present_pos; + u32 write_pos; +} __attribute__((packed)); + +/* Stream get position */ +struct sst_hsw_ipc_stream_get_position { + u32 position; + u32 fw_cycle_count; +} __attribute__((packed)); + +/* Stream set position */ +struct sst_hsw_ipc_stream_set_position { + u32 position; + u32 end_of_buffer; +} __attribute__((packed)); + +/* Stream Free Request */ +struct sst_hsw_ipc_stream_free_req { + u8 stream_id; + u8 reserved[3]; +} __attribute__((packed)); + +/* Set Volume Request */ +struct sst_hsw_ipc_volume_req { + u32 channel; + u32 target_volume; + u64 curve_duration; + u32 curve_type; +} __attribute__((packed)); + +/* Device Configuration Request */ +struct sst_hsw_ipc_device_config_req { + u32 ssp_interface; + u32 clock_frequency; + u32 mode; + u16 clock_divider; + u16 reserved; +} __attribute__((packed)); + +/* Audio Data formats */ +struct sst_hsw_audio_data_format_ipc { + u32 frequency; + u32 bitdepth; + u32 map; + u32 config; + u32 style; + u8 ch_num; + u8 valid_bit; + u8 reserved[2]; +} __attribute__((packed)); + +/* Stream Allocate Request */ +struct sst_hsw_ipc_stream_alloc_req { + u8 path_id; + u8 stream_type; + u8 format_id; + u8 reserved; + struct sst_hsw_audio_data_format_ipc format; + struct sst_hsw_ipc_stream_ring ringinfo; + struct sst_hsw_module_map map; + struct sst_hsw_memory_info persistent_mem; + struct sst_hsw_memory_info scratch_mem; + u32 number_of_notifications; +} __attribute__((packed)); + +/* Stream Allocate Reply */ +struct sst_hsw_ipc_stream_alloc_reply { + u32 stream_hw_id; + u32 mixer_hw_id; // returns rate ???? + u32 read_position_register_address; + u32 presentation_position_register_address; + u32 peak_meter_register_address[SST_HSW_NO_CHANNELS]; + u32 volume_register_address[SST_HSW_NO_CHANNELS]; +} __attribute__((packed)); + +/* Get Mixer Stream Info */ +struct sst_hsw_ipc_stream_info_reply { + u32 mixer_hw_id; + u32 peak_meter_register_address[SST_HSW_NO_CHANNELS]; + u32 volume_register_address[SST_HSW_NO_CHANNELS]; +} __attribute__((packed)); + +/* DX State Request */ +struct sst_hsw_ipc_dx_req { + u8 state; + u8 reserved[3]; +} __attribute__((packed)); + +/* DX State Reply Memory Info Item */ +struct sst_hsw_ipc_dx_memory_item { + u32 offset; + u32 size; + u32 source; +} __attribute__((packed)); + +/* DX State Reply */ +struct sst_hsw_ipc_dx_reply { + u32 entries_no; + struct sst_hsw_ipc_dx_memory_item mem_info[SST_HSW_MAX_DX_REGIONS]; +} __attribute__((packed)); + +struct sst_hsw_ipc_fw_version; + +/* SST Init & Free */ +struct sst_hsw *sst_hsw_new(struct device *dev, const u8 *fw, size_t fw_length, + u32 fw_offset); +void sst_hsw_free(struct sst_hsw *hsw); +int sst_hsw_fw_get_version(struct sst_hsw *hsw, + struct sst_hsw_ipc_fw_version *version); +u32 create_channel_map(enum sst_hsw_channel_config config); + +/* Stream Mixer Controls - */ +int sst_hsw_stream_mute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 stage_id, u32 channel); +int sst_hsw_stream_unmute(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 stage_id, u32 channel); + +int sst_hsw_stream_set_volume(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume); +int sst_hsw_stream_get_volume(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 *volume); + +int sst_hsw_stream_set_volume_curve(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u64 curve_duration, + enum sst_hsw_volume_curve curve); + +/* Global Mixer Controls - */ +int sst_hsw_mixer_mute(struct sst_hsw *hsw, u32 stage_id, u32 channel); +int sst_hsw_mixer_unmute(struct sst_hsw *hsw, u32 stage_id, u32 channel); + +int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, + u32 volume); +int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, + u32 *volume); + +int sst_hsw_mixer_set_volume_curve(struct sst_hsw *hsw, + u64 curve_duration, enum sst_hsw_volume_curve curve); + +/* Stream API */ +struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, + u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data), + void *data); + +int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream); + +/* Stream Configuration */ +int sst_hsw_stream_format(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + enum sst_hsw_stream_path_id path_id, + enum sst_hsw_stream_type stream_type, + enum sst_hsw_stream_format format_id); + +int sst_hsw_stream_buffer(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 ring_pt_address, u32 num_pages, + u32 ring_size, u32 ring_offset, u32 ring_first_pfn); + +int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream); + +int sst_hsw_stream_set_valid(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + u32 bits); +int sst_hsw_stream_set_rate(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + int rate); +int sst_hsw_stream_set_bits(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + enum sst_hsw_bitdepth bits); +int sst_hsw_stream_set_channels(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, int channels); +int sst_hsw_stream_set_map_config(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 map, + enum sst_hsw_channel_config config); +int sst_hsw_stream_set_style(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + enum sst_hsw_interleaving style); +int sst_hsw_stream_set_module_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, enum sst_hsw_module_id module_id, + u32 entry_point); +int sst_hsw_stream_set_pmemory_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 offset, u32 size); +int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 offset, u32 size); +int sst_hsw_stream_get_hw_id(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); +int sst_hsw_stream_get_mixer_id(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); +u32 sst_hsw_stream_get_read_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); +u32 sst_hsw_stream_get_pointer_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); +u32 sst_hsw_stream_get_peak_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 channel); +u32 sst_hsw_stream_get_vol_reg(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 channel); +int sst_hsw_mixer_get_info(struct sst_hsw *hsw); + +/* Stream ALSA trigger operations */ +int sst_hsw_stream_pause(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + int wait); +int sst_hsw_stream_resume(struct sst_hsw *hsw, struct sst_hsw_stream *stream, + int wait); +int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream); + +/* Stream pointer positions */ +int sst_hsw_stream_get_read_pos(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 *position); +int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 *position); +int sst_hsw_stream_set_write_position(struct sst_hsw *hsw, + struct sst_hsw_stream *stream, u32 stage_id, u32 position); +int sst_hsw_get_dsp_position(struct sst_hsw *hsw, + struct sst_hsw_stream *stream); + +/* HW port config */ +int sst_hsw_device_set_config(struct sst_hsw *hsw, + enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk, + enum sst_hsw_device_mode mode, u32 clock_divider); + +/* DX Config */ +int sst_hsw_dx_set_state(struct sst_hsw *hsw, + enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx); +int sst_hsw_dx_get_state(struct sst_hsw *hsw, u32 item, + u32 *offset, u32 *size, u32 *source); + +/* init */ +int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata); +void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata); +struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw); +void sst_hsw_set_scratch_module(struct sst_hsw *hsw, + struct sst_module *scratch); + +#endif -- cgit v1.2.3 From d37797705d959c21e2f846ac73c2e17303bff936 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 20 Feb 2014 21:48:44 +0000 Subject: ASoC: Intel: Add Haswell and Broadwell PCM platform driver Add the Haswell and Broadwell PCM DSP platform driver. This driver uses the IPC driver for communication with the SST DSP. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-pcm.c | 872 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 872 insertions(+) create mode 100644 sound/soc/intel/sst-haswell-pcm.c (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-haswell-pcm.c b/sound/soc/intel/sst-haswell-pcm.c new file mode 100644 index 000000000000..0a32dd13a23d --- /dev/null +++ b/sound/soc/intel/sst-haswell-pcm.c @@ -0,0 +1,872 @@ +/* + * Intel SST Haswell/Broadwell PCM Support + * + * Copyright (C) 2013, Intel Corporation. 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 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sst-haswell-ipc.h" +#include "sst-dsp-priv.h" +#include "sst-dsp.h" + +#define HSW_PCM_COUNT 6 +#define HSW_VOLUME_MAX 0x7FFFFFFF /* 0dB */ + +/* simple volume table */ +static const u32 volume_map[] = { + HSW_VOLUME_MAX >> 30, + HSW_VOLUME_MAX >> 29, + HSW_VOLUME_MAX >> 28, + HSW_VOLUME_MAX >> 27, + HSW_VOLUME_MAX >> 26, + HSW_VOLUME_MAX >> 25, + HSW_VOLUME_MAX >> 24, + HSW_VOLUME_MAX >> 23, + HSW_VOLUME_MAX >> 22, + HSW_VOLUME_MAX >> 21, + HSW_VOLUME_MAX >> 20, + HSW_VOLUME_MAX >> 19, + HSW_VOLUME_MAX >> 18, + HSW_VOLUME_MAX >> 17, + HSW_VOLUME_MAX >> 16, + HSW_VOLUME_MAX >> 15, + HSW_VOLUME_MAX >> 14, + HSW_VOLUME_MAX >> 13, + HSW_VOLUME_MAX >> 12, + HSW_VOLUME_MAX >> 11, + HSW_VOLUME_MAX >> 10, + HSW_VOLUME_MAX >> 9, + HSW_VOLUME_MAX >> 8, + HSW_VOLUME_MAX >> 7, + HSW_VOLUME_MAX >> 6, + HSW_VOLUME_MAX >> 5, + HSW_VOLUME_MAX >> 4, + HSW_VOLUME_MAX >> 3, + HSW_VOLUME_MAX >> 2, + HSW_VOLUME_MAX >> 1, + HSW_VOLUME_MAX >> 0, +}; + +#define HSW_PCM_PERIODS_MAX 64 +#define HSW_PCM_PERIODS_MIN 2 + +static const struct snd_pcm_hardware hsw_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .period_bytes_min = PAGE_SIZE, + .period_bytes_max = (HSW_PCM_PERIODS_MAX / HSW_PCM_PERIODS_MIN) * PAGE_SIZE, + .periods_min = HSW_PCM_PERIODS_MIN, + .periods_max = HSW_PCM_PERIODS_MAX, + .buffer_bytes_max = HSW_PCM_PERIODS_MAX * PAGE_SIZE, +}; + +/* private data for each PCM DSP stream */ +struct hsw_pcm_data { + int dai_id; + struct sst_hsw_stream *stream; + u32 volume[2]; + struct snd_pcm_substream *substream; + struct snd_compr_stream *cstream; + unsigned int wpos; + struct mutex mutex; +}; + +/* private data for the driver */ +struct hsw_priv_data { + /* runtime DSP */ + struct sst_hsw *hsw; + + /* page tables */ + unsigned char *pcm_pg[HSW_PCM_COUNT][2]; + + /* DAI data */ + struct hsw_pcm_data pcm[HSW_PCM_COUNT]; +}; + +static inline u32 hsw_mixer_to_ipc(unsigned int value) +{ + if (value >= ARRAY_SIZE(volume_map)) + return volume_map[0]; + else + return volume_map[value]; +} + +static inline unsigned int hsw_ipc_to_mixer(u32 value) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(volume_map); i++) { + if (volume_map[i] >= value) + return i; + } + + return i - 1; +} + +static int hsw_stream_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(platform); + struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; + struct sst_hsw *hsw = pdata->hsw; + u32 volume; + + mutex_lock(&pcm_data->mutex); + + if (!pcm_data->stream) { + pcm_data->volume[0] = + hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); + pcm_data->volume[1] = + hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); + mutex_unlock(&pcm_data->mutex); + return 0; + } + + if (ucontrol->value.integer.value[0] == + ucontrol->value.integer.value[1]) { + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); + sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 2, volume); + } else { + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); + sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 0, volume); + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); + sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, 1, volume); + } + + mutex_unlock(&pcm_data->mutex); + return 0; +} + +static int hsw_stream_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(platform); + struct hsw_pcm_data *pcm_data = &pdata->pcm[mc->reg]; + struct sst_hsw *hsw = pdata->hsw; + u32 volume; + + mutex_lock(&pcm_data->mutex); + + if (!pcm_data->stream) { + ucontrol->value.integer.value[0] = + hsw_ipc_to_mixer(pcm_data->volume[0]); + ucontrol->value.integer.value[1] = + hsw_ipc_to_mixer(pcm_data->volume[1]); + mutex_unlock(&pcm_data->mutex); + return 0; + } + + sst_hsw_stream_get_volume(hsw, pcm_data->stream, 0, 0, &volume); + ucontrol->value.integer.value[0] = hsw_ipc_to_mixer(volume); + sst_hsw_stream_get_volume(hsw, pcm_data->stream, 0, 1, &volume); + ucontrol->value.integer.value[1] = hsw_ipc_to_mixer(volume); + mutex_unlock(&pcm_data->mutex); + + return 0; +} + +static int hsw_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); + struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform); + struct sst_hsw *hsw = pdata->hsw; + u32 volume; + + if (ucontrol->value.integer.value[0] == + ucontrol->value.integer.value[1]) { + + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); + sst_hsw_mixer_set_volume(hsw, 0, 2, volume); + + } else { + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[0]); + sst_hsw_mixer_set_volume(hsw, 0, 0, volume); + + volume = hsw_mixer_to_ipc(ucontrol->value.integer.value[1]); + sst_hsw_mixer_set_volume(hsw, 0, 1, volume); + } + + return 0; +} + +static int hsw_volume_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol); + struct hsw_priv_data *pdata = snd_soc_platform_get_drvdata(platform); + struct sst_hsw *hsw = pdata->hsw; + unsigned int volume = 0; + + sst_hsw_mixer_get_volume(hsw, 0, 0, &volume); + ucontrol->value.integer.value[0] = hsw_ipc_to_mixer(volume); + + sst_hsw_mixer_get_volume(hsw, 0, 1, &volume); + ucontrol->value.integer.value[1] = hsw_ipc_to_mixer(volume); + + return 0; +} + +/* TLV used by both global and stream volumes */ +static const DECLARE_TLV_DB_SCALE(hsw_vol_tlv, -9000, 300, 1); + +/* System Pin has no volume control */ +static const struct snd_kcontrol_new hsw_volume_controls[] = { + /* Global DSP volume */ + SOC_DOUBLE_EXT_TLV("Master Playback Volume", 0, 0, 8, + ARRAY_SIZE(volume_map) -1, 0, + hsw_volume_get, hsw_volume_put, hsw_vol_tlv), + /* Offload 0 volume */ + SOC_DOUBLE_EXT_TLV("Media0 Playback Volume", 1, 0, 8, + ARRAY_SIZE(volume_map), 0, + hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), + /* Offload 1 volume */ + SOC_DOUBLE_EXT_TLV("Media1 Playback Volume", 2, 0, 8, + ARRAY_SIZE(volume_map), 0, + hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), + /* Loopback volume */ + SOC_DOUBLE_EXT_TLV("Loopback Capture Volume", 3, 0, 8, + ARRAY_SIZE(volume_map), 0, + hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), + /* Mic Capture volume */ + SOC_DOUBLE_EXT_TLV("Mic Capture Volume", 4, 0, 8, + ARRAY_SIZE(volume_map), 0, + hsw_stream_volume_get, hsw_stream_volume_put, hsw_vol_tlv), +}; + +/* Create DMA buffer page table for DSP */ +static int create_adsp_page_table(struct hsw_priv_data *pdata, + struct snd_soc_pcm_runtime *rtd, + unsigned char *dma_area, size_t size, int pcm, int stream) +{ + int i, pages; + + if (size % PAGE_SIZE) + pages = (size / PAGE_SIZE) + 1; + else + pages = size / PAGE_SIZE; + + dev_dbg(rtd->dev, "generating page table for %p size 0x%zu pages %d\n", + dma_area, size, pages); + + for (i = 0; i < pages; i++) { + u32 idx = (((i << 2) + i)) >> 1; + u32 pfn = (virt_to_phys(dma_area + i * PAGE_SIZE)) >> PAGE_SHIFT; + u32 *pg_table; + + dev_dbg(rtd->dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn); + + pg_table = (u32*)(pdata->pcm_pg[pcm][stream] + idx); + + if (i & 1) + *pg_table |= (pfn << 4); + else + *pg_table |= pfn; + } + + return 0; +} + +/* this may get called several times by oss emulation */ +static int hsw_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_hsw *hsw = pdata->hsw; + struct sst_module *module_data; + struct sst_dsp *dsp; + enum sst_hsw_stream_type stream_type; + enum sst_hsw_stream_path_id path_id; + u32 rate, bits, map, pages, module_id; + u8 channels; + int ret; + + /* stream direction */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + path_id = SST_HSW_STREAM_PATH_SSP0_OUT; + else + path_id = SST_HSW_STREAM_PATH_SSP0_IN; + + /* DSP stream type depends on DAI ID */ + switch (rtd->cpu_dai->id) { + case 0: + stream_type = SST_HSW_STREAM_TYPE_SYSTEM; + module_id = SST_HSW_MODULE_PCM_SYSTEM; + break; + case 1: + case 2: + stream_type = SST_HSW_STREAM_TYPE_RENDER; + module_id = SST_HSW_MODULE_PCM; + break; + case 3: + /* path ID needs to be OUT for loopback */ + stream_type = SST_HSW_STREAM_TYPE_LOOPBACK; + path_id = SST_HSW_STREAM_PATH_SSP0_OUT; + module_id = SST_HSW_MODULE_PCM_REFERENCE; + break; + case 4: + stream_type = SST_HSW_STREAM_TYPE_CAPTURE; + module_id = SST_HSW_MODULE_PCM_CAPTURE; + break; + default: + dev_err(rtd->dev, "error: invalid DAI ID %d\n", + rtd->cpu_dai->id); + return -EINVAL; + }; + + ret = sst_hsw_stream_format(hsw, pcm_data->stream, + path_id, stream_type, SST_HSW_STREAM_FORMAT_PCM_FORMAT); + if (ret < 0) { + dev_err(rtd->dev, "error: failed to set format %d\n", ret); + return ret; + } + + rate = params_rate(params); + ret = sst_hsw_stream_set_rate(hsw, pcm_data->stream, rate); + if (ret < 0) { + dev_err(rtd->dev, "error: could not set rate %d\n", rate); + return ret; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + bits = SST_HSW_DEPTH_16BIT; + sst_hsw_stream_set_valid(hsw, pcm_data->stream, 16); + break; + case SNDRV_PCM_FORMAT_S24_LE: + bits = SST_HSW_DEPTH_24BIT; + sst_hsw_stream_set_valid(hsw, pcm_data->stream, 32); + break; + default: + dev_err(rtd->dev, "error: invalid format %d\n", + params_format(params)); + return -EINVAL; + } + + ret = sst_hsw_stream_set_bits(hsw, pcm_data->stream, bits); + if (ret < 0) { + dev_err(rtd->dev, "error: could not set bits %d\n", bits); + return ret; + } + + /* we only support stereo atm */ + channels = params_channels(params); + if (channels != 2) { + dev_err(rtd->dev, "error: invalid channels %d\n", channels); + return -EINVAL; + } + + map = create_channel_map(SST_HSW_CHANNEL_CONFIG_STEREO); + sst_hsw_stream_set_map_config(hsw, pcm_data->stream, + map, SST_HSW_CHANNEL_CONFIG_STEREO); + + ret = sst_hsw_stream_set_channels(hsw, pcm_data->stream, channels); + if (ret < 0) { + dev_err(rtd->dev, "error: could not set channels %d\n", + channels); + return ret; + } + + ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); + if (ret < 0) { + dev_err(rtd->dev, "error: could not allocate %d bytes for PCM %d\n", + params_buffer_bytes(params), ret); + return ret; + } + + ret = create_adsp_page_table(pdata, rtd, runtime->dma_area, + runtime->dma_bytes, rtd->cpu_dai->id, substream->stream); + if (ret < 0) + return ret; + + sst_hsw_stream_set_style(hsw, pcm_data->stream, + SST_HSW_INTERLEAVING_PER_CHANNEL); + + if (runtime->dma_bytes % PAGE_SIZE) + pages = (runtime->dma_bytes / PAGE_SIZE) + 1; + else + pages = runtime->dma_bytes / PAGE_SIZE; + + ret = sst_hsw_stream_buffer(hsw, pcm_data->stream, + virt_to_phys(pdata->pcm_pg[rtd->cpu_dai->id][substream->stream]), + pages, runtime->dma_bytes, 0, + (u32)(virt_to_phys(runtime->dma_area) >> PAGE_SHIFT)); + if (ret < 0) { + dev_err(rtd->dev, "error: failed to set DMA buffer %d\n", ret); + return ret; + } + + dsp = sst_hsw_get_dsp(hsw); + + module_data = sst_module_get_from_id(dsp, module_id); + if (module_data == NULL) { + dev_err(rtd->dev, "error: failed to get module config\n"); + return -EINVAL; + } + + /* we use hardcoded memory offsets atm, will be updated for new FW */ + if (stream_type == SST_HSW_STREAM_TYPE_CAPTURE) { + sst_hsw_stream_set_module_info(hsw, pcm_data->stream, + SST_HSW_MODULE_PCM_CAPTURE, module_data->entry); + sst_hsw_stream_set_pmemory_info(hsw, pcm_data->stream, + 0x449400, 0x4000); + sst_hsw_stream_set_smemory_info(hsw, pcm_data->stream, + 0x400000, 0); + } else { /* stream_type == SST_HSW_STREAM_TYPE_SYSTEM */ + sst_hsw_stream_set_module_info(hsw, pcm_data->stream, + SST_HSW_MODULE_PCM_SYSTEM, module_data->entry); + + sst_hsw_stream_set_pmemory_info(hsw, pcm_data->stream, + module_data->offset, module_data->size); + sst_hsw_stream_set_pmemory_info(hsw, pcm_data->stream, + 0x44d400, 0x3800); + + sst_hsw_stream_set_smemory_info(hsw, pcm_data->stream, + module_data->offset, module_data->size); + sst_hsw_stream_set_smemory_info(hsw, pcm_data->stream, + 0x400000, 0); + } + + ret = sst_hsw_stream_commit(hsw, pcm_data->stream); + if (ret < 0) { + dev_err(rtd->dev, "error: failed to commit stream %d\n", ret); + return ret; + } + + ret = sst_hsw_stream_pause(hsw, pcm_data->stream, 1); + if (ret < 0) + dev_err(rtd->dev, "error: failed to pause %d\n", ret); + + return 0; +} + +static int hsw_pcm_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_lib_free_pages(substream); + return 0; +} + +static int hsw_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_hsw *hsw = pdata->hsw; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + sst_hsw_stream_resume(hsw, pcm_data->stream, 0); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + sst_hsw_stream_pause(hsw, pcm_data->stream, 0); + break; + default: + break; + } + + return 0; +} + +static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data) +{ + struct hsw_pcm_data *pcm_data = data; + struct snd_pcm_substream *substream = pcm_data->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + u32 pos; + + pos = frames_to_bytes(runtime, + (runtime->control->appl_ptr % runtime->buffer_size)); + + dev_dbg(rtd->dev, "PCM: App pointer %d bytes\n", pos); + + /* let alsa know we have play a period */ + snd_pcm_period_elapsed(substream); + return pos; +} + +static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_hsw *hsw = pdata->hsw; + snd_pcm_uframes_t offset; + + offset = bytes_to_frames(runtime, + sst_hsw_get_dsp_position(hsw, pcm_data->stream)); + + dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", + frames_to_bytes(runtime, (u32)offset)); + return offset; +} + +static int hsw_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct hsw_pcm_data *pcm_data; + struct sst_hsw *hsw = pdata->hsw; + + pcm_data = &pdata->pcm[rtd->cpu_dai->id]; + + mutex_lock(&pcm_data->mutex); + + snd_soc_pcm_set_drvdata(rtd, pcm_data); + pcm_data->substream = substream; + + snd_soc_set_runtime_hwparams(substream, &hsw_pcm_hardware); + + pcm_data->stream = sst_hsw_stream_new(hsw, rtd->cpu_dai->id, + hsw_notify_pointer, pcm_data); + if (pcm_data->stream == NULL) { + dev_err(rtd->dev, "error: failed to create stream\n"); + mutex_unlock(&pcm_data->mutex); + return -EINVAL; + } + + /* Set previous saved volume */ + sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, + 0, pcm_data->volume[0]); + sst_hsw_stream_set_volume(hsw, pcm_data->stream, 0, + 1, pcm_data->volume[1]); + + mutex_unlock(&pcm_data->mutex); + return 0; +} + +static int hsw_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct hsw_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_hsw *hsw = pdata->hsw; + int ret; + + mutex_lock(&pcm_data->mutex); + ret = sst_hsw_stream_reset(hsw, pcm_data->stream); + if (ret < 0) { + dev_dbg(rtd->dev, "error: reset stream failed %d\n", ret); + goto out; + } + + ret = sst_hsw_stream_free(hsw, pcm_data->stream); + if (ret < 0) { + dev_dbg(rtd->dev, "error: free stream failed %d\n", ret); + goto out; + } + pcm_data->stream = NULL; + +out: + mutex_unlock(&pcm_data->mutex); + return ret; +} + +static struct snd_pcm_ops hsw_pcm_ops = { + .open = hsw_pcm_open, + .close = hsw_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = hsw_pcm_hw_params, + .hw_free = hsw_pcm_hw_free, + .trigger = hsw_pcm_trigger, + .pointer = hsw_pcm_pointer, + .mmap = snd_pcm_lib_default_mmap, +}; + +static void hsw_pcm_free(struct snd_pcm *pcm) +{ + snd_pcm_lib_preallocate_free_for_all(pcm); +} + +static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + + ret = dma_coerce_mask_and_coherent(rtd->card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || + pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + ret = snd_pcm_lib_preallocate_pages_for_all(pcm, + SNDRV_DMA_TYPE_DEV, + rtd->card->dev, + hsw_pcm_hardware.buffer_bytes_max, + hsw_pcm_hardware.buffer_bytes_max); + if (ret) { + dev_err(rtd->dev, "dma buffer allocation failed %d\n", + ret); + return ret; + } + } + + return ret; +} + +#define HSW_FORMATS \ + (SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver hsw_dais[] = { + { + .name = "System Pin", + .playback = { + .stream_name = "System Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, + { + /* PCM */ + .name = "Offload0 Pin", + .playback = { + .stream_name = "Offload0 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = HSW_FORMATS, + }, + }, + { + /* PCM */ + .name = "Offload1 Pin", + .playback = { + .stream_name = "Offload1 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = HSW_FORMATS, + }, + }, + { + .name = "Loopback Pin", + .capture = { + .stream_name = "Loopback Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = HSW_FORMATS, + }, + }, + { + .name = "Capture Pin", + .capture = { + .stream_name = "Analog Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = HSW_FORMATS, + }, + }, +}; + +static const struct snd_soc_dapm_widget widgets[] = { + + /* Backend DAIs */ + SND_SOC_DAPM_AIF_IN("SSP0 CODEC IN", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("SSP0 CODEC OUT", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("SSP1 BT IN", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("SSP1 BT OUT", NULL, 0, SND_SOC_NOPM, 0, 0), + + /* Global Playback Mixer */ + SND_SOC_DAPM_MIXER("Playback VMixer", SND_SOC_NOPM, 0, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route graph[] = { + + /* Playback Mixer */ + {"Playback VMixer", NULL, "System Playback"}, + {"Playback VMixer", NULL, "Offload0 Playback"}, + {"Playback VMixer", NULL, "Offload1 Playback"}, + + {"SSP0 CODEC OUT", NULL, "Playback VMixer"}, + + {"Analog Capture", NULL, "SSP0 CODEC IN"}, +}; + +static int hsw_pcm_probe(struct snd_soc_platform *platform) +{ + struct sst_pdata *pdata = dev_get_platdata(platform->dev); + struct hsw_priv_data *priv_data; + int i; + + if (!pdata) + return -ENODEV; + + priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data), GFP_KERNEL); + priv_data->hsw = pdata->dsp; + snd_soc_platform_set_drvdata(platform, priv_data); + + /* allocate DSP buffer page tables */ + for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { + + mutex_init(&priv_data->pcm[i].mutex); + + /* playback */ + if (hsw_dais[i].playback.channels_min) { + priv_data->pcm_pg[i][0] = kzalloc(PAGE_SIZE, GFP_DMA); + if (priv_data->pcm_pg[i][0] == NULL) + goto err; + } + + /* capture */ + if (hsw_dais[i].capture.channels_min) { + priv_data->pcm_pg[i][1] = kzalloc(PAGE_SIZE, GFP_DMA); + if (priv_data->pcm_pg[i][1] == NULL) + goto err; + } + } + + return 0; + +err: + for (;i >= 0; i--) { + if (hsw_dais[i].playback.channels_min) + kfree(priv_data->pcm_pg[i][0]); + if (hsw_dais[i].capture.channels_min) + kfree(priv_data->pcm_pg[i][1]); + } + return -ENOMEM; +} + +static int hsw_pcm_remove(struct snd_soc_platform *platform) +{ + struct hsw_priv_data *priv_data = + snd_soc_platform_get_drvdata(platform); + int i; + + for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) { + if (hsw_dais[i].playback.channels_min) + kfree(priv_data->pcm_pg[i][0]); + if (hsw_dais[i].capture.channels_min) + kfree(priv_data->pcm_pg[i][1]); + } + + return 0; +} + +static struct snd_soc_platform_driver hsw_soc_platform = { + .probe = hsw_pcm_probe, + .remove = hsw_pcm_remove, + .ops = &hsw_pcm_ops, + .pcm_new = hsw_pcm_new, + .pcm_free = hsw_pcm_free, + .controls = hsw_volume_controls, + .num_controls = ARRAY_SIZE(hsw_volume_controls), + .dapm_widgets = widgets, + .num_dapm_widgets = ARRAY_SIZE(widgets), + .dapm_routes = graph, + .num_dapm_routes = ARRAY_SIZE(graph), +}; + +static const struct snd_soc_component_driver hsw_dai_component = { + .name = "haswell-dai", +}; + +static int hsw_pcm_dev_probe(struct platform_device *pdev) +{ + struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); + int ret; + + ret = sst_hsw_dsp_init(&pdev->dev, sst_pdata); + if (ret < 0) + return -ENODEV; + + ret = snd_soc_register_platform(&pdev->dev, &hsw_soc_platform); + if (ret < 0) + goto err_plat; + + ret = snd_soc_register_component(&pdev->dev, &hsw_dai_component, + hsw_dais, ARRAY_SIZE(hsw_dais)); + if (ret < 0) + goto err_comp; + + return 0; + +err_comp: + snd_soc_unregister_platform(&pdev->dev); +err_plat: + sst_hsw_dsp_free(&pdev->dev, sst_pdata); + return 0; +} + +static int hsw_pcm_dev_remove(struct platform_device *pdev) +{ + struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); + + snd_soc_unregister_platform(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); + sst_hsw_dsp_free(&pdev->dev, sst_pdata); + + return 0; +} + +static struct platform_driver hsw_pcm_driver = { + .driver = { + .name = "haswell-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = hsw_pcm_dev_probe, + .remove = hsw_pcm_dev_remove, +}; +module_platform_driver(hsw_pcm_driver); + +MODULE_AUTHOR("Liam Girdwood, Xingchao Wang"); +MODULE_DESCRIPTION("Haswell/Lynxpoint + Broadwell/Wildcatpoint PCM"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:haswell-pcm-audio"); -- cgit v1.2.3 From 5e4482fcb119d61f4bef226c442634cdd2618b31 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 20 Feb 2014 21:48:46 +0000 Subject: ASoC: Intel: Add build support for Haswell ADSP Build the Haswell/Broadwell PCM, IPC and DSP drivers. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 2 ++ sound/soc/intel/Makefile | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index dd048fef7248..4f1ac8f82862 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -24,3 +24,5 @@ config SND_SOC_INTEL_SST config SND_SOC_INTEL_SST_ACPI tristate +config SND_SOC_INTEL_HASWELL + tristate diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index cf47100661e9..4c08b215fbeb 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -10,3 +10,9 @@ obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o + +# Platform Support +snd-soc-sst-haswell-pcm-objs := \ + sst-haswell-ipc.o sst-haswell-pcm.o sst-haswell-dsp.o + +obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += snd-soc-sst-haswell-pcm.o -- cgit v1.2.3 From 90931b9eaed9aaf772784a93da320cf10713effa Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 20 Feb 2014 21:48:47 +0000 Subject: ASoC: Intel: Add Haswell Machine support Add support for Haswell based machines with SST DSP audio. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 11 +++ sound/soc/intel/Makefile | 5 + sound/soc/intel/haswell.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 257 insertions(+) create mode 100644 sound/soc/intel/haswell.c (limited to 'sound/soc') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 4f1ac8f82862..ce5a6928e601 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -26,3 +26,14 @@ config SND_SOC_INTEL_SST_ACPI config SND_SOC_INTEL_HASWELL tristate + +config SND_SOC_INTEL_HASWELL_MACH + tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" + depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS + select SND_SOC_INTEL_HASWELL + select SND_SOC_RT5640 + help + This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell + Ultrabook platforms. + Say Y if you have such a device + If unsure select "N". \ No newline at end of file diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 4c08b215fbeb..1c188150accb 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -16,3 +16,8 @@ snd-soc-sst-haswell-pcm-objs := \ sst-haswell-ipc.o sst-haswell-pcm.o sst-haswell-dsp.o obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += snd-soc-sst-haswell-pcm.o + +# Machine support +snd-soc-sst-haswell-objs := haswell.o + +obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o diff --git a/sound/soc/intel/haswell.c b/sound/soc/intel/haswell.c new file mode 100644 index 000000000000..0d61197661d8 --- /dev/null +++ b/sound/soc/intel/haswell.c @@ -0,0 +1,241 @@ +/* + * Intel Haswell Lynxpoint SST Audio + * + * Copyright (C) 2013, Intel Corporation. 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 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. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "sst-dsp.h" +#include "sst-haswell-ipc.h" + +#include "../codecs/rt5640.h" + +/* Haswell ULT platforms have a Headphone and Mic jack */ +static const struct snd_soc_dapm_widget haswell_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_MIC("Mic", NULL), +}; + +static const struct snd_soc_dapm_route haswell_rt5640_map[] = { + + {"Headphones", NULL, "HPOR"}, + {"Headphones", NULL, "HPOL"}, + {"IN2P", NULL, "Mic"}, + + /* CODEC BE connections */ + {"SSP0 CODEC IN", NULL, "AIF1 Capture"}, + {"AIF1 Playback", NULL, "SSP0 CODEC OUT"}, +}; + +static int haswell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + + /* The ADSP will covert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP0 to 16 bit */ + snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - + SNDRV_PCM_HW_PARAM_FIRST_MASK], + SNDRV_PCM_FORMAT_S16_LE); + return 0; +} + +static int haswell_rt5640_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int ret; + + /* Set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec DAI configuration\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_MCLK, 12288000, + SND_SOC_CLOCK_IN); + + if (ret < 0) { + dev_err(rtd->dev, "can't set codec sysclk configuration\n"); + return ret; + } + + /* set correct codec filter for DAI format and clock config */ + snd_soc_update_bits(rtd->codec, 0x83, 0xffff, 0x8000); + + return ret; +} + +static struct snd_soc_ops haswell_rt5640_ops = { + .hw_params = haswell_rt5640_hw_params, +}; + +static int haswell_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct sst_pdata *pdata = dev_get_platdata(rtd->platform->dev); + struct sst_hsw *haswell = pdata->dsp; + int ret; + + /* Set ADSP SSP port settings */ + ret = sst_hsw_device_set_config(haswell, SST_HSW_DEVICE_SSP_0, + SST_HSW_DEVICE_MCLK_FREQ_24_MHZ, + SST_HSW_DEVICE_CLOCK_MASTER, 9); + if (ret < 0) { + dev_err(rtd->dev, "failed to set device config\n"); + return ret; + } + + /* always connected */ + snd_soc_dapm_enable_pin(dapm, "Headphones"); + snd_soc_dapm_enable_pin(dapm, "Mic"); + + return 0; +} + +static struct snd_soc_dai_link haswell_rt5640_dais[] = { + /* Front End DAI links */ + { + .name = "System", + .stream_name = "System Playback", + .cpu_dai_name = "System Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .init = haswell_rtd_init, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_playback = 1, + }, + { + .name = "Offload0", + .stream_name = "Offload0 Playback", + .cpu_dai_name = "Offload0 Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_playback = 1, + }, + { + .name = "Offload1", + .stream_name = "Offload1 Playback", + .cpu_dai_name = "Offload1 Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_playback = 1, + }, + { + .name = "Loopback", + .stream_name = "Loopback", + .cpu_dai_name = "Loopback Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 0, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_capture = 1, + }, + { + .name = "Capture", + .stream_name = "Capture", + .cpu_dai_name = "Capture Pin", + .platform_name = "haswell-pcm-audio", + .dynamic = 1, + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .dpcm_capture = 1, + }, + + /* Back End DAI links */ + { + /* SSP0 - Codec */ + .name = "Codec", + .be_id = 0, + .cpu_dai_name = "snd-soc-dummy-dai", + .platform_name = "snd-soc-dummy", + .no_pcm = 1, + .codec_name = "i2c-INT33CA:00", + .codec_dai_name = "rt5640-aif1", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .be_hw_params_fixup = haswell_ssp0_fixup, + .ops = &haswell_rt5640_ops, + .dpcm_playback = 1, + .dpcm_capture = 1, + }, +}; + +/* audio machine driver for Haswell Lynxpoint DSP + RT5640 */ +static struct snd_soc_card haswell_rt5640 = { + .name = "haswell-rt5640", + .owner = THIS_MODULE, + .dai_link = haswell_rt5640_dais, + .num_links = ARRAY_SIZE(haswell_rt5640_dais), + .dapm_widgets = haswell_widgets, + .num_dapm_widgets = ARRAY_SIZE(haswell_widgets), + .dapm_routes = haswell_rt5640_map, + .num_dapm_routes = ARRAY_SIZE(haswell_rt5640_map), + .fully_routed = true, +}; + +static int haswell_audio_probe(struct platform_device *pdev) +{ + haswell_rt5640.dev = &pdev->dev; + + return snd_soc_register_card(&haswell_rt5640); +} + +static int haswell_audio_remove(struct platform_device *pdev) +{ + snd_soc_unregister_card(&haswell_rt5640); + return 0; +} + +static struct platform_driver haswell_audio = { + .probe = haswell_audio_probe, + .remove = haswell_audio_remove, + .driver = { + .name = "haswell-audio", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(haswell_audio) + +/* Module information */ +MODULE_AUTHOR("Liam Girdwood, Xingchao Wang"); +MODULE_DESCRIPTION("Intel SST Audio for Haswell Lynxpoint"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:haswell-audio"); -- cgit v1.2.3 From 9b87a5b0d4aad02e9dff299b63cd85930eb233d8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:44:17 +0100 Subject: ASoC: pxa: Remove superfluous locking The locking here was added in commit 71a295602e ("ASoC: Lock the CODEC in PXA external jack controls") to protect the DAPM changes that are made inside of ${board}_ext_control() against concurrent updates. The ASoC core was updated in commit a73fb2df01 ("ASoC: dapm: Use DAPM mutex for DAPM ops instead of codec mutex") to use a card wide lock rather the CODEC mutex to protect DAPM operations. We now have proper locking inside ${board}_ext_control() itself, so taking the CODEC lock can be removed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/corgi.c | 4 ---- sound/soc/pxa/magician.c | 4 ---- sound/soc/pxa/poodle.c | 4 ---- sound/soc/pxa/spitz.c | 4 ---- sound/soc/pxa/tosa.c | 4 ---- 5 files changed, 20 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 1853d41034bf..b51f88002e62 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -99,13 +99,9 @@ static int corgi_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ corgi_ext_control(&codec->dapm); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index aace19e0fe2c..aeb08f5f3e1c 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -73,13 +73,9 @@ static int magician_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ magician_ext_control(codec); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index c93e138d8dc3..27c6c03bc5d7 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -76,13 +76,9 @@ static int poodle_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ poodle_ext_control(&codec->dapm); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index fc052d8247ff..0728c1eb780c 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -108,13 +108,9 @@ static int spitz_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ spitz_ext_control(&codec->dapm); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 1d9c2ed223bc..d6f38d7ecc1c 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -80,13 +80,9 @@ static int tosa_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ tosa_ext_control(codec); - mutex_unlock(&codec->mutex); - return 0; } -- cgit v1.2.3 From d1755bb75c68abaa2024dc9507d1c78521adadeb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:16:08 +0100 Subject: ASoC: mc13783: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/mc13783.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 582c2bbd42cb..21c8baa2dd22 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -408,8 +408,8 @@ static const char * const adcl_enum_text[] = { "MC1L", "RXINL", }; -static const struct soc_enum adcl_enum = - SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcl_enum_text), adcl_enum_text); +static SOC_ENUM_SINGLE_DECL(adcl_enum, + 0, 0, adcl_enum_text); static const struct snd_kcontrol_new left_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcl_enum); @@ -418,8 +418,8 @@ static const char * const adcr_enum_text[] = { "MC1R", "MC2", "RXINR", "TXIN", }; -static const struct soc_enum adcr_enum = - SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adcr_enum_text), adcr_enum_text); +static SOC_ENUM_SINGLE_DECL(adcr_enum, + 0, 0, adcr_enum_text); static const struct snd_kcontrol_new right_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcr_enum); @@ -580,9 +580,9 @@ static struct snd_soc_dapm_route mc13783_routes[] = { static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix", "Mono", "Mono Mix"}; -static const struct soc_enum mc13783_enum_3d_mixer = - SOC_ENUM_SINGLE(MC13783_AUDIO_RX1, 16, ARRAY_SIZE(mc13783_3d_mixer), - mc13783_3d_mixer); +static SOC_ENUM_SINGLE_DECL(mc13783_enum_3d_mixer, + MC13783_AUDIO_RX1, 16, + mc13783_3d_mixer); static struct snd_kcontrol_new mc13783_control_list[] = { SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0), -- cgit v1.2.3 From c8ed6504218c5a1951159033d1b1e7927665f109 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:16:31 +0100 Subject: ASoC: sgtl5000: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 0fcbe90f3ef2..ab4754a7a88c 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -187,8 +187,9 @@ static const char *adc_mux_text[] = { "MIC_IN", "LINE_IN" }; -static const struct soc_enum adc_enum = -SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 2, 2, adc_mux_text); +static SOC_ENUM_SINGLE_DECL(adc_enum, + SGTL5000_CHIP_ANA_CTRL, 2, + adc_mux_text); static const struct snd_kcontrol_new adc_mux = SOC_DAPM_ENUM("Capture Mux", adc_enum); @@ -198,8 +199,9 @@ static const char *dac_mux_text[] = { "DAC", "LINE_IN" }; -static const struct soc_enum dac_enum = -SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 6, 2, dac_mux_text); +static SOC_ENUM_SINGLE_DECL(dac_enum, + SGTL5000_CHIP_ANA_CTRL, 6, + dac_mux_text); static const struct snd_kcontrol_new dac_mux = SOC_DAPM_ENUM("Headphone Mux", dac_enum); -- cgit v1.2.3 From f3c1196e16a84e81978bdf60690cb82fe33e880f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:17:24 +0100 Subject: ASoC: sn95031: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/sn95031.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 13045f2af4d3..bca7d02b362a 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -312,14 +312,14 @@ static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w, /* mux controls */ static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" }; -static const struct soc_enum sn95031_micl_enum = - SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_micl_enum, + SN95031_ADCCONFIG, 1, sn95031_mic_texts); static const struct snd_kcontrol_new sn95031_micl_mux_control = SOC_DAPM_ENUM("Route", sn95031_micl_enum); -static const struct soc_enum sn95031_micr_enum = - SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_micr_enum, + SN95031_ADCCONFIG, 3, sn95031_mic_texts); static const struct snd_kcontrol_new sn95031_micr_mux_control = SOC_DAPM_ENUM("Route", sn95031_micr_enum); @@ -328,26 +328,26 @@ static const char *sn95031_input_texts[] = { "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6", "ADC Left", "ADC Right" }; -static const struct soc_enum sn95031_input1_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input1_enum, + SN95031_AUDIOMUX12, 0, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input1_mux_control = SOC_DAPM_ENUM("Route", sn95031_input1_enum); -static const struct soc_enum sn95031_input2_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input2_enum, + SN95031_AUDIOMUX12, 4, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input2_mux_control = SOC_DAPM_ENUM("Route", sn95031_input2_enum); -static const struct soc_enum sn95031_input3_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input3_enum, + SN95031_AUDIOMUX34, 0, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input3_mux_control = SOC_DAPM_ENUM("Route", sn95031_input3_enum); -static const struct soc_enum sn95031_input4_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts); +static SOC_ENUM_SINGLE_DECL(sn95031_input4_enum, + SN95031_AUDIOMUX34, 4, sn95031_input_texts); static const struct snd_kcontrol_new sn95031_input4_mux_control = SOC_DAPM_ENUM("Route", sn95031_input4_enum); @@ -359,19 +359,19 @@ static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"}; /* 0dB to 30dB in 10dB steps */ static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 0); -static const struct soc_enum sn95031_micmode1_enum = - SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text); -static const struct soc_enum sn95031_micmode2_enum = - SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text); +static SOC_ENUM_SINGLE_DECL(sn95031_micmode1_enum, + SN95031_MICAMP1, 1, sn95031_micmode_text); +static SOC_ENUM_SINGLE_DECL(sn95031_micmode2_enum, + SN95031_MICAMP2, 1, sn95031_micmode_text); static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"}; -static const struct soc_enum sn95031_dmic12_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text); -static const struct soc_enum sn95031_dmic34_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text); -static const struct soc_enum sn95031_dmic56_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(sn95031_dmic12_cfg_enum, + SN95031_DMICMUX, 0, sn95031_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(sn95031_dmic34_cfg_enum, + SN95031_DMICMUX, 1, sn95031_dmic_cfg_text); +static SOC_ENUM_SINGLE_DECL(sn95031_dmic56_cfg_enum, + SN95031_DMICMUX, 2, sn95031_dmic_cfg_text); static const struct snd_kcontrol_new sn95031_snd_controls[] = { SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum), -- cgit v1.2.3 From 3cd7ca58827234c40bb683de2d1d8512631be8e4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:26:27 +0100 Subject: ASoC: stac9766: Use SOC_ENUM_{SINGLE|DOUBLE}_DECL() Just replace with the helper macros. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/stac9766.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index a5455c1aea42..53b810d23fea 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -62,25 +62,25 @@ static const char *stac9766_boost1[] = {"0dB", "10dB"}; static const char *stac9766_boost2[] = {"0dB", "20dB"}; static const char *stac9766_stereo_mic[] = {"Off", "On"}; -static const struct soc_enum stac9766_record_enum = - SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, stac9766_record_mux); -static const struct soc_enum stac9766_mono_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, stac9766_mono_mux); -static const struct soc_enum stac9766_mic_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, stac9766_mic_mux); -static const struct soc_enum stac9766_SPDIF_enum = - SOC_ENUM_SINGLE(AC97_STAC_DA_CONTROL, 1, 2, stac9766_SPDIF_mux); -static const struct soc_enum stac9766_popbypass_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, stac9766_popbypass_mux); -static const struct soc_enum stac9766_record_all_enum = - SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 12, 2, - stac9766_record_all_mux); -static const struct soc_enum stac9766_boost1_enum = - SOC_ENUM_SINGLE(AC97_MIC, 6, 2, stac9766_boost1); /* 0/10dB */ -static const struct soc_enum stac9766_boost2_enum = - SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 2, 2, stac9766_boost2); /* 0/20dB */ -static const struct soc_enum stac9766_stereo_mic_enum = - SOC_ENUM_SINGLE(AC97_STAC_STEREO_MIC, 2, 1, stac9766_stereo_mic); +static SOC_ENUM_DOUBLE_DECL(stac9766_record_enum, + AC97_REC_SEL, 8, 0, stac9766_record_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_mono_enum, + AC97_GENERAL_PURPOSE, 9, stac9766_mono_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_mic_enum, + AC97_GENERAL_PURPOSE, 8, stac9766_mic_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_SPDIF_enum, + AC97_STAC_DA_CONTROL, 1, stac9766_SPDIF_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_popbypass_enum, + AC97_GENERAL_PURPOSE, 15, stac9766_popbypass_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_record_all_enum, + AC97_STAC_ANALOG_SPECIAL, 12, + stac9766_record_all_mux); +static SOC_ENUM_SINGLE_DECL(stac9766_boost1_enum, + AC97_MIC, 6, stac9766_boost1); /* 0/10dB */ +static SOC_ENUM_SINGLE_DECL(stac9766_boost2_enum, + AC97_STAC_ANALOG_SPECIAL, 2, stac9766_boost2); /* 0/20dB */ +static SOC_ENUM_SINGLE_DECL(stac9766_stereo_mic_enum, + AC97_STAC_STEREO_MIC, 2, stac9766_stereo_mic); static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0); static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250); -- cgit v1.2.3 From 6900ab55dda48825b1cddc87e5e1908d51e96b95 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:27:40 +0100 Subject: ASoC: tlv320aic26: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic26.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 94a658fa6d97..ff5f23d482b7 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -238,8 +238,9 @@ static struct snd_soc_dai_driver aic26_dai = { * ALSA controls */ static const char *aic26_capture_src_text[] = {"Mic", "Aux"}; -static const struct soc_enum aic26_capture_src_enum = - SOC_ENUM_SINGLE(AIC26_REG_AUDIO_CTRL1, 12, 2, aic26_capture_src_text); +static SOC_ENUM_SINGLE_DECL(aic26_capture_src_enum, + AIC26_REG_AUDIO_CTRL1, 12, + aic26_capture_src_text); static const struct snd_kcontrol_new aic26_snd_controls[] = { /* Output */ -- cgit v1.2.3 From 9f04fba79781fb3ba39eac631f4bd6762f9717db Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:28:25 +0100 Subject: ASoC: twl4030: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/twl4030.c | 84 ++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 48 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 00665ada23e2..e084df7e27a5 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -415,10 +415,9 @@ static const struct snd_kcontrol_new twl4030_dapm_carkitr_controls[] = { static const char *twl4030_handsfreel_texts[] = {"Voice", "AudioL1", "AudioL2", "AudioR2"}; -static const struct soc_enum twl4030_handsfreel_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0, - ARRAY_SIZE(twl4030_handsfreel_texts), - twl4030_handsfreel_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_handsfreel_enum, + TWL4030_REG_HFL_CTL, 0, + twl4030_handsfreel_texts); static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control = SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); @@ -431,10 +430,9 @@ static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control = static const char *twl4030_handsfreer_texts[] = {"Voice", "AudioR1", "AudioR2", "AudioL2"}; -static const struct soc_enum twl4030_handsfreer_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0, - ARRAY_SIZE(twl4030_handsfreer_texts), - twl4030_handsfreer_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_handsfreer_enum, + TWL4030_REG_HFR_CTL, 0, + twl4030_handsfreer_texts); static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control = SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); @@ -448,10 +446,9 @@ static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control = static const char *twl4030_vibra_texts[] = {"AudioL1", "AudioR1", "AudioL2", "AudioR2"}; -static const struct soc_enum twl4030_vibra_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 2, - ARRAY_SIZE(twl4030_vibra_texts), - twl4030_vibra_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibra_enum, + TWL4030_REG_VIBRA_CTL, 2, + twl4030_vibra_texts); static const struct snd_kcontrol_new twl4030_dapm_vibra_control = SOC_DAPM_ENUM("Route", twl4030_vibra_enum); @@ -460,10 +457,9 @@ SOC_DAPM_ENUM("Route", twl4030_vibra_enum); static const char *twl4030_vibrapath_texts[] = {"Local vibrator", "Audio"}; -static const struct soc_enum twl4030_vibrapath_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 4, - ARRAY_SIZE(twl4030_vibrapath_texts), - twl4030_vibrapath_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibrapath_enum, + TWL4030_REG_VIBRA_CTL, 4, + twl4030_vibrapath_texts); static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control = SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum); @@ -490,10 +486,9 @@ static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = { static const char *twl4030_micpathtx1_texts[] = {"Analog", "Digimic0"}; -static const struct soc_enum twl4030_micpathtx1_enum = - SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 0, - ARRAY_SIZE(twl4030_micpathtx1_texts), - twl4030_micpathtx1_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_micpathtx1_enum, + TWL4030_REG_ADCMICSEL, 0, + twl4030_micpathtx1_texts); static const struct snd_kcontrol_new twl4030_dapm_micpathtx1_control = SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum); @@ -502,10 +497,9 @@ SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum); static const char *twl4030_micpathtx2_texts[] = {"Analog", "Digimic1"}; -static const struct soc_enum twl4030_micpathtx2_enum = - SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 2, - ARRAY_SIZE(twl4030_micpathtx2_texts), - twl4030_micpathtx2_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_micpathtx2_enum, + TWL4030_REG_ADCMICSEL, 2, + twl4030_micpathtx2_texts); static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control = SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum); @@ -955,10 +949,9 @@ static const char *twl4030_op_modes_texts[] = { "Option 2 (voice/audio)", "Option 1 (audio)" }; -static const struct soc_enum twl4030_op_modes_enum = - SOC_ENUM_SINGLE(TWL4030_REG_CODEC_MODE, 0, - ARRAY_SIZE(twl4030_op_modes_texts), - twl4030_op_modes_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_op_modes_enum, + TWL4030_REG_CODEC_MODE, 0, + twl4030_op_modes_texts); static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -1044,10 +1037,9 @@ static const char *twl4030_avadc_clk_priority_texts[] = { "Voice high priority", "HiFi high priority" }; -static const struct soc_enum twl4030_avadc_clk_priority_enum = - SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2, - ARRAY_SIZE(twl4030_avadc_clk_priority_texts), - twl4030_avadc_clk_priority_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_avadc_clk_priority_enum, + TWL4030_REG_AVADC_CTL, 2, + twl4030_avadc_clk_priority_texts); static const char *twl4030_rampdelay_texts[] = { "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", @@ -1055,40 +1047,36 @@ static const char *twl4030_rampdelay_texts[] = { "3495/2581/1748 ms" }; -static const struct soc_enum twl4030_rampdelay_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HS_POPN_SET, 2, - ARRAY_SIZE(twl4030_rampdelay_texts), - twl4030_rampdelay_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_rampdelay_enum, + TWL4030_REG_HS_POPN_SET, 2, + twl4030_rampdelay_texts); /* Vibra H-bridge direction mode */ static const char *twl4030_vibradirmode_texts[] = { "Vibra H-bridge direction", "Audio data MSB", }; -static const struct soc_enum twl4030_vibradirmode_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 5, - ARRAY_SIZE(twl4030_vibradirmode_texts), - twl4030_vibradirmode_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibradirmode_enum, + TWL4030_REG_VIBRA_CTL, 5, + twl4030_vibradirmode_texts); /* Vibra H-bridge direction */ static const char *twl4030_vibradir_texts[] = { "Positive polarity", "Negative polarity", }; -static const struct soc_enum twl4030_vibradir_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 1, - ARRAY_SIZE(twl4030_vibradir_texts), - twl4030_vibradir_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_vibradir_enum, + TWL4030_REG_VIBRA_CTL, 1, + twl4030_vibradir_texts); /* Digimic Left and right swapping */ static const char *twl4030_digimicswap_texts[] = { "Not swapped", "Swapped", }; -static const struct soc_enum twl4030_digimicswap_enum = - SOC_ENUM_SINGLE(TWL4030_REG_MISC_SET_1, 0, - ARRAY_SIZE(twl4030_digimicswap_texts), - twl4030_digimicswap_texts); +static SOC_ENUM_SINGLE_DECL(twl4030_digimicswap_enum, + TWL4030_REG_MISC_SET_1, 0, + twl4030_digimicswap_texts); static const struct snd_kcontrol_new twl4030_snd_controls[] = { /* Codec operation mode control */ -- cgit v1.2.3 From a1d0d786af587c50ea948439e610c90525af36d7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:30:20 +0100 Subject: ASoC: twl6040: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. Also, use ARRAY_SIZE() in some ASOC_ENUM_SINGLE() lines. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/twl6040.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index cb642c927dc8..bd3a20647fdf 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -392,8 +392,10 @@ static const char *twl6040_amicr_texts[] = {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"}; static const struct soc_enum twl6040_enum[] = { - SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 4, twl6040_amicl_texts), - SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 4, twl6040_amicr_texts), + SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, + ARRAY_SIZE(twl6040_amicl_texts), twl6040_amicl_texts), + SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, + ARRAY_SIZE(twl6040_amicr_texts), twl6040_amicr_texts), }; static const char *twl6040_hs_texts[] = { @@ -476,9 +478,8 @@ static const char *twl6040_power_mode_texts[] = { "Low-Power", "High-Performance", }; -static const struct soc_enum twl6040_power_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_power_mode_texts), - twl6040_power_mode_texts); +static SOC_ENUM_SINGLE_EXT_DECL(twl6040_power_mode_enum, + twl6040_power_mode_texts); static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -- cgit v1.2.3 From 1dbb348d904baed36789078e1202344f5a6ecc84 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:32:16 +0100 Subject: ASoC: uda1380: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. Also, use ARRAY_SIZE() in some ASOC_ENUM_SINGLE() lines. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/uda1380.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 726df6d43c2b..72ee8e1838e5 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -237,25 +237,27 @@ static const char *uda1380_os_setting[] = { }; static const struct soc_enum uda1380_deemp_enum[] = { - SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, 5, uda1380_deemp), - SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, 5, uda1380_deemp), + SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, ARRAY_SIZE(uda1380_deemp), + uda1380_deemp), + SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, ARRAY_SIZE(uda1380_deemp), + uda1380_deemp), }; -static const struct soc_enum uda1380_input_sel_enum = - SOC_ENUM_SINGLE(UDA1380_ADC, 2, 4, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ -static const struct soc_enum uda1380_output_sel_enum = - SOC_ENUM_SINGLE(UDA1380_PM, 7, 2, uda1380_output_sel); /* R02_EN_AVC */ -static const struct soc_enum uda1380_spf_enum = - SOC_ENUM_SINGLE(UDA1380_MODE, 14, 4, uda1380_spf_mode); /* M */ -static const struct soc_enum uda1380_capture_sel_enum = - SOC_ENUM_SINGLE(UDA1380_IFACE, 6, 2, uda1380_capture_sel); /* SEL_SOURCE */ -static const struct soc_enum uda1380_sel_ns_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 14, 2, uda1380_sel_ns); /* SEL_NS */ -static const struct soc_enum uda1380_mix_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 12, 4, uda1380_mix_control); /* MIX, MIX_POS */ -static const struct soc_enum uda1380_sdet_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 4, 4, uda1380_sdet_setting); /* SD_VALUE */ -static const struct soc_enum uda1380_os_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 0, 3, uda1380_os_setting); /* OS */ +static SOC_ENUM_SINGLE_DECL(uda1380_input_sel_enum, + UDA1380_ADC, 2, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ +static SOC_ENUM_SINGLE_DECL(uda1380_output_sel_enum, + UDA1380_PM, 7, uda1380_output_sel); /* R02_EN_AVC */ +static SOC_ENUM_SINGLE_DECL(uda1380_spf_enum, + UDA1380_MODE, 14, uda1380_spf_mode); /* M */ +static SOC_ENUM_SINGLE_DECL(uda1380_capture_sel_enum, + UDA1380_IFACE, 6, uda1380_capture_sel); /* SEL_SOURCE */ +static SOC_ENUM_SINGLE_DECL(uda1380_sel_ns_enum, + UDA1380_MIXER, 14, uda1380_sel_ns); /* SEL_NS */ +static SOC_ENUM_SINGLE_DECL(uda1380_mix_enum, + UDA1380_MIXER, 12, uda1380_mix_control); /* MIX, MIX_POS */ +static SOC_ENUM_SINGLE_DECL(uda1380_sdet_enum, + UDA1380_MIXER, 4, uda1380_sdet_setting); /* SD_VALUE */ +static SOC_ENUM_SINGLE_DECL(uda1380_os_enum, + UDA1380_MIXER, 0, uda1380_os_setting); /* OS */ /* * from -48 dB in 1.5 dB steps (mute instead of -49.5 dB) -- cgit v1.2.3 From 4ec20a9700f6f4fa140d8586f4f8ff5f76ea4ba7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:33:06 +0100 Subject: ASoC: wl1273: Use SOC_ENUM_SINGLE_EXT_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wl1273.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index b7ab2ef567c8..7485285d08d2 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c @@ -209,8 +209,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, return 1; } -static const struct soc_enum wl1273_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_route), wl1273_audio_route); +static SOC_ENUM_SINGLE_EXT_DECL(wl1273_enum, wl1273_audio_route); static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -247,9 +246,7 @@ static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol, static const char * const wl1273_audio_strings[] = { "Digital", "Analog" }; -static const struct soc_enum wl1273_audio_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_strings), - wl1273_audio_strings); +static SOC_ENUM_SINGLE_EXT_DECL(wl1273_audio_enum, wl1273_audio_strings); static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -- cgit v1.2.3 From 9614be73d810a02f23f3cc19d8eb97b81213545e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:33:59 +0100 Subject: ASoC: wm2200: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm2200.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 57ba315d0c84..1e0a083d8345 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1113,11 +1113,10 @@ static const char *wm2200_rxanc_input_sel_texts[] = { "None", "IN1", "IN2", "IN3", }; -static const struct soc_enum wm2200_rxanc_input_sel = - SOC_ENUM_SINGLE(WM2200_RXANC_SRC, - WM2200_IN_RXANC_SEL_SHIFT, - ARRAY_SIZE(wm2200_rxanc_input_sel_texts), - wm2200_rxanc_input_sel_texts); +static SOC_ENUM_SINGLE_DECL(wm2200_rxanc_input_sel, + WM2200_RXANC_SRC, + WM2200_IN_RXANC_SEL_SHIFT, + wm2200_rxanc_input_sel_texts); static const struct snd_kcontrol_new wm2200_snd_controls[] = { SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL, @@ -1288,11 +1287,10 @@ static const char *wm2200_aec_loopback_texts[] = { "OUT1L", "OUT1R", "OUT2L", "OUT2R", }; -static const struct soc_enum wm2200_aec_loopback = - SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1, - WM2200_AEC_LOOPBACK_SRC_SHIFT, - ARRAY_SIZE(wm2200_aec_loopback_texts), - wm2200_aec_loopback_texts); +static SOC_ENUM_SINGLE_DECL(wm2200_aec_loopback, + WM2200_DAC_AEC_CONTROL_1, + WM2200_AEC_LOOPBACK_SRC_SHIFT, + wm2200_aec_loopback_texts); static const struct snd_kcontrol_new wm2200_aec_loopback_mux = SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback); -- cgit v1.2.3 From fed08d94bf3f930ebe9ad2f3ad7744b8e2eab6bc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:35:49 +0100 Subject: ASoC: wm8523: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8523.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 74d106dc7667..5dfd571b1a03 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -75,8 +75,8 @@ static const char *wm8523_zd_count_text[] = { "2048", }; -static const struct soc_enum wm8523_zc_count = - SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); +static SOC_ENUM_SINGLE_DECL(wm8523_zc_count, WM8523_ZERO_DETECT, 0, + wm8523_zd_count_text); static const struct snd_kcontrol_new wm8523_controls[] = { SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, -- cgit v1.2.3 From 9e74b14ad5140837cfa0dc639dc13acaa2b05b0f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:36:16 +0100 Subject: ASoC: wm8731: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8731.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 029720366ff8..d9655f981df1 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -83,8 +83,8 @@ static bool wm8731_writeable(struct device *dev, unsigned int reg) static const char *wm8731_input_select[] = {"Line In", "Mic"}; -static const struct soc_enum wm8731_insel_enum = - SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select); +static SOC_ENUM_SINGLE_DECL(wm8731_insel_enum, + WM8731_APANA, 2, wm8731_input_select); static int wm8731_deemph[] = { 0, 32000, 44100, 48000 }; -- cgit v1.2.3 From ca275811fd2eef7e0121fefbc46cc5b47d680b10 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:37:14 +0100 Subject: ASoC: wm8737: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8737.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 22de2420bec8..ecc4e8725d5b 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -99,29 +99,29 @@ static const char *micbias_enum_text[] = { "100%", }; -static const struct soc_enum micbias_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 0, 4, micbias_enum_text); +static SOC_ENUM_SINGLE_DECL(micbias_enum, + WM8737_MIC_PREAMP_CONTROL, 0, micbias_enum_text); static const char *low_cutoff_text[] = { "Low", "High" }; -static const struct soc_enum low_3d = - SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 6, 2, low_cutoff_text); +static SOC_ENUM_SINGLE_DECL(low_3d, + WM8737_3D_ENHANCE, 6, low_cutoff_text); static const char *high_cutoff_text[] = { "High", "Low" }; -static const struct soc_enum high_3d = - SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 5, 2, high_cutoff_text); +static SOC_ENUM_SINGLE_DECL(high_3d, + WM8737_3D_ENHANCE, 5, high_cutoff_text); static const char *alc_fn_text[] = { "Disabled", "Right", "Left", "Stereo" }; -static const struct soc_enum alc_fn = - SOC_ENUM_SINGLE(WM8737_ALC1, 7, 4, alc_fn_text); +static SOC_ENUM_SINGLE_DECL(alc_fn, + WM8737_ALC1, 7, alc_fn_text); static const char *alc_hold_text[] = { "0", "2.67ms", "5.33ms", "10.66ms", "21.32ms", "42.64ms", "85.28ms", @@ -129,24 +129,24 @@ static const char *alc_hold_text[] = { "10.916s", "21.832s", "43.691s" }; -static const struct soc_enum alc_hold = - SOC_ENUM_SINGLE(WM8737_ALC2, 0, 16, alc_hold_text); +static SOC_ENUM_SINGLE_DECL(alc_hold, + WM8737_ALC2, 0, alc_hold_text); static const char *alc_atk_text[] = { "8.4ms", "16.8ms", "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s", "4.3s", "8.6s" }; -static const struct soc_enum alc_atk = - SOC_ENUM_SINGLE(WM8737_ALC3, 0, 11, alc_atk_text); +static SOC_ENUM_SINGLE_DECL(alc_atk, + WM8737_ALC3, 0, alc_atk_text); static const char *alc_dcy_text[] = { "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s", "4.3s", "8.6s", "17.2s", "34.41s" }; -static const struct soc_enum alc_dcy = - SOC_ENUM_SINGLE(WM8737_ALC3, 4, 11, alc_dcy_text); +static SOC_ENUM_SINGLE_DECL(alc_dcy, + WM8737_ALC3, 4, alc_dcy_text); static const struct snd_kcontrol_new wm8737_snd_controls[] = { SOC_DOUBLE_R_TLV("Mic Boost Volume", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R, @@ -191,8 +191,8 @@ static const char *linsel_text[] = { "LINPUT1", "LINPUT2", "LINPUT3", "LINPUT1 DC", }; -static const struct soc_enum linsel_enum = - SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_L, 7, 4, linsel_text); +static SOC_ENUM_SINGLE_DECL(linsel_enum, + WM8737_AUDIO_PATH_L, 7, linsel_text); static const struct snd_kcontrol_new linsel_mux = SOC_DAPM_ENUM("LINSEL", linsel_enum); @@ -202,8 +202,8 @@ static const char *rinsel_text[] = { "RINPUT1", "RINPUT2", "RINPUT3", "RINPUT1 DC", }; -static const struct soc_enum rinsel_enum = - SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_R, 7, 4, rinsel_text); +static SOC_ENUM_SINGLE_DECL(rinsel_enum, + WM8737_AUDIO_PATH_R, 7, rinsel_text); static const struct snd_kcontrol_new rinsel_mux = SOC_DAPM_ENUM("RINSEL", rinsel_enum); @@ -212,15 +212,15 @@ static const char *bypass_text[] = { "Direct", "Preamp" }; -static const struct soc_enum lbypass_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 2, 2, bypass_text); +static SOC_ENUM_SINGLE_DECL(lbypass_enum, + WM8737_MIC_PREAMP_CONTROL, 2, bypass_text); static const struct snd_kcontrol_new lbypass_mux = SOC_DAPM_ENUM("Left Bypass", lbypass_enum); -static const struct soc_enum rbypass_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 3, 2, bypass_text); +static SOC_ENUM_SINGLE_DECL(rbypass_enum, + WM8737_MIC_PREAMP_CONTROL, 3, bypass_text); static const struct snd_kcontrol_new rbypass_mux = SOC_DAPM_ENUM("Left Bypass", rbypass_enum); -- cgit v1.2.3 From a21bc5c5bdeb19314976b79db6dc3993c9b227c8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:40:16 +0100 Subject: ASoC: wm8903: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8903.c | 108 +++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 54 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index eebcb1da3b7b..b82b70a3b3d3 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -489,28 +489,28 @@ static const char *hpf_mode_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3" }; -static const struct soc_enum hpf_mode = - SOC_ENUM_SINGLE(WM8903_ADC_DIGITAL_0, 5, 4, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(hpf_mode, + WM8903_ADC_DIGITAL_0, 5, hpf_mode_text); static const char *osr_text[] = { "Low power", "High performance" }; -static const struct soc_enum adc_osr = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_ADC_0, 0, 2, osr_text); +static SOC_ENUM_SINGLE_DECL(adc_osr, + WM8903_ANALOGUE_ADC_0, 0, osr_text); -static const struct soc_enum dac_osr = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 0, 2, osr_text); +static SOC_ENUM_SINGLE_DECL(dac_osr, + WM8903_DAC_DIGITAL_1, 0, osr_text); static const char *drc_slope_text[] = { "1", "1/2", "1/4", "1/8", "1/16", "0" }; -static const struct soc_enum drc_slope_r0 = - SOC_ENUM_SINGLE(WM8903_DRC_2, 3, 6, drc_slope_text); +static SOC_ENUM_SINGLE_DECL(drc_slope_r0, + WM8903_DRC_2, 3, drc_slope_text); -static const struct soc_enum drc_slope_r1 = - SOC_ENUM_SINGLE(WM8903_DRC_2, 0, 6, drc_slope_text); +static SOC_ENUM_SINGLE_DECL(drc_slope_r1, + WM8903_DRC_2, 0, drc_slope_text); static const char *drc_attack_text[] = { "instantaneous", @@ -518,125 +518,125 @@ static const char *drc_attack_text[] = { "46.4ms", "92.8ms", "185.6ms" }; -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8903_DRC_1, 12, 11, drc_attack_text); +static SOC_ENUM_SINGLE_DECL(drc_attack, + WM8903_DRC_1, 12, drc_attack_text); static const char *drc_decay_text[] = { "186ms", "372ms", "743ms", "1.49s", "2.97s", "5.94s", "11.89s", "23.87s", "47.56s" }; -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8903_DRC_1, 8, 9, drc_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_decay, + WM8903_DRC_1, 8, drc_decay_text); static const char *drc_ff_delay_text[] = { "5 samples", "9 samples" }; -static const struct soc_enum drc_ff_delay = - SOC_ENUM_SINGLE(WM8903_DRC_0, 5, 2, drc_ff_delay_text); +static SOC_ENUM_SINGLE_DECL(drc_ff_delay, + WM8903_DRC_0, 5, drc_ff_delay_text); static const char *drc_qr_decay_text[] = { "0.725ms", "1.45ms", "5.8ms" }; -static const struct soc_enum drc_qr_decay = - SOC_ENUM_SINGLE(WM8903_DRC_1, 4, 3, drc_qr_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_decay, + WM8903_DRC_1, 4, drc_qr_decay_text); static const char *drc_smoothing_text[] = { "Low", "Medium", "High" }; -static const struct soc_enum drc_smoothing = - SOC_ENUM_SINGLE(WM8903_DRC_0, 11, 3, drc_smoothing_text); +static SOC_ENUM_SINGLE_DECL(drc_smoothing, + WM8903_DRC_0, 11, drc_smoothing_text); static const char *soft_mute_text[] = { "Fast (fs/2)", "Slow (fs/32)" }; -static const struct soc_enum soft_mute = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 10, 2, soft_mute_text); +static SOC_ENUM_SINGLE_DECL(soft_mute, + WM8903_DAC_DIGITAL_1, 10, soft_mute_text); static const char *mute_mode_text[] = { "Hard", "Soft" }; -static const struct soc_enum mute_mode = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 9, 2, mute_mode_text); +static SOC_ENUM_SINGLE_DECL(mute_mode, + WM8903_DAC_DIGITAL_1, 9, mute_mode_text); static const char *companding_text[] = { "ulaw", "alaw" }; -static const struct soc_enum dac_companding = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 0, 2, companding_text); +static SOC_ENUM_SINGLE_DECL(dac_companding, + WM8903_AUDIO_INTERFACE_0, 0, companding_text); -static const struct soc_enum adc_companding = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 2, 2, companding_text); +static SOC_ENUM_SINGLE_DECL(adc_companding, + WM8903_AUDIO_INTERFACE_0, 2, companding_text); static const char *input_mode_text[] = { "Single-Ended", "Differential Line", "Differential Mic" }; -static const struct soc_enum linput_mode_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(linput_mode_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 0, input_mode_text); -static const struct soc_enum rinput_mode_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(rinput_mode_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 0, input_mode_text); static const char *linput_mux_text[] = { "IN1L", "IN2L", "IN3L" }; -static const struct soc_enum linput_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 2, 3, linput_mux_text); +static SOC_ENUM_SINGLE_DECL(linput_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 2, linput_mux_text); -static const struct soc_enum linput_inv_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 4, 3, linput_mux_text); +static SOC_ENUM_SINGLE_DECL(linput_inv_enum, + WM8903_ANALOGUE_LEFT_INPUT_1, 4, linput_mux_text); static const char *rinput_mux_text[] = { "IN1R", "IN2R", "IN3R" }; -static const struct soc_enum rinput_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 2, 3, rinput_mux_text); +static SOC_ENUM_SINGLE_DECL(rinput_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 2, rinput_mux_text); -static const struct soc_enum rinput_inv_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text); +static SOC_ENUM_SINGLE_DECL(rinput_inv_enum, + WM8903_ANALOGUE_RIGHT_INPUT_1, 4, rinput_mux_text); static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum lsidetone_enum = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(lsidetone_enum, + WM8903_DAC_DIGITAL_0, 2, sidetone_text); -static const struct soc_enum rsidetone_enum = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(rsidetone_enum, + WM8903_DAC_DIGITAL_0, 0, sidetone_text); static const char *adcinput_text[] = { "ADC", "DMIC" }; -static const struct soc_enum adcinput_enum = - SOC_ENUM_SINGLE(WM8903_CLOCK_RATE_TEST_4, 9, 2, adcinput_text); +static SOC_ENUM_SINGLE_DECL(adcinput_enum, + WM8903_CLOCK_RATE_TEST_4, 9, adcinput_text); static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum lcapture_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 7, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(lcapture_enum, + WM8903_AUDIO_INTERFACE_0, 7, aif_text); -static const struct soc_enum rcapture_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 6, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(rcapture_enum, + WM8903_AUDIO_INTERFACE_0, 6, aif_text); -static const struct soc_enum lplay_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 5, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(lplay_enum, + WM8903_AUDIO_INTERFACE_0, 5, aif_text); -static const struct soc_enum rplay_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 4, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(rplay_enum, + WM8903_AUDIO_INTERFACE_0, 4, aif_text); static const struct snd_kcontrol_new wm8903_snd_controls[] = { -- cgit v1.2.3 From d12bfd62fa936f7549a02811b4168493c67c98be Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:40:50 +0100 Subject: ASoC: wm8904: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8904.c | 73 ++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 36 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 53bbfac6a83a..cf12a9023bae 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -552,18 +552,20 @@ static const char *input_mode_text[] = { "Single-Ended", "Differential Line", "Differential Mic" }; -static const struct soc_enum lin_mode = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(lin_mode, + WM8904_ANALOGUE_LEFT_INPUT_1, 0, + input_mode_text); -static const struct soc_enum rin_mode = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); +static SOC_ENUM_SINGLE_DECL(rin_mode, + WM8904_ANALOGUE_RIGHT_INPUT_1, 0, + input_mode_text); static const char *hpf_mode_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3" }; -static const struct soc_enum hpf_mode = - SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(hpf_mode, WM8904_ADC_DIGITAL_0, 5, + hpf_mode_text); static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -611,8 +613,7 @@ static const char *drc_path_text[] = { "ADC", "DAC" }; -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8904_DRC_0, 14, 2, drc_path_text); +static SOC_ENUM_SINGLE_DECL(drc_path, WM8904_DRC_0, 14, drc_path_text); static const struct snd_kcontrol_new wm8904_dac_snd_controls[] = { SOC_SINGLE_TLV("Digital Playback Boost Volume", @@ -858,14 +859,14 @@ static const char *lin_text[] = { "IN1L", "IN2L", "IN3L" }; -static const struct soc_enum lin_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 2, 3, lin_text); +static SOC_ENUM_SINGLE_DECL(lin_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 2, + lin_text); static const struct snd_kcontrol_new lin_mux = SOC_DAPM_ENUM("Left Capture Mux", lin_enum); -static const struct soc_enum lin_inv_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 4, 3, lin_text); +static SOC_ENUM_SINGLE_DECL(lin_inv_enum, WM8904_ANALOGUE_LEFT_INPUT_1, 4, + lin_text); static const struct snd_kcontrol_new lin_inv_mux = SOC_DAPM_ENUM("Left Capture Inveting Mux", lin_inv_enum); @@ -874,14 +875,14 @@ static const char *rin_text[] = { "IN1R", "IN2R", "IN3R" }; -static const struct soc_enum rin_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 2, 3, rin_text); +static SOC_ENUM_SINGLE_DECL(rin_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 2, + rin_text); static const struct snd_kcontrol_new rin_mux = SOC_DAPM_ENUM("Right Capture Mux", rin_enum); -static const struct soc_enum rin_inv_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 4, 3, rin_text); +static SOC_ENUM_SINGLE_DECL(rin_inv_enum, WM8904_ANALOGUE_RIGHT_INPUT_1, 4, + rin_text); static const struct snd_kcontrol_new rin_inv_mux = SOC_DAPM_ENUM("Right Capture Inveting Mux", rin_inv_enum); @@ -890,26 +891,26 @@ static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum aifoutl_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 7, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutl_enum, WM8904_AUDIO_INTERFACE_0, 7, + aif_text); static const struct snd_kcontrol_new aifoutl_mux = SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); -static const struct soc_enum aifoutr_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 6, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutr_enum, WM8904_AUDIO_INTERFACE_0, 6, + aif_text); static const struct snd_kcontrol_new aifoutr_mux = SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); -static const struct soc_enum aifinl_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 5, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinl_enum, WM8904_AUDIO_INTERFACE_0, 5, + aif_text); static const struct snd_kcontrol_new aifinl_mux = SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); -static const struct soc_enum aifinr_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 4, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinr_enum, WM8904_AUDIO_INTERFACE_0, 4, + aif_text); static const struct snd_kcontrol_new aifinr_mux = SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); @@ -991,26 +992,26 @@ static const char *out_mux_text[] = { "DAC", "Bypass" }; -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 3, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(hpl_enum, WM8904_ANALOGUE_OUT12_ZC, 3, + out_mux_text); static const struct snd_kcontrol_new hpl_mux = SOC_DAPM_ENUM("HPL Mux", hpl_enum); -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 2, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(hpr_enum, WM8904_ANALOGUE_OUT12_ZC, 2, + out_mux_text); static const struct snd_kcontrol_new hpr_mux = SOC_DAPM_ENUM("HPR Mux", hpr_enum); -static const struct soc_enum linel_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 1, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(linel_enum, WM8904_ANALOGUE_OUT12_ZC, 1, + out_mux_text); static const struct snd_kcontrol_new linel_mux = SOC_DAPM_ENUM("LINEL Mux", linel_enum); -static const struct soc_enum liner_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 0, 2, out_mux_text); +static SOC_ENUM_SINGLE_DECL(liner_enum, WM8904_ANALOGUE_OUT12_ZC, 0, + out_mux_text); static const struct snd_kcontrol_new liner_mux = SOC_DAPM_ENUM("LINER Mux", liner_enum); @@ -1019,14 +1020,14 @@ static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum dacl_sidetone_enum = - SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacl_sidetone_enum, WM8904_DAC_DIGITAL_0, 2, + sidetone_text); static const struct snd_kcontrol_new dacl_sidetone_mux = SOC_DAPM_ENUM("Left Sidetone Mux", dacl_sidetone_enum); -static const struct soc_enum dacr_sidetone_enum = - SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacr_sidetone_enum, WM8904_DAC_DIGITAL_0, 0, + sidetone_text); static const struct snd_kcontrol_new dacr_sidetone_mux = SOC_DAPM_ENUM("Right Sidetone Mux", dacr_sidetone_enum); -- cgit v1.2.3 From 47ef34271b8714b01ec1647d9013abf8f11fda3d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:42:06 +0100 Subject: ASoC: wm8940: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8940.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index b404c26c1753..87f032d0d19f 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -154,22 +154,22 @@ static const struct reg_default wm8940_reg_defaults[] = { }; static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" }; -static const struct soc_enum wm8940_adc_companding_enum -= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding); -static const struct soc_enum wm8940_dac_companding_enum -= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 3, 4, wm8940_companding); +static SOC_ENUM_SINGLE_DECL(wm8940_adc_companding_enum, + WM8940_COMPANDINGCTL, 1, wm8940_companding); +static SOC_ENUM_SINGLE_DECL(wm8940_dac_companding_enum, + WM8940_COMPANDINGCTL, 3, wm8940_companding); static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"}; -static const struct soc_enum wm8940_alc_mode_enum -= SOC_ENUM_SINGLE(WM8940_ALC3, 8, 2, wm8940_alc_mode_text); +static SOC_ENUM_SINGLE_DECL(wm8940_alc_mode_enum, + WM8940_ALC3, 8, wm8940_alc_mode_text); static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"}; -static const struct soc_enum wm8940_mic_bias_level_enum -= SOC_ENUM_SINGLE(WM8940_INPUTCTL, 8, 2, wm8940_mic_bias_level_text); +static SOC_ENUM_SINGLE_DECL(wm8940_mic_bias_level_enum, + WM8940_INPUTCTL, 8, wm8940_mic_bias_level_text); static const char *wm8940_filter_mode_text[] = {"Audio", "Application"}; -static const struct soc_enum wm8940_filter_mode_enum -= SOC_ENUM_SINGLE(WM8940_ADC, 7, 2, wm8940_filter_mode_text); +static SOC_ENUM_SINGLE_DECL(wm8940_filter_mode_enum, + WM8940_ADC, 7, wm8940_filter_mode_text); static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1); static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0); -- cgit v1.2.3 From a6616cda405c9b42732a481a71d69f0b60dafc38 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:42:45 +0100 Subject: ASoC: wm8961: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8961.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 900328e28a15..ce8fa6e01cb4 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -317,15 +317,15 @@ static const char *adc_hpf_text[] = { "Hi-fi", "Voice 1", "Voice 2", "Voice 3", }; -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text); +static SOC_ENUM_SINGLE_DECL(adc_hpf, + WM8961_ADC_DAC_CONTROL_2, 7, adc_hpf_text); static const char *dac_deemph_text[] = { "None", "32kHz", "44.1kHz", "48kHz", }; -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text); +static SOC_ENUM_SINGLE_DECL(dac_deemph, + WM8961_ADC_DAC_CONTROL_1, 1, dac_deemph_text); static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0); @@ -385,11 +385,11 @@ static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum dacl_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacl_sidetone, + WM8961_DSP_SIDETONE_0, 2, sidetone_text); -static const struct soc_enum dacr_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(dacr_sidetone, + WM8961_DSP_SIDETONE_1, 2, sidetone_text); static const struct snd_kcontrol_new dacl_mux = SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone); -- cgit v1.2.3 From da6ebf83bb8f3ad5e12b2543f15962e27939ff7f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:07 +0100 Subject: ASoC: wm8962: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index c06bb5088e60..3924ee243745 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1658,16 +1658,16 @@ static const char *cap_hpf_mode_text[] = { "Hi-fi", "Application" }; -static const struct soc_enum cap_hpf_mode = - SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(cap_hpf_mode, + WM8962_ADC_DAC_CONTROL_2, 10, cap_hpf_mode_text); static const char *cap_lhpf_mode_text[] = { "LPF", "HPF" }; -static const struct soc_enum cap_lhpf_mode = - SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(cap_lhpf_mode, + WM8962_LHPF1, 1, cap_lhpf_mode_text); static const struct snd_kcontrol_new wm8962_snd_controls[] = { SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), @@ -2014,40 +2014,40 @@ static int dsp2_event(struct snd_soc_dapm_widget *w, static const char *st_text[] = { "None", "Left", "Right" }; -static const struct soc_enum str_enum = - SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text); +static SOC_ENUM_SINGLE_DECL(str_enum, + WM8962_DAC_DSP_MIXING_1, 2, st_text); static const struct snd_kcontrol_new str_mux = SOC_DAPM_ENUM("Right Sidetone", str_enum); -static const struct soc_enum stl_enum = - SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text); +static SOC_ENUM_SINGLE_DECL(stl_enum, + WM8962_DAC_DSP_MIXING_2, 2, st_text); static const struct snd_kcontrol_new stl_mux = SOC_DAPM_ENUM("Left Sidetone", stl_enum); static const char *outmux_text[] = { "DAC", "Mixer" }; -static const struct soc_enum spkoutr_enum = - SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(spkoutr_enum, + WM8962_SPEAKER_MIXER_2, 7, outmux_text); static const struct snd_kcontrol_new spkoutr_mux = SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum); -static const struct soc_enum spkoutl_enum = - SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(spkoutl_enum, + WM8962_SPEAKER_MIXER_1, 7, outmux_text); static const struct snd_kcontrol_new spkoutl_mux = SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum); -static const struct soc_enum hpoutr_enum = - SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(hpoutr_enum, + WM8962_HEADPHONE_MIXER_2, 7, outmux_text); static const struct snd_kcontrol_new hpoutr_mux = SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum); -static const struct soc_enum hpoutl_enum = - SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text); +static SOC_ENUM_SINGLE_DECL(hpoutl_enum, + WM8962_HEADPHONE_MIXER_1, 7, outmux_text); static const struct snd_kcontrol_new hpoutl_mux = SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum); -- cgit v1.2.3 From de461bd2908c44ac51ff3be6a7bf8d13ad23ce1f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:31 +0100 Subject: ASoC: wm8974: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8974.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 15f45c7bd833..6e16c4306461 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -84,8 +84,8 @@ static const struct soc_enum wm8974_enum[] = { static const char *wm8974_auxmode_text[] = { "Buffer", "Mixer" }; -static const struct soc_enum wm8974_auxmode = - SOC_ENUM_SINGLE(WM8974_INPUT, 3, 2, wm8974_auxmode_text); +static SOC_ENUM_SINGLE_DECL(wm8974_auxmode, + WM8974_INPUT, 3, wm8974_auxmode_text); static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -- cgit v1.2.3 From 2d075611c67c7a351fead73ac6bf0864049305b3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:45:12 +0100 Subject: ASoC: wm8993: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8993.c | 64 +++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 2ee23a39622c..1c12f2c9418a 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -646,8 +646,8 @@ static const char *dac_deemph_text[] = { "48kHz", }; -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text); +static SOC_ENUM_SINGLE_DECL(dac_deemph, + WM8993_DAC_CTRL, 4, dac_deemph_text); static const char *adc_hpf_text[] = { "Hi-Fi", @@ -656,16 +656,16 @@ static const char *adc_hpf_text[] = { "Voice 3", }; -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text); +static SOC_ENUM_SINGLE_DECL(adc_hpf, + WM8993_ADC_CTRL, 5, adc_hpf_text); static const char *drc_path_text[] = { "ADC", "DAC" }; -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text); +static SOC_ENUM_SINGLE_DECL(drc_path, + WM8993_DRC_CONTROL_1, 14, drc_path_text); static const char *drc_r0_text[] = { "1", @@ -676,8 +676,8 @@ static const char *drc_r0_text[] = { "0", }; -static const struct soc_enum drc_r0 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text); +static SOC_ENUM_SINGLE_DECL(drc_r0, + WM8993_DRC_CONTROL_3, 8, drc_r0_text); static const char *drc_r1_text[] = { "1", @@ -687,8 +687,8 @@ static const char *drc_r1_text[] = { "0", }; -static const struct soc_enum drc_r1 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text); +static SOC_ENUM_SINGLE_DECL(drc_r1, + WM8993_DRC_CONTROL_4, 13, drc_r1_text); static const char *drc_attack_text[] = { "Reserved", @@ -705,8 +705,8 @@ static const char *drc_attack_text[] = { "185.6ms", }; -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text); +static SOC_ENUM_SINGLE_DECL(drc_attack, + WM8993_DRC_CONTROL_2, 12, drc_attack_text); static const char *drc_decay_text[] = { "186ms", @@ -720,16 +720,16 @@ static const char *drc_decay_text[] = { "47.56ms", }; -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text); +static SOC_ENUM_SINGLE_DECL(drc_decay, + WM8993_DRC_CONTROL_2, 8, drc_decay_text); static const char *drc_ff_text[] = { "5 samples", "9 samples", }; -static const struct soc_enum drc_ff = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text); +static SOC_ENUM_SINGLE_DECL(drc_ff, + WM8993_DRC_CONTROL_3, 7, drc_ff_text); static const char *drc_qr_rate_text[] = { "0.725ms", @@ -737,8 +737,8 @@ static const char *drc_qr_rate_text[] = { "5.8ms", }; -static const struct soc_enum drc_qr_rate = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_rate, + WM8993_DRC_CONTROL_3, 0, drc_qr_rate_text); static const char *drc_smooth_text[] = { "Low", @@ -746,8 +746,8 @@ static const char *drc_smooth_text[] = { "High", }; -static const struct soc_enum drc_smooth = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text); +static SOC_ENUM_SINGLE_DECL(drc_smooth, + WM8993_DRC_CONTROL_1, 4, drc_smooth_text); static const struct snd_kcontrol_new wm8993_snd_controls[] = { SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE, @@ -841,26 +841,26 @@ static const char *aif_text[] = { "Left", "Right" }; -static const struct soc_enum aifoutl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutl_enum, + WM8993_AUDIO_INTERFACE_1, 15, aif_text); static const struct snd_kcontrol_new aifoutl_mux = SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); -static const struct soc_enum aifoutr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifoutr_enum, + WM8993_AUDIO_INTERFACE_1, 14, aif_text); static const struct snd_kcontrol_new aifoutr_mux = SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); -static const struct soc_enum aifinl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinl_enum, + WM8993_AUDIO_INTERFACE_2, 15, aif_text); static const struct snd_kcontrol_new aifinl_mux = SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); -static const struct soc_enum aifinr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text); +static SOC_ENUM_SINGLE_DECL(aifinr_enum, + WM8993_AUDIO_INTERFACE_2, 14, aif_text); static const struct snd_kcontrol_new aifinr_mux = SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); @@ -869,14 +869,14 @@ static const char *sidetone_text[] = { "None", "Left", "Right" }; -static const struct soc_enum sidetonel_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetonel_enum, + WM8993_DIGITAL_SIDE_TONE, 2, sidetone_text); static const struct snd_kcontrol_new sidetonel_mux = SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum); -static const struct soc_enum sidetoner_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetoner_enum, + WM8993_DIGITAL_SIDE_TONE, 0, sidetone_text); static const struct snd_kcontrol_new sidetoner_mux = SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum); -- cgit v1.2.3 From 15b49e73d375a952e34d31f7aac92944df003ca3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:46:47 +0100 Subject: ASoC: wm8995: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8995.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 403e1db6870f..0c539bf1105c 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -781,14 +781,12 @@ static const char *sidetone_text[] = { "ADC/DMIC1", "DMIC2", }; -static const struct soc_enum sidetone1_enum = - SOC_ENUM_SINGLE(WM8995_SIDETONE, 0, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetone1_enum, WM8995_SIDETONE, 0, sidetone_text); static const struct snd_kcontrol_new sidetone1_mux = SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); -static const struct soc_enum sidetone2_enum = - SOC_ENUM_SINGLE(WM8995_SIDETONE, 1, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(sidetone2_enum, WM8995_SIDETONE, 1, sidetone_text); static const struct snd_kcontrol_new sidetone2_mux = SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); @@ -884,8 +882,7 @@ static const char *adc_mux_text[] = { "DMIC", }; -static const struct soc_enum adc_enum = - SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text); +static const SOC_ENUM_SINGLE_DECL(adc_enum, 0, 0, adc_mux_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); -- cgit v1.2.3 From 5cca5a916f7ade910e2996e3b44ddffee8e08caf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:47:05 +0100 Subject: ASoC: wm8996: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 56 +++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1a7655b0aa22..92bb02185c46 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -311,28 +311,28 @@ static const char *sidetone_hpf_text[] = { "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" }; -static const struct soc_enum sidetone_hpf = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 7, sidetone_hpf_text); +static SOC_ENUM_SINGLE_DECL(sidetone_hpf, + WM8996_SIDETONE, 7, sidetone_hpf_text); static const char *hpf_mode_text[] = { "HiFi", "Custom", "Voice" }; -static const struct soc_enum dsp1tx_hpf_mode = - SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 3, 3, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(dsp1tx_hpf_mode, + WM8996_DSP1_TX_FILTERS, 3, hpf_mode_text); -static const struct soc_enum dsp2tx_hpf_mode = - SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 3, 3, hpf_mode_text); +static SOC_ENUM_SINGLE_DECL(dsp2tx_hpf_mode, + WM8996_DSP2_TX_FILTERS, 3, hpf_mode_text); static const char *hpf_cutoff_text[] = { "50Hz", "75Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum dsp1tx_hpf_cutoff = - SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 0, 7, hpf_cutoff_text); +static SOC_ENUM_SINGLE_DECL(dsp1tx_hpf_cutoff, + WM8996_DSP1_TX_FILTERS, 0, hpf_cutoff_text); -static const struct soc_enum dsp2tx_hpf_cutoff = - SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 0, 7, hpf_cutoff_text); +static SOC_ENUM_SINGLE_DECL(dsp2tx_hpf_cutoff, + WM8996_DSP2_TX_FILTERS, 0, hpf_cutoff_text); static void wm8996_set_retune_mobile(struct snd_soc_codec *codec, int block) { @@ -780,14 +780,14 @@ static const char *sidetone_text[] = { "IN1", "IN2", }; -static const struct soc_enum left_sidetone_enum = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 0, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(left_sidetone_enum, + WM8996_SIDETONE, 0, sidetone_text); static const struct snd_kcontrol_new left_sidetone = SOC_DAPM_ENUM("Left Sidetone", left_sidetone_enum); -static const struct soc_enum right_sidetone_enum = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 1, 2, sidetone_text); +static SOC_ENUM_SINGLE_DECL(right_sidetone_enum, + WM8996_SIDETONE, 1, sidetone_text); static const struct snd_kcontrol_new right_sidetone = SOC_DAPM_ENUM("Right Sidetone", right_sidetone_enum); @@ -796,14 +796,14 @@ static const char *spk_text[] = { "DAC1L", "DAC1R", "DAC2L", "DAC2R" }; -static const struct soc_enum spkl_enum = - SOC_ENUM_SINGLE(WM8996_LEFT_PDM_SPEAKER, 0, 4, spk_text); +static SOC_ENUM_SINGLE_DECL(spkl_enum, + WM8996_LEFT_PDM_SPEAKER, 0, spk_text); static const struct snd_kcontrol_new spkl_mux = SOC_DAPM_ENUM("SPKL", spkl_enum); -static const struct soc_enum spkr_enum = - SOC_ENUM_SINGLE(WM8996_RIGHT_PDM_SPEAKER, 0, 4, spk_text); +static SOC_ENUM_SINGLE_DECL(spkr_enum, + WM8996_RIGHT_PDM_SPEAKER, 0, spk_text); static const struct snd_kcontrol_new spkr_mux = SOC_DAPM_ENUM("SPKR", spkr_enum); @@ -812,8 +812,8 @@ static const char *dsp1rx_text[] = { "AIF1", "AIF2" }; -static const struct soc_enum dsp1rx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 0, 2, dsp1rx_text); +static SOC_ENUM_SINGLE_DECL(dsp1rx_enum, + WM8996_POWER_MANAGEMENT_8, 0, dsp1rx_text); static const struct snd_kcontrol_new dsp1rx = SOC_DAPM_ENUM("DSP1RX", dsp1rx_enum); @@ -822,8 +822,8 @@ static const char *dsp2rx_text[] = { "AIF2", "AIF1" }; -static const struct soc_enum dsp2rx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 4, 2, dsp2rx_text); +static SOC_ENUM_SINGLE_DECL(dsp2rx_enum, + WM8996_POWER_MANAGEMENT_8, 4, dsp2rx_text); static const struct snd_kcontrol_new dsp2rx = SOC_DAPM_ENUM("DSP2RX", dsp2rx_enum); @@ -832,8 +832,8 @@ static const char *aif2tx_text[] = { "DSP2", "DSP1", "AIF1" }; -static const struct soc_enum aif2tx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 6, 3, aif2tx_text); +static SOC_ENUM_SINGLE_DECL(aif2tx_enum, + WM8996_POWER_MANAGEMENT_8, 6, aif2tx_text); static const struct snd_kcontrol_new aif2tx = SOC_DAPM_ENUM("AIF2TX", aif2tx_enum); @@ -842,14 +842,14 @@ static const char *inmux_text[] = { "ADC", "DMIC1", "DMIC2" }; -static const struct soc_enum in1_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 0, 3, inmux_text); +static SOC_ENUM_SINGLE_DECL(in1_enum, + WM8996_POWER_MANAGEMENT_7, 0, inmux_text); static const struct snd_kcontrol_new in1_mux = SOC_DAPM_ENUM("IN1 Mux", in1_enum); -static const struct soc_enum in2_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 4, 3, inmux_text); +static SOC_ENUM_SINGLE_DECL(in2_enum, + WM8996_POWER_MANAGEMENT_7, 4, inmux_text); static const struct snd_kcontrol_new in2_mux = SOC_DAPM_ENUM("IN2 Mux", in2_enum); -- cgit v1.2.3 From abc4b4fb94a274055f5da900976d0970f73a00cc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:47:17 +0100 Subject: ASoC: wm_hubs: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index b371066dd5bc..b6209662ab13 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -50,16 +50,16 @@ static const char *speaker_ref_text[] = { "VMID", }; -static const struct soc_enum speaker_ref = - SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text); +static SOC_ENUM_SINGLE_DECL(speaker_ref, + WM8993_SPEAKER_MIXER, 8, speaker_ref_text); static const char *speaker_mode_text[] = { "Class D", "Class AB", }; -static const struct soc_enum speaker_mode = - SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); +static SOC_ENUM_SINGLE_DECL(speaker_mode, + WM8993_SPKMIXR_ATTENUATION, 8, speaker_mode_text); static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) { @@ -735,15 +735,15 @@ static const char *hp_mux_text[] = { "DAC", }; -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text); +static SOC_ENUM_SINGLE_DECL(hpl_enum, + WM8993_OUTPUT_MIXER1, 8, hp_mux_text); const struct snd_kcontrol_new wm_hubs_hpl_mux = WM_HUBS_ENUM_W("Left Headphone Mux", hpl_enum); EXPORT_SYMBOL_GPL(wm_hubs_hpl_mux); -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text); +static SOC_ENUM_SINGLE_DECL(hpr_enum, + WM8993_OUTPUT_MIXER2, 8, hp_mux_text); const struct snd_kcontrol_new wm_hubs_hpr_mux = WM_HUBS_ENUM_W("Right Headphone Mux", hpr_enum); -- cgit v1.2.3 From 7cb5e1bb9f91bf984f26b520072a22610235d869 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:47:34 +0100 Subject: ASoC: omap: Use SOC_ENUM_SINGLE_EXT_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/omap/ams-delta.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 629446482a91..99b314d53790 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -194,13 +194,11 @@ static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol, return 0; } -static const struct soc_enum ams_delta_audio_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode), - ams_delta_audio_mode), -}; +static const SOC_ENUM_SINGLE_EXT_DECL(ams_delta_audio_enum, + ams_delta_audio_mode); static const struct snd_kcontrol_new ams_delta_audio_controls[] = { - SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0], + SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum, ams_delta_get_audio_mode, ams_delta_set_audio_mode), }; -- cgit v1.2.3 From 6eb0e8f90f5156bb8441c8427b1c11ed9401178f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:13 +0100 Subject: ASoC: 88pm860x: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/88pm860x-codec.c | 116 +++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 58 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 75d0ad5d2dcb..697d24be7897 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -448,38 +448,38 @@ static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"}; static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"}; -static const struct soc_enum pm860x_hs1_opamp_enum = - SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs1_opamp_enum, + PM860X_HS1_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_hs2_opamp_enum = - SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs2_opamp_enum, + PM860X_HS2_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_hs1_pa_enum = - SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs1_pa_enum, + PM860X_HS1_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_hs2_pa_enum = - SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_hs2_pa_enum, + PM860X_HS2_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_lo1_opamp_enum = - SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo1_opamp_enum, + PM860X_LO1_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_lo2_opamp_enum = - SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo2_opamp_enum, + PM860X_LO2_CTRL, 5, pm860x_opamp_texts); -static const struct soc_enum pm860x_lo1_pa_enum = - SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo1_pa_enum, + PM860X_LO1_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_lo2_pa_enum = - SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_lo2_pa_enum, + PM860X_LO2_CTRL, 3, pm860x_pa_texts); -static const struct soc_enum pm860x_spk_pa_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_spk_pa_enum, + PM860X_EAR_CTRL_1, 5, pm860x_pa_texts); -static const struct soc_enum pm860x_ear_pa_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_ear_pa_enum, + PM860X_EAR_CTRL_2, 0, pm860x_pa_texts); -static const struct soc_enum pm860x_spk_ear_opamp_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts); +static SOC_ENUM_SINGLE_DECL(pm860x_spk_ear_opamp_enum, + PM860X_EAR_CTRL_1, 3, pm860x_opamp_texts); static const struct snd_kcontrol_new pm860x_snd_controls[] = { SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2, @@ -561,8 +561,8 @@ static const char *aif1_text[] = { "PCM L", "PCM R", }; -static const struct soc_enum aif1_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text); +static SOC_ENUM_SINGLE_DECL(aif1_enum, + PM860X_PCM_IFACE_3, 6, aif1_text); static const struct snd_kcontrol_new aif1_mux = SOC_DAPM_ENUM("PCM Mux", aif1_enum); @@ -572,8 +572,8 @@ static const char *i2s_din_text[] = { "DIN", "DIN1", }; -static const struct soc_enum i2s_din_enum = - SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text); +static SOC_ENUM_SINGLE_DECL(i2s_din_enum, + PM860X_I2S_IFACE_3, 1, i2s_din_text); static const struct snd_kcontrol_new i2s_din_mux = SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum); @@ -583,8 +583,8 @@ static const char *i2s_mic_text[] = { "Ex PA", "ADC", }; -static const struct soc_enum i2s_mic_enum = - SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text); +static SOC_ENUM_SINGLE_DECL(i2s_mic_enum, + PM860X_I2S_IFACE_3, 4, i2s_mic_text); static const struct snd_kcontrol_new i2s_mic_mux = SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum); @@ -594,8 +594,8 @@ static const char *adcl_text[] = { "ADCR", "ADCL", }; -static const struct soc_enum adcl_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text); +static SOC_ENUM_SINGLE_DECL(adcl_enum, + PM860X_PCM_IFACE_3, 4, adcl_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM("ADC Left Mux", adcl_enum); @@ -605,8 +605,8 @@ static const char *adcr_text[] = { "ADCL", "ADCR", }; -static const struct soc_enum adcr_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text); +static SOC_ENUM_SINGLE_DECL(adcr_enum, + PM860X_PCM_IFACE_3, 2, adcr_text); static const struct snd_kcontrol_new adcr_mux = SOC_DAPM_ENUM("ADC Right Mux", adcr_enum); @@ -616,8 +616,8 @@ static const char *adcr_ec_text[] = { "ADCR", "EC", }; -static const struct soc_enum adcr_ec_enum = - SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text); +static SOC_ENUM_SINGLE_DECL(adcr_ec_enum, + PM860X_ADC_EN_2, 3, adcr_ec_text); static const struct snd_kcontrol_new adcr_ec_mux = SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum); @@ -627,8 +627,8 @@ static const char *ec_text[] = { "Left", "Right", "Left + Right", }; -static const struct soc_enum ec_enum = - SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text); +static SOC_ENUM_SINGLE_DECL(ec_enum, + PM860X_EC_PATH, 1, ec_text); static const struct snd_kcontrol_new ec_mux = SOC_DAPM_ENUM("EC Mux", ec_enum); @@ -638,36 +638,36 @@ static const char *dac_text[] = { }; /* DAC Headset 1 Mux / Mux10 */ -static const struct soc_enum dac_hs1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_hs1_enum, + PM860X_ANA_INPUT_SEL_1, 0, dac_text); static const struct snd_kcontrol_new dac_hs1_mux = SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum); /* DAC Headset 2 Mux / Mux11 */ -static const struct soc_enum dac_hs2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_hs2_enum, + PM860X_ANA_INPUT_SEL_1, 2, dac_text); static const struct snd_kcontrol_new dac_hs2_mux = SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum); /* DAC Lineout 1 Mux / Mux12 */ -static const struct soc_enum dac_lo1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_lo1_enum, + PM860X_ANA_INPUT_SEL_1, 4, dac_text); static const struct snd_kcontrol_new dac_lo1_mux = SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum); /* DAC Lineout 2 Mux / Mux13 */ -static const struct soc_enum dac_lo2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_lo2_enum, + PM860X_ANA_INPUT_SEL_1, 6, dac_text); static const struct snd_kcontrol_new dac_lo2_mux = SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum); /* DAC Spearker Earphone Mux / Mux14 */ -static const struct soc_enum dac_spk_ear_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text); +static SOC_ENUM_SINGLE_DECL(dac_spk_ear_enum, + PM860X_ANA_INPUT_SEL_2, 0, dac_text); static const struct snd_kcontrol_new dac_spk_ear_mux = SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum); @@ -677,29 +677,29 @@ static const char *in_text[] = { "Digital", "Analog", }; -static const struct soc_enum hs1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text); +static SOC_ENUM_SINGLE_DECL(hs1_enum, + PM860X_ANA_TO_ANA, 0, in_text); static const struct snd_kcontrol_new hs1_mux = SOC_DAPM_ENUM("Headset1 Mux", hs1_enum); /* Headset 2 Mux / Mux16 */ -static const struct soc_enum hs2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text); +static SOC_ENUM_SINGLE_DECL(hs2_enum, + PM860X_ANA_TO_ANA, 1, in_text); static const struct snd_kcontrol_new hs2_mux = SOC_DAPM_ENUM("Headset2 Mux", hs2_enum); /* Lineout 1 Mux / Mux17 */ -static const struct soc_enum lo1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text); +static SOC_ENUM_SINGLE_DECL(lo1_enum, + PM860X_ANA_TO_ANA, 2, in_text); static const struct snd_kcontrol_new lo1_mux = SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum); /* Lineout 2 Mux / Mux18 */ -static const struct soc_enum lo2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text); +static SOC_ENUM_SINGLE_DECL(lo2_enum, + PM860X_ANA_TO_ANA, 3, in_text); static const struct snd_kcontrol_new lo2_mux = SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum); @@ -709,8 +709,8 @@ static const char *spk_text[] = { "Earpiece", "Speaker", }; -static const struct soc_enum spk_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text); +static SOC_ENUM_SINGLE_DECL(spk_enum, + PM860X_ANA_TO_ANA, 6, spk_text); static const struct snd_kcontrol_new spk_demux = SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum); @@ -720,8 +720,8 @@ static const char *mic_text[] = { "Mic 1", "Mic 2", }; -static const struct soc_enum mic_enum = - SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text); +static SOC_ENUM_SINGLE_DECL(mic_enum, + PM860X_ADC_ANA_4, 4, mic_text); static const struct snd_kcontrol_new mic_mux = SOC_DAPM_ENUM("MIC Mux", mic_enum); -- cgit v1.2.3 From cbf6242281069c3405b57fc10563d094aae6c9c0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:45 +0100 Subject: ASoC: ak4641: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ak4641.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 94cbe508dd37..684b56f2856a 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -113,14 +113,14 @@ static const DECLARE_TLV_DB_SCALE(alc_tlv, -800, 50, 0); static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0); -static const struct soc_enum ak4641_mono_out_enum = - SOC_ENUM_SINGLE(AK4641_SIG1, 6, 2, ak4641_mono_out); -static const struct soc_enum ak4641_hp_out_enum = - SOC_ENUM_SINGLE(AK4641_MODE2, 2, 2, ak4641_hp_out); -static const struct soc_enum ak4641_mic_select_enum = - SOC_ENUM_SINGLE(AK4641_MIC, 1, 2, ak4641_mic_select); -static const struct soc_enum ak4641_mic_or_dac_enum = - SOC_ENUM_SINGLE(AK4641_BTIF, 4, 2, ak4641_mic_or_dac); +static SOC_ENUM_SINGLE_DECL(ak4641_mono_out_enum, + AK4641_SIG1, 6, ak4641_mono_out); +static SOC_ENUM_SINGLE_DECL(ak4641_hp_out_enum, + AK4641_MODE2, 2, ak4641_hp_out); +static SOC_ENUM_SINGLE_DECL(ak4641_mic_select_enum, + AK4641_MIC, 1, ak4641_mic_select); +static SOC_ENUM_SINGLE_DECL(ak4641_mic_or_dac_enum, + AK4641_BTIF, 4, ak4641_mic_or_dac); static const struct snd_kcontrol_new ak4641_snd_controls[] = { SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum), -- cgit v1.2.3 From 64e6b58db9c3ee550092c73e18e36ad9dc168334 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:43:58 +0100 Subject: ASoC: ak4671: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ak4671.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 743bbe31bc08..deb2b44669de 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -237,19 +237,17 @@ static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = { /* Input MUXs */ static const char *ak4671_lin_mux_texts[] = {"LIN1", "LIN2", "LIN3", "LIN4"}; -static const struct soc_enum ak4671_lin_mux_enum = - SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0, - ARRAY_SIZE(ak4671_lin_mux_texts), - ak4671_lin_mux_texts); +static SOC_ENUM_SINGLE_DECL(ak4671_lin_mux_enum, + AK4671_MIC_SIGNAL_SELECT, 0, + ak4671_lin_mux_texts); static const struct snd_kcontrol_new ak4671_lin_mux_control = SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum); static const char *ak4671_rin_mux_texts[] = {"RIN1", "RIN2", "RIN3", "RIN4"}; -static const struct soc_enum ak4671_rin_mux_enum = - SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2, - ARRAY_SIZE(ak4671_rin_mux_texts), - ak4671_rin_mux_texts); +static SOC_ENUM_SINGLE_DECL(ak4671_rin_mux_enum, + AK4671_MIC_SIGNAL_SELECT, 2, + ak4671_rin_mux_texts); static const struct snd_kcontrol_new ak4671_rin_mux_control = SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum); -- cgit v1.2.3 From e84f2463765ff34a322511be815ad235dcc1f218 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:44:32 +0100 Subject: ASoC: alc5632: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/alc5632.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index fb001c56cf8d..d885056ad8f2 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -293,51 +293,59 @@ static const char * const alc5632_i2s_out_sel[] = { "ADC LR", "Voice Stereo Digital"}; /* auxout output mux */ -static const struct soc_enum alc5632_aux_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_aux_out_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 6, + alc5632_aux_out_input_sel); static const struct snd_kcontrol_new alc5632_auxout_mux_controls = SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum); /* speaker output mux */ -static const struct soc_enum alc5632_spkout_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_spkout_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 10, + alc5632_spkout_input_sel); static const struct snd_kcontrol_new alc5632_spkout_mux_controls = SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum); /* headphone left output mux */ -static const struct soc_enum alc5632_hpl_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_hpl_out_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 9, + alc5632_hpl_out_input_sel); static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls = SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum); /* headphone right output mux */ -static const struct soc_enum alc5632_hpr_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_hpr_out_input_enum, + ALC5632_OUTPUT_MIXER_CTRL, 8, + alc5632_hpr_out_input_sel); static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls = SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum); /* speaker output N select */ -static const struct soc_enum alc5632_spk_n_sour_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_spk_n_sour_enum, + ALC5632_OUTPUT_MIXER_CTRL, 14, + alc5632_spk_n_sour_sel); static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls = SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum); /* speaker amplifier */ static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"}; -static const struct soc_enum alc5632_amp_enum = - SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names); +static SOC_ENUM_SINGLE_DECL(alc5632_amp_enum, + ALC5632_OUTPUT_MIXER_CTRL, 13, + alc5632_amp_names); static const struct snd_kcontrol_new alc5632_amp_mux_controls = SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum); /* ADC output select */ -static const struct soc_enum alc5632_adcr_func_enum = - SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_adcr_func_enum, + ALC5632_DAC_FUNC_SELECT, 5, + alc5632_adcr_func_sel); static const struct snd_kcontrol_new alc5632_adcr_func_controls = SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum); /* I2S out select */ -static const struct soc_enum alc5632_i2s_out_enum = - SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel); +static SOC_ENUM_SINGLE_DECL(alc5632_i2s_out_enum, + ALC5632_I2S_OUT_CTL, 5, + alc5632_i2s_out_sel); static const struct snd_kcontrol_new alc5632_i2s_out_controls = SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum); -- cgit v1.2.3 From 0cd257bf9b9b0cbb4fa1a5c988a232506997867c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 20 Feb 2014 09:04:06 +0900 Subject: ASoC: alc5623: Convert to direct regmap API usage Convert to directly use the regmap API, allowing us to eliminate the last user of the ASoC level I/O implementations (there are still open coded I/O implementations in drivers), avoiding duplicating code in regmap. We no longer cache the entire CODEC register map on probe since the more advanced cache infrastructure in regmap is able to fill the cache on demand. Signed-off-by: Mark Brown --- sound/soc/codecs/alc5623.c | 87 ++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 38 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index ba61c07ebbb2..ed506253a914 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -38,26 +39,13 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)"); /* codec private data */ struct alc5623_priv { - enum snd_soc_control_type control_type; + struct regmap *regmap; u8 id; unsigned int sysclk; - u16 reg_cache[ALC5623_VENDOR_ID2+2]; unsigned int add_ctrl; unsigned int jack_det_ctrl; }; -static void alc5623_fill_cache(struct snd_soc_codec *codec) -{ - int i, step = codec->driver->reg_cache_step; - u16 *cache = codec->reg_cache; - - /* not really efficient ... */ - codec->cache_bypass = 1; - for (i = 0 ; i < codec->driver->reg_cache_size ; i += step) - cache[i] = snd_soc_read(codec, i); - codec->cache_bypass = 0; -} - static inline int alc5623_reset(struct snd_soc_codec *codec) { return snd_soc_write(codec, ALC5623_RESET, 0); @@ -875,18 +863,28 @@ static struct snd_soc_dai_driver alc5623_dai = { static int alc5623_suspend(struct snd_soc_codec *codec) { + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); + regcache_cache_only(alc5623->regmap, true); + return 0; } static int alc5623_resume(struct snd_soc_codec *codec) { - int i, step = codec->driver->reg_cache_step; - u16 *cache = codec->reg_cache; + struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); + int ret; /* Sync reg_cache with the hardware */ - for (i = 2 ; i < codec->driver->reg_cache_size ; i += step) - snd_soc_write(codec, i, cache[i]); + regcache_cache_only(alc5623->regmap, false); + ret = regcache_sync(alc5623->regmap); + if (ret != 0) { + dev_err(codec->dev, "Failed to sync register cache: %d\n", + ret); + regcache_cache_only(alc5623->regmap, true); + return ret; + } alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -906,14 +904,14 @@ static int alc5623_probe(struct snd_soc_codec *codec) struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type); + codec->control_data = alc5623->regmap; + ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; } alc5623_reset(codec); - alc5623_fill_cache(codec); /* power on device */ alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -986,9 +984,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = { .suspend = alc5623_suspend, .resume = alc5623_resume, .set_bias_level = alc5623_set_bias_level, - .reg_cache_size = ALC5623_VENDOR_ID2+2, - .reg_word_size = sizeof(u16), - .reg_cache_step = 2, +}; + +static const struct regmap_config alc5623_regmap = { + .reg_bits = 8, + .val_bits = 16, + .reg_stride = 2, + + .max_register = ALC5623_VENDOR_ID2, + .cache_type = REGCACHE_RBTREE, }; /* @@ -1002,19 +1006,32 @@ static int alc5623_i2c_probe(struct i2c_client *client, { struct alc5623_platform_data *pdata; struct alc5623_priv *alc5623; - int ret, vid1, vid2; + unsigned int vid1, vid2; + int ret; - vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1); - if (vid1 < 0) { - dev_err(&client->dev, "failed to read I2C\n"); - return -EIO; + alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), + GFP_KERNEL); + if (alc5623 == NULL) + return -ENOMEM; + + alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap); + if (IS_ERR(alc5623->regmap)) { + ret = PTR_ERR(alc5623->regmap); + dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret); + return ret; + } + + ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1); + if (ret < 0) { + dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret); + return ret; } vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); - vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2); - if (vid2 < 0) { - dev_err(&client->dev, "failed to read I2C\n"); - return -EIO; + ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2); + if (ret < 0) { + dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret); + return ret; } if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { @@ -1027,11 +1044,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); - alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), - GFP_KERNEL); - if (alc5623 == NULL) - return -ENOMEM; - pdata = client->dev.platform_data; if (pdata) { alc5623->add_ctrl = pdata->add_ctrl; @@ -1054,7 +1066,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, } i2c_set_clientdata(client, alc5623); - alc5623->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&client->dev, &soc_codec_device_alc5623, &alc5623_dai, 1); -- cgit v1.2.3 From 6109ab2bfc22c903e4e8592bdcce268758f1dd5b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:44:57 +0100 Subject: ASoC: wm2200: Use SOC_ENUM_SINGLE_*_DECL() Just replace with the helper macros. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l51.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 6e9ea8379a91..1703b9c988db 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -135,8 +135,7 @@ static const char *chan_mix[] = { "R L", }; -static const struct soc_enum cs42l51_chan_mix = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix); +static SOC_ENUM_SINGLE_EXT_DECL(cs42l51_chan_mix, chan_mix); static const struct snd_kcontrol_new cs42l51_snd_controls[] = { SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", @@ -192,22 +191,22 @@ static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, static const char *cs42l51_dac_names[] = {"Direct PCM", "DSP PCM", "ADC"}; -static const struct soc_enum cs42l51_dac_mux_enum = - SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names); +static SOC_ENUM_SINGLE_DECL(cs42l51_dac_mux_enum, + CS42L51_DAC_CTL, 6, cs42l51_dac_names); static const struct snd_kcontrol_new cs42l51_dac_mux_controls = SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum); static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left", "MIC Left", "MIC+preamp Left"}; -static const struct soc_enum cs42l51_adcl_mux_enum = - SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names); +static SOC_ENUM_SINGLE_DECL(cs42l51_adcl_mux_enum, + CS42L51_ADC_INPUT, 4, cs42l51_adcl_names); static const struct snd_kcontrol_new cs42l51_adcl_mux_controls = SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum); static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right", "MIC Right", "MIC+preamp Right"}; -static const struct soc_enum cs42l51_adcr_mux_enum = - SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names); +static SOC_ENUM_SINGLE_DECL(cs42l51_adcr_mux_enum, + CS42L51_ADC_INPUT, 6, cs42l51_adcr_names); static const struct snd_kcontrol_new cs42l51_adcr_mux_controls = SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum); -- cgit v1.2.3 From 7e5091087246b620dfbfed2ce4f17c53898b66d4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:45:17 +0100 Subject: ASoC: da732x: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/da732x.c | 160 +++++++++++++++++++++------------------------- 1 file changed, 72 insertions(+), 88 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index f295b6569910..3219fa1f3cf5 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -269,81 +269,65 @@ static const char *da732x_hpf_voice[] = { "150Hz", "200Hz", "300Hz", "400Hz" }; -static const struct soc_enum da732x_dac1_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; - -static const struct soc_enum da732x_dac2_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac1_hpf_mode_enum, + DA732X_REG_DAC1_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_dac3_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac2_hpf_mode_enum, + DA732X_REG_DAC2_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_adc1_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac3_hpf_mode_enum, + DA732X_REG_DAC3_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_adc2_hpf_mode_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, - DA732X_HPF_MODE_MAX, da732x_hpf_mode) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc1_hpf_mode_enum, + DA732X_REG_ADC1_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_dac1_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc2_hpf_mode_enum, + DA732X_REG_ADC2_HPF, DA732X_HPF_MODE_SHIFT, + da732x_hpf_mode); -static const struct soc_enum da732x_dac2_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac1_hp_filter_enum, + DA732X_REG_DAC1_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_dac3_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac2_hp_filter_enum, + DA732X_REG_DAC2_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_adc1_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac3_hp_filter_enum, + DA732X_REG_DAC3_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_adc2_hp_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, - DA732X_HPF_MUSIC_MAX, da732x_hpf_music) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc1_hp_filter_enum, + DA732X_REG_ADC1_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_dac1_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc2_hp_filter_enum, + DA732X_REG_ADC2_HPF, DA732X_HPF_MUSIC_SHIFT, + da732x_hpf_music); -static const struct soc_enum da732x_dac2_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac1_voice_filter_enum, + DA732X_REG_DAC1_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); -static const struct soc_enum da732x_dac3_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac2_voice_filter_enum, + DA732X_REG_DAC2_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); -static const struct soc_enum da732x_adc1_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_dac3_voice_filter_enum, + DA732X_REG_DAC3_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); -static const struct soc_enum da732x_adc2_voice_filter_enum[] = { - SOC_ENUM_SINGLE(DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, - DA732X_HPF_VOICE_MAX, da732x_hpf_voice) -}; +static SOC_ENUM_SINGLE_DECL(da732x_adc1_voice_filter_enum, + DA732X_REG_ADC1_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); +static SOC_ENUM_SINGLE_DECL(da732x_adc2_voice_filter_enum, + DA732X_REG_ADC2_HPF, DA732X_HPF_VOICE_SHIFT, + da732x_hpf_voice); static int da732x_hpf_set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -714,65 +698,65 @@ static const char *enable_text[] = { }; /* ADC1LMUX */ -static const struct soc_enum adc1l_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, - DA732X_ADCL_MUX_MAX, adcl_text); +static SOC_ENUM_SINGLE_DECL(adc1l_enum, + DA732X_REG_INP_MUX, DA732X_ADC1L_MUX_SEL_SHIFT, + adcl_text); static const struct snd_kcontrol_new adc1l_mux = SOC_DAPM_ENUM("ADC Route", adc1l_enum); /* ADC1RMUX */ -static const struct soc_enum adc1r_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, - DA732X_ADCR_MUX_MAX, adcr_text); +static SOC_ENUM_SINGLE_DECL(adc1r_enum, + DA732X_REG_INP_MUX, DA732X_ADC1R_MUX_SEL_SHIFT, + adcr_text); static const struct snd_kcontrol_new adc1r_mux = SOC_DAPM_ENUM("ADC Route", adc1r_enum); /* ADC2LMUX */ -static const struct soc_enum adc2l_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, - DA732X_ADCL_MUX_MAX, adcl_text); +static SOC_ENUM_SINGLE_DECL(adc2l_enum, + DA732X_REG_INP_MUX, DA732X_ADC2L_MUX_SEL_SHIFT, + adcl_text); static const struct snd_kcontrol_new adc2l_mux = SOC_DAPM_ENUM("ADC Route", adc2l_enum); /* ADC2RMUX */ -static const struct soc_enum adc2r_enum = - SOC_ENUM_SINGLE(DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, - DA732X_ADCR_MUX_MAX, adcr_text); +static SOC_ENUM_SINGLE_DECL(adc2r_enum, + DA732X_REG_INP_MUX, DA732X_ADC2R_MUX_SEL_SHIFT, + adcr_text); static const struct snd_kcontrol_new adc2r_mux = SOC_DAPM_ENUM("ADC Route", adc2r_enum); -static const struct soc_enum da732x_hp_left_output = - SOC_ENUM_SINGLE(DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_hp_left_output, + DA732X_REG_HPL, DA732X_HP_OUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new hpl_mux = SOC_DAPM_ENUM("HPL Switch", da732x_hp_left_output); -static const struct soc_enum da732x_hp_right_output = - SOC_ENUM_SINGLE(DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_hp_right_output, + DA732X_REG_HPR, DA732X_HP_OUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new hpr_mux = SOC_DAPM_ENUM("HPR Switch", da732x_hp_right_output); -static const struct soc_enum da732x_speaker_output = - SOC_ENUM_SINGLE(DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_speaker_output, + DA732X_REG_LIN3, DA732X_LOUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new spk_mux = SOC_DAPM_ENUM("SPK Switch", da732x_speaker_output); -static const struct soc_enum da732x_lout4_output = - SOC_ENUM_SINGLE(DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_lout4_output, + DA732X_REG_LIN4, DA732X_LOUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new lout4_mux = SOC_DAPM_ENUM("LOUT4 Switch", da732x_lout4_output); -static const struct soc_enum da732x_lout2_output = - SOC_ENUM_SINGLE(DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, - DA732X_DAC_EN_MAX, enable_text); +static SOC_ENUM_SINGLE_DECL(da732x_lout2_output, + DA732X_REG_LIN2, DA732X_LOUT_DAC_EN_SHIFT, + enable_text); static const struct snd_kcontrol_new lout2_mux = SOC_DAPM_ENUM("LOUT2 Switch", da732x_lout2_output); -- cgit v1.2.3 From c3518d1bd45ebfdfd88480e5781054fed378fb22 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:45:36 +0100 Subject: ASoC: ml26124: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ml26124.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 185fa3bc3052..577fb8776ce7 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -73,11 +73,11 @@ static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0); static const char * const ml26124_companding[] = {"16bit PCM", "u-law", "A-law"}; -static const struct soc_enum ml26124_adc_companding_enum - = SOC_ENUM_SINGLE(ML26124_SAI_TRANS_CTL, 6, 3, ml26124_companding); +static SOC_ENUM_SINGLE_DECL(ml26124_adc_companding_enum, + ML26124_SAI_TRANS_CTL, 6, ml26124_companding); -static const struct soc_enum ml26124_dac_companding_enum - = SOC_ENUM_SINGLE(ML26124_SAI_RCV_CTL, 6, 3, ml26124_companding); +static SOC_ENUM_SINGLE_DECL(ml26124_dac_companding_enum, + ML26124_SAI_RCV_CTL, 6, ml26124_companding); static const struct snd_kcontrol_new ml26124_snd_controls[] = { SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0, @@ -136,8 +136,8 @@ static const struct snd_kcontrol_new ml26124_output_mixer_controls[] = { static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in", "Digital MIC in", "Analog MIC Differential in"}; -static const struct soc_enum ml26124_insel_enum = - SOC_ENUM_SINGLE(ML26124_MIC_IF_CTL, 0, 3, ml26124_input_select); +static SOC_ENUM_SINGLE_DECL(ml26124_insel_enum, + ML26124_MIC_IF_CTL, 0, ml26124_input_select); static const struct snd_kcontrol_new ml26124_input_mux_controls = SOC_DAPM_ENUM("Input Select", ml26124_insel_enum); -- cgit v1.2.3 From 806057cc75ef641cd9b012b0278c1f179090bab2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:45:53 +0100 Subject: ASoC: tlv320aic23: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic23.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 5d430cc56f51..139f11f4dd8b 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -64,16 +64,16 @@ static const struct regmap_config tlv320aic23_regmap = { static const char *rec_src_text[] = { "Line", "Mic" }; static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const struct soc_enum rec_src_enum = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); +static SOC_ENUM_SINGLE_DECL(rec_src_enum, + TLV320AIC23_ANLG, 2, rec_src_text); static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = SOC_DAPM_ENUM("Input Select", rec_src_enum); -static const struct soc_enum tlv320aic23_rec_src = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); -static const struct soc_enum tlv320aic23_deemph = - SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text); +static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src, + TLV320AIC23_ANLG, 2, rec_src_text); +static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph, + TLV320AIC23_DIGT, 1, deemph_text); static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0); static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0); -- cgit v1.2.3 From 0224ba6a01983a52ed809bdc8647510d02656143 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:46:09 +0100 Subject: ASoC: wm5100: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm5100.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 4e3e31aaf509..14beefd7e58c 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -506,21 +506,21 @@ static const char *wm5100_lhpf_mode_text[] = { "Low-pass", "High-pass" }; -static const struct soc_enum wm5100_lhpf1_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf1_mode, + WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, + wm5100_lhpf_mode_text); -static const struct soc_enum wm5100_lhpf2_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf2_mode, + WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, + wm5100_lhpf_mode_text); -static const struct soc_enum wm5100_lhpf3_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf3_mode, + WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, + wm5100_lhpf_mode_text); -static const struct soc_enum wm5100_lhpf4_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); +static SOC_ENUM_SINGLE_DECL(wm5100_lhpf4_mode, + WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, + wm5100_lhpf_mode_text); static const struct snd_kcontrol_new wm5100_snd_controls[] = { SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL, -- cgit v1.2.3 From 54db41c116c31b8829ba636895556a9fa45df987 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:46:22 +0100 Subject: ASoC: wm8955: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8955.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 82c8ba975720..d4dcaecc8a5f 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -416,22 +416,21 @@ static const char *bass_mode_text[] = { "Linear", "Adaptive", }; -static const struct soc_enum bass_mode = - SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 7, 2, bass_mode_text); +static SOC_ENUM_SINGLE_DECL(bass_mode, WM8955_BASS_CONTROL, 7, bass_mode_text); static const char *bass_cutoff_text[] = { "Low", "High" }; -static const struct soc_enum bass_cutoff = - SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 6, 2, bass_cutoff_text); +static SOC_ENUM_SINGLE_DECL(bass_cutoff, WM8955_BASS_CONTROL, 6, + bass_cutoff_text); static const char *treble_cutoff_text[] = { "High", "Low" }; -static const struct soc_enum treble_cutoff = - SOC_ENUM_SINGLE(WM8955_TREBLE_CONTROL, 6, 2, treble_cutoff_text); +static SOC_ENUM_SINGLE_DECL(treble_cutoff, WM8955_TREBLE_CONTROL, 2, + treble_cutoff_text); static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(atten_tlv, -600, 600, 0); -- cgit v1.2.3 From b13a054aed6f6f3103df14f8bb0f9da4c4edb514 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:46:35 +0100 Subject: ASoC: wm8988: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8988.c | 48 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index c6e4aba25b77..0277a76c6bef 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -126,46 +126,46 @@ struct wm8988_priv { */ static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"}; -static const struct soc_enum bass_boost = - SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt); +static SOC_ENUM_SINGLE_DECL(bass_boost, + WM8988_BASS, 7, bass_boost_txt); static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" }; -static const struct soc_enum bass_filter = - SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt); +static SOC_ENUM_SINGLE_DECL(bass_filter, + WM8988_BASS, 6, bass_filter_txt); static const char *treble_txt[] = {"8kHz", "4kHz"}; -static const struct soc_enum treble = - SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt); +static SOC_ENUM_SINGLE_DECL(treble, + WM8988_TREBLE, 6, treble_txt); static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"}; -static const struct soc_enum stereo_3d_lc = - SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt); +static SOC_ENUM_SINGLE_DECL(stereo_3d_lc, + WM8988_3D, 5, stereo_3d_lc_txt); static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"}; -static const struct soc_enum stereo_3d_uc = - SOC_ENUM_SINGLE(WM8988_3D, 6, 2, stereo_3d_uc_txt); +static SOC_ENUM_SINGLE_DECL(stereo_3d_uc, + WM8988_3D, 6, stereo_3d_uc_txt); static const char *stereo_3d_func_txt[] = {"Capture", "Playback"}; -static const struct soc_enum stereo_3d_func = - SOC_ENUM_SINGLE(WM8988_3D, 7, 2, stereo_3d_func_txt); +static SOC_ENUM_SINGLE_DECL(stereo_3d_func, + WM8988_3D, 7, stereo_3d_func_txt); static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"}; -static const struct soc_enum alc_func = - SOC_ENUM_SINGLE(WM8988_ALC1, 7, 4, alc_func_txt); +static SOC_ENUM_SINGLE_DECL(alc_func, + WM8988_ALC1, 7, alc_func_txt); static const char *ng_type_txt[] = {"Constant PGA Gain", "Mute ADC Output"}; -static const struct soc_enum ng_type = - SOC_ENUM_SINGLE(WM8988_NGATE, 1, 2, ng_type_txt); +static SOC_ENUM_SINGLE_DECL(ng_type, + WM8988_NGATE, 1, ng_type_txt); static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const struct soc_enum deemph = - SOC_ENUM_SINGLE(WM8988_ADCDAC, 1, 4, deemph_txt); +static SOC_ENUM_SINGLE_DECL(deemph, + WM8988_ADCDAC, 1, deemph_txt); static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert", "L + R Invert"}; -static const struct soc_enum adcpol = - SOC_ENUM_SINGLE(WM8988_ADCDAC, 5, 4, adcpol_txt); +static SOC_ENUM_SINGLE_DECL(adcpol, + WM8988_ADCDAC, 5, adcpol_txt); static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1); @@ -317,16 +317,16 @@ static const struct snd_kcontrol_new wm8988_right_pga_controls = /* Differential Mux */ static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"}; -static const struct soc_enum diffmux = - SOC_ENUM_SINGLE(WM8988_ADCIN, 8, 2, wm8988_diff_sel); +static SOC_ENUM_SINGLE_DECL(diffmux, + WM8988_ADCIN, 8, wm8988_diff_sel); static const struct snd_kcontrol_new wm8988_diffmux_controls = SOC_DAPM_ENUM("Route", diffmux); /* Mono ADC Mux */ static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)", "Mono (Right)", "Digital Mono"}; -static const struct soc_enum monomux = - SOC_ENUM_SINGLE(WM8988_ADCIN, 6, 4, wm8988_mono_mux); +static SOC_ENUM_SINGLE_DECL(monomux, + WM8988_ADCIN, 6, wm8988_mono_mux); static const struct snd_kcontrol_new wm8988_monomux_controls = SOC_DAPM_ENUM("Route", monomux); -- cgit v1.2.3 From aedbfd9649c5a9ee8e601f8f35e74ea617371ae5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:46:48 +0100 Subject: ASoC: wm9081: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm9081.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 0982c1d38ec4..721cee71d5fc 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -268,8 +268,7 @@ static const char *drc_high_text[] = { "0", }; -static const struct soc_enum drc_high = - SOC_ENUM_SINGLE(WM9081_DRC_3, 3, 6, drc_high_text); +static SOC_ENUM_SINGLE_DECL(drc_high, WM9081_DRC_3, 3, drc_high_text); static const char *drc_low_text[] = { "1", @@ -279,8 +278,7 @@ static const char *drc_low_text[] = { "0", }; -static const struct soc_enum drc_low = - SOC_ENUM_SINGLE(WM9081_DRC_3, 0, 5, drc_low_text); +static SOC_ENUM_SINGLE_DECL(drc_low, WM9081_DRC_3, 0, drc_low_text); static const char *drc_atk_text[] = { "181us", @@ -297,8 +295,7 @@ static const char *drc_atk_text[] = { "185.6ms", }; -static const struct soc_enum drc_atk = - SOC_ENUM_SINGLE(WM9081_DRC_2, 12, 12, drc_atk_text); +static SOC_ENUM_SINGLE_DECL(drc_atk, WM9081_DRC_2, 12, drc_atk_text); static const char *drc_dcy_text[] = { "186ms", @@ -312,8 +309,7 @@ static const char *drc_dcy_text[] = { "47.56s", }; -static const struct soc_enum drc_dcy = - SOC_ENUM_SINGLE(WM9081_DRC_2, 8, 9, drc_dcy_text); +static SOC_ENUM_SINGLE_DECL(drc_dcy, WM9081_DRC_2, 8, drc_dcy_text); static const char *drc_qr_dcy_text[] = { "0.725ms", @@ -321,8 +317,7 @@ static const char *drc_qr_dcy_text[] = { "5.8ms", }; -static const struct soc_enum drc_qr_dcy = - SOC_ENUM_SINGLE(WM9081_DRC_2, 4, 3, drc_qr_dcy_text); +static SOC_ENUM_SINGLE_DECL(drc_qr_dcy, WM9081_DRC_2, 4, drc_qr_dcy_text); static const char *dac_deemph_text[] = { "None", @@ -331,16 +326,16 @@ static const char *dac_deemph_text[] = { "48kHz", }; -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM9081_DAC_DIGITAL_2, 1, 4, dac_deemph_text); +static SOC_ENUM_SINGLE_DECL(dac_deemph, WM9081_DAC_DIGITAL_2, 1, + dac_deemph_text); static const char *speaker_mode_text[] = { "Class D", "Class AB", }; -static const struct soc_enum speaker_mode = - SOC_ENUM_SINGLE(WM9081_ANALOGUE_SPEAKER_2, 6, 2, speaker_mode_text); +static SOC_ENUM_SINGLE_DECL(speaker_mode, WM9081_ANALOGUE_SPEAKER_2, 6, + speaker_mode_text); static int speaker_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -- cgit v1.2.3 From 09981dcb77eba05974eed4def32931fb12421fae Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:47:00 +0100 Subject: ASoC: wm9705: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm9705.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 70ce6793c5bd..c0b7f45dfa37 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -67,12 +67,12 @@ static const char *wm9705_mic[] = {"Mic 1", "Mic 2"}; static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC", "Line", "Stereo Mix", "Mono Mix", "Phone"}; -static const struct soc_enum wm9705_enum_mic = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic); -static const struct soc_enum wm9705_enum_rec_l = - SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel); -static const struct soc_enum wm9705_enum_rec_r = - SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_mic, + AC97_GENERAL_PURPOSE, 8, wm9705_mic); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_l, + AC97_REC_SEL, 8, wm9705_rec_sel); +static SOC_ENUM_SINGLE_DECL(wm9705_enum_rec_r, + AC97_REC_SEL, 0, wm9705_rec_sel); /* Headphone Mixer */ static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = { -- cgit v1.2.3 From 2e86434f9eeb4a6d9379895b889ac85fa51b0ac9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:54:31 +0100 Subject: ASoC: ad1836: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad1836.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 77f459868579..685998dd086e 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -40,8 +40,8 @@ struct ad1836_priv { */ static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"}; -static const struct soc_enum ad1836_deemp_enum = - SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); +static SOC_ENUM_SINGLE_DECL(ad1836_deemp_enum, + AD1836_DAC_CTRL1, 8, ad1836_deemp); #define AD1836_DAC_VOLUME(x) \ SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \ -- cgit v1.2.3 From 52a5b545bc09ebc7b1e4a55d765ccb76286ca48d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:57:55 +0100 Subject: ASoC: cs42l73: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Acked-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l73.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 69c8e2de7d0e..06f429184821 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -278,13 +278,13 @@ static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1); static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" }; static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" }; -static const struct soc_enum pgaa_enum = - SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3, - ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text); +static SOC_ENUM_SINGLE_DECL(pgaa_enum, + CS42L73_ADCIPC, 3, + cs42l73_pgaa_text); -static const struct soc_enum pgab_enum = - SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7, - ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text); +static SOC_ENUM_SINGLE_DECL(pgab_enum, + CS42L73_ADCIPC, 7, + cs42l73_pgab_text); static const struct snd_kcontrol_new pgaa_mux = SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum); @@ -309,9 +309,9 @@ static const struct snd_kcontrol_new input_right_mixer[] = { static const char * const cs42l73_ng_delay_text[] = { "50ms", "100ms", "150ms", "200ms" }; -static const struct soc_enum ng_delay_enum = - SOC_ENUM_SINGLE(CS42L73_NGCAB, 0, - ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text); +static SOC_ENUM_SINGLE_DECL(ng_delay_enum, + CS42L73_NGCAB, 0, + cs42l73_ng_delay_text); static const char * const cs42l73_mono_mix_texts[] = { "Left", "Right", "Mono Mix"}; @@ -357,19 +357,19 @@ static const struct snd_kcontrol_new esl_xsp_mixer = static const char * const cs42l73_ip_swap_text[] = { "Stereo", "Mono A", "Mono B", "Swap A-B"}; -static const struct soc_enum ip_swap_enum = - SOC_ENUM_SINGLE(CS42L73_MIOPC, 6, - ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text); +static SOC_ENUM_SINGLE_DECL(ip_swap_enum, + CS42L73_MIOPC, 6, + cs42l73_ip_swap_text); static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"}; -static const struct soc_enum vsp_output_mux_enum = - SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5, - ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text); +static SOC_ENUM_SINGLE_DECL(vsp_output_mux_enum, + CS42L73_MIXERCTL, 5, + cs42l73_spo_mixer_text); -static const struct soc_enum xsp_output_mux_enum = - SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4, - ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text); +static SOC_ENUM_SINGLE_DECL(xsp_output_mux_enum, + CS42L73_MIXERCTL, 4, + cs42l73_spo_mixer_text); static const struct snd_kcontrol_new vsp_output_mux = SOC_DAPM_ENUM("Route", vsp_output_mux_enum); -- cgit v1.2.3 From 26d04ca8c46e3af510f0bbbe4d0b1aca8e18b393 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 11:00:13 +0100 Subject: ASoC: lm49453: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/lm49453.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index e19490cfb3a8..d6f391a0f37e 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -213,15 +213,13 @@ static const char *lm49453_adcl_mux_text[] = { "MIC1", "Aux_L" }; static const char *lm49453_adcr_mux_text[] = { "MIC2", "Aux_R" }; -static const struct soc_enum lm49453_adcl_enum = - SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 0, - ARRAY_SIZE(lm49453_adcl_mux_text), - lm49453_adcl_mux_text); - -static const struct soc_enum lm49453_adcr_enum = - SOC_ENUM_SINGLE(LM49453_P0_ANALOG_MIXER_ADC_REG, 1, - ARRAY_SIZE(lm49453_adcr_mux_text), - lm49453_adcr_mux_text); +static SOC_ENUM_SINGLE_DECL(lm49453_adcl_enum, + LM49453_P0_ANALOG_MIXER_ADC_REG, 0, + lm49453_adcl_mux_text); + +static SOC_ENUM_SINGLE_DECL(lm49453_adcr_enum, + LM49453_P0_ANALOG_MIXER_ADC_REG, 1, + lm49453_adcr_mux_text); static const struct snd_kcontrol_new lm49453_adcl_mux_control = SOC_DAPM_ENUM("ADC Left Mux", lm49453_adcl_enum); -- cgit v1.2.3 From d77c290af76637e87dc07df28536231ee5042c98 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 11:07:32 +0100 Subject: ASoC: tlv320dac33: Use SOC_ENUM_SINGLE_*_DECL() Just replace with the helper macros. No functional change at all. Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320dac33.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 4f358393d6d6..9ce849623a0a 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -478,9 +478,7 @@ static const char *dac33_fifo_mode_texts[] = { "Bypass", "Mode 1", "Mode 7" }; -static const struct soc_enum dac33_fifo_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts), - dac33_fifo_mode_texts); +static SOC_ENUM_SINGLE_EXT_DECL(dac33_fifo_mode_enum, dac33_fifo_mode_texts); /* L/R Line Output Gain */ static const char *lr_lineout_gain_texts[] = { @@ -488,15 +486,13 @@ static const char *lr_lineout_gain_texts[] = { "Line 0dB DAC 12dB", "Line 6dB DAC 18dB", }; -static const struct soc_enum l_lineout_gain_enum = - SOC_ENUM_SINGLE(DAC33_LDAC_PWR_CTRL, 0, - ARRAY_SIZE(lr_lineout_gain_texts), - lr_lineout_gain_texts); +static SOC_ENUM_SINGLE_DECL(l_lineout_gain_enum, + DAC33_LDAC_PWR_CTRL, 0, + lr_lineout_gain_texts); -static const struct soc_enum r_lineout_gain_enum = - SOC_ENUM_SINGLE(DAC33_RDAC_PWR_CTRL, 0, - ARRAY_SIZE(lr_lineout_gain_texts), - lr_lineout_gain_texts); +static SOC_ENUM_SINGLE_DECL(r_lineout_gain_enum, + DAC33_RDAC_PWR_CTRL, 0, + lr_lineout_gain_texts); /* * DACL/R digital volume control: @@ -534,18 +530,16 @@ static const struct snd_kcontrol_new dac33_dapm_abypassr_control = /* LOP L/R invert selection */ static const char *dac33_lr_lom_texts[] = {"DAC", "LOP"}; -static const struct soc_enum dac33_left_lom_enum = - SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 3, - ARRAY_SIZE(dac33_lr_lom_texts), - dac33_lr_lom_texts); +static SOC_ENUM_SINGLE_DECL(dac33_left_lom_enum, + DAC33_OUT_AMP_CTRL, 3, + dac33_lr_lom_texts); static const struct snd_kcontrol_new dac33_dapm_left_lom_control = SOC_DAPM_ENUM("Route", dac33_left_lom_enum); -static const struct soc_enum dac33_right_lom_enum = - SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 2, - ARRAY_SIZE(dac33_lr_lom_texts), - dac33_lr_lom_texts); +static SOC_ENUM_SINGLE_DECL(dac33_right_lom_enum, + DAC33_OUT_AMP_CTRL, 2, + dac33_lr_lom_texts); static const struct snd_kcontrol_new dac33_dapm_right_lom_control = SOC_DAPM_ENUM("Route", dac33_right_lom_enum); -- cgit v1.2.3 From daf152a21d361967bd9d2d7a976c125de842d589 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 11:49:02 +0100 Subject: ASoC: wm5102: Use ARRAY_SIZE() for SOC_VALUE_ENUM_SINGLE() ... to make clear the meaning of the argument. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index ebffe81daa1d..293dffcb1d2f 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -622,13 +622,16 @@ static const unsigned int wm5102_osr_val[] = { static const struct soc_enum wm5102_hpout_osr[] = { SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, - ARIZONA_OUT1_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT1_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm5102_osr_text), wm5102_osr_text, wm5102_osr_val), SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L, - ARIZONA_OUT2_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT2_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm5102_osr_text), wm5102_osr_text, wm5102_osr_val), SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, - ARIZONA_OUT3_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT3_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm5102_osr_text), wm5102_osr_text, wm5102_osr_val), }; -- cgit v1.2.3 From 347e5512642da44d15bf8b48ee0fe196b37a78f1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 11:49:56 +0100 Subject: ASoC: wm8997: Use ARRAY_SIZE() for SOC_VALUE_ENUM_SINGLE() ... to make clear the meaning of the argument. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8997.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 6107108228b6..4e6442ce9a2a 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -123,10 +123,12 @@ static const unsigned int wm8997_osr_val[] = { static const struct soc_enum wm8997_hpout_osr[] = { SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L, - ARIZONA_OUT1_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT1_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm8997_osr_text), wm8997_osr_text, wm8997_osr_val), SOC_VALUE_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L, - ARIZONA_OUT3_OSR_SHIFT, 0x7, 3, + ARIZONA_OUT3_OSR_SHIFT, 0x7, + ARRAY_SIZE(wm8997_osr_text), wm8997_osr_text, wm8997_osr_val), }; -- cgit v1.2.3 From 98b664e2ceddd40120e8cd2aa56f7eb9a51870cf Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 18:22:58 +0100 Subject: ASoC: tlv320aic32x4: Support for master clock Add support for a master clock passed through DT. The master clock of the codec is only active when the codec is in use. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tlv320aic32x4.txt | 4 ++++ sound/soc/codecs/tlv320aic32x4.c | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt index db0551088cc4..352be7b1f7e2 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -8,6 +8,8 @@ Required properties: Optional properties: - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt + - clocks/clock-names: Clock named 'mclk' for the master clock of the codec. + See clock/clock-bindings.txt for information about the detailed format. Example: @@ -15,4 +17,6 @@ Example: codec: tlv320aic32x4@18 { compatible = "ti,tlv320aic32x4"; reg = <0x18>; + clocks = <&clks 201>; + clock-names = "mclk"; }; diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 1dd50e48934c..643fa53beaab 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,7 @@ struct aic32x4_priv { u32 micpga_routing; bool swapdacs; int rstn_gpio; + struct clk *mclk; }; /* 0dB min, 0.5dB steps */ @@ -487,8 +489,18 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute) static int aic32x4_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); + int ret; + switch (level) { case SND_SOC_BIAS_ON: + /* Switch on master clock */ + ret = clk_prepare_enable(aic32x4->mclk); + if (ret) { + dev_err(codec->dev, "Failed to enable master clock\n"); + return ret; + } + /* Switch on PLL */ snd_soc_update_bits(codec, AIC32X4_PLLPR, AIC32X4_PLLEN, AIC32X4_PLLEN); @@ -539,6 +551,9 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, /* Switch off BCLK_N Divider */ snd_soc_update_bits(codec, AIC32X4_BCLKN, AIC32X4_BCLKEN, 0); + + /* Switch off master clock */ + clk_disable_unprepare(aic32x4->mclk); break; case SND_SOC_BIAS_OFF: break; @@ -717,6 +732,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->rstn_gpio = -1; } + aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk"); + if (IS_ERR(aic32x4->mclk)) { + dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); + return PTR_ERR(aic32x4->mclk); + } + if (gpio_is_valid(aic32x4->rstn_gpio)) { ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); -- cgit v1.2.3 From 239b669b2dedc46d5e6b07d87c3d1dedf8d9477c Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 18:22:59 +0100 Subject: ASoC: tlv320aic32x4: Support for regulators Support regulators to power up the codec. This patch also enables the AVDD LDO if no AV regulator was found. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tlv320aic32x4.txt | 8 ++ sound/soc/codecs/tlv320aic32x4.c | 126 ++++++++++++++++++++- 2 files changed, 133 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt index 352be7b1f7e2..5e2741af27be 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -5,6 +5,14 @@ The tlv320aic32x4 serial control bus communicates through I2C protocols Required properties: - compatible: Should be "ti,tlv320aic32x4" - reg: I2C slave address + - supply-*: Required supply regulators are: + "iov" - digital IO power supply + "ldoin" - LDO power supply + "dv" - Digital core power supply + "av" - Analog core power supply + If you supply ldoin, dv and av are optional. Otherwise they are required + See regulator/regulator.txt for more information about the detailed binding + format. Optional properties: - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 643fa53beaab..d69c61ffcda8 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,11 @@ struct aic32x4_priv { bool swapdacs; int rstn_gpio; struct clk *mclk; + + struct regulator *supply_ldo; + struct regulator *supply_iov; + struct regulator *supply_dv; + struct regulator *supply_av; }; /* 0dB min, 0.5dB steps */ @@ -695,6 +701,106 @@ static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, return 0; } +static void aic32x4_disable_regulators(struct aic32x4_priv *aic32x4) +{ + regulator_disable(aic32x4->supply_iov); + + if (!IS_ERR(aic32x4->supply_ldo)) + regulator_disable(aic32x4->supply_ldo); + + if (!IS_ERR(aic32x4->supply_dv)) + regulator_disable(aic32x4->supply_dv); + + if (!IS_ERR(aic32x4->supply_av)) + regulator_disable(aic32x4->supply_av); +} + +static int aic32x4_setup_regulators(struct device *dev, + struct aic32x4_priv *aic32x4) +{ + int ret = 0; + + aic32x4->supply_ldo = devm_regulator_get_optional(dev, "ldoin"); + aic32x4->supply_iov = devm_regulator_get(dev, "iov"); + aic32x4->supply_dv = devm_regulator_get_optional(dev, "dv"); + aic32x4->supply_av = devm_regulator_get_optional(dev, "av"); + + /* Check if the regulator requirements are fulfilled */ + + if (IS_ERR(aic32x4->supply_iov)) { + dev_err(dev, "Missing supply 'iov'\n"); + return PTR_ERR(aic32x4->supply_iov); + } + + if (IS_ERR(aic32x4->supply_ldo)) { + if (PTR_ERR(aic32x4->supply_ldo) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + if (IS_ERR(aic32x4->supply_dv)) { + dev_err(dev, "Missing supply 'dv' or 'ldoin'\n"); + return PTR_ERR(aic32x4->supply_dv); + } + if (IS_ERR(aic32x4->supply_av)) { + dev_err(dev, "Missing supply 'av' or 'ldoin'\n"); + return PTR_ERR(aic32x4->supply_av); + } + } else { + if (IS_ERR(aic32x4->supply_dv) && + PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (IS_ERR(aic32x4->supply_av) && + PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER) + return -EPROBE_DEFER; + } + + ret = regulator_enable(aic32x4->supply_iov); + if (ret) { + dev_err(dev, "Failed to enable regulator iov\n"); + return ret; + } + + if (!IS_ERR(aic32x4->supply_ldo)) { + ret = regulator_enable(aic32x4->supply_ldo); + if (ret) { + dev_err(dev, "Failed to enable regulator ldo\n"); + goto error_ldo; + } + } + + if (!IS_ERR(aic32x4->supply_dv)) { + ret = regulator_enable(aic32x4->supply_dv); + if (ret) { + dev_err(dev, "Failed to enable regulator dv\n"); + goto error_dv; + } + } + + if (!IS_ERR(aic32x4->supply_av)) { + ret = regulator_enable(aic32x4->supply_av); + if (ret) { + dev_err(dev, "Failed to enable regulator av\n"); + goto error_av; + } + } + + if (!IS_ERR(aic32x4->supply_ldo) && IS_ERR(aic32x4->supply_av)) + aic32x4->power_cfg |= AIC32X4_PWR_AIC32X4_LDO_ENABLE; + + return 0; + +error_av: + if (!IS_ERR(aic32x4->supply_dv)) + regulator_disable(aic32x4->supply_dv); + +error_dv: + if (!IS_ERR(aic32x4->supply_ldo)) + regulator_disable(aic32x4->supply_ldo); + +error_ldo: + regulator_disable(aic32x4->supply_iov); + return ret; +} + static int aic32x4_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -745,13 +851,31 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, return ret; } + ret = aic32x4_setup_regulators(&i2c->dev, aic32x4); + if (ret) { + dev_err(&i2c->dev, "Failed to setup regulators\n"); + return ret; + } + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_aic32x4, &aic32x4_dai, 1); - return ret; + if (ret) { + dev_err(&i2c->dev, "Failed to register codec\n"); + aic32x4_disable_regulators(aic32x4); + return ret; + } + + i2c_set_clientdata(i2c, aic32x4); + + return 0; } static int aic32x4_i2c_remove(struct i2c_client *client) { + struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client); + + aic32x4_disable_regulators(aic32x4); + snd_soc_unregister_codec(&client->dev); return 0; } -- cgit v1.2.3 From 3154cc7404506700ff270b6f123ec9c734f002fd Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 18:23:00 +0100 Subject: ASoC: tlv320aic32x4: Rearrange clock tree shutdown Rearrange clock tree shutdown to disable them in the reversed order of startup. First disable all dividers, then PLL followed by master clock. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index d69c61ffcda8..c6bd7e75352d 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -534,29 +534,29 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: - /* Switch off PLL */ - snd_soc_update_bits(codec, AIC32X4_PLLPR, - AIC32X4_PLLEN, 0); - - /* Switch off NDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_NDAC, - AIC32X4_NDACEN, 0); + /* Switch off BCLK_N Divider */ + snd_soc_update_bits(codec, AIC32X4_BCLKN, + AIC32X4_BCLKEN, 0); - /* Switch off MDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_MDAC, - AIC32X4_MDACEN, 0); + /* Switch off MADC Divider */ + snd_soc_update_bits(codec, AIC32X4_MADC, + AIC32X4_MADCEN, 0); /* Switch off NADC Divider */ snd_soc_update_bits(codec, AIC32X4_NADC, AIC32X4_NADCEN, 0); - /* Switch off MADC Divider */ - snd_soc_update_bits(codec, AIC32X4_MADC, - AIC32X4_MADCEN, 0); + /* Switch off MDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_MDAC, + AIC32X4_MDACEN, 0); - /* Switch off BCLK_N Divider */ - snd_soc_update_bits(codec, AIC32X4_BCLKN, - AIC32X4_BCLKEN, 0); + /* Switch off NDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_NDAC, + AIC32X4_NDACEN, 0); + + /* Switch off PLL */ + snd_soc_update_bits(codec, AIC32X4_PLLPR, + AIC32X4_PLLEN, 0); /* Switch off master clock */ clk_disable_unprepare(aic32x4->mclk); -- cgit v1.2.3 From 56b2f349137bfdd23e498f12a97fe3d6139c097b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 20 Feb 2014 09:06:30 +0900 Subject: ASoC: io: Remove SND_SOC_I2C Now that all users have been converted to regmap we can eliminate the ASoC level wrapper for I2C I/O reducing the amount of duplicated functionality. Signed-off-by: Mark Brown --- include/sound/soc.h | 1 - sound/soc/soc-io.c | 7 ------- 2 files changed, 8 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 6197ba0642cc..6d0b6cb9c484 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -341,7 +341,6 @@ typedef int (*hw_write_t)(void *,const char* ,int); extern struct snd_ac97_bus_ops *soc_ac97_ops; enum snd_soc_control_type { - SND_SOC_I2C = 1, SND_SOC_REGMAP, }; diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index 3a0d99edf030..add99e2f7996 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -99,13 +99,6 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, config.val_bits = data_bits; switch (control) { -#if IS_ENABLED(CONFIG_REGMAP_I2C) - case SND_SOC_I2C: - codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev), - &config); - break; -#endif - case SND_SOC_REGMAP: /* Device has made its own regmap arrangements */ codec->using_regmap = true; -- cgit v1.2.3 From 89c6785715592a6b082b3f9f28c27bb14b041c7d Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 14 Feb 2014 09:34:35 +0800 Subject: ASoC: core: add TDM slot parsing from DT supports For some CPU/CODEC DAI devices the TDM slot infomation maybe needed. This patch adds the slot parsing from DT supports. TDM slot properties: dai-tdm-slot-num : Number of slots in use. dai-tdm-slot-width : Width in bits for each slot. For instance: dai-tdm-slot-num = <2>; dai-tdm-slot-width = <8>; And for each spcified driver, there could be one .of_xlate_tdm_slot_mask() to specify a explicit mapping of the channels and the slots. If it's absent the default snd_soc_of_xlate_tdm_slot_mask() will be used to generating the tx and rx masks. For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit for an active slot as default, and the default active bits are at the LSB of the masks. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ include/sound/soc.h | 3 +++ sound/soc/soc-core.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) (limited to 'sound/soc') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 71f27c403194..d86e0fc41e80 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -142,6 +142,8 @@ struct snd_soc_dai_ops { * Called by soc_card drivers, normally in their hw_params. */ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); + int (*of_xlate_tdm_slot_mask)(unsigned int slots, + unsigned int *tx_mask, unsigned int *rx_mask); int (*set_tdm_slot)(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); diff --git a/include/sound/soc.h b/include/sound/soc.h index 465dc6e0674d..2a878d03c147 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1175,6 +1175,9 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width); int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0540cb08e0ea..5b7d3ba87c7a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3608,6 +3608,30 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); +/** + * snd_soc_of_xlate_tdm_slot - generate tx/rx slot mask. + * @slots: Number of slots in use. + * @tx_mask: bitmask representing active TX slots. + * @rx_mask: bitmask representing active RX slots. + * + * Generates the TDM tx and rx slot default masks for DAI. + */ +static int snd_soc_of_xlate_tdm_slot_mask(unsigned int slots, + unsigned int *tx_mask, + unsigned int *rx_mask) +{ + if (*tx_mask || *rx_mask) + return 0; + + if (!slots) + return -EINVAL; + + *tx_mask = (1 << slots) - 1; + *rx_mask = (1 << slots) - 1; + + return 0; +} + /** * snd_soc_dai_set_tdm_slot - configure DAI TDM. * @dai: DAI @@ -3622,6 +3646,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { + if (dai->driver && dai->driver->ops->of_xlate_tdm_slot_mask) + dai->driver->ops->of_xlate_tdm_slot_mask(slots, + &tx_mask, &rx_mask); + else + snd_soc_of_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + if (dai->driver && dai->driver->ops->set_tdm_slot) return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); @@ -4504,6 +4534,35 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); +int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width) +{ + u32 val; + int ret; + + if (of_property_read_bool(np, "dai-tdm-slot-num")) { + ret = of_property_read_u32(np, "dai-tdm-slot-num", &val); + if (ret) + return ret; + + if (slots) + *slots = val; + } + + if (of_property_read_bool(np, "dai-tdm-slot-width")) { + ret = of_property_read_u32(np, "dai-tdm-slot-width", &val); + if (ret) + return ret; + + if (slot_width) + *slot_width = val; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); + int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname) { -- cgit v1.2.3 From 6ff62eedce4f7756b092d276165d8e11edab9f28 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 14 Feb 2014 09:34:36 +0800 Subject: ASoC: simple-card: add slot information parsing supports For some CPU/CODEC DAI devices the slot information maybe needed. This patch adds the slot information parsing for simple-card driver. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/simple-card.txt | 5 +++++ include/sound/simple_card.h | 2 ++ sound/soc/generic/simple-card.c | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index 05273583490c..b30c222f9cd3 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -18,6 +18,8 @@ Optional properties: Each entry is a pair of strings, the first being the connection's sink, the second being the connection's source. +- dai-tdm-slot-num : Please refer to tdm-slot.txt. +- dai-tdm-slot-width : Please refer to tdm-slot.txt. Required subnodes: @@ -56,6 +58,9 @@ sound { "Headphone Jack", "HP_OUT", "External Speaker", "LINE_OUT"; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <8>; + simple-audio-card,cpu { sound-dai = <&sh_fsi2 0>; }; diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h index e1ac996c8feb..9b0ac77177b6 100644 --- a/include/sound/simple_card.h +++ b/include/sound/simple_card.h @@ -18,6 +18,8 @@ struct asoc_simple_dai { const char *name; unsigned int fmt; unsigned int sysclk; + int slots; + int slot_width; }; struct asoc_simple_card_info { diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 4fe8abc6e216..bdd176ddff07 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -9,11 +9,14 @@ * published by the Free Software Foundation. */ #include +#include #include #include #include #include #include +#include +#include struct simple_card_data { struct snd_soc_card snd_card; @@ -44,6 +47,16 @@ static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, } } + if (set->slots) { + ret = snd_soc_dai_set_tdm_slot(dai, 0, 0, + set->slots, + set->slot_width); + if (ret && ret != -ENOTSUPP) { + dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); + goto err; + } + } + ret = 0; err: @@ -94,6 +107,11 @@ asoc_simple_card_sub_parse_of(struct device_node *np, if (ret < 0) goto parse_error; + /* parse TDM slot */ + ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); + if (ret) + goto parse_error; + /* * bitclock-inversion, frame-inversion * bitclock-master, frame-master -- cgit v1.2.3 From cb29d7b9ef7faf95e27d90362a5e7694c5479093 Mon Sep 17 00:00:00 2001 From: xiangxiao Date: Sun, 23 Feb 2014 14:40:44 +0800 Subject: ASoC: add data field into snd_soc_jack_gpio so callback could get the context data as needed Signed-off-by: xiangxiao Signed-off-by: Mark Brown --- include/sound/soc.h | 3 ++- sound/soc/soc-jack.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a001472b96a..266c188cc36f 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -600,7 +600,8 @@ struct snd_soc_jack_gpio { struct snd_soc_jack *jack; struct delayed_work work; - int (*jack_status_check)(void); + void *data; + int (*jack_status_check)(void *data); }; struct snd_soc_jack { diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 23d43dac91da..720060286d19 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -250,7 +250,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) report = 0; if (gpio->jack_status_check) - report = gpio->jack_status_check(); + report = gpio->jack_status_check(gpio->data); snd_soc_jack_report(jack, report, gpio->report); } -- cgit v1.2.3 From f1adf5be51a952d06760d8b38c55e209bbf7054e Mon Sep 17 00:00:00 2001 From: xiangxiao Date: Sun, 23 Feb 2014 14:44:52 +0800 Subject: ASoC: delay the initial jack detect by debounce_time so the hardware could get time to initialize and debounce Signed-off-by: xiangxiao Signed-off-by: Mark Brown --- sound/soc/soc-jack.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 720060286d19..b903f822d1b2 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -342,7 +342,8 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, gpio_export(gpios[i].gpio, false); /* Update initial jack status */ - snd_soc_jack_gpio_detect(&gpios[i]); + schedule_delayed_work(&gpios[i].work, + msecs_to_jiffies(gpios[i].debounce_time)); } return 0; -- cgit v1.2.3 From eeecf1a3f9f4791371bf35035ab9b95ab6aab5e7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 24 Feb 2014 11:38:11 +0900 Subject: ASoC: da732x: Remove leftover cache size setting The da732x driver no longer uses the ASoC level register cache but the cache size setting had been left in the driver by mistake. Remove it. Signed-off-by: Mark Brown --- sound/soc/codecs/da732x.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 3219fa1f3cf5..05f07fb49860 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1538,7 +1538,6 @@ static struct snd_soc_codec_driver soc_codec_dev_da732x = { .dapm_routes = da732x_dapm_routes, .num_dapm_routes = ARRAY_SIZE(da732x_dapm_routes), .set_pll = da732x_set_dai_pll, - .reg_cache_size = ARRAY_SIZE(da732x_reg_cache), }; static int da732x_i2c_probe(struct i2c_client *i2c, -- cgit v1.2.3 From ea9f8535a46d3753649b6e28f47e3109ca63284a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 24 Feb 2014 00:20:43 -0300 Subject: ASoC: fsl: imx-pcm-fiq: Remove unneeded 'out' label Instead of jumping to the 'out' label, just return the error code immediately. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-fiq.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c index 6553202dd48c..7abf6a079574 100644 --- a/sound/soc/fsl/imx-pcm-fiq.c +++ b/sound/soc/fsl/imx-pcm-fiq.c @@ -270,18 +270,17 @@ static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) ret = imx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); if (ret) - goto out; + return ret; } if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { ret = imx_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); if (ret) - goto out; + return ret; } -out: - return ret; + return 0; } static int ssi_irq = 0; -- cgit v1.2.3 From 30812cca63600a3e4b44b93ed2ec7e00ce572ee0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:34:45 +0100 Subject: ASoC: da732x: Use da732x->regmap instead of codec->control_data With the ongoing component-ization of the ASoC framework and the continuing migration to using regmap for IO the control_data field of the snd_soc_codec struct will eventually be removed. Prepare the da732x driver for this by using da732x->regmap instead of accessing the CODEC's control_data field. Signed-off-by: Lars-Peter Clausen Acked-by: Adam Thomson Signed-off-by: Mark Brown --- sound/soc/codecs/da732x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 05f07fb49860..cf9b15472c85 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1471,8 +1471,8 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, da732x_hp_dc_offset_cancellation(codec); - regcache_cache_only(codec->control_data, false); - regcache_sync(codec->control_data); + regcache_cache_only(da732x->regmap, false); + regcache_sync(da732x->regmap); } else { snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_BOOST_MASK, @@ -1483,7 +1483,7 @@ static int da732x_set_bias_level(struct snd_soc_codec *codec, } break; case SND_SOC_BIAS_OFF: - regcache_cache_only(codec->control_data, true); + regcache_cache_only(da732x->regmap, true); da732x_set_charge_pump(codec, DA732X_DISABLE_CP); snd_soc_update_bits(codec, DA732X_REG_BIAS_EN, DA732X_BIAS_EN, DA732X_BIAS_DIS); -- cgit v1.2.3 From 180c275eb8a65c919d09af49179b99e4c01a3d1e Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Sat, 22 Feb 2014 16:00:16 +0100 Subject: ASoC: wm8993: Remove unused pointer in wm8993_remove() Commit 88b5bdfd (ASoC: wm8993: drop regulator_bulk_free of devm_ allocated data) eliminated the last user of driver data pointer 'wm8993' in function wm8993_remove() - Thus remove it. Detected by Coverity: CID 1186208. Signed-off-by: Christian Engelmayer Signed-off-by: Mark Brown --- sound/soc/codecs/wm8993.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 1c12f2c9418a..7b0630a076fa 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1559,8 +1559,6 @@ static int wm8993_probe(struct snd_soc_codec *codec) static int wm8993_remove(struct snd_soc_codec *codec) { - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -- cgit v1.2.3 From b7c1b73097b48a7922d1320d5a8c8315ff4fae71 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:32:04 +0100 Subject: ASoC: wm8996: Replace codec->control_data with wm8996->regmap With the ongoing component-ization of the ASoC framework and the continuing migration to using regmap for IO the control_data field of the snd_soc_codec struct will eventually be removed. Prepare the wm8996 driver for this by using wm8996->regmap instead of accessing the CODEC's control_data field. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 92bb02185c46..36a52b9e97e7 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -1608,8 +1608,8 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, msleep(5); } - regcache_cache_only(codec->control_data, false); - regcache_sync(codec->control_data); + regcache_cache_only(wm8996->regmap, false); + regcache_sync(wm8996->regmap); } /* Bypass the MICBIASes for lowest power */ @@ -1620,10 +1620,10 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: - regcache_cache_only(codec->control_data, true); + regcache_cache_only(wm8996->regmap, true); if (wm8996->pdata.ldo_ena >= 0) { gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); - regcache_cache_only(codec->control_data, true); + regcache_cache_only(wm8996->regmap, true); } regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); -- cgit v1.2.3 From d7f31d3c898e3e621a34d5d64966f7b830df66f1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:32:05 +0100 Subject: ASoC: wm8962: Replace codec->control_data with wm8962->regmap With the ongoing component-ization of the ASoC framework and the continuing migration to using regmap for IO the control_data field of the snd_soc_codec struct will eventually be removed. Prepare the wm8962 driver for this by using wm8962->regmap instead of accessing the CODEC's control_data field. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 3924ee243745..6ff1ff83b4dd 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1479,7 +1479,9 @@ static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) { - return regcache_sync_region(codec->control_data, + struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + + return regcache_sync_region(wm8962->regmap, WM8962_HDBASS_AI_1, WM8962_MAX_REGISTER); } -- cgit v1.2.3 From 6ef20de726bd68b68a925cc63f12e0ed655c6b56 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 24 Feb 2014 17:26:56 +0200 Subject: ASoC: Intel: Add Baytrail SST ID and Baytrail specific register bits While the SHIM register addresses in Baytrail are the same than Haswell and Broadwell their register size is 64-bit and some bits are different. This patch adds the SST device ID for Baytrail and Baytrail specific SHIM bit definitions. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-dsp.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h index 608418c1181a..74052b59485c 100644 --- a/sound/soc/intel/sst-dsp.h +++ b/sound/soc/intel/sst-dsp.h @@ -24,6 +24,7 @@ /* SST Device IDs */ #define SST_DEV_ID_LYNX_POINT 0x33C8 #define SST_DEV_ID_WILDCAT_POINT 0x3438 +#define SST_DEV_ID_BYT 0x0F28 /* Supported SST DMA Devices */ #define SST_DMA_TYPE_DW 1 @@ -72,10 +73,15 @@ #define SST_CSR_S0IOCS (0x1 << 21) #define SST_CSR_S1IOCS (0x1 << 23) #define SST_CSR_LPCS (0x1 << 31) +#define SST_BYT_CSR_RST (0x1 << 0) +#define SST_BYT_CSR_VECTOR_SEL (0x1 << 1) +#define SST_BYT_CSR_STALL (0x1 << 2) +#define SST_BYT_CSR_PWAITMODE (0x1 << 3) /* ISRX / ISC */ #define SST_ISRX_BUSY (0x1 << 1) #define SST_ISRX_DONE (0x1 << 0) +#define SST_BYT_ISRX_REQUEST (0x1 << 1) /* ISRD / ISD */ #define SST_ISRD_BUSY (0x1 << 1) @@ -84,14 +90,19 @@ /* IMRX / IMC */ #define SST_IMRX_BUSY (0x1 << 1) #define SST_IMRX_DONE (0x1 << 0) +#define SST_BYT_IMRX_REQUEST (0x1 << 1) /* IPCX / IPCC */ #define SST_IPCX_DONE (0x1 << 30) #define SST_IPCX_BUSY (0x1 << 31) +#define SST_BYT_IPCX_DONE ((u64)0x1 << 62) +#define SST_BYT_IPCX_BUSY ((u64)0x1 << 63) /* IPCD */ #define SST_IPCD_DONE (0x1 << 30) #define SST_IPCD_BUSY (0x1 << 31) +#define SST_BYT_IPCD_DONE ((u64)0x1 << 62) +#define SST_BYT_IPCD_BUSY ((u64)0x1 << 63) /* CLKCTL */ #define SST_CLKCTL_SMOS(x) (x << 24) -- cgit v1.2.3 From f746966377d08aea60a1f21a6387855409524b9b Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 24 Feb 2014 17:26:57 +0200 Subject: ASoC: Intel: Add Intel Baytrail SST DSP support This adds basic functionality for Baytrail SST DSP initialization and firmware loading. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-baytrail-dsp.c | 372 +++++++++++++++++++++++++++++++++++++ sound/soc/intel/sst-dsp-priv.h | 1 + 2 files changed, 373 insertions(+) create mode 100644 sound/soc/intel/sst-baytrail-dsp.c (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-baytrail-dsp.c b/sound/soc/intel/sst-baytrail-dsp.c new file mode 100644 index 000000000000..a50bf7fc0e3a --- /dev/null +++ b/sound/soc/intel/sst-baytrail-dsp.c @@ -0,0 +1,372 @@ +/* + * Intel Baytrail SST DSP driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sst-dsp.h" +#include "sst-dsp-priv.h" +#include "sst-baytrail-ipc.h" + +#define SST_BYT_FW_SIGNATURE_SIZE 4 +#define SST_BYT_FW_SIGN "$SST" + +#define SST_BYT_IRAM_OFFSET 0xC0000 +#define SST_BYT_DRAM_OFFSET 0x100000 +#define SST_BYT_SHIM_OFFSET 0x140000 + +enum sst_ram_type { + SST_BYT_IRAM = 1, + SST_BYT_DRAM = 2, + SST_BYT_CACHE = 3, +}; + +struct dma_block_info { + enum sst_ram_type type; /* IRAM/DRAM */ + u32 size; /* Bytes */ + u32 ram_offset; /* Offset in I/DRAM */ + u32 rsvd; /* Reserved field */ +}; + +struct fw_header { + unsigned char signature[SST_BYT_FW_SIGNATURE_SIZE]; + u32 file_size; /* size of fw minus this header */ + u32 modules; /* # of modules */ + u32 file_format; /* version of header format */ + u32 reserved[4]; +}; + +struct sst_byt_fw_module_header { + unsigned char signature[SST_BYT_FW_SIGNATURE_SIZE]; + u32 mod_size; /* size of module */ + u32 blocks; /* # of blocks */ + u32 type; /* codec type, pp lib */ + u32 entry_point; +}; + +static int sst_byt_parse_module(struct sst_dsp *dsp, struct sst_fw *fw, + struct sst_byt_fw_module_header *module) +{ + struct dma_block_info *block; + struct sst_module *mod; + struct sst_module_data block_data; + struct sst_module_template template; + int count; + + memset(&template, 0, sizeof(template)); + template.id = module->type; + template.entry = module->entry_point; + template.p.type = SST_MEM_DRAM; + template.p.data_type = SST_DATA_P; + template.s.type = SST_MEM_DRAM; + template.s.data_type = SST_DATA_S; + + mod = sst_module_new(fw, &template, NULL); + if (mod == NULL) + return -ENOMEM; + + block = (void *)module + sizeof(*module); + + for (count = 0; count < module->blocks; count++) { + + if (block->size <= 0) { + dev_err(dsp->dev, "block %d size invalid\n", count); + return -EINVAL; + } + + switch (block->type) { + case SST_BYT_IRAM: + block_data.offset = block->ram_offset + + dsp->addr.iram_offset; + block_data.type = SST_MEM_IRAM; + break; + case SST_BYT_DRAM: + block_data.offset = block->ram_offset + + dsp->addr.dram_offset; + block_data.type = SST_MEM_DRAM; + break; + case SST_BYT_CACHE: + block_data.offset = block->ram_offset + + (dsp->addr.fw_ext - dsp->addr.lpe); + block_data.type = SST_MEM_CACHE; + break; + default: + dev_err(dsp->dev, "wrong ram type 0x%x in block0x%x\n", + block->type, count); + return -EINVAL; + } + + block_data.size = block->size; + block_data.data_type = SST_DATA_M; + block_data.data = (void *)block + sizeof(*block); + + sst_module_insert_fixed_block(mod, &block_data); + + block = (void *)block + sizeof(*block) + block->size; + } + return 0; +} + +static int sst_byt_parse_fw_image(struct sst_fw *sst_fw) +{ + struct fw_header *header; + struct sst_byt_fw_module_header *module; + struct sst_dsp *dsp = sst_fw->dsp; + int ret, count; + + /* Read the header information from the data pointer */ + header = (struct fw_header *)sst_fw->dma_buf; + + /* verify FW */ + if ((strncmp(header->signature, SST_BYT_FW_SIGN, 4) != 0) || + (sst_fw->size != header->file_size + sizeof(*header))) { + /* Invalid FW signature */ + dev_err(dsp->dev, "Invalid FW sign/filesize mismatch\n"); + return -EINVAL; + } + + dev_dbg(dsp->dev, + "header sign=%4s size=0x%x modules=0x%x fmt=0x%x size=%zu\n", + header->signature, header->file_size, header->modules, + header->file_format, sizeof(*header)); + + module = (void *)sst_fw->dma_buf + sizeof(*header); + for (count = 0; count < header->modules; count++) { + /* module */ + ret = sst_byt_parse_module(dsp, sst_fw, module); + if (ret < 0) { + dev_err(dsp->dev, "invalid module %d\n", count); + return ret; + } + module = (void *)module + sizeof(*module) + module->mod_size; + } + + return 0; +} + +static void sst_byt_dump_shim(struct sst_dsp *sst) +{ + int i; + u64 reg; + + for (i = 0; i <= 0xF0; i += 8) { + reg = sst_dsp_shim_read64_unlocked(sst, i); + if (reg) + dev_dbg(sst->dev, "shim 0x%2.2x value 0x%16.16llx\n", + i, reg); + } + + for (i = 0x00; i <= 0xff; i += 4) { + reg = readl(sst->addr.pci_cfg + i); + if (reg) + dev_dbg(sst->dev, "pci 0x%2.2x value 0x%8.8x\n", + i, (u32)reg); + } +} + +static irqreturn_t sst_byt_irq(int irq, void *context) +{ + struct sst_dsp *sst = (struct sst_dsp *) context; + u64 isrx; + irqreturn_t ret = IRQ_NONE; + + spin_lock(&sst->spinlock); + + isrx = sst_dsp_shim_read64_unlocked(sst, SST_ISRX); + if (isrx & SST_ISRX_DONE) { + /* ADSP has processed the message request from IA */ + sst_dsp_shim_update_bits64_unlocked(sst, SST_IPCX, + SST_BYT_IPCX_DONE, 0); + ret = IRQ_WAKE_THREAD; + } + if (isrx & SST_BYT_ISRX_REQUEST) { + /* mask message request from ADSP and do processing later */ + sst_dsp_shim_update_bits64_unlocked(sst, SST_IMRX, + SST_BYT_IMRX_REQUEST, + SST_BYT_IMRX_REQUEST); + ret = IRQ_WAKE_THREAD; + } + + spin_unlock(&sst->spinlock); + + return ret; +} + +static void sst_byt_boot(struct sst_dsp *sst) +{ + int tries = 10; + + /* release stall and wait to unstall */ + sst_dsp_shim_update_bits64(sst, SST_CSR, SST_BYT_CSR_STALL, 0x0); + while (tries--) { + if (!(sst_dsp_shim_read64(sst, SST_CSR) & + SST_BYT_CSR_PWAITMODE)) + break; + msleep(100); + } + if (tries < 0) { + dev_err(sst->dev, "unable to start DSP\n"); + sst_byt_dump_shim(sst); + } +} + +static void sst_byt_reset(struct sst_dsp *sst) +{ + /* put DSP into reset, set reset vector and stall */ + sst_dsp_shim_update_bits64(sst, SST_CSR, + SST_BYT_CSR_RST | SST_BYT_CSR_VECTOR_SEL | SST_BYT_CSR_STALL, + SST_BYT_CSR_RST | SST_BYT_CSR_VECTOR_SEL | SST_BYT_CSR_STALL); + + udelay(10); + + /* take DSP out of reset and keep stalled for FW loading */ + sst_dsp_shim_update_bits64(sst, SST_CSR, SST_BYT_CSR_RST, 0); +} + +struct sst_adsp_memregion { + u32 start; + u32 end; + int blocks; + enum sst_mem_type type; +}; + +/* BYT test stuff */ +static const struct sst_adsp_memregion byt_region[] = { + {0xC0000, 0x100000, 8, SST_MEM_IRAM}, /* I-SRAM - 8 * 32kB */ + {0x100000, 0x140000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */ +}; + +static int sst_byt_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata) +{ + sst->addr.lpe_base = pdata->lpe_base; + sst->addr.lpe = ioremap(pdata->lpe_base, pdata->lpe_size); + if (!sst->addr.lpe) + return -ENODEV; + + /* ADSP PCI MMIO config space */ + sst->addr.pci_cfg = ioremap(pdata->pcicfg_base, pdata->pcicfg_size); + if (!sst->addr.pci_cfg) { + iounmap(sst->addr.lpe); + return -ENODEV; + } + + /* SST Extended FW allocation */ + sst->addr.fw_ext = ioremap(pdata->fw_base, pdata->fw_size); + if (!sst->addr.fw_ext) { + iounmap(sst->addr.pci_cfg); + iounmap(sst->addr.lpe); + return -ENODEV; + } + + /* SST Shim */ + sst->addr.shim = sst->addr.lpe + sst->addr.shim_offset; + + sst_dsp_mailbox_init(sst, SST_BYT_MAILBOX_OFFSET + 0x204, + SST_BYT_IPC_MAX_PAYLOAD_SIZE, + SST_BYT_MAILBOX_OFFSET, + SST_BYT_IPC_MAX_PAYLOAD_SIZE); + + sst->irq = pdata->irq; + + return 0; +} + +static int sst_byt_init(struct sst_dsp *sst, struct sst_pdata *pdata) +{ + const struct sst_adsp_memregion *region; + struct device *dev; + int ret = -ENODEV, i, j, region_count; + u32 offset, size; + + dev = sst->dev; + + switch (sst->id) { + case SST_DEV_ID_BYT: + region = byt_region; + region_count = ARRAY_SIZE(byt_region); + sst->addr.iram_offset = SST_BYT_IRAM_OFFSET; + sst->addr.dram_offset = SST_BYT_DRAM_OFFSET; + sst->addr.shim_offset = SST_BYT_SHIM_OFFSET; + break; + default: + dev_err(dev, "failed to get mem resources\n"); + return ret; + } + + ret = sst_byt_resource_map(sst, pdata); + if (ret < 0) { + dev_err(dev, "failed to map resources\n"); + return ret; + } + + /* + * save the physical address of extended firmware block in the first + * 4 bytes of the mailbox + */ + memcpy_toio(sst->addr.lpe + SST_BYT_MAILBOX_OFFSET, + &pdata->fw_base, sizeof(u32)); + + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + /* enable Interrupt from both sides */ + sst_dsp_shim_update_bits64(sst, SST_IMRX, 0x3, 0x0); + sst_dsp_shim_update_bits64(sst, SST_IMRD, 0x3, 0x0); + + /* register DSP memory blocks - ideally we should get this from ACPI */ + for (i = 0; i < region_count; i++) { + offset = region[i].start; + size = (region[i].end - region[i].start) / region[i].blocks; + + /* register individual memory blocks */ + for (j = 0; j < region[i].blocks; j++) { + sst_mem_block_register(sst, offset, size, + region[i].type, NULL, j, sst); + offset += size; + } + } + + return 0; +} + +static void sst_byt_free(struct sst_dsp *sst) +{ + sst_mem_block_unregister_all(sst); + iounmap(sst->addr.lpe); + iounmap(sst->addr.pci_cfg); + iounmap(sst->addr.fw_ext); +} + +struct sst_ops sst_byt_ops = { + .reset = sst_byt_reset, + .boot = sst_byt_boot, + .write = sst_shim32_write, + .read = sst_shim32_read, + .write64 = sst_shim32_write64, + .read64 = sst_shim32_read64, + .ram_read = sst_memcpy_fromio_32, + .ram_write = sst_memcpy_toio_32, + .irq_handler = sst_byt_irq, + .init = sst_byt_init, + .free = sst_byt_free, + .parse_fw = sst_byt_parse_fw_image, +}; diff --git a/sound/soc/intel/sst-dsp-priv.h b/sound/soc/intel/sst-dsp-priv.h index fa2c780c888b..fe8e81aad646 100644 --- a/sound/soc/intel/sst-dsp-priv.h +++ b/sound/soc/intel/sst-dsp-priv.h @@ -66,6 +66,7 @@ struct sst_addr { u32 lpe_base; u32 shim_offset; u32 iram_offset; + u32 dram_offset; void __iomem *lpe; void __iomem *shim; void __iomem *pci_cfg; -- cgit v1.2.3 From f7d01fd6754c1a257af46ec465d946132c7d004d Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 24 Feb 2014 17:26:58 +0200 Subject: ASoC: Intel: Add Intel Baytrail SST DSP IPC support Add support for Baytrail SST DSP IPC. This provides mechanism to communicate with the DSP firmware. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-baytrail-ipc.c | 866 +++++++++++++++++++++++++++++++++++++ sound/soc/intel/sst-baytrail-ipc.h | 69 +++ 2 files changed, 935 insertions(+) create mode 100644 sound/soc/intel/sst-baytrail-ipc.c create mode 100644 sound/soc/intel/sst-baytrail-ipc.h (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c new file mode 100644 index 000000000000..8c91a68b90bc --- /dev/null +++ b/sound/soc/intel/sst-baytrail-ipc.c @@ -0,0 +1,866 @@ +/* + * Intel Baytrail SST IPC Support + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sst-baytrail-ipc.h" +#include "sst-dsp.h" +#include "sst-dsp-priv.h" + +/* IPC message timeout */ +#define IPC_TIMEOUT_MSECS 300 +#define IPC_BOOT_MSECS 200 + +#define IPC_EMPTY_LIST_SIZE 8 + +/* IPC header bits */ +#define IPC_HEADER_MSG_ID_MASK 0xff +#define IPC_HEADER_MSG_ID(x) ((x) & IPC_HEADER_MSG_ID_MASK) +#define IPC_HEADER_STR_ID_SHIFT 8 +#define IPC_HEADER_STR_ID_MASK 0x1f +#define IPC_HEADER_STR_ID(x) (((x) & 0x1f) << IPC_HEADER_STR_ID_SHIFT) +#define IPC_HEADER_LARGE_SHIFT 13 +#define IPC_HEADER_LARGE(x) (((x) & 0x1) << IPC_HEADER_LARGE_SHIFT) +#define IPC_HEADER_DATA_SHIFT 16 +#define IPC_HEADER_DATA_MASK 0x3fff +#define IPC_HEADER_DATA(x) (((x) & 0x3fff) << IPC_HEADER_DATA_SHIFT) + +/* mask for differentiating between notification and reply message */ +#define IPC_NOTIFICATION (0x1 << 7) + +/* I2L Stream config/control msgs */ +#define IPC_IA_ALLOC_STREAM 0x20 +#define IPC_IA_FREE_STREAM 0x21 +#define IPC_IA_PAUSE_STREAM 0x24 +#define IPC_IA_RESUME_STREAM 0x25 +#define IPC_IA_DROP_STREAM 0x26 +#define IPC_IA_START_STREAM 0x30 + +/* notification messages */ +#define IPC_IA_FW_INIT_CMPLT 0x81 +#define IPC_SST_PERIOD_ELAPSED 0x97 + +/* IPC messages between host and ADSP */ +struct sst_byt_address_info { + u32 addr; + u32 size; +} __packed; + +struct sst_byt_str_type { + u8 codec_type; + u8 str_type; + u8 operation; + u8 protected_str; + u8 time_slots; + u8 reserved; + u16 result; +} __packed; + +struct sst_byt_pcm_params { + u8 num_chan; + u8 pcm_wd_sz; + u8 use_offload_path; + u8 reserved; + u32 sfreq; + u8 channel_map[8]; +} __packed; + +struct sst_byt_frames_info { + u16 num_entries; + u16 rsrvd; + u32 frag_size; + struct sst_byt_address_info ring_buf_info[8]; +} __packed; + +struct sst_byt_alloc_params { + struct sst_byt_str_type str_type; + struct sst_byt_pcm_params pcm_params; + struct sst_byt_frames_info frame_info; +} __packed; + +struct sst_byt_alloc_response { + struct sst_byt_str_type str_type; + u8 reserved[88]; +} __packed; + +struct sst_byt_start_stream_params { + u32 byte_offset; +} __packed; + +struct sst_byt_tstamp { + u64 ring_buffer_counter; + u64 hardware_counter; + u64 frames_decoded; + u64 bytes_decoded; + u64 bytes_copied; + u32 sampling_frequency; + u32 channel_peak[8]; +} __packed; + +/* driver internal IPC message structure */ +struct ipc_message { + struct list_head list; + u64 header; + + /* direction wrt host CPU */ + char tx_data[SST_BYT_IPC_MAX_PAYLOAD_SIZE]; + size_t tx_size; + char rx_data[SST_BYT_IPC_MAX_PAYLOAD_SIZE]; + size_t rx_size; + + wait_queue_head_t waitq; + bool complete; + bool wait; + int errno; +}; + +struct sst_byt_stream; +struct sst_byt; + +/* stream infomation */ +struct sst_byt_stream { + struct list_head node; + + /* configuration */ + struct sst_byt_alloc_params request; + struct sst_byt_alloc_response reply; + + /* runtime info */ + struct sst_byt *byt; + int str_id; + bool commited; + bool running; + + /* driver callback */ + u32 (*notify_position)(struct sst_byt_stream *stream, void *data); + void *pdata; +}; + +/* SST Baytrail IPC data */ +struct sst_byt { + struct device *dev; + struct sst_dsp *dsp; + + /* stream */ + struct list_head stream_list; + + /* boot */ + wait_queue_head_t boot_wait; + bool boot_complete; + + /* IPC messaging */ + struct list_head tx_list; + struct list_head rx_list; + struct list_head empty_list; + wait_queue_head_t wait_txq; + struct task_struct *tx_thread; + struct kthread_worker kworker; + struct kthread_work kwork; + struct ipc_message *msg; +}; + +static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id) +{ + u64 header; + + header = IPC_HEADER_MSG_ID(msg_id) | + IPC_HEADER_STR_ID(str_id) | + IPC_HEADER_LARGE(large) | + IPC_HEADER_DATA(data) | + SST_BYT_IPCX_BUSY; + + return header; +} + +static inline u16 sst_byt_header_msg_id(u64 header) +{ + return header & IPC_HEADER_MSG_ID_MASK; +} + +static inline u8 sst_byt_header_str_id(u64 header) +{ + return (header >> IPC_HEADER_STR_ID_SHIFT) & IPC_HEADER_STR_ID_MASK; +} + +static inline u16 sst_byt_header_data(u64 header) +{ + return (header >> IPC_HEADER_DATA_SHIFT) & IPC_HEADER_DATA_MASK; +} + +static struct sst_byt_stream *sst_byt_get_stream(struct sst_byt *byt, + int stream_id) +{ + struct sst_byt_stream *stream; + + list_for_each_entry(stream, &byt->stream_list, node) { + if (stream->str_id == stream_id) + return stream; + } + + return NULL; +} + +static void sst_byt_ipc_shim_dbg(struct sst_byt *byt, const char *text) +{ + struct sst_dsp *sst = byt->dsp; + u64 isr, ipcd, imrx, ipcx; + + ipcx = sst_dsp_shim_read64_unlocked(sst, SST_IPCX); + isr = sst_dsp_shim_read64_unlocked(sst, SST_ISRX); + ipcd = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); + imrx = sst_dsp_shim_read64_unlocked(sst, SST_IMRX); + + dev_err(byt->dev, + "ipc: --%s-- ipcx 0x%llx isr 0x%llx ipcd 0x%llx imrx 0x%llx\n", + text, ipcx, isr, ipcd, imrx); +} + +/* locks held by caller */ +static struct ipc_message *sst_byt_msg_get_empty(struct sst_byt *byt) +{ + struct ipc_message *msg = NULL; + + if (!list_empty(&byt->empty_list)) { + msg = list_first_entry(&byt->empty_list, + struct ipc_message, list); + list_del(&msg->list); + } + + return msg; +} + +static void sst_byt_ipc_tx_msgs(struct kthread_work *work) +{ + struct sst_byt *byt = + container_of(work, struct sst_byt, kwork); + struct ipc_message *msg; + u64 ipcx; + unsigned long flags; + + spin_lock_irqsave(&byt->dsp->spinlock, flags); + if (list_empty(&byt->tx_list)) { + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); + return; + } + + /* if the DSP is busy we will TX messages after IRQ */ + ipcx = sst_dsp_shim_read64_unlocked(byt->dsp, SST_IPCX); + if (ipcx & SST_BYT_IPCX_BUSY) { + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); + return; + } + + msg = list_first_entry(&byt->tx_list, struct ipc_message, list); + + list_move(&msg->list, &byt->rx_list); + + /* send the message */ + if (msg->header & IPC_HEADER_LARGE(true)) + sst_dsp_outbox_write(byt->dsp, msg->tx_data, msg->tx_size); + sst_dsp_shim_write64_unlocked(byt->dsp, SST_IPCX, msg->header); + + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); +} + +static inline void sst_byt_tx_msg_reply_complete(struct sst_byt *byt, + struct ipc_message *msg) +{ + msg->complete = true; + + if (!msg->wait) + list_add_tail(&msg->list, &byt->empty_list); + else + wake_up(&msg->waitq); +} + +static int sst_byt_tx_wait_done(struct sst_byt *byt, struct ipc_message *msg, + void *rx_data) +{ + unsigned long flags; + int ret; + + /* wait for DSP completion */ + ret = wait_event_timeout(msg->waitq, msg->complete, + msecs_to_jiffies(IPC_TIMEOUT_MSECS)); + + spin_lock_irqsave(&byt->dsp->spinlock, flags); + if (ret == 0) { + list_del(&msg->list); + sst_byt_ipc_shim_dbg(byt, "message timeout"); + + ret = -ETIMEDOUT; + } else { + + /* copy the data returned from DSP */ + if (msg->rx_size) + memcpy(rx_data, msg->rx_data, msg->rx_size); + ret = msg->errno; + } + + list_add_tail(&msg->list, &byt->empty_list); + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); + return ret; +} + +static int sst_byt_ipc_tx_message(struct sst_byt *byt, u64 header, + void *tx_data, size_t tx_bytes, + void *rx_data, size_t rx_bytes, int wait) +{ + unsigned long flags; + struct ipc_message *msg; + + spin_lock_irqsave(&byt->dsp->spinlock, flags); + + msg = sst_byt_msg_get_empty(byt); + if (msg == NULL) { + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); + return -EBUSY; + } + + msg->header = header; + msg->tx_size = tx_bytes; + msg->rx_size = rx_bytes; + msg->wait = wait; + msg->errno = 0; + msg->complete = false; + + if (tx_bytes) { + /* msg content = lower 32-bit of the header + data */ + *(u32 *)msg->tx_data = (u32)(header & (u32)-1); + memcpy(msg->tx_data + sizeof(u32), tx_data, tx_bytes); + msg->tx_size += sizeof(u32); + } + + list_add_tail(&msg->list, &byt->tx_list); + spin_unlock_irqrestore(&byt->dsp->spinlock, flags); + + queue_kthread_work(&byt->kworker, &byt->kwork); + + if (wait) + return sst_byt_tx_wait_done(byt, msg, rx_data); + else + return 0; +} + +static inline int sst_byt_ipc_tx_msg_wait(struct sst_byt *byt, u64 header, + void *tx_data, size_t tx_bytes, + void *rx_data, size_t rx_bytes) +{ + return sst_byt_ipc_tx_message(byt, header, tx_data, tx_bytes, + rx_data, rx_bytes, 1); +} + +static inline int sst_byt_ipc_tx_msg_nowait(struct sst_byt *byt, u64 header, + void *tx_data, size_t tx_bytes) +{ + return sst_byt_ipc_tx_message(byt, header, tx_data, tx_bytes, + NULL, 0, 0); +} + +static struct ipc_message *sst_byt_reply_find_msg(struct sst_byt *byt, + u64 header) +{ + struct ipc_message *msg = NULL, *_msg; + u64 mask; + + /* match reply to message sent based on msg and stream IDs */ + mask = IPC_HEADER_MSG_ID_MASK | + IPC_HEADER_STR_ID_MASK << IPC_HEADER_STR_ID_SHIFT; + header &= mask; + + if (list_empty(&byt->rx_list)) { + dev_err(byt->dev, + "ipc: rx list is empty but received 0x%llx\n", header); + goto out; + } + + list_for_each_entry(_msg, &byt->rx_list, list) { + if ((_msg->header & mask) == header) { + msg = _msg; + break; + } + } + +out: + return msg; +} + +static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg) +{ + struct sst_byt_stream *stream; + u64 header = msg->header; + u8 stream_id = sst_byt_header_str_id(header); + u8 stream_msg = sst_byt_header_msg_id(header); + + stream = sst_byt_get_stream(byt, stream_id); + if (stream == NULL) + return; + + switch (stream_msg) { + case IPC_IA_DROP_STREAM: + case IPC_IA_PAUSE_STREAM: + case IPC_IA_FREE_STREAM: + stream->running = false; + break; + case IPC_IA_START_STREAM: + case IPC_IA_RESUME_STREAM: + stream->running = true; + break; + } +} + +static int sst_byt_process_reply(struct sst_byt *byt, u64 header) +{ + struct ipc_message *msg; + + msg = sst_byt_reply_find_msg(byt, header); + if (msg == NULL) + return 1; + + if (header & IPC_HEADER_LARGE(true)) { + msg->rx_size = sst_byt_header_data(header); + sst_dsp_inbox_read(byt->dsp, msg->rx_data, msg->rx_size); + } + + /* update any stream states */ + sst_byt_stream_update(byt, msg); + + list_del(&msg->list); + /* wake up */ + sst_byt_tx_msg_reply_complete(byt, msg); + + return 1; +} + +static void sst_byt_fw_ready(struct sst_byt *byt, u64 header) +{ + dev_dbg(byt->dev, "ipc: DSP is ready 0x%llX\n", header); + + byt->boot_complete = true; + wake_up(&byt->boot_wait); +} + +static int sst_byt_process_notification(struct sst_byt *byt, + unsigned long *flags) +{ + struct sst_dsp *sst = byt->dsp; + struct sst_byt_stream *stream; + u64 header; + u8 msg_id, stream_id; + int handled = 1; + + header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); + msg_id = sst_byt_header_msg_id(header); + + switch (msg_id) { + case IPC_SST_PERIOD_ELAPSED: + stream_id = sst_byt_header_str_id(header); + stream = sst_byt_get_stream(byt, stream_id); + if (stream && stream->running && stream->notify_position) { + spin_unlock_irqrestore(&sst->spinlock, *flags); + stream->notify_position(stream, stream->pdata); + spin_lock_irqsave(&sst->spinlock, *flags); + } + break; + case IPC_IA_FW_INIT_CMPLT: + sst_byt_fw_ready(byt, header); + break; + } + + return handled; +} + +static irqreturn_t sst_byt_irq_thread(int irq, void *context) +{ + struct sst_dsp *sst = (struct sst_dsp *) context; + struct sst_byt *byt = sst_dsp_get_thread_context(sst); + u64 header; + unsigned long flags; + + spin_lock_irqsave(&sst->spinlock, flags); + + header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD); + if (header & SST_BYT_IPCD_BUSY) { + if (header & IPC_NOTIFICATION) { + /* message from ADSP */ + sst_byt_process_notification(byt, &flags); + } else { + /* reply from ADSP */ + sst_byt_process_reply(byt, header); + } + /* + * clear IPCD BUSY bit and set DONE bit. Tell DSP we have + * processed the message and can accept new. Clear data part + * of the header + */ + sst_dsp_shim_update_bits64_unlocked(sst, SST_IPCD, + SST_BYT_IPCD_DONE | SST_BYT_IPCD_BUSY | + IPC_HEADER_DATA(IPC_HEADER_DATA_MASK), + SST_BYT_IPCD_DONE); + /* unmask message request interrupts */ + sst_dsp_shim_update_bits64_unlocked(sst, SST_IMRX, + SST_BYT_IMRX_REQUEST, 0); + } + + spin_unlock_irqrestore(&sst->spinlock, flags); + + /* continue to send any remaining messages... */ + queue_kthread_work(&byt->kworker, &byt->kwork); + + return IRQ_HANDLED; +} + +/* stream API */ +struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id, + u32 (*notify_position)(struct sst_byt_stream *stream, void *data), + void *data) +{ + struct sst_byt_stream *stream; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (stream == NULL) + return NULL; + + list_add(&stream->node, &byt->stream_list); + stream->notify_position = notify_position; + stream->pdata = data; + stream->byt = byt; + stream->str_id = id; + + return stream; +} + +int sst_byt_stream_set_bits(struct sst_byt *byt, struct sst_byt_stream *stream, + int bits) +{ + stream->request.pcm_params.pcm_wd_sz = bits; + return 0; +} + +int sst_byt_stream_set_channels(struct sst_byt *byt, + struct sst_byt_stream *stream, u8 channels) +{ + stream->request.pcm_params.num_chan = channels; + return 0; +} + +int sst_byt_stream_set_rate(struct sst_byt *byt, struct sst_byt_stream *stream, + unsigned int rate) +{ + stream->request.pcm_params.sfreq = rate; + return 0; +} + +/* stream sonfiguration */ +int sst_byt_stream_type(struct sst_byt *byt, struct sst_byt_stream *stream, + int codec_type, int stream_type, int operation) +{ + stream->request.str_type.codec_type = codec_type; + stream->request.str_type.str_type = stream_type; + stream->request.str_type.operation = operation; + stream->request.str_type.time_slots = 0xc; + + return 0; +} + +int sst_byt_stream_buffer(struct sst_byt *byt, struct sst_byt_stream *stream, + uint32_t buffer_addr, uint32_t buffer_size) +{ + stream->request.frame_info.num_entries = 1; + stream->request.frame_info.ring_buf_info[0].addr = buffer_addr; + stream->request.frame_info.ring_buf_info[0].size = buffer_size; + /* calculate bytes per 4 ms fragment */ + stream->request.frame_info.frag_size = + stream->request.pcm_params.sfreq * + stream->request.pcm_params.num_chan * + stream->request.pcm_params.pcm_wd_sz / 8 * + 4 / 1000; + return 0; +} + +int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + struct sst_byt_alloc_params *str_req = &stream->request; + struct sst_byt_alloc_response *reply = &stream->reply; + u64 header; + int ret; + + header = sst_byt_header(IPC_IA_ALLOC_STREAM, + sizeof(*str_req) + sizeof(u32), + true, stream->str_id); + ret = sst_byt_ipc_tx_msg_wait(byt, header, str_req, sizeof(*str_req), + reply, sizeof(*reply)); + if (ret < 0) { + dev_err(byt->dev, "ipc: error stream commit failed\n"); + return ret; + } + + stream->commited = true; + + return 0; +} + +int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + u64 header; + int ret = 0; + + if (!stream->commited) + goto out; + + header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id); + ret = sst_byt_ipc_tx_msg_wait(byt, header, NULL, 0, NULL, 0); + if (ret < 0) { + dev_err(byt->dev, "ipc: free stream %d failed\n", + stream->str_id); + return -EAGAIN; + } + + stream->commited = false; +out: + list_del(&stream->node); + kfree(stream); + + return ret; +} + +static int sst_byt_stream_operations(struct sst_byt *byt, int type, + int stream_id, int wait) +{ + struct sst_byt_start_stream_params start_stream; + u64 header; + void *tx_msg = NULL; + size_t size = 0; + + if (type != IPC_IA_START_STREAM) { + header = sst_byt_header(type, 0, false, stream_id); + } else { + start_stream.byte_offset = 0; + header = sst_byt_header(IPC_IA_START_STREAM, + sizeof(start_stream) + sizeof(u32), + true, stream_id); + tx_msg = &start_stream; + size = sizeof(start_stream); + } + + if (wait) + return sst_byt_ipc_tx_msg_wait(byt, header, + tx_msg, size, NULL, 0); + else + return sst_byt_ipc_tx_msg_nowait(byt, header, tx_msg, size); +} + +/* stream ALSA trigger operations */ +int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + int ret; + + ret = sst_byt_stream_operations(byt, IPC_IA_START_STREAM, + stream->str_id, 0); + if (ret < 0) + dev_err(byt->dev, "ipc: error failed to start stream %d\n", + stream->str_id); + + return ret; +} + +int sst_byt_stream_stop(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + int ret; + + /* don't stop streams that are not commited */ + if (!stream->commited) + return 0; + + ret = sst_byt_stream_operations(byt, IPC_IA_DROP_STREAM, + stream->str_id, 0); + if (ret < 0) + dev_err(byt->dev, "ipc: error failed to stop stream %d\n", + stream->str_id); + return ret; +} + +int sst_byt_stream_pause(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + int ret; + + ret = sst_byt_stream_operations(byt, IPC_IA_PAUSE_STREAM, + stream->str_id, 0); + if (ret < 0) + dev_err(byt->dev, "ipc: error failed to pause stream %d\n", + stream->str_id); + + return ret; +} + +int sst_byt_stream_resume(struct sst_byt *byt, struct sst_byt_stream *stream) +{ + int ret; + + ret = sst_byt_stream_operations(byt, IPC_IA_RESUME_STREAM, + stream->str_id, 0); + if (ret < 0) + dev_err(byt->dev, "ipc: error failed to resume stream %d\n", + stream->str_id); + + return ret; +} + +int sst_byt_get_dsp_position(struct sst_byt *byt, + struct sst_byt_stream *stream, int buffer_size) +{ + struct sst_dsp *sst = byt->dsp; + struct sst_byt_tstamp fw_tstamp; + u8 str_id = stream->str_id; + u32 tstamp_offset; + + tstamp_offset = SST_BYT_TIMESTAMP_OFFSET + str_id * sizeof(fw_tstamp); + memcpy_fromio(&fw_tstamp, + sst->addr.lpe + tstamp_offset, sizeof(fw_tstamp)); + + return do_div(fw_tstamp.ring_buffer_counter, buffer_size); +} + +static int msg_empty_list_init(struct sst_byt *byt) +{ + struct ipc_message *msg; + int i; + + byt->msg = kzalloc(sizeof(*msg) * IPC_EMPTY_LIST_SIZE, GFP_KERNEL); + if (byt->msg == NULL) + return -ENOMEM; + + for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { + init_waitqueue_head(&byt->msg[i].waitq); + list_add(&byt->msg[i].list, &byt->empty_list); + } + + return 0; +} + +struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt) +{ + return byt->dsp; +} + +static struct sst_dsp_device byt_dev = { + .thread = sst_byt_irq_thread, + .ops = &sst_byt_ops, +}; + +int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_byt *byt; + struct sst_fw *byt_sst_fw; + int err; + + dev_dbg(dev, "initialising Byt DSP IPC\n"); + + byt = devm_kzalloc(dev, sizeof(*byt), GFP_KERNEL); + if (byt == NULL) + return -ENOMEM; + + byt->dev = dev; + INIT_LIST_HEAD(&byt->stream_list); + INIT_LIST_HEAD(&byt->tx_list); + INIT_LIST_HEAD(&byt->rx_list); + INIT_LIST_HEAD(&byt->empty_list); + init_waitqueue_head(&byt->boot_wait); + init_waitqueue_head(&byt->wait_txq); + + err = msg_empty_list_init(byt); + if (err < 0) + goto list_err; + + /* start the IPC message thread */ + init_kthread_worker(&byt->kworker); + byt->tx_thread = kthread_run(kthread_worker_fn, + &byt->kworker, + dev_name(byt->dev)); + if (IS_ERR(byt->tx_thread)) { + err = PTR_ERR(byt->tx_thread); + dev_err(byt->dev, "error failed to create message TX task\n"); + goto list_err; + } + init_kthread_work(&byt->kwork, sst_byt_ipc_tx_msgs); + + byt_dev.thread_context = byt; + + /* init SST shim */ + byt->dsp = sst_dsp_new(dev, &byt_dev, pdata); + if (byt->dsp == NULL) { + err = -ENODEV; + goto list_err; + } + + /* keep the DSP in reset state for base FW loading */ + sst_dsp_reset(byt->dsp); + + byt_sst_fw = sst_fw_new(byt->dsp, pdata->fw, byt); + if (byt_sst_fw == NULL) { + err = -ENODEV; + dev_err(dev, "error: failed to load firmware\n"); + goto fw_err; + } + + /* wait for DSP boot completion */ + sst_dsp_boot(byt->dsp); + err = wait_event_timeout(byt->boot_wait, byt->boot_complete, + msecs_to_jiffies(IPC_BOOT_MSECS)); + if (err == 0) { + err = -EIO; + dev_err(byt->dev, "ipc: error DSP boot timeout\n"); + goto boot_err; + } + + pdata->dsp = byt; + + return 0; + +boot_err: + sst_dsp_reset(byt->dsp); + sst_fw_free(byt_sst_fw); +fw_err: + sst_dsp_free(byt->dsp); + kfree(byt->msg); +list_err: + kfree(byt); + return err; +} +EXPORT_SYMBOL_GPL(sst_byt_dsp_init); + +void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata) +{ + struct sst_byt *byt = pdata->dsp; + + sst_dsp_reset(byt->dsp); + sst_fw_free_all(byt->dsp); + sst_dsp_free(byt->dsp); + kfree(byt->msg); +} +EXPORT_SYMBOL_GPL(sst_byt_dsp_free); diff --git a/sound/soc/intel/sst-baytrail-ipc.h b/sound/soc/intel/sst-baytrail-ipc.h new file mode 100644 index 000000000000..f172b6440fa9 --- /dev/null +++ b/sound/soc/intel/sst-baytrail-ipc.h @@ -0,0 +1,69 @@ +/* + * Intel Baytrail SST IPC Support + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 __SST_BYT_IPC_H +#define __SST_BYT_IPC_H + +#include + +struct sst_byt; +struct sst_byt_stream; +struct sst_pdata; +extern struct sst_ops sst_byt_ops; + + +#define SST_BYT_MAILBOX_OFFSET 0x144000 +#define SST_BYT_TIMESTAMP_OFFSET (SST_BYT_MAILBOX_OFFSET + 0x800) + +/** + * Upfront defined maximum message size that is + * expected by the in/out communication pipes in FW. + */ +#define SST_BYT_IPC_MAX_PAYLOAD_SIZE 200 + +/* stream API */ +struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id, + uint32_t (*get_write_position)(struct sst_byt_stream *stream, + void *data), + void *data); + +/* stream configuration */ +int sst_byt_stream_set_bits(struct sst_byt *byt, struct sst_byt_stream *stream, + int bits); +int sst_byt_stream_set_channels(struct sst_byt *byt, + struct sst_byt_stream *stream, u8 channels); +int sst_byt_stream_set_rate(struct sst_byt *byt, struct sst_byt_stream *stream, + unsigned int rate); +int sst_byt_stream_type(struct sst_byt *byt, struct sst_byt_stream *stream, + int codec_type, int stream_type, int operation); +int sst_byt_stream_buffer(struct sst_byt *byt, struct sst_byt_stream *stream, + uint32_t buffer_addr, uint32_t buffer_size); +int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream); +int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream); + +/* stream ALSA trigger operations */ +int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream); +int sst_byt_stream_stop(struct sst_byt *byt, struct sst_byt_stream *stream); +int sst_byt_stream_pause(struct sst_byt *byt, struct sst_byt_stream *stream); +int sst_byt_stream_resume(struct sst_byt *byt, struct sst_byt_stream *stream); + +int sst_byt_get_dsp_position(struct sst_byt *byt, + struct sst_byt_stream *stream, int buffer_size); + +/* init */ +int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata); +void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata); +struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt); + +#endif -- cgit v1.2.3 From aef1311a7d7e77408611cdf143d32bb1709527b6 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 24 Feb 2014 17:26:59 +0200 Subject: ASoC: Intel: Add Intel Baytrail SST PCM platform driver This adds the Baytrail SST DSP PCM platform driver. It registers itself with the ALSA SoC layer and uses Intel Baytrail SST DSP IPC for DSP control. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-baytrail-pcm.c | 422 +++++++++++++++++++++++++++++++++++++ 1 file changed, 422 insertions(+) create mode 100644 sound/soc/intel/sst-baytrail-pcm.c (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-baytrail-pcm.c b/sound/soc/intel/sst-baytrail-pcm.c new file mode 100644 index 000000000000..6d101f3813b4 --- /dev/null +++ b/sound/soc/intel/sst-baytrail-pcm.c @@ -0,0 +1,422 @@ +/* + * Intel Baytrail SST PCM Support + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sst-baytrail-ipc.h" +#include "sst-dsp-priv.h" +#include "sst-dsp.h" + +#define BYT_PCM_COUNT 2 + +static const struct snd_pcm_hardware sst_byt_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FORMAT_S24_LE, + .period_bytes_min = 384, + .period_bytes_max = 48000, + .periods_min = 2, + .periods_max = 250, + .buffer_bytes_max = 96000, +}; + +/* private data for each PCM DSP stream */ +struct sst_byt_pcm_data { + struct sst_byt_stream *stream; + struct snd_pcm_substream *substream; + struct mutex mutex; +}; + +/* private data for the driver */ +struct sst_byt_priv_data { + /* runtime DSP */ + struct sst_byt *byt; + + /* DAI data */ + struct sst_byt_pcm_data pcm[BYT_PCM_COUNT]; +}; + +/* this may get called several times by oss emulation */ +static int sst_byt_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sst_byt_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_byt *byt = pdata->byt; + u32 rate, bits; + u8 channels; + int ret, playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + + dev_dbg(rtd->dev, "PCM: hw_params, pcm_data %p\n", pcm_data); + + ret = sst_byt_stream_type(byt, pcm_data->stream, + 1, 1, !playback); + if (ret < 0) { + dev_err(rtd->dev, "failed to set stream format %d\n", ret); + return ret; + } + + rate = params_rate(params); + ret = sst_byt_stream_set_rate(byt, pcm_data->stream, rate); + if (ret < 0) { + dev_err(rtd->dev, "could not set rate %d\n", rate); + return ret; + } + + bits = snd_pcm_format_width(params_format(params)); + ret = sst_byt_stream_set_bits(byt, pcm_data->stream, bits); + if (ret < 0) { + dev_err(rtd->dev, "could not set formats %d\n", + params_rate(params)); + return ret; + } + + channels = (u8)(params_channels(params) & 0xF); + ret = sst_byt_stream_set_channels(byt, pcm_data->stream, channels); + if (ret < 0) { + dev_err(rtd->dev, "could not set channels %d\n", + params_rate(params)); + return ret; + } + + snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); + + ret = sst_byt_stream_buffer(byt, pcm_data->stream, + substream->dma_buffer.addr, + params_buffer_bytes(params)); + if (ret < 0) { + dev_err(rtd->dev, "PCM: failed to set DMA buffer %d\n", ret); + return ret; + } + + ret = sst_byt_stream_commit(byt, pcm_data->stream); + if (ret < 0) { + dev_err(rtd->dev, "PCM: failed stream commit %d\n", ret); + return ret; + } + + return 0; +} + +static int sst_byt_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + dev_dbg(rtd->dev, "PCM: hw_free\n"); + snd_pcm_lib_free_pages(substream); + + return 0; +} + +static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sst_byt_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_byt *byt = pdata->byt; + + dev_dbg(rtd->dev, "PCM: trigger %d\n", cmd); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + sst_byt_stream_start(byt, pcm_data->stream); + break; + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + sst_byt_stream_resume(byt, pcm_data->stream); + break; + case SNDRV_PCM_TRIGGER_STOP: + sst_byt_stream_stop(byt, pcm_data->stream); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + sst_byt_stream_pause(byt, pcm_data->stream); + break; + default: + break; + } + + return 0; +} + +static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data) +{ + struct sst_byt_pcm_data *pcm_data = data; + struct snd_pcm_substream *substream = pcm_data->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + u32 pos; + + pos = frames_to_bytes(runtime, + (runtime->control->appl_ptr % + runtime->buffer_size)); + + dev_dbg(rtd->dev, "PCM: App pointer %d bytes\n", pos); + + snd_pcm_period_elapsed(substream); + return pos; +} + +static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct sst_byt_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_byt *byt = pdata->byt; + snd_pcm_uframes_t offset; + int pos; + + pos = sst_byt_get_dsp_position(byt, pcm_data->stream, + snd_pcm_lib_buffer_bytes(substream)); + offset = bytes_to_frames(runtime, pos); + + dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n", + frames_to_bytes(runtime, (u32)offset)); + return offset; +} + +static int sst_byt_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sst_byt_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_byt *byt = pdata->byt; + + dev_dbg(rtd->dev, "PCM: open\n"); + + pcm_data = &pdata->pcm[rtd->cpu_dai->id]; + mutex_lock(&pcm_data->mutex); + + snd_soc_pcm_set_drvdata(rtd, pcm_data); + pcm_data->substream = substream; + + snd_soc_set_runtime_hwparams(substream, &sst_byt_pcm_hardware); + + pcm_data->stream = sst_byt_stream_new(byt, rtd->cpu_dai->id + 1, + byt_notify_pointer, pcm_data); + if (pcm_data->stream == NULL) { + dev_err(rtd->dev, "failed to create stream\n"); + mutex_unlock(&pcm_data->mutex); + return -EINVAL; + } + + mutex_unlock(&pcm_data->mutex); + return 0; +} + +static int sst_byt_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sst_byt_priv_data *pdata = + snd_soc_platform_get_drvdata(rtd->platform); + struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd); + struct sst_byt *byt = pdata->byt; + int ret; + + dev_dbg(rtd->dev, "PCM: close\n"); + + mutex_lock(&pcm_data->mutex); + ret = sst_byt_stream_free(byt, pcm_data->stream); + if (ret < 0) { + dev_dbg(rtd->dev, "Free stream fail\n"); + goto out; + } + pcm_data->stream = NULL; + +out: + mutex_unlock(&pcm_data->mutex); + return ret; +} + +static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + + dev_dbg(rtd->dev, "PCM: mmap\n"); + return snd_pcm_lib_default_mmap(substream, vma); +} + +static struct snd_pcm_ops sst_byt_pcm_ops = { + .open = sst_byt_pcm_open, + .close = sst_byt_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = sst_byt_pcm_hw_params, + .hw_free = sst_byt_pcm_hw_free, + .trigger = sst_byt_pcm_trigger, + .pointer = sst_byt_pcm_pointer, + .mmap = sst_byt_pcm_mmap, +}; + +static void sst_byt_pcm_free(struct snd_pcm *pcm) +{ + snd_pcm_lib_preallocate_free_for_all(pcm); +} + +static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm; + size_t size; + int ret = 0; + + ret = dma_coerce_mask_and_coherent(rtd->card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || + pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + size = sst_byt_pcm_hardware.buffer_bytes_max; + ret = snd_pcm_lib_preallocate_pages_for_all(pcm, + SNDRV_DMA_TYPE_DEV, + rtd->card->dev, + size, size); + if (ret) { + dev_err(rtd->dev, "dma buffer allocation failed %d\n", + ret); + return ret; + } + } + + return ret; +} + +static struct snd_soc_dai_driver byt_dais[] = { + { + .name = "Front-cpu-dai", + .playback = { + .stream_name = "System Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S16_LE, + }, + }, + { + .name = "Mic1-cpu-dai", + .capture = { + .stream_name = "Analog Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, +}; + +static int sst_byt_pcm_probe(struct snd_soc_platform *platform) +{ + struct sst_pdata *plat_data = dev_get_platdata(platform->dev); + struct sst_byt_priv_data *priv_data; + int i; + + if (!plat_data) + return -ENODEV; + + priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data), + GFP_KERNEL); + priv_data->byt = plat_data->dsp; + snd_soc_platform_set_drvdata(platform, priv_data); + + for (i = 0; i < ARRAY_SIZE(byt_dais); i++) + mutex_init(&priv_data->pcm[i].mutex); + + return 0; +} + +static int sst_byt_pcm_remove(struct snd_soc_platform *platform) +{ + return 0; +} + +static struct snd_soc_platform_driver byt_soc_platform = { + .probe = sst_byt_pcm_probe, + .remove = sst_byt_pcm_remove, + .ops = &sst_byt_pcm_ops, + .pcm_new = sst_byt_pcm_new, + .pcm_free = sst_byt_pcm_free, +}; + +static const struct snd_soc_component_driver byt_dai_component = { + .name = "byt-dai", +}; + +static int sst_byt_pcm_dev_probe(struct platform_device *pdev) +{ + struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); + int ret; + + ret = sst_byt_dsp_init(&pdev->dev, sst_pdata); + if (ret < 0) + return -ENODEV; + + ret = snd_soc_register_platform(&pdev->dev, &byt_soc_platform); + if (ret < 0) + goto err_plat; + + ret = snd_soc_register_component(&pdev->dev, &byt_dai_component, + byt_dais, ARRAY_SIZE(byt_dais)); + if (ret < 0) + goto err_comp; + + return 0; + +err_comp: + snd_soc_unregister_platform(&pdev->dev); +err_plat: + sst_byt_dsp_free(&pdev->dev, sst_pdata); + return ret; +} + +static int sst_byt_pcm_dev_remove(struct platform_device *pdev) +{ + struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev); + + snd_soc_unregister_platform(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); + sst_byt_dsp_free(&pdev->dev, sst_pdata); + + return 0; +} + +static struct platform_driver sst_byt_pcm_driver = { + .driver = { + .name = "baytrail-pcm-audio", + .owner = THIS_MODULE, + }, + + .probe = sst_byt_pcm_dev_probe, + .remove = sst_byt_pcm_dev_remove, +}; +module_platform_driver(sst_byt_pcm_driver); + +MODULE_AUTHOR("Jarkko Nikula"); +MODULE_DESCRIPTION("Baytrail PCM"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:baytrail-pcm-audio"); -- cgit v1.2.3 From 6439c8ad1edcca1051936de9f624c5ab9ebe03f7 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 24 Feb 2014 17:27:00 +0200 Subject: ASoC: Intel: Add machine driver for Baytrail SST with RT5640 codec Add machine driver for Baytrail SST DSP platform with RT5640 audio codec. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/byt-rt5640.c | 194 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 sound/soc/intel/byt-rt5640.c (limited to 'sound/soc') diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c new file mode 100644 index 000000000000..038547b48b2d --- /dev/null +++ b/sound/soc/intel/byt-rt5640.c @@ -0,0 +1,194 @@ +/* + * Intel Baytrail SST RT5640 machine driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../codecs/rt5640.h" + +#include "sst-dsp.h" + +static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), +}; + +static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { + {"IN2P", NULL, "Headset Mic"}, + {"IN2N", NULL, "Headset Mic"}, + {"DMIC1", NULL, "Int Mic"}, + {"Headphone", NULL, "HPOL"}, + {"Headphone", NULL, "HPOR"}, + {"Ext Spk", NULL, "SPOLP"}, + {"Ext Spk", NULL, "SPOLN"}, + {"Ext Spk", NULL, "SPORP"}, + {"Ext Spk", NULL, "SPORN"}, +}; + +static const struct snd_kcontrol_new byt_rt5640_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Int Mic"), + SOC_DAPM_PIN_SWITCH("Ext Spk"), +}; + +static int byt_rt5640_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + unsigned int fmt; + int ret; + + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS; + + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + dev_err(codec_dai->dev, + "can't set codec DAI configuration %d\n", ret); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, + params_rate(params) * 256, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "can't set codec clock %d\n", ret); + return ret; + } + ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1, + params_rate(params) * 64, + params_rate(params) * 256); + if (ret < 0) { + dev_err(codec_dai->dev, "can't set codec pll: %d\n", ret); + return ret; + } + return 0; +} + +static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) +{ + int ret; + struct snd_soc_codec *codec = runtime->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_card *card = runtime->card; + + card->dapm.idle_bias_off = true; + + ret = snd_soc_add_card_controls(card, byt_rt5640_controls, + ARRAY_SIZE(byt_rt5640_controls)); + if (ret) { + dev_err(card->dev, "unable to add card controls\n"); + return ret; + } + + snd_soc_dapm_ignore_suspend(dapm, "HPOL"); + snd_soc_dapm_ignore_suspend(dapm, "HPOR"); + + snd_soc_dapm_ignore_suspend(dapm, "SPOLP"); + snd_soc_dapm_ignore_suspend(dapm, "SPOLN"); + snd_soc_dapm_ignore_suspend(dapm, "SPORP"); + snd_soc_dapm_ignore_suspend(dapm, "SPORN"); + + snd_soc_dapm_enable_pin(dapm, "Headset Mic"); + snd_soc_dapm_enable_pin(dapm, "Headphone"); + snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + snd_soc_dapm_enable_pin(dapm, "Int Mic"); + + snd_soc_dapm_sync(dapm); + return ret; +} + +static struct snd_soc_ops byt_rt5640_ops = { + .hw_params = byt_rt5640_hw_params, +}; + +static struct snd_soc_dai_link byt_rt5640_dais[] = { + { + .name = "Baytrail Audio", + .stream_name = "Audio", + .cpu_dai_name = "Front-cpu-dai", + .codec_dai_name = "rt5640-aif1", + .codec_name = "i2c-10EC5640:00", + .platform_name = "baytrail-pcm-audio", + .init = byt_rt5640_init, + .ignore_suspend = 1, + .ops = &byt_rt5640_ops, + }, + { + .name = "Baytrail Voice", + .stream_name = "Voice", + .cpu_dai_name = "Mic1-cpu-dai", + .codec_dai_name = "rt5640-aif1", + .codec_name = "i2c-10EC5640:00", + .platform_name = "baytrail-pcm-audio", + .init = NULL, + .ignore_suspend = 1, + .ops = &byt_rt5640_ops, + }, +}; + +static struct snd_soc_card byt_rt5640_card = { + .name = "byt-rt5640", + .dai_link = byt_rt5640_dais, + .num_links = ARRAY_SIZE(byt_rt5640_dais), + .dapm_widgets = byt_rt5640_widgets, + .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets), + .dapm_routes = byt_rt5640_audio_map, + .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map), +}; + +static int byt_rt5640_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &byt_rt5640_card; + struct device *dev = &pdev->dev; + + card->dev = &pdev->dev; + dev_set_drvdata(dev, card); + return snd_soc_register_card(card); +} + +static int byt_rt5640_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + + return 0; +} + +static struct platform_driver byt_rt5640_audio = { + .probe = byt_rt5640_probe, + .remove = byt_rt5640_remove, + .driver = { + .name = "byt-rt5640", + .owner = THIS_MODULE, + }, +}; +module_platform_driver(byt_rt5640_audio) + +MODULE_DESCRIPTION("ASoC Intel(R) Baytrail Machine driver"); +MODULE_AUTHOR("Omair Md Abdullah, Jarkko Nikula"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:byt-rt5640"); -- cgit v1.2.3 From e0298612147f668b55644e230340237b7c1a991d Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 24 Feb 2014 17:27:01 +0200 Subject: ASoC: Intel: Add Baytrail SST and byt-rt5640 machine driver probing Add Baytrail SST descriptor with the byt-rt5640 machine driver to sst-acpi loader. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-acpi.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c index c7e36c9ee52f..0bb43169e146 100644 --- a/sound/soc/intel/sst-acpi.c +++ b/sound/soc/intel/sst-acpi.c @@ -243,9 +243,26 @@ static struct sst_acpi_desc sst_acpi_broadwell_desc = { .dma_size = SST_LPT_DSP_DMA_SIZE, }; +static struct sst_acpi_mach baytrail_machines[] = { + { "10EC5640", "byt-rt5640", "intel/fw_sst_0f28.bin-i2s_master" }, + {} +}; + +static struct sst_acpi_desc sst_acpi_baytrail_desc = { + .drv_name = "baytrail-pcm-audio", + .machines = baytrail_machines, + .resindex_lpe_base = 0, + .resindex_pcicfg_base = 1, + .resindex_fw_base = 2, + .irqindex_host_ipc = 5, + .sst_id = SST_DEV_ID_BYT, + .resindex_dma_base = -1, +}; + static struct acpi_device_id sst_acpi_match[] = { { "INT33C8", (unsigned long)&sst_acpi_haswell_desc }, { "INT3438", (unsigned long)&sst_acpi_broadwell_desc }, + { "80860F28", (unsigned long)&sst_acpi_baytrail_desc }, { } }; MODULE_DEVICE_TABLE(acpi, sst_acpi_match); -- cgit v1.2.3 From 20df8d03a7a6d71cc8c1fe54cf2c69b2d416423f Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 24 Feb 2014 17:27:02 +0200 Subject: ASoC: Intel: Add build support for Baytrail SST Enable build support for Baytrail SST DSP platform and byt-rt5640 machine drivers. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 14 +++++++++++++- sound/soc/intel/Makefile | 5 +++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index ce5a6928e601..274af1639781 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -27,6 +27,9 @@ config SND_SOC_INTEL_SST_ACPI config SND_SOC_INTEL_HASWELL tristate +config SND_SOC_INTEL_BAYTRAIL + tristate + config SND_SOC_INTEL_HASWELL_MACH tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS @@ -36,4 +39,13 @@ config SND_SOC_INTEL_HASWELL_MACH This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell Ultrabook platforms. Say Y if you have such a device - If unsure select "N". \ No newline at end of file + If unsure select "N". + +config SND_SOC_INTEL_BYT_RT5640_MACH + tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" + depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS + select SND_SOC_INTEL_BAYTRAIL + select SND_SOC_RT5640 + help + This adds audio driver for Intel Baytrail platform based boards + with the RT5640 audio codec. diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 1c188150accb..edeb79ae3dff 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -14,10 +14,15 @@ obj-$(CONFIG_SND_SOC_INTEL_SST_ACPI) += snd-soc-sst-acpi.o # Platform Support snd-soc-sst-haswell-pcm-objs := \ sst-haswell-ipc.o sst-haswell-pcm.o sst-haswell-dsp.o +snd-soc-sst-baytrail-pcm-objs := \ + sst-baytrail-ipc.o sst-baytrail-pcm.o sst-baytrail-dsp.o obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += snd-soc-sst-haswell-pcm.o +obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o # Machine support snd-soc-sst-haswell-objs := haswell.o +snd-soc-sst-byt-rt5640-mach-objs := byt-rt5640.o obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o +obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o -- cgit v1.2.3 From 5069e5c93ca73eab185d3bb338a1362275f9ea70 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 25 Feb 2014 16:37:47 +0200 Subject: ASoC: Intel: sst-acpi: Fix Oops in case of missing firmware I swear I tested missing firmware in commit e5161d7987f1 ("ASoC: Intel: sst-acpi: Request firmware before SST platform driver probing"). Unfortunately same wasn't done in commit 6dda27cbbd1d ("ASoC: Intel: sst-acpi: Add support for multiple machine drivers per platform") which will cause NULL pointer dereference in sst_acpi_fw_cb() when printing the error since sst_acpi->mach is not set. Fix this obvious error by setting the sst_acpi->mach in sst_acpi_probe(). Reported-by: Mika Westerberg Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-acpi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c index 0bb43169e146..5d06eecb6198 100644 --- a/sound/soc/intel/sst-acpi.c +++ b/sound/soc/intel/sst-acpi.c @@ -139,6 +139,7 @@ static int sst_acpi_probe(struct platform_device *pdev) sst_pdata = &sst_acpi->sst_pdata; sst_pdata->id = desc->sst_id; sst_acpi->desc = desc; + sst_acpi->mach = mach; if (desc->resindex_dma_base >= 0) { sst_pdata->dma_engine = desc->dma_engine; -- cgit v1.2.3 From 951e9bb1fa589177183af1696ecfd4e4d8d37cbf Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 21 Feb 2014 11:52:40 +0300 Subject: ASoC: Intel: sst-firmware: missing curly braces (harmless) There were some curly braces intended here, but the code actually works the same either way so it's not a bug. Signed-off-by: Dan Carpenter Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-firmware.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index dee7eb5befb7..f7687107cf7f 100644 --- a/sound/soc/intel/sst-firmware.c +++ b/sound/soc/intel/sst-firmware.c @@ -293,7 +293,7 @@ static int block_module_prepare(struct sst_module *module) /* enable each block so that's it'e ready for module P/S data */ list_for_each_entry(block, &module->block_list, module_list) { - if (block->ops && block->ops->enable) + if (block->ops && block->ops->enable) { ret = block->ops->enable(block); if (ret < 0) { dev_err(module->dsp->dev, @@ -301,6 +301,7 @@ static int block_module_prepare(struct sst_module *module) block->type, block->index); goto err; } + } } return ret; -- cgit v1.2.3 From f9da9e434d9dad684aec159a74b9c8436d4faf5a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 25 Feb 2014 11:32:50 +0300 Subject: ASoC: intel: restore IRQs on error This should be spin_unlock_irqrestore() instead of spin_unlock() Fixes: 22981243589c ('ASoC: Intel: Add Haswell/Broadwell IPC') Signed-off-by: Dan Carpenter Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 668d486520ae..552aebf2c8f5 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c @@ -527,7 +527,7 @@ static int ipc_tx_message(struct sst_hsw *hsw, u32 header, void *tx_data, msg = msg_get_empty(hsw); if (msg == NULL) { - spin_unlock(&hsw->dsp->spinlock); + spin_unlock_irqrestore(&hsw->dsp->spinlock, flags); return -EBUSY; } -- cgit v1.2.3 From 31d632f95567a84e1344aa110249a8346c35d2ec Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 25 Feb 2014 11:33:44 +0300 Subject: ASoC: intel: incorrect sizeof() This should be sizeof(pos) instead of sizeof(&pos). Most likely they are both 8 bytes though so it doesn't often make a difference in real life. Fixes: 22981243589c ('ASoC: Intel: Add Haswell/Broadwell IPC') Signed-off-by: Dan Carpenter Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 552aebf2c8f5..1f1576a9586a 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c @@ -617,7 +617,7 @@ static void hsw_notification_work(struct work_struct *work) case IPC_POSITION_CHANGED: trace_ipc_notification("DSP stream position changed for", stream->reply.stream_hw_id); - sst_dsp_inbox_read(hsw->dsp, pos, sizeof(&pos)); + sst_dsp_inbox_read(hsw->dsp, pos, sizeof(pos)); if (stream->notify_position) stream->notify_position(stream, stream->pdata); -- cgit v1.2.3 From 52be4776cace06bf3d3df85fa490e61421824051 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 25 Feb 2014 15:17:27 +0200 Subject: ASoC: Intel: byt-rt5640: Update internal mic and speaker kcontrol names Use more sensible kcontrol names than "Int Mic" and "Ext Spk". Speakers especially are usually integrated devices in sales models. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwoood Signed-off-by: Mark Brown --- sound/soc/intel/byt-rt5640.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c index 038547b48b2d..672fedbfa680 100644 --- a/sound/soc/intel/byt-rt5640.c +++ b/sound/soc/intel/byt-rt5640.c @@ -29,27 +29,27 @@ static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("Int Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_MIC("Internal Mic", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), }; static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { {"IN2P", NULL, "Headset Mic"}, {"IN2N", NULL, "Headset Mic"}, - {"DMIC1", NULL, "Int Mic"}, + {"DMIC1", NULL, "Internal Mic"}, {"Headphone", NULL, "HPOL"}, {"Headphone", NULL, "HPOR"}, - {"Ext Spk", NULL, "SPOLP"}, - {"Ext Spk", NULL, "SPOLN"}, - {"Ext Spk", NULL, "SPORP"}, - {"Ext Spk", NULL, "SPORN"}, + {"Speaker", NULL, "SPOLP"}, + {"Speaker", NULL, "SPOLN"}, + {"Speaker", NULL, "SPORP"}, + {"Speaker", NULL, "SPORN"}, }; static const struct snd_kcontrol_new byt_rt5640_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Int Mic"), - SOC_DAPM_PIN_SWITCH("Ext Spk"), + SOC_DAPM_PIN_SWITCH("Internal Mic"), + SOC_DAPM_PIN_SWITCH("Speaker"), }; static int byt_rt5640_hw_params(struct snd_pcm_substream *substream, @@ -113,8 +113,8 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) snd_soc_dapm_enable_pin(dapm, "Headset Mic"); snd_soc_dapm_enable_pin(dapm, "Headphone"); - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - snd_soc_dapm_enable_pin(dapm, "Int Mic"); + snd_soc_dapm_enable_pin(dapm, "Speaker"); + snd_soc_dapm_enable_pin(dapm, "Internal Mic"); snd_soc_dapm_sync(dapm); return ret; -- cgit v1.2.3 From 95c40d4b0eb47d82a8841364627a35ad6fad720b Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 25 Feb 2014 15:17:28 +0200 Subject: ASoC: Intel: byt-rt5640: Use init time DAI format Setting static DAI format has been supported in the soc-core quite some time now so there is no need to set it runtime in machine driver. Signed-off-by: Jarkko Nikula Acked-by: Liam Girdwoood Signed-off-by: Mark Brown --- sound/soc/intel/byt-rt5640.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/byt-rt5640.c b/sound/soc/intel/byt-rt5640.c index 672fedbfa680..eff97c8e5218 100644 --- a/sound/soc/intel/byt-rt5640.c +++ b/sound/soc/intel/byt-rt5640.c @@ -57,19 +57,8 @@ static int byt_rt5640_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; - unsigned int fmt; int ret; - fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS; - - ret = snd_soc_dai_set_fmt(codec_dai, fmt); - if (ret < 0) { - dev_err(codec_dai->dev, - "can't set codec DAI configuration %d\n", ret); - return ret; - } - ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, params_rate(params) * 256, SND_SOC_CLOCK_IN); @@ -132,6 +121,8 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .codec_dai_name = "rt5640-aif1", .codec_name = "i2c-10EC5640:00", .platform_name = "baytrail-pcm-audio", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, .init = byt_rt5640_init, .ignore_suspend = 1, .ops = &byt_rt5640_ops, @@ -143,6 +134,8 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .codec_dai_name = "rt5640-aif1", .codec_name = "i2c-10EC5640:00", .platform_name = "baytrail-pcm-audio", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, .init = NULL, .ignore_suspend = 1, .ops = &byt_rt5640_ops, -- cgit v1.2.3 From 13cde090030c7d00e991c85b87c12891cc8e4df4 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 25 Feb 2014 17:54:51 +0800 Subject: ASoC: fsl-sai: fix Freescale SAI DAI format setting. o Fix some bugs of fsl_sai_set_dai_fmt_tr(). o Add SND_SOC_DAIFMT_LEFT_J support. o Add SND_SOC_DAIFMT_CBS_CFM support. o Add SND_SOC_DAIFMT_CBM_CFS support. o And SND_SOC_DAIFMT_RIGHT_J need to be done in the future. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index faa65afb6951..26d9f5ed6959 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -105,35 +105,47 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, else val_cr4 |= FSL_SAI_CR4_MF; + /* DAI mode */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - val_cr4 |= FSL_SAI_CR4_FSE; + /* Data on rising edge of bclk, frame low, 1clk before data */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP; + break; + case SND_SOC_DAIFMT_LEFT_J: + /* Data on rising edge of bclk, frame high, 0clk before data */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP); break; + case SND_SOC_DAIFMT_RIGHT_J: + /* To be done */ default: return -EINVAL; } + /* DAI clock inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_IB_IF: - val_cr4 |= FSL_SAI_CR4_FSP; - val_cr2 &= ~FSL_SAI_CR2_BCP; + /* Invert both clocks */ + val_cr2 ^= FSL_SAI_CR2_BCP; + val_cr4 ^= FSL_SAI_CR4_FSP; break; case SND_SOC_DAIFMT_IB_NF: - val_cr4 &= ~FSL_SAI_CR4_FSP; - val_cr2 &= ~FSL_SAI_CR2_BCP; + /* Invert bit clock */ + val_cr2 ^= FSL_SAI_CR2_BCP; break; case SND_SOC_DAIFMT_NB_IF: - val_cr4 |= FSL_SAI_CR4_FSP; - val_cr2 |= FSL_SAI_CR2_BCP; + /* Invert frame clock */ + val_cr4 ^= FSL_SAI_CR4_FSP; break; case SND_SOC_DAIFMT_NB_NF: - val_cr4 &= ~FSL_SAI_CR4_FSP; - val_cr2 |= FSL_SAI_CR2_BCP; + /* Nothing to do for both normal cases */ break; default: return -EINVAL; } + /* DAI clock master masks */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: val_cr2 |= FSL_SAI_CR2_BCD_MSTR; @@ -143,6 +155,14 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; break; + case SND_SOC_DAIFMT_CBS_CFM: + val_cr2 |= FSL_SAI_CR2_BCD_MSTR; + val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR; + break; + case SND_SOC_DAIFMT_CBM_CFS: + val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR; + val_cr4 |= FSL_SAI_CR4_FSD_MSTR; + break; default: return -EINVAL; } -- cgit v1.2.3 From 17cb37aafdc11b875b915292ae21ac3a4f1425a7 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 25 Feb 2014 22:01:54 +0400 Subject: ASoC: cirrus: Remove excess dependencies on SND_SOC Configuration for Cirrus Logic audio support is included only if SND_SOC symbol selected, so no reason to check it once more. Signed-off-by: Alexander Shiyan Signed-off-by: Mark Brown --- sound/soc/cirrus/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 06f938deda15..c872dacbab98 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig @@ -1,6 +1,6 @@ config SND_EP93XX_SOC tristate "SoC Audio support for the Cirrus Logic EP93xx series" - depends on (ARCH_EP93XX || COMPILE_TEST) && SND_SOC + depends on ARCH_EP93XX || COMPILE_TEST select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for codecs attached to -- cgit v1.2.3 From a6cf8f7b53fff6b5e3463793aa9885e133e7ef86 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 26 Feb 2014 15:31:46 +0200 Subject: ASoC: Intel: Baytrail: Fix implicit declaration of function 'memcpy_fromio' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some kernel configurations can cause following build error: sound/soc/intel/sst-baytrail-ipc.c: In function ‘sst_byt_get_dsp_position’: sound/soc/intel/sst-baytrail-ipc.c:744:2: error: implicit declaration of function ‘memcpy_fromio’ [-Werror=implicit-function-declaration] memcpy_fromio(&fw_tstamp, ^ cc1: some warnings being treated as errors Fix this by including explicitly. Reported-by: kbuild test robot Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- sound/soc/intel/sst-baytrail-ipc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c index 8c91a68b90bc..c12e194bbc6b 100644 --- a/sound/soc/intel/sst-baytrail-ipc.c +++ b/sound/soc/intel/sst-baytrail-ipc.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "sst-baytrail-ipc.h" -- cgit v1.2.3 From a3f7dcc9cc0392528bff75b17adfcd74fb8a0ecd Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Thu, 27 Feb 2014 08:45:01 +0800 Subject: ASoC: fsl-sai: Add SND_SOC_DAIFMT_DSP_A/B support. o Add SND_SOC_DAIFMT_DSP_A support. o Add SND_SOC_DAIFMT_DSP_B support. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- sound/soc/fsl/fsl_sai.h | 1 + 2 files changed, 43 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 26d9f5ed6959..c4a423111673 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -108,15 +108,44 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, /* DAI mode */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - /* Data on rising edge of bclk, frame low, 1clk before data */ + /* + * Frame low, 1clk before data, one word length for frame sync, + * frame sync starts one serial clock cycle earlier, + * that is, together with the last bit of the previous + * data word. + */ val_cr2 &= ~FSL_SAI_CR2_BCP; val_cr4 |= FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP; break; case SND_SOC_DAIFMT_LEFT_J: - /* Data on rising edge of bclk, frame high, 0clk before data */ + /* + * Frame high, one word length for frame sync, + * frame sync asserts with the first bit of the frame. + */ val_cr2 &= ~FSL_SAI_CR2_BCP; val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP); break; + case SND_SOC_DAIFMT_DSP_A: + /* + * Frame high, 1clk before data, one bit for frame sync, + * frame sync starts one serial clock cycle earlier, + * that is, together with the last bit of the previous + * data word. + */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 &= ~FSL_SAI_CR4_FSP; + val_cr4 |= FSL_SAI_CR4_FSE; + sai->is_dsp_mode = true; + break; + case SND_SOC_DAIFMT_DSP_B: + /* + * Frame high, one bit for frame sync, + * frame sync asserts with the first bit of the frame. + */ + val_cr2 &= ~FSL_SAI_CR2_BCP; + val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP); + sai->is_dsp_mode = true; + break; case SND_SOC_DAIFMT_RIGHT_J: /* To be done */ default: @@ -219,7 +248,9 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, val_cr5 &= ~FSL_SAI_CR5_W0W_MASK; val_cr5 &= ~FSL_SAI_CR5_FBT_MASK; - val_cr4 |= FSL_SAI_CR4_SYWD(word_width); + if (!sai->is_dsp_mode) + val_cr4 |= FSL_SAI_CR4_SYWD(word_width); + val_cr5 |= FSL_SAI_CR5_WNW(word_width); val_cr5 |= FSL_SAI_CR5_W0W(word_width); @@ -245,6 +276,10 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai); u32 tcsr, rcsr; + /* + * The transmitter bit clock and frame sync are to be + * used by both the transmitter and receiver. + */ regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC, ~FSL_SAI_CR2_SYNC); regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC, @@ -261,6 +296,10 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, tcsr &= ~FSL_SAI_CSR_FRDE; } + /* + * It is recommended that the transmitter is the last enabled + * and the first disabled. + */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index 1571459d13ec..e432260be598 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -103,6 +103,7 @@ struct fsl_sai { bool big_endian_regs; bool big_endian_data; + bool is_dsp_mode; struct snd_dmaengine_dai_dma_data dma_params_rx; struct snd_dmaengine_dai_dma_data dma_params_tx; -- cgit v1.2.3 From 9aa8210d40c2140daf655c5299557bd68362399a Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Thu, 27 Feb 2014 17:49:51 +0800 Subject: ASoC: io: Clean up snd_soc_codec_set_cache_io() Now that all users have been converted to regmap and the config.reg_bits and config.val_bits can be setted by each user through regmap core API. So these two params are redundant here. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/soc-io.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index add99e2f7996..18353f111b6a 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -88,16 +88,11 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, int addr_bits, int data_bits, enum snd_soc_control_type control) { - struct regmap_config config; int ret; - memset(&config, 0, sizeof(config)); codec->write = hw_write; codec->read = hw_read; - config.reg_bits = addr_bits; - config.val_bits = data_bits; - switch (control) { case SND_SOC_REGMAP: /* Device has made its own regmap arrangements */ -- cgit v1.2.3 From fe2265e4833a3ebea426d748b5ecf8d3ff31edc8 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Thu, 27 Feb 2014 17:49:52 +0800 Subject: ASoC: core: Set the default I/O up try regmap. For most CODEC drivers which the REGMAP is used, the soc_probe_codec() will do the stuff work of snd_soc_codec_set_cache_io(), which the CODEC drivers' ASoC probe will do too, and almost at the same time. This patch set the default I/O up try regmap, and then the CODEC drivers' stuff work of snd_soc_codec_set_cache_io() will be redundant, while if one CODEC driver needed to set it's own I/O, then it can rewrite the default ones. Then could we just discard the snd_soc_codec_set_cache_io() from the CODEC drivers' ASoC probe to simplify the code. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..93854f031523 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1137,6 +1137,10 @@ static int soc_probe_codec(struct snd_soc_card *card, codec->dapm.idle_bias_off = driver->idle_bias_off; + /* Set the default I/O up try regmap */ + if (dev_get_regmap(codec->dev, NULL)) + snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + if (driver->probe) { ret = driver->probe(codec); if (ret < 0) { @@ -1150,10 +1154,6 @@ static int soc_probe_codec(struct snd_soc_card *card, codec->name); } - /* If the driver didn't set I/O up try regmap */ - if (!codec->write && dev_get_regmap(codec->dev, NULL)) - snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (driver->controls) snd_soc_add_codec_controls(codec, driver->controls, driver->num_controls); -- cgit v1.2.3 From 30519cb8d2ecb7f0f0cdc42d709da0d9f7a04bcb Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Thu, 27 Feb 2014 17:49:53 +0800 Subject: ASoC: sgtl5000: Simplify ASoC probe code Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 0fcbe90f3ef2..c8c37e431e7c 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1350,14 +1350,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) int ret; struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - /* setup i2c data ops */ - codec->control_data = sgtl5000->regmap; - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = sgtl5000_enable_regulators(codec); if (ret) return ret; -- cgit v1.2.3 From f687d900d30a61dda38db2a99239f5284a86a309 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 27 Feb 2014 18:25:24 -0800 Subject: ASoC: simple-card: cpu_dai_name creates confusion when DT case Basically, soc_bind_dai_link() checks cpu_dai->dev->of_node and dai_link->cpu_of_node in DT case. But after that it will check cpu_dai->name and dai_link->cpu_dai_name too. On the other hand, snd_soc_dai :: name is created by fmt_single_name() or fmt_multiple_name(). There is no confusion if dai name is created by fmt_multiple_name(), since cpu_dai->name is same as dai_link->cpu_dai_name. but, if dai name is created by fmt_single_name(), CPU DAI never match. Thus, simple-card not set dai_link->cpu_dai_name if DT case to skip naming match on soc_bind_dai_link() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index bdd176ddff07..034a2b73f6c1 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -234,6 +234,17 @@ static int asoc_simple_card_parse_of(struct device_node *node, priv->codec_dai.fmt, priv->codec_dai.sysclk); + /* + * soc_bind_dai_link() will check cpu name + * after of_node matching if dai_link has cpu_dai_name. + * but, it will never match if name was created by fmt_single_name() + * remove cpu_dai_name to escape name matching. + * see + * fmt_single_name() + * fmt_multiple_name() + */ + dai_link->cpu_dai_name = NULL; + return 0; } -- cgit v1.2.3 From 29ae2fa5533e607a7d97b7564dc015252f1e73f4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:03 +0100 Subject: ASoC: Consolidate enum and value enum controls The implementations for enum and value enum controls are almost identical. The only difference is that the value enum uses an additional look-up table to map the control value to the register value, while the enum control uses a direct mapping. Enums and value enums can easily be distinguished at runtime, for value enums the values field of the snd_soc_enum struct contains the look-up table, while for enums it is NULL. This patch adds two new small helper functions called snd_soc_enum_item_to_val() and snd_soc_enum_val_to_item() which map between register value and control item. If the items field of the snd_soc_enum struct is NULL the function will do a direct mapping otherwise they'll use the look-up table to do the mapping. Using these small helper functions it is possible to use the same kcontrol handlers for both enums and value enums. The functions are added a inline functions in soc.h so they can also be used by the DAPM code to accomplish similar consolidation. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 34 ++++++++++++----- sound/soc/soc-core.c | 101 ++++++++------------------------------------------- 2 files changed, 41 insertions(+), 94 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 49d6c10f4612..60c700ccc518 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -195,11 +195,7 @@ .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \ .private_value = (unsigned long)&xenum } #define SOC_VALUE_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_get_value_enum_double, \ - .put = snd_soc_put_value_enum_double, \ - .private_value = (unsigned long)&xenum } + SOC_ENUM(xname, xenum) #define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -510,10 +506,6 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); #define snd_soc_info_bool_ext snd_ctl_boolean_mono_info @@ -1182,6 +1174,30 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) return 1; } +static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, + unsigned int val) +{ + unsigned int i; + + if (!e->values) + return val; + + for (i = 0; i < e->items; i++) + if (val == e->values[i]) + return i; + + return 0; +} + +static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, + unsigned int item) +{ + if (!e->values) + return item; + + return e->values[item]; +} + int snd_soc_util_init(void); void snd_soc_util_exit(void); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 851733897206..2ddc7a4939d2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2596,14 +2596,18 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; + unsigned int val, item; + unsigned int reg_val; - val = snd_soc_read(codec, e->reg); - ucontrol->value.enumerated.item[0] - = (val >> e->shift_l) & e->mask; - if (e->shift_l != e->shift_r) - ucontrol->value.enumerated.item[1] = - (val >> e->shift_r) & e->mask; + reg_val = snd_soc_read(codec, e->reg); + val = (reg_val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + ucontrol->value.enumerated.item[0] = item; + if (e->shift_l != e->shift_r) { + val = (reg_val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + ucontrol->value.enumerated.item[1] = item; + } return 0; } @@ -2623,17 +2627,18 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int *item = ucontrol->value.enumerated.item; unsigned int val; unsigned int mask; - if (ucontrol->value.enumerated.item[0] >= e->items) + if (item[0] >= e->items) return -EINVAL; - val = ucontrol->value.enumerated.item[0] << e->shift_l; + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] >= e->items) + if (item[1] >= e->items) return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; + val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; mask |= e->mask << e->shift_r; } @@ -2641,80 +2646,6 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); -/** - * snd_soc_get_value_enum_double - semi enumerated double mixer get callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to get the value of a double semi enumerated mixer. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. - * - * Returns 0 for success. - */ -int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int reg_val, val, mux; - - reg_val = snd_soc_read(codec, e->reg); - val = (reg_val >> e->shift_l) & e->mask; - for (mux = 0; mux < e->items; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[0] = mux; - if (e->shift_l != e->shift_r) { - val = (reg_val >> e->shift_r) & e->mask; - for (mux = 0; mux < e->items; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[1] = mux; - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_get_value_enum_double); - -/** - * snd_soc_put_value_enum_double - semi enumerated double mixer put callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to set the value of a double semi enumerated mixer. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. - * - * Returns 0 for success. - */ -int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; - unsigned int mask; - - if (ucontrol->value.enumerated.item[0] >= e->items) - return -EINVAL; - val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; - mask = e->mask << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] >= e->items) - return -EINVAL; - val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; - mask |= e->mask << e->shift_r; - } - - return snd_soc_update_bits_locked(codec, e->reg, mask, val); -} -EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); - /** * snd_soc_read_signed - Read a codec register and interprete as signed value * @codec: codec -- cgit v1.2.3 From 3727b4968453dbab8fe18f979d67285eb6b66801 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:04 +0100 Subject: ASoC: dapm: Consolidate MUXs and value MUXs MUXs and value MUXs are almost identical, the only difference is that a value MUX uses a look-up table to map from the selected control item to a register value, while MUXs use a direct mapping. This patch uses snd_soc_enum_item_to_val() and snd_soc_enum_val_to_item(), which where earlier introduced during the consolidation of enum and value enum controls, to hide this difference. This allows us to use the same code path for both MUXs and value MUXs and a lot of nearly duplicated code can be removed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 15 +---- sound/soc/soc-dapm.c | 157 ++++++----------------------------------------- 2 files changed, 21 insertions(+), 151 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 3b991766a8f2..2ec14cb3ff1e 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -112,9 +112,7 @@ struct device; SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1} #define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \ -{ .id = snd_soc_dapm_value_mux, .name = wname, \ - SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ - .kcontrol_news = wcontrols, .num_kcontrols = 1} + SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ @@ -324,11 +322,7 @@ struct device; .put = xput, \ .private_value = (unsigned long)&xenum } #define SOC_DAPM_VALUE_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_value_enum_double, \ - .put = snd_soc_dapm_put_value_enum_double, \ - .private_value = (unsigned long)&xenum } + SOC_DAPM_ENUM(xname, xenum) #define SOC_DAPM_PIN_SWITCH(xname) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \ .info = snd_soc_dapm_info_pin_switch, \ @@ -396,10 +390,6 @@ int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, @@ -486,7 +476,6 @@ enum snd_soc_dapm_type { snd_soc_dapm_output, /* output pin */ snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ snd_soc_dapm_virt_mux, /* virtual version of snd_soc_dapm_mux */ - snd_soc_dapm_value_mux, /* selects 1 analog signal from many inputs */ snd_soc_dapm_mixer, /* mixes several analog signals together */ snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */ snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 96a97a3dfb68..f23eeeeaafc5 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -71,7 +71,6 @@ static int dapm_up_seq[] = { [snd_soc_dapm_mic] = 5, [snd_soc_dapm_mux] = 6, [snd_soc_dapm_virt_mux] = 6, - [snd_soc_dapm_value_mux] = 6, [snd_soc_dapm_dac] = 7, [snd_soc_dapm_switch] = 8, [snd_soc_dapm_mixer] = 8, @@ -103,7 +102,6 @@ static int dapm_down_seq[] = { [snd_soc_dapm_micbias] = 8, [snd_soc_dapm_mux] = 9, [snd_soc_dapm_virt_mux] = 9, - [snd_soc_dapm_value_mux] = 9, [snd_soc_dapm_aif_in] = 10, [snd_soc_dapm_aif_out] = 10, [snd_soc_dapm_dai_in] = 10, @@ -534,7 +532,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, unsigned int val, item; soc_widget_read(w, e->reg, &val); - item = (val >> e->shift_l) & e->mask; + val = (val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); if (item < e->items && !strcmp(p->name, e->texts[item])) p->connect = 1; @@ -557,24 +556,6 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, p->connect = 1; } break; - case snd_soc_dapm_value_mux: { - struct soc_enum *e = (struct soc_enum *) - w->kcontrol_news[i].private_value; - unsigned int val, item; - - soc_widget_read(w, e->reg, &val); - val = (val >> e->shift_l) & e->mask; - for (item = 0; item < e->items; item++) { - if (val == e->values[item]) - break; - } - - if (item < e->items && !strcmp(p->name, e->texts[item])) - p->connect = 1; - else - p->connect = 0; - } - break; /* does not affect routing - always connected */ case snd_soc_dapm_pga: case snd_soc_dapm_out_drv: @@ -725,7 +706,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, break; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: wname_in_long_name = true; kcname_in_long_name = false; break; @@ -2463,7 +2443,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, return 0; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: ret = dapm_connect_mux(dapm, wsource, wsink, path, control, &wsink->kcontrol_news[0]); if (ret != 0) @@ -2791,7 +2770,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) break; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: dapm_new_mux(w); break; case snd_soc_dapm_pga: @@ -2953,13 +2931,16 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; + unsigned int reg_val, val; - val = snd_soc_read(codec, e->reg); - ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; - if (e->shift_l != e->shift_r) - ucontrol->value.enumerated.item[1] = - (val >> e->shift_r) & e->mask; + reg_val = snd_soc_read(codec, e->reg); + val = (reg_val >> e->shift_l) & e->mask; + ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); + if (e->shift_l != e->shift_r) { + val = (reg_val >> e->shift_r) & e->mask; + val = snd_soc_enum_val_to_item(e, val); + ucontrol->value.enumerated.item[1] = val; + } return 0; } @@ -2980,20 +2961,21 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); struct snd_soc_card *card = codec->card; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, mux, change; + unsigned int *item = ucontrol->value.enumerated.item; + unsigned int val, change; unsigned int mask; struct snd_soc_dapm_update update; int ret = 0; - if (ucontrol->value.enumerated.item[0] >= e->items) + if (item[0] >= e->items) return -EINVAL; - mux = ucontrol->value.enumerated.item[0]; - val = mux << e->shift_l; + + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] >= e->items) + if (item[1] > e->items) return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; + val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_l; mask |= e->mask << e->shift_r; } @@ -3007,7 +2989,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, update.val = val; card->update = &update; - ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); + ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e); card->update = NULL; } @@ -3073,106 +3055,6 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); -/** - * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get - * callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to get the value of a dapm semi enumerated double mixer control. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. - * - * Returns 0 for success. - */ -int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int reg_val, val, mux; - - reg_val = snd_soc_read(codec, e->reg); - val = (reg_val >> e->shift_l) & e->mask; - for (mux = 0; mux < e->items; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[0] = mux; - if (e->shift_l != e->shift_r) { - val = (reg_val >> e->shift_r) & e->mask; - for (mux = 0; mux < e->items; mux++) { - if (val == e->values[mux]) - break; - } - ucontrol->value.enumerated.item[1] = mux; - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); - -/** - * snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set - * callback - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Callback to set the value of a dapm semi enumerated double mixer control. - * - * Semi enumerated mixer: the enumerated items are referred as values. Can be - * used for handling bitfield coded enumeration for example. - * - * Returns 0 for success. - */ -int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct snd_soc_card *card = codec->card; - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, mux, change; - unsigned int mask; - struct snd_soc_dapm_update update; - int ret = 0; - - if (ucontrol->value.enumerated.item[0] >= e->items) - return -EINVAL; - mux = ucontrol->value.enumerated.item[0]; - val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; - mask = e->mask << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] >= e->items) - return -EINVAL; - val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; - mask |= e->mask << e->shift_r; - } - - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - - change = snd_soc_test_bits(codec, e->reg, mask, val); - if (change) { - update.kcontrol = kcontrol; - update.reg = e->reg; - update.mask = mask; - update.val = val; - card->update = &update; - - ret = soc_dapm_mux_update_power(card, kcontrol, mux, e); - - card->update = NULL; - } - - mutex_unlock(&card->dapm_mutex); - - if (ret > 0) - soc_dpcm_runtime_update(card); - - return change; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); - /** * snd_soc_dapm_info_pin_switch - Info for a pin switch * @@ -3302,7 +3184,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, break; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: - case snd_soc_dapm_value_mux: w->power_check = dapm_generic_check_power; break; case snd_soc_dapm_dai_out: -- cgit v1.2.3 From 28963178427386e83788d314d2a05f0c093f836a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:06 +0100 Subject: ASoC: adau1373: Use SOC_ENUM_SINGLE_VIRT_DECL() For the upcoming consolidation for MUXs and virtual MUXs we need to mark virtual enums as such. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/adau1373.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 5765c224cd9a..5223800775ad 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -576,8 +576,8 @@ static const char *adau1373_decimator_text[] = { "DMIC1", }; -static SOC_ENUM_SINGLE_DECL(adau1373_decimator_enum, - 0, 0, adau1373_decimator_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adau1373_decimator_enum, + adau1373_decimator_text); static const struct snd_kcontrol_new adau1373_decimator_mux = SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); -- cgit v1.2.3 From ba513116403bc93072dd54a1f89dacdb4d89fcab Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:07 +0100 Subject: ASoC: max98090: Use SOC_ENUM_SINGLE_VIRT_DECL() For the upcoming consolidation for MUXs and virtual MUXs we need to mark virtual enums as such. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/max98090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index c7b9e901bdac..1686ade2a429 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -871,7 +871,7 @@ static const struct snd_kcontrol_new max98090_mic2_mux = static const char *dmic_mux_text[] = { "ADC", "DMIC" }; -static SOC_ENUM_SINGLE_EXT_DECL(dmic_mux_enum, dmic_mux_text); +static SOC_ENUM_SINGLE_VIRT_DECL(dmic_mux_enum, dmic_mux_text); static const struct snd_kcontrol_new max98090_dmic_mux = SOC_DAPM_ENUM_VIRT("DMIC Mux", dmic_mux_enum); -- cgit v1.2.3 From 15ab40a9a83035d92b4f4c83cb88c7529bf73c71 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:08 +0100 Subject: ASoC: mc13783: Use SOC_ENUM_SINGLE_VIRT_DECL() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the upcoming consolidation for MUXs and virtual MUXs we need to mark virtual enums as such. Signed-off-by: Lars-Peter Clausen Tested-by: Philippe Rétornaz Signed-off-by: Mark Brown --- sound/soc/codecs/mc13783.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index c605036cc0b0..ec89b8f90a64 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -408,8 +408,7 @@ static const char * const adcl_enum_text[] = { "MC1L", "RXINL", }; -static SOC_ENUM_SINGLE_DECL(adcl_enum, - 0, 0, adcl_enum_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adcl_enum, adcl_enum_text); static const struct snd_kcontrol_new left_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcl_enum); @@ -418,8 +417,7 @@ static const char * const adcr_enum_text[] = { "MC1R", "MC2", "RXINR", "TXIN", }; -static SOC_ENUM_SINGLE_DECL(adcr_enum, - 0, 0, adcr_enum_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adcr_enum, adcr_enum_text); static const struct snd_kcontrol_new right_input_mux = SOC_DAPM_ENUM_VIRT("Route", adcr_enum); -- cgit v1.2.3 From 86d4c9ab28b73f9eeb8cbd3b11cb2f2aee079a00 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:09 +0100 Subject: ASoC: wm8994: Use SOC_ENUM_SINGLE_VIRT_DECL() For the upcoming consolidation for MUXs and virtual MUXs we need to mark virtual enums as such. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 699b527e2a77..79854cb7feb6 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1344,8 +1344,7 @@ static const char *adc_mux_text[] = { "DMIC", }; -static SOC_ENUM_SINGLE_DECL(adc_enum, - 0, 0, adc_mux_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); -- cgit v1.2.3 From f6b45c28f451e8e415db49f693b2fec90c2cb557 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:10 +0100 Subject: ASoC: wm8995: Use SOC_ENUM_SINGLE_VIRT_DECL() For the upcoming consolidation for MUXs and virtual MUXs we need to mark virtual enums as such. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8995.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 33ff361250a8..ddb197dc1d53 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -882,7 +882,7 @@ static const char *adc_mux_text[] = { "DMIC", }; -static const SOC_ENUM_SINGLE_DECL(adc_enum, 0, 0, adc_mux_text); +static SOC_ENUM_SINGLE_VIRT_DECL(adc_enum, adc_mux_text); static const struct snd_kcontrol_new adcl_mux = SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); -- cgit v1.2.3 From 236aaa6863581634bd6d599ccf7f7b38deeafdc0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:11 +0100 Subject: ASoC: dapm: Consolidate MUXs and virtual MUXs MUXs and virtual MUXs are almost identical, the only difference is that for virtual MUX there is no hardware backing register in which setting is stored. This patch adds code, which is similar to what we already do for DAPM mixer controls to support virtual mixer controls, to DAPM enum controls. The new code will check if the enum does a hardware backing register and skip over reading and writing to the register if it has not. This allows us to use the same code path for both MUXs and virtual MUXs and a lot of nearly identical code can be removed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 23 +++------- sound/soc/soc-dapm.c | 113 +++++++++++++---------------------------------- 2 files changed, 35 insertions(+), 101 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 2ec14cb3ff1e..04d32d89bc7d 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -108,9 +108,7 @@ struct device; SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1} #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \ -{ .id = snd_soc_dapm_virt_mux, .name = wname, \ - SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ - .kcontrol_news = wcontrols, .num_kcontrols = 1} + SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) #define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \ SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) @@ -170,10 +168,8 @@ struct device; .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ wevent, wflags) \ -{ .id = snd_soc_dapm_virt_mux, .name = wname, \ - SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ - .kcontrol_news = wcontrols, .num_kcontrols = 1, \ - .event = wevent, .event_flags = wflags} + SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, wevent, \ + wflags) /* additional sequencing control within an event type */ #define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \ @@ -309,12 +305,8 @@ struct device; .get = snd_soc_dapm_get_enum_double, \ .put = snd_soc_dapm_put_enum_double, \ .private_value = (unsigned long)&xenum } -#define SOC_DAPM_ENUM_VIRT(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_enum_virt, \ - .put = snd_soc_dapm_put_enum_virt, \ - .private_value = (unsigned long)&xenum } +#define SOC_DAPM_ENUM_VIRT(xname, xenum) \ + SOC_DAPM_ENUM(xname, xenum) #define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_enum_double, \ @@ -386,10 +378,6 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, @@ -475,7 +463,6 @@ enum snd_soc_dapm_type { snd_soc_dapm_input = 0, /* input pin */ snd_soc_dapm_output, /* output pin */ snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ - snd_soc_dapm_virt_mux, /* virtual version of snd_soc_dapm_mux */ snd_soc_dapm_mixer, /* mixes several analog signals together */ snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */ snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f23eeeeaafc5..c07c7fb7593a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -70,7 +70,6 @@ static int dapm_up_seq[] = { [snd_soc_dapm_aif_out] = 4, [snd_soc_dapm_mic] = 5, [snd_soc_dapm_mux] = 6, - [snd_soc_dapm_virt_mux] = 6, [snd_soc_dapm_dac] = 7, [snd_soc_dapm_switch] = 8, [snd_soc_dapm_mixer] = 8, @@ -101,7 +100,6 @@ static int dapm_down_seq[] = { [snd_soc_dapm_mic] = 7, [snd_soc_dapm_micbias] = 8, [snd_soc_dapm_mux] = 9, - [snd_soc_dapm_virt_mux] = 9, [snd_soc_dapm_aif_in] = 10, [snd_soc_dapm_aif_out] = 10, [snd_soc_dapm_dai_in] = 10, @@ -531,9 +529,19 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, w->kcontrol_news[i].private_value; unsigned int val, item; - soc_widget_read(w, e->reg, &val); - val = (val >> e->shift_l) & e->mask; - item = snd_soc_enum_val_to_item(e, val); + if (e->reg != SND_SOC_NOPM) { + soc_widget_read(w, e->reg, &val); + val = (val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + } else { + /* since a virtual mux has no backing registers to + * decide which path to connect, it will try to match + * with the first enumeration. This is to ensure + * that the default mux choice (the first) will be + * correctly powered up during initialization. + */ + item = 0; + } if (item < e->items && !strcmp(p->name, e->texts[item])) p->connect = 1; @@ -541,21 +549,6 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, p->connect = 0; } break; - case snd_soc_dapm_virt_mux: { - struct soc_enum *e = (struct soc_enum *) - w->kcontrol_news[i].private_value; - - p->connect = 0; - /* since a virtual mux has no backing registers to - * decide which path to connect, it will try to match - * with the first enumeration. This is to ensure - * that the default mux choice (the first) will be - * correctly powered up during initialization. - */ - if (!strcmp(p->name, e->texts[0])) - p->connect = 1; - } - break; /* does not affect routing - always connected */ case snd_soc_dapm_pga: case snd_soc_dapm_out_drv: @@ -705,7 +698,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, kcname_in_long_name = true; break; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: wname_in_long_name = true; kcname_in_long_name = false; break; @@ -2442,7 +2434,6 @@ static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm, path->connect = 1; return 0; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: ret = dapm_connect_mux(dapm, wsource, wsink, path, control, &wsink->kcontrol_news[0]); if (ret != 0) @@ -2769,7 +2760,6 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) dapm_new_mixer(w); break; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: dapm_new_mux(w); break; case snd_soc_dapm_pga: @@ -2933,7 +2923,11 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int reg_val, val; - reg_val = snd_soc_read(codec, e->reg); + if (e->reg != SND_SOC_NOPM) + reg_val = snd_soc_read(codec, e->reg); + else + reg_val = dapm_kcontrol_get_value(kcontrol); + val = (reg_val >> e->shift_l) & e->mask; ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val); if (e->shift_l != e->shift_r) { @@ -2981,13 +2975,19 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - change = snd_soc_test_bits(codec, e->reg, mask, val); + if (e->reg != SND_SOC_NOPM) + change = snd_soc_test_bits(codec, e->reg, mask, val); + else + change = dapm_kcontrol_set_value(kcontrol, val); + if (change) { - update.kcontrol = kcontrol; - update.reg = e->reg; - update.mask = mask; - update.val = val; - card->update = &update; + if (e->reg != SND_SOC_NOPM) { + update.kcontrol = kcontrol; + update.reg = e->reg; + update.mask = mask; + update.val = val; + card->update = &update; + } ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e); @@ -3003,58 +3003,6 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); -/** - * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Returns 0 for success. - */ -int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.enumerated.item[0] = dapm_kcontrol_get_value(kcontrol); - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt); - -/** - * snd_soc_dapm_put_enum_virt - Set virtual DAPM mux - * @kcontrol: mixer control - * @ucontrol: control element information - * - * Returns 0 for success. - */ -int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); - struct snd_soc_card *card = codec->card; - unsigned int value; - struct soc_enum *e = - (struct soc_enum *)kcontrol->private_value; - int change; - int ret = 0; - - if (ucontrol->value.enumerated.item[0] >= e->items) - return -EINVAL; - - mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - - value = ucontrol->value.enumerated.item[0]; - change = dapm_kcontrol_set_value(kcontrol, value); - if (change) - ret = soc_dapm_mux_update_power(card, kcontrol, value, e); - - mutex_unlock(&card->dapm_mutex); - - if (ret > 0) - soc_dpcm_runtime_update(card); - - return change; -} -EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt); - /** * snd_soc_dapm_info_pin_switch - Info for a pin switch * @@ -3183,7 +3131,6 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, w->power_check = dapm_generic_check_power; break; case snd_soc_dapm_mux: - case snd_soc_dapm_virt_mux: w->power_check = dapm_generic_check_power; break; case snd_soc_dapm_dai_out: -- cgit v1.2.3 From 234c0b8fb0db790aaebec07d1d190e789d8ec7b9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Feb 2014 08:31:12 +0100 Subject: ASoC: dapm: Break dapm_set_path_status() appart There are three different completely independent code paths in dapm_set_path_status(). One of them is never used at all and the other two (one for mixers, one for MUXs) have their distincive callsites that always go onto the same path. Breaking the function into two parts allows us to reduce the code size and in the MUX case also do some optimizations to avoid having to calcualte the selected item for each item again. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 133 +++++++++++++++++---------------------------------- 1 file changed, 44 insertions(+), 89 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c07c7fb7593a..3651a37bb2c7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -495,93 +495,6 @@ out: return ret; } -/* set up initial codec paths */ -static void dapm_set_path_status(struct snd_soc_dapm_widget *w, - struct snd_soc_dapm_path *p, int i) -{ - switch (w->id) { - case snd_soc_dapm_switch: - case snd_soc_dapm_mixer: - case snd_soc_dapm_mixer_named_ctl: { - unsigned int val; - struct soc_mixer_control *mc = (struct soc_mixer_control *) - w->kcontrol_news[i].private_value; - int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - - if (reg != SND_SOC_NOPM) { - soc_widget_read(w, reg, &val); - val = (val >> shift) & mask; - if (invert) - val = max - val; - p->connect = !!val; - } else { - p->connect = 0; - } - - } - break; - case snd_soc_dapm_mux: { - struct soc_enum *e = (struct soc_enum *) - w->kcontrol_news[i].private_value; - unsigned int val, item; - - if (e->reg != SND_SOC_NOPM) { - soc_widget_read(w, e->reg, &val); - val = (val >> e->shift_l) & e->mask; - item = snd_soc_enum_val_to_item(e, val); - } else { - /* since a virtual mux has no backing registers to - * decide which path to connect, it will try to match - * with the first enumeration. This is to ensure - * that the default mux choice (the first) will be - * correctly powered up during initialization. - */ - item = 0; - } - - if (item < e->items && !strcmp(p->name, e->texts[item])) - p->connect = 1; - else - p->connect = 0; - } - break; - /* does not affect routing - always connected */ - case snd_soc_dapm_pga: - case snd_soc_dapm_out_drv: - case snd_soc_dapm_output: - case snd_soc_dapm_adc: - case snd_soc_dapm_input: - case snd_soc_dapm_siggen: - case snd_soc_dapm_dac: - case snd_soc_dapm_micbias: - case snd_soc_dapm_vmid: - case snd_soc_dapm_supply: - case snd_soc_dapm_regulator_supply: - case snd_soc_dapm_clock_supply: - case snd_soc_dapm_aif_in: - case snd_soc_dapm_aif_out: - case snd_soc_dapm_dai_in: - case snd_soc_dapm_dai_out: - case snd_soc_dapm_hp: - case snd_soc_dapm_mic: - case snd_soc_dapm_spk: - case snd_soc_dapm_line: - case snd_soc_dapm_dai_link: - case snd_soc_dapm_kcontrol: - p->connect = 1; - break; - /* does affect routing - dynamically connected */ - case snd_soc_dapm_pre: - case snd_soc_dapm_post: - p->connect = 0; - break; - } -} - /* connect mux widget to its interconnecting audio paths */ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, @@ -589,15 +502,33 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, const struct snd_kcontrol_new *kcontrol) { struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int val, item; int i; + if (e->reg != SND_SOC_NOPM) { + soc_widget_read(dest, e->reg, &val); + val = (val >> e->shift_l) & e->mask; + item = snd_soc_enum_val_to_item(e, val); + } else { + /* since a virtual mux has no backing registers to + * decide which path to connect, it will try to match + * with the first enumeration. This is to ensure + * that the default mux choice (the first) will be + * correctly powered up during initialization. + */ + item = 0; + } + for (i = 0; i < e->items; i++) { if (!(strcmp(control_name, e->texts[i]))) { list_add(&path->list, &dapm->card->paths); list_add(&path->list_sink, &dest->sources); list_add(&path->list_source, &src->sinks); path->name = (char*)e->texts[i]; - dapm_set_path_status(dest, path, 0); + if (i == item) + path->connect = 1; + else + path->connect = 0; return 0; } } @@ -605,6 +536,30 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, return -ENODEV; } +/* set up initial codec paths */ +static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, + struct snd_soc_dapm_path *p, int i) +{ + struct soc_mixer_control *mc = (struct soc_mixer_control *) + w->kcontrol_news[i].private_value; + unsigned int reg = mc->reg; + unsigned int shift = mc->shift; + unsigned int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + unsigned int val; + + if (reg != SND_SOC_NOPM) { + soc_widget_read(w, reg, &val); + val = (val >> shift) & mask; + if (invert) + val = max - val; + p->connect = !!val; + } else { + p->connect = 0; + } +} + /* connect mixer widget to its interconnecting audio paths */ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, @@ -619,7 +574,7 @@ static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, list_add(&path->list_sink, &dest->sources); list_add(&path->list_source, &src->sinks); path->name = dest->kcontrol_news[i].name; - dapm_set_path_status(dest, path, i); + dapm_set_mixer_path_status(dest, path, i); return 0; } } -- cgit v1.2.3 From 498480731e232d7c9a96a338924b5a275121e091 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:14:33 -0800 Subject: ASoC: rsnd: move priv member settings to upper side There is no big meaning, but preparation for platform dai support Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f316a663e4d3..a8e6aa6cb334 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -594,6 +594,10 @@ static int rsnd_dai_probe(struct platform_device *pdev, return -ENOMEM; } + priv->dai_nr = dai_nr; + priv->daidrv = drv; + priv->rdai = rdai; + for (i = 0; i < dai_nr; i++) { pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1); @@ -630,10 +634,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, cmod ? "capture" : " -- "); } - priv->dai_nr = dai_nr; - priv->daidrv = drv; - priv->rdai = rdai; - return 0; } -- cgit v1.2.3 From d870a91e9d0eae524ac2da7cbdc7e399a71b86c4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:14:41 -0800 Subject: ASoC: rsnd: move rsnd_mod_call() macro core.c is the only user of rsnd_mod_call() macro. Move it to core.c from rsnd.h Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 34 ++++++++++++++++++++++++---------- sound/soc/sh/rcar/rsnd.h | 13 ------------- 2 files changed, 24 insertions(+), 23 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index a8e6aa6cb334..5f6d9fef23d1 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -291,16 +291,30 @@ void rsnd_dma_quit(struct rsnd_priv *priv, /* * rsnd_dai functions */ -#define rsnd_dai_call(rdai, io, fn) \ -({ \ - struct rsnd_mod *mod, *n; \ - int ret = 0; \ - for_each_rsnd_mod(mod, n, io) { \ - ret = rsnd_mod_call(mod, fn, rdai, io); \ - if (ret < 0) \ - break; \ - } \ - ret; \ +#define __rsnd_mod_call(mod, func, rdai, io) \ +({ \ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ + struct device *dev = rsnd_priv_to_dev(priv); \ + dev_dbg(dev, "%s [%d] %s\n", \ + rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ + (mod)->ops->func(mod, rdai, io); \ +}) + +#define rsnd_mod_call(mod, func, rdai, io) \ + (!(mod) ? -ENODEV : \ + !((mod)->ops->func) ? 0 : \ + __rsnd_mod_call(mod, func, (rdai), (io))) + +#define rsnd_dai_call(rdai, io, fn) \ +({ \ + struct rsnd_mod *mod, *n; \ + int ret = 0; \ + for_each_rsnd_mod(mod, n, (io)) { \ + ret = rsnd_mod_call(mod, fn, (rdai), (io)); \ + if (ret < 0) \ + break; \ + } \ + ret; \ }) int rsnd_dai_connect(struct rsnd_dai *rdai, diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index d4093907dfd8..fb1e0cee08b6 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -169,19 +169,6 @@ struct rsnd_mod { #define rsnd_mod_id(mod) ((mod)->id) #define for_each_rsnd_mod(pos, n, io) \ list_for_each_entry_safe(pos, n, &(io)->head, list) -#define __rsnd_mod_call(mod, func, rdai, io) \ -({ \ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ - struct device *dev = rsnd_priv_to_dev(priv); \ - dev_dbg(dev, "%s-%d-%s\n", \ - rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ - (mod)->ops->func(mod, rdai, io); \ -}) - -#define rsnd_mod_call(mod, func, rdai, io) \ - (!(mod) ? -ENODEV : \ - !((mod)->ops->func) ? 0 : \ - __rsnd_mod_call(mod, func, rdai, io)) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, -- cgit v1.2.3 From 5da39cf30454bbf3e92f56935e7d137e5bd2c830 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:15:00 -0800 Subject: ASoC: rsnd: remove verbose function parameter priv has rcar_snd_info pointer. having priv and info in same time is verbose. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 1 - sound/soc/sh/rcar/core.c | 11 +++++------ sound/soc/sh/rcar/gen.c | 7 ++----- sound/soc/sh/rcar/rsnd.h | 5 +---- sound/soc/sh/rcar/scu.c | 2 +- sound/soc/sh/rcar/ssi.c | 2 +- 6 files changed, 10 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index af9e4407aa89..69d9394f3697 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -391,7 +391,6 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) } int rsnd_adg_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct rsnd_adg *adg; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 5f6d9fef23d1..b2370f68e645 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -577,7 +577,6 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { }; static int rsnd_dai_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct snd_soc_dai_driver *drv; @@ -773,23 +772,23 @@ static int rsnd_probe(struct platform_device *pdev) /* * init each module */ - ret = rsnd_gen_probe(pdev, info, priv); + ret = rsnd_gen_probe(pdev, priv); if (ret) return ret; - ret = rsnd_ssi_probe(pdev, info, priv); + ret = rsnd_ssi_probe(pdev, priv); if (ret) return ret; - ret = rsnd_scu_probe(pdev, info, priv); + ret = rsnd_scu_probe(pdev, priv); if (ret) return ret; - ret = rsnd_adg_probe(pdev, info, priv); + ret = rsnd_adg_probe(pdev, priv); if (ret) return ret; - ret = rsnd_dai_probe(pdev, info, priv); + ret = rsnd_dai_probe(pdev, priv); if (ret) return ret; diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 0a43b906ffdf..bcb98f4be831 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -276,7 +276,6 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) } static int rsnd_gen2_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -374,7 +373,6 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) } static int rsnd_gen1_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -419,7 +417,6 @@ static int rsnd_gen1_probe(struct platform_device *pdev, * Gen */ int rsnd_gen_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -436,9 +433,9 @@ int rsnd_gen_probe(struct platform_device *pdev, ret = -ENODEV; if (rsnd_is_gen1(priv)) - ret = rsnd_gen1_probe(pdev, info, priv); + ret = rsnd_gen1_probe(pdev, priv); else if (rsnd_is_gen2(priv)) - ret = rsnd_gen2_probe(pdev, info, priv); + ret = rsnd_gen2_probe(pdev, priv); if (ret < 0) dev_err(dev, "unknown generation R-Car sound device\n"); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index fb1e0cee08b6..8ac28acc7086 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -226,7 +226,6 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); * R-Car Gen1/Gen2 */ int rsnd_gen_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_gen_remove(struct platform_device *pdev, struct rsnd_priv *priv); @@ -248,7 +247,6 @@ void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); int rsnd_adg_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_adg_remove(struct platform_device *pdev, struct rsnd_priv *priv); @@ -305,6 +303,7 @@ struct rsnd_priv { }; #define rsnd_priv_to_dev(priv) ((priv)->dev) +#define rsnd_priv_to_info(priv) ((priv)->info) #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) @@ -312,7 +311,6 @@ struct rsnd_priv { * R-Car SCU */ int rsnd_scu_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv); @@ -327,7 +325,6 @@ unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, * R-Car SSI */ int rsnd_ssi_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_ssi_remove(struct platform_device *pdev, struct rsnd_priv *priv); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 3984d4b4f2df..82d8b20a6ffb 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -604,9 +604,9 @@ struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) } int rsnd_scu_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_scu *scu; struct rsnd_mod_ops *ops; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index d3371d798d54..2460c9f564de 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -511,9 +511,9 @@ static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *s } int rsnd_ssi_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_ssi_platform_info *pinfo; struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod_ops *ops; -- cgit v1.2.3 From 98455ed5ddbfbcbcd0adb300c6cb1964ed0a6931 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:15:07 -0800 Subject: ASoC: rsnd: remove verbose debug message from scu/ssi scu/ssi probe() already have more detail debug message. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 1 - sound/soc/sh/rcar/ssi.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 82d8b20a6ffb..882e837d39d1 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -663,7 +663,6 @@ int rsnd_scu_probe(struct platform_device *pdev, dev_dbg(dev, "SCU%d probed\n", i); } - dev_dbg(dev, "scu probed\n"); return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 2460c9f564de..38a62a883b83 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -589,8 +589,6 @@ int rsnd_ssi_probe(struct platform_device *pdev, rsnd_ssi_parent_clk_setup(priv, ssi); } - dev_dbg(dev, "ssi probed\n"); - return 0; } -- cgit v1.2.3 From ecba9e724c5775aebd3a28e831643160c7146e83 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:15:18 -0800 Subject: ASoC: rsnd: unify rdai naming struct rsnd_dai is called as "rdai", but its size has been called as "dai_nr". Unify these as "rdai" Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 8 ++++---- sound/soc/sh/rcar/rsnd.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index b2370f68e645..f0745af316be 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -352,7 +352,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) { int id = rdai - priv->rdai; - if ((id < 0) || (id >= rsnd_dai_nr(priv))) + if ((id < 0) || (id >= rsnd_rdai_nr(priv))) return -EINVAL; return id; @@ -360,7 +360,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id) { - if ((id < 0) || (id >= rsnd_dai_nr(priv))) + if ((id < 0) || (id >= rsnd_rdai_nr(priv))) return NULL; return priv->rdai + id; @@ -607,7 +607,7 @@ static int rsnd_dai_probe(struct platform_device *pdev, return -ENOMEM; } - priv->dai_nr = dai_nr; + priv->rdai_nr = dai_nr; priv->daidrv = drv; priv->rdai = rdai; @@ -802,7 +802,7 @@ static int rsnd_probe(struct platform_device *pdev) } ret = snd_soc_register_component(dev, &rsnd_soc_component, - priv->daidrv, rsnd_dai_nr(priv)); + priv->daidrv, rsnd_rdai_nr(priv)); if (ret < 0) { dev_err(dev, "cannot snd dai register\n"); goto exit_snd_soc; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 8ac28acc7086..3962a50977e5 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -202,10 +202,10 @@ struct rsnd_dai { unsigned int data_alignment:1; }; -#define rsnd_dai_nr(priv) ((priv)->dai_nr) +#define rsnd_rdai_nr(priv) ((priv)->rdai_nr) #define for_each_rsnd_dai(rdai, priv, i) \ for (i = 0; \ - (i < rsnd_dai_nr(priv)) && \ + (i < rsnd_rdai_nr(priv)) && \ ((rdai) = rsnd_dai_get(priv, i)); \ i++) @@ -299,7 +299,7 @@ struct rsnd_priv { */ struct snd_soc_dai_driver *daidrv; struct rsnd_dai *rdai; - int dai_nr; + int rdai_nr; }; #define rsnd_priv_to_dev(priv) ((priv)->dev) -- cgit v1.2.3 From 61e7fe2577479a1f2650c3fe41c6c842797dddf6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 16:17:02 +0100 Subject: ASoC: neo1973_wm8753: Post gta01 support removal cleanup With GTA01 support gone from the driver there is no need to keep a separate initilization routine for the GTA02 specific bits. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/samsung/neo1973_wm8753.c | 116 ++++++++++++------------------------- 1 file changed, 37 insertions(+), 79 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 98a04c11202d..0125d9d5fbe7 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -192,44 +192,6 @@ static struct snd_soc_ops neo1973_voice_ops = { .hw_free = neo1973_voice_hw_free, }; -/* Shared routes and controls */ - -static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { - SND_SOC_DAPM_LINE("GSM Line Out", NULL), - SND_SOC_DAPM_LINE("GSM Line In", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("Handset Mic", NULL), -}; - -static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { - /* Connections to the GSM Module */ - {"GSM Line Out", NULL, "MONO1"}, - {"GSM Line Out", NULL, "MONO2"}, - {"RXP", NULL, "GSM Line In"}, - {"RXN", NULL, "GSM Line In"}, - - /* Connections to Headset */ - {"MIC1", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Headset Mic"}, - - /* Call Mic */ - {"MIC2", NULL, "Mic Bias"}, - {"MIC2N", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Handset Mic"}, - - /* Connect the ALC pins */ - {"ACIN", NULL, "ACOP"}, -}; - -static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { - SOC_DAPM_PIN_SWITCH("GSM Line Out"), - SOC_DAPM_PIN_SWITCH("GSM Line In"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Handset Mic"), -}; - -/* GTA02 specific routes and controls */ - static int gta02_speaker_enabled; static int lm4853_set_spk(struct snd_kcontrol *kcontrol, @@ -257,7 +219,34 @@ static int lm4853_event(struct snd_soc_dapm_widget *w, return 0; } -static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { +static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { + SND_SOC_DAPM_LINE("GSM Line Out", NULL), + SND_SOC_DAPM_LINE("GSM Line In", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Handset Mic", NULL), + SND_SOC_DAPM_SPK("Handset Spk", NULL), + SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), +}; + +static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { + /* Connections to the GSM Module */ + {"GSM Line Out", NULL, "MONO1"}, + {"GSM Line Out", NULL, "MONO2"}, + {"RXP", NULL, "GSM Line In"}, + {"RXN", NULL, "GSM Line In"}, + + /* Connections to Headset */ + {"MIC1", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "Headset Mic"}, + + /* Call Mic */ + {"MIC2", NULL, "Mic Bias"}, + {"MIC2N", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "Handset Mic"}, + + /* Connect the ALC pins */ + {"ACIN", NULL, "ACOP"}, + /* Connections to the amp */ {"Stereo Out", NULL, "LOUT1"}, {"Stereo Out", NULL, "ROUT1"}, @@ -267,7 +256,11 @@ static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { {"Handset Spk", NULL, "ROUT2"}, }; -static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { +static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { + SOC_DAPM_PIN_SWITCH("GSM Line Out"), + SOC_DAPM_PIN_SWITCH("GSM Line In"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Handset Mic"), SOC_DAPM_PIN_SWITCH("Handset Spk"), SOC_DAPM_PIN_SWITCH("Stereo Out"), @@ -276,39 +269,6 @@ static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { lm4853_set_spk), }; -static const struct snd_soc_dapm_widget neo1973_gta02_wm8753_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Handset Spk", NULL), - SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), -}; - -static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - ret = snd_soc_dapm_new_controls(dapm, neo1973_gta02_wm8753_dapm_widgets, - ARRAY_SIZE(neo1973_gta02_wm8753_dapm_widgets)); - if (ret) - return ret; - - ret = snd_soc_dapm_add_routes(dapm, neo1973_gta02_routes, - ARRAY_SIZE(neo1973_gta02_routes)); - if (ret) - return ret; - - ret = snd_soc_add_card_controls(codec->card, neo1973_gta02_wm8753_controls, - ARRAY_SIZE(neo1973_gta02_wm8753_controls)); - if (ret) - return ret; - - snd_soc_dapm_disable_pin(dapm, "Stereo Out"); - snd_soc_dapm_disable_pin(dapm, "Handset Spk"); - snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); - snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); - - return 0; -} - static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; @@ -344,18 +304,16 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_disable_pin(dapm, "GSM Line In"); snd_soc_dapm_disable_pin(dapm, "Headset Mic"); snd_soc_dapm_disable_pin(dapm, "Handset Mic"); + snd_soc_dapm_disable_pin(dapm, "Stereo Out"); + snd_soc_dapm_disable_pin(dapm, "Handset Spk"); /* allow audio paths from the GSM modem to run during suspend */ snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out"); snd_soc_dapm_ignore_suspend(dapm, "GSM Line In"); snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); - - if (machine_is_neo1973_gta02()) { - ret = neo1973_gta02_wm8753_init(codec); - if (ret) - return ret; - } + snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); + snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); return 0; } -- cgit v1.2.3 From 4f07c9ccdf92155dd8a216eee262f2954a6d69a2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 16:17:03 +0100 Subject: ASoC: neo1973_wm8753: Convert to table based setup Use table based setup to register the controls and DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/samsung/neo1973_wm8753.c | 60 +++++++++++++++----------------------- 1 file changed, 24 insertions(+), 36 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 0125d9d5fbe7..b0800337b79e 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -272,48 +272,29 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; + struct snd_soc_card *card = rtd->card; /* set up NC codec pins */ - snd_soc_dapm_nc_pin(dapm, "OUT3"); - snd_soc_dapm_nc_pin(dapm, "OUT4"); - snd_soc_dapm_nc_pin(dapm, "LINE1"); - snd_soc_dapm_nc_pin(dapm, "LINE2"); - - /* Add neo1973 specific widgets */ - ret = snd_soc_dapm_new_controls(dapm, neo1973_wm8753_dapm_widgets, - ARRAY_SIZE(neo1973_wm8753_dapm_widgets)); - if (ret) - return ret; - - /* add neo1973 specific controls */ - ret = snd_soc_add_card_controls(rtd->card, neo1973_wm8753_controls, - ARRAY_SIZE(neo1973_wm8753_controls)); - if (ret) - return ret; - - /* set up neo1973 specific audio routes */ - ret = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes, - ARRAY_SIZE(neo1973_wm8753_routes)); - if (ret) - return ret; + snd_soc_dapm_nc_pin(&codec->dapm, "OUT3"); + snd_soc_dapm_nc_pin(&codec->dapm, "OUT4"); + snd_soc_dapm_nc_pin(&codec->dapm, "LINE1"); + snd_soc_dapm_nc_pin(&codec->dapm, "LINE2"); /* set endpoints to default off mode */ - snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); - snd_soc_dapm_disable_pin(dapm, "GSM Line In"); - snd_soc_dapm_disable_pin(dapm, "Headset Mic"); - snd_soc_dapm_disable_pin(dapm, "Handset Mic"); - snd_soc_dapm_disable_pin(dapm, "Stereo Out"); - snd_soc_dapm_disable_pin(dapm, "Handset Spk"); + snd_soc_dapm_disable_pin(&card->dapm, "GSM Line Out"); + snd_soc_dapm_disable_pin(&card->dapm, "GSM Line In"); + snd_soc_dapm_disable_pin(&card->dapm, "Headset Mic"); + snd_soc_dapm_disable_pin(&card->dapm, "Handset Mic"); + snd_soc_dapm_disable_pin(&card->dapm, "Stereo Out"); + snd_soc_dapm_disable_pin(&card->dapm, "Handset Spk"); /* allow audio paths from the GSM modem to run during suspend */ - snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out"); - snd_soc_dapm_ignore_suspend(dapm, "GSM Line In"); - snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); - snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); - snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); - snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); + snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line Out"); + snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line In"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Mic"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Stereo Out"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Spk"); return 0; } @@ -367,6 +348,13 @@ static struct snd_soc_card neo1973 = { .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs), .codec_conf = neo1973_codec_conf, .num_configs = ARRAY_SIZE(neo1973_codec_conf), + + .controls = neo1973_wm8753_controls, + .num_controls = ARRAY_SIZE(neo1973_wm8753_controls), + .dapm_widgets = neo1973_wm8753_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(neo1973_wm8753_dapm_widgets), + .dapm_routes = neo1973_wm8753_routes, + .num_dapm_routes = ARRAY_SIZE(neo1973_wm8753_routes), }; static struct platform_device *neo1973_snd_device; -- cgit v1.2.3 From e14de47ac95fb25818294325cd77d520c90c6ced Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:13 +0100 Subject: ASoC: pxa: Pass correct DAPM context to {corgi,poodle,spitz}_ext_control When calling {corgi,poodle,spitz}_ext_control() from the startup callback we pass the CODEC's DAPM context instead of the card's DAPM context. This is not a problem per se since all the DAPM functions in ext_control() fallback to widgets from other DAPM contexts, but passing the card's context is more consistent. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/corgi.c | 3 +-- sound/soc/pxa/poodle.c | 3 +-- sound/soc/pxa/spitz.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index b51f88002e62..916ff63d85d0 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -97,10 +97,9 @@ static void corgi_ext_control(struct snd_soc_dapm_context *dapm) static int corgi_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - corgi_ext_control(&codec->dapm); + corgi_ext_control(&rtd->card->dapm); return 0; } diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 27c6c03bc5d7..c6bdc6c0eff6 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -74,10 +74,9 @@ static void poodle_ext_control(struct snd_soc_dapm_context *dapm) static int poodle_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - poodle_ext_control(&codec->dapm); + poodle_ext_control(&rtd->card->dapm); return 0; } diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 0728c1eb780c..d1b6bf9c8583 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -106,10 +106,9 @@ static void spitz_ext_control(struct snd_soc_dapm_context *dapm) static int spitz_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - spitz_ext_control(&codec->dapm); + spitz_ext_control(&rtd->card->dapm); return 0; } -- cgit v1.2.3 From 23d8f2253c5ebe975465a61dd416a35b5ebda4b0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:14 +0100 Subject: ASoC: pxa: e740_wm9705: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/e740_wm9705.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 44b5c09d296b..c29fedab2f49 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -103,11 +103,6 @@ static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "PCBEEP"); snd_soc_dapm_nc_pin(dapm, "MIC2"); - snd_soc_dapm_new_controls(dapm, e740_dapm_widgets, - ARRAY_SIZE(e740_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -136,6 +131,11 @@ static struct snd_soc_card e740 = { .owner = THIS_MODULE, .dai_link = e740_dai, .num_links = ARRAY_SIZE(e740_dai), + + .dapm_widgets = e740_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e740_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e740_audio_gpios[] = { -- cgit v1.2.3 From 98308c825ba856796bf52b3c6d6955e62f1fc45c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:15 +0100 Subject: ASoC: pxa: e750_wm9705: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/e750_wm9705.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index c34e447eb991..ee36aba88063 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -85,11 +85,6 @@ static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "PCBEEP"); snd_soc_dapm_nc_pin(dapm, "MIC2"); - snd_soc_dapm_new_controls(dapm, e750_dapm_widgets, - ARRAY_SIZE(e750_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -119,6 +114,11 @@ static struct snd_soc_card e750 = { .owner = THIS_MODULE, .dai_link = e750_dai, .num_links = ARRAY_SIZE(e750_dai), + + .dapm_widgets = e750_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e750_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e750_audio_gpios[] = { -- cgit v1.2.3 From 1bdd301f791e047ed36c18656890c0001f8ce5a3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:16 +0100 Subject: ASoC: pxa: e800_wm9712: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/e800_wm9712.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 3137f800b43f..24c2078ce70b 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -71,19 +71,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MIC2", NULL, "Mic (Internal2)"}, }; -static int e800_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_new_controls(dapm, e800_dapm_widgets, - ARRAY_SIZE(e800_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - return 0; -} - static struct snd_soc_dai_link e800_dai[] = { { .name = "AC97", @@ -92,7 +79,6 @@ static struct snd_soc_dai_link e800_dai[] = { .codec_dai_name = "wm9712-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm9712-codec", - .init = e800_ac97_init, }, { .name = "AC97 Aux", @@ -109,6 +95,11 @@ static struct snd_soc_card e800 = { .owner = THIS_MODULE, .dai_link = e800_dai, .num_links = ARRAY_SIZE(e800_dai), + + .dapm_widgets = e800_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e800_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e800_audio_gpios[] = { -- cgit v1.2.3 From f6b2a04590bb3f7323a45b183956e63574d1f14b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:18 +0100 Subject: ASoC: pxa: mioa701_wm9713: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Also remove the snd_soc_dapm_enable_pin() calls, since pins are enabled by default and there are no matching snd_soc_dapm_disable_pin() calls. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/mioa701_wm9713.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 160c5245448f..595eee341e90 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -127,16 +127,8 @@ static const struct snd_soc_dapm_route audio_map[] = { static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; unsigned short reg; - /* Add mioa701 specific widgets */ - snd_soc_dapm_new_controls(dapm, mioa701_dapm_widgets, - ARRAY_SIZE(mioa701_dapm_widgets)); - - /* Set up mioa701 specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - /* Prepare GPIO8 for rear speaker amplifier */ reg = codec->driver->read(codec, AC97_GPIO_CFG); codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100); @@ -145,12 +137,6 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) reg = codec->driver->read(codec, AC97_3D_CONTROL); codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000); - snd_soc_dapm_enable_pin(dapm, "Front Speaker"); - snd_soc_dapm_enable_pin(dapm, "Rear Speaker"); - snd_soc_dapm_enable_pin(dapm, "Front Mic"); - snd_soc_dapm_enable_pin(dapm, "GSM Line In"); - snd_soc_dapm_enable_pin(dapm, "GSM Line Out"); - return 0; } @@ -183,6 +169,11 @@ static struct snd_soc_card mioa701 = { .owner = THIS_MODULE, .dai_link = mioa701_dai, .num_links = ARRAY_SIZE(mioa701_dai), + + .dapm_widgets = mioa701_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mioa701_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int mioa701_wm9713_probe(struct platform_device *pdev) -- cgit v1.2.3 From a9576cbbbafa2c687121638dadebfb136562a522 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:20 +0100 Subject: ASoC: pxa: zylonite: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Also drop the two snd_soc_dapm_enable_pin() since pins are enabled by default and there is no matching snd_soc_dapm_disable_pin() in the driver. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/zylonite.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index db8aadf8932d..23bf991e95d5 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -71,22 +71,10 @@ static const struct snd_soc_dapm_route audio_map[] = { static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - if (clk_pout) snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, clk_get_rate(pout), 0); - snd_soc_dapm_new_controls(dapm, zylonite_dapm_widgets, - ARRAY_SIZE(zylonite_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - /* Static setup for now */ - snd_soc_dapm_enable_pin(dapm, "Headphone"); - snd_soc_dapm_enable_pin(dapm, "Headset Earpiece"); - return 0; } @@ -256,6 +244,11 @@ static struct snd_soc_card zylonite = { .resume_pre = &zylonite_resume_pre, .dai_link = zylonite_dai, .num_links = ARRAY_SIZE(zylonite_dai), + + .dapm_widgets = zylonite_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(zylonite_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *zylonite_snd_ac97_device; -- cgit v1.2.3 From 66f232908de2f7393a1f7c4c300f73534af57f07 Mon Sep 17 00:00:00 2001 From: Denis Carikli Date: Wed, 15 Jan 2014 18:23:25 +0100 Subject: ASoC: eukrea-tlv320: Add DT support. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Eric Bénard Cc: Ian Campbell Cc: Liam Girdwood Cc: Mark Brown Cc: Mark Rutland Cc: Pawel Moll Cc: Rob Herring Cc: alsa-devel@alsa-project.org Cc: devicetree@vger.kernel.org Signed-off-by: Denis Carikli Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/eukrea-tlv320.txt | 21 ++++ sound/soc/fsl/Kconfig | 5 +- sound/soc/fsl/eukrea-tlv320.c | 108 ++++++++++++++++++--- 3 files changed, 121 insertions(+), 13 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/eukrea-tlv320.txt (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt b/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt new file mode 100644 index 000000000000..0d7985c864af --- /dev/null +++ b/Documentation/devicetree/bindings/sound/eukrea-tlv320.txt @@ -0,0 +1,21 @@ +Audio complex for Eukrea boards with tlv320aic23 codec. + +Required properties: +- compatible : "eukrea,asoc-tlv320" +- eukrea,model : The user-visible name of this sound complex. +- ssi-controller : The phandle of the SSI controller. +- fsl,mux-int-port : The internal port of the i.MX audio muxer (AUDMUX). +- fsl,mux-ext-port : The external port of the i.MX audio muxer. + +Note: The AUDMUX port numbering should start at 1, which is consistent with +hardware manual. + +Example: + + sound { + compatible = "eukrea,asoc-tlv320"; + eukrea,model = "imx51-eukrea-tlv320aic23"; + ssi-controller = <&ssi2>; + fsl,mux-int-port = <2>; + fsl,mux-ext-port = <3>; + }; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 07f8f141727d..b8f8703e2b46 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -168,12 +168,15 @@ config SND_SOC_EUKREA_TLV320 depends on MACH_EUKREA_MBIMX27_BASEBOARD \ || MACH_EUKREA_MBIMXSD25_BASEBOARD \ || MACH_EUKREA_MBIMXSD35_BASEBOARD \ - || MACH_EUKREA_MBIMXSD51_BASEBOARD + || MACH_EUKREA_MBIMXSD51_BASEBOARD \ + || (OF && ARM) depends on I2C select SND_SOC_TLV320AIC23 select SND_SOC_IMX_PCM_FIQ select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_SSI + select SND_SOC_FSL_SSI + select SND_SOC_IMX_PCM_DMA help Enable I2S based access to the TLV320AIC23B codec attached to the SSI interface diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 5983740be123..eb093d5b85c4 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -15,8 +15,11 @@ * */ +#include #include #include +#include +#include #include #include #include @@ -26,6 +29,7 @@ #include "../codecs/tlv320aic23.h" #include "imx-ssi.h" +#include "fsl_ssi.h" #include "imx-audmux.h" #define CODEC_CLOCK 12000000 @@ -41,7 +45,8 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret) { + /* fsl_ssi lacks the set_fmt ops. */ + if (ret && ret != -ENOTSUPP) { dev_err(cpu_dai->dev, "Failed to set the cpu dai format.\n"); return ret; @@ -63,11 +68,13 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, "Failed to set the codec sysclk.\n"); return ret; } + snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN); - if (ret) { + /* fsl_ssi lacks the set_sysclk ops */ + if (ret && ret != -EINVAL) { dev_err(cpu_dai->dev, "Can't set the IMX_SSP_SYS_CLK CPU system clock.\n"); return ret; @@ -84,14 +91,10 @@ static struct snd_soc_dai_link eukrea_tlv320_dai = { .name = "tlv320aic23", .stream_name = "TLV320AIC23", .codec_dai_name = "tlv320aic23-hifi", - .platform_name = "imx-ssi.0", - .codec_name = "tlv320aic23-codec.0-001a", - .cpu_dai_name = "imx-ssi.0", .ops = &eukrea_tlv320_snd_ops, }; static struct snd_soc_card eukrea_tlv320 = { - .name = "cpuimx-audio", .owner = THIS_MODULE, .dai_link = &eukrea_tlv320_dai, .num_links = 1, @@ -101,8 +104,65 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) { int ret; int int_port = 0, ext_port; + struct device_node *np = pdev->dev.of_node; + struct device_node *ssi_np, *codec_np; - if (machine_is_eukrea_cpuimx27()) { + eukrea_tlv320.dev = &pdev->dev; + if (np) { + ret = snd_soc_of_parse_card_name(&eukrea_tlv320, + "eukrea,model"); + if (ret) { + dev_err(&pdev->dev, + "eukrea,model node missing or invalid.\n"); + goto err; + } + + ssi_np = of_parse_phandle(pdev->dev.of_node, + "ssi-controller", 0); + if (!ssi_np) { + dev_err(&pdev->dev, + "ssi-controller missing or invalid.\n"); + ret = -ENODEV; + goto err; + } + + codec_np = of_parse_phandle(ssi_np, "codec-handle", 0); + if (codec_np) + eukrea_tlv320_dai.codec_of_node = codec_np; + else + dev_err(&pdev->dev, "codec-handle node missing or invalid.\n"); + + ret = of_property_read_u32(np, "fsl,mux-int-port", &int_port); + if (ret) { + dev_err(&pdev->dev, + "fsl,mux-int-port node missing or invalid.\n"); + return ret; + } + ret = of_property_read_u32(np, "fsl,mux-ext-port", &ext_port); + if (ret) { + dev_err(&pdev->dev, + "fsl,mux-ext-port node missing or invalid.\n"); + return ret; + } + + /* + * The port numbering in the hardware manual starts at 1, while + * the audmux API expects it starts at 0. + */ + int_port--; + ext_port--; + + eukrea_tlv320_dai.cpu_of_node = ssi_np; + eukrea_tlv320_dai.platform_of_node = ssi_np; + } else { + eukrea_tlv320_dai.cpu_dai_name = "imx-ssi.0"; + eukrea_tlv320_dai.platform_name = "imx-ssi.0"; + eukrea_tlv320_dai.codec_name = "tlv320aic23-codec.0-001a"; + eukrea_tlv320.name = "cpuimx-audio"; + } + + if (machine_is_eukrea_cpuimx27() || + of_find_compatible_node(NULL, NULL, "fsl,imx21-audmux")) { imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, IMX_AUDMUX_V1_PCR_SYN | IMX_AUDMUX_V1_PCR_TFSDIR | @@ -119,8 +179,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) ); } else if (machine_is_eukrea_cpuimx25sd() || machine_is_eukrea_cpuimx35sd() || - machine_is_eukrea_cpuimx51sd()) { - ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3; + machine_is_eukrea_cpuimx51sd() || + of_find_compatible_node(NULL, NULL, "fsl,imx31-audmux")) { + if (!np) + ext_port = machine_is_eukrea_cpuimx25sd() ? + 4 : 3; + imx_audmux_v2_configure_port(int_port, IMX_AUDMUX_V2_PTCR_SYN | IMX_AUDMUX_V2_PTCR_TFSDIR | @@ -134,14 +198,27 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) IMX_AUDMUX_V2_PDCR_RXDSEL(int_port) ); } else { - /* return happy. We might run on a totally different machine */ - return 0; + if (np) { + /* The eukrea,asoc-tlv320 driver was explicitely + * requested (through the device tree). + */ + dev_err(&pdev->dev, + "Missing or invalid audmux DT node.\n"); + return -ENODEV; + } else { + /* Return happy. + * We might run on a totally different machine. + */ + return 0; + } } - eukrea_tlv320.dev = &pdev->dev; ret = snd_soc_register_card(&eukrea_tlv320); +err: if (ret) dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + if (np) + of_node_put(ssi_np); return ret; } @@ -153,10 +230,17 @@ static int eukrea_tlv320_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id imx_tlv320_dt_ids[] = { + { .compatible = "eukrea,asoc-tlv320"}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_tlv320_dt_ids); + static struct platform_driver eukrea_tlv320_driver = { .driver = { .name = "eukrea_tlv320", .owner = THIS_MODULE, + .of_match_table = imx_tlv320_dt_ids, }, .probe = eukrea_tlv320_probe, .remove = eukrea_tlv320_remove, -- cgit v1.2.3 From 57996358f4d679b2bc39d4cd15166bb89fc8d981 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 2 Mar 2014 00:04:02 +0800 Subject: ASoC: dapm: Power off all widgets in the snd_soc_dapm_shutdown The widgets generated by the machine driver need to power off too. Signed-off-by: Xiang Xiao Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 4200f96a1483..d856e7c4c631 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4116,7 +4116,7 @@ void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm) } EXPORT_SYMBOL_GPL(snd_soc_dapm_free); -static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) +static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) { struct snd_soc_card *card = dapm->card; struct snd_soc_dapm_widget *w; @@ -4156,12 +4156,12 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) */ void snd_soc_dapm_shutdown(struct snd_soc_card *card) { - struct snd_soc_codec *codec; + struct snd_soc_dapm_context *dapm; - list_for_each_entry(codec, &card->codec_dev_list, card_list) { - soc_dapm_shutdown_codec(&codec->dapm); - if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) - snd_soc_dapm_set_bias_level(&codec->dapm, + list_for_each_entry(dapm, &card->dapm_list, list) { + soc_dapm_shutdown_dapm(dapm); + if (dapm->bias_level == SND_SOC_BIAS_STANDBY) + snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_OFF); } } -- cgit v1.2.3 From 17282ba4310cdad05f172d4dc1ebcb63d0b5de98 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 2 Mar 2014 00:04:03 +0800 Subject: ASoC: dapm: Reorder the bias update sequence The new sequence ensure that dapm_pre_sequence_async work on the card before all codecs and dapm_post_sequence_async work on the card after all codecs. So the machine driver could utilize the determinate sequence to do the gloabl setup and teardown in the right place. Signed-off-by: Xiang Xiao Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d856e7c4c631..77743e51420a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1898,10 +1898,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) trace_snd_soc_dapm_walk_done(card); - /* Run all the bias changes in parallel */ - list_for_each_entry(d, &card->dapm_list, list) - async_schedule_domain(dapm_pre_sequence_async, d, - &async_domain); + /* Run card bias changes at first */ + dapm_pre_sequence_async(&card->dapm, 0); + /* Run other bias changes in parallel */ + list_for_each_entry(d, &card->dapm_list, list) { + if (d != &card->dapm) + async_schedule_domain(dapm_pre_sequence_async, d, + &async_domain); + } async_synchronize_full_domain(&async_domain); list_for_each_entry(w, &down_list, power_list) { @@ -1921,10 +1925,14 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) dapm_seq_run(card, &up_list, event, true); /* Run all the bias changes in parallel */ - list_for_each_entry(d, &card->dapm_list, list) - async_schedule_domain(dapm_post_sequence_async, d, - &async_domain); + list_for_each_entry(d, &card->dapm_list, list) { + if (d != &card->dapm) + async_schedule_domain(dapm_post_sequence_async, d, + &async_domain); + } async_synchronize_full_domain(&async_domain); + /* Run card bias changes at last */ + dapm_post_sequence_async(&card->dapm, 0); /* do we need to notify any clients that DAPM event is complete */ list_for_each_entry(d, &card->dapm_list, list) { @@ -4159,11 +4167,18 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) struct snd_soc_dapm_context *dapm; list_for_each_entry(dapm, &card->dapm_list, list) { - soc_dapm_shutdown_dapm(dapm); - if (dapm->bias_level == SND_SOC_BIAS_STANDBY) - snd_soc_dapm_set_bias_level(dapm, - SND_SOC_BIAS_OFF); + if (dapm != &card->dapm) { + soc_dapm_shutdown_dapm(dapm); + if (dapm->bias_level == SND_SOC_BIAS_STANDBY) + snd_soc_dapm_set_bias_level(dapm, + SND_SOC_BIAS_OFF); + } } + + soc_dapm_shutdown_dapm(&card->dapm); + if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY) + snd_soc_dapm_set_bias_level(&card->dapm, + SND_SOC_BIAS_OFF); } /* Module information */ -- cgit v1.2.3 From 112ad7f28e7ed2e9966ab464274b143c29d3ce15 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Mar 2014 08:17:08 +0100 Subject: ASoC: wm1133-ev1: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/fsl/wm1133-ev1.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/wm1133-ev1.c b/sound/soc/fsl/wm1133-ev1.c index fce63252bdbb..804749a6c61e 100644 --- a/sound/soc/fsl/wm1133-ev1.c +++ b/sound/soc/fsl/wm1133-ev1.c @@ -214,12 +214,6 @@ static int wm1133_ev1_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_new_controls(dapm, wm1133_ev1_widgets, - ARRAY_SIZE(wm1133_ev1_widgets)); - - snd_soc_dapm_add_routes(dapm, wm1133_ev1_map, - ARRAY_SIZE(wm1133_ev1_map)); - /* Headphone jack detection */ snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack); snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), @@ -257,6 +251,11 @@ static struct snd_soc_card wm1133_ev1 = { .owner = THIS_MODULE, .dai_link = &wm1133_ev1_dai, .num_links = 1, + + .dapm_widgets = wm1133_ev1_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm1133_ev1_widgets), + .dapm_routes = wm1133_ev1_map, + .num_dapm_routes = ARRAY_SIZE(wm1133_ev1_map), }; static struct platform_device *wm1133_ev1_snd_device; -- cgit v1.2.3 From 939d9f16994166156fa3d6dfece9c46b92e368e0 Mon Sep 17 00:00:00 2001 From: Nenghua Cao Date: Mon, 3 Mar 2014 19:08:23 +0800 Subject: ASoC: core: fix coccinelle warnings sound/soc/soc-core.c:2708:6-13: WARNING: Assignment of bool to 0/1 sound/soc/soc-core.c:2726:3-10: WARNING: Assignment of bool to 0/1 More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Nenghua Cao Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 393ff069af69..45a1fafdbd7b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2818,7 +2818,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; int err; - bool type_2r = 0; + bool type_2r = false; unsigned int val2 = 0; unsigned int val, val_mask; @@ -2836,7 +2836,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, val |= val2 << rshift; } else { val2 = val2 << shift; - type_2r = 1; + type_2r = true; } } err = snd_soc_update_bits_locked(codec, reg, val_mask, val); -- cgit v1.2.3 From 64895739835c431fbc62dfabbe2267fff552a2f2 Mon Sep 17 00:00:00 2001 From: Nenghua Cao Date: Mon, 3 Mar 2014 19:08:23 +0800 Subject: asoc: soc-core: fix coccinelle warnings sound/soc/soc-core.c:2708:6-13: WARNING: Assignment of bool to 0/1 sound/soc/soc-core.c:2726:3-10: WARNING: Assignment of bool to 0/1 More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Nenghua Cao Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..3477525247c3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2818,7 +2818,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; int err; - bool type_2r = 0; + bool type_2r = false; unsigned int val2 = 0; unsigned int val, val_mask; @@ -2836,7 +2836,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, val |= val2 << rshift; } else { val2 = val2 << shift; - type_2r = 1; + type_2r = true; } } err = snd_soc_update_bits_locked(codec, reg, val_mask, val); -- cgit v1.2.3 From 48b5e1fb883c8c72b50ee1ccd3ee51e4f53f632f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 13:46:44 +0100 Subject: ASoC: wm8753: Remove superfluous 'codec->cache_sync = 1' The wm8763 driver uses regmap for IO which means that codec->cache_sync is not used. The line was added in commit d3398ff ('ASoC: Convert WM8753 to direct regmap API usage'). Presumably this was meant to be regcache_mark_dirty(), but since we already call regcache_mark_dirty() in the core when suspending the CODEC it is safe to just remove the line. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8753.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index be85da93a268..a02e76c248f6 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1440,7 +1440,6 @@ static void wm8753_work(struct work_struct *work) static int wm8753_suspend(struct snd_soc_codec *codec) { wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); - codec->cache_sync = 1; return 0; } -- cgit v1.2.3 From 055bbe2df957343fece60fe1f60553a9c1005217 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 13:45:32 +0100 Subject: ASoC: wm{5102, 5110, 8997}: Replace codec->control_data with arizona->regmap With the ongoing component-ization of the ASoC framework and the continuing migration to using regmap for IO the control_data field of the snd_soc_codec struct will eventually be removed. Prepare the wm5192, wm5110 and wm8997 drivers for this by using arizona->regmap instead of accessing the CODEC's control_data field. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 2 +- sound/soc/codecs/wm5110.c | 2 +- sound/soc/codecs/wm8997.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 293dffcb1d2f..34109050ceed 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -582,7 +582,7 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct arizona *arizona = dev_get_drvdata(codec->dev->parent); - struct regmap *regmap = codec->control_data; + struct regmap *regmap = arizona->regmap; const struct reg_default *patch = NULL; int i, patch_size; diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 4de2bf16dc74..d7bf8848174a 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -136,7 +136,7 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct arizona *arizona = dev_get_drvdata(codec->dev->parent); - struct regmap *regmap = codec->control_data; + struct regmap *regmap = arizona->regmap; const struct reg_default *patch = NULL; int i, patch_size; diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 4e6442ce9a2a..e10f44d7fdb7 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -86,7 +86,7 @@ static int wm8997_sysclk_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct arizona *arizona = dev_get_drvdata(codec->dev->parent); - struct regmap *regmap = codec->control_data; + struct regmap *regmap = arizona->regmap; const struct reg_default *patch = NULL; int i, patch_size; -- cgit v1.2.3 From 9bfed6cf4fa2cd2c5e80431244348b0c5d933cf5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:42:47 -0800 Subject: ASoC: rsnd: run rsnd_path_init() when probe() timing Current rsnd SSIU/SSI/SCU/SRU path is set when playback/capture starts up. But it is meaningless method, since the path is based on platform and can be set in probe() timing. This patch sets the path on probe() timing. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 94 +++++++++++++++++++++++++++++++++++++++--------- sound/soc/sh/rcar/gen.c | 56 ----------------------------- sound/soc/sh/rcar/rsnd.h | 9 ----- 3 files changed, 78 insertions(+), 81 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f0745af316be..96cb78612a7d 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -317,9 +317,9 @@ void rsnd_dma_quit(struct rsnd_priv *priv, ret; \ }) -int rsnd_dai_connect(struct rsnd_dai *rdai, - struct rsnd_mod *mod, - struct rsnd_dai_stream *io) +static int rsnd_dai_connect(struct rsnd_dai *rdai, + struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { if (!mod) return -EIO; @@ -340,7 +340,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, return 0; } -int rsnd_dai_disconnect(struct rsnd_mod *mod) +static int rsnd_dai_disconnect(struct rsnd_mod *mod) { list_del_init(&mod->list); mod->io = NULL; @@ -418,10 +418,6 @@ static int rsnd_dai_stream_init(struct rsnd_dai_stream *io, { struct snd_pcm_runtime *runtime = substream->runtime; - if (!list_empty(&io->head)) - return -EIO; - - INIT_LIST_HEAD(&io->head); io->substream = substream; io->byte_pos = 0; io->period_pos = 0; @@ -476,10 +472,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) goto dai_trigger_end; - ret = rsnd_gen_path_init(priv, rdai, io); - if (ret < 0) - goto dai_trigger_end; - ret = rsnd_dai_call(rdai, io, init); if (ret < 0) goto dai_trigger_end; @@ -497,10 +489,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) goto dai_trigger_end; - ret = rsnd_gen_path_exit(priv, rdai, io); - if (ret < 0) - goto dai_trigger_end; - ret = rsnd_platform_call(priv, dai, stop, ssi_id); if (ret < 0) goto dai_trigger_end; @@ -576,6 +564,70 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { .set_fmt = rsnd_soc_dai_set_fmt, }; +static int rsnd_path_init(struct rsnd_priv *priv, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_mod *mod; + int ret; + int id; + + /* + * Gen1 is created by SRU/SSI, and this SRU is base module of + * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) + * + * Easy image is.. + * Gen1 SRU = Gen2 SCU + SSIU + etc + * + * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is + * using fixed path. + * + * Then, SSI id = SCU id here + */ + /* get SSI's ID */ + mod = rsnd_ssi_mod_get_frm_dai(priv, + rsnd_dai_id(priv, rdai), + rsnd_dai_is_play(rdai, io)); + if (!mod) + return 0; + id = rsnd_mod_id(mod); + ret = 0; + + /* SCU */ + mod = rsnd_scu_mod_get(priv, id); + if (mod) { + ret = rsnd_dai_connect(rdai, mod, io); + if (ret < 0) + return ret; + } + + /* SSI */ + mod = rsnd_ssi_mod_get(priv, id); + if (mod) { + ret = rsnd_dai_connect(rdai, mod, io); + if (ret < 0) + return ret; + } + + return ret; +} + +static int rsnd_path_exit(struct rsnd_priv *priv, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_mod *mod, *n; + int ret = 0; + + /* + * remove all mod from rdai + */ + for_each_rsnd_mod(mod, n, io) + ret |= rsnd_dai_disconnect(mod); + + return ret; +} + static int rsnd_dai_probe(struct platform_device *pdev, struct rsnd_priv *priv) { @@ -634,12 +686,14 @@ static int rsnd_dai_probe(struct platform_device *pdev, drv[i].playback.formats = RSND_FMTS; drv[i].playback.channels_min = 2; drv[i].playback.channels_max = 2; + rsnd_path_init(priv, &rdai[i], &rdai[i].playback); } if (cmod) { drv[i].capture.rates = RSND_RATES; drv[i].capture.formats = RSND_FMTS; drv[i].capture.channels_min = 2; drv[i].capture.channels_max = 2; + rsnd_path_init(priv, &rdai[i], &rdai[i].capture); } dev_dbg(dev, "%s (%s/%s)\n", rdai[i].name, @@ -653,6 +707,14 @@ static int rsnd_dai_probe(struct platform_device *pdev, static void rsnd_dai_remove(struct platform_device *pdev, struct rsnd_priv *priv) { + struct rsnd_dai *rdai; + int i; + + for (i = 0; i < rsnd_rdai_nr(priv); i++) { + rdai = rsnd_dai_get(priv, i); + rsnd_path_exit(priv, rdai, &rdai->playback); + rsnd_path_exit(priv, rdai, &rdai->capture); + } } /* diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index bcb98f4be831..4f2c1d0c6970 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -155,62 +155,6 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, return 0; } -int rsnd_gen_path_init(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod; - int ret; - int id; - - /* - * Gen1 is created by SRU/SSI, and this SRU is base module of - * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) - * - * Easy image is.. - * Gen1 SRU = Gen2 SCU + SSIU + etc - * - * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is - * using fixed path. - * - * Then, SSI id = SCU id here - */ - - /* get SSI's ID */ - mod = rsnd_ssi_mod_get_frm_dai(priv, - rsnd_dai_id(priv, rdai), - rsnd_dai_is_play(rdai, io)); - id = rsnd_mod_id(mod); - - /* SCU */ - mod = rsnd_scu_mod_get(priv, id); - ret = rsnd_dai_connect(rdai, mod, io); - if (ret < 0) - return ret; - - /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); - ret = rsnd_dai_connect(rdai, mod, io); - - return ret; -} - -int rsnd_gen_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod, *n; - int ret = 0; - - /* - * remove all mod from rdai - */ - for_each_rsnd_mod(mod, n, io) - ret |= rsnd_dai_disconnect(mod); - - return ret; -} - /* * Gen2 */ diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3962a50977e5..6a25203e0f08 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -210,9 +210,6 @@ struct rsnd_dai { i++) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); -int rsnd_dai_disconnect(struct rsnd_mod *mod); -int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod, - struct rsnd_dai_stream *io); int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) @@ -229,12 +226,6 @@ int rsnd_gen_probe(struct platform_device *pdev, struct rsnd_priv *priv); void rsnd_gen_remove(struct platform_device *pdev, struct rsnd_priv *priv); -int rsnd_gen_path_init(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); -int rsnd_gen_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); -- cgit v1.2.3 From a126021d144bae88a563db2b57b0ad5eb1ee66d9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:42:55 -0800 Subject: ASoC: rsnd: use mod array instead of list on rdai struct rsnd_dai_stream used list for mod list. It added only odd flexibility to current driver, and it is a factor which makes extendibility difficult. rsnd use mod array instead of list from now. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 42 +++++++++++++++++++++++------------------- sound/soc/sh/rcar/rsnd.h | 12 ++++++++---- sound/soc/sh/rcar/scu.c | 2 +- sound/soc/sh/rcar/ssi.c | 2 +- 4 files changed, 33 insertions(+), 25 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 96cb78612a7d..416b0782503a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -121,12 +121,13 @@ char *rsnd_mod_name(struct rsnd_mod *mod) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_mod_ops *ops, + enum rsnd_mod_type type, int id) { mod->priv = priv; mod->id = id; mod->ops = ops; - INIT_LIST_HEAD(&mod->list); + mod->type = type; } /* @@ -307,9 +308,12 @@ void rsnd_dma_quit(struct rsnd_priv *priv, #define rsnd_dai_call(rdai, io, fn) \ ({ \ - struct rsnd_mod *mod, *n; \ - int ret = 0; \ - for_each_rsnd_mod(mod, n, (io)) { \ + struct rsnd_mod *mod; \ + int ret = 0, i; \ + for (i = 0; i < RSND_MOD_MAX; i++) { \ + mod = (io)->mod[i]; \ + if (!mod) \ + continue; \ ret = rsnd_mod_call(mod, fn, (rdai), (io)); \ if (ret < 0) \ break; \ @@ -317,14 +321,13 @@ void rsnd_dma_quit(struct rsnd_priv *priv, ret; \ }) -static int rsnd_dai_connect(struct rsnd_dai *rdai, - struct rsnd_mod *mod, +static int rsnd_dai_connect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { if (!mod) return -EIO; - if (!list_empty(&mod->list)) { + if (io->mod[mod->type]) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); @@ -334,15 +337,15 @@ static int rsnd_dai_connect(struct rsnd_dai *rdai, return -EIO; } - list_add_tail(&mod->list, &io->head); + io->mod[mod->type] = mod; mod->io = io; return 0; } -static int rsnd_dai_disconnect(struct rsnd_mod *mod) +static int rsnd_dai_disconnect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { - list_del_init(&mod->list); + io->mod[mod->type] = NULL; mod->io = NULL; return 0; @@ -596,7 +599,7 @@ static int rsnd_path_init(struct rsnd_priv *priv, /* SCU */ mod = rsnd_scu_mod_get(priv, id); if (mod) { - ret = rsnd_dai_connect(rdai, mod, io); + ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; } @@ -604,7 +607,7 @@ static int rsnd_path_init(struct rsnd_priv *priv, /* SSI */ mod = rsnd_ssi_mod_get(priv, id); if (mod) { - ret = rsnd_dai_connect(rdai, mod, io); + ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; } @@ -616,14 +619,18 @@ static int rsnd_path_exit(struct rsnd_priv *priv, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_mod *mod, *n; - int ret = 0; + struct rsnd_mod *mod; + int ret = 0, i; /* * remove all mod from rdai */ - for_each_rsnd_mod(mod, n, io) - ret |= rsnd_dai_disconnect(mod); + for (i = 0; i < RSND_MOD_MAX; i++) { + mod = io->mod[i]; + if (!mod) + continue; + ret |= rsnd_dai_disconnect(mod, io); + } return ret; } @@ -671,9 +678,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, /* * init rsnd_dai */ - INIT_LIST_HEAD(&rdai[i].playback.head); - INIT_LIST_HEAD(&rdai[i].capture.head); - snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i); /* diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 6a25203e0f08..7767a8f1994a 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -135,6 +135,11 @@ void rsnd_dma_quit(struct rsnd_priv *priv, /* * R-Car sound mod */ +enum rsnd_mod_type { + RSND_MOD_SCU = 0, + RSND_MOD_SSI, + RSND_MOD_MAX, +}; struct rsnd_mod_ops { char *name; @@ -155,9 +160,9 @@ struct rsnd_mod_ops { struct rsnd_dai_stream; struct rsnd_mod { int id; + enum rsnd_mod_type type; struct rsnd_priv *priv; struct rsnd_mod_ops *ops; - struct list_head list; /* connect to rsnd_dai playback/capture */ struct rsnd_dma dma; struct rsnd_dai_stream *io; }; @@ -167,12 +172,11 @@ struct rsnd_mod { #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) #define rsnd_mod_to_io(mod) ((mod)->io) #define rsnd_mod_id(mod) ((mod)->id) -#define for_each_rsnd_mod(pos, n, io) \ - list_for_each_entry_safe(pos, n, &(io)->head, list) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_mod_ops *ops, + enum rsnd_mod_type type, int id); char *rsnd_mod_name(struct rsnd_mod *mod); @@ -181,8 +185,8 @@ char *rsnd_mod_name(struct rsnd_mod *mod); */ #define RSND_DAI_NAME_SIZE 16 struct rsnd_dai_stream { - struct list_head head; /* head of rsnd_mod list */ struct snd_pcm_substream *substream; + struct rsnd_mod *mod[RSND_MOD_MAX]; int byte_pos; int period_pos; int byte_per_period; diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 882e837d39d1..81264ecd82ac 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -659,7 +659,7 @@ int rsnd_scu_probe(struct platform_device *pdev, ops = &rsnd_scu_non_gen2_ops; } - rsnd_mod_init(priv, &scu->mod, ops, i); + rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); dev_dbg(dev, "SCU%d probed\n", i); } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 38a62a883b83..480dde5076b7 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -584,7 +584,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, dev_dbg(dev, "SSI%d use PIO transfer\n", i); } - rsnd_mod_init(priv, &ssi->mod, ops, i); + rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i); rsnd_ssi_parent_clk_setup(priv, ssi); } -- cgit v1.2.3 From 374e5426377604a94d672650ef22dd2b4285de17 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:03 -0800 Subject: ASoC: rsnd: get ssi/scu from rsnd_dai_stream Current driver is assuming that SSI id = SCU id. But, now, it can get correct SSI/SCU from rsnd_dai_stream. use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 4 +++- sound/soc/sh/rcar/scu.c | 20 +++++++++++--------- sound/soc/sh/rcar/ssi.c | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 7767a8f1994a..cbc38a2be81c 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -192,6 +192,8 @@ struct rsnd_dai_stream { int byte_per_period; int next_period_byte; }; +#define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) +#define rsnd_io_to_mod_scu(io) ((io)->mod[RSND_MOD_SCU]) struct rsnd_dai { char name[RSND_DAI_NAME_SIZE]; @@ -311,7 +313,7 @@ void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv); struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, + struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); #define rsnd_scu_nr(priv) ((priv)->scu_nr) diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 81264ecd82ac..1073d35486e3 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -121,7 +121,8 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); + struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); + int ssi_id = rsnd_mod_id(ssi_mod); u32 convert_rate = rsnd_scu_convert_rate(scu); if (convert_rate && !rsnd_dai_is_clk_master(rdai)) { @@ -134,15 +135,15 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, /* * SSI_MODE0 */ - rsnd_mod_bset(mod, SSI_MODE0, (1 << id), - rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << id)); + rsnd_mod_bset(mod, SSI_MODE0, (1 << ssi_id), + rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << ssi_id)); /* * SSI_MODE1 */ - if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { + if (rsnd_ssi_is_pin_sharing(ssi_mod)) { int shift = -1; - switch (id) { + switch (ssi_id) { case 1: shift = 0; break; @@ -165,14 +166,13 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, } unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, + struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime) { struct rsnd_scu *scu; unsigned int rate; - /* this function is assuming SSI id = SCU id here */ - scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); + scu = rsnd_mod_to_scu(rsnd_io_to_mod_scu(io)); /* * return convert rate if SRC is used, @@ -583,8 +583,10 @@ static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { + struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); + /* enable PIO interrupt */ - rsnd_mod_write(mod, INT_ENABLE, 0x0f000000); + rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 480dde5076b7..25a7d441f8fc 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -121,7 +121,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, 1, 2, 4, 8, 16, 6, 12, }; unsigned int main_rate; - unsigned int rate = rsnd_scu_get_ssi_rate(priv, &ssi->mod, runtime); + unsigned int rate = rsnd_scu_get_ssi_rate(priv, io, runtime); /* * Find best clock, and try to start ADG -- cgit v1.2.3 From 468be93eb4e28c5710ed8acc1b938937707e537c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:11 -0800 Subject: ASoC: rsnd: use devm_clk_get() instead of clk_get() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 69d9394f3697..a05ad8159824 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -405,11 +405,11 @@ int rsnd_adg_probe(struct platform_device *pdev, return -ENOMEM; } - clk_orig = clk_get(dev, NULL); - adg->clk[CLKA] = clk_get(dev, "clk_a"); - adg->clk[CLKB] = clk_get(dev, "clk_b"); - adg->clk[CLKC] = clk_get(dev, "clk_c"); - adg->clk[CLKI] = clk_get(dev, "clk_i"); + clk_orig = devm_clk_get(dev, NULL); + adg->clk[CLKA] = devm_clk_get(dev, "clk_a"); + adg->clk[CLKB] = devm_clk_get(dev, "clk_b"); + adg->clk[CLKC] = devm_clk_get(dev, "clk_c"); + adg->clk[CLKI] = devm_clk_get(dev, "clk_i"); /* * It request device dependent audio clock. @@ -432,10 +432,10 @@ int rsnd_adg_probe(struct platform_device *pdev, * but will be removed soon */ if (use_old_style) { - adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); - adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); - adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); - adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); + adg->clk[CLKA] = devm_clk_get(NULL, "audio_clk_a"); + adg->clk[CLKB] = devm_clk_get(NULL, "audio_clk_b"); + adg->clk[CLKC] = devm_clk_get(NULL, "audio_clk_c"); + adg->clk[CLKI] = devm_clk_get(NULL, "audio_clk_internal"); } for_each_rsnd_clk(clk, adg, i) { @@ -457,10 +457,4 @@ int rsnd_adg_probe(struct platform_device *pdev, void rsnd_adg_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_adg *adg = priv->adg; - struct clk *clk; - int i; - - for_each_rsnd_clk(clk, adg, i) - clk_put(clk); } -- cgit v1.2.3 From d1ac970f5de94bef9e094b46f016899d04e8178b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:18 -0800 Subject: ASoC: rsnd: use function pointer for each probe R-Car sound consists of many devices. It will have more device support in the future. Thus, for each probe become now function pointer array. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 416b0782503a..ea747614fbf8 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -814,7 +814,15 @@ static int rsnd_probe(struct platform_device *pdev) struct rcar_snd_info *info; struct rsnd_priv *priv; struct device *dev = &pdev->dev; - int ret; + int (*probe_func[])(struct platform_device *pdev, + struct rsnd_priv *priv) = { + rsnd_gen_probe, + rsnd_ssi_probe, + rsnd_scu_probe, + rsnd_adg_probe, + rsnd_dai_probe, + }; + int ret, i; info = pdev->dev.platform_data; if (!info) { @@ -838,25 +846,11 @@ static int rsnd_probe(struct platform_device *pdev) /* * init each module */ - ret = rsnd_gen_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_ssi_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_scu_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_adg_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_dai_probe(pdev, priv); - if (ret) - return ret; + for (i = 0; i < ARRAY_SIZE(probe_func); i++) { + ret = probe_func[i](pdev, priv); + if (ret) + return ret; + } /* * asoc register -- cgit v1.2.3 From 685fb3eb31445bd872ab30ae301404b2cac7cd75 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:26 -0800 Subject: ASoC: rsnd: remove unused SSI_CONTROL Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 1 - sound/soc/sh/rcar/rsnd.h | 1 - 2 files changed, 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 4f2c1d0c6970..92d1bc9acef0 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -173,7 +173,6 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), /* FIXME: it needs SSI_MODE2/3 in the future */ - RSND_GEN2_S_REG(gen, SSIU, SSI_CONTROL, 0x810), RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index cbc38a2be81c..e16acd2037a0 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -39,7 +39,6 @@ enum rsnd_reg { RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ RSND_REG_SRC_CTRL, /* for Gen2 */ RSND_REG_SSI_CTRL, /* for Gen2 */ - RSND_REG_SSI_CONTROL, RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ RSND_REG_SSI_MODE0, -- cgit v1.2.3 From 8467dedc9dae3630a2ede49a43120af3ed54ba19 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:33 -0800 Subject: ASoC: rsnd: modify rsnd_adg_ssi_ws_timing_gen2() parameter rsnd_adg_ssi_ws_timing_gen2() returns SSI WS timing, and it used "mod" as parameter. but, this "mod" is sometimes not ssi mod. Get SSI mod from rsnd_dai_stream Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index a05ad8159824..8df00ac3b120 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -32,8 +32,9 @@ struct rsnd_adg { #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) -static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_mod *mod) +static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io) { + struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); int id = rsnd_mod_id(mod); int ws = id; @@ -67,7 +68,7 @@ static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, u32 mask, ws; u32 in, out; - ws = rsnd_adg_ssi_ws_timing_gen2(mod); + ws = rsnd_adg_ssi_ws_timing_gen2(io); in = (is_play) ? timsel : ws; out = (is_play) ? ws : timsel; @@ -174,7 +175,7 @@ int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - u32 val = rsnd_adg_ssi_ws_timing_gen2(mod); + u32 val = rsnd_adg_ssi_ws_timing_gen2(io); return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); } -- cgit v1.2.3 From c82e1c8874e5abaf52f9ed886386cbe08ec98a5b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:40 -0800 Subject: ASoC: rsnd: share reg_field and reduce memory Gen1/Gen2 code never be used in same time. Thus, driver can share Gen1 only register and Gen2 only register. It can reduce memory too. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 81 +++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 28 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index e16acd2037a0..d5afdee6b6f2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -32,18 +32,8 @@ */ enum rsnd_reg { /* SRU/SCU/SSIU */ - RSND_REG_SRC_ROUTE_SEL, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL0, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ - RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ - RSND_REG_SRC_CTRL, /* for Gen2 */ - RSND_REG_SSI_CTRL, /* for Gen2 */ - RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ - RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, - RSND_REG_INT_ENABLE, /* for Gen2 */ RSND_REG_SRC_BUSIF_MODE, RSND_REG_SRC_ROUTE_MODE0, RSND_REG_SRC_SWRSR, @@ -52,9 +42,6 @@ enum rsnd_reg { RSND_REG_SRC_IFSCR, RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, - RSND_REG_SRC_MNFSR, /* for Gen1 */ - RSND_REG_SRC_BSDSR, /* for Gen2 */ - RSND_REG_SRC_BSISR, /* for Gen2 */ /* ADG */ RSND_REG_BRRA, @@ -62,21 +49,6 @@ enum rsnd_reg { RSND_REG_SSICKR, RSND_REG_AUDIO_CLK_SEL0, RSND_REG_AUDIO_CLK_SEL1, - RSND_REG_AUDIO_CLK_SEL2, - RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ - RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ - RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ - RSND_REG_DIV_EN, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL3, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL4, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL0, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL1, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL2, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL3, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL4, /* for Gen2 */ /* SSI */ RSND_REG_SSICR, @@ -85,9 +57,62 @@ enum rsnd_reg { RSND_REG_SSIRDR, RSND_REG_SSIWSR, + /* SHARE see below */ + RSND_REG_SHARE01, + RSND_REG_SHARE02, + RSND_REG_SHARE03, + RSND_REG_SHARE04, + RSND_REG_SHARE05, + RSND_REG_SHARE06, + RSND_REG_SHARE07, + RSND_REG_SHARE08, + RSND_REG_SHARE09, + RSND_REG_SHARE10, + RSND_REG_SHARE11, + RSND_REG_SHARE12, + RSND_REG_SHARE13, + RSND_REG_SHARE14, + RSND_REG_SHARE15, + RSND_REG_SHARE16, + RSND_REG_SHARE17, + RSND_REG_SHARE18, + RSND_REG_SHARE19, + RSND_REG_MAX, }; +/* Gen1 only */ +#define RSND_REG_SRC_ROUTE_SEL RSND_REG_SHARE01 +#define RSND_REG_SRC_TMG_SEL0 RSND_REG_SHARE02 +#define RSND_REG_SRC_TMG_SEL1 RSND_REG_SHARE03 +#define RSND_REG_SRC_TMG_SEL2 RSND_REG_SHARE04 +#define RSND_REG_SRC_ROUTE_CTRL RSND_REG_SHARE05 +#define RSND_REG_SRC_MNFSR RSND_REG_SHARE06 +#define RSND_REG_AUDIO_CLK_SEL3 RSND_REG_SHARE07 +#define RSND_REG_AUDIO_CLK_SEL4 RSND_REG_SHARE08 +#define RSND_REG_AUDIO_CLK_SEL5 RSND_REG_SHARE09 + +/* Gen2 only */ +#define RSND_REG_SRC_CTRL RSND_REG_SHARE01 +#define RSND_REG_SSI_CTRL RSND_REG_SHARE02 +#define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03 +#define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04 +#define RSND_REG_INT_ENABLE RSND_REG_SHARE05 +#define RSND_REG_SRC_BSDSR RSND_REG_SHARE06 +#define RSND_REG_SRC_BSISR RSND_REG_SHARE07 +#define RSND_REG_DIV_EN RSND_REG_SHARE08 +#define RSND_REG_SRCIN_TIMSEL0 RSND_REG_SHARE09 +#define RSND_REG_SRCIN_TIMSEL1 RSND_REG_SHARE10 +#define RSND_REG_SRCIN_TIMSEL2 RSND_REG_SHARE11 +#define RSND_REG_SRCIN_TIMSEL3 RSND_REG_SHARE12 +#define RSND_REG_SRCIN_TIMSEL4 RSND_REG_SHARE13 +#define RSND_REG_SRCOUT_TIMSEL0 RSND_REG_SHARE14 +#define RSND_REG_SRCOUT_TIMSEL1 RSND_REG_SHARE15 +#define RSND_REG_SRCOUT_TIMSEL2 RSND_REG_SHARE16 +#define RSND_REG_SRCOUT_TIMSEL3 RSND_REG_SHARE17 +#define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18 +#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 + struct rsnd_priv; struct rsnd_mod; struct rsnd_dai; -- cgit v1.2.3 From 931f27c6e892fdfe98896055e0df7962e21969d9 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 28 Feb 2014 10:48:19 +0800 Subject: ASoC: cache: Do the codec->reg_cache zero pionter check For the snd_soc_cache_init(), the reg_size maybe zero and then the value of codec->reg_cache, which is alloced via kzalloc, maybe equal to ZERO_SIZE_PTR. If the reg parameter of snd_soc_cache_write() is large enough, the cache[idx] = val maybe cause the kernel crash... So this patch fix this via doing the zero pionter check of it. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/soc-cache.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 375dc6dfba4e..bfed3e4c45ff 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -96,8 +96,7 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec) { dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n", codec->name); - if (!codec->reg_cache) - return 0; + kfree(codec->reg_cache); codec->reg_cache = NULL; return 0; @@ -117,8 +116,9 @@ int snd_soc_cache_read(struct snd_soc_codec *codec, return -EINVAL; mutex_lock(&codec->cache_rw_mutex); - *value = snd_soc_get_cache_val(codec->reg_cache, reg, - codec->driver->reg_word_size); + if (!ZERO_OR_NULL_PTR(codec->reg_cache)) + *value = snd_soc_get_cache_val(codec->reg_cache, reg, + codec->driver->reg_word_size); mutex_unlock(&codec->cache_rw_mutex); return 0; @@ -136,8 +136,9 @@ int snd_soc_cache_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { mutex_lock(&codec->cache_rw_mutex); - snd_soc_set_cache_val(codec->reg_cache, reg, value, - codec->driver->reg_word_size); + if (!ZERO_OR_NULL_PTR(codec->reg_cache)) + snd_soc_set_cache_val(codec->reg_cache, reg, value, + codec->driver->reg_word_size); mutex_unlock(&codec->cache_rw_mutex); return 0; -- cgit v1.2.3 From d4179c1deafd216b9358f76f5f399220cb8451ab Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 4 Mar 2014 16:54:58 +0800 Subject: ASoC: da732x: Replace hw_read usage with snd_soc_read() Pre-merge code was using direct hw_read() calls as an out of framework way of doing volatile register I/O when not using regmap. This has never functioned correctly in mainline due to the regmap conversion, the hw_read() implementation still does caching. In order to facilitate removal of the subsystem level I/O code convert to use snd_soc_read(), there should be no functional impact. Signed-off-by: Mark Brown Acked-by: Adam Thomson --- sound/soc/codecs/da732x.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index f295b6569910..8053e0e7f4a7 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1301,9 +1301,9 @@ static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); /* Check DAC offset sign */ - sign[DA732X_HPL_DAC] = (codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & + sign[DA732X_HPL_DAC] = (snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO); - sign[DA732X_HPR_DAC] = (codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & + sign[DA732X_HPR_DAC] = (snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO); /* Binary search DAC offset values (both channels at once) */ @@ -1320,10 +1320,10 @@ static void da732x_dac_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); - if ((codec->hw_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & + if ((snd_soc_read(codec, DA732X_REG_HPL_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPL_DAC]) offset[DA732X_HPL_DAC] &= ~step; - if ((codec->hw_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & + if ((snd_soc_read(codec, DA732X_REG_HPR_DAC_OFF_CNTL) & DA732X_HP_DAC_OFF_CNTL_COMPO) ^ sign[DA732X_HPR_DAC]) offset[DA732X_HPR_DAC] &= ~step; @@ -1364,9 +1364,9 @@ static void da732x_output_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); /* Check output offset sign */ - sign[DA732X_HPL_AMP] = codec->hw_read(codec, DA732X_REG_HPL) & + sign[DA732X_HPL_AMP] = snd_soc_read(codec, DA732X_REG_HPL) & DA732X_HP_OUT_COMPO; - sign[DA732X_HPR_AMP] = codec->hw_read(codec, DA732X_REG_HPR) & + sign[DA732X_HPR_AMP] = snd_soc_read(codec, DA732X_REG_HPR) & DA732X_HP_OUT_COMPO; snd_soc_write(codec, DA732X_REG_HPL, DA732X_HP_OUT_COMP | @@ -1387,10 +1387,10 @@ static void da732x_output_offset_adjust(struct snd_soc_codec *codec) msleep(DA732X_WAIT_FOR_STABILIZATION); - if ((codec->hw_read(codec, DA732X_REG_HPL) & + if ((snd_soc_read(codec, DA732X_REG_HPL) & DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPL_AMP]) offset[DA732X_HPL_AMP] &= ~step; - if ((codec->hw_read(codec, DA732X_REG_HPR) & + if ((snd_soc_read(codec, DA732X_REG_HPR) & DA732X_HP_OUT_COMPO) ^ sign[DA732X_HPR_AMP]) offset[DA732X_HPR_AMP] &= ~step; -- cgit v1.2.3 From d433570d9cac9c98de4c71b38d47b759f9168dea Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 5 Mar 2014 09:10:02 +0800 Subject: ASoC: fsl: Don't select FIQ from Eukrea There is no point in using FIQ if DMA is available (it is selected) and selecting FIQ currently breaks the build on non-i.MX platforms. If FIQ is actually required the build will need to be restricted or have a select for the relevant FIQ code adding. Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index b8f8703e2b46..c26ff3441f43 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -172,7 +172,6 @@ config SND_SOC_EUKREA_TLV320 || (OF && ARM) depends on I2C select SND_SOC_TLV320AIC23 - select SND_SOC_IMX_PCM_FIQ select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_SSI select SND_SOC_FSL_SSI -- cgit v1.2.3 From 57d4325a4fa67436b05f30c02a36e204c6cd1282 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Mar 2014 09:19:37 +0100 Subject: ASoC: ak4104: Remove superfluous codec->control_data initialization The driver uses automatic IO setup, which will also initialize the control_data field of the CODEC, no need to do it manually. Signed-off-by: Lars-Peter Clausen Acked-by: Daniel Mack Signed-off-by: Mark Brown --- sound/soc/codecs/ak4104.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index b4819dcd4f4d..10adf25d4c14 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -174,8 +174,6 @@ static int ak4104_probe(struct snd_soc_codec *codec) struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = ak4104->regmap; - /* set power-up and non-reset bits */ ret = regmap_update_bits(ak4104->regmap, AK4104_REG_CONTROL1, AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, -- cgit v1.2.3 From 78f13d0c5a2888564b2bed7f8433c8ec889997ff Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:49:50 -0800 Subject: ASoC: rsnd: add struct rsnd_dai_platform_info R-Car sound DAI consists from SSI/SCU/SSIU/SRU... Current R-Car sound DAI is decided from these settings, but it is intuitively unclear, and is not good design for DT support. This patch adds new rsnd_dai_platform_info to solve this issue. But now, many platform is using this driver without rsnd_dai_platform_info. So, this patch still supports DAI settings via SSI to keep compatible. It will be removed in next Linux version. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 17 ++++++++++++++++- sound/soc/sh/rcar/core.c | 23 ++++++++++++++++------- sound/soc/sh/rcar/ssi.c | 14 ++++++++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index e3d585c67685..698f7b5fc76d 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -36,13 +36,15 @@ #define RSND_SSI_CLK_PIN_SHARE (1 << 31) #define RSND_SSI_PLAY (1 << 24) +#define RSND_SSI(_dma_id, _pio_irq, _flags) \ +{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags } #define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags) \ { .dai_id = _dai_id, .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags } #define RSND_SSI_UNUSED \ { .dai_id = -1, .dma_id = -1, .pio_irq = -1, .flags = 0 } struct rsnd_ssi_platform_info { - int dai_id; + int dai_id; /* will be removed */ int dma_id; int pio_irq; u32 flags; @@ -53,6 +55,8 @@ struct rsnd_ssi_platform_info { */ #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ +#define RSND_SCU(rate, _dma_id) \ +{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } #define RSND_SCU_SET(rate, _dma_id) \ { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } #define RSND_SCU_UNUSED \ @@ -64,6 +68,15 @@ struct rsnd_scu_platform_info { int dma_id; /* for Gen2 SCU */ }; +struct rsnd_dai_path_info { + struct rsnd_ssi_platform_info *ssi; +}; + +struct rsnd_dai_platform_info { + struct rsnd_dai_path_info playback; + struct rsnd_dai_path_info capture; +}; + /* * flags * @@ -81,6 +94,8 @@ struct rcar_snd_info { int ssi_info_nr; struct rsnd_scu_platform_info *scu_info; int scu_info_nr; + struct rsnd_dai_platform_info *dai_info; + int dai_info_nr; int (*start)(int id); int (*stop)(int id); }; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ea747614fbf8..450472633eb1 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -639,19 +639,26 @@ static int rsnd_dai_probe(struct platform_device *pdev, struct rsnd_priv *priv) { struct snd_soc_dai_driver *drv; + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_dai *rdai; struct rsnd_mod *pmod, *cmod; struct device *dev = rsnd_priv_to_dev(priv); - int dai_nr; + int dai_nr = info->dai_info_nr; int i; - /* get max dai nr */ - for (dai_nr = 0; dai_nr < 32; dai_nr++) { - pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); - cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); + /* + * dai_nr should be set via dai_info_nr, + * but allow it to keeping compatible + */ + if (!dai_nr) { + /* get max dai nr */ + for (dai_nr = 0; dai_nr < 32; dai_nr++) { + pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); + cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); - if (!pmod && !cmod) - break; + if (!pmod && !cmod) + break; + } } if (!dai_nr) { @@ -671,6 +678,8 @@ static int rsnd_dai_probe(struct platform_device *pdev, priv->rdai = rdai; for (i = 0; i < dai_nr; i++) { + if (info->dai_info) + rdai[i].info = &info->dai_info[i]; pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1); cmod = rsnd_ssi_mod_get_frm_dai(priv, i, 0); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 25a7d441f8fc..34234813f742 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -451,12 +451,26 @@ static struct rsnd_mod_ops rsnd_ssi_non_ops = { struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play) { + struct rsnd_dai_platform_info *dai_info = NULL; + struct rsnd_dai_path_info *path_info = NULL; + struct rsnd_ssi_platform_info *target_info = NULL; struct rsnd_ssi *ssi; int i, has_play; + if (priv->rdai) + dai_info = priv->rdai[dai_id].info; + if (dai_info) + path_info = (is_play) ? &dai_info->playback : &dai_info->capture; + if (path_info) + target_info = path_info->ssi; + is_play = !!is_play; for_each_rsnd_ssi(ssi, priv, i) { + if (target_info == ssi->info) + return &ssi->mod; + + /* for compatible */ if (rsnd_ssi_dai_id(ssi) != dai_id) continue; -- cgit v1.2.3 From 389933d9f6e55a1ef3a71549c36f6283b9f8c145 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:00 -0800 Subject: ASoC: rsnd: Get correct SCU ID Current rsnd driver is assuming that SCU/SRU ID is same as SSIU/SSI ID, because Gen1 can't select it. But, Gen2 can select it. The SCU/SRU/SSIU/SSI pair depends on the platform. This patch get correct SCU ID from platform info. To keep compatible, it still assuming SCU ID = SSI ID if platform doesn't have info Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 1 + sound/soc/sh/rcar/core.c | 47 +++++++++++++++++++++++++++++++++-------------- sound/soc/sh/rcar/rsnd.h | 14 ++++++++++++++ sound/soc/sh/rcar/scu.c | 21 ++++++++++++++++----- sound/soc/sh/rcar/ssi.c | 9 ++++++++- 5 files changed, 72 insertions(+), 20 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 698f7b5fc76d..1d8c68323f49 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -70,6 +70,7 @@ struct rsnd_scu_platform_info { struct rsnd_dai_path_info { struct rsnd_ssi_platform_info *ssi; + struct rsnd_scu_platform_info *scu; }; struct rsnd_dai_platform_info { diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 450472633eb1..7316d10e4649 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -107,6 +107,11 @@ (!(priv->info->func) ? 0 : \ priv->info->func(param)) +#define rsnd_is_enable_path(io, name) \ + ((io)->info ? (io)->info->name : NULL) +#define rsnd_info_id(priv, io, name) \ + ((io)->info->name - priv->info->name##_info) + /* * rsnd_mod functions */ @@ -572,8 +577,10 @@ static int rsnd_path_init(struct rsnd_priv *priv, struct rsnd_dai_stream *io) { struct rsnd_mod *mod; + struct rsnd_dai_platform_info *dai_info = rdai->info; int ret; - int id; + int ssi_id = -1; + int scu_id = -1; /* * Gen1 is created by SRU/SSI, and this SRU is base module of @@ -584,29 +591,35 @@ static int rsnd_path_init(struct rsnd_priv *priv, * * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is * using fixed path. - * - * Then, SSI id = SCU id here */ - /* get SSI's ID */ - mod = rsnd_ssi_mod_get_frm_dai(priv, - rsnd_dai_id(priv, rdai), - rsnd_dai_is_play(rdai, io)); - if (!mod) - return 0; - id = rsnd_mod_id(mod); + if (dai_info) { + if (rsnd_is_enable_path(io, ssi)) + ssi_id = rsnd_info_id(priv, io, ssi); + if (rsnd_is_enable_path(io, scu)) + scu_id = rsnd_info_id(priv, io, scu); + } else { + /* get SSI's ID */ + mod = rsnd_ssi_mod_get_frm_dai(priv, + rsnd_dai_id(priv, rdai), + rsnd_dai_is_play(rdai, io)); + if (!mod) + return 0; + ssi_id = scu_id = rsnd_mod_id(mod); + } + ret = 0; /* SCU */ - mod = rsnd_scu_mod_get(priv, id); - if (mod) { + if (scu_id >= 0) { + mod = rsnd_scu_mod_get(priv, scu_id); ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; } /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); - if (mod) { + if (ssi_id >= 0) { + mod = rsnd_ssi_mod_get(priv, ssi_id); ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; @@ -699,6 +712,9 @@ static int rsnd_dai_probe(struct platform_device *pdev, drv[i].playback.formats = RSND_FMTS; drv[i].playback.channels_min = 2; drv[i].playback.channels_max = 2; + + if (info->dai_info) + rdai[i].playback.info = &info->dai_info[i].playback; rsnd_path_init(priv, &rdai[i], &rdai[i].playback); } if (cmod) { @@ -706,6 +722,9 @@ static int rsnd_dai_probe(struct platform_device *pdev, drv[i].capture.formats = RSND_FMTS; drv[i].capture.channels_min = 2; drv[i].capture.channels_max = 2; + + if (info->dai_info) + rdai[i].capture.info = &info->dai_info[i].capture; rsnd_path_init(priv, &rdai[i], &rdai[i].capture); } diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index d5afdee6b6f2..3472631c7b35 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -211,6 +211,7 @@ char *rsnd_mod_name(struct rsnd_mod *mod); struct rsnd_dai_stream { struct snd_pcm_substream *substream; struct rsnd_mod *mod[RSND_MOD_MAX]; + struct rsnd_dai_path_info *info; /* rcar_snd.h */ int byte_pos; int period_pos; int byte_per_period; @@ -328,6 +329,19 @@ struct rsnd_priv { #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) +#define rsnd_info_is_playback(priv, type) \ +({ \ + struct rcar_snd_info *info = rsnd_priv_to_info(priv); \ + int i, is_play = 0; \ + for (i = 0; i < info->dai_info_nr; i++) { \ + if (info->dai_info[i].playback.type == (type)->info) { \ + is_play = 1; \ + break; \ + } \ + } \ + is_play; \ +}) + /* * R-Car SCU */ diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 1073d35486e3..b517300f32ce 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -620,6 +620,9 @@ int rsnd_scu_probe(struct platform_device *pdev, * init SCU */ nr = info->scu_info_nr; + if (!nr) + return 0; + scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL); if (!scu) { dev_err(dev, "SCU allocate failed\n"); @@ -644,11 +647,19 @@ int rsnd_scu_probe(struct platform_device *pdev, if (rsnd_is_gen1(priv)) ops = &rsnd_scu_gen1_ops; if (rsnd_is_gen2(priv)) { - struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); - int ret = rsnd_dma_init(priv, - rsnd_mod_to_dma(&scu->mod), - rsnd_ssi_is_play(ssi), - scu->info->dma_id); + int ret; + int is_play; + + if (info->dai_info) { + is_play = rsnd_info_is_playback(priv, scu); + } else { + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); + is_play = rsnd_ssi_is_play(ssi); + } + ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(&scu->mod), + is_play, + scu->info->dma_id); if (ret < 0) return ret; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 34234813f742..9162c2bb6cc5 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -567,9 +567,16 @@ int rsnd_ssi_probe(struct platform_device *pdev, * SSI DMA case */ if (pinfo->dma_id > 0) { + int is_play; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, ssi); + else + is_play = rsnd_ssi_is_play(&ssi->mod); + ret = rsnd_dma_init( priv, rsnd_mod_to_dma(&ssi->mod), - rsnd_ssi_is_play(&ssi->mod), + is_play, pinfo->dma_id); if (ret < 0) dev_info(dev, "SSI DMA failed. try PIO transter\n"); -- cgit v1.2.3 From b8cc41e9e8cc5beec9dcbe044cfc44aa0325d9e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:08 -0800 Subject: ASoC: rsnd: add rsnd_scu_enable_ssi_irq() Current R-Car sound driver is assuming that SCU mod is used even though it is not needed. Because scu.c is controlling SSIU too. (it is Gen1 compatibility) But, SCU mod will be really not used if new platform dai feature was used. Thus, SSIU irq setting is called from SSI directory by this patch. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 3 +++ sound/soc/sh/rcar/scu.c | 26 +++++++++++++------------- sound/soc/sh/rcar/ssi.c | 2 ++ 3 files changed, 18 insertions(+), 13 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3472631c7b35..3b71b77c4fd8 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -353,6 +353,9 @@ struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); +int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); #define rsnd_scu_nr(priv) ((priv)->scu_nr) diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index b517300f32ce..8ce79e855cf0 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -165,6 +165,19 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, return 0; } +int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + + /* enable PIO interrupt if Gen2 */ + if (rsnd_is_gen2(priv)) + rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); + + return 0; +} + unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime) @@ -579,22 +592,9 @@ static struct rsnd_mod_ops rsnd_scu_gen2_ops = { .stop = rsnd_scu_stop_gen2, }; -static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); - - /* enable PIO interrupt */ - rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); - - return 0; -} - static struct rsnd_mod_ops rsnd_scu_non_gen2_ops = { .name = "non-scu (gen2)", .init = rsnd_scu_ssi_mode_init, - .start = rsnd_scu_start_non_gen2, }; struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 9162c2bb6cc5..a74c7a789b2b 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -365,6 +365,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; + rsnd_scu_enable_ssi_irq(mod, rdai, io); + rsnd_ssi_hw_start(ssi, rdai, io); return 0; -- cgit v1.2.3 From 221bf523e31306c1095b28932e079950108e3887 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:24 -0800 Subject: ASoC: rsnd: call rsnd_scu_ssi_mode_init() from SSI Current R-Car sound driver is assuming that SCU mod is used even though it is not needed. Because scu.c is controlling SSIU too. (it is Gen1 compatibility) But, SCU mod will be really not used if new platform dai feature was added. Thus, rsnd_scu_ssi_mode_init() is called from SSI directory by this patch. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 3 +++ sound/soc/sh/rcar/scu.c | 54 +++++++++++++++--------------------------------- sound/soc/sh/rcar/ssi.c | 2 ++ 3 files changed, 22 insertions(+), 37 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3b71b77c4fd8..9205f96da2f4 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -353,6 +353,9 @@ struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); +int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 8ce79e855cf0..63e6aeb8c42d 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -115,28 +115,28 @@ struct rsnd_scu { /* * Gen1/Gen2 common functions */ -static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + struct rsnd_mod *scu_mod = rsnd_io_to_mod_scu(io); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); int ssi_id = rsnd_mod_id(ssi_mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - - if (convert_rate && !rsnd_dai_is_clk_master(rdai)) { - struct device *dev = rsnd_priv_to_dev(priv); - - dev_err(dev, "rsnd should be clk master when you rate convert\n"); - return -EINVAL; - } + int has_scu = 0; /* * SSI_MODE0 */ - rsnd_mod_bset(mod, SSI_MODE0, (1 << ssi_id), - rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << ssi_id)); + if (info->dai_info) { + has_scu = !!scu_mod; + } else { + struct rsnd_scu *scu = rsnd_mod_to_scu(scu_mod); + has_scu = rsnd_scu_hpbif_is_enable(scu); + } + + rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), + has_scu ? 0 : (1 << ssi_id)); /* * SSI_MODE1 @@ -156,7 +156,7 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, } if (shift >= 0) - rsnd_mod_bset(mod, SSI_MODE1, + rsnd_mod_bset(ssi_mod, SSI_MODE1, 0x3 << shift, rsnd_dai_is_clk_master(rdai) ? 0x2 << shift : 0x1 << shift); @@ -253,14 +253,9 @@ static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int ret; clk_enable(scu->clk); - ret = rsnd_scu_ssi_mode_init(mod, rdai, io); - if (ret < 0) - return ret; - return 0; } @@ -487,11 +482,6 @@ static struct rsnd_mod_ops rsnd_scu_gen1_ops = { .stop = rsnd_scu_stop_gen1, }; -static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = { - .name = "non-sru (gen1)", - .init = rsnd_scu_ssi_mode_init, -}; - /* * Gen2 functions */ @@ -592,11 +582,6 @@ static struct rsnd_mod_ops rsnd_scu_gen2_ops = { .stop = rsnd_scu_stop_gen2, }; -static struct rsnd_mod_ops rsnd_scu_non_gen2_ops = { - .name = "non-scu (gen2)", - .init = rsnd_scu_ssi_mode_init, -}; - struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) { if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) @@ -665,11 +650,6 @@ int rsnd_scu_probe(struct platform_device *pdev, ops = &rsnd_scu_gen2_ops; } - } else { - if (rsnd_is_gen1(priv)) - ops = &rsnd_scu_non_gen1_ops; - if (rsnd_is_gen2(priv)) - ops = &rsnd_scu_non_gen2_ops; } rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index a74c7a789b2b..a7df216a46da 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -287,6 +287,8 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ + rsnd_scu_ssi_mode_init(mod, rdai, io); + return 0; } -- cgit v1.2.3 From 7681f6ac6b6338932621f842d68e54f6267b785f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:33 -0800 Subject: ASoC: rsnd: add probe/remove callback on rsnd_mod_ops Each rsnd mod needs specific probe method, and its best timing is DAI probe timing. But current code runs it mod probe timing. This patch adds new probe/remove callback to solve it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 23 +++++++++++++++++++++++ sound/soc/sh/rcar/rsnd.h | 6 ++++++ 2 files changed, 29 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 7316d10e4649..e8e585de7251 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -842,6 +842,7 @@ static int rsnd_probe(struct platform_device *pdev) struct rcar_snd_info *info; struct rsnd_priv *priv; struct device *dev = &pdev->dev; + struct rsnd_dai *rdai; int (*probe_func[])(struct platform_device *pdev, struct rsnd_priv *priv) = { rsnd_gen_probe, @@ -880,6 +881,16 @@ static int rsnd_probe(struct platform_device *pdev) return ret; } + for_each_rsnd_dai(rdai, priv, i) { + ret = rsnd_dai_call(rdai, &rdai->playback, probe); + if (ret) + return ret; + + ret = rsnd_dai_call(rdai, &rdai->capture, probe); + if (ret) + return ret; + } + /* * asoc register */ @@ -912,9 +923,21 @@ exit_snd_soc: static int rsnd_remove(struct platform_device *pdev) { struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); + struct rsnd_dai *rdai; + int ret, i; pm_runtime_disable(&pdev->dev); + for_each_rsnd_dai(rdai, priv, i) { + ret = rsnd_dai_call(rdai, &rdai->playback, remove); + if (ret) + return ret; + + ret = rsnd_dai_call(rdai, &rdai->capture, remove); + if (ret) + return ret; + } + /* * remove each module */ diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 9205f96da2f4..db20b3721953 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -167,6 +167,12 @@ enum rsnd_mod_type { struct rsnd_mod_ops { char *name; + int (*probe)(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); + int (*remove)(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); int (*init)(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); -- cgit v1.2.3 From 76c6fb5c49790da44d553f655182b426ade2c599 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:41 -0800 Subject: ASoC: rsnd: use mod probe method on SCU Now, it can use .probe Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 64 ++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 25 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 63e6aeb8c42d..40250acf608d 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -525,6 +525,42 @@ static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod, return ret; } +static int rsnd_scu_probe_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); + struct device *dev = rsnd_priv_to_dev(priv); + int ret; + int is_play; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, scu); + else + is_play = rsnd_ssi_is_play(ssi); + + ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(mod), + is_play, + scu->info->dma_id); + if (ret < 0) + dev_err(dev, "SCU DMA failed\n"); + + return ret; +} + +static int rsnd_scu_remove_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); + + return 0; +} + static int rsnd_scu_init_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -576,6 +612,8 @@ static int rsnd_scu_stop_gen2(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_scu_gen2_ops = { .name = "scu (gen2)", + .probe = rsnd_scu_probe_gen2, + .remove = rsnd_scu_remove_gen2, .init = rsnd_scu_init_gen2, .quit = rsnd_scu_quit, .start = rsnd_scu_start_gen2, @@ -631,25 +669,8 @@ int rsnd_scu_probe(struct platform_device *pdev, if (rsnd_scu_hpbif_is_enable(scu)) { if (rsnd_is_gen1(priv)) ops = &rsnd_scu_gen1_ops; - if (rsnd_is_gen2(priv)) { - int ret; - int is_play; - - if (info->dai_info) { - is_play = rsnd_info_is_playback(priv, scu); - } else { - struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); - is_play = rsnd_ssi_is_play(ssi); - } - ret = rsnd_dma_init(priv, - rsnd_mod_to_dma(&scu->mod), - is_play, - scu->info->dma_id); - if (ret < 0) - return ret; - + if (rsnd_is_gen2(priv)) ops = &rsnd_scu_gen2_ops; - } } rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); @@ -663,11 +684,4 @@ int rsnd_scu_probe(struct platform_device *pdev, void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_scu *scu; - int i; - - for_each_rsnd_scu(scu, priv, i) { - if (rsnd_scu_dma_available(scu)) - rsnd_dma_quit(priv, rsnd_mod_to_dma(&scu->mod)); - } } -- cgit v1.2.3 From ff8f30e688477beead6d1e648fb11f321220a4d7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:49 -0800 Subject: ASoC: rsnd: use mod probe method on SSI Now, it can use .probe Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 116 +++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 51 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index a7df216a46da..0f3eeac56155 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -358,6 +358,26 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) return ret; } +static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + int irq = ssi->info->pio_irq; + int ret; + + ret = devm_request_irq(dev, irq, + rsnd_ssi_pio_interrupt, + IRQF_SHARED, + dev_name(dev), ssi); + if (ret) + dev_err(dev, "SSI request interrupt failed\n"); + + return ret; +} + static int rsnd_ssi_pio_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -389,12 +409,50 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .name = "ssi (pio)", + .probe = rsnd_ssi_pio_probe, .init = rsnd_ssi_init, .quit = rsnd_ssi_quit, .start = rsnd_ssi_pio_start, .stop = rsnd_ssi_pio_stop, }; +static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = rsnd_priv_to_dev(priv); + int dma_id = ssi->info->dma_id; + int is_play; + int ret; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, ssi); + else + is_play = rsnd_ssi_is_play(&ssi->mod); + + ret = rsnd_dma_init( + priv, rsnd_mod_to_dma(mod), + is_play, + dma_id); + + if (ret < 0) + dev_err(dev, "SSI DMA failed\n"); + + return ret; +} + +static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); + + return 0; +} + static int rsnd_ssi_dma_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -436,6 +494,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_ssi_dma_ops = { .name = "ssi (dma)", + .probe = rsnd_ssi_dma_probe, + .remove = rsnd_ssi_dma_remove, .init = rsnd_ssi_init, .quit = rsnd_ssi_quit, .start = rsnd_ssi_dma_start, @@ -538,7 +598,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, struct clk *clk; struct rsnd_ssi *ssi; char name[RSND_SSI_NAME_SIZE]; - int i, nr, ret; + int i, nr; /* * init SSI @@ -566,48 +626,10 @@ int rsnd_ssi_probe(struct platform_device *pdev, ssi->clk = clk; ops = &rsnd_ssi_non_ops; - - /* - * SSI DMA case - */ - if (pinfo->dma_id > 0) { - int is_play; - - if (info->dai_info) - is_play = rsnd_info_is_playback(priv, ssi); - else - is_play = rsnd_ssi_is_play(&ssi->mod); - - ret = rsnd_dma_init( - priv, rsnd_mod_to_dma(&ssi->mod), - is_play, - pinfo->dma_id); - if (ret < 0) - dev_info(dev, "SSI DMA failed. try PIO transter\n"); - else - ops = &rsnd_ssi_dma_ops; - - dev_dbg(dev, "SSI%d use DMA transfer\n", i); - } - - /* - * SSI PIO case - */ - if (!rsnd_ssi_dma_available(ssi) && - rsnd_ssi_pio_available(ssi)) { - ret = devm_request_irq(dev, pinfo->pio_irq, - &rsnd_ssi_pio_interrupt, - IRQF_SHARED, - dev_name(dev), ssi); - if (ret) { - dev_err(dev, "SSI request interrupt failed\n"); - return ret; - } - - ops = &rsnd_ssi_pio_ops; - - dev_dbg(dev, "SSI%d use PIO transfer\n", i); - } + if (pinfo->dma_id > 0) + ops = &rsnd_ssi_dma_ops; + else if (rsnd_ssi_pio_available(ssi)) + ops = &rsnd_ssi_pio_ops; rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i); @@ -620,12 +642,4 @@ int rsnd_ssi_probe(struct platform_device *pdev, void rsnd_ssi_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_ssi *ssi; - int i; - - for_each_rsnd_ssi(ssi, priv, i) { - if (rsnd_ssi_dma_available(ssi)) - rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod)); - } - } -- cgit v1.2.3 From 4076220767416b8b65009dd57eeb317c38d41baa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:51:03 -0800 Subject: ASoC: rsnd: nothing to do on rsnd_dai_remove() rsnd_dai_remove() called rsnd_path_exit(), but these memory will be cleaned automatically. Because it is created by devm_kzalloc(). nothing to do on rsnd_dai_remove() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index e8e585de7251..92e155b7b6a7 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -348,14 +348,6 @@ static int rsnd_dai_connect(struct rsnd_mod *mod, return 0; } -static int rsnd_dai_disconnect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) -{ - io->mod[mod->type] = NULL; - mod->io = NULL; - - return 0; -} - int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) { int id = rdai - priv->rdai; @@ -628,26 +620,6 @@ static int rsnd_path_init(struct rsnd_priv *priv, return ret; } -static int rsnd_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod; - int ret = 0, i; - - /* - * remove all mod from rdai - */ - for (i = 0; i < RSND_MOD_MAX; i++) { - mod = io->mod[i]; - if (!mod) - continue; - ret |= rsnd_dai_disconnect(mod, io); - } - - return ret; -} - static int rsnd_dai_probe(struct platform_device *pdev, struct rsnd_priv *priv) { @@ -739,14 +711,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, static void rsnd_dai_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_dai *rdai; - int i; - - for (i = 0; i < rsnd_rdai_nr(priv); i++) { - rdai = rsnd_dai_get(priv, i); - rsnd_path_exit(priv, rdai, &rdai->playback); - rsnd_path_exit(priv, rdai, &rdai->capture); - } } /* -- cgit v1.2.3 From 9524be0e761edd9f3c020344677d914ed249d010 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:51:11 -0800 Subject: ASoC: rsnd: remove all rsnd_xxx_remove() Now, rsnd_xxx_remove() do nothing. remove these Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 5 ----- sound/soc/sh/rcar/core.c | 14 -------------- sound/soc/sh/rcar/gen.c | 5 ----- sound/soc/sh/rcar/rsnd.h | 8 -------- sound/soc/sh/rcar/scu.c | 5 ----- sound/soc/sh/rcar/ssi.c | 5 ----- 6 files changed, 42 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 8df00ac3b120..953f1cce982d 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -454,8 +454,3 @@ int rsnd_adg_probe(struct platform_device *pdev, return 0; } - -void rsnd_adg_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 92e155b7b6a7..ceb4e8bd4970 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -708,11 +708,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, return 0; } -static void rsnd_dai_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} - /* * pcm ops */ @@ -902,15 +897,6 @@ static int rsnd_remove(struct platform_device *pdev) return ret; } - /* - * remove each module - */ - rsnd_ssi_remove(pdev, priv); - rsnd_adg_remove(pdev, priv); - rsnd_scu_remove(pdev, priv); - rsnd_dai_remove(pdev, priv); - rsnd_gen_remove(pdev, priv); - return 0; } diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 92d1bc9acef0..9094970dbdfb 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -385,8 +385,3 @@ int rsnd_gen_probe(struct platform_device *pdev, return ret; } - -void rsnd_gen_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index db20b3721953..878dc6e20ff2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -261,8 +261,6 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); */ int rsnd_gen_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_gen_remove(struct platform_device *pdev, - struct rsnd_priv *priv); void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); @@ -276,8 +274,6 @@ int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); int rsnd_adg_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_adg_remove(struct platform_device *pdev, - struct rsnd_priv *priv); int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, unsigned int src_rate, @@ -353,8 +349,6 @@ struct rsnd_priv { */ int rsnd_scu_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_scu_remove(struct platform_device *pdev, - struct rsnd_priv *priv); struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, @@ -373,8 +367,6 @@ int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, */ int rsnd_ssi_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_ssi_remove(struct platform_device *pdev, - struct rsnd_priv *priv); struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 40250acf608d..3526a5c2f608 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -680,8 +680,3 @@ int rsnd_scu_probe(struct platform_device *pdev, return 0; } - -void rsnd_scu_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 0f3eeac56155..45f828ded935 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -638,8 +638,3 @@ int rsnd_ssi_probe(struct platform_device *pdev, return 0; } - -void rsnd_ssi_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} -- cgit v1.2.3 From ba9c949f797aa3af56303445812a452144c61c35 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:51:21 -0800 Subject: ASoC: rsnd: rename scu to src R-Car sound has SCU unit which has SRC/CTU/MIX/DVC, and current rsnd driver has scu.c and scu module. Current scu.c has SRC support only. My first concept was control these feature on scu.c but, it become difficult and un-understandable now. This patch rename scu to src Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 18 +- sound/soc/sh/rcar/Makefile | 2 +- sound/soc/sh/rcar/core.c | 26 +- sound/soc/sh/rcar/rsnd.h | 24 +- sound/soc/sh/rcar/scu.c | 682 -------------------------------------------- sound/soc/sh/rcar/src.c | 687 +++++++++++++++++++++++++++++++++++++++++++++ sound/soc/sh/rcar/ssi.c | 6 +- 7 files changed, 727 insertions(+), 718 deletions(-) delete mode 100644 sound/soc/sh/rcar/scu.c create mode 100644 sound/soc/sh/rcar/src.c (limited to 'sound/soc') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 1d8c68323f49..34a3c02a4576 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -55,14 +55,18 @@ struct rsnd_ssi_platform_info { */ #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ -#define RSND_SCU(rate, _dma_id) \ +#define RSND_SRC(rate, _dma_id) \ { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } -#define RSND_SCU_SET(rate, _dma_id) \ +#define RSND_SRC_SET(rate, _dma_id) \ { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } -#define RSND_SCU_UNUSED \ +#define RSND_SRC_UNUSED \ { .flags = 0, .convert_rate = 0, .dma_id = 0, } -struct rsnd_scu_platform_info { +#define rsnd_scu_platform_info rsnd_src_platform_info +#define src_info scu_info +#define src_info_nr scu_info_nr + +struct rsnd_src_platform_info { u32 flags; u32 convert_rate; /* sampling rate convert */ int dma_id; /* for Gen2 SCU */ @@ -70,7 +74,7 @@ struct rsnd_scu_platform_info { struct rsnd_dai_path_info { struct rsnd_ssi_platform_info *ssi; - struct rsnd_scu_platform_info *scu; + struct rsnd_src_platform_info *src; }; struct rsnd_dai_platform_info { @@ -93,8 +97,8 @@ struct rcar_snd_info { u32 flags; struct rsnd_ssi_platform_info *ssi_info; int ssi_info_nr; - struct rsnd_scu_platform_info *scu_info; - int scu_info_nr; + struct rsnd_src_platform_info *src_info; + int src_info_nr; struct rsnd_dai_platform_info *dai_info; int dai_info_nr; int (*start)(int id); diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index 0ff492df7929..7d0051ced838 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile @@ -1,2 +1,2 @@ -snd-soc-rcar-objs := core.o gen.o scu.o adg.o ssi.o +snd-soc-rcar-objs := core.o gen.o src.o adg.o ssi.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o \ No newline at end of file diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ceb4e8bd4970..6a1b45df8101 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -73,13 +73,13 @@ * | +- ssi[2] * | ... * | - * | ** these control scu + * | ** these control src * | - * +- scu + * +- src * | - * +- scu[0] - * +- scu[1] - * +- scu[2] + * +- src[0] + * +- src[1] + * +- src[2] * ... * * @@ -572,7 +572,7 @@ static int rsnd_path_init(struct rsnd_priv *priv, struct rsnd_dai_platform_info *dai_info = rdai->info; int ret; int ssi_id = -1; - int scu_id = -1; + int src_id = -1; /* * Gen1 is created by SRU/SSI, and this SRU is base module of @@ -587,8 +587,8 @@ static int rsnd_path_init(struct rsnd_priv *priv, if (dai_info) { if (rsnd_is_enable_path(io, ssi)) ssi_id = rsnd_info_id(priv, io, ssi); - if (rsnd_is_enable_path(io, scu)) - scu_id = rsnd_info_id(priv, io, scu); + if (rsnd_is_enable_path(io, src)) + src_id = rsnd_info_id(priv, io, src); } else { /* get SSI's ID */ mod = rsnd_ssi_mod_get_frm_dai(priv, @@ -596,14 +596,14 @@ static int rsnd_path_init(struct rsnd_priv *priv, rsnd_dai_is_play(rdai, io)); if (!mod) return 0; - ssi_id = scu_id = rsnd_mod_id(mod); + ssi_id = src_id = rsnd_mod_id(mod); } ret = 0; - /* SCU */ - if (scu_id >= 0) { - mod = rsnd_scu_mod_get(priv, scu_id); + /* SRC */ + if (src_id >= 0) { + mod = rsnd_src_mod_get(priv, src_id); ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; @@ -806,7 +806,7 @@ static int rsnd_probe(struct platform_device *pdev) struct rsnd_priv *priv) = { rsnd_gen_probe, rsnd_ssi_probe, - rsnd_scu_probe, + rsnd_src_probe, rsnd_adg_probe, rsnd_dai_probe, }; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 878dc6e20ff2..c46e0afa54ae 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -160,7 +160,7 @@ void rsnd_dma_quit(struct rsnd_priv *priv, * R-Car sound mod */ enum rsnd_mod_type { - RSND_MOD_SCU = 0, + RSND_MOD_SRC = 0, RSND_MOD_SSI, RSND_MOD_MAX, }; @@ -224,7 +224,7 @@ struct rsnd_dai_stream { int next_period_byte; }; #define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) -#define rsnd_io_to_mod_scu(io) ((io)->mod[RSND_MOD_SCU]) +#define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) struct rsnd_dai { char name[RSND_DAI_NAME_SIZE]; @@ -302,10 +302,10 @@ struct rsnd_priv { void *gen; /* - * below value will be filled on rsnd_scu_probe() + * below value will be filled on rsnd_src_probe() */ - void *scu; - int scu_nr; + void *src; + int src_nr; /* * below value will be filled on rsnd_adg_probe() @@ -345,22 +345,22 @@ struct rsnd_priv { }) /* - * R-Car SCU + * R-Car SRC */ -int rsnd_scu_probe(struct platform_device *pdev, +int rsnd_src_probe(struct platform_device *pdev, struct rsnd_priv *priv); -struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, +struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); +unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); -int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, +int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); -int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, +int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); -#define rsnd_scu_nr(priv) ((priv)->scu_nr) +#define rsnd_src_nr(priv) ((priv)->src_nr) /* * R-Car SSI diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c deleted file mode 100644 index 3526a5c2f608..000000000000 --- a/sound/soc/sh/rcar/scu.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * Renesas R-Car SCU support - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Kuninori Morimoto - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include "rsnd.h" - -struct rsnd_scu { - struct rsnd_scu_platform_info *info; /* rcar_snd.h */ - struct rsnd_mod mod; - struct clk *clk; -}; - -#define RSND_SCU_NAME_SIZE 16 - -/* - * ADINR - */ -#define OTBL_24 (0 << 16) -#define OTBL_22 (2 << 16) -#define OTBL_20 (4 << 16) -#define OTBL_18 (6 << 16) -#define OTBL_16 (8 << 16) - -#define rsnd_scu_mode_flags(p) ((p)->info->flags) -#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) -#define rsnd_mod_to_scu(_mod) \ - container_of((_mod), struct rsnd_scu, mod) -#define rsnd_scu_hpbif_is_enable(scu) \ - (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) -#define rsnd_scu_dma_available(scu) \ - rsnd_dma_available(rsnd_mod_to_dma(&(scu)->mod)) - -#define for_each_rsnd_scu(pos, priv, i) \ - for ((i) = 0; \ - ((i) < rsnd_scu_nr(priv)) && \ - ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ - i++) - - -/* - * image of SRC (Sampling Rate Converter) - * - * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ - * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | - * 44.1kHz <-> +-----+ +-----+ +-------+ - * ... - * - */ - -/* - * scu.c is caring... - * - * Gen1 - * - * [mem] -> [SRU] -> [SSI] - * |--------| - * - * Gen2 - * - * [mem] -> [SCU] -> [SSIU] -> [SSI] - * |-----------------| - */ - -/* - * How to use SRC bypass mode for debugging - * - * SRC has bypass mode, and it is useful for debugging. - * In Gen2 case, - * SRCm_MODE controls whether SRC is used or not - * SSI_MODE0 controls whether SSIU which receives SRC data - * is used or not. - * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, - * but SRC bypass mode needs SSI_MODE0 only. - * - * This driver request - * struct rsnd_scu_platform_info { - * u32 flags; - * u32 convert_rate; - * } - * - * rsnd_scu_hpbif_is_enable() will be true - * if flags had RSND_SCU_USE_HPBIF, - * and it controls whether SSIU is used or not. - * - * rsnd_scu_convert_rate() indicates - * above convert_rate, and it controls - * whether SRC is used or not. - * - * ex) doesn't use SRC - * struct rsnd_scu_platform_info info = { - * .flags = 0, - * .convert_rate = 0, - * }; - * - * ex) uses SRC - * struct rsnd_scu_platform_info info = { - * .flags = RSND_SCU_USE_HPBIF, - * .convert_rate = 48000, - * }; - * - * ex) uses SRC bypass mode - * struct rsnd_scu_platform_info info = { - * .flags = RSND_SCU_USE_HPBIF, - * .convert_rate = 0, - * }; - * - */ - -/* - * Gen1/Gen2 common functions - */ -int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); - struct rsnd_mod *scu_mod = rsnd_io_to_mod_scu(io); - struct rcar_snd_info *info = rsnd_priv_to_info(priv); - int ssi_id = rsnd_mod_id(ssi_mod); - int has_scu = 0; - - /* - * SSI_MODE0 - */ - if (info->dai_info) { - has_scu = !!scu_mod; - } else { - struct rsnd_scu *scu = rsnd_mod_to_scu(scu_mod); - has_scu = rsnd_scu_hpbif_is_enable(scu); - } - - rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), - has_scu ? 0 : (1 << ssi_id)); - - /* - * SSI_MODE1 - */ - if (rsnd_ssi_is_pin_sharing(ssi_mod)) { - int shift = -1; - switch (ssi_id) { - case 1: - shift = 0; - break; - case 2: - shift = 2; - break; - case 4: - shift = 16; - break; - } - - if (shift >= 0) - rsnd_mod_bset(ssi_mod, SSI_MODE1, - 0x3 << shift, - rsnd_dai_is_clk_master(rdai) ? - 0x2 << shift : 0x1 << shift); - } - - return 0; -} - -int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); - - /* enable PIO interrupt if Gen2 */ - if (rsnd_is_gen2(priv)) - rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); - - return 0; -} - -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_dai_stream *io, - struct snd_pcm_runtime *runtime) -{ - struct rsnd_scu *scu; - unsigned int rate; - - scu = rsnd_mod_to_scu(rsnd_io_to_mod_scu(io)); - - /* - * return convert rate if SRC is used, - * otherwise, return runtime->rate as usual - */ - rate = rsnd_scu_convert_rate(scu); - if (!rate) - rate = runtime->rate; - - return rate; -} - -static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - u32 adinr = runtime->channels; - u32 fsrate = 0; - - if (convert_rate) - fsrate = 0x0400000 / convert_rate * runtime->rate; - - /* set/clear soft reset */ - rsnd_mod_write(mod, SRC_SWRSR, 0); - rsnd_mod_write(mod, SRC_SWRSR, 1); - - /* - * Initialize the operation of the SRC internal circuits - * see rsnd_scu_start() - */ - rsnd_mod_write(mod, SRC_SRCIR, 1); - - /* Set channel number and output bit length */ - switch (runtime->sample_bits) { - case 16: - adinr |= OTBL_16; - break; - case 32: - adinr |= OTBL_24; - break; - default: - return -EIO; - } - rsnd_mod_write(mod, SRC_ADINR, adinr); - - /* Enable the initial value of IFS */ - if (fsrate) { - rsnd_mod_write(mod, SRC_IFSCR, 1); - - /* Set initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSVR, fsrate); - } - - /* use DMA transfer */ - rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); - - return 0; -} - -static int rsnd_scu_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - clk_enable(scu->clk); - - return 0; -} - -static int rsnd_scu_quit(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - clk_disable(scu->clk); - - return 0; -} - -static int rsnd_scu_start(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - /* - * Cancel the initialization and operate the SRC function - * see rsnd_scu_set_convert_rate() - */ - rsnd_mod_write(mod, SRC_SRCIR, 0); - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); - - return 0; -} - - -static int rsnd_scu_stop(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); - - return 0; -} - -static struct rsnd_mod_ops rsnd_scu_non_ops = { - .name = "scu (non)", -}; - -/* - * Gen1 functions - */ -static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct scu_route_config { - u32 mask; - int shift; - } routes[] = { - { 0xF, 0, }, /* 0 */ - { 0xF, 4, }, /* 1 */ - { 0xF, 8, }, /* 2 */ - { 0x7, 12, }, /* 3 */ - { 0x7, 16, }, /* 4 */ - { 0x7, 20, }, /* 5 */ - { 0x7, 24, }, /* 6 */ - { 0x3, 28, }, /* 7 */ - { 0x3, 30, }, /* 8 */ - }; - u32 mask; - u32 val; - int id; - - id = rsnd_mod_id(mod); - if (id < 0 || id >= ARRAY_SIZE(routes)) - return -EIO; - - /* - * SRC_ROUTE_SELECT - */ - val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; - val = val << routes[id].shift; - mask = routes[id].mask << routes[id].shift; - - rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); - - return 0; -} - -static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - u32 convert_rate = rsnd_scu_convert_rate(scu); - u32 mask; - u32 val; - int shift; - int id = rsnd_mod_id(mod); - int ret; - - /* - * SRC_TIMING_SELECT - */ - shift = (id % 4) * 8; - mask = 0x1F << shift; - - /* - * ADG is used as source clock if SRC was used, - * then, SSI WS is used as destination clock. - * SSI WS is used as source clock if SRC is not used - * (when playback, source/destination become reverse when capture) - */ - ret = 0; - if (convert_rate) { - /* use ADG */ - val = 0; - ret = rsnd_adg_set_convert_clk_gen1(priv, mod, - runtime->rate, - convert_rate); - } else if (8 == id) { - /* use SSI WS, but SRU8 is special */ - val = id << shift; - } else { - /* use SSI WS */ - val = (id + 1) << shift; - } - - if (ret < 0) - return ret; - - switch (id / 4) { - case 0: - rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); - break; - case 1: - rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); - break; - case 2: - rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); - break; - } - - return 0; -} - -static int rsnd_scu_set_convert_rate_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_set_convert_rate(mod, rdai, io); - if (ret < 0) - return ret; - - /* Select SRC mode (fixed value) */ - rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); - - /* Set the restriction value of the FS ratio (98%) */ - rsnd_mod_write(mod, SRC_MNFSR, - rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); - - /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ - - return 0; -} - -static int rsnd_scu_init_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_init(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_src_set_route_gen1(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_rate_gen1(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_timing_gen1(mod, rdai, io); - if (ret < 0) - return ret; - - return 0; -} - -static int rsnd_scu_start_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int id = rsnd_mod_id(mod); - - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); - - return rsnd_scu_start(mod, rdai, io); -} - -static int rsnd_scu_stop_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int id = rsnd_mod_id(mod); - - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); - - return rsnd_scu_stop(mod, rdai, io); -} - -static struct rsnd_mod_ops rsnd_scu_gen1_ops = { - .name = "sru (gen1)", - .init = rsnd_scu_init_gen1, - .quit = rsnd_scu_quit, - .start = rsnd_scu_start_gen1, - .stop = rsnd_scu_stop_gen1, -}; - -/* - * Gen2 functions - */ -static int rsnd_scu_set_convert_rate_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_set_convert_rate(mod, rdai, io); - if (ret < 0) - return ret; - - rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); - rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); - - rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); - - rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); - rsnd_mod_write(mod, SRC_BSISR, 0x00100060); - - return 0; -} - -static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - int ret; - - if (convert_rate) - ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, - runtime->rate, - convert_rate); - else - ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); - - return ret; -} - -static int rsnd_scu_probe_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rcar_snd_info *info = rsnd_priv_to_info(priv); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); - struct device *dev = rsnd_priv_to_dev(priv); - int ret; - int is_play; - - if (info->dai_info) - is_play = rsnd_info_is_playback(priv, scu); - else - is_play = rsnd_ssi_is_play(ssi); - - ret = rsnd_dma_init(priv, - rsnd_mod_to_dma(mod), - is_play, - scu->info->dma_id); - if (ret < 0) - dev_err(dev, "SCU DMA failed\n"); - - return ret; -} - -static int rsnd_scu_remove_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); - - return 0; -} - -static int rsnd_scu_init_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_init(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_rate_gen2(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_timing_gen2(mod, rdai, io); - if (ret < 0) - return ret; - - return 0; -} - -static int rsnd_scu_start_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - rsnd_dma_start(rsnd_mod_to_dma(&scu->mod)); - - rsnd_mod_write(mod, SSI_CTRL, 0x1); - rsnd_mod_write(mod, SRC_CTRL, 0x11); - - return rsnd_scu_start(mod, rdai, io); -} - -static int rsnd_scu_stop_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - rsnd_mod_write(mod, SSI_CTRL, 0); - rsnd_mod_write(mod, SRC_CTRL, 0); - - rsnd_dma_stop(rsnd_mod_to_dma(&scu->mod)); - - return rsnd_scu_stop(mod, rdai, io); -} - -static struct rsnd_mod_ops rsnd_scu_gen2_ops = { - .name = "scu (gen2)", - .probe = rsnd_scu_probe_gen2, - .remove = rsnd_scu_remove_gen2, - .init = rsnd_scu_init_gen2, - .quit = rsnd_scu_quit, - .start = rsnd_scu_start_gen2, - .stop = rsnd_scu_stop_gen2, -}; - -struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) -{ - if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) - id = 0; - - return &((struct rsnd_scu *)(priv->scu) + id)->mod; -} - -int rsnd_scu_probe(struct platform_device *pdev, - struct rsnd_priv *priv) -{ - struct rcar_snd_info *info = rsnd_priv_to_info(priv); - struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_scu *scu; - struct rsnd_mod_ops *ops; - struct clk *clk; - char name[RSND_SCU_NAME_SIZE]; - int i, nr; - - /* - * init SCU - */ - nr = info->scu_info_nr; - if (!nr) - return 0; - - scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL); - if (!scu) { - dev_err(dev, "SCU allocate failed\n"); - return -ENOMEM; - } - - priv->scu_nr = nr; - priv->scu = scu; - - for_each_rsnd_scu(scu, priv, i) { - snprintf(name, RSND_SCU_NAME_SIZE, "scu.%d", i); - - clk = devm_clk_get(dev, name); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - scu->info = &info->scu_info[i]; - scu->clk = clk; - - ops = &rsnd_scu_non_ops; - if (rsnd_scu_hpbif_is_enable(scu)) { - if (rsnd_is_gen1(priv)) - ops = &rsnd_scu_gen1_ops; - if (rsnd_is_gen2(priv)) - ops = &rsnd_scu_gen2_ops; - } - - rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); - - dev_dbg(dev, "SCU%d probed\n", i); - } - - return 0; -} diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c new file mode 100644 index 000000000000..ea6a214985d0 --- /dev/null +++ b/sound/soc/sh/rcar/src.c @@ -0,0 +1,687 @@ +/* + * Renesas R-Car SRC support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Kuninori Morimoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include "rsnd.h" + +struct rsnd_src { + struct rsnd_src_platform_info *info; /* rcar_snd.h */ + struct rsnd_mod mod; + struct clk *clk; +}; + +#define RSND_SRC_NAME_SIZE 16 + +/* + * ADINR + */ +#define OTBL_24 (0 << 16) +#define OTBL_22 (2 << 16) +#define OTBL_20 (4 << 16) +#define OTBL_18 (6 << 16) +#define OTBL_16 (8 << 16) + +#define rsnd_src_mode_flags(p) ((p)->info->flags) +#define rsnd_src_convert_rate(p) ((p)->info->convert_rate) +#define rsnd_mod_to_src(_mod) \ + container_of((_mod), struct rsnd_src, mod) +#define rsnd_src_hpbif_is_enable(src) \ + (rsnd_src_mode_flags(src) & RSND_SCU_USE_HPBIF) +#define rsnd_src_dma_available(src) \ + rsnd_dma_available(rsnd_mod_to_dma(&(src)->mod)) + +#define for_each_rsnd_src(pos, priv, i) \ + for ((i) = 0; \ + ((i) < rsnd_src_nr(priv)) && \ + ((pos) = (struct rsnd_src *)(priv)->src + i); \ + i++) + + +/* + * image of SRC (Sampling Rate Converter) + * + * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ + * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | + * 44.1kHz <-> +-----+ +-----+ +-------+ + * ... + * + */ + +/* + * src.c is caring... + * + * Gen1 + * + * [mem] -> [SRU] -> [SSI] + * |--------| + * + * Gen2 + * + * [mem] -> [SRC] -> [SSIU] -> [SSI] + * |-----------------| + */ + +/* + * How to use SRC bypass mode for debugging + * + * SRC has bypass mode, and it is useful for debugging. + * In Gen2 case, + * SRCm_MODE controls whether SRC is used or not + * SSI_MODE0 controls whether SSIU which receives SRC data + * is used or not. + * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, + * but SRC bypass mode needs SSI_MODE0 only. + * + * This driver request + * struct rsnd_src_platform_info { + * u32 flags; + * u32 convert_rate; + * } + * + * rsnd_src_hpbif_is_enable() will be true + * if flags had RSND_SRC_USE_HPBIF, + * and it controls whether SSIU is used or not. + * + * rsnd_src_convert_rate() indicates + * above convert_rate, and it controls + * whether SRC is used or not. + * + * ex) doesn't use SRC + * struct rsnd_src_platform_info info = { + * .flags = 0, + * .convert_rate = 0, + * }; + * + * ex) uses SRC + * struct rsnd_src_platform_info info = { + * .flags = RSND_SRC_USE_HPBIF, + * .convert_rate = 48000, + * }; + * + * ex) uses SRC bypass mode + * struct rsnd_src_platform_info info = { + * .flags = RSND_SRC_USE_HPBIF, + * .convert_rate = 0, + * }; + * + */ + +/* + * Gen1/Gen2 common functions + */ +int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + int ssi_id = rsnd_mod_id(ssi_mod); + int has_src = 0; + + /* + * SSI_MODE0 + */ + if (info->dai_info) { + has_src = !!src_mod; + } else { + struct rsnd_src *src = rsnd_mod_to_src(src_mod); + has_src = rsnd_src_hpbif_is_enable(src); + } + + rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), + has_src ? 0 : (1 << ssi_id)); + + /* + * SSI_MODE1 + */ + if (rsnd_ssi_is_pin_sharing(ssi_mod)) { + int shift = -1; + switch (ssi_id) { + case 1: + shift = 0; + break; + case 2: + shift = 2; + break; + case 4: + shift = 16; + break; + } + + if (shift >= 0) + rsnd_mod_bset(ssi_mod, SSI_MODE1, + 0x3 << shift, + rsnd_dai_is_clk_master(rdai) ? + 0x2 << shift : 0x1 << shift); + } + + return 0; +} + +int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + + /* enable PIO interrupt if Gen2 */ + if (rsnd_is_gen2(priv)) + rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); + + return 0; +} + +unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, + struct rsnd_dai_stream *io, + struct snd_pcm_runtime *runtime) +{ + struct rsnd_src *src; + unsigned int rate; + + src = rsnd_mod_to_src(rsnd_io_to_mod_src(io)); + + /* + * return convert rate if SRC is used, + * otherwise, return runtime->rate as usual + */ + rate = rsnd_src_convert_rate(src); + if (!rate) + rate = runtime->rate; + + return rate; +} + +static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_src *src = rsnd_mod_to_src(mod); + u32 convert_rate = rsnd_src_convert_rate(src); + u32 adinr = runtime->channels; + u32 fsrate = 0; + + if (convert_rate) + fsrate = 0x0400000 / convert_rate * runtime->rate; + + /* set/clear soft reset */ + rsnd_mod_write(mod, SRC_SWRSR, 0); + rsnd_mod_write(mod, SRC_SWRSR, 1); + + /* + * Initialize the operation of the SRC internal circuits + * see rsnd_src_start() + */ + rsnd_mod_write(mod, SRC_SRCIR, 1); + + /* Set channel number and output bit length */ + switch (runtime->sample_bits) { + case 16: + adinr |= OTBL_16; + break; + case 32: + adinr |= OTBL_24; + break; + default: + return -EIO; + } + rsnd_mod_write(mod, SRC_ADINR, adinr); + + /* Enable the initial value of IFS */ + if (fsrate) { + rsnd_mod_write(mod, SRC_IFSCR, 1); + + /* Set initial value of IFS */ + rsnd_mod_write(mod, SRC_IFSVR, fsrate); + } + + /* use DMA transfer */ + rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); + + return 0; +} + +static int rsnd_src_init(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + clk_enable(src->clk); + + return 0; +} + +static int rsnd_src_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + clk_disable(src->clk); + + return 0; +} + +static int rsnd_src_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + /* + * Cancel the initialization and operate the SRC function + * see rsnd_src_set_convert_rate() + */ + rsnd_mod_write(mod, SRC_SRCIR, 0); + + if (rsnd_src_convert_rate(src)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + + return 0; +} + + +static int rsnd_src_stop(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + if (rsnd_src_convert_rate(src)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); + + return 0; +} + +static struct rsnd_mod_ops rsnd_src_non_ops = { + .name = "src (non)", +}; + +/* + * Gen1 functions + */ +static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct src_route_config { + u32 mask; + int shift; + } routes[] = { + { 0xF, 0, }, /* 0 */ + { 0xF, 4, }, /* 1 */ + { 0xF, 8, }, /* 2 */ + { 0x7, 12, }, /* 3 */ + { 0x7, 16, }, /* 4 */ + { 0x7, 20, }, /* 5 */ + { 0x7, 24, }, /* 6 */ + { 0x3, 28, }, /* 7 */ + { 0x3, 30, }, /* 8 */ + }; + u32 mask; + u32 val; + int id; + + id = rsnd_mod_id(mod); + if (id < 0 || id >= ARRAY_SIZE(routes)) + return -EIO; + + /* + * SRC_ROUTE_SELECT + */ + val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; + val = val << routes[id].shift; + mask = routes[id].mask << routes[id].shift; + + rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); + + return 0; +} + +static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_src *src = rsnd_mod_to_src(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + u32 convert_rate = rsnd_src_convert_rate(src); + u32 mask; + u32 val; + int shift; + int id = rsnd_mod_id(mod); + int ret; + + /* + * SRC_TIMING_SELECT + */ + shift = (id % 4) * 8; + mask = 0x1F << shift; + + /* + * ADG is used as source clock if SRC was used, + * then, SSI WS is used as destination clock. + * SSI WS is used as source clock if SRC is not used + * (when playback, source/destination become reverse when capture) + */ + ret = 0; + if (convert_rate) { + /* use ADG */ + val = 0; + ret = rsnd_adg_set_convert_clk_gen1(priv, mod, + runtime->rate, + convert_rate); + } else if (8 == id) { + /* use SSI WS, but SRU8 is special */ + val = id << shift; + } else { + /* use SSI WS */ + val = (id + 1) << shift; + } + + if (ret < 0) + return ret; + + switch (id / 4) { + case 0: + rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); + break; + case 1: + rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); + break; + case 2: + rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); + break; + } + + return 0; +} + +static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + /* Select SRC mode (fixed value) */ + rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); + + /* Set the restriction value of the FS ratio (98%) */ + rsnd_mod_write(mod, SRC_MNFSR, + rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); + + /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ + + return 0; +} + +static int rsnd_src_init_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_route_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_rate_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_timing_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_src_start_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int id = rsnd_mod_id(mod); + + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); + + return rsnd_src_start(mod, rdai, io); +} + +static int rsnd_src_stop_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int id = rsnd_mod_id(mod); + + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); + + return rsnd_src_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_src_gen1_ops = { + .name = "sru (gen1)", + .init = rsnd_src_init_gen1, + .quit = rsnd_src_quit, + .start = rsnd_src_start_gen1, + .stop = rsnd_src_stop_gen1, +}; + +/* + * Gen2 functions + */ +static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); + rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); + + rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); + + rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); + rsnd_mod_write(mod, SRC_BSISR, 0x00100060); + + return 0; +} + +static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_src *src = rsnd_mod_to_src(mod); + u32 convert_rate = rsnd_src_convert_rate(src); + int ret; + + if (convert_rate) + ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, + runtime->rate, + convert_rate); + else + ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); + + return ret; +} + +static int rsnd_src_probe_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct rsnd_src *src = rsnd_mod_to_src(mod); + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); + struct device *dev = rsnd_priv_to_dev(priv); + int ret; + int is_play; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, src); + else + is_play = rsnd_ssi_is_play(ssi); + + ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(mod), + is_play, + src->info->dma_id); + if (ret < 0) + dev_err(dev, "SRC DMA failed\n"); + + return ret; +} + +static int rsnd_src_remove_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); + + return 0; +} + +static int rsnd_src_init_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_rate_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_timing_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_src_start_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); + + rsnd_mod_write(mod, SSI_CTRL, 0x1); + rsnd_mod_write(mod, SRC_CTRL, 0x11); + + return rsnd_src_start(mod, rdai, io); +} + +static int rsnd_src_stop_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + rsnd_mod_write(mod, SSI_CTRL, 0); + rsnd_mod_write(mod, SRC_CTRL, 0); + + rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); + + return rsnd_src_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_src_gen2_ops = { + .name = "src (gen2)", + .probe = rsnd_src_probe_gen2, + .remove = rsnd_src_remove_gen2, + .init = rsnd_src_init_gen2, + .quit = rsnd_src_quit, + .start = rsnd_src_start_gen2, + .stop = rsnd_src_stop_gen2, +}; + +struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) +{ + if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) + id = 0; + + return &((struct rsnd_src *)(priv->src) + id)->mod; +} + +int rsnd_src_probe(struct platform_device *pdev, + struct rsnd_priv *priv) +{ + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_src *src; + struct rsnd_mod_ops *ops; + struct clk *clk; + char name[RSND_SRC_NAME_SIZE]; + int i, nr; + + /* + * init SRC + */ + nr = info->src_info_nr; + if (!nr) + return 0; + + src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); + if (!src) { + dev_err(dev, "SRC allocate failed\n"); + return -ENOMEM; + } + + priv->src_nr = nr; + priv->src = src; + + for_each_rsnd_src(src, priv, i) { + snprintf(name, RSND_SRC_NAME_SIZE, "src.%d", i); + + clk = devm_clk_get(dev, name); + if (IS_ERR(clk)) { + snprintf(name, RSND_SRC_NAME_SIZE, "scu.%d", i); + clk = devm_clk_get(dev, name); + } + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + src->info = &info->src_info[i]; + src->clk = clk; + + ops = &rsnd_src_non_ops; + if (rsnd_src_hpbif_is_enable(src)) { + if (rsnd_is_gen1(priv)) + ops = &rsnd_src_gen1_ops; + if (rsnd_is_gen2(priv)) + ops = &rsnd_src_gen2_ops; + } + + rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i); + + dev_dbg(dev, "SRC%d probed\n", i); + } + + return 0; +} diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 45f828ded935..633b23d209b9 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -121,7 +121,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, 1, 2, 4, 8, 16, 6, 12, }; unsigned int main_rate; - unsigned int rate = rsnd_scu_get_ssi_rate(priv, io, runtime); + unsigned int rate = rsnd_src_get_ssi_rate(priv, io, runtime); /* * Find best clock, and try to start ADG @@ -287,7 +287,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ - rsnd_scu_ssi_mode_init(mod, rdai, io); + rsnd_src_ssi_mode_init(mod, rdai, io); return 0; } @@ -387,7 +387,7 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; - rsnd_scu_enable_ssi_irq(mod, rdai, io); + rsnd_src_enable_ssi_irq(mod, rdai, io); rsnd_ssi_hw_start(ssi, rdai, io); -- cgit v1.2.3 From 81985bd63f6f1711035aa8d97caf2fb203250a95 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 20:32:43 -0800 Subject: ASoC: simple-card: tidyup cpu/codec dai_fmt settings for non-DT 30d0341e7da0c012f64fb290dd1153360fb49a8d (ASoC: simple-card: simplify the daifmt code) simplify cpu/codec dai_fmt which consists from dai specific format + common format. But, it didn't care about non-DT case. This patch fixes it Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 034a2b73f6c1..7cabcc5c8703 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -307,6 +307,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev) sizeof(priv->cpu_dai)); memcpy(&priv->codec_dai, &cinfo->codec_dai, sizeof(priv->codec_dai)); + + priv->cpu_dai.fmt |= cinfo->daifmt; + priv->codec_dai.fmt |= cinfo->daifmt; } /* -- cgit v1.2.3 From 9202c377390f2708dece910f2e066a6308a38abc Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 5 Mar 2014 14:11:57 +0300 Subject: ASoC: Baytrail: fix error handling in sst_byt_dsp_init() Calling "kfree(byt)" is a double free because that was allocated with devm_kzalloc(). There were a couple places which leak "byt->msg". That memory is allocated in msg_empty_list_init(). Fixes: f7d01fd6754c ('ASoC: Intel: Add Intel Baytrail SST DSP IPC support') Signed-off-by: Dan Carpenter Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-baytrail-ipc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-baytrail-ipc.c b/sound/soc/intel/sst-baytrail-ipc.c index c12e194bbc6b..d0eaeee21be4 100644 --- a/sound/soc/intel/sst-baytrail-ipc.c +++ b/sound/soc/intel/sst-baytrail-ipc.c @@ -796,7 +796,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) err = msg_empty_list_init(byt); if (err < 0) - goto list_err; + return -ENOMEM; /* start the IPC message thread */ init_kthread_worker(&byt->kworker); @@ -806,7 +806,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) if (IS_ERR(byt->tx_thread)) { err = PTR_ERR(byt->tx_thread); dev_err(byt->dev, "error failed to create message TX task\n"); - goto list_err; + goto err_free_msg; } init_kthread_work(&byt->kwork, sst_byt_ipc_tx_msgs); @@ -816,7 +816,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) byt->dsp = sst_dsp_new(dev, &byt_dev, pdata); if (byt->dsp == NULL) { err = -ENODEV; - goto list_err; + goto err_free_msg; } /* keep the DSP in reset state for base FW loading */ @@ -848,9 +848,9 @@ boot_err: sst_fw_free(byt_sst_fw); fw_err: sst_dsp_free(byt->dsp); +err_free_msg: kfree(byt->msg); -list_err: - kfree(byt); + return err; } EXPORT_SYMBOL_GPL(sst_byt_dsp_init); -- cgit v1.2.3 From 9c369c6e885599818d98ff7130d6ef62ce6ae8d4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 5 Mar 2014 17:53:31 +0100 Subject: ASoC: cs4271: Fix build error without CONFIG_SPI_MASTER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cs4271_common_probe() is called from cs4271_i2c_probe() but defined in CONFIG_SPI_MASTER block, thus it results in a build error when CONFIG_SPI_MASTER=n: sound/soc/codecs/cs4271.c:721:2: error: implicit declaration of function ‘cs4271_common_probe’ [-Werror=implicit-function-declaration] Move the function out of #if block. Fixes: d6cf89ee07cb ('ASoC: cs4271: claim reset GPIO in bus probe function') Signed-off-by: Takashi Iwai Acked-by: Daniel Mack Acked-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/cs4271.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 96c309777208..aef4965750c7 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -612,22 +612,6 @@ static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { .num_dapm_routes = ARRAY_SIZE(cs4271_dapm_routes), }; -#if defined(CONFIG_SPI_MASTER) - -static const struct regmap_config cs4271_spi_regmap = { - .reg_bits = 16, - .val_bits = 8, - .max_register = CS4271_LASTREG, - .read_flag_mask = 0x21, - .write_flag_mask = 0x20, - - .reg_defaults = cs4271_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), - .cache_type = REGCACHE_RBTREE, - - .volatile_reg = cs4271_volatile_reg, -}; - static int cs4271_common_probe(struct device *dev, struct cs4271_private **c) { @@ -658,6 +642,22 @@ static int cs4271_common_probe(struct device *dev, return 0; } +#if defined(CONFIG_SPI_MASTER) + +static const struct regmap_config cs4271_spi_regmap = { + .reg_bits = 16, + .val_bits = 8, + .max_register = CS4271_LASTREG, + .read_flag_mask = 0x21, + .write_flag_mask = 0x20, + + .reg_defaults = cs4271_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(cs4271_reg_defaults), + .cache_type = REGCACHE_RBTREE, + + .volatile_reg = cs4271_volatile_reg, +}; + static int cs4271_spi_probe(struct spi_device *spi) { struct cs4271_private *cs4271; -- cgit v1.2.3 From c1a7898d655fd265feefcf6fe82ab0096e6d078e Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Mar 2014 14:28:16 +0000 Subject: ASoC: wm_adsp: Split firmware load into smaller chunks The firmware files can be quite large and allocating the whole firmware a single DMA safe buffer can be problematic if the system is under a high memory load. Ease the requirements slightly by writing the firmware out in page sized chunks. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 48 ++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index f9fd56444a14..937af6f31ffa 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -684,24 +684,38 @@ static int wm_adsp_load(struct wm_adsp *dsp) } if (reg) { - buf = wm_adsp_buf_alloc(region->data, - le32_to_cpu(region->len), - &buf_list); - if (!buf) { - adsp_err(dsp, "Out of memory\n"); - ret = -ENOMEM; - goto out_fw; - } + size_t to_write = PAGE_SIZE; + size_t remain = le32_to_cpu(region->len); + const u8 *data = region->data; + + while (remain > 0) { + if (remain < PAGE_SIZE) + to_write = remain; + + buf = wm_adsp_buf_alloc(data, + to_write, + &buf_list); + if (!buf) { + adsp_err(dsp, "Out of memory\n"); + ret = -ENOMEM; + goto out_fw; + } - ret = regmap_raw_write_async(regmap, reg, buf->buf, - le32_to_cpu(region->len)); - if (ret != 0) { - adsp_err(dsp, - "%s.%d: Failed to write %d bytes at %d in %s: %d\n", - file, regions, - le32_to_cpu(region->len), offset, - region_name, ret); - goto out_fw; + ret = regmap_raw_write_async(regmap, reg, + buf->buf, + to_write); + if (ret != 0) { + adsp_err(dsp, + "%s.%d: Failed to write %d bytes at %d in %s: %d\n", + file, regions, + to_write, offset, + region_name, ret); + goto out_fw; + } + + data += to_write; + reg += to_write / 2; + remain -= to_write; } } -- cgit v1.2.3 From f516e368dcb5eb5fbe23246c09bf69573d67cd18 Mon Sep 17 00:00:00 2001 From: Rongjun Ying Date: Wed, 5 Mar 2014 16:34:34 +0800 Subject: ASoC: sirf: Add SiRF internal audio codec driver SiRF internal audio codec is integrated in SiRF atlas6 and prima2 SoC. Features include: 1. Stereo DAC and ADC with 16-bit resolution amd 48KHz sample rate 2. Support headphone and/or speaker output 3. Integrate headphone and speaker output amp 4. Support LINE and MIC input 5. Support single ended and differential input mode Signed-off-by: Rongjun Ying --v5: 1. Drop all inlines. 2. Reordering the Kconfig and Makefile 3. Remove the sirf_audio_codec_reg_bits struct, use the new controls instead it. 4. Add some SND_SOC_DAPM_OUT_DRV instead of HP and SPK enable driver 5. Add audio codec clock supply instead of adc event callback 6. Fixed playback and capture can't concurrent work bug. -- .../devicetree/bindings/sound/sirf-audio-codec.txt | 17 + sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 1 + sound/soc/codecs/sirf-audio-codec.c | 533 ++++++++++++++++++++ sound/soc/codecs/sirf-audio-codec.h | 75 +++ 5 files changed, 631 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/sirf-audio-codec.txt create mode 100644 sound/soc/codecs/sirf-audio-codec.c create mode 100644 sound/soc/codecs/sirf-audio-codec.h Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/sirf-audio-codec.txt | 17 + sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 1 + sound/soc/codecs/sirf-audio-codec.c | 533 +++++++++++++++++++++ sound/soc/codecs/sirf-audio-codec.h | 75 +++ 5 files changed, 631 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/sirf-audio-codec.txt create mode 100644 sound/soc/codecs/sirf-audio-codec.c create mode 100644 sound/soc/codecs/sirf-audio-codec.h (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt b/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt new file mode 100644 index 000000000000..062f5ec36f9b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sirf-audio-codec.txt @@ -0,0 +1,17 @@ +SiRF internal audio CODEC + +Required properties: + + - compatible : "sirf,atlas6-audio-codec" or "sirf,prima2-audio-codec" + + - reg : the register address of the device. + + - clocks: the clock of SiRF internal audio codec + +Example: + +audiocodec: audiocodec@b0040000 { + compatible = "sirf,atlas6-audio-codec"; + reg = <0xb0040000 0x10000>; + clocks = <&clks 27>; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..bf9b12c1a9c0 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -63,6 +63,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RT5640 if I2C select SND_SOC_SGTL5000 if I2C select SND_SOC_SI476X if MFD_SI476X_CORE + select SND_SOC_SIRF_AUDIO_CODEC select SND_SOC_SN95031 if INTEL_SCU_IPC select SND_SOC_SPDIF select SND_SOC_SSM2518 if I2C @@ -330,6 +331,10 @@ config SND_SOC_SIGMADSP tristate select CRC32 +config SND_SOC_SIRF_AUDIO_CODEC + tristate "SiRF SoC internal audio codec" + select REGMAP_MMIO + config SND_SOC_SN95031 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..de6d7f81b5f6 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -53,6 +53,7 @@ snd-soc-alc5623-objs := alc5623.o snd-soc-alc5632-objs := alc5632.o snd-soc-sigmadsp-objs := sigmadsp.o snd-soc-si476x-objs := si476x.o +snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o snd-soc-sn95031-objs := sn95031.o snd-soc-spdif-tx-objs := spdif_transmitter.o snd-soc-spdif-rx-objs := spdif_receiver.o diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c new file mode 100644 index 000000000000..90e3a228bae4 --- /dev/null +++ b/sound/soc/codecs/sirf-audio-codec.c @@ -0,0 +1,533 @@ +/* + * SiRF audio codec driver + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sirf-audio-codec.h" + +struct sirf_audio_codec { + struct clk *clk; + struct regmap *regmap; + u32 reg_ctrl0, reg_ctrl1; +}; + +static const char * const input_mode_mux[] = {"Single-ended", + "Differential"}; + +static const struct soc_enum input_mode_mux_enum = + SOC_ENUM_SINGLE(AUDIO_IC_CODEC_CTRL1, 4, 2, input_mode_mux); + +static const struct snd_kcontrol_new sirf_audio_codec_input_mode_control = + SOC_DAPM_ENUM("Route", input_mode_mux_enum); + +static const DECLARE_TLV_DB_SCALE(playback_vol_tlv, -12400, 100, 0); +static const DECLARE_TLV_DB_SCALE(capture_vol_tlv_prima2, 500, 100, 0); +static const DECLARE_TLV_DB_RANGE(capture_vol_tlv_atlas6, + 0, 7, TLV_DB_SCALE_ITEM(-100, 100, 0), + 0x22, 0x3F, TLV_DB_SCALE_ITEM(700, 100, 0), +); + +static struct snd_kcontrol_new volume_controls_atlas6[] = { + SOC_DOUBLE_TLV("Playback Volume", AUDIO_IC_CODEC_CTRL0, 21, 14, + 0x7F, 0, playback_vol_tlv), + SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 16, 10, + 0x3F, 0, capture_vol_tlv_atlas6), +}; + +static struct snd_kcontrol_new volume_controls_prima2[] = { + SOC_DOUBLE_TLV("Speaker Volume", AUDIO_IC_CODEC_CTRL0, 21, 14, + 0x7F, 0, playback_vol_tlv), + SOC_DOUBLE_TLV("Capture Volume", AUDIO_IC_CODEC_CTRL1, 15, 10, + 0x1F, 0, capture_vol_tlv_prima2), +}; + +static struct snd_kcontrol_new left_input_path_controls[] = { + SOC_DAPM_SINGLE("Line Left Switch", AUDIO_IC_CODEC_CTRL1, 6, 1, 0), + SOC_DAPM_SINGLE("Mic Left Switch", AUDIO_IC_CODEC_CTRL1, 3, 1, 0), +}; + +static struct snd_kcontrol_new right_input_path_controls[] = { + SOC_DAPM_SINGLE("Line Right Switch", AUDIO_IC_CODEC_CTRL1, 5, 1, 0), + SOC_DAPM_SINGLE("Mic Right Switch", AUDIO_IC_CODEC_CTRL1, 2, 1, 0), +}; + +static struct snd_kcontrol_new left_dac_to_hp_left_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 9, 1, 0); + +static struct snd_kcontrol_new left_dac_to_hp_right_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 8, 1, 0); + +static struct snd_kcontrol_new right_dac_to_hp_left_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 7, 1, 0); + +static struct snd_kcontrol_new right_dac_to_hp_right_amp_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 6, 1, 0); + +static struct snd_kcontrol_new left_dac_to_speaker_lineout_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 11, 1, 0); + +static struct snd_kcontrol_new right_dac_to_speaker_lineout_switch_control = + SOC_DAPM_SINGLE("Switch", AUDIO_IC_CODEC_CTRL0, 10, 1, 0); + +/* After enable adc, Delay 200ms to avoid pop noise */ +static int adc_enable_delay_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + msleep(200); + break; + default: + break; + } + + return 0; +} + +static void enable_and_reset_codec(struct regmap *regmap, + u32 codec_enable_bits, u32 codec_reset_bits) +{ + regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, + codec_enable_bits | codec_reset_bits, + codec_enable_bits | ~codec_reset_bits); + msleep(20); + regmap_update_bits(regmap, AUDIO_IC_CODEC_CTRL1, + codec_reset_bits, codec_reset_bits); +} + +static int atlas6_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ +#define ATLAS6_CODEC_ENABLE_BITS (1 << 29) +#define ATLAS6_CODEC_RESET_BITS (1 << 28) + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + enable_and_reset_codec(sirf_audio_codec->regmap, + ATLAS6_CODEC_ENABLE_BITS, ATLAS6_CODEC_RESET_BITS); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_IC_CODEC_CTRL1, ATLAS6_CODEC_ENABLE_BITS, + ~ATLAS6_CODEC_ENABLE_BITS); + break; + default: + break; + } + + return 0; +} + +static int prima2_codec_enable_and_reset_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ +#define PRIMA2_CODEC_ENABLE_BITS (1 << 27) +#define PRIMA2_CODEC_RESET_BITS (1 << 26) + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(w->codec->dev); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + enable_and_reset_codec(sirf_audio_codec->regmap, + PRIMA2_CODEC_ENABLE_BITS, PRIMA2_CODEC_RESET_BITS); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_IC_CODEC_CTRL1, PRIMA2_CODEC_ENABLE_BITS, + ~PRIMA2_CODEC_ENABLE_BITS); + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget atlas6_output_driver_dapm_widgets[] = { + SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1, + 25, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1, + 26, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1, + 27, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_widget prima2_output_driver_dapm_widgets[] = { + SND_SOC_DAPM_OUT_DRV("HP Left Driver", AUDIO_IC_CODEC_CTRL1, + 23, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("HP Right Driver", AUDIO_IC_CODEC_CTRL1, + 24, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("Speaker Driver", AUDIO_IC_CODEC_CTRL1, + 25, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_widget atlas6_codec_clock_dapm_widget = + SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0, + atlas6_codec_enable_and_reset_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); + +static const struct snd_soc_dapm_widget prima2_codec_clock_dapm_widget = + SND_SOC_DAPM_SUPPLY("codecclk", SND_SOC_NOPM, 0, 0, + prima2_codec_enable_and_reset_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD); + +static const struct snd_soc_dapm_widget sirf_audio_codec_dapm_widgets[] = { + SND_SOC_DAPM_DAC("DAC left", NULL, AUDIO_IC_CODEC_CTRL0, 1, 0), + SND_SOC_DAPM_DAC("DAC right", NULL, AUDIO_IC_CODEC_CTRL0, 0, 0), + SND_SOC_DAPM_SWITCH("Left dac to hp left amp", SND_SOC_NOPM, 0, 0, + &left_dac_to_hp_left_amp_switch_control), + SND_SOC_DAPM_SWITCH("Left dac to hp right amp", SND_SOC_NOPM, 0, 0, + &left_dac_to_hp_right_amp_switch_control), + SND_SOC_DAPM_SWITCH("Right dac to hp left amp", SND_SOC_NOPM, 0, 0, + &right_dac_to_hp_left_amp_switch_control), + SND_SOC_DAPM_SWITCH("Right dac to hp right amp", SND_SOC_NOPM, 0, 0, + &right_dac_to_hp_right_amp_switch_control), + SND_SOC_DAPM_OUT_DRV("HP amp left driver", AUDIO_IC_CODEC_CTRL0, 3, 0, + NULL, 0), + SND_SOC_DAPM_OUT_DRV("HP amp right driver", AUDIO_IC_CODEC_CTRL0, 3, 0, + NULL, 0), + + SND_SOC_DAPM_SWITCH("Left dac to speaker lineout", SND_SOC_NOPM, 0, 0, + &left_dac_to_speaker_lineout_switch_control), + SND_SOC_DAPM_SWITCH("Right dac to speaker lineout", SND_SOC_NOPM, 0, 0, + &right_dac_to_speaker_lineout_switch_control), + SND_SOC_DAPM_OUT_DRV("Speaker amp driver", AUDIO_IC_CODEC_CTRL0, 4, 0, + NULL, 0), + + SND_SOC_DAPM_OUTPUT("HPOUTL"), + SND_SOC_DAPM_OUTPUT("HPOUTR"), + SND_SOC_DAPM_OUTPUT("SPKOUT"), + + SND_SOC_DAPM_ADC_E("ADC left", NULL, AUDIO_IC_CODEC_CTRL1, 8, 0, + adc_enable_delay_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_ADC_E("ADC right", NULL, AUDIO_IC_CODEC_CTRL1, 7, 0, + adc_enable_delay_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_MIXER("Left PGA mixer", AUDIO_IC_CODEC_CTRL1, 1, 0, + &left_input_path_controls[0], + ARRAY_SIZE(left_input_path_controls)), + SND_SOC_DAPM_MIXER("Right PGA mixer", AUDIO_IC_CODEC_CTRL1, 0, 0, + &right_input_path_controls[0], + ARRAY_SIZE(right_input_path_controls)), + + SND_SOC_DAPM_MUX("Mic input mode mux", SND_SOC_NOPM, 0, 0, + &sirf_audio_codec_input_mode_control), + SND_SOC_DAPM_MICBIAS("Mic Bias", AUDIO_IC_CODEC_PWR, 3, 0), + SND_SOC_DAPM_INPUT("MICIN1"), + SND_SOC_DAPM_INPUT("MICIN2"), + SND_SOC_DAPM_INPUT("LINEIN1"), + SND_SOC_DAPM_INPUT("LINEIN2"), + + SND_SOC_DAPM_SUPPLY("HSL Phase Opposite", AUDIO_IC_CODEC_CTRL0, + 30, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route sirf_audio_codec_map[] = { + {"SPKOUT", NULL, "Speaker Driver"}, + {"Speaker Driver", NULL, "Speaker amp driver"}, + {"Speaker amp driver", NULL, "Left dac to speaker lineout"}, + {"Speaker amp driver", NULL, "Right dac to speaker lineout"}, + {"Left dac to speaker lineout", "Switch", "DAC left"}, + {"Right dac to speaker lineout", "Switch", "DAC right"}, + {"HPOUTL", NULL, "HP Left Driver"}, + {"HPOUTR", NULL, "HP Right Driver"}, + {"HP Left Driver", NULL, "HP amp left driver"}, + {"HP Right Driver", NULL, "HP amp right driver"}, + {"HP amp left driver", NULL, "Right dac to hp left amp"}, + {"HP amp right driver", NULL , "Right dac to hp right amp"}, + {"HP amp left driver", NULL, "Left dac to hp left amp"}, + {"HP amp right driver", NULL , "Right dac to hp right amp"}, + {"Right dac to hp left amp", "Switch", "DAC left"}, + {"Right dac to hp right amp", "Switch", "DAC right"}, + {"Left dac to hp left amp", "Switch", "DAC left"}, + {"Left dac to hp right amp", "Switch", "DAC right"}, + {"DAC left", NULL, "codecclk"}, + {"DAC right", NULL, "codecclk"}, + {"DAC left", NULL, "Playback"}, + {"DAC right", NULL, "Playback"}, + {"DAC left", NULL, "HSL Phase Opposite"}, + {"DAC right", NULL, "HSL Phase Opposite"}, + + {"Capture", NULL, "ADC left"}, + {"Capture", NULL, "ADC right"}, + {"ADC left", NULL, "codecclk"}, + {"ADC right", NULL, "codecclk"}, + {"ADC left", NULL, "Left PGA mixer"}, + {"ADC right", NULL, "Right PGA mixer"}, + {"Left PGA mixer", "Line Left Switch", "LINEIN2"}, + {"Right PGA mixer", "Line Right Switch", "LINEIN1"}, + {"Left PGA mixer", "Mic Left Switch", "MICIN2"}, + {"Right PGA mixer", "Mic Right Switch", "Mic input mode mux"}, + {"Mic input mode mux", "Single-ended", "MICIN1"}, + {"Mic input mode mux", "Differential", "MICIN1"}, +}; + +static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, + int cmd, + struct snd_soc_dai *dai) +{ + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + struct snd_soc_codec *codec = dai->codec; + u32 val = 0; + + /* + * This is a workaround, When stop playback, + * need disable HP amp, avoid the current noise. + */ + switch (cmd) { + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + break; + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (playback) + val = IC_HSLEN | IC_HSREN; + break; + default: + return -EINVAL; + } + + if (playback) + snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, + IC_HSLEN | IC_HSREN, val); + return 0; +} + +struct snd_soc_dai_ops sirf_audio_codec_dai_ops = { + .trigger = sirf_audio_codec_trigger, +}; + +struct snd_soc_dai_driver sirf_audio_codec_dai = { + .name = "sirf-audio-codec", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &sirf_audio_codec_dai_ops, +}; + +static int sirf_audio_codec_probe(struct snd_soc_codec *codec) +{ + int ret; + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); + + pm_runtime_enable(codec->dev); + codec->control_data = sirf_audio_codec->regmap; + + ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + if (ret != 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + return ret; + } + + if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { + snd_soc_dapm_new_controls(dapm, + prima2_output_driver_dapm_widgets, + ARRAY_SIZE(prima2_output_driver_dapm_widgets)); + snd_soc_dapm_new_controls(dapm, + &prima2_codec_clock_dapm_widget, 1); + return snd_soc_add_codec_controls(codec, + volume_controls_prima2, + ARRAY_SIZE(volume_controls_prima2)); + } + if (of_device_is_compatible(codec->dev->of_node, "sirf,atlas6-audio-codec")) { + snd_soc_dapm_new_controls(dapm, + atlas6_output_driver_dapm_widgets, + ARRAY_SIZE(atlas6_output_driver_dapm_widgets)); + snd_soc_dapm_new_controls(dapm, + &atlas6_codec_clock_dapm_widget, 1); + return snd_soc_add_codec_controls(codec, + volume_controls_atlas6, + ARRAY_SIZE(volume_controls_atlas6)); + } + + return -EINVAL; +} + +static int sirf_audio_codec_remove(struct snd_soc_codec *codec) +{ + pm_runtime_disable(codec->dev); + return 0; +} + +static struct snd_soc_codec_driver soc_codec_device_sirf_audio_codec = { + .probe = sirf_audio_codec_probe, + .remove = sirf_audio_codec_remove, + .dapm_widgets = sirf_audio_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sirf_audio_codec_dapm_widgets), + .dapm_routes = sirf_audio_codec_map, + .num_dapm_routes = ARRAY_SIZE(sirf_audio_codec_map), + .idle_bias_off = true, +}; + +static const struct of_device_id sirf_audio_codec_of_match[] = { + { .compatible = "sirf,prima2-audio-codec" }, + { .compatible = "sirf,atlas6-audio-codec" }, + {} +}; +MODULE_DEVICE_TABLE(of, sirf_audio_codec_of_match); + +static const struct regmap_config sirf_audio_codec_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = AUDIO_IC_CODEC_CTRL3, + .cache_type = REGCACHE_NONE, +}; + +static int sirf_audio_codec_driver_probe(struct platform_device *pdev) +{ + int ret; + struct sirf_audio_codec *sirf_audio_codec; + void __iomem *base; + struct resource *mem_res; + const struct of_device_id *match; + + match = of_match_node(sirf_audio_codec_of_match, pdev->dev.of_node); + + sirf_audio_codec = devm_kzalloc(&pdev->dev, + sizeof(struct sirf_audio_codec), GFP_KERNEL); + if (!sirf_audio_codec) + return -ENOMEM; + + platform_set_drvdata(pdev, sirf_audio_codec); + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, mem_res); + if (base == NULL) + return -ENOMEM; + + sirf_audio_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sirf_audio_codec_regmap_config); + if (IS_ERR(sirf_audio_codec->regmap)) + return PTR_ERR(sirf_audio_codec->regmap); + + sirf_audio_codec->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(sirf_audio_codec->clk)) { + dev_err(&pdev->dev, "Get clock failed.\n"); + return PTR_ERR(sirf_audio_codec->clk); + } + + ret = clk_prepare_enable(sirf_audio_codec->clk); + if (ret) { + dev_err(&pdev->dev, "Enable clock failed.\n"); + return ret; + } + + ret = snd_soc_register_codec(&(pdev->dev), + &soc_codec_device_sirf_audio_codec, + &sirf_audio_codec_dai, 1); + if (ret) { + dev_err(&pdev->dev, "Register Audio Codec dai failed.\n"); + goto err_clk_put; + } + + /* + * Always open charge pump, if not, when the charge pump closed the + * adc will not stable + */ + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, + IC_CPFREQ, IC_CPFREQ); + + if (of_device_is_compatible(pdev->dev.of_node, "sirf,atlas6-audio-codec")) + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_IC_CODEC_CTRL0, IC_CPEN, IC_CPEN); + return 0; + +err_clk_put: + clk_disable_unprepare(sirf_audio_codec->clk); + return ret; +} + +static int sirf_audio_codec_driver_remove(struct platform_device *pdev) +{ + struct sirf_audio_codec *sirf_audio_codec = platform_get_drvdata(pdev); + + clk_disable_unprepare(sirf_audio_codec->clk); + snd_soc_unregister_codec(&(pdev->dev)); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int sirf_audio_codec_suspend(struct device *dev) +{ + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev); + + regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, + &sirf_audio_codec->reg_ctrl0); + regmap_read(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1, + &sirf_audio_codec->reg_ctrl1); + clk_disable_unprepare(sirf_audio_codec->clk); + + return 0; +} + +static int sirf_audio_codec_resume(struct device *dev) +{ + struct sirf_audio_codec *sirf_audio_codec = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(sirf_audio_codec->clk); + if (ret) + return ret; + + regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL0, + sirf_audio_codec->reg_ctrl0); + regmap_write(sirf_audio_codec->regmap, AUDIO_IC_CODEC_CTRL1, + sirf_audio_codec->reg_ctrl1); + + return 0; +} +#endif + +static const struct dev_pm_ops sirf_audio_codec_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(sirf_audio_codec_suspend, sirf_audio_codec_resume) +}; + +static struct platform_driver sirf_audio_codec_driver = { + .driver = { + .name = "sirf-audio-codec", + .owner = THIS_MODULE, + .of_match_table = sirf_audio_codec_of_match, + .pm = &sirf_audio_codec_pm_ops, + }, + .probe = sirf_audio_codec_driver_probe, + .remove = sirf_audio_codec_driver_remove, +}; + +module_platform_driver(sirf_audio_codec_driver); + +MODULE_DESCRIPTION("SiRF audio codec driver"); +MODULE_AUTHOR("RongJun Ying "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/sirf-audio-codec.h b/sound/soc/codecs/sirf-audio-codec.h new file mode 100644 index 000000000000..d4c187b8e54a --- /dev/null +++ b/sound/soc/codecs/sirf-audio-codec.h @@ -0,0 +1,75 @@ +/* + * SiRF inner codec controllers define + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _SIRF_AUDIO_CODEC_H +#define _SIRF_AUDIO_CODEC_H + + +#define AUDIO_IC_CODEC_PWR (0x00E0) +#define AUDIO_IC_CODEC_CTRL0 (0x00E4) +#define AUDIO_IC_CODEC_CTRL1 (0x00E8) +#define AUDIO_IC_CODEC_CTRL2 (0x00EC) +#define AUDIO_IC_CODEC_CTRL3 (0x00F0) + +#define MICBIASEN (1 << 3) + +#define IC_RDACEN (1 << 0) +#define IC_LDACEN (1 << 1) +#define IC_HSREN (1 << 2) +#define IC_HSLEN (1 << 3) +#define IC_SPEN (1 << 4) +#define IC_CPEN (1 << 5) + +#define IC_HPRSELR (1 << 6) +#define IC_HPLSELR (1 << 7) +#define IC_HPRSELL (1 << 8) +#define IC_HPLSELL (1 << 9) +#define IC_SPSELR (1 << 10) +#define IC_SPSELL (1 << 11) + +#define IC_MONOR (1 << 12) +#define IC_MONOL (1 << 13) + +#define IC_RXOSRSEL (1 << 28) +#define IC_CPFREQ (1 << 29) +#define IC_HSINVEN (1 << 30) + +#define IC_MICINREN (1 << 0) +#define IC_MICINLEN (1 << 1) +#define IC_MICIN1SEL (1 << 2) +#define IC_MICIN2SEL (1 << 3) +#define IC_MICDIFSEL (1 << 4) +#define IC_LINEIN1SEL (1 << 5) +#define IC_LINEIN2SEL (1 << 6) +#define IC_RADCEN (1 << 7) +#define IC_LADCEN (1 << 8) +#define IC_ALM (1 << 9) + +#define IC_DIGMICEN (1 << 22) +#define IC_DIGMICFREQ (1 << 23) +#define IC_ADC14B_12 (1 << 24) +#define IC_FIRDAC_HSL_EN (1 << 25) +#define IC_FIRDAC_HSR_EN (1 << 26) +#define IC_FIRDAC_LOUT_EN (1 << 27) +#define IC_POR (1 << 28) +#define IC_CODEC_CLK_EN (1 << 29) +#define IC_HP_3DB_BOOST (1 << 30) + +#define IC_ADC_LEFT_GAIN_SHIFT 16 +#define IC_ADC_RIGHT_GAIN_SHIFT 10 +#define IC_ADC_GAIN_MASK 0x3F +#define IC_MIC_MAX_GAIN 0x39 + +#define IC_RXPGAR_MASK 0x3F +#define IC_RXPGAR_SHIFT 14 +#define IC_RXPGAL_MASK 0x3F +#define IC_RXPGAL_SHIFT 21 +#define IC_RXPGAR 0x7B +#define IC_RXPGAL 0x7B + +#endif /*__SIRF_AUDIO_CODEC_H*/ -- cgit v1.2.3 From 208a1589db3e30767223d97e39e13237328e8a6e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:42 +0100 Subject: ASoC: Handle ignore_pmdown_time for CODEC to CODEC links For CODEC to CODEC links we should only immediately power down if both CODECs are configured to ignore the power down delay. Factor the logic for this into a helper function that can be used for both compressed and normal PCMs. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 2 ++ sound/soc/soc-compress.c | 3 +-- sound/soc/soc-pcm.c | 27 +++++++++++++++++++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a001472b96a..93c31c70b90a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -413,6 +413,8 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, const char *dai_link); +bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); + /* Utility functions to get clock rates from various things */ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 5e9690c85d8f..ef585af4081b 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -235,8 +235,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream) cpu_dai->runtime = NULL; if (cstream->direction == SND_COMPRESS_PLAYBACK) { - if (!rtd->pmdown_time || codec->ignore_pmdown_time || - rtd->dai_link->ignore_pmdown_time) { + if (snd_soc_runtime_ignore_pmdown_time(rtd)) { snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, SND_SOC_DAPM_STREAM_STOP); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 47e1ce771e65..f098c8007cbe 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -34,6 +34,30 @@ #define DPCM_MAX_BE_USERS 8 +/** + * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay + * @rtd: The ASoC PCM runtime that should be checked. + * + * This function checks whether the power down delay should be ignored for a + * specific PCM runtime. Returns true if the delay is 0, if it the DAI link has + * been configured to ignore the delay, or if none of the components benefits + * from having the delay. + */ +bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) +{ + bool ignore = true; + + if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) + return true; + + if (rtd->cpu_dai->codec) + ignore &= rtd->cpu_dai->codec->ignore_pmdown_time; + + ignore &= rtd->codec_dai->codec->ignore_pmdown_time; + + return ignore; +} + /** * snd_soc_set_runtime_hwparams - set the runtime hardware parameters * @substream: the pcm substream @@ -496,8 +520,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) cpu_dai->runtime = NULL; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (!rtd->pmdown_time || codec->ignore_pmdown_time || - rtd->dai_link->ignore_pmdown_time) { + if (snd_soc_runtime_ignore_pmdown_time(rtd)) { /* powered down playback stream now */ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, -- cgit v1.2.3 From 24894b76468ed250d03f9718ddfe77b902995cbd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:43 +0100 Subject: ASoC: Add helper functions for PCM runtime 'active' management We have the same code that increments and decrements the active field of the various PCM runtime components (all with the same bugs). Factor this out into common helper functions. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 2 ++ sound/soc/soc-compress.c | 62 +++++++--------------------------- sound/soc/soc-pcm.c | 86 +++++++++++++++++++++++++++++++++++------------- 3 files changed, 78 insertions(+), 72 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 93c31c70b90a..53d15e0e6e89 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -414,6 +414,8 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, const char *dai_link); bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); +void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream); +void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream); /* Utility functions to get clock rates from various things */ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index ef585af4081b..91083e6a6b38 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -30,8 +30,6 @@ static int soc_compr_open(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *rtd = cstream->private_data; struct snd_soc_platform *platform = rtd->platform; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret = 0; mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); @@ -52,17 +50,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream) } } - if (cstream->direction == SND_COMPRESS_PLAYBACK) { - cpu_dai->playback_active++; - codec_dai->playback_active++; - } else { - cpu_dai->capture_active++; - codec_dai->capture_active++; - } - - cpu_dai->active++; - codec_dai->active++; - rtd->codec->active++; + snd_soc_runtime_activate(rtd, cstream->direction); mutex_unlock(&rtd->pcm_mutex); @@ -81,8 +69,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) struct snd_soc_pcm_runtime *fe = cstream->private_data; struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; struct snd_soc_platform *platform = fe->platform; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; - struct snd_soc_dai *codec_dai = fe->codec_dai; struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; int stream; @@ -140,17 +126,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; - if (cstream->direction == SND_COMPRESS_PLAYBACK) { - cpu_dai->playback_active++; - codec_dai->playback_active++; - } else { - cpu_dai->capture_active++; - codec_dai->capture_active++; - } - - cpu_dai->active++; - codec_dai->active++; - fe->codec->active++; + snd_soc_runtime_activate(fe, stream); mutex_unlock(&fe->card->mutex); @@ -202,23 +178,18 @@ static int soc_compr_free(struct snd_compr_stream *cstream) struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; + int stream; mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); - if (cstream->direction == SND_COMPRESS_PLAYBACK) { - cpu_dai->playback_active--; - codec_dai->playback_active--; - } else { - cpu_dai->capture_active--; - codec_dai->capture_active--; - } + if (cstream->direction == SND_COMPRESS_PLAYBACK) + stream = SNDRV_PCM_STREAM_PLAYBACK; + else + stream = SNDRV_PCM_STREAM_CAPTURE; - snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); + snd_soc_runtime_deactivate(rtd, stream); - cpu_dai->active--; - codec_dai->active--; - codec->active--; + snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); if (!cpu_dai->active) cpu_dai->rate = 0; @@ -260,26 +231,17 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; struct snd_soc_platform *platform = fe->platform; - struct snd_soc_dai *cpu_dai = fe->cpu_dai; - struct snd_soc_dai *codec_dai = fe->codec_dai; struct snd_soc_dpcm *dpcm; int stream, ret; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); - if (cstream->direction == SND_COMPRESS_PLAYBACK) { + if (cstream->direction == SND_COMPRESS_PLAYBACK) stream = SNDRV_PCM_STREAM_PLAYBACK; - cpu_dai->playback_active--; - codec_dai->playback_active--; - } else { + else stream = SNDRV_PCM_STREAM_CAPTURE; - cpu_dai->capture_active--; - codec_dai->capture_active--; - } - cpu_dai->active--; - codec_dai->active--; - fe->codec->active--; + snd_soc_runtime_deactivate(fe, stream); fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index f098c8007cbe..1a9857519d65 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -34,6 +34,66 @@ #define DPCM_MAX_BE_USERS 8 +/** + * snd_soc_runtime_activate() - Increment active count for PCM runtime components + * @rtd: ASoC PCM runtime that is activated + * @stream: Direction of the PCM stream + * + * Increments the active count for all the DAIs and components attached to a PCM + * runtime. Should typically be called when a stream is opened. + * + * Must be called with the rtd->pcm_mutex being held + */ +void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) +{ + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + + lockdep_assert_held(&rtd->pcm_mutex); + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + cpu_dai->playback_active++; + codec_dai->playback_active++; + } else { + cpu_dai->capture_active++; + codec_dai->capture_active++; + } + + cpu_dai->active++; + codec_dai->active++; + rtd->codec->active++; +} + +/** + * snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components + * @rtd: ASoC PCM runtime that is deactivated + * @stream: Direction of the PCM stream + * + * Decrements the active count for all the DAIs and components attached to a PCM + * runtime. Should typically be called when a stream is closed. + * + * Must be called with the rtd->pcm_mutex being held + */ +void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) +{ + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + + lockdep_assert_held(&rtd->pcm_mutex); + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + cpu_dai->playback_active--; + codec_dai->playback_active--; + } else { + cpu_dai->capture_active--; + codec_dai->capture_active--; + } + + cpu_dai->active--; + codec_dai->active--; + rtd->codec->active--; +} + /** * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay * @rtd: The ASoC PCM runtime that should be checked. @@ -402,16 +462,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) runtime->hw.rate_max); dynamic: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback_active++; - codec_dai->playback_active++; - } else { - cpu_dai->capture_active++; - codec_dai->capture_active++; - } - cpu_dai->active++; - codec_dai->active++; - rtd->codec->active++; + + snd_soc_runtime_activate(rtd, substream->stream); + mutex_unlock(&rtd->pcm_mutex); return 0; @@ -483,21 +536,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - cpu_dai->playback_active--; - codec_dai->playback_active--; - } else { - cpu_dai->capture_active--; - codec_dai->capture_active--; - } - - cpu_dai->active--; - codec_dai->active--; - codec->active--; + snd_soc_runtime_deactivate(rtd, substream->stream); /* clear the corresponding DAIs rate when inactive */ if (!cpu_dai->active) -- cgit v1.2.3 From a1a0cc0646e38b41bfaac94f2b84422bb1df40e0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:44 +0100 Subject: ASoC: Fix active count tracking for CODEC to CODEC links For CODEC to CODEC links we need to make sure to also manage the 'active' field of the cpu_dai CODEC. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 1a9857519d65..71a01dda1867 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -61,7 +61,9 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) cpu_dai->active++; codec_dai->active++; - rtd->codec->active++; + if (cpu_dai->codec) + cpu_dai->codec->active++; + codec_dai->codec->active++; } /** @@ -91,7 +93,9 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) cpu_dai->active--; codec_dai->active--; - rtd->codec->active--; + if (cpu_dai->codec) + cpu_dai->codec->active--; + codec_dai->codec->active--; } /** -- cgit v1.2.3 From 5c898e74d135a23ce12e0263c1a3c78eeae1b52b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:45 +0100 Subject: ASoC: Add helper function to check whether a CODEC is active Instead of directly checking the 'active' field of the CODEC struct add a new helper function that will return either true or false depending on whether the CODEC is active. This will make the migration to the component level easier. The patch also updates all CODEC drivers that check the active attribute to use the new helper function. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 5 +++++ sound/soc/codecs/adav80x.c | 4 ++-- sound/soc/codecs/tlv320aic23.c | 2 +- sound/soc/codecs/tlv320dac33.c | 2 +- sound/soc/codecs/uda1380.c | 2 +- sound/soc/codecs/wl1273.c | 2 +- sound/soc/codecs/wm8711.c | 2 +- sound/soc/codecs/wm8753.c | 4 ++-- 8 files changed, 14 insertions(+), 9 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 53d15e0e6e89..5c2b4f4b5cfa 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1172,6 +1172,11 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) return 1; } +static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec) +{ + return codec->active != 0; +} + int snd_soc_util_init(void); void snd_soc_util_exit(void); diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index f78b27a7c461..d50cf5b29a27 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -722,7 +722,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - if (!codec->active || !adav80x->rate) + if (!snd_soc_codec_is_active(codec) || !adav80x->rate) return 0; return snd_pcm_hw_constraint_minmax(substream->runtime, @@ -735,7 +735,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - if (!codec->active) + if (!snd_soc_codec_is_active(codec)) adav80x->rate = 0; } diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 5d430cc56f51..458a6aed203e 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -400,7 +400,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); /* deactivate */ - if (!codec->active) { + if (!snd_soc_codec_is_active(codec)) { udelay(50); snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); } diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 4f358393d6d6..35b2d244e42e 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -461,7 +461,7 @@ static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol, if (dac33->fifo_mode == ucontrol->value.integer.value[0]) return 0; /* Do not allow changes while stream is running*/ - if (codec->active) + if (snd_soc_codec_is_active(codec)) return -EPERM; if (ucontrol->value.integer.value[0] < 0 || diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 726df6d43c2b..8e3940dcff20 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -108,7 +108,7 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, /* the interpolator & decimator regs must only be written when the * codec DAI is active. */ - if (!codec->active && (reg >= UDA1380_MVOL)) + if (!snd_soc_codec_is_active(codec) && (reg >= UDA1380_MVOL)) return 0; pr_debug("uda1380: hw write %x val %x\n", reg, value); if (codec->hw_write(codec->control_data, data, 3) == 3) { diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c index b7ab2ef567c8..47e96ff30064 100644 --- a/sound/soc/codecs/wl1273.c +++ b/sound/soc/codecs/wl1273.c @@ -197,7 +197,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, return 0; /* Do not allow changes while stream is running */ - if (codec->active) + if (snd_soc_codec_is_active(codec)) return -EPERM; if (ucontrol->value.integer.value[0] < 0 || diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index d99f948c513c..6efcc40a7cb3 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -201,7 +201,7 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = dai->codec; /* deactivate */ - if (!codec->active) { + if (!snd_soc_codec_is_active(codec)) { udelay(50); snd_soc_write(codec, WM8711_ACTIVE, 0x0); } diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index be85da93a268..5cf4bebc5d89 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -251,7 +251,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, if (wm8753->dai_func == ucontrol->value.integer.value[0]) return 0; - if (codec->active) + if (snd_soc_codec_is_active(codec)) return -EBUSY; ioctl = snd_soc_read(codec, WM8753_IOCTL); @@ -1314,7 +1314,7 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) /* the digital mute covers the HiFi and Voice DAC's on the WM8753. * make sure we check if they are not both active when we mute */ if (mute && wm8753->dai_func == 1) { - if (!codec->active) + if (!snd_soc_codec_is_active(codec)) snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); } else { if (mute) -- cgit v1.2.3 From 6106d12947d1b05dc15ca3933eb514347d6ed726 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:46 +0100 Subject: ASoC: Add component pointer to the DAI struct Keep track of which component registered a DAI. We'll need this as componentization progresses. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 + sound/soc/soc-core.c | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 71f27c403194..8763e539c487 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -270,6 +270,7 @@ struct snd_soc_dai { /* parent platform/codec */ struct snd_soc_platform *platform; struct snd_soc_codec *codec; + struct snd_soc_component *component; struct snd_soc_card *card; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..6401e97b2e68 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3884,11 +3884,13 @@ static inline char *fmt_multiple_name(struct device *dev, /** * snd_soc_register_dai - Register a DAI with the ASoC core * - * @dai: DAI to register + * @component: The component the DAIs are registered for + * @dai_drv: DAI driver to use for the DAIs */ -static int snd_soc_register_dai(struct device *dev, +static int snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv) { + struct device *dev = component->dev; struct snd_soc_codec *codec; struct snd_soc_dai *dai; @@ -3905,6 +3907,7 @@ static int snd_soc_register_dai(struct device *dev, return -ENOMEM; } + dai->component = component; dai->dev = dev; dai->driver = dai_drv; dai->dapm.dev = dev; @@ -3962,12 +3965,14 @@ found: /** * snd_soc_register_dais - Register multiple DAIs with the ASoC core * - * @dai: Array of DAIs to register + * @component: The component the DAIs are registered for + * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs */ -static int snd_soc_register_dais(struct device *dev, +static int snd_soc_register_dais(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, size_t count) { + struct device *dev = component->dev; struct snd_soc_codec *codec; struct snd_soc_dai *dai; int i, ret = 0; @@ -3990,6 +3995,7 @@ static int snd_soc_register_dais(struct device *dev, goto err; } + dai->component = component; dai->dev = dev; dai->driver = &dai_drv[i]; if (dai->driver->id) @@ -4086,9 +4092,9 @@ __snd_soc_register_component(struct device *dev, * since it had been used snd_soc_register_dais(), */ if ((1 == num_dai) && allow_single_dai) - ret = snd_soc_register_dai(dev, dai_drv); + ret = snd_soc_register_dai(cmpnt, dai_drv); else - ret = snd_soc_register_dais(dev, dai_drv, num_dai); + ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai); if (ret < 0) { dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); goto error_component_name; -- cgit v1.2.3 From cdde4ccb14b4959bd1c96a07367bf02b746328d3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:47 +0100 Subject: ASoC: Move active count from CODEC to component There is no reason why active count tracking should only be done for CODECs but not for other components. Moving the active count from the snd_soc_codec struct to the snd_soc_component struct reduces the differences between CODECs and other components and will eventually allow component to component DAI links (Which is a prerequisite for converting CODECs to components). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 12 ++++++++++-- sound/soc/soc-pcm.c | 10 ++++------ 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 5c2b4f4b5cfa..0495b4aaeb70 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -660,6 +660,9 @@ struct snd_soc_component { const char *name; int id; struct device *dev; + + unsigned int active; + struct list_head list; struct snd_soc_dai_driver *dai_drv; @@ -687,7 +690,6 @@ struct snd_soc_codec { /* runtime */ struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ - unsigned int active; unsigned int cache_bypass:1; /* Suppress access to the cache */ unsigned int suspended:1; /* Codec is in suspend PM state */ unsigned int probed:1; /* Codec has been probed */ @@ -1172,9 +1174,15 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) return 1; } +static inline bool snd_soc_component_is_active( + struct snd_soc_component *component) +{ + return component->active != 0; +} + static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec) { - return codec->active != 0; + return snd_soc_component_is_active(&codec->component); } int snd_soc_util_init(void); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 71a01dda1867..98b46295785d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -61,9 +61,8 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream) cpu_dai->active++; codec_dai->active++; - if (cpu_dai->codec) - cpu_dai->codec->active++; - codec_dai->codec->active++; + cpu_dai->component->active++; + codec_dai->component->active++; } /** @@ -93,9 +92,8 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) cpu_dai->active--; codec_dai->active--; - if (cpu_dai->codec) - cpu_dai->codec->active--; - codec_dai->codec->active--; + cpu_dai->component->active--; + codec_dai->component->active--; } /** -- cgit v1.2.3 From 3d59400fe47e7e8bfb024cd1651433bef42e268e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Mar 2014 13:17:48 +0100 Subject: ASoC: Move ignore_pmdown_time from CODEC to component In preparation for componentization move the ignore_pmdown_time field from the snd_soc_codec struct to the snd_soc_component struct. Set it to true for non CODEC components for now. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 3 ++- sound/soc/soc-core.c | 4 +++- sound/soc/soc-pcm.c | 10 ++-------- 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 0495b4aaeb70..b14acd8228ab 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -663,6 +663,8 @@ struct snd_soc_component { unsigned int active; + unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ + struct list_head list; struct snd_soc_dai_driver *dai_drv; @@ -715,7 +717,6 @@ struct snd_soc_codec { /* dapm */ struct snd_soc_dapm_context dapm; - unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_codec_root; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6401e97b2e68..18aecd2841a8 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4127,6 +4127,8 @@ int snd_soc_register_component(struct device *dev, return -ENOMEM; } + cmpnt->ignore_pmdown_time = true; + return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, dai_drv, num_dai, true); } @@ -4325,7 +4327,7 @@ int snd_soc_register_codec(struct device *dev, codec->volatile_register = codec_drv->volatile_register; codec->readable_register = codec_drv->readable_register; codec->writable_register = codec_drv->writable_register; - codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time; + codec->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time; codec->dapm.bias_level = SND_SOC_BIAS_OFF; codec->dapm.dev = dev; codec->dapm.codec = codec; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 98b46295785d..2cedf09f6d96 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -107,17 +107,11 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream) */ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) { - bool ignore = true; - if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) return true; - if (rtd->cpu_dai->codec) - ignore &= rtd->cpu_dai->codec->ignore_pmdown_time; - - ignore &= rtd->codec_dai->codec->ignore_pmdown_time; - - return ignore; + return rtd->cpu_dai->component->ignore_pmdown_time && + rtd->codec_dai->component->ignore_pmdown_time; } /** -- cgit v1.2.3 From a731e217df3a2ee3ef9413153ed7b45e578d8687 Mon Sep 17 00:00:00 2001 From: Rongjun Ying Date: Wed, 5 Mar 2014 16:34:35 +0800 Subject: ASoC: sirf: Add SiRF audio port driver is used by SiRF internal audio codec This driver is used by SIRF internal audio codec. Use dedicated SiRF audio port TXFIFO and RXFIFO Supports two DMA channels for SiRF audio port TXFIFO and RXFIFO The audio port like as audio bus such as i2s. Signed-off-by: Rongjun Ying Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/sirf-audio-port.txt | 20 +++ sound/soc/Kconfig | 1 + sound/soc/Makefile | 1 + sound/soc/sirf/Kconfig | 8 + sound/soc/sirf/Makefile | 3 + sound/soc/sirf/sirf-audio-port.c | 194 +++++++++++++++++++++ sound/soc/sirf/sirf-audio-port.h | 62 +++++++ 7 files changed, 289 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/sirf-audio-port.txt create mode 100644 sound/soc/sirf/Kconfig create mode 100644 sound/soc/sirf/Makefile create mode 100644 sound/soc/sirf/sirf-audio-port.c create mode 100644 sound/soc/sirf/sirf-audio-port.h (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/sirf-audio-port.txt b/Documentation/devicetree/bindings/sound/sirf-audio-port.txt new file mode 100644 index 000000000000..1f66de3c8f00 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sirf-audio-port.txt @@ -0,0 +1,20 @@ +* SiRF SoC audio port + +Required properties: +- compatible: "sirf,audio-port" +- reg: Base address and size entries: +- dmas: List of DMA controller phandle and DMA request line ordered pairs. +- dma-names: Identifier string for each DMA request line in the dmas property. + These strings correspond 1:1 with the ordered pairs in dmas. + + One of the DMA channels will be responsible for transmission (should be + named "tx") and one for reception (should be named "rx"). + +Example: + +audioport: audioport@b0040000 { + compatible = "sirf,audio-port"; + reg = <0xb0040000 0x10000>; + dmas = <&dmac1 3>, <&dmac1 8>; + dma-names = "rx", "tx"; +}; diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index d62ce483a443..0060b31cc3f3 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -50,6 +50,7 @@ source "sound/soc/pxa/Kconfig" source "sound/soc/samsung/Kconfig" source "sound/soc/s6000/Kconfig" source "sound/soc/sh/Kconfig" +source "sound/soc/sirf/Kconfig" source "sound/soc/spear/Kconfig" source "sound/soc/tegra/Kconfig" source "sound/soc/txx9/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 62a1822e77bf..5f1df02984f8 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_SND_SOC) += pxa/ obj-$(CONFIG_SND_SOC) += samsung/ obj-$(CONFIG_SND_SOC) += s6000/ obj-$(CONFIG_SND_SOC) += sh/ +obj-$(CONFIG_SND_SOC) += sirf/ obj-$(CONFIG_SND_SOC) += spear/ obj-$(CONFIG_SND_SOC) += tegra/ obj-$(CONFIG_SND_SOC) += txx9/ diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig new file mode 100644 index 000000000000..75b0344d2151 --- /dev/null +++ b/sound/soc/sirf/Kconfig @@ -0,0 +1,8 @@ +config SND_SOC_SIRF + tristate "SoC Audio for the SiRF SoC chips" + depends on ARCH_SIRF || COMPILE_TEST + select SND_SOC_GENERIC_DMAENGINE_PCM + +config SND_SOC_SIRF_AUDIO_PORT + select REGMAP_MMIO + tristate diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile new file mode 100644 index 000000000000..fb012c852b28 --- /dev/null +++ b/sound/soc/sirf/Makefile @@ -0,0 +1,3 @@ +snd-soc-sirf-audio-port-objs := sirf-audio-port.o + +obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c new file mode 100644 index 000000000000..b04a53f2b4f6 --- /dev/null +++ b/sound/soc/sirf/sirf-audio-port.c @@ -0,0 +1,194 @@ +/* + * SiRF Audio port driver + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ +#include +#include +#include +#include +#include + +#include "sirf-audio-port.h" + +struct sirf_audio_port { + struct regmap *regmap; + struct snd_dmaengine_dai_dma_data playback_dma_data; + struct snd_dmaengine_dai_dma_data capture_dma_data; +}; + +static void sirf_audio_port_tx_enable(struct sirf_audio_port *port) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0); + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, + IC_TX_ENABLE, IC_TX_ENABLE); +} + +static void sirf_audio_port_tx_disable(struct sirf_audio_port *port) +{ + regmap_write(port->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_TX_CTRL, + IC_TX_ENABLE, ~IC_TX_ENABLE); +} + +static void sirf_audio_port_rx_enable(struct sirf_audio_port *port, + int channels) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_INT_MSK, 0); + regmap_write(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0); + regmap_update_bits(port->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + if (channels == 1) + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO); + else + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO); +} + +static void sirf_audio_port_rx_disable(struct sirf_audio_port *port) +{ + regmap_update_bits(port->regmap, AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO); +} + +static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) +{ + struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); + snd_soc_dai_init_dma_data(dai, &port->playback_dma_data, + &port->capture_dma_data); + return 0; +} + +static int sirf_audio_port_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct sirf_audio_port *port = snd_soc_dai_get_drvdata(dai); + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (playback) + sirf_audio_port_tx_disable(port); + else + sirf_audio_port_rx_disable(port); + break; + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (playback) + sirf_audio_port_tx_enable(port); + else + sirf_audio_port_rx_enable(port, + substream->runtime->channels); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops sirf_audio_port_dai_ops = { + .trigger = sirf_audio_port_trigger, +}; + +static struct snd_soc_dai_driver sirf_audio_port_dai = { + .probe = sirf_audio_port_dai_probe, + .name = "sirf-audio-port", + .id = 0, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &sirf_audio_port_dai_ops, +}; + +static const struct snd_soc_component_driver sirf_audio_port_component = { + .name = "sirf-audio-port", +}; + +static const struct regmap_config sirf_audio_port_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK, + .cache_type = REGCACHE_NONE, +}; + +static int sirf_audio_port_probe(struct platform_device *pdev) +{ + int ret; + struct sirf_audio_port *port; + void __iomem *base; + struct resource *mem_res; + + port = devm_kzalloc(&pdev->dev, + sizeof(struct sirf_audio_port), GFP_KERNEL); + if (!port) + return -ENOMEM; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem_res) { + dev_err(&pdev->dev, "no mem resource?\n"); + return -ENODEV; + } + + base = devm_ioremap(&pdev->dev, mem_res->start, + resource_size(mem_res)); + if (base == NULL) + return -ENOMEM; + + port->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sirf_audio_port_regmap_config); + if (IS_ERR(port->regmap)) + return PTR_ERR(port->regmap); + + ret = devm_snd_soc_register_component(&pdev->dev, + &sirf_audio_port_component, &sirf_audio_port_dai, 1); + if (ret) + return ret; + + platform_set_drvdata(pdev, port); + return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); +} + +static const struct of_device_id sirf_audio_port_of_match[] = { + { .compatible = "sirf,audio-port", }, + {} +}; +MODULE_DEVICE_TABLE(of, sirf_audio_port_of_match); + +static struct platform_driver sirf_audio_port_driver = { + .driver = { + .name = "sirf-audio-port", + .owner = THIS_MODULE, + .of_match_table = sirf_audio_port_of_match, + }, + .probe = sirf_audio_port_probe, +}; + +module_platform_driver(sirf_audio_port_driver); + +MODULE_DESCRIPTION("SiRF Audio Port driver"); +MODULE_AUTHOR("RongJun Ying "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/sirf/sirf-audio-port.h b/sound/soc/sirf/sirf-audio-port.h new file mode 100644 index 000000000000..f32dc54f4499 --- /dev/null +++ b/sound/soc/sirf/sirf-audio-port.h @@ -0,0 +1,62 @@ +/* + * SiRF Audio port controllers define + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#ifndef _SIRF_AUDIO_PORT_H +#define _SIRF_AUDIO_PORT_H + +#define AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK 0x3F +#define AUDIO_PORT_TX_FIFO_SC_OFFSET 0 +#define AUDIO_PORT_TX_FIFO_LC_OFFSET 10 +#define AUDIO_PORT_TX_FIFO_HC_OFFSET 20 + +#define TX_FIFO_SC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_SC_OFFSET) +#define TX_FIFO_LC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_LC_OFFSET) +#define TX_FIFO_HC(x) (((x) & AUDIO_PORT_TX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_TX_FIFO_HC_OFFSET) + +#define AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK 0x0F +#define AUDIO_PORT_RX_FIFO_SC_OFFSET 0 +#define AUDIO_PORT_RX_FIFO_LC_OFFSET 10 +#define AUDIO_PORT_RX_FIFO_HC_OFFSET 20 + +#define RX_FIFO_SC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_SC_OFFSET) +#define RX_FIFO_LC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_LC_OFFSET) +#define RX_FIFO_HC(x) (((x) & AUDIO_PORT_RX_FIFO_LEVEL_CHECK_MASK) \ + << AUDIO_PORT_RX_FIFO_HC_OFFSET) +#define AUDIO_PORT_IC_CODEC_TX_CTRL (0x00F4) +#define AUDIO_PORT_IC_CODEC_RX_CTRL (0x00F8) + +#define AUDIO_PORT_IC_TXFIFO_OP (0x00FC) +#define AUDIO_PORT_IC_TXFIFO_LEV_CHK (0x0100) +#define AUDIO_PORT_IC_TXFIFO_STS (0x0104) +#define AUDIO_PORT_IC_TXFIFO_INT (0x0108) +#define AUDIO_PORT_IC_TXFIFO_INT_MSK (0x010C) + +#define AUDIO_PORT_IC_RXFIFO_OP (0x0110) +#define AUDIO_PORT_IC_RXFIFO_LEV_CHK (0x0114) +#define AUDIO_PORT_IC_RXFIFO_STS (0x0118) +#define AUDIO_PORT_IC_RXFIFO_INT (0x011C) +#define AUDIO_PORT_IC_RXFIFO_INT_MSK (0x0120) + +#define AUDIO_FIFO_START (1 << 0) +#define AUDIO_FIFO_RESET (1 << 1) + +#define AUDIO_FIFO_FULL (1 << 0) +#define AUDIO_FIFO_EMPTY (1 << 1) +#define AUDIO_FIFO_OFLOW (1 << 2) +#define AUDIO_FIFO_UFLOW (1 << 3) + +#define IC_TX_ENABLE (0x03) +#define IC_RX_ENABLE_MONO (0x01) +#define IC_RX_ENABLE_STEREO (0x03) + +#endif /*__SIRF_AUDIO_PORT_H*/ -- cgit v1.2.3 From af12a31f054f55b75c8cf4a459c7bd9d1c7726a9 Mon Sep 17 00:00:00 2001 From: Rongjun Ying Date: Wed, 5 Mar 2014 16:34:36 +0800 Subject: ASoC: sirf: Add SiRF audio card This connects platform DAI, SiRF internal audio codec DAI and SiRF auido port DAI together and works as a mach driver. Signed-off-by: Rongjun Ying Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/sirf-audio.txt | 41 ++++++ sound/soc/sirf/Kconfig | 6 + sound/soc/sirf/Makefile | 2 + sound/soc/sirf/sirf-audio.c | 156 +++++++++++++++++++++ 4 files changed, 205 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/sirf-audio.txt create mode 100644 sound/soc/sirf/sirf-audio.c (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/sirf-audio.txt b/Documentation/devicetree/bindings/sound/sirf-audio.txt new file mode 100644 index 000000000000..c88882ca3704 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/sirf-audio.txt @@ -0,0 +1,41 @@ +* SiRF atlas6 and prima2 internal audio codec and port based audio setups + +Required properties: +- compatible: "sirf,sirf-audio-card" +- sirf,audio-platform: phandle for the platform node +- sirf,audio-codec: phandle for the SiRF internal codec node + +Optional properties: +- hp-pa-gpios: Need to be present if the board need control external + headphone amplifier. +- spk-pa-gpios: Need to be present if the board need control external + speaker amplifier. +- hp-switch-gpios: Need to be present if the board capable to detect jack + insertion, removal. + +Available audio endpoints for the audio-routing table: + +Board connectors: + * Headset Stereophone + * Ext Spk + * Line In + * Mic + +SiRF internal audio codec pins: + * HPOUTL + * HPOUTR + * SPKOUT + * Ext Mic + * Mic Bias + +Example: + +sound { + compatible = "sirf,sirf-audio-card"; + sirf,audio-codec = <&audiocodec>; + sirf,audio-platform = <&audioport>; + hp-pa-gpios = <&gpio 44 0>; + spk-pa-gpios = <&gpio 46 0>; + hp-switch-gpios = <&gpio 45 0>; +}; + diff --git a/sound/soc/sirf/Kconfig b/sound/soc/sirf/Kconfig index 75b0344d2151..89e89429b04a 100644 --- a/sound/soc/sirf/Kconfig +++ b/sound/soc/sirf/Kconfig @@ -3,6 +3,12 @@ config SND_SOC_SIRF depends on ARCH_SIRF || COMPILE_TEST select SND_SOC_GENERIC_DMAENGINE_PCM +config SND_SOC_SIRF_AUDIO + tristate "SoC Audio support for SiRF internal audio codec" + depends on SND_SOC_SIRF + select SND_SOC_SIRF_AUDIO_CODEC + select SND_SOC_SIRF_AUDIO_PORT + config SND_SOC_SIRF_AUDIO_PORT select REGMAP_MMIO tristate diff --git a/sound/soc/sirf/Makefile b/sound/soc/sirf/Makefile index fb012c852b28..913b93231d4e 100644 --- a/sound/soc/sirf/Makefile +++ b/sound/soc/sirf/Makefile @@ -1,3 +1,5 @@ +snd-soc-sirf-audio-objs := sirf-audio.o snd-soc-sirf-audio-port-objs := sirf-audio-port.o +obj-$(CONFIG_SND_SOC_SIRF_AUDIO) += snd-soc-sirf-audio.o obj-$(CONFIG_SND_SOC_SIRF_AUDIO_PORT) += snd-soc-sirf-audio-port.o diff --git a/sound/soc/sirf/sirf-audio.c b/sound/soc/sirf/sirf-audio.c new file mode 100644 index 000000000000..ecef51021653 --- /dev/null +++ b/sound/soc/sirf/sirf-audio.c @@ -0,0 +1,156 @@ +/* + * SiRF audio card driver + * + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct sirf_audio_card { + unsigned int gpio_hp_pa; + unsigned int gpio_spk_pa; +}; + +static int sirf_audio_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *ctrl, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); + int on = !SND_SOC_DAPM_EVENT_OFF(event); + if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) + gpio_set_value(sirf_audio_card->gpio_hp_pa, on); + return 0; +} + +static int sirf_audio_spk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *ctrl, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct sirf_audio_card *sirf_audio_card = snd_soc_card_get_drvdata(card); + int on = !SND_SOC_DAPM_EVENT_OFF(event); + + if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) + gpio_set_value(sirf_audio_card->gpio_spk_pa, on); + + return 0; +} +static const struct snd_soc_dapm_widget sirf_audio_dapm_widgets[] = { + SND_SOC_DAPM_HP("Hp", sirf_audio_hp_event), + SND_SOC_DAPM_SPK("Ext Spk", sirf_audio_spk_event), + SND_SOC_DAPM_MIC("Ext Mic", NULL), +}; + +static const struct snd_soc_dapm_route intercon[] = { + {"Hp", NULL, "HPOUTL"}, + {"Hp", NULL, "HPOUTR"}, + {"Ext Spk", NULL, "SPKOUT"}, + {"MICIN1", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "Ext Mic"}, +}; + +/* Digital audio interface glue - connects codec <--> CPU */ +static struct snd_soc_dai_link sirf_audio_dai_link[] = { + { + .name = "SiRF audio card", + .stream_name = "SiRF audio HiFi", + .codec_dai_name = "sirf-audio-codec", + }, +}; + +/* Audio machine driver */ +static struct snd_soc_card snd_soc_sirf_audio_card = { + .name = "SiRF audio card", + .owner = THIS_MODULE, + .dai_link = sirf_audio_dai_link, + .num_links = ARRAY_SIZE(sirf_audio_dai_link), + .dapm_widgets = sirf_audio_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sirf_audio_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), +}; + +static int sirf_audio_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &snd_soc_sirf_audio_card; + struct sirf_audio_card *sirf_audio_card; + int ret; + + sirf_audio_card = devm_kzalloc(&pdev->dev, sizeof(struct sirf_audio_card), + GFP_KERNEL); + if (sirf_audio_card == NULL) + return -ENOMEM; + + sirf_audio_dai_link[0].cpu_of_node = + of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); + sirf_audio_dai_link[0].platform_of_node = + of_parse_phandle(pdev->dev.of_node, "sirf,audio-platform", 0); + sirf_audio_dai_link[0].codec_of_node = + of_parse_phandle(pdev->dev.of_node, "sirf,audio-codec", 0); + sirf_audio_card->gpio_spk_pa = of_get_named_gpio(pdev->dev.of_node, + "spk-pa-gpios", 0); + sirf_audio_card->gpio_hp_pa = of_get_named_gpio(pdev->dev.of_node, + "hp-pa-gpios", 0); + if (gpio_is_valid(sirf_audio_card->gpio_spk_pa)) { + ret = devm_gpio_request_one(&pdev->dev, + sirf_audio_card->gpio_spk_pa, + GPIOF_OUT_INIT_LOW, "SPA_PA_SD"); + if (ret) { + dev_err(&pdev->dev, + "Failed to request GPIO_%d for reset: %d\n", + sirf_audio_card->gpio_spk_pa, ret); + return ret; + } + } + if (gpio_is_valid(sirf_audio_card->gpio_hp_pa)) { + ret = devm_gpio_request_one(&pdev->dev, + sirf_audio_card->gpio_hp_pa, + GPIOF_OUT_INIT_LOW, "HP_PA_SD"); + if (ret) { + dev_err(&pdev->dev, + "Failed to request GPIO_%d for reset: %d\n", + sirf_audio_card->gpio_hp_pa, ret); + return ret; + } + } + + card->dev = &pdev->dev; + snd_soc_card_set_drvdata(card, sirf_audio_card); + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) + dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret); + + return ret; +} + +static const struct of_device_id sirf_audio_of_match[] = { + {.compatible = "sirf,sirf-audio-card", }, + { }, +}; +MODULE_DEVICE_TABLE(of, sirf_audio_of_match); + +static struct platform_driver sirf_audio_driver = { + .driver = { + .name = "sirf-audio-card", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + .of_match_table = sirf_audio_of_match, + }, + .probe = sirf_audio_probe, +}; +module_platform_driver(sirf_audio_driver); + +MODULE_AUTHOR("RongJun Ying "); +MODULE_DESCRIPTION("ALSA SoC SIRF audio card driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From a1a564ed6abf62e05fcffa9ed3f46a826400df3a Mon Sep 17 00:00:00 2001 From: Nenghua Cao Date: Wed, 19 Feb 2014 18:44:58 +0800 Subject: ASoC: core: use regmap's parse_val to do endian translation In snd_soc_bytes_put function, it forces cpu to do cpu_to_be translation, but for mmio bus which uses REGMAP_ENDIAN_NATIVE, it doesn't need to do endian translation. So it is better to use regmap's api which can decide if this translation is needed according to bus configuration. Signed-off-by: Nenghua Cao Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 45a1fafdbd7b..9d25c2e0fb92 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3234,7 +3234,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, struct soc_bytes *params = (void *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); int ret, len; - unsigned int val; + unsigned int val, mask; void *data; if (!codec->using_regmap) @@ -3264,12 +3264,36 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, ((u8 *)data)[0] |= val; break; case 2: - ((u16 *)data)[0] &= cpu_to_be16(~params->mask); - ((u16 *)data)[0] |= cpu_to_be16(val); + mask = ~params->mask; + ret = regmap_parse_val(codec->control_data, + &mask, &mask); + if (ret != 0) + goto out; + + ((u16 *)data)[0] &= mask; + + ret = regmap_parse_val(codec->control_data, + &val, &val); + if (ret != 0) + goto out; + + ((u16 *)data)[0] |= val; break; case 4: - ((u32 *)data)[0] &= cpu_to_be32(~params->mask); - ((u32 *)data)[0] |= cpu_to_be32(val); + mask = ~params->mask; + ret = regmap_parse_val(codec->control_data, + &mask, &mask); + if (ret != 0) + goto out; + + ((u32 *)data)[0] &= mask; + + ret = regmap_parse_val(codec->control_data, + &val, &val); + if (ret != 0) + goto out; + + ((u32 *)data)[0] |= val; break; default: ret = -EINVAL; -- cgit v1.2.3 From fab800cc33e98378336faf75688ea0961eac21b6 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 6 Mar 2014 10:00:18 +0000 Subject: ASoC: wm_adsp: Correct type specifier in printf Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 937af6f31ffa..bb5f7b4e3ebb 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -706,7 +706,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) to_write); if (ret != 0) { adsp_err(dsp, - "%s.%d: Failed to write %d bytes at %d in %s: %d\n", + "%s.%d: Failed to write %zd bytes at %d in %s: %d\n", file, regions, to_write, offset, region_name, ret); -- cgit v1.2.3 From f69f41e1a2568f2ebdcf021fe216c1e9ba24cc1f Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 6 Mar 2014 14:56:04 +0000 Subject: ASoC: Intel: Check Haswell IPC process_reply/notification return value. Check the return value for error when processing replies and notifications. The patch 22981243589c: "ASoC: Intel: Add Haswell/Broadwell IPC" from > Feb 20, 2014, leads to the following imaginary static checker warning: > > sound/soc/intel/sst-haswell-ipc.c:898 hsw_irq_thread() > warn: this is always true. > > sound/soc/intel/sst-haswell-ipc.c > 895 /* Handle Immediate reply from DSP Core */ > 896 handled = hsw_process_reply(hsw, ipcx); > ^^^^^^^^^^^^^^^^^ > Returns 1 on success/error and -EIO on error. > > 897 > 898 if (handled) { > 899 /* clear DONE bit - tell DSP we have completed */ > 900 sst_dsp_shim_update_bits_unlocked(sst, SST_IPCX, > 901 SST_IPCX_DONE, 0); > 902 > 903 /* unmask Done interrupt */ > 904 sst_dsp_shim_update_bits_unlocked(sst, SST_IMRX, > 905 SST_IMRX_DONE, 0); > 906 } > Reported-by: Dan Carpenter Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/sst-haswell-ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/sst-haswell-ipc.c b/sound/soc/intel/sst-haswell-ipc.c index 1f1576a9586a..f46bb4ddde6f 100644 --- a/sound/soc/intel/sst-haswell-ipc.c +++ b/sound/soc/intel/sst-haswell-ipc.c @@ -895,7 +895,7 @@ static irqreturn_t hsw_irq_thread(int irq, void *context) /* Handle Immediate reply from DSP Core */ handled = hsw_process_reply(hsw, ipcx); - if (handled) { + if (handled > 0) { /* clear DONE bit - tell DSP we have completed */ sst_dsp_shim_update_bits_unlocked(sst, SST_IPCX, SST_IPCX_DONE, 0); @@ -913,7 +913,7 @@ static irqreturn_t hsw_irq_thread(int irq, void *context) handled = hsw_process_notification(hsw); /* clear BUSY bit and set DONE bit - accept new messages */ - if (handled) { + if (handled > 0) { sst_dsp_shim_update_bits_unlocked(sst, SST_IPCD, SST_IPCD_BUSY | SST_IPCD_DONE, SST_IPCD_DONE); -- cgit v1.2.3 From dd6646bcfa9c811518bfcdbd13e4f73b749646bb Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 6 Mar 2014 14:56:05 +0000 Subject: ASoC: Intel: Use .dai_fmt for setting Haswell BE format. Update the Haswell driver to use .dai_fmt in DAI link to set the format. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/haswell.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/haswell.c b/sound/soc/intel/haswell.c index 0d61197661d8..54345a2a7386 100644 --- a/sound/soc/intel/haswell.c +++ b/sound/soc/intel/haswell.c @@ -69,14 +69,6 @@ static int haswell_rt5640_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret; - /* Set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - if (ret < 0) { - dev_err(rtd->dev, "can't set codec DAI configuration\n"); - return ret; - } - ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_MCLK, 12288000, SND_SOC_CLOCK_IN); @@ -188,6 +180,8 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = { .no_pcm = 1, .codec_name = "i2c-INT33CA:00", .codec_dai_name = "rt5640-aif1", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, .ignore_suspend = 1, .ignore_pmdown_time = 1, .be_hw_params_fixup = haswell_ssp0_fixup, -- cgit v1.2.3 From a8282136a1b811edb95b3c0e1d9664510afaa307 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Thu, 6 Mar 2014 14:56:06 +0000 Subject: ASoC: Intel: Clean up indentation for Haswell machine driver/Kconfig Clean up some indentation. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 10 +++++----- sound/soc/intel/sst-haswell-dsp.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 274af1639781..4577b69fcf2c 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -31,15 +31,15 @@ config SND_SOC_INTEL_BAYTRAIL tristate config SND_SOC_INTEL_HASWELL_MACH - tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" - depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS + tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" + depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS select SND_SOC_INTEL_HASWELL select SND_SOC_RT5640 help - This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell + This adds support for the Lynxpoint Audio DSP on Intel(R) Haswell Ultrabook platforms. - Say Y if you have such a device - If unsure select "N". + Say Y if you have such a device + If unsure select "N". config SND_SOC_INTEL_BYT_RT5640_MACH tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" diff --git a/sound/soc/intel/sst-haswell-dsp.c b/sound/soc/intel/sst-haswell-dsp.c index 12f73173a792..f5ebf36af889 100644 --- a/sound/soc/intel/sst-haswell-dsp.c +++ b/sound/soc/intel/sst-haswell-dsp.c @@ -503,7 +503,7 @@ static void hsw_free(struct sst_dsp *sst) struct sst_ops haswell_ops = { .reset = hsw_reset, - .boot = hsw_boot, + .boot = hsw_boot, .write = sst_shim32_write, .read = sst_shim32_read, .write64 = sst_shim32_write64, -- cgit v1.2.3 From b3fc5725967cea8b661383742ccce21fdeb3ef72 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 6 Mar 2014 14:04:41 +0400 Subject: ASoC: tlv320aic23: add support for SPI control mode tlv320aic23 chip control interface may work in either I2C or SPI mode depending on the MODE pin state. Functionality and register layout are independent of the control mode. Implement bus-specific parts as separate modules. Signed-off-by: Max Filippov Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 11 ++++++- sound/soc/codecs/Makefile | 4 +++ sound/soc/codecs/tlv320aic23-i2c.c | 59 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tlv320aic23-spi.c | 57 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tlv320aic23.c | 55 +++++++---------------------------- sound/soc/codecs/tlv320aic23.h | 6 ++++ 6 files changed, 147 insertions(+), 45 deletions(-) create mode 100644 sound/soc/codecs/tlv320aic23-i2c.c create mode 100644 sound/soc/codecs/tlv320aic23-spi.c (limited to 'sound/soc') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..5e4fc048d42a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -71,7 +71,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_STA529 if I2C select SND_SOC_STAC9766 if SND_SOC_AC97_BUS select SND_SOC_TAS5086 if I2C - select SND_SOC_TLV320AIC23 if I2C + select SND_SOC_TLV320AIC23_I2C if I2C + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER select SND_SOC_TLV320AIC26 if SPI_MASTER select SND_SOC_TLV320AIC32X4 if I2C select SND_SOC_TLV320AIC3X if I2C @@ -357,6 +358,14 @@ config SND_SOC_TAS5086 config SND_SOC_TLV320AIC23 tristate +config SND_SOC_TLV320AIC23_I2C + tristate + select SND_SOC_TLV320AIC23 + +config SND_SOC_TLV320AIC23_SPI + tristate + select SND_SOC_TLV320AIC23 + config SND_SOC_TLV320AIC26 tristate depends on SPI diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..ed1fd8925e43 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -63,6 +63,8 @@ snd-soc-sta529-objs := sta529.o snd-soc-stac9766-objs := stac9766.o snd-soc-tas5086-objs := tas5086.o snd-soc-tlv320aic23-objs := tlv320aic23.o +snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o +snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o @@ -193,6 +195,8 @@ obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o +obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o +obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c new file mode 100644 index 000000000000..20fc46092c2c --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-i2c.c @@ -0,0 +1,59 @@ +/* + * ALSA SoC TLV320AIC23 codec driver I2C interface + * + * Author: Arun KS, + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., + * + * Based on sound/soc/codecs/wm8731.c by Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "tlv320aic23.h" + +static int tlv320aic23_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *i2c_id) +{ + struct regmap *regmap; + + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EINVAL; + + regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); + return tlv320aic23_probe(&i2c->dev, regmap); +} + +static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + return 0; +} + +static const struct i2c_device_id tlv320aic23_id[] = { + {"tlv320aic23", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); + +static struct i2c_driver tlv320aic23_i2c_driver = { + .driver = { + .name = "tlv320aic23-codec", + }, + .probe = tlv320aic23_i2c_probe, + .remove = __exit_p(tlv320aic23_i2c_remove), + .id_table = tlv320aic23_id, +}; + +module_i2c_driver(tlv320aic23_i2c_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C"); +MODULE_AUTHOR("Arun KS "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23-spi.c b/sound/soc/codecs/tlv320aic23-spi.c new file mode 100644 index 000000000000..585aea436c6a --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-spi.c @@ -0,0 +1,57 @@ +/* + * ALSA SoC TLV320AIC23 codec driver SPI interface + * + * Author: Arun KS, + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., + * + * Based on sound/soc/codecs/wm8731.c by Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "tlv320aic23.h" + +static int aic23_spi_probe(struct spi_device *spi) +{ + int ret; + struct regmap *regmap; + + dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n"); + + spi->bits_per_word = 16; + spi->mode = SPI_MODE_0; + ret = spi_setup(spi); + if (ret < 0) + return ret; + + regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap); + return tlv320aic23_probe(&spi->dev, regmap); +} + +static int aic23_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver aic23_spi = { + .driver = { + .name = "tlv320aic23", + .owner = THIS_MODULE, + }, + .probe = aic23_spi_probe, + .remove = aic23_spi_remove, +}; + +module_spi_driver(aic23_spi); + +MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI"); +MODULE_AUTHOR("Arun KS "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 139f11f4dd8b..ab369ae76b8c 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,7 @@ static const struct reg_default tlv320aic23_reg[] = { { 9, 0x0000 }, }; -static const struct regmap_config tlv320aic23_regmap = { +const struct regmap_config tlv320aic23_regmap = { .reg_bits = 7, .val_bits = 9, @@ -557,7 +556,7 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) return 0; } -static int tlv320aic23_probe(struct snd_soc_codec *codec) +static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) { int ret; @@ -604,7 +603,7 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { - .probe = tlv320aic23_probe, + .probe = tlv320aic23_codec_probe, .remove = tlv320aic23_remove, .suspend = tlv320aic23_suspend, .resume = tlv320aic23_resume, @@ -617,57 +616,25 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), }; -/* - * If the i2c layer weren't so broken, we could pass this kind of data - * around - */ -static int tlv320aic23_codec_probe(struct i2c_client *i2c, - const struct i2c_device_id *i2c_id) +int tlv320aic23_probe(struct device *dev, struct regmap *regmap) { struct aic23 *aic23; - int ret; - if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EINVAL; + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL); + aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL); if (aic23 == NULL) return -ENOMEM; - aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); - if (IS_ERR(aic23->regmap)) - return PTR_ERR(aic23->regmap); + aic23->regmap = regmap; - i2c_set_clientdata(i2c, aic23); + dev_set_drvdata(dev, aic23); - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); - return ret; -} -static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_codec(&i2c->dev); - return 0; + return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, + &tlv320aic23_dai, 1); } -static const struct i2c_device_id tlv320aic23_id[] = { - {"tlv320aic23", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); - -static struct i2c_driver tlv320aic23_i2c_driver = { - .driver = { - .name = "tlv320aic23-codec", - }, - .probe = tlv320aic23_codec_probe, - .remove = __exit_p(tlv320aic23_i2c_remove), - .id_table = tlv320aic23_id, -}; - -module_i2c_driver(tlv320aic23_i2c_driver); - MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); MODULE_AUTHOR("Arun KS "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h index e804120bd3da..3a7235a04a89 100644 --- a/sound/soc/codecs/tlv320aic23.h +++ b/sound/soc/codecs/tlv320aic23.h @@ -12,6 +12,12 @@ #ifndef _TLV320AIC23_H #define _TLV320AIC23_H +struct device; +struct regmap_config; + +extern const struct regmap_config tlv320aic23_regmap; +int tlv320aic23_probe(struct device *dev, struct regmap *regmap); + /* Codec TLV320AIC23 */ #define TLV320AIC23_LINVOL 0x00 #define TLV320AIC23_RINVOL 0x01 -- cgit v1.2.3 From cc1bc54aa787c39125fe843e81bd693e8f507c32 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 6 Mar 2014 14:04:42 +0400 Subject: ASoC: update Kconfig of AIC23 users to select I2C variant Now that AIC23 supports two control interfaces all existing I2C users should select I2C variant. Signed-off-by: Max Filippov Signed-off-by: Mark Brown --- sound/soc/atmel/Kconfig | 2 +- sound/soc/cirrus/Kconfig | 2 +- sound/soc/fsl/Kconfig | 2 +- sound/soc/omap/Kconfig | 4 ++-- sound/soc/samsung/Kconfig | 2 +- sound/soc/tegra/Kconfig | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index e634eb78ed03..4789619a52d8 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -58,6 +58,6 @@ config SND_AT91_SOC_AFEB9260 depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC select SND_ATMEL_SOC_PDC select SND_ATMEL_SOC_SSC - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y here to support sound on AFEB9260 board. diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 06f938deda15..a0bf4a610397 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig @@ -18,7 +18,7 @@ config SND_EP93XX_SOC_SNAPPERCL15 tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 select SND_EP93XX_SOC_I2S - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y or M here if you want to add support for I2S audio on the Bluewater Systems Snapper CL15 module. diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 07f8f141727d..19a18a4f133a 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -170,7 +170,7 @@ config SND_SOC_EUKREA_TLV320 || MACH_EUKREA_MBIMXSD35_BASEBOARD \ || MACH_EUKREA_MBIMXSD51_BASEBOARD depends on I2C - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C select SND_SOC_IMX_PCM_FIQ select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_SSI diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 22ad9c5654b5..e00659351a4e 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -58,7 +58,7 @@ config SND_OMAP_SOC_OSK5912 tristate "SoC Audio support for omap osk5912" depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y if you want to add support for SoC audio on osk5912. @@ -66,7 +66,7 @@ config SND_OMAP_SOC_AM3517EVM tristate "SoC Audio support for OMAP3517 / AM3517 EVM" depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 EVM. diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 454f41cfc828..47a7a1b633ae 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -117,7 +117,7 @@ config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" depends on SND_SOC_SAMSUNG && ARCH_S3C24XX select SND_S3C24XX_I2S - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C select SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_SIMTEC_HERMES diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 9f9c1856f822..31198cf7f88d 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -105,7 +105,7 @@ config SND_SOC_TEGRA_TRIMSLICE tristate "SoC Audio support for TrimSlice board" depends on SND_SOC_TEGRA && I2C select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y or M here if you want to add support for SoC audio on the TrimSlice platform. -- cgit v1.2.3 From 22066226b50e40591d67aef1d5525abce7515df2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Mar 2014 11:44:08 +0800 Subject: ASoC: pcm512x: Split out bus drivers Move to the new style of defining the bus interfaces in separate modules in order to simplify dependencies. Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 18 +++++- sound/soc/codecs/Makefile | 4 ++ sound/soc/codecs/pcm512x-i2c.c | 71 ++++++++++++++++++++++ sound/soc/codecs/pcm512x-spi.c | 69 +++++++++++++++++++++ sound/soc/codecs/pcm512x.c | 134 +++-------------------------------------- sound/soc/codecs/pcm512x.h | 9 +++ 6 files changed, 176 insertions(+), 129 deletions(-) create mode 100644 sound/soc/codecs/pcm512x-i2c.c create mode 100644 sound/soc/codecs/pcm512x-spi.c (limited to 'sound/soc') diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index fa47a8336be3..cebe3ceef4bd 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -59,7 +59,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM1681 if I2C select SND_SOC_PCM1792A if SPI_MASTER select SND_SOC_PCM3008 - select SND_SOC_PCM512x if SND_SOC_I2C_AND_SPI + select SND_SOC_PCM512x_I2C if I2C + select SND_SOC_PCM512x_SPI if SPI_MASTER select SND_SOC_RT5631 if I2C select SND_SOC_RT5640 if I2C select SND_SOC_SGTL5000 if I2C @@ -315,8 +316,19 @@ config SND_SOC_PCM3008 tristate config SND_SOC_PCM512x - tristate "Texas Instruments PCM512x CODECs" - select REGMAP + tristate + +config SND_SOC_PCM512x_I2C + tristate "Texas Instruments PCM512x CODECs - I2C" + depends on I2C + select SND_SOC_PCM512x + select REGMAP_I2C + +config SND_SOC_PCM512x_SPI + tristate "Texas Instruments PCM512x CODECs - SPI" + depends on SPI_MASTER + select SND_SOC_PCM512x + select REGMAP_SPI config SND_SOC_RT5631 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d3b536fc075d..c1191c05c88e 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -47,6 +47,8 @@ snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm1792a-codec-objs := pcm1792a.o snd-soc-pcm3008-objs := pcm3008.o snd-soc-pcm512x-objs := pcm512x.o +snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o +snd-soc-pcm512x-spi-objs := pcm512x-spi.o snd-soc-rt5631-objs := rt5631.o snd-soc-rt5640-objs := rt5640.o snd-soc-sgtl5000-objs := sgtl5000.o @@ -181,6 +183,8 @@ obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o +obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o +obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c new file mode 100644 index 000000000000..4d62230bd378 --- /dev/null +++ b/sound/soc/codecs/pcm512x-i2c.c @@ -0,0 +1,71 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + */ + +#include +#include +#include + +#include "pcm512x.h" + +static int pcm512x_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return pcm512x_probe(&i2c->dev, regmap); +} + +static int pcm512x_i2c_remove(struct i2c_client *i2c) +{ + pcm512x_remove(&i2c->dev); + return 0; +} + +static const struct i2c_device_id pcm512x_i2c_id[] = { + { "pcm5121", }, + { "pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); + +static const struct of_device_id pcm512x_of_match[] = { + { .compatible = "ti,pcm5121", }, + { .compatible = "ti,pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm512x_of_match); + +static struct i2c_driver pcm512x_i2c_driver = { + .probe = pcm512x_i2c_probe, + .remove = pcm512x_i2c_remove, + .id_table = pcm512x_i2c_id, + .driver = { + .name = "pcm512x", + .owner = THIS_MODULE, + .of_match_table = pcm512x_of_match, + .pm = &pcm512x_pm_ops, + }, +}; + +module_i2c_driver(pcm512x_i2c_driver); + +MODULE_DESCRIPTION("ASoC PCM512x codec driver - I2C"); +MODULE_AUTHOR("Mark Brown "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c new file mode 100644 index 000000000000..f297058c0038 --- /dev/null +++ b/sound/soc/codecs/pcm512x-spi.c @@ -0,0 +1,69 @@ +/* + * Driver for the PCM512x CODECs + * + * Author: Mark Brown + * Copyright 2014 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + */ + +#include +#include +#include + +#include "pcm512x.h" + +static int pcm512x_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + int ret; + + regmap = devm_regmap_init_spi(spi, &pcm512x_regmap); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + return ret; + } + + return pcm512x_probe(&spi->dev, regmap); +} + +static int pcm512x_spi_remove(struct spi_device *spi) +{ + pcm512x_remove(&spi->dev); + return 0; +} + +static const struct spi_device_id pcm512x_spi_id[] = { + { "pcm5121", }, + { "pcm5122", }, + { }, +}; +MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); + +static const struct of_device_id pcm512x_of_match[] = { + { .compatible = "ti,pcm5121", }, + { .compatible = "ti,pcm5122", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm512x_of_match); + +static struct spi_driver pcm512x_spi_driver = { + .probe = pcm512x_spi_probe, + .remove = pcm512x_spi_remove, + .id_table = pcm512x_spi_id, + .driver = { + .name = "pcm512x", + .owner = THIS_MODULE, + .of_match_table = pcm512x_of_match, + .pm = &pcm512x_pm_ops, + }, +}; + +module_spi_driver(pcm512x_spi_driver); diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 3a0bbb6ab242..0c907051cc7b 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -18,11 +18,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -375,7 +373,7 @@ static const struct regmap_range_cfg pcm512x_range = { .window_start = 0, .window_len = 0x100, }; -static const struct regmap_config pcm512x_regmap = { +const struct regmap_config pcm512x_regmap = { .reg_bits = 8, .val_bits = 8, @@ -390,15 +388,9 @@ static const struct regmap_config pcm512x_regmap = { .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults), .cache_type = REGCACHE_RBTREE, }; +EXPORT_SYMBOL_GPL(pcm512x_regmap); -static const struct of_device_id pcm512x_of_match[] = { - { .compatible = "ti,pcm5121", }, - { .compatible = "ti,pcm5122", }, - { } -}; -MODULE_DEVICE_TABLE(of, pcm512x_of_match); - -static int pcm512x_probe(struct device *dev, struct regmap *regmap) +int pcm512x_probe(struct device *dev, struct regmap *regmap) { struct pcm512x_priv *pcm512x; int i, ret; @@ -510,8 +502,9 @@ err: pcm512x->supplies); return ret; } +EXPORT_SYMBOL_GPL(pcm512x_probe); -static void pcm512x_remove(struct device *dev) +void pcm512x_remove(struct device *dev) { struct pcm512x_priv *pcm512x = dev_get_drvdata(dev); @@ -522,6 +515,7 @@ static void pcm512x_remove(struct device *dev) regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies), pcm512x->supplies); } +EXPORT_SYMBOL_GPL(pcm512x_remove); static int pcm512x_suspend(struct device *dev) { @@ -585,122 +579,10 @@ static int pcm512x_resume(struct device *dev) return 0; } -static const struct dev_pm_ops pcm512x_pm_ops = { +const struct dev_pm_ops pcm512x_pm_ops = { SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL) }; - -#if IS_ENABLED(CONFIG_I2C) -static int pcm512x_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct regmap *regmap; - - regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap); - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - - return pcm512x_probe(&i2c->dev, regmap); -} - -static int pcm512x_i2c_remove(struct i2c_client *i2c) -{ - pcm512x_remove(&i2c->dev); - return 0; -} - -static const struct i2c_device_id pcm512x_i2c_id[] = { - { "pcm5121", }, - { "pcm5122", }, - { } -}; -MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); - -static struct i2c_driver pcm512x_i2c_driver = { - .probe = pcm512x_i2c_probe, - .remove = pcm512x_i2c_remove, - .id_table = pcm512x_i2c_id, - .driver = { - .name = "pcm512x", - .owner = THIS_MODULE, - .of_match_table = pcm512x_of_match, - .pm = &pcm512x_pm_ops, - }, -}; -#endif - -#if defined(CONFIG_SPI_MASTER) -static int pcm512x_spi_probe(struct spi_device *spi) -{ - struct regmap *regmap; - int ret; - - regmap = devm_regmap_init_spi(spi, &pcm512x_regmap); - if (IS_ERR(regmap)) { - ret = PTR_ERR(regmap); - return ret; - } - - return pcm512x_probe(&spi->dev, regmap); -} - -static int pcm512x_spi_remove(struct spi_device *spi) -{ - pcm512x_remove(&spi->dev); - return 0; -} - -static const struct spi_device_id pcm512x_spi_id[] = { - { "pcm5121", }, - { "pcm5122", }, - { }, -}; -MODULE_DEVICE_TABLE(spi, pcm512x_spi_id); - -static struct spi_driver pcm512x_spi_driver = { - .probe = pcm512x_spi_probe, - .remove = pcm512x_spi_remove, - .id_table = pcm512x_spi_id, - .driver = { - .name = "pcm512x", - .owner = THIS_MODULE, - .of_match_table = pcm512x_of_match, - .pm = &pcm512x_pm_ops, - }, -}; -#endif - -static int __init pcm512x_modinit(void) -{ - int ret = 0; - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&pcm512x_i2c_driver); - if (ret) { - printk(KERN_ERR "Failed to register pcm512x I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&pcm512x_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register pcm512x SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(pcm512x_modinit); - -static void __exit pcm512x_exit(void) -{ -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&pcm512x_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&pcm512x_spi_driver); -#endif -} -module_exit(pcm512x_exit); +EXPORT_SYMBOL_GPL(pcm512x_pm_ops); MODULE_DESCRIPTION("ASoC PCM512x codec driver"); MODULE_AUTHOR("Mark Brown "); diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h index ac4a52c9ccf4..6ee76aaca09a 100644 --- a/sound/soc/codecs/pcm512x.h +++ b/sound/soc/codecs/pcm512x.h @@ -17,6 +17,9 @@ #ifndef _SND_SOC_PCM512X #define _SND_SOC_PCM512X +#include +#include + #define PCM512x_VIRT_BASE 0x100 #define PCM512x_PAGE_LEN 0x100 #define PCM512x_PAGE_BASE(n) (PCM512x_VIRT_BASE + (PCM512x_PAGE_LEN * n)) @@ -159,4 +162,10 @@ #define PCM512x_AGBR_SHIFT 0 #define PCM512x_AGBL_SHIFT 4 +extern const struct dev_pm_ops pcm512x_pm_ops; +extern const struct regmap_config pcm512x_regmap; + +int pcm512x_probe(struct device *dev, struct regmap *regmap); +void pcm512x_remove(struct device *dev); + #endif -- cgit v1.2.3 From e97db9abf99280e6ff7d9b339dd2ca4846ce2eea Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 7 Mar 2014 11:43:04 +0800 Subject: ASoC: pcm512x: Fix duplicate const warning Signed-off-by: Mark Brown --- sound/soc/codecs/pcm512x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 0c907051cc7b..4b4c0c7bb918 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -201,10 +201,10 @@ static const unsigned int pcm512x_dsp_program_values[] = { 7, }; -static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, - PCM512x_DSP_PROGRAM, 0, 0x1f, - pcm512x_dsp_program_texts, - pcm512x_dsp_program_values); +static SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program, + PCM512x_DSP_PROGRAM, 0, 0x1f, + pcm512x_dsp_program_texts, + pcm512x_dsp_program_values); static const char * const pcm512x_clk_missing_text[] = { "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s" -- cgit v1.2.3 From 40423285a10e317b8e89e430779633eaef0b4add Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 8 Mar 2014 13:31:06 +0400 Subject: ASoC: tlv320aic23: add missing EXPORT_SYMBOLs This fixes the following build errors when aic23 is configured as module: >> ERROR: "tlv320aic23_probe" >> [sound/soc/codecs/snd-soc-tlv320aic23-i2c.ko] undefined! >> ERROR: "tlv320aic23_regmap" >> [sound/soc/codecs/snd-soc-tlv320aic23-i2c.ko] undefined! Signed-off-by: Max Filippov Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic23.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index ab369ae76b8c..7b4cfef232ea 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -59,6 +59,7 @@ const struct regmap_config tlv320aic23_regmap = { .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg), .cache_type = REGCACHE_RBTREE, }; +EXPORT_SYMBOL(tlv320aic23_regmap); static const char *rec_src_text[] = { "Line", "Mic" }; static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; @@ -634,6 +635,7 @@ int tlv320aic23_probe(struct device *dev, struct regmap *regmap) return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); } +EXPORT_SYMBOL(tlv320aic23_probe); MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); MODULE_AUTHOR("Arun KS "); -- cgit v1.2.3 From da28ed585b26dc6eb0c8d897a9b842a86dd6a659 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:17 +0000 Subject: ASoC: arizona: An OUTDIV of 1 is not valid, avoid this One is not a valid value for the OUTDIV start searching at 2 instead. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index e4295fee8f13..d90804686e4e 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1406,7 +1406,7 @@ static int arizona_calc_fll(struct arizona_fll *fll, Fref /= div; /* Fvco should be over the targt; don't check the upper bound */ - div = 1; + div = 2; while (Fout * div < 90000000 * fll->vco_mult) { div++; if (div > 7) { -- cgit v1.2.3 From 87383ac5a73ff34c60d3ea483bf24cabb27fb522 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:18 +0000 Subject: ASoC: arizona: Add defines for FLL configuration constants Improve readability by adding defines for some of the constants associated with FLL configuration. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index d90804686e4e..3d4408db075f 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -53,6 +53,12 @@ #define ARIZONA_AIF_RX_ENABLES 0x1A #define ARIZONA_AIF_FORCE_WRITE 0x1B +#define ARIZONA_FLL_MAX_FREF 13500000 +#define ARIZONA_FLL_MIN_FVCO 90000000 +#define ARIZONA_FLL_MAX_REFDIV 8 +#define ARIZONA_FLL_MIN_OUTDIV 2 +#define ARIZONA_FLL_MAX_OUTDIV 7 + #define arizona_fll_err(_fll, fmt, ...) \ dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__) #define arizona_fll_warn(_fll, fmt, ...) \ @@ -1390,11 +1396,11 @@ static int arizona_calc_fll(struct arizona_fll *fll, /* Fref must be <=13.5MHz */ div = 1; cfg->refdiv = 0; - while ((Fref / div) > 13500000) { + while ((Fref / div) > ARIZONA_FLL_MAX_FREF) { div *= 2; cfg->refdiv++; - if (div > 8) { + if (div > ARIZONA_FLL_MAX_REFDIV) { arizona_fll_err(fll, "Can't scale %dMHz in to <=13.5MHz\n", Fref); @@ -1406,10 +1412,10 @@ static int arizona_calc_fll(struct arizona_fll *fll, Fref /= div; /* Fvco should be over the targt; don't check the upper bound */ - div = 2; - while (Fout * div < 90000000 * fll->vco_mult) { + div = ARIZONA_FLL_MIN_OUTDIV; + while (Fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { div++; - if (div > 7) { + if (div > ARIZONA_FLL_MAX_OUTDIV) { arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", Fout); return -EINVAL; -- cgit v1.2.3 From 61719db8141acde1a6293bbbddc733655defcc3c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:19 +0000 Subject: ASoC: arizona: Move set of OUTDIV in to arizona_apply_fll Since we know in arizona_apply_fll if we are setting the sync or ref path there is no need to set the outdiv seperately anymore. This patch moves this from arizona_enable_fll to arizona_apply_fll. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 3d4408db075f..9afd8c41d143 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1502,14 +1502,18 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base, cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT | source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT); - if (sync) - regmap_update_bits_async(arizona->regmap, base + 0x7, - ARIZONA_FLL1_GAIN_MASK, - cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); - else - regmap_update_bits_async(arizona->regmap, base + 0x9, - ARIZONA_FLL1_GAIN_MASK, - cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); + if (sync) { + regmap_update_bits(arizona->regmap, base + 0x7, + ARIZONA_FLL1_GAIN_MASK, + cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); + } else { + regmap_update_bits(arizona->regmap, base + 0x5, + ARIZONA_FLL1_OUTDIV_MASK, + cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); + regmap_update_bits(arizona->regmap, base + 0x9, + ARIZONA_FLL1_GAIN_MASK, + cfg->gain << ARIZONA_FLL1_GAIN_SHIFT); + } regmap_update_bits_async(arizona->regmap, base + 2, ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK, @@ -1546,10 +1550,6 @@ static void arizona_enable_fll(struct arizona_fll *fll, */ if (fll->ref_src >= 0 && fll->ref_freq && fll->ref_src != fll->sync_src) { - regmap_update_bits_async(arizona->regmap, fll->base + 5, - ARIZONA_FLL1_OUTDIV_MASK, - ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); - arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, false); if (fll->sync_src >= 0) { @@ -1558,10 +1558,6 @@ static void arizona_enable_fll(struct arizona_fll *fll, use_sync = true; } } else if (fll->sync_src >= 0) { - regmap_update_bits_async(arizona->regmap, fll->base + 5, - ARIZONA_FLL1_OUTDIV_MASK, - sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); - arizona_apply_fll(arizona, fll->base, sync, fll->sync_src, false); -- cgit v1.2.3 From 23f785a8bc33a98c4c384a653b9bff9c0cc3591d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:20 +0000 Subject: ASoC: arizona: Move calculation of FLL configuration Currently the FLL configuration is calculated before it is known which FLL path the configuration will be applied to. Newer versions of the IP have differences in the configuration required for each FLL path, which makes it complicated to calculate the FLL configuration in advance. This patch simply checks the validity of a requested input and output frequency before we know which FLL path they will be applied to and saves the actual calculation of the configuration until we know where the settings will be applied. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 79 ++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 35 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 9afd8c41d143..7398c69192cb 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1383,6 +1383,29 @@ struct arizona_fll_cfg { int gain; }; +static int arizona_validate_fll(struct arizona_fll *fll, + unsigned int Fref, + unsigned int Fout) +{ + unsigned int Fvco_min; + + if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) { + arizona_fll_err(fll, + "Can't scale %dMHz in to <=13.5MHz\n", + Fref); + return -EINVAL; + } + + Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult; + if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) { + arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", + Fout); + return -EINVAL; + } + + return 0; +} + static int arizona_calc_fll(struct arizona_fll *fll, struct arizona_fll_cfg *cfg, unsigned int Fref, @@ -1400,12 +1423,8 @@ static int arizona_calc_fll(struct arizona_fll *fll, div *= 2; cfg->refdiv++; - if (div > ARIZONA_FLL_MAX_REFDIV) { - arizona_fll_err(fll, - "Can't scale %dMHz in to <=13.5MHz\n", - Fref); + if (div > ARIZONA_FLL_MAX_REFDIV) return -EINVAL; - } } /* Apply the division for our remaining calculations */ @@ -1415,11 +1434,8 @@ static int arizona_calc_fll(struct arizona_fll *fll, div = ARIZONA_FLL_MIN_OUTDIV; while (Fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { div++; - if (div > ARIZONA_FLL_MAX_OUTDIV) { - arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n", - Fout); + if (div > ARIZONA_FLL_MAX_OUTDIV) return -EINVAL; - } } target = Fout * div / fll->vco_mult; cfg->outdiv = div; @@ -1536,13 +1552,12 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll) return reg & ARIZONA_FLL1_ENA; } -static void arizona_enable_fll(struct arizona_fll *fll, - struct arizona_fll_cfg *ref, - struct arizona_fll_cfg *sync) +static void arizona_enable_fll(struct arizona_fll *fll) { struct arizona *arizona = fll->arizona; int ret; bool use_sync = false; + struct arizona_fll_cfg cfg; /* * If we have both REFCLK and SYNCCLK then enable both, @@ -1550,15 +1565,21 @@ static void arizona_enable_fll(struct arizona_fll *fll, */ if (fll->ref_src >= 0 && fll->ref_freq && fll->ref_src != fll->sync_src) { - arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, + arizona_calc_fll(fll, &cfg, fll->ref_freq, fll->fout); + + arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, false); if (fll->sync_src >= 0) { - arizona_apply_fll(arizona, fll->base + 0x10, sync, + arizona_calc_fll(fll, &cfg, fll->sync_freq, fll->fout); + + arizona_apply_fll(arizona, fll->base + 0x10, &cfg, fll->sync_src, true); use_sync = true; } } else if (fll->sync_src >= 0) { - arizona_apply_fll(arizona, fll->base, sync, + arizona_calc_fll(fll, &cfg, fll->sync_freq, fll->fout); + + arizona_apply_fll(arizona, fll->base, &cfg, fll->sync_src, false); regmap_update_bits_async(arizona->regmap, fll->base + 0x11, @@ -1620,32 +1641,22 @@ static void arizona_disable_fll(struct arizona_fll *fll) int arizona_set_fll_refclk(struct arizona_fll *fll, int source, unsigned int Fref, unsigned int Fout) { - struct arizona_fll_cfg ref, sync; int ret; if (fll->ref_src == source && fll->ref_freq == Fref) return 0; - if (fll->fout) { - if (Fref > 0) { - ret = arizona_calc_fll(fll, &ref, Fref, fll->fout); - if (ret != 0) - return ret; - } - - if (fll->sync_src >= 0) { - ret = arizona_calc_fll(fll, &sync, fll->sync_freq, - fll->fout); - if (ret != 0) - return ret; - } + if (fll->fout && Fref > 0) { + ret = arizona_validate_fll(fll, Fref, fll->fout); + if (ret != 0) + return ret; } fll->ref_src = source; fll->ref_freq = Fref; if (fll->fout && Fref > 0) { - arizona_enable_fll(fll, &ref, &sync); + arizona_enable_fll(fll); } return 0; @@ -1655,7 +1666,6 @@ EXPORT_SYMBOL_GPL(arizona_set_fll_refclk); int arizona_set_fll(struct arizona_fll *fll, int source, unsigned int Fref, unsigned int Fout) { - struct arizona_fll_cfg ref, sync; int ret; if (fll->sync_src == source && @@ -1664,13 +1674,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source, if (Fout) { if (fll->ref_src >= 0) { - ret = arizona_calc_fll(fll, &ref, fll->ref_freq, - Fout); + ret = arizona_validate_fll(fll, fll->ref_freq, Fout); if (ret != 0) return ret; } - ret = arizona_calc_fll(fll, &sync, Fref, Fout); + ret = arizona_validate_fll(fll, Fref, Fout); if (ret != 0) return ret; } @@ -1680,7 +1689,7 @@ int arizona_set_fll(struct arizona_fll *fll, int source, fll->fout = Fout; if (Fout) { - arizona_enable_fll(fll, &ref, &sync); + arizona_enable_fll(fll); } else { arizona_disable_fll(fll); } -- cgit v1.2.3 From 8ccefcd265b486186c94ea70c77511e7c570347d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:21 +0000 Subject: ASoC: arizona: Don't pass Fout into arizona_calc_fll As we now calculate the FLL configuration at a later stage in the process the fout member of the FLL structure will contain the desired Fout frequency so no need to pass this in seperately. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 7398c69192cb..7b1354ae337b 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1408,13 +1408,12 @@ static int arizona_validate_fll(struct arizona_fll *fll, static int arizona_calc_fll(struct arizona_fll *fll, struct arizona_fll_cfg *cfg, - unsigned int Fref, - unsigned int Fout) + unsigned int Fref) { unsigned int target, div, gcd_fll; int i, ratio; - arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, Fout); + arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout); /* Fref must be <=13.5MHz */ div = 1; @@ -1432,12 +1431,12 @@ static int arizona_calc_fll(struct arizona_fll *fll, /* Fvco should be over the targt; don't check the upper bound */ div = ARIZONA_FLL_MIN_OUTDIV; - while (Fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { + while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { div++; if (div > ARIZONA_FLL_MAX_OUTDIV) return -EINVAL; } - target = Fout * div / fll->vco_mult; + target = fll->fout * div / fll->vco_mult; cfg->outdiv = div; arizona_fll_dbg(fll, "Fvco=%dHz\n", target); @@ -1565,19 +1564,19 @@ static void arizona_enable_fll(struct arizona_fll *fll) */ if (fll->ref_src >= 0 && fll->ref_freq && fll->ref_src != fll->sync_src) { - arizona_calc_fll(fll, &cfg, fll->ref_freq, fll->fout); + arizona_calc_fll(fll, &cfg, fll->ref_freq); arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, false); if (fll->sync_src >= 0) { - arizona_calc_fll(fll, &cfg, fll->sync_freq, fll->fout); + arizona_calc_fll(fll, &cfg, fll->sync_freq); arizona_apply_fll(arizona, fll->base + 0x10, &cfg, fll->sync_src, true); use_sync = true; } } else if (fll->sync_src >= 0) { - arizona_calc_fll(fll, &cfg, fll->sync_freq, fll->fout); + arizona_calc_fll(fll, &cfg, fll->sync_freq); arizona_apply_fll(arizona, fll->base, &cfg, fll->sync_src, false); -- cgit v1.2.3 From f641aec62c948c7754429136ad176824fbb97238 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:22 +0000 Subject: ASoC: arizona: Calculate OUTDIV first OUTDIV will remain unchanged whilst the rest of the FLL configuration is calculated so do this first. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 7b1354ae337b..1f106abf1bb0 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1415,6 +1415,18 @@ static int arizona_calc_fll(struct arizona_fll *fll, arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout); + /* Fvco should be over the targt; don't check the upper bound */ + div = ARIZONA_FLL_MIN_OUTDIV; + while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { + div++; + if (div > ARIZONA_FLL_MAX_OUTDIV) + return -EINVAL; + } + target = fll->fout * div / fll->vco_mult; + cfg->outdiv = div; + + arizona_fll_dbg(fll, "Fvco=%dHz\n", target); + /* Fref must be <=13.5MHz */ div = 1; cfg->refdiv = 0; @@ -1429,18 +1441,6 @@ static int arizona_calc_fll(struct arizona_fll *fll, /* Apply the division for our remaining calculations */ Fref /= div; - /* Fvco should be over the targt; don't check the upper bound */ - div = ARIZONA_FLL_MIN_OUTDIV; - while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { - div++; - if (div > ARIZONA_FLL_MAX_OUTDIV) - return -EINVAL; - } - target = fll->fout * div / fll->vco_mult; - cfg->outdiv = div; - - arizona_fll_dbg(fll, "Fvco=%dHz\n", target); - /* Find an appropraite FLL_FRATIO and factor it out of the target */ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { -- cgit v1.2.3 From 5a3935c7643966e4172e7a704a48a35f9b4dc668 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:23 +0000 Subject: ASoC: arizona: Calculate FLL gain last No part of the FLL calculation depends on the value determined for the gain but the gain does depend on other values. In preparation for future updates this patch moves the gain to be the last thing calculated. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 1f106abf1bb0..219d1d54f536 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1455,18 +1455,6 @@ static int arizona_calc_fll(struct arizona_fll *fll, return -EINVAL; } - for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { - if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { - cfg->gain = fll_gains[i].gain; - break; - } - } - if (i == ARRAY_SIZE(fll_gains)) { - arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", - Fref); - return -EINVAL; - } - cfg->n = target / (ratio * Fref); if (target % (ratio * Fref)) { @@ -1490,6 +1478,18 @@ static int arizona_calc_fll(struct arizona_fll *fll, cfg->lambda >>= 1; } + for (i = 0; i < ARRAY_SIZE(fll_gains); i++) { + if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) { + cfg->gain = fll_gains[i].gain; + break; + } + } + if (i == ARRAY_SIZE(fll_gains)) { + arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n", + Fref); + return -EINVAL; + } + arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n", cfg->n, cfg->theta, cfg->lambda); arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n", -- cgit v1.2.3 From d0800342bba71e7f11b2a67a29cf00c41ad1a3e4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 7 Mar 2014 16:34:25 +0000 Subject: ASoC: arizona: Support new fratio encoding on the wm5110 rev D The reference clock path on newer IP FLLs requires a different configuration, and should avoid integer mode operation. This patch adds support for both the new encoding and updates the calculation. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 130 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 101 insertions(+), 29 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 219d1d54f536..c3884861e8cb 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -53,8 +53,10 @@ #define ARIZONA_AIF_RX_ENABLES 0x1A #define ARIZONA_AIF_FORCE_WRITE 0x1B +#define ARIZONA_FLL_VCO_CORNER 141900000 #define ARIZONA_FLL_MAX_FREF 13500000 #define ARIZONA_FLL_MIN_FVCO 90000000 +#define ARIZONA_FLL_MAX_FRATIO 16 #define ARIZONA_FLL_MAX_REFDIV 8 #define ARIZONA_FLL_MIN_OUTDIV 2 #define ARIZONA_FLL_MAX_OUTDIV 7 @@ -1406,9 +1408,99 @@ static int arizona_validate_fll(struct arizona_fll *fll, return 0; } +static int arizona_find_fratio(unsigned int Fref, int *fratio) +{ + int i; + + /* Find an appropriate FLL_FRATIO */ + for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { + if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { + if (fratio) + *fratio = fll_fratios[i].fratio; + return fll_fratios[i].ratio; + } + } + + return -EINVAL; +} + +static int arizona_calc_fratio(struct arizona_fll *fll, + struct arizona_fll_cfg *cfg, + unsigned int target, + unsigned int Fref, bool sync) +{ + int init_ratio, ratio; + int refdiv, div; + + /* Fref must be <=13.5MHz, find initial refdiv */ + div = 1; + cfg->refdiv = 0; + while (Fref > ARIZONA_FLL_MAX_FREF) { + div *= 2; + Fref /= 2; + cfg->refdiv++; + + if (div > ARIZONA_FLL_MAX_REFDIV) + return -EINVAL; + } + + /* Find an appropriate FLL_FRATIO */ + init_ratio = arizona_find_fratio(Fref, &cfg->fratio); + if (init_ratio < 0) { + arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", + Fref); + return init_ratio; + } + + switch (fll->arizona->type) { + case WM5110: + if (fll->arizona->rev < 3 || sync) + return init_ratio; + break; + default: + return init_ratio; + } + + cfg->fratio = init_ratio - 1; + + /* Adjust FRATIO/refdiv to avoid integer mode if possible */ + refdiv = cfg->refdiv; + + while (div <= ARIZONA_FLL_MAX_REFDIV) { + for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO; + ratio++) { + if (target % (ratio * Fref)) { + cfg->refdiv = refdiv; + cfg->fratio = ratio - 1; + return ratio; + } + } + + for (ratio = init_ratio - 1; ratio >= 0; ratio--) { + if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) < + Fref) + break; + + if (target % (ratio * Fref)) { + cfg->refdiv = refdiv; + cfg->fratio = ratio - 1; + return ratio; + } + } + + div *= 2; + Fref /= 2; + refdiv++; + init_ratio = arizona_find_fratio(Fref, NULL); + } + + arizona_fll_warn(fll, "Falling back to integer mode operation\n"); + return cfg->fratio + 1; +} + static int arizona_calc_fll(struct arizona_fll *fll, struct arizona_fll_cfg *cfg, - unsigned int Fref) + unsigned int Fref, bool sync) { unsigned int target, div, gcd_fll; int i, ratio; @@ -1427,33 +1519,13 @@ static int arizona_calc_fll(struct arizona_fll *fll, arizona_fll_dbg(fll, "Fvco=%dHz\n", target); - /* Fref must be <=13.5MHz */ - div = 1; - cfg->refdiv = 0; - while ((Fref / div) > ARIZONA_FLL_MAX_FREF) { - div *= 2; - cfg->refdiv++; - - if (div > ARIZONA_FLL_MAX_REFDIV) - return -EINVAL; - } + /* Find an appropriate FLL_FRATIO and refdiv */ + ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync); + if (ratio < 0) + return ratio; /* Apply the division for our remaining calculations */ - Fref /= div; - - /* Find an appropraite FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - cfg->fratio = fll_fratios[i].fratio; - ratio = fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n", - Fref); - return -EINVAL; - } + Fref = Fref / (1 << cfg->refdiv); cfg->n = target / (ratio * Fref); @@ -1564,19 +1636,19 @@ static void arizona_enable_fll(struct arizona_fll *fll) */ if (fll->ref_src >= 0 && fll->ref_freq && fll->ref_src != fll->sync_src) { - arizona_calc_fll(fll, &cfg, fll->ref_freq); + arizona_calc_fll(fll, &cfg, fll->ref_freq, false); arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src, false); if (fll->sync_src >= 0) { - arizona_calc_fll(fll, &cfg, fll->sync_freq); + arizona_calc_fll(fll, &cfg, fll->sync_freq, true); arizona_apply_fll(arizona, fll->base + 0x10, &cfg, fll->sync_src, true); use_sync = true; } } else if (fll->sync_src >= 0) { - arizona_calc_fll(fll, &cfg, fll->sync_freq); + arizona_calc_fll(fll, &cfg, fll->sync_freq, false); arizona_apply_fll(arizona, fll->base, &cfg, fll->sync_src, false); -- cgit v1.2.3 From 64ebdec36a2a70dc9805c7172b50c43d868dedb6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 7 Mar 2014 15:03:55 +0200 Subject: ASoC: davinci-mcasp: Rename the pointer to davinci dma_params as dma_params It is quite confusing to name the pointer to davinci_pcm_dma_params as dma_data. Rename the pointer to avoid confusion. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 44 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 35b9b5505f07..b0ae0677f023 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -1025,7 +1025,7 @@ nodata: static int davinci_mcasp_probe(struct platform_device *pdev) { - struct davinci_pcm_dma_params *dma_data; + struct davinci_pcm_dma_params *dma_params; struct resource *mem, *ioarea, *res, *dat; struct davinci_mcasp_pdata *pdata; struct davinci_mcasp *mcasp; @@ -1094,41 +1094,41 @@ static int davinci_mcasp_probe(struct platform_device *pdev) if (dat) mcasp->dat_port = true; - dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_pool = pdata->sram_pool; - dma_data->sram_size = pdata->sram_size_playback; + dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; + dma_params->asp_chan_q = pdata->asp_chan_q; + dma_params->ram_chan_q = pdata->ram_chan_q; + dma_params->sram_pool = pdata->sram_pool; + dma_params->sram_size = pdata->sram_size_playback; if (dat) - dma_data->dma_addr = dat->start; + dma_params->dma_addr = dat->start; else - dma_data->dma_addr = mem->start + pdata->tx_dma_offset; + dma_params->dma_addr = mem->start + pdata->tx_dma_offset; /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_data->dma_addr; + mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_params->dma_addr; res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (res) - dma_data->channel = res->start; + dma_params->channel = res->start; else - dma_data->channel = pdata->tx_dma_channel; + dma_params->channel = pdata->tx_dma_channel; - dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_pool = pdata->sram_pool; - dma_data->sram_size = pdata->sram_size_capture; + dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; + dma_params->asp_chan_q = pdata->asp_chan_q; + dma_params->ram_chan_q = pdata->ram_chan_q; + dma_params->sram_pool = pdata->sram_pool; + dma_params->sram_size = pdata->sram_size_capture; if (dat) - dma_data->dma_addr = dat->start; + dma_params->dma_addr = dat->start; else - dma_data->dma_addr = mem->start + pdata->rx_dma_offset; + dma_params->dma_addr = mem->start + pdata->rx_dma_offset; /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_data->dma_addr; + mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_params->dma_addr; if (mcasp->version < MCASP_VERSION_3) { mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; - /* dma_data->dma_addr is pointing to the data port address */ + /* dma_params->dma_addr is pointing to the data port address */ mcasp->dat_port = true; } else { mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; @@ -1136,9 +1136,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_DMA, 1); if (res) - dma_data->channel = res->start; + dma_params->channel = res->start; else - dma_data->channel = pdata->rx_dma_channel; + dma_params->channel = pdata->rx_dma_channel; /* Unconditional dmaengine stuff */ mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = "tx"; -- cgit v1.2.3 From b46f2c5c0054153a6e5f76b6a943df5d837879f6 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Fri, 7 Mar 2014 14:58:32 +0200 Subject: ASoC: tlv320aic32x4: Sort Makefile in alphabetic order The tlv320aic32x4 related lines were wrongly placed after tlv320aic3x lines. Signed-off-by: Jyri Sarha Signed-off-by: Mark Brown --- sound/soc/codecs/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..1deeb20fd411 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -64,8 +64,8 @@ snd-soc-stac9766-objs := stac9766.o snd-soc-tas5086-objs := tas5086.o snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic26-objs := tlv320aic26.o -snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o +snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o @@ -194,8 +194,8 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o -obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o +obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o -- cgit v1.2.3 From 12ffa6fc1958879a81b6af1624c1a2edd83ec04a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 9 Mar 2014 19:37:56 -0700 Subject: ASoC: simple-card: card name can be option snd_card.name is now option on DT case. non-DT case can follow same style, and it is understandable from platform point of view. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 7cabcc5c8703..5dd47691ba41 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -287,7 +287,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) } if (!cinfo->name || - !cinfo->card || !cinfo->codec_dai.name || !cinfo->codec || !cinfo->platform || @@ -296,7 +295,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) return -EINVAL; } - priv->snd_card.name = cinfo->card; + priv->snd_card.name = (cinfo->card) ? cinfo->card : cinfo->name; dai_link->name = cinfo->name; dai_link->stream_name = cinfo->name; dai_link->platform_name = cinfo->platform; -- cgit v1.2.3 From b0ffe9b1ab8705eeffa72feacd791ab6fdd2a06c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 8 Mar 2014 15:47:22 +0100 Subject: ASoC: sam9g20_wm8731: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. While we are at it also remove the snd_soc_dapm_enable_pin() in the init callback. Pins are enabled by default. Signed-off-by: Lars-Peter Clausen Tested-by: Bo Shen Acked-by: Bo Shen Signed-off-by: Mark Brown --- sound/soc/atmel/sam9g20_wm8731.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index f15bff1548f8..174bd546c08b 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -155,25 +155,14 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) return ret; } - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets, - ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); - /* Set up specific audio path interconnects */ - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - /* not connected */ snd_soc_dapm_nc_pin(dapm, "RLINEIN"); snd_soc_dapm_nc_pin(dapm, "LLINEIN"); -#ifdef ENABLE_MIC_INPUT - snd_soc_dapm_enable_pin(dapm, "Int Mic"); -#else - snd_soc_dapm_nc_pin(dapm, "Int Mic"); +#ifndef ENABLE_MIC_INPUT + snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic"); #endif - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - return 0; } @@ -194,6 +183,11 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = { .dai_link = &at91sam9g20ek_dai, .num_links = 1, .set_bias_level = at91sam9g20ek_set_bias_level, + + .dapm_widgets = at91sam9g20ek_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets), + .dapm_routes = intercon, + .num_dapm_routes = ARRAY_SIZE(intercon), }; static int at91sam9g20ek_audio_probe(struct platform_device *pdev) -- cgit v1.2.3 From 32c9ba544b65991b14ede102928c552ed24d4827 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Mar 2014 17:41:45 +0100 Subject: ASoC: Consolidate snd_soc_register_dai() and snd_soc_register_dais() snd_soc_register_dais() has basically the same code as snd_soc_register_dai(), but running in a loop. The only difference is that snd_soc_register_dai() calls fmt_single_name() to generate the DAIs name and snd_soc_register_dais() calls fmt_multiple_name(). This patch pushes the check in __snd_soc_register_component() which decides whether to call snd_soc_register_dai() or snd_soc_register_dais() to snd_soc_register_dais() to decide which naming scheme to use. This allows us to remove snd_soc_register_dai(). The patch also updates snd_soc_register_dais() to unregister every DAI it finds for the component rather than trying to unregister one DAI for each DAI that was registered. Both have the same result since there won't be more DAIs than what have been registered, but the former is easier to implement. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 154 ++++++++++++++------------------------------------- 1 file changed, 42 insertions(+), 112 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 255eca9afc9b..c365be98b0c3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3906,100 +3906,47 @@ static inline char *fmt_multiple_name(struct device *dev, } /** - * snd_soc_register_dai - Register a DAI with the ASoC core + * snd_soc_unregister_dai - Unregister DAIs from the ASoC core * - * @component: The component the DAIs are registered for - * @dai_drv: DAI driver to use for the DAIs + * @component: The component for which the DAIs should be unregistered */ -static int snd_soc_register_dai(struct snd_soc_component *component, - struct snd_soc_dai_driver *dai_drv) +static void snd_soc_unregister_dais(struct snd_soc_component *component) { - struct device *dev = component->dev; - struct snd_soc_codec *codec; - struct snd_soc_dai *dai; - - dev_dbg(dev, "ASoC: dai register %s\n", dev_name(dev)); - - dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); - if (dai == NULL) - return -ENOMEM; - - /* create DAI component name */ - dai->name = fmt_single_name(dev, &dai->id); - if (dai->name == NULL) { - kfree(dai); - return -ENOMEM; - } - - dai->component = component; - dai->dev = dev; - dai->driver = dai_drv; - dai->dapm.dev = dev; - if (!dai->driver->ops) - dai->driver->ops = &null_dai_ops; + struct snd_soc_dai *dai, *_dai; mutex_lock(&client_mutex); + list_for_each_entry_safe(dai, _dai, &dai_list, list) { + if (dai->dev != component->dev) + continue; - list_for_each_entry(codec, &codec_list, list) { - if (codec->dev == dev) { - dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n", - dai->name, codec->name); - dai->codec = codec; - break; - } - } - - if (!dai->codec) - dai->dapm.idle_bias_off = 1; - - list_add(&dai->list, &dai_list); - - mutex_unlock(&client_mutex); - - dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); - - return 0; -} - -/** - * snd_soc_unregister_dai - Unregister a DAI from the ASoC core - * - * @dai: DAI to unregister - */ -static void snd_soc_unregister_dai(struct device *dev) -{ - struct snd_soc_dai *dai; + list_del(&dai->list); - list_for_each_entry(dai, &dai_list, list) { - if (dev == dai->dev) - goto found; + dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", + dai->name); + kfree(dai->name); + kfree(dai); } - return; - -found: - mutex_lock(&client_mutex); - list_del(&dai->list); mutex_unlock(&client_mutex); - - dev_dbg(dev, "ASoC: Unregistered DAI '%s'\n", dai->name); - kfree(dai->name); - kfree(dai); } /** - * snd_soc_register_dais - Register multiple DAIs with the ASoC core + * snd_soc_register_dais - Register a DAI with the ASoC core * * @component: The component the DAIs are registered for * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs + * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the + * parent's name. */ static int snd_soc_register_dais(struct snd_soc_component *component, - struct snd_soc_dai_driver *dai_drv, size_t count) + struct snd_soc_dai_driver *dai_drv, size_t count, + bool legacy_dai_naming) { struct device *dev = component->dev; struct snd_soc_codec *codec; struct snd_soc_dai *dai; - int i, ret = 0; + unsigned int i; + int ret; dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); @@ -4011,21 +3958,32 @@ static int snd_soc_register_dais(struct snd_soc_component *component, goto err; } - /* create DAI component name */ - dai->name = fmt_multiple_name(dev, &dai_drv[i]); + /* + * Back in the old days when we still had component-less DAIs, + * instead of having a static name, component-less DAIs would + * inherit the name of the parent device so it is possible to + * register multiple instances of the DAI. We still need to keep + * the same naming style even though those DAIs are not + * component-less anymore. + */ + if (count == 1 && legacy_dai_naming) { + dai->name = fmt_single_name(dev, &dai->id); + } else { + dai->name = fmt_multiple_name(dev, &dai_drv[i]); + if (dai_drv[i].id) + dai->id = dai_drv[i].id; + else + dai->id = i; + } if (dai->name == NULL) { kfree(dai); - ret = -EINVAL; + ret = -ENOMEM; goto err; } dai->component = component; dai->dev = dev; dai->driver = &dai_drv[i]; - if (dai->driver->id) - dai->id = dai->driver->id; - else - dai->id = i; dai->dapm.dev = dev; if (!dai->driver->ops) dai->driver->ops = &null_dai_ops; @@ -4034,8 +3992,7 @@ static int snd_soc_register_dais(struct snd_soc_component *component, list_for_each_entry(codec, &codec_list, list) { if (codec->dev == dev) { - dev_dbg(dev, - "ASoC: Mapped DAI %s to CODEC %s\n", + dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n", dai->name, codec->name); dai->codec = codec; break; @@ -4049,32 +4006,17 @@ static int snd_soc_register_dais(struct snd_soc_component *component, mutex_unlock(&client_mutex); - dev_dbg(dai->dev, "ASoC: Registered DAI '%s'\n", dai->name); + dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); } return 0; err: - for (i--; i >= 0; i--) - snd_soc_unregister_dai(dev); + snd_soc_unregister_dais(component); return ret; } -/** - * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core - * - * @dai: Array of DAIs to unregister - * @count: Number of DAIs - */ -static void snd_soc_unregister_dais(struct device *dev, size_t count) -{ - int i; - - for (i = 0; i < count; i++) - snd_soc_unregister_dai(dev); -} - /** * snd_soc_register_component - Register a component with the ASoC core * @@ -4106,19 +4048,7 @@ __snd_soc_register_component(struct device *dev, cmpnt->dai_drv = dai_drv; cmpnt->num_dai = num_dai; - /* - * snd_soc_register_dai() uses fmt_single_name(), and - * snd_soc_register_dais() uses fmt_multiple_name() - * for dai->name which is used for name based matching - * - * this function is used from cpu/codec. - * allow_single_dai flag can ignore "codec" driver reworking - * since it had been used snd_soc_register_dais(), - */ - if ((1 == num_dai) && allow_single_dai) - ret = snd_soc_register_dai(cmpnt, dai_drv); - else - ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai); + ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, allow_single_dai); if (ret < 0) { dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); goto error_component_name; @@ -4173,7 +4103,7 @@ void snd_soc_unregister_component(struct device *dev) return; found: - snd_soc_unregister_dais(dev, cmpnt->num_dai); + snd_soc_unregister_dais(cmpnt); mutex_lock(&client_mutex); list_del(&cmpnt->list); -- cgit v1.2.3 From 6cc240f39d393c5878bc6cf053aa0fe8e3fe4260 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Mar 2014 17:41:46 +0100 Subject: ASoC: Pass CODEC to snd_soc_register_dais() snd_soc_register_dais() looks up the CODEC that is registering the DAIs by looping over all registered CODECs. This patch updates the code to simply pass the CODEC that registers the DAIs to snd_soc_register_dais() thus avoiding the lookup. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c365be98b0c3..cc522418e9c4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3933,17 +3933,18 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component) * snd_soc_register_dais - Register a DAI with the ASoC core * * @component: The component the DAIs are registered for + * @codec: The CODEC that the DAIs are registered for, NULL if the component is + * not a CODEC. * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the * parent's name. */ static int snd_soc_register_dais(struct snd_soc_component *component, - struct snd_soc_dai_driver *dai_drv, size_t count, - bool legacy_dai_naming) + struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, + size_t count, bool legacy_dai_naming) { struct device *dev = component->dev; - struct snd_soc_codec *codec; struct snd_soc_dai *dai; unsigned int i; int ret; @@ -3982,28 +3983,19 @@ static int snd_soc_register_dais(struct snd_soc_component *component, } dai->component = component; + dai->codec = codec; dai->dev = dev; dai->driver = &dai_drv[i]; dai->dapm.dev = dev; if (!dai->driver->ops) dai->driver->ops = &null_dai_ops; - mutex_lock(&client_mutex); - - list_for_each_entry(codec, &codec_list, list) { - if (codec->dev == dev) { - dev_dbg(dev, "ASoC: Mapped DAI %s to CODEC %s\n", - dai->name, codec->name); - dai->codec = codec; - break; - } - } if (!dai->codec) dai->dapm.idle_bias_off = 1; + mutex_lock(&client_mutex); list_add(&dai->list, &dai_list); - mutex_unlock(&client_mutex); dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); @@ -4025,6 +4017,7 @@ static int __snd_soc_register_component(struct device *dev, struct snd_soc_component *cmpnt, const struct snd_soc_component_driver *cmpnt_drv, + struct snd_soc_codec *codec, struct snd_soc_dai_driver *dai_drv, int num_dai, bool allow_single_dai) { @@ -4048,7 +4041,8 @@ __snd_soc_register_component(struct device *dev, cmpnt->dai_drv = dai_drv; cmpnt->num_dai = num_dai; - ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, allow_single_dai); + ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, + allow_single_dai); if (ret < 0) { dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); goto error_component_name; @@ -4083,7 +4077,7 @@ int snd_soc_register_component(struct device *dev, cmpnt->ignore_pmdown_time = true; - return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, + return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, NULL, dai_drv, num_dai, true); } EXPORT_SYMBOL_GPL(snd_soc_register_component); @@ -4304,7 +4298,7 @@ int snd_soc_register_codec(struct device *dev, /* register component */ ret = __snd_soc_register_component(dev, &codec->component, &codec_drv->component_driver, - dai_drv, num_dai, false); + codec, dai_drv, num_dai, false); if (ret < 0) { dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); goto fail_codec_name; -- cgit v1.2.3 From 1438c2f60ba955114cff3717f1a334878c7886a9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Mar 2014 17:41:47 +0100 Subject: ASoC: Add a per component dai list Now that every DAI has a component we can track the DAIs on a per component basis. This simplifies the DAI lookup when we are only interested in DAIs of a specific component and also makes it possible to have multiple components with the same parent device and also register DAIs. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- include/sound/soc.h | 2 ++ sound/soc/soc-core.c | 76 +++++++++++++++++++++++----------------------------- 2 files changed, 36 insertions(+), 42 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index b14acd8228ab..37b470c1e127 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -671,6 +671,8 @@ struct snd_soc_component { int num_dai; const struct snd_soc_component_driver *driver; + + struct list_head dai_list; }; /* SoC Audio Codec device */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index cc522418e9c4..f34f1a01fce1 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -56,7 +56,6 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); #endif static DEFINE_MUTEX(client_mutex); -static LIST_HEAD(dai_list); static LIST_HEAD(platform_list); static LIST_HEAD(codec_list); static LIST_HEAD(component_list); @@ -370,18 +369,22 @@ static ssize_t dai_list_read_file(struct file *file, char __user *user_buf, { char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); ssize_t len, ret = 0; + struct snd_soc_component *component; struct snd_soc_dai *dai; if (!buf) return -ENOMEM; - list_for_each_entry(dai, &dai_list, list) { - len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", dai->name); - if (len >= 0) - ret += len; - if (ret > PAGE_SIZE) { - ret = PAGE_SIZE; - break; + list_for_each_entry(component, &component_list, list) { + list_for_each_entry(dai, &component->dai_list, list) { + len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", + dai->name); + if (len >= 0) + ret += len; + if (ret > PAGE_SIZE) { + ret = PAGE_SIZE; + break; + } } } @@ -855,6 +858,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) { struct snd_soc_dai_link *dai_link = &card->dai_link[num]; struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; + struct snd_soc_component *component; struct snd_soc_codec *codec; struct snd_soc_platform *platform; struct snd_soc_dai *codec_dai, *cpu_dai; @@ -863,18 +867,20 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); /* Find CPU DAI from registered DAIs*/ - list_for_each_entry(cpu_dai, &dai_list, list) { + list_for_each_entry(component, &component_list, list) { if (dai_link->cpu_of_node && - (cpu_dai->dev->of_node != dai_link->cpu_of_node)) + component->dev->of_node != dai_link->cpu_of_node) continue; if (dai_link->cpu_name && - strcmp(dev_name(cpu_dai->dev), dai_link->cpu_name)) - continue; - if (dai_link->cpu_dai_name && - strcmp(cpu_dai->name, dai_link->cpu_dai_name)) + strcmp(dev_name(component->dev), dai_link->cpu_name)) continue; + list_for_each_entry(cpu_dai, &component->dai_list, list) { + if (dai_link->cpu_dai_name && + strcmp(cpu_dai->name, dai_link->cpu_dai_name)) + continue; - rtd->cpu_dai = cpu_dai; + rtd->cpu_dai = cpu_dai; + } } if (!rtd->cpu_dai) { @@ -899,12 +905,10 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) * CODEC found, so find CODEC DAI from registered DAIs from * this CODEC */ - list_for_each_entry(codec_dai, &dai_list, list) { - if (codec->dev == codec_dai->dev && - !strcmp(codec_dai->name, - dai_link->codec_dai_name)) { - + list_for_each_entry(codec_dai, &codec->component.dai_list, list) { + if (!strcmp(codec_dai->name, dai_link->codec_dai_name)) { rtd->codec_dai = codec_dai; + break; } } @@ -1128,12 +1132,8 @@ static int soc_probe_codec(struct snd_soc_card *card, driver->num_dapm_widgets); /* Create DAPM widgets for each DAI stream */ - list_for_each_entry(dai, &dai_list, list) { - if (dai->dev != codec->dev) - continue; - + list_for_each_entry(dai, &codec->component.dai_list, list) snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); - } codec->dapm.idle_bias_off = driver->idle_bias_off; @@ -1180,6 +1180,7 @@ static int soc_probe_platform(struct snd_soc_card *card, { int ret = 0; const struct snd_soc_platform_driver *driver = platform->driver; + struct snd_soc_component *component; struct snd_soc_dai *dai; platform->card = card; @@ -1195,11 +1196,11 @@ static int soc_probe_platform(struct snd_soc_card *card, driver->dapm_widgets, driver->num_dapm_widgets); /* Create DAPM widgets for each DAI stream */ - list_for_each_entry(dai, &dai_list, list) { - if (dai->dev != platform->dev) + list_for_each_entry(component, &component_list, list) { + if (component->dev != platform->dev) continue; - - snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); + list_for_each_entry(dai, &component->dai_list, list) + snd_soc_dapm_new_dai_widgets(&platform->dapm, dai); } platform->dapm.idle_bias_off = 1; @@ -3912,21 +3913,14 @@ static inline char *fmt_multiple_name(struct device *dev, */ static void snd_soc_unregister_dais(struct snd_soc_component *component) { - struct snd_soc_dai *dai, *_dai; - - mutex_lock(&client_mutex); - list_for_each_entry_safe(dai, _dai, &dai_list, list) { - if (dai->dev != component->dev) - continue; - - list_del(&dai->list); + struct snd_soc_dai *dai; + list_for_each_entry(dai, &component->dai_list, list) { dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", dai->name); kfree(dai->name); kfree(dai); } - mutex_unlock(&client_mutex); } /** @@ -3990,13 +3984,10 @@ static int snd_soc_register_dais(struct snd_soc_component *component, if (!dai->driver->ops) dai->driver->ops = &null_dai_ops; - if (!dai->codec) dai->dapm.idle_bias_off = 1; - mutex_lock(&client_mutex); - list_add(&dai->list, &dai_list); - mutex_unlock(&client_mutex); + list_add(&dai->list, &component->dai_list); dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name); } @@ -4040,6 +4031,7 @@ __snd_soc_register_component(struct device *dev, cmpnt->driver = cmpnt_drv; cmpnt->dai_drv = dai_drv; cmpnt->num_dai = num_dai; + INIT_LIST_HEAD(&cmpnt->dai_list); ret = snd_soc_register_dais(cmpnt, codec, dai_drv, num_dai, allow_single_dai); -- cgit v1.2.3 From 492c0a18b7b4f171b5af382541e72541de69f545 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 6 Mar 2014 16:15:48 +0800 Subject: ASoC: dapm: Staticise dapm_mark_dirty() The function is not called outside soc-dapm.c so there is no need for it to be exported. Signed-off-by: Mark Brown --- include/sound/soc-dapm.h | 1 - sound/soc/soc-dapm.c | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 3b991766a8f2..05aaaf689ac0 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -471,7 +471,6 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec); /* Mostly internal - should not normally be used */ -void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason); void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm); /* dapm path query */ diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 77743e51420a..5a4376b41926 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -146,7 +146,7 @@ static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w) return !list_empty(&w->dirty); } -void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) +static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) { if (!dapm_dirty_widget(w)) { dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n", @@ -154,7 +154,6 @@ void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty); } } -EXPORT_SYMBOL_GPL(dapm_mark_dirty); void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) { -- cgit v1.2.3 From f9fa2b1855a9ece2ec2a4f54b7f9131cd89257d6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 6 Mar 2014 16:49:11 +0800 Subject: ASoC: dapm: Sprinkle lockdep asserts through the code Try to spot locking issues by asserting that the DAPM mutex is held when it should be. There's a bit of fun due to us not requiring the lock to be held prior to the card being instantiated which mean we need to wrap the assert in some paths and this isn't methodical by any stretch of the imagination. Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'sound/soc') diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 5a4376b41926..5c01ac1cfc0a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -115,6 +115,12 @@ static int dapm_down_seq[] = { [snd_soc_dapm_post] = 14, }; +static void dapm_assert_locked(struct snd_soc_dapm_context *dapm) +{ + if (dapm->card && dapm->card->instantiated) + lockdep_assert_held(&dapm->card->dapm_mutex); +} + static void pop_wait(u32 pop_time) { if (pop_time) @@ -148,6 +154,8 @@ static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w) static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) { + dapm_assert_locked(w->dapm); + if (!dapm_dirty_widget(w)) { dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n", w->name, reason); @@ -360,6 +368,8 @@ static void dapm_reset(struct snd_soc_card *card) { struct snd_soc_dapm_widget *w; + lockdep_assert_held(&card->dapm_mutex); + memset(&card->dapm_stats, 0, sizeof(card->dapm_stats)); list_for_each_entry(w, &card->widgets, list) { @@ -1823,6 +1833,8 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) ASYNC_DOMAIN_EXCLUSIVE(async_domain); enum snd_soc_bias_level bias; + lockdep_assert_held(&card->dapm_mutex); + trace_snd_soc_dapm_start(card); list_for_each_entry(d, &card->dapm_list, list) { @@ -2118,6 +2130,8 @@ static int soc_dapm_mux_update_power(struct snd_soc_card *card, struct snd_soc_dapm_path *path; int found = 0; + lockdep_assert_held(&card->dapm_mutex); + /* find dapm widget path assoc with kcontrol */ dapm_kcontrol_for_each_path(path, kcontrol) { if (!path->name || !e->texts[mux]) @@ -2168,6 +2182,8 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, struct snd_soc_dapm_path *path; int found = 0; + lockdep_assert_held(&card->dapm_mutex); + /* find dapm widget path assoc with kcontrol */ dapm_kcontrol_for_each_path(path, kcontrol) { found = 1; @@ -2333,6 +2349,8 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, { struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); + dapm_assert_locked(dapm); + if (!w) { dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin); return -EINVAL; -- cgit v1.2.3 From 23a735cc0200609edeff7c148c83d5046169dee9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Mar 2014 08:14:14 +0100 Subject: ASoC: migor: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/sh/migor.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c index 5014a884afee..c58c2529f103 100644 --- a/sound/soc/sh/migor.c +++ b/sound/soc/sh/migor.c @@ -136,19 +136,6 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Mic Bias", NULL, "External Microphone" }, }; -static int migor_dai_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_new_controls(dapm, migor_dapm_widgets, - ARRAY_SIZE(migor_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - return 0; -} - /* migor digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link migor_dai = { .name = "wm8978", @@ -158,7 +145,6 @@ static struct snd_soc_dai_link migor_dai = { .platform_name = "siu-pcm-audio", .codec_name = "wm8978.0-001a", .ops = &migor_dai_ops, - .init = migor_dai_init, }; /* migor audio machine driver */ @@ -167,6 +153,11 @@ static struct snd_soc_card snd_soc_migor = { .owner = THIS_MODULE, .dai_link = &migor_dai, .num_links = 1, + + .dapm_widgets = migor_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(migor_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *migor_snd_device; -- cgit v1.2.3 From bde24030b5a2825ef198b2f092b7271e22fae142 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Mar 2014 08:57:49 +0100 Subject: ASoC: spear: spdif_out: Fix mute control For controls registers with snd_soc_add_dai_controls snd_kcontrol_chip() returns a pointer to the DAI, not to the CODEC. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/spear/spdif_out.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c index fe99f461aff0..19cca043e6e4 100644 --- a/sound/soc/spear/spdif_out.c +++ b/sound/soc/spear/spdif_out.c @@ -213,10 +213,7 @@ static int spdif_digital_mute(struct snd_soc_dai *dai, int mute) static int spdif_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_card *card = codec->card; - struct snd_soc_pcm_runtime *rtd = card->rtd; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); ucontrol->value.integer.value[0] = host->saved_params.mute; @@ -226,10 +223,7 @@ static int spdif_mute_get(struct snd_kcontrol *kcontrol, static int spdif_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_card *card = codec->card; - struct snd_soc_pcm_runtime *rtd = card->rtd; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct spdif_out_dev *host = snd_soc_dai_get_drvdata(cpu_dai); if (host->saved_params.mute == ucontrol->value.integer.value[0]) -- cgit v1.2.3 From 5d6be5aa6becc750c5c2aa0ef8f7209ce19aa328 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 11 Mar 2014 12:43:20 +0800 Subject: ASoC: codec: Simplify ASoC probe code. For some CODEC drivers like who act as the MFDs children are ignored by this patch. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 10 +--------- sound/soc/codecs/adau1373.c | 7 ------- sound/soc/codecs/adav80x.c | 7 ------- sound/soc/codecs/ak4535.c | 9 --------- sound/soc/codecs/ak4641.c | 8 -------- sound/soc/codecs/ak4642.c | 8 -------- sound/soc/codecs/ak4671.c | 12 +----------- sound/soc/codecs/alc5623.c | 7 ------- sound/soc/codecs/alc5632.c | 8 -------- sound/soc/codecs/cs4270.c | 9 --------- sound/soc/codecs/cs42l51.c | 6 ------ sound/soc/codecs/cs42l52.c | 9 +-------- sound/soc/codecs/cs42l73.c | 11 +---------- sound/soc/codecs/da7210.c | 8 -------- sound/soc/codecs/da7213.c | 8 -------- sound/soc/codecs/da732x.c | 13 ++----------- sound/soc/codecs/da9055.c | 8 -------- sound/soc/codecs/isabelle.c | 16 ---------------- sound/soc/codecs/lm49453.c | 17 ----------------- sound/soc/codecs/max9768.c | 5 ----- sound/soc/codecs/max98088.c | 6 ------ sound/soc/codecs/max98090.c | 8 -------- sound/soc/codecs/max98095.c | 6 ------ sound/soc/codecs/max9850.c | 8 -------- sound/soc/codecs/ml26124.c | 10 ---------- sound/soc/codecs/rt5631.c | 9 --------- sound/soc/codecs/rt5640.c | 8 -------- sound/soc/codecs/sn95031.c | 2 -- sound/soc/codecs/ssm2518.c | 10 ---------- sound/soc/codecs/ssm2602.c | 7 ------- sound/soc/codecs/sta32x.c | 14 -------------- sound/soc/codecs/sta529.c | 10 ---------- sound/soc/codecs/tlv320aic23.c | 8 -------- sound/soc/codecs/tlv320aic26.c | 2 -- sound/soc/codecs/tlv320aic32x4.c | 2 -- sound/soc/codecs/tlv320aic3x.c | 6 ------ sound/soc/codecs/wm2000.c | 2 -- sound/soc/codecs/wm2200.c | 7 ------- sound/soc/codecs/wm5100.c | 7 ------- sound/soc/codecs/wm8510.c | 10 +--------- sound/soc/codecs/wm8523.c | 7 ------- sound/soc/codecs/wm8580.c | 6 ------ sound/soc/codecs/wm8711.c | 6 ------ sound/soc/codecs/wm8728.c | 11 +---------- sound/soc/codecs/wm8731.c | 7 ------- sound/soc/codecs/wm8737.c | 6 ------ sound/soc/codecs/wm8741.c | 6 ------ sound/soc/codecs/wm8750.c | 6 ------ sound/soc/codecs/wm8753.c | 7 ------- sound/soc/codecs/wm8770.c | 6 ------ sound/soc/codecs/wm8776.c | 6 ------ sound/soc/codecs/wm8804.c | 8 -------- sound/soc/codecs/wm8900.c | 8 +------- sound/soc/codecs/wm8903.c | 10 +--------- sound/soc/codecs/wm8904.c | 9 --------- sound/soc/codecs/wm8940.c | 6 ------ sound/soc/codecs/wm8955.c | 8 -------- sound/soc/codecs/wm8960.c | 6 ------ sound/soc/codecs/wm8961.c | 7 ------- sound/soc/codecs/wm8962.c | 7 ------- sound/soc/codecs/wm8971.c | 6 ------ sound/soc/codecs/wm8974.c | 6 ------ sound/soc/codecs/wm8978.c | 8 +------- sound/soc/codecs/wm8983.c | 6 ------ sound/soc/codecs/wm8985.c | 7 ------- sound/soc/codecs/wm8988.c | 8 -------- sound/soc/codecs/wm8990.c | 8 -------- sound/soc/codecs/wm8991.c | 8 -------- sound/soc/codecs/wm8993.c | 7 ------- sound/soc/codecs/wm8995.c | 7 ------- sound/soc/codecs/wm8996.c | 12 +----------- sound/soc/codecs/wm9081.c | 11 +---------- sound/soc/codecs/wm9090.c | 10 ---------- 73 files changed, 13 insertions(+), 562 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 9381a767e75f..6844d0b2af68 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -322,14 +322,6 @@ static struct snd_soc_dai_driver ad193x_dai = { static int ad193x_codec_probe(struct snd_soc_codec *codec) { struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ad193x->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } /* default setting for ad193x */ @@ -347,7 +339,7 @@ static int ad193x_codec_probe(struct snd_soc_codec *codec) regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); - return ret; + return 0; } static struct snd_soc_codec_driver soc_codec_dev_ad193x = { diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index eb836ed5271f..db5c303dcdbc 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -1376,15 +1376,8 @@ static int adau1373_probe(struct snd_soc_codec *codec) struct adau1373_platform_data *pdata = codec->dev->platform_data; bool lineout_differential = false; unsigned int val; - int ret; int i; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } - if (pdata) { if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting)) return -EINVAL; diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index f78b27a7c461..8d79c3fe02dc 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c @@ -798,15 +798,8 @@ static struct snd_soc_dai_driver adav80x_dais[] = { static int adav80x_probe(struct snd_soc_codec *codec) { - int ret; struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } - /* Force PLLs on for SYSCLK output */ snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 684fe910669f..30e297890fec 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -388,15 +388,6 @@ static int ak4535_resume(struct snd_soc_codec *codec) static int ak4535_probe(struct snd_soc_codec *codec) { - struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ak4535->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* power on device */ ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 94cbe508dd37..a7b7d9858f8a 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -519,14 +519,6 @@ static int ak4641_resume(struct snd_soc_codec *codec) static int ak4641_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* power on device */ ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 1f646c6e90c6..92655cc189ae 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -465,14 +465,6 @@ static int ak4642_resume(struct snd_soc_codec *codec) static int ak4642_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index deb2b44669de..998fa0c5a0b9 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -613,17 +613,7 @@ static struct snd_soc_dai_driver ak4671_dai = { static int ak4671_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return ret; + return ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); } static int ak4671_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index ed506253a914..09f7e773bafb 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -904,13 +904,6 @@ static int alc5623_probe(struct snd_soc_codec *codec) struct snd_soc_dapm_context *dapm = &codec->dapm; int ret; - codec->control_data = alc5623->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - alc5623_reset(codec); /* power on device */ diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index d885056ad8f2..ec071a6306ef 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -1063,14 +1063,6 @@ static int alc5632_probe(struct snd_soc_codec *codec) struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = alc5632->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* power on device */ alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 83c835d9fd88..3920e6264948 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -506,15 +506,6 @@ static int cs4270_probe(struct snd_soc_codec *codec) struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); int ret; - /* Tell ASoC what kind of I/O to use to read the registers. ASoC will - * then do the I2C transactions itself. - */ - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); - return ret; - } - /* Disable auto-mute. This feature appears to be buggy. In some * situations, auto-mute will not deactivate when it should, so we want * this feature disabled by default. An application (e.g. alsactl) can diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 3eab46020a30..a0c6060df4b4 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -489,12 +489,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec) { int ret, reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* * DAC configuration * - Use signal processor diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 0bac6d5a4ac8..4bd59cea4922 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -1115,14 +1115,7 @@ static void cs42l52_free_beep(struct snd_soc_codec *codec) static int cs42l52_probe(struct snd_soc_codec *codec) { struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); - int ret; - codec->control_data = cs42l52->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } regcache_cache_only(cs42l52->regmap, true); cs42l52_add_mic_controls(codec); @@ -1134,7 +1127,7 @@ static int cs42l52_probe(struct snd_soc_codec *codec) cs42l52->sysclk = CS42L52_DEFAULT_CLK; cs42l52->config.format = CS42L52_DEFAULT_FORMAT; - return ret; + return 0; } static int cs42l52_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 549d5d6a3fef..b9aa009b5b01 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1348,17 +1348,8 @@ static int cs42l73_resume(struct snd_soc_codec *codec) static int cs42l73_probe(struct snd_soc_codec *codec) { - int ret; struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec); - codec->control_data = cs42l73->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Set Charge Pump Frequency */ @@ -1371,7 +1362,7 @@ static int cs42l73_probe(struct snd_soc_codec *codec) cs42l73->mclksel = CS42L73_CLKID_MCLK1; cs42l73->mclk = 0; - return ret; + return 0; } static int cs42l73_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index e62e294a8033..a5838ba69e4e 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -1071,17 +1071,9 @@ static struct snd_soc_dai_driver da7210_dai = { static int da7210_probe(struct snd_soc_codec *codec) { struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); - int ret; dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); - codec->control_data = da7210->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - da7210->mclk_rate = 0; /* This will be set from set_sysclk() */ da7210->master = 0; /* This will be set from set_fmt() */ diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 0c77e7ad7423..110f4dd1a89e 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1384,17 +1384,9 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, static int da7213_probe(struct snd_soc_codec *codec) { - int ret; struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec); struct da7213_platform_data *pdata = da7213->pdata; - codec->control_data = da7213->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Default to using ALC auto offset calibration mode. */ snd_soc_update_bits(codec, DA7213_ALC_CTRL1, DA7213_ALC_CALIB_MODE_MAN, 0); diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 8053e0e7f4a7..fdefc4bb8bc4 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1516,23 +1516,14 @@ static int da732x_probe(struct snd_soc_codec *codec) { struct da732x_priv *da732x = snd_soc_codec_get_drvdata(codec); struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret = 0; da732x->codec = codec; dapm->idle_bias_off = false; - codec->control_data = da732x->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec.\n"); - goto err; - } - da732x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -err: - return ret; + + return 0; } static int da732x_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 52b79a487ac7..f0a371dbaee3 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -1381,16 +1381,8 @@ static int da9055_set_bias_level(struct snd_soc_codec *codec, static int da9055_probe(struct snd_soc_codec *codec) { - int ret; struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); - codec->control_data = da9055->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Enable all Gain Ramps */ snd_soc_update_bits(codec, DA9055_AUX_L_CTRL, DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 5839048ec467..087b3cb2dcdf 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -1082,23 +1082,7 @@ static struct snd_soc_dai_driver isabelle_dai[] = { }, }; -static int isabelle_probe(struct snd_soc_codec *codec) -{ - int ret = 0; - - codec->control_data = dev_get_regmap(codec->dev, NULL); - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - return 0; -} - static struct snd_soc_codec_driver soc_codec_dev_isabelle = { - .probe = isabelle_probe, .set_bias_level = isabelle_set_bias_level, .controls = isabelle_snd_controls, .num_controls = ARRAY_SIZE(isabelle_snd_controls), diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index e19490cfb3a8..069cb0359932 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1409,22 +1409,6 @@ static int lm49453_resume(struct snd_soc_codec *codec) return 0; } -static int lm49453_probe(struct snd_soc_codec *codec) -{ - struct lm49453_priv *lm49453 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - codec->control_data = lm49453->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - return 0; -} - /* power down chip */ static int lm49453_remove(struct snd_soc_codec *codec) { @@ -1433,7 +1417,6 @@ static int lm49453_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_lm49453 = { - .probe = lm49453_probe, .remove = lm49453_remove, .suspend = lm49453_suspend, .resume = lm49453_resume, diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c index 31f91560e9f6..ec481fc428c7 100644 --- a/sound/soc/codecs/max9768.c +++ b/sound/soc/codecs/max9768.c @@ -135,11 +135,6 @@ static int max9768_probe(struct snd_soc_codec *codec) struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = max9768->regmap; - ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP); - if (ret) - return ret; - if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) { ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM); if (ret) diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index ee660e2d3df3..64965005a41e 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -1915,12 +1915,6 @@ static int max98088_probe(struct snd_soc_codec *codec) regcache_mark_dirty(max98088->regmap); - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* initialize private data */ max98088->sysclk = (unsigned)-1; diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 51f9b3d16b41..4ac3b67b2006 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2195,14 +2195,6 @@ static int max98090_probe(struct snd_soc_codec *codec) max98090->codec = codec; - codec->control_data = max98090->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Reset the codec, the DSP core, and disable all interrupts */ max98090_reset(max98090); diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 3ba1170ebb53..2a9bfefb7d26 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -2234,12 +2234,6 @@ static int max98095_probe(struct snd_soc_codec *codec) struct i2c_client *client; int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* reset the codec, the DSP core, and disable all interrupts */ max98095_reset(codec); diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 82757ebf0301..4fdf5aaa236f 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -312,14 +312,6 @@ static int max9850_resume(struct snd_soc_codec *codec) static int max9850_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* enable zero-detect */ snd_soc_update_bits(codec, MAX9850_GENERAL_PURPOSE, 1, 1); /* enable slew-rate control */ diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 185fa3bc3052..b9f21fe5a7dc 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -586,16 +586,6 @@ static int ml26124_resume(struct snd_soc_codec *codec) static int ml26124_probe(struct snd_soc_codec *codec) { - int ret; - struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec); - codec->control_data = priv->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Software Reset */ snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 1); snd_soc_update_bits(codec, ML26124_SW_RST, 0x01, 0); diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 912c9cbc2724..73fcd3cff327 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1585,15 +1585,6 @@ static int rt5631_probe(struct snd_soc_codec *codec) { struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); unsigned int val; - int ret; - - codec->control_data = rt5631->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3); if (val & 0x0002) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index a3fb41179636..074cff100f54 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1943,16 +1943,8 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec, static int rt5640_probe(struct snd_soc_codec *codec) { struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); - int ret; rt5640->codec = codec; - codec->control_data = rt5640->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } codec->dapm.idle_bias_off = 1; rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF); diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 13045f2af4d3..193760ec98ef 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -825,8 +825,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec) { pr_debug("codec_probe called\n"); - snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - /* PCM interface config * This sets the pcm rx slot conguration to max 6 slots * for max 4 dais (2 stereo and 2 mono) diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index cc8debce752f..cf4a6572f35b 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -648,16 +648,6 @@ static struct snd_soc_dai_driver ssm2518_dai = { static int ssm2518_probe(struct snd_soc_codec *codec) { - struct ssm2518 *ssm2518 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ssm2518->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - return ssm2518_set_bias_level(codec, SND_SOC_BIAS_OFF); } diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index af76bbd1b24f..9fe4d485e699 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -573,13 +573,6 @@ static int ssm260x_probe(struct snd_soc_codec *codec) struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = ssm2602->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regmap_write(ssm2602->regmap, SSM2602_RESET, 0); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 06edb396e733..1cab6f62be7c 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -872,16 +872,6 @@ static int sta32x_probe(struct snd_soc_codec *codec) return ret; } - /* Tell ASoC what kind of I/O to use to read the registers. ASoC will - * then do the I2C transactions itself. - */ - codec->control_data = sta32x->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); - goto err; - } - /* Chip documentation explicitly requires that the reset values * of reserved register bits are left untouched. * Write the register default value to cache for reserved registers, @@ -946,10 +936,6 @@ static int sta32x_probe(struct snd_soc_codec *codec) regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); return 0; - -err: - regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); - return ret; } static int sta32x_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 40c07be9b581..30aae61bfdb3 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -322,16 +322,6 @@ static struct snd_soc_dai_driver sta529_dai = { static int sta529_probe(struct snd_soc_codec *codec) { - struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = sta529->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 7b4cfef232ea..46b8a5073857 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -559,14 +559,6 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Reset codec */ snd_soc_write(codec, TLV320AIC23_RESET, 0); diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 94a658fa6d97..8037beabd030 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -295,8 +295,6 @@ static int aic26_probe(struct snd_soc_codec *codec) struct aic26 *aic26 = dev_get_drvdata(codec->dev); int ret, reg; - snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - aic26->codec = codec; /* Reset the codec to power on defaults */ diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index c6bd7e75352d..1d9b117345a3 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -614,8 +614,6 @@ static int aic32x4_probe(struct snd_soc_codec *codec) struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); u32 tmp_reg; - snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (gpio_is_valid(aic32x4->rstn_gpio)) { ndelay(10); gpio_set_value(aic32x4->rstn_gpio, 1); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 470fbfb4b386..b1835103e9b4 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1344,12 +1344,6 @@ static int aic3x_probe(struct snd_soc_codec *codec) INIT_LIST_HEAD(&aic3x->list); aic3x->codec = codec; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; aic3x->disable_nb[i].aic3x = aic3x; diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 8ae50274ea8f..83a2c872925c 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -786,8 +786,6 @@ static int wm2000_probe(struct snd_soc_codec *codec) { struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_REGMAP); - /* This will trigger a transition to standby mode by default */ wm2000_anc_set_mode(wm2000); diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 57ba315d0c84..5129d91a6da4 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1556,15 +1556,8 @@ static int wm2200_probe(struct snd_soc_codec *codec) int ret; wm2200->codec = codec; - codec->control_data = wm2200->regmap; codec->dapm.bias_level = SND_SOC_BIAS_OFF; - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = snd_soc_add_codec_controls(codec, wm_adsp1_fw_controls, 2); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 4e3e31aaf509..bac848f009e7 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2337,13 +2337,6 @@ static int wm5100_probe(struct snd_soc_codec *codec) int ret, i; wm5100->codec = codec; - codec->control_data = wm5100->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++) snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU, diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 7df7d4572755..1c1e328feeb8 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -589,20 +589,12 @@ static int wm8510_resume(struct snd_soc_codec *codec) static int wm8510_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); - return ret; - } - wm8510_reset(codec); /* power on device */ wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return ret; + return 0; } /* power down chip */ diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 74d106dc7667..e6116aff0943 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -392,18 +392,11 @@ static int wm8523_resume(struct snd_soc_codec *codec) static int wm8523_probe(struct snd_soc_codec *codec) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - int ret; wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; wm8523->rate_constraint.count = ARRAY_SIZE(wm8523->rate_constraint_list); - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Change some default settings - latch VU and enable ZC */ snd_soc_update_bits(codec, WM8523_DAC_GAINR, WM8523_DACR_VU, WM8523_DACR_VU); diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 318989acbbe5..7558c838193d 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -869,12 +869,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); if (ret != 0) { diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index d99f948c513c..ef6cbc7ba489 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -367,12 +367,6 @@ static int wm8711_probe(struct snd_soc_codec *codec) { int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8711_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index cd89033e84c0..bac7fc28fe71 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -228,19 +228,10 @@ static int wm8728_resume(struct snd_soc_codec *codec) static int wm8728_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", - ret); - return ret; - } - /* power on device */ wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return ret; + return 0; } static int wm8728_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 029720366ff8..2c95b633e7df 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -583,13 +583,6 @@ static int wm8731_probe(struct snd_soc_codec *codec) struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); int ret = 0, i; - codec->control_data = wm8731->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) wm8731->supplies[i].supply = wm8731_supply_names[i]; diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 2f167a8ca01b..3693479b43d5 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -570,12 +570,6 @@ static int wm8737_probe(struct snd_soc_codec *codec) struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); if (ret != 0) { diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 2895c8d3b5e4..ecf4fcfa99fd 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -429,12 +429,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) goto err_get; } - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err_enable; - } - ret = wm8741_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 78616a638a55..33990b63d214 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -702,12 +702,6 @@ static int wm8750_probe(struct snd_soc_codec *codec) { int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8750_reset(codec); if (ret < 0) { printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index be85da93a268..0d1670b70702 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1471,13 +1471,6 @@ static int wm8753_probe(struct snd_soc_codec *codec) INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work); - codec->control_data = wm8753->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8753_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 89a18d82f303..32e736320526 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c @@ -580,12 +580,6 @@ static int wm8770_probe(struct snd_soc_codec *codec) wm8770 = snd_soc_codec_get_drvdata(codec); wm8770->codec = codec; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); if (ret) { diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index ef8246725232..70952ceb278b 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -430,12 +430,6 @@ static int wm8776_probe(struct snd_soc_codec *codec) { int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8776_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 9bc8206a6807..448a943e5a1b 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -546,14 +546,6 @@ static int wm8804_probe(struct snd_soc_codec *codec) wm8804 = snd_soc_codec_get_drvdata(codec); - codec->control_data = wm8804->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) wm8804->supplies[i].supply = wm8804_supply_names[i]; diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index e98bc7038a08..637be63cd474 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1178,13 +1178,7 @@ static int wm8900_resume(struct snd_soc_codec *codec) static int wm8900_probe(struct snd_soc_codec *codec) { - int ret = 0, reg; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } + int reg; reg = snd_soc_read(codec, WM8900_REG_ID); if (reg != 0x8900) { diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index eebcb1da3b7b..cf2f49fdb3bd 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1897,21 +1897,13 @@ static void wm8903_free_gpio(struct wm8903_priv *wm8903) static int wm8903_probe(struct snd_soc_codec *codec) { struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int ret; wm8903->codec = codec; - codec->control_data = wm8903->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* power on device */ wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return ret; + return 0; } /* power down chip */ diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 53bbfac6a83a..817dddc7f8a1 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2047,9 +2047,6 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec) static int wm8904_probe(struct snd_soc_codec *codec) { struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = wm8904->regmap; switch (wm8904->devtype) { case WM8904: @@ -2063,12 +2060,6 @@ static int wm8904_probe(struct snd_soc_codec *codec) return -EINVAL; } - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - wm8904_handle_pdata(codec); wm8904_add_widgets(codec); diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index b404c26c1753..1cdabaf07639 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -712,12 +712,6 @@ static int wm8940_probe(struct snd_soc_codec *codec) int ret; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8940_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 82c8ba975720..a94d1858930a 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -896,14 +896,6 @@ static int wm8955_probe(struct snd_soc_codec *codec) struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); int ret, i; - codec->control_data = wm8955->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) wm8955->supplies[i].supply = wm8955_supply_names[i]; diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index f156010e52bc..d04e9cad445c 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -976,12 +976,6 @@ static int wm8960_probe(struct snd_soc_codec *codec) wm8960->set_bias_level = wm8960_set_bias_level_capless; } - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8960_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 900328e28a15..db84507c1ec5 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -836,15 +836,8 @@ static struct snd_soc_dai_driver wm8961_dai = { static int wm8961_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret = 0; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Enable class W */ reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); reg |= WM8961_CP_DYN_PWR_MASK; diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 97db3b45b411..1d556c945bb2 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3400,13 +3400,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) bool dmicclk, dmicdat; wm8962->codec = codec; - codec->control_data = wm8962->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0; wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1; diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 67aba78a7ca5..09b7b4200221 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -648,12 +648,6 @@ static int wm8971_probe(struct snd_soc_codec *codec) int ret = 0; u16 reg; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); - return ret; - } - INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8971_work); wm8971_workq = create_workqueue("wm8971"); if (wm8971_workq == NULL) diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 15f45c7bd833..ea0de269a472 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -593,12 +593,6 @@ static int wm8974_probe(struct snd_soc_codec *codec) { int ret = 0; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8974_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index d8fc531c0e59..13de3688e86f 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -975,19 +975,13 @@ static const int update_reg[] = { static int wm8978_probe(struct snd_soc_codec *codec) { struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); - int ret = 0, i; + int i; /* * Set default system clock to PLL, it is more precise, this is also the * default hardware setting */ wm8978->sysclk = WM8978_PLL; - codec->control_data = wm8978->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* * Set the update bit in all registers, that have one. This way all diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index aa41ba0dfff4..84aa09319ba1 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -1000,12 +1000,6 @@ static int wm8983_probe(struct snd_soc_codec *codec) int ret; int i; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset: %d\n", ret); diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 271b517911a4..64e211cb4bcf 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -1000,13 +1000,6 @@ static int wm8985_probe(struct snd_soc_codec *codec) int ret; wm8985 = snd_soc_codec_get_drvdata(codec); - codec->control_data = wm8985->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } for (i = 0; i < ARRAY_SIZE(wm8985->supplies); i++) wm8985->supplies[i].supply = wm8985_supply_names[i]; diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index a55e1c2c382e..424bbf752f3f 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -810,16 +810,8 @@ static int wm8988_resume(struct snd_soc_codec *codec) static int wm8988_probe(struct snd_soc_codec *codec) { - struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); int ret = 0; - codec->control_data = wm8988->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - ret = wm8988_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 0ccd4d8d043b..1487625551e7 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1292,14 +1292,6 @@ static int wm8990_resume(struct snd_soc_codec *codec) */ static int wm8990_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); - return ret; - } - wm8990_reset(codec); /* charge output caps */ diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 32d219570cca..844cc4a60d66 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1248,14 +1248,6 @@ static int wm8991_remove(struct snd_soc_codec *codec) static int wm8991_probe(struct snd_soc_codec *codec) { - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 433d59a0f3ef..1674a1f33ba0 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1493,13 +1493,6 @@ static int wm8993_probe(struct snd_soc_codec *codec) wm8993->hubs_data.dcs_codes_r = -2; wm8993->hubs_data.series_startup = 1; - codec->control_data = wm8993->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Latch volume update bits and default ZC on */ snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, WM8993_DAC_VU, WM8993_DAC_VU); diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 4300caff1783..9fd76c9c4e36 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -2047,13 +2047,6 @@ static int wm8995_probe(struct snd_soc_codec *codec) wm8995 = snd_soc_codec_get_drvdata(codec); wm8995->codec = codec; - codec->control_data = wm8995->regmap; - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) wm8995->supplies[i].supply = wm8995_supply_names[i]; diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 1a7655b0aa22..54066436d72c 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2628,14 +2628,6 @@ static int wm8996_probe(struct snd_soc_codec *codec) init_completion(&wm8996->dcs_done); init_completion(&wm8996->fll_lock); - codec->control_data = wm8996->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - if (wm8996->pdata.num_retune_mobile_cfgs) wm8996_retune_mobile_pdata(codec); else @@ -2674,13 +2666,11 @@ static int wm8996_probe(struct snd_soc_codec *codec) } else { dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); + return ret; } } return 0; - -err: - return ret; } static int wm8996_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 0982c1d38ec4..cda185d436f7 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1265,15 +1265,6 @@ static struct snd_soc_dai_driver wm9081_dai = { static int wm9081_probe(struct snd_soc_codec *codec) { struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = wm9081->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } /* Enable zero cross by default */ snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT, @@ -1288,7 +1279,7 @@ static int wm9081_probe(struct snd_soc_codec *codec) ARRAY_SIZE(wm9081_eq_controls)); } - return ret; + return 0; } static int wm9081_remove(struct snd_soc_codec *codec) diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index a07fe1618eec..87934171f063 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -522,16 +522,6 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, static int wm9090_probe(struct snd_soc_codec *codec) { - struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev); - int ret; - - codec->control_data = wm9090->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* Configure some defaults; they will be written out when we * bring the bias up. */ -- cgit v1.2.3 From 092eba937d948a76ff55825922eff4df010f6a17 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 11 Mar 2014 12:43:21 +0800 Subject: ASoC: io: New signature for snd_soc_codec_set_cache_io() Now that all users have been converted to regmap and the config.reg_bits and config.val_bits can be setted by each user through regmap core API. So these two params are redundant here. Since the only control type that left is SND_SOC_REGMAP, so remove it. Drop the control params and add struct regmap *regmap to simplify the code. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- include/sound/soc.h | 7 +----- sound/soc/codecs/88pm860x-codec.c | 3 +-- sound/soc/codecs/cq93vc.c | 3 +-- sound/soc/codecs/mc13783.c | 4 ++-- sound/soc/codecs/si476x.c | 6 +++-- sound/soc/codecs/tlv320dac33.c | 1 - sound/soc/codecs/wm5102.c | 4 +--- sound/soc/codecs/wm5110.c | 3 +-- sound/soc/codecs/wm8350.c | 4 +--- sound/soc/codecs/wm8400.c | 3 +-- sound/soc/codecs/wm8994.c | 3 +-- sound/soc/codecs/wm8997.c | 4 +--- sound/soc/soc-core.c | 2 +- sound/soc/soc-io.c | 47 +++++++++++++++++---------------------- 14 files changed, 36 insertions(+), 58 deletions(-) (limited to 'sound/soc') diff --git a/include/sound/soc.h b/include/sound/soc.h index 2d8982db0344..85a5b7bbe39a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -354,10 +354,6 @@ typedef int (*hw_write_t)(void *,const char* ,int); extern struct snd_ac97_bus_ops *soc_ac97_ops; -enum snd_soc_control_type { - SND_SOC_REGMAP, -}; - enum snd_soc_pcm_subclass { SND_SOC_PCM_CLASS_PCM = 0, SND_SOC_PCM_CLASS_BE = 1, @@ -404,8 +400,7 @@ int snd_soc_codec_readable_register(struct snd_soc_codec *codec, int snd_soc_codec_writable_register(struct snd_soc_codec *codec, unsigned int reg); int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control); + struct regmap *regmap); int snd_soc_cache_sync(struct snd_soc_codec *codec); int snd_soc_cache_init(struct snd_soc_codec *codec); int snd_soc_cache_exit(struct snd_soc_codec *codec); diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 647a72cda005..773b53366ada 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -1327,8 +1327,7 @@ static int pm860x_probe(struct snd_soc_codec *codec) pm860x->codec = codec; - codec->control_data = pm860x->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, pm860x->regmap); if (ret) return ret; diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c index 43737a27d79c..1e25c7af853b 100644 --- a/sound/soc/codecs/cq93vc.c +++ b/sound/soc/codecs/cq93vc.c @@ -138,9 +138,8 @@ static int cq93vc_probe(struct snd_soc_codec *codec) struct davinci_vc *davinci_vc = codec->dev->platform_data; davinci_vc->cq93vc.codec = codec; - codec->control_data = davinci_vc->regmap; - snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, davinci_vc->regmap); /* Off, with power on */ cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 582c2bbd42cb..fc28b20f6c69 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -614,8 +614,8 @@ static int mc13783_probe(struct snd_soc_codec *codec) struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = dev_get_regmap(codec->dev->parent, NULL); - ret = snd_soc_codec_set_cache_io(codec, 8, 24, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, + dev_get_regmap(codec->dev->parent, NULL)); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index fa2b8e07f420..244c097cd905 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -209,8 +210,9 @@ out: static int si476x_codec_probe(struct snd_soc_codec *codec) { - codec->control_data = dev_get_regmap(codec->dev->parent, NULL); - return snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + struct regmap *regmap = dev_get_regmap(codec->dev->parent, NULL); + + return snd_soc_codec_set_cache_io(codec, regmap); } static struct snd_soc_dai_ops si476x_dai_ops = { diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 4f358393d6d6..64afda740c80 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -122,7 +122,6 @@ struct tlv320dac33_priv { unsigned int uthr; enum dac33_state state; - enum snd_soc_control_type control_type; void *control_data; }; diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index ce9c8e14d4bd..5613d0efe19b 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1758,9 +1758,7 @@ static int wm5102_codec_probe(struct snd_soc_codec *codec) struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = priv->core.arizona->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 2c3c962d9a85..66d3ad4176c3 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -1588,10 +1588,9 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec) struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = priv->core.arizona->regmap; priv->core.arizona->dapm = &codec->dapm; - ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); if (ret != 0) return ret; diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index a183dcf3d5c1..757256bf7672 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -1505,9 +1505,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) if (ret != 0) return ret; - codec->control_data = wm8350->regmap; - - snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, wm8350->regmap); /* Put the codec into reset if it wasn't already */ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 48dc7d2fee36..939baf83bb59 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -1310,10 +1310,9 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec) snd_soc_codec_set_drvdata(codec, priv); priv->wm8400 = wm8400; - codec->control_data = wm8400->regmap; priv->codec = codec; - snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, wm8400->regmap); ret = devm_regulator_bulk_get(wm8400->dev, ARRAY_SIZE(power), &power[0]); diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b9be9cbc4603..32cc83e3f1ff 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3985,9 +3985,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) int ret, i; wm8994->hubs.codec = codec; - codec->control_data = control->regmap; - snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, control->regmap); mutex_init(&wm8994->accdet_lock); INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 555115ee2159..e3d1522daf64 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -1052,9 +1052,7 @@ static int wm8997_codec_probe(struct snd_soc_codec *codec) struct wm8997_priv *priv = snd_soc_codec_get_drvdata(codec); int ret; - codec->control_data = priv->core.arizona->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); + ret = snd_soc_codec_set_cache_io(codec, priv->core.arizona->regmap); if (ret != 0) return ret; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ad2dd14f0e3e..6510a8e4a5af 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1139,7 +1139,7 @@ static int soc_probe_codec(struct snd_soc_card *card, /* Set the default I/O up try regmap */ if (dev_get_regmap(codec->dev, NULL)) - snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + snd_soc_codec_set_cache_io(codec, NULL); if (driver->probe) { ret = driver->probe(codec); diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index 18353f111b6a..8aa086996866 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -69,9 +69,7 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) * snd_soc_codec_set_cache_io: Set up standard I/O functions. * * @codec: CODEC to configure. - * @addr_bits: Number of bits of register address data. - * @data_bits: Number of bits of data per register. - * @control: Control bus used. + * @map: Register map to write to * * Register formats are frequently shared between many I2C and SPI * devices. In order to promote code reuse the ASoC core provides @@ -85,41 +83,36 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) * volatile registers. */ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control) + struct regmap *regmap) { int ret; + /* Device has made its own regmap arrangements */ + if (!regmap) + codec->control_data = dev_get_regmap(codec->dev, NULL); + else + codec->control_data = regmap; + + if (IS_ERR(codec->control_data)) + return PTR_ERR(codec->control_data); + codec->write = hw_write; codec->read = hw_read; - switch (control) { - case SND_SOC_REGMAP: - /* Device has made its own regmap arrangements */ - codec->using_regmap = true; - if (!codec->control_data) - codec->control_data = dev_get_regmap(codec->dev, NULL); - - if (codec->control_data) { - ret = regmap_get_val_bytes(codec->control_data); - /* Errors are legitimate for non-integer byte - * multiples */ - if (ret > 0) - codec->val_bytes = ret; - } - break; - - default: - return -EINVAL; - } + ret = regmap_get_val_bytes(codec->control_data); + /* Errors are legitimate for non-integer byte + * multiples */ + if (ret > 0) + codec->val_bytes = ret; + + codec->using_regmap = true; - return PTR_ERR_OR_ZERO(codec->control_data); + return 0; } EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); #else int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control) + struct regmap *regmap) { return -ENOTSUPP; } -- cgit v1.2.3 From a32c17b87c17f5e2e68edcf4d163ee42f9490652 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 11 Mar 2014 12:43:22 +0800 Subject: ASoC: core: Fix check before setting default I/O up try regmap Since the CODEC driver could specify its own I/O(read and write) while registering the CODEC for some reason, maybe the MFDs is used, etc. So just do check it, if they are not specified by CODEC driver then try to set up the default regmap I/O if regmap is used. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 6510a8e4a5af..cbddbd595213 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1137,9 +1137,15 @@ static int soc_probe_codec(struct snd_soc_card *card, codec->dapm.idle_bias_off = driver->idle_bias_off; - /* Set the default I/O up try regmap */ - if (dev_get_regmap(codec->dev, NULL)) - snd_soc_codec_set_cache_io(codec, NULL); + if (!codec->write && dev_get_regmap(codec->dev, NULL)) { + /* Set the default I/O up try regmap */ + ret = snd_soc_codec_set_cache_io(codec, NULL); + if (ret < 0) { + dev_err(codec->dev, + "Failed to set cache I/O: %d\n", ret); + goto err_probe; + } + } if (driver->probe) { ret = driver->probe(codec); -- cgit v1.2.3 From 5c1d5f091dc39eecf9a34a8be01492d14c23ad91 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 08:34:39 +0100 Subject: ASoC: Fix use after free Freeing the current list element while iterating over the list will cause a use after free since the iterator function will still use the current element to look up the next. Use list_for_each_safe() and remove the element from the list before freeing it to avoid this. Fixes: 1438c2f60b ("ASoC: Add a per component dai list") Reported-by: Dan Carpenter Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f34f1a01fce1..a78bba4d52fb 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3913,11 +3913,12 @@ static inline char *fmt_multiple_name(struct device *dev, */ static void snd_soc_unregister_dais(struct snd_soc_component *component) { - struct snd_soc_dai *dai; + struct snd_soc_dai *dai, *_dai; - list_for_each_entry(dai, &component->dai_list, list) { + list_for_each_entry_safe(dai, _dai, &component->dai_list, list) { dev_dbg(component->dev, "ASoC: Unregistered DAI '%s'\n", dai->name); + list_del(&dai->list); kfree(dai->name); kfree(dai); } -- cgit v1.2.3 From 051389e250d018f7c38c8043c54aa8979d4b2cab Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Mar 2014 13:32:34 +0000 Subject: ASoC: tlv320aic23: Remove spurious bits per word setting regmap should handle any byte ordering issues required, it is looking for a byte stream from the bus, so don't set 16 bits per word. This is likely to have tested out OK due to use of an unmerged SPI controller driver. Signed-off-by: Mark Brown Tested-by: Max Filippov --- sound/soc/codecs/tlv320aic23-spi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic23-spi.c b/sound/soc/codecs/tlv320aic23-spi.c index 585aea436c6a..3b387e41d75d 100644 --- a/sound/soc/codecs/tlv320aic23-spi.c +++ b/sound/soc/codecs/tlv320aic23-spi.c @@ -25,7 +25,6 @@ static int aic23_spi_probe(struct spi_device *spi) dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n"); - spi->bits_per_word = 16; spi->mode = SPI_MODE_0; ret = spi_setup(spi); if (ret < 0) -- cgit v1.2.3 From e95d73c437a09e7febea18f8e998f958ef6d7a72 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:29 +0100 Subject: ASoC: ams-delta: Fix compile error snd_soc_dapm_mutex_unlock() wants a pointer to the DAPM context, not the CODEC. Fixes: 03510ca07 ("ASoC: ams-delta: Update locking around use of DAPM pin API") Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/omap/ams-delta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 5750de197d0d..14718cd6c29f 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -327,7 +327,7 @@ static void cx81801_close(struct tty_struct *tty) snd_soc_dapm_sync_unlocked(dapm); - snd_soc_dapm_mutex_unlock(codec); + snd_soc_dapm_mutex_unlock(dapm); } /* Line discipline .hangup() */ -- cgit v1.2.3 From 7b2655b409211d619d99a1bb325797dee22a1c8b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:36 +0100 Subject: ASoC: snappercl15: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/cirrus/snappercl15.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index 29238a7476dd..5b68b106cfc2 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c @@ -65,18 +65,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MICIN", NULL, "Mic Jack"}, }; -static int snappercl15_tlv320aic23_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_new_controls(dapm, tlv320aic23_dapm_widgets, - ARRAY_SIZE(tlv320aic23_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; -} - static struct snd_soc_dai_link snappercl15_dai = { .name = "tlv320aic23", .stream_name = "AIC23", @@ -84,7 +72,6 @@ static struct snd_soc_dai_link snappercl15_dai = { .codec_dai_name = "tlv320aic23-hifi", .codec_name = "tlv320aic23-codec.0-001a", .platform_name = "ep93xx-i2s", - .init = snappercl15_tlv320aic23_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBS_CFS, .ops = &snappercl15_ops, @@ -95,6 +82,11 @@ static struct snd_soc_card snd_soc_snappercl15 = { .owner = THIS_MODULE, .dai_link = &snappercl15_dai, .num_links = 1, + + .dapm_widgets = tlv320aic23_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int snappercl15_probe(struct platform_device *pdev) -- cgit v1.2.3 From 0fbd44ab772890cf5dcda87311575e99d2c000c1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:38 +0100 Subject: ASoC: pxa: magician: Convert to table based DAPM and control setup Use table based setup to register the controls and DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/magician.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index 41ab6678b65d..259e048681c0 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -41,9 +41,8 @@ static int magician_hp_switch; static int magician_spk_switch = 1; static int magician_in_sel = MAGICIAN_MIC; -static void magician_ext_control(struct snd_soc_codec *codec) +static void magician_ext_control(struct snd_soc_dapm_context *dapm) { - struct snd_soc_dapm_context *dapm = &codec->dapm; snd_soc_dapm_mutex_lock(dapm); @@ -75,10 +74,9 @@ static void magician_ext_control(struct snd_soc_codec *codec) static int magician_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - magician_ext_control(codec); + magician_ext_control(&rtd->card->dapm); return 0; } @@ -277,13 +275,13 @@ static int magician_get_hp(struct snd_kcontrol *kcontrol, static int magician_set_hp(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (magician_hp_switch == ucontrol->value.integer.value[0]) return 0; magician_hp_switch = ucontrol->value.integer.value[0]; - magician_ext_control(codec); + magician_ext_control(&card->dapm); return 1; } @@ -297,13 +295,13 @@ static int magician_get_spk(struct snd_kcontrol *kcontrol, static int magician_set_spk(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (magician_spk_switch == ucontrol->value.integer.value[0]) return 0; magician_spk_switch = ucontrol->value.integer.value[0]; - magician_ext_control(codec); + magician_ext_control(&card->dapm); return 1; } @@ -400,7 +398,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; /* NC codec pins */ snd_soc_dapm_nc_pin(dapm, "VOUTLHP"); @@ -410,19 +407,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "VINL"); snd_soc_dapm_nc_pin(dapm, "VINR"); - /* Add magician specific controls */ - err = snd_soc_add_codec_controls(codec, uda1380_magician_controls, - ARRAY_SIZE(uda1380_magician_controls)); - if (err < 0) - return err; - - /* Add magician specific widgets */ - snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets, - ARRAY_SIZE(uda1380_dapm_widgets)); - - /* Set up magician specific audio path interconnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -456,6 +440,12 @@ static struct snd_soc_card snd_soc_card_magician = { .dai_link = magician_dai, .num_links = ARRAY_SIZE(magician_dai), + .controls = uda1380_magician_controls, + .num_controls = ARRAY_SIZE(uda1380_magician_controls), + .dapm_widgets = uda1380_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *magician_snd_device; -- cgit v1.2.3 From 079942abb389e6d4197db03299ad13297afd812a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:39 +0100 Subject: ASoC: pxa: tosa: Convert to table based DAPM and control setup Use table based setup to register the controls and DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/tosa.c | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index cead1658d10a..4a956d1cb269 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -44,9 +44,8 @@ static int tosa_jack_func; static int tosa_spk_func; -static void tosa_ext_control(struct snd_soc_codec *codec) +static void tosa_ext_control(struct snd_soc_dapm_context *dapm) { - struct snd_soc_dapm_context *dapm = &codec->dapm; snd_soc_dapm_mutex_lock(dapm); @@ -82,10 +81,9 @@ static void tosa_ext_control(struct snd_soc_codec *codec) static int tosa_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - tosa_ext_control(codec); + tosa_ext_control(&rtd->card->dapm); return 0; } @@ -104,13 +102,13 @@ static int tosa_get_jack(struct snd_kcontrol *kcontrol, static int tosa_set_jack(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (tosa_jack_func == ucontrol->value.integer.value[0]) return 0; tosa_jack_func = ucontrol->value.integer.value[0]; - tosa_ext_control(codec); + tosa_ext_control(&card->dapm); return 1; } @@ -124,13 +122,13 @@ static int tosa_get_spk(struct snd_kcontrol *kcontrol, static int tosa_set_spk(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); if (tosa_spk_func == ucontrol->value.integer.value[0]) return 0; tosa_spk_func = ucontrol->value.integer.value[0]; - tosa_ext_control(codec); + tosa_ext_control(&card->dapm); return 1; } @@ -191,24 +189,10 @@ 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; - int err; snd_soc_dapm_nc_pin(dapm, "OUT3"); snd_soc_dapm_nc_pin(dapm, "MONOOUT"); - /* add tosa specific controls */ - err = snd_soc_add_codec_controls(codec, tosa_controls, - ARRAY_SIZE(tosa_controls)); - if (err < 0) - return err; - - /* add tosa specific widgets */ - snd_soc_dapm_new_controls(dapm, tosa_dapm_widgets, - ARRAY_SIZE(tosa_dapm_widgets)); - - /* set up tosa specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -239,6 +223,13 @@ static struct snd_soc_card tosa = { .owner = THIS_MODULE, .dai_link = tosa_dai, .num_links = ARRAY_SIZE(tosa_dai), + + .controls = tosa_controls, + .num_controls = ARRAY_SIZE(tosa_controls), + .dapm_widgets = tosa_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tosa_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int tosa_probe(struct platform_device *pdev) -- cgit v1.2.3 From f410d5c953cf3c11629f138c5a2c3d3f40c61b5d Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 10 Mar 2014 10:38:40 -0600 Subject: ASoC: Intel: don't select RT5640 if !I2C MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rt5640 driver won't compile without I2C enabled. Hence, the Intel Haswell and Baytrail+RT5640 ASoC drivers must also depend on I2C, since these select RT5640. This solves: sound/soc/codecs/rt5640.c:2220:1: warning: data definition has no type or storage class [enabled by default] sound/soc/codecs/rt5640.c:2220:1: error: type defaults to ‘int’ in declaration of ‘module_i2c_driver’ [-Werror=implicit-int] sound/soc/codecs/rt5640.c:2220:1: warning: parameter names (without types) in function declaration [enabled by default] sound/soc/codecs/rt5640.c:2210:26: warning: ‘rt5640_i2c_driver’ defined but not used [-Wunused-variable] Reported-by: Jim Davis Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 4577b69fcf2c..3c81b3891209 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -32,7 +32,7 @@ config SND_SOC_INTEL_BAYTRAIL config SND_SOC_INTEL_HASWELL_MACH tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint" - depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS + depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C select SND_SOC_INTEL_HASWELL select SND_SOC_RT5640 help @@ -43,7 +43,7 @@ config SND_SOC_INTEL_HASWELL_MACH config SND_SOC_INTEL_BYT_RT5640_MACH tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec" - depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS + depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C select SND_SOC_INTEL_BAYTRAIL select SND_SOC_RT5640 help -- cgit v1.2.3 From b92af2b8844c964fc7e1905f797a8d780c7212de Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:37 +0100 Subject: ASoC: s6105-ipcam: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit shorter and cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. While we are at it also remove the snd_soc_dapm_enable_pin() in the init callback, since pins are enabled by default. Also drop the snd_soc_dapm_sync() calls, since they are ignored by the core anyway until the card has been fully instantiated. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/s6000/s6105-ipcam.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c index 945e8abdc10f..0b21d1dc80c1 100644 --- a/sound/soc/s6000/s6105-ipcam.c +++ b/sound/soc/s6000/s6105-ipcam.c @@ -104,8 +104,8 @@ static int output_type_get(struct snd_kcontrol *kcontrol, static int output_type_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = kcontrol->private_data; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_card *card = kcontrol->private_data; + struct snd_soc_dapm_context *dapm = &card->dapm; unsigned int val = (ucontrol->value.enumerated.item[0] != 0); char *differential = "Audio Out Differential"; char *stereo = "Audio Out Stereo"; @@ -137,13 +137,7 @@ static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - - /* Add s6105 specific widgets */ - snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, - ARRAY_SIZE(aic3x_dapm_widgets)); - - /* Set up s6105 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + struct snd_soc_card *card = rtd->card; /* not present */ snd_soc_dapm_nc_pin(dapm, "MONO_LOUT"); @@ -157,17 +151,10 @@ static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "RLOUT"); snd_soc_dapm_nc_pin(dapm, "HPRCOM"); - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Audio In"); - /* must correspond to audio_out_mux.private_value initializer */ - snd_soc_dapm_disable_pin(dapm, "Audio Out Differential"); - snd_soc_dapm_sync(dapm); - snd_soc_dapm_enable_pin(dapm, "Audio Out Stereo"); - - snd_soc_dapm_sync(dapm); + snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential"); - snd_ctl_add(codec->card->snd_card, snd_ctl_new1(&audio_out_mux, codec)); + snd_ctl_add(card->snd_card, snd_ctl_new1(&audio_out_mux, card)); return 0; } @@ -190,6 +177,11 @@ static struct snd_soc_card snd_soc_card_s6105 = { .owner = THIS_MODULE, .dai_link = &s6105_dai, .num_links = 1, + + .dapm_widgets = aic3x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct s6000_snd_platform_data s6105_snd_data __initdata = { -- cgit v1.2.3 From e00447fafbf7daf2cd49205b97e63d9734068a4f Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 11 Mar 2014 12:57:32 +0200 Subject: ASoC: tlv320aic31xx: Add basic codec driver implementation This commit adds a bare bones driver support for TLV320AIC31XX family audio codecs. The driver adds basic stereo playback trough headphone and speaker outputs and mono capture trough microphone inputs. The driver is currently missing support at least for mini DSP features and jack detection. I have tested the driver only on TLV320AIC3111, but based on the data sheets TLV320AIC3100, TLV320AIC3110, and TLV320AIC3120 should work Ok too. The base for the implementation was taken from: git@gitorious.org:ti-codecs/ti-codecs.git ajitk/topics/k3.10.1-aic31xx -branch at commit 77504eba0294764e9e63b4a0c696b44db187cd13. Signed-off-by: Jyri Sarha Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tlv320aic31xx.txt | 61 + include/dt-bindings/sound/tlv320aic31xx-micbias.h | 8 + sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tlv320aic31xx.c | 1295 ++++++++++++++++++++ sound/soc/codecs/tlv320aic31xx.h | 258 ++++ 6 files changed, 1628 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/tlv320aic31xx.txt create mode 100644 include/dt-bindings/sound/tlv320aic31xx-micbias.h create mode 100644 sound/soc/codecs/tlv320aic31xx.c create mode 100644 sound/soc/codecs/tlv320aic31xx.h (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt new file mode 100644 index 000000000000..74c66dee3e14 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt @@ -0,0 +1,61 @@ +Texas Instruments - tlv320aic31xx Codec module + +The tlv320aic31xx serial control bus communicates through I2C protocols + +Required properties: + +- compatible - "string" - One of: + "ti,tlv320aic310x" - Generic TLV320AIC31xx with mono speaker amp + "ti,tlv320aic311x" - Generic TLV320AIC31xx with stereo speaker amp + "ti,tlv320aic3100" - TLV320AIC3100 (mono speaker amp, no MiniDSP) + "ti,tlv320aic3110" - TLV320AIC3110 (stereo speaker amp, no MiniDSP) + "ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP) + "ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP) + +- reg - - I2C slave address + + +Optional properties: + +- gpio-reset - gpio pin number used for codec reset +- ai31xx-micbias-vg - MicBias Voltage setting + 1 or MICBIAS_2_0V - MICBIAS output is powered to 2.0V + 2 or MICBIAS_2_5V - MICBIAS output is powered to 2.5V + 3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD + If this node is not mentioned or if the value is unknown, then + micbias is set to 2.0V. +- HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply, + DVDD-supply : power supplies for the device as covered in + Documentation/devicetree/bindings/regulator/regulator.txt + +CODEC output pins: + * HPL + * HPR + * SPL, devices with stereo speaker amp + * SPR, devices with stereo speaker amp + * SPK, devices with mono speaker amp + * MICBIAS + +CODEC input pins: + * MIC1LP + * MIC1RP + * MIC1LM + +The pins can be used in referring sound node's audio-routing property. + +Example: +#include + +tlv320aic31xx: tlv320aic31xx@18 { + compatible = "ti,tlv320aic311x"; + reg = <0x18>; + + ai31xx-micbias-vg = ; + + HPVDD-supply = <®ulator>; + SPRVDD-supply = <®ulator>; + SPLVDD-supply = <®ulator>; + AVDD-supply = <®ulator>; + IOVDD-supply = <®ulator>; + DVDD-supply = <®ulator>; +}; diff --git a/include/dt-bindings/sound/tlv320aic31xx-micbias.h b/include/dt-bindings/sound/tlv320aic31xx-micbias.h new file mode 100644 index 000000000000..f5cb772ab9c8 --- /dev/null +++ b/include/dt-bindings/sound/tlv320aic31xx-micbias.h @@ -0,0 +1,8 @@ +#ifndef __DT_TLV320AIC31XX_MICBIAS_H +#define __DT_TLV320AIC31XX_MICBIAS_H + +#define MICBIAS_2_0V 1 +#define MICBIAS_2_5V 2 +#define MICBIAS_AVDDV 3 + +#endif /* __DT_TLV320AIC31XX_MICBIAS_H */ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..66f6c53ea328 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -73,6 +73,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_TAS5086 if I2C select SND_SOC_TLV320AIC23 if I2C select SND_SOC_TLV320AIC26 if SPI_MASTER + select SND_SOC_TLV320AIC31XX if I2C select SND_SOC_TLV320AIC32X4 if I2C select SND_SOC_TLV320AIC3X if I2C select SND_SOC_TPA6130A2 if I2C @@ -361,6 +362,9 @@ config SND_SOC_TLV320AIC26 tristate depends on SPI +config SND_SOC_TLV320AIC31XX + tristate + config SND_SOC_TLV320AIC32X4 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 1deeb20fd411..ff1775c562fe 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -64,6 +64,7 @@ snd-soc-stac9766-objs := stac9766.o snd-soc-tas5086-objs := tas5086.o snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic26-objs := tlv320aic26.o +snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320dac33-objs := tlv320dac33.o @@ -194,6 +195,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o +obj-$(CONFIG_SND_SOC_TLV320AIC31XX) += snd-soc-tlv320aic31xx.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c new file mode 100644 index 000000000000..e60e37b43a1b --- /dev/null +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -0,0 +1,1295 @@ +/* + * ALSA SoC TLV320AIC31XX codec driver + * + * Copyright (C) 2014 Texas Instruments, Inc. + * + * Author: Jyri Sarha + * + * Based on ground work by: Ajit Kulkarni + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * THIS PACKAGE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * The TLV320AIC31xx series of audio codec is a low-power, highly integrated + * high performance codec which provides a stereo DAC, a mono ADC, + * and mono/stereo Class-D speaker driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tlv320aic31xx.h" + +static const struct reg_default aic31xx_reg_defaults[] = { + { AIC31XX_CLKMUX, 0x00 }, + { AIC31XX_PLLPR, 0x11 }, + { AIC31XX_PLLJ, 0x04 }, + { AIC31XX_PLLDMSB, 0x00 }, + { AIC31XX_PLLDLSB, 0x00 }, + { AIC31XX_NDAC, 0x01 }, + { AIC31XX_MDAC, 0x01 }, + { AIC31XX_DOSRMSB, 0x00 }, + { AIC31XX_DOSRLSB, 0x80 }, + { AIC31XX_NADC, 0x01 }, + { AIC31XX_MADC, 0x01 }, + { AIC31XX_AOSR, 0x80 }, + { AIC31XX_IFACE1, 0x00 }, + { AIC31XX_DATA_OFFSET, 0x00 }, + { AIC31XX_IFACE2, 0x00 }, + { AIC31XX_BCLKN, 0x01 }, + { AIC31XX_DACSETUP, 0x14 }, + { AIC31XX_DACMUTE, 0x0c }, + { AIC31XX_LDACVOL, 0x00 }, + { AIC31XX_RDACVOL, 0x00 }, + { AIC31XX_ADCSETUP, 0x00 }, + { AIC31XX_ADCFGA, 0x80 }, + { AIC31XX_ADCVOL, 0x00 }, + { AIC31XX_HPDRIVER, 0x04 }, + { AIC31XX_SPKAMP, 0x06 }, + { AIC31XX_DACMIXERROUTE, 0x00 }, + { AIC31XX_LANALOGHPL, 0x7f }, + { AIC31XX_RANALOGHPR, 0x7f }, + { AIC31XX_LANALOGSPL, 0x7f }, + { AIC31XX_RANALOGSPR, 0x7f }, + { AIC31XX_HPLGAIN, 0x02 }, + { AIC31XX_HPRGAIN, 0x02 }, + { AIC31XX_SPLGAIN, 0x00 }, + { AIC31XX_SPRGAIN, 0x00 }, + { AIC31XX_MICBIAS, 0x00 }, + { AIC31XX_MICPGA, 0x80 }, + { AIC31XX_MICPGAPI, 0x00 }, + { AIC31XX_MICPGAMI, 0x00 }, +}; + +static bool aic31xx_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AIC31XX_PAGECTL: /* regmap implementation requires this */ + case AIC31XX_RESET: /* always clears after write */ + case AIC31XX_OT_FLAG: + case AIC31XX_ADCFLAG: + case AIC31XX_DACFLAG1: + case AIC31XX_DACFLAG2: + case AIC31XX_OFFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG2: + case AIC31XX_INTRADCFLAG2: + return true; + } + return false; +} + +static bool aic31xx_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AIC31XX_OT_FLAG: + case AIC31XX_ADCFLAG: + case AIC31XX_DACFLAG1: + case AIC31XX_DACFLAG2: + case AIC31XX_OFFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRADCFLAG: /* Sticky interrupt flags */ + case AIC31XX_INTRDACFLAG2: + case AIC31XX_INTRADCFLAG2: + return false; + } + return true; +} + +static const struct regmap_range_cfg aic31xx_ranges[] = { + { + .range_min = 0, + .range_max = 12 * 128, + .selector_reg = AIC31XX_PAGECTL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 128, + }, +}; + +struct regmap_config aic31xx_i2c_regmap = { + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = aic31xx_writeable, + .volatile_reg = aic31xx_volatile, + .reg_defaults = aic31xx_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(aic31xx_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .ranges = aic31xx_ranges, + .num_ranges = ARRAY_SIZE(aic31xx_ranges), + .max_register = 12 * 128, +}; + +#define AIC31XX_NUM_SUPPLIES 6 +static const char * const aic31xx_supply_names[AIC31XX_NUM_SUPPLIES] = { + "HPVDD", + "SPRVDD", + "SPLVDD", + "AVDD", + "IOVDD", + "DVDD", +}; + +struct aic31xx_disable_nb { + struct notifier_block nb; + struct aic31xx_priv *aic31xx; +}; + +struct aic31xx_priv { + struct snd_soc_codec *codec; + u8 i2c_regs_status; + struct device *dev; + struct regmap *regmap; + struct aic31xx_pdata pdata; + struct regulator_bulk_data supplies[AIC31XX_NUM_SUPPLIES]; + struct aic31xx_disable_nb disable_nb[AIC31XX_NUM_SUPPLIES]; + unsigned int sysclk; + int rate_div_line; +}; + +struct aic31xx_rate_divs { + u32 mclk; + u32 rate; + u8 p_val; + u8 pll_j; + u16 pll_d; + u16 dosr; + u8 ndac; + u8 mdac; + u8 aosr; + u8 nadc; + u8 madc; +}; + +/* ADC dividers can be disabled by cofiguring them to 0 */ +static const struct aic31xx_rate_divs aic31xx_divs[] = { + /* mclk rate pll: p j d dosr ndac mdac aors nadc madc */ + /* 8k rate */ + {12000000, 8000, 1, 8, 1920, 128, 48, 2, 128, 48, 2}, + {24000000, 8000, 2, 8, 1920, 128, 48, 2, 128, 48, 2}, + {25000000, 8000, 2, 7, 8643, 128, 48, 2, 128, 48, 2}, + /* 11.025k rate */ + {12000000, 11025, 1, 7, 5264, 128, 32, 2, 128, 32, 2}, + {24000000, 11025, 2, 7, 5264, 128, 32, 2, 128, 32, 2}, + {25000000, 11025, 2, 7, 2253, 128, 32, 2, 128, 32, 2}, + /* 16k rate */ + {12000000, 16000, 1, 8, 1920, 128, 24, 2, 128, 24, 2}, + {24000000, 16000, 2, 8, 1920, 128, 24, 2, 128, 24, 2}, + {25000000, 16000, 2, 7, 8643, 128, 24, 2, 128, 24, 2}, + /* 22.05k rate */ + {12000000, 22050, 1, 7, 5264, 128, 16, 2, 128, 16, 2}, + {24000000, 22050, 2, 7, 5264, 128, 16, 2, 128, 16, 2}, + {25000000, 22050, 2, 7, 2253, 128, 16, 2, 128, 16, 2}, + /* 32k rate */ + {12000000, 32000, 1, 8, 1920, 128, 12, 2, 128, 12, 2}, + {24000000, 32000, 2, 8, 1920, 128, 12, 2, 128, 12, 2}, + {25000000, 32000, 2, 7, 8643, 128, 12, 2, 128, 12, 2}, + /* 44.1k rate */ + {12000000, 44100, 1, 7, 5264, 128, 8, 2, 128, 8, 2}, + {24000000, 44100, 2, 7, 5264, 128, 8, 2, 128, 8, 2}, + {25000000, 44100, 2, 7, 2253, 128, 8, 2, 128, 8, 2}, + /* 48k rate */ + {12000000, 48000, 1, 8, 1920, 128, 8, 2, 128, 8, 2}, + {24000000, 48000, 2, 8, 1920, 128, 8, 2, 128, 8, 2}, + {25000000, 48000, 2, 7, 8643, 128, 8, 2, 128, 8, 2}, + /* 88.2k rate */ + {12000000, 88200, 1, 7, 5264, 64, 8, 2, 64, 8, 2}, + {24000000, 88200, 2, 7, 5264, 64, 8, 2, 64, 8, 2}, + {25000000, 88200, 2, 7, 2253, 64, 8, 2, 64, 8, 2}, + /* 96k rate */ + {12000000, 96000, 1, 8, 1920, 64, 8, 2, 64, 8, 2}, + {24000000, 96000, 2, 8, 1920, 64, 8, 2, 64, 8, 2}, + {25000000, 96000, 2, 7, 8643, 64, 8, 2, 64, 8, 2}, + /* 176.4k rate */ + {12000000, 176400, 1, 7, 5264, 32, 8, 2, 32, 8, 2}, + {24000000, 176400, 2, 7, 5264, 32, 8, 2, 32, 8, 2}, + {25000000, 176400, 2, 7, 2253, 32, 8, 2, 32, 8, 2}, + /* 192k rate */ + {12000000, 192000, 1, 8, 1920, 32, 8, 2, 32, 8, 2}, + {24000000, 192000, 2, 8, 1920, 32, 8, 2, 32, 8, 2}, + {25000000, 192000, 2, 7, 8643, 32, 8, 2, 32, 8, 2}, +}; + +static const char * const ldac_in_text[] = { + "Off", "Left Data", "Right Data", "Mono" +}; + +static const char * const rdac_in_text[] = { + "Off", "Right Data", "Left Data", "Mono" +}; + +static SOC_ENUM_SINGLE_DECL(ldac_in_enum, AIC31XX_DACSETUP, 4, ldac_in_text); + +static SOC_ENUM_SINGLE_DECL(rdac_in_enum, AIC31XX_DACSETUP, 2, rdac_in_text); + +static const char * const mic_select_text[] = { + "Off", "FFR 10 Ohm", "FFR 20 Ohm", "FFR 40 Ohm" +}; + +static const +SOC_ENUM_SINGLE_DECL(mic1lp_p_enum, AIC31XX_MICPGAPI, 6, mic_select_text); +static const +SOC_ENUM_SINGLE_DECL(mic1rp_p_enum, AIC31XX_MICPGAPI, 4, mic_select_text); +static const +SOC_ENUM_SINGLE_DECL(mic1lm_p_enum, AIC31XX_MICPGAPI, 2, mic_select_text); + +static const +SOC_ENUM_SINGLE_DECL(cm_m_enum, AIC31XX_MICPGAMI, 6, mic_select_text); +static const +SOC_ENUM_SINGLE_DECL(mic1lm_m_enum, AIC31XX_MICPGAMI, 4, mic_select_text); + +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0); +static const DECLARE_TLV_DB_SCALE(adc_fgain_tlv, 0, 10, 0); +static const DECLARE_TLV_DB_SCALE(adc_cgain_tlv, -2000, 50, 0); +static const DECLARE_TLV_DB_SCALE(mic_pga_tlv, 0, 50, 0); +static const DECLARE_TLV_DB_SCALE(hp_drv_tlv, 0, 100, 0); +static const DECLARE_TLV_DB_SCALE(class_D_drv_tlv, 600, 600, 0); +static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -6350, 50, 0); +static const DECLARE_TLV_DB_SCALE(sp_vol_tlv, -6350, 50, 0); + +/* + * controls to be exported to the user space + */ +static const struct snd_kcontrol_new aic31xx_snd_controls[] = { + SOC_DOUBLE_R_S_TLV("DAC Playback Volume", AIC31XX_LDACVOL, + AIC31XX_RDACVOL, 0, -127, 48, 7, 0, dac_vol_tlv), + + SOC_SINGLE_TLV("ADC Fine Capture Volume", AIC31XX_ADCFGA, 4, 4, 1, + adc_fgain_tlv), + + SOC_SINGLE("ADC Capture Switch", AIC31XX_ADCFGA, 7, 1, 1), + SOC_DOUBLE_R_S_TLV("ADC Capture Volume", AIC31XX_ADCVOL, AIC31XX_ADCVOL, + 0, -24, 40, 6, 0, adc_cgain_tlv), + + SOC_SINGLE_TLV("Mic PGA Capture Volume", AIC31XX_MICPGA, 0, + 119, 0, mic_pga_tlv), + + SOC_DOUBLE_R("HP Driver Playback Switch", AIC31XX_HPLGAIN, + AIC31XX_HPRGAIN, 2, 1, 0), + SOC_DOUBLE_R_TLV("HP Driver Playback Volume", AIC31XX_HPLGAIN, + AIC31XX_HPRGAIN, 3, 0x09, 0, hp_drv_tlv), + + SOC_DOUBLE_R_TLV("HP Analog Playback Volume", AIC31XX_LANALOGHPL, + AIC31XX_RANALOGHPR, 0, 0x7F, 1, hp_vol_tlv), +}; + +static const struct snd_kcontrol_new aic311x_snd_controls[] = { + SOC_DOUBLE_R("Speaker Driver Playback Switch", AIC31XX_SPLGAIN, + AIC31XX_SPRGAIN, 2, 1, 0), + SOC_DOUBLE_R_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN, + AIC31XX_SPRGAIN, 3, 3, 0, class_D_drv_tlv), + + SOC_DOUBLE_R_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL, + AIC31XX_RANALOGSPR, 0, 0x7F, 1, sp_vol_tlv), +}; + +static const struct snd_kcontrol_new aic310x_snd_controls[] = { + SOC_SINGLE("Speaker Driver Playback Switch", AIC31XX_SPLGAIN, + 2, 1, 0), + SOC_SINGLE_TLV("Speaker Driver Playback Volume", AIC31XX_SPLGAIN, + 3, 3, 0, class_D_drv_tlv), + + SOC_SINGLE_TLV("Speaker Analog Playback Volume", AIC31XX_LANALOGSPL, + 0, 0x7F, 1, sp_vol_tlv), +}; + +static const struct snd_kcontrol_new ldac_in_control = + SOC_DAPM_ENUM("DAC Left Input", ldac_in_enum); + +static const struct snd_kcontrol_new rdac_in_control = + SOC_DAPM_ENUM("DAC Right Input", rdac_in_enum); + +int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg, + unsigned int mask, unsigned int wbits, int sleep, + int count) +{ + unsigned int bits; + int counter = count; + int ret = regmap_read(aic31xx->regmap, reg, &bits); + while ((bits & mask) != wbits && counter && !ret) { + usleep_range(sleep, sleep * 2); + ret = regmap_read(aic31xx->regmap, reg, &bits); + counter--; + } + if ((bits & mask) != wbits) { + dev_err(aic31xx->dev, + "%s: Failed! 0x%x was 0x%x expected 0x%x (%d, 0x%x, %d us)\n", + __func__, reg, bits, wbits, ret, mask, + (count - counter) * sleep); + ret = -1; + } + return ret; +} + +#define WIDGET_BIT(reg, shift) (((shift) << 8) | (reg)) + +static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(w->codec); + unsigned int reg = AIC31XX_DACFLAG1; + unsigned int mask; + + switch (WIDGET_BIT(w->reg, w->shift)) { + case WIDGET_BIT(AIC31XX_DACSETUP, 7): + mask = AIC31XX_LDACPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_DACSETUP, 6): + mask = AIC31XX_RDACPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_HPDRIVER, 7): + mask = AIC31XX_HPLDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_HPDRIVER, 6): + mask = AIC31XX_HPRDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_SPKAMP, 7): + mask = AIC31XX_SPLDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_SPKAMP, 6): + mask = AIC31XX_SPRDRVPWRSTATUS_MASK; + break; + case WIDGET_BIT(AIC31XX_ADCSETUP, 7): + mask = AIC31XX_ADCPWRSTATUS_MASK; + reg = AIC31XX_ADCFLAG; + break; + default: + dev_err(w->codec->dev, "Unknown widget '%s' calling %s/n", + w->name, __func__); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + return aic31xx_wait_bits(aic31xx, reg, mask, mask, 5000, 100); + case SND_SOC_DAPM_POST_PMD: + return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100); + default: + dev_dbg(w->codec->dev, + "Unhandled dapm widget event %d from %s\n", + event, w->name); + } + return 0; +} + +static const struct snd_kcontrol_new left_output_switches[] = { + SOC_DAPM_SINGLE("From Left DAC", AIC31XX_DACMIXERROUTE, 6, 1, 0), + SOC_DAPM_SINGLE("From MIC1LP", AIC31XX_DACMIXERROUTE, 5, 1, 0), + SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 4, 1, 0), +}; + +static const struct snd_kcontrol_new right_output_switches[] = { + SOC_DAPM_SINGLE("From Right DAC", AIC31XX_DACMIXERROUTE, 2, 1, 0), + SOC_DAPM_SINGLE("From MIC1RP", AIC31XX_DACMIXERROUTE, 1, 1, 0), +}; + +static const struct snd_kcontrol_new p_term_mic1lp = + SOC_DAPM_ENUM("MIC1LP P-Terminal", mic1lp_p_enum); + +static const struct snd_kcontrol_new p_term_mic1rp = + SOC_DAPM_ENUM("MIC1RP P-Terminal", mic1rp_p_enum); + +static const struct snd_kcontrol_new p_term_mic1lm = + SOC_DAPM_ENUM("MIC1LM P-Terminal", mic1lm_p_enum); + +static const struct snd_kcontrol_new m_term_mic1lm = + SOC_DAPM_ENUM("MIC1LM M-Terminal", mic1lm_m_enum); + +static const struct snd_kcontrol_new aic31xx_dapm_hpl_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGHPL, 7, 1, 0); + +static const struct snd_kcontrol_new aic31xx_dapm_hpr_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGHPR, 7, 1, 0); + +static const struct snd_kcontrol_new aic31xx_dapm_spl_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_LANALOGSPL, 7, 1, 0); + +static const struct snd_kcontrol_new aic31xx_dapm_spr_switch = + SOC_DAPM_SINGLE("Switch", AIC31XX_RANALOGSPR, 7, 1, 0); + +static int mic_bias_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* change mic bias voltage to user defined */ + snd_soc_update_bits(codec, AIC31XX_MICBIAS, + AIC31XX_MICBIAS_MASK, + aic31xx->pdata.micbias_vg << + AIC31XX_MICBIAS_SHIFT); + dev_dbg(codec->dev, "%s: turned on\n", __func__); + break; + case SND_SOC_DAPM_PRE_PMD: + /* turn mic bias off */ + snd_soc_update_bits(codec, AIC31XX_MICBIAS, + AIC31XX_MICBIAS_MASK, 0); + dev_dbg(codec->dev, "%s: turned off\n", __func__); + break; + } + return 0; +} + +static const struct snd_soc_dapm_widget aic31xx_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_MUX("DAC Left Input", + SND_SOC_NOPM, 0, 0, &ldac_in_control), + SND_SOC_DAPM_MUX("DAC Right Input", + SND_SOC_NOPM, 0, 0, &rdac_in_control), + /* DACs */ + SND_SOC_DAPM_DAC_E("DAC Left", "Left Playback", + AIC31XX_DACSETUP, 7, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_DAC_E("DAC Right", "Right Playback", + AIC31XX_DACSETUP, 6, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + /* Output Mixers */ + SND_SOC_DAPM_MIXER("Output Left", SND_SOC_NOPM, 0, 0, + left_output_switches, + ARRAY_SIZE(left_output_switches)), + SND_SOC_DAPM_MIXER("Output Right", SND_SOC_NOPM, 0, 0, + right_output_switches, + ARRAY_SIZE(right_output_switches)), + + SND_SOC_DAPM_SWITCH("HP Left", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_hpl_switch), + SND_SOC_DAPM_SWITCH("HP Right", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_hpr_switch), + + /* Output drivers */ + SND_SOC_DAPM_OUT_DRV_E("HPL Driver", AIC31XX_HPDRIVER, 7, 0, + NULL, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_OUT_DRV_E("HPR Driver", AIC31XX_HPDRIVER, 6, 0, + NULL, 0, aic31xx_dapm_power_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + + /* ADC */ + SND_SOC_DAPM_ADC_E("ADC", "Capture", AIC31XX_ADCSETUP, 7, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + /* Input Selection to MIC_PGA */ + SND_SOC_DAPM_MUX("MIC1LP P-Terminal", SND_SOC_NOPM, 0, 0, + &p_term_mic1lp), + SND_SOC_DAPM_MUX("MIC1RP P-Terminal", SND_SOC_NOPM, 0, 0, + &p_term_mic1rp), + SND_SOC_DAPM_MUX("MIC1LM P-Terminal", SND_SOC_NOPM, 0, 0, + &p_term_mic1lm), + + SND_SOC_DAPM_MUX("MIC1LM M-Terminal", SND_SOC_NOPM, 0, 0, + &m_term_mic1lm), + /* Enabling & Disabling MIC Gain Ctl */ + SND_SOC_DAPM_PGA("MIC_GAIN_CTL", AIC31XX_MICPGA, + 7, 1, NULL, 0), + + /* Mic Bias */ + SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, mic_bias_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + /* Outputs */ + SND_SOC_DAPM_OUTPUT("HPL"), + SND_SOC_DAPM_OUTPUT("HPR"), + + /* Inputs */ + SND_SOC_DAPM_INPUT("MIC1LP"), + SND_SOC_DAPM_INPUT("MIC1RP"), + SND_SOC_DAPM_INPUT("MIC1LM"), +}; + +static const struct snd_soc_dapm_widget aic311x_dapm_widgets[] = { + /* AIC3111 and AIC3110 have stereo class-D amplifier */ + SND_SOC_DAPM_OUT_DRV_E("SPL ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUT_DRV_E("SPR ClassD", AIC31XX_SPKAMP, 6, 0, NULL, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SWITCH("Speaker Left", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_spl_switch), + SND_SOC_DAPM_SWITCH("Speaker Right", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_spr_switch), + SND_SOC_DAPM_OUTPUT("SPL"), + SND_SOC_DAPM_OUTPUT("SPR"), +}; + +/* AIC3100 and AIC3120 have only mono class-D amplifier */ +static const struct snd_soc_dapm_widget aic310x_dapm_widgets[] = { + SND_SOC_DAPM_OUT_DRV_E("SPK ClassD", AIC31XX_SPKAMP, 7, 0, NULL, 0, + aic31xx_dapm_power_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SWITCH("Speaker", SND_SOC_NOPM, 0, 0, + &aic31xx_dapm_spl_switch), + SND_SOC_DAPM_OUTPUT("SPK"), +}; + +static const struct snd_soc_dapm_route +aic31xx_audio_map[] = { + /* DAC Input Routing */ + {"DAC Left Input", "Left Data", "DAC IN"}, + {"DAC Left Input", "Right Data", "DAC IN"}, + {"DAC Left Input", "Mono", "DAC IN"}, + {"DAC Right Input", "Left Data", "DAC IN"}, + {"DAC Right Input", "Right Data", "DAC IN"}, + {"DAC Right Input", "Mono", "DAC IN"}, + {"DAC Left", NULL, "DAC Left Input"}, + {"DAC Right", NULL, "DAC Right Input"}, + + /* Mic input */ + {"MIC1LP P-Terminal", "FFR 10 Ohm", "MIC1LP"}, + {"MIC1LP P-Terminal", "FFR 20 Ohm", "MIC1LP"}, + {"MIC1LP P-Terminal", "FFR 40 Ohm", "MIC1LP"}, + {"MIC1RP P-Terminal", "FFR 10 Ohm", "MIC1RP"}, + {"MIC1RP P-Terminal", "FFR 20 Ohm", "MIC1RP"}, + {"MIC1RP P-Terminal", "FFR 40 Ohm", "MIC1RP"}, + {"MIC1LM P-Terminal", "FFR 10 Ohm", "MIC1LM"}, + {"MIC1LM P-Terminal", "FFR 20 Ohm", "MIC1LM"}, + {"MIC1LM P-Terminal", "FFR 40 Ohm", "MIC1LM"}, + + {"MIC1LM M-Terminal", "FFR 10 Ohm", "MIC1LM"}, + {"MIC1LM M-Terminal", "FFR 20 Ohm", "MIC1LM"}, + {"MIC1LM M-Terminal", "FFR 40 Ohm", "MIC1LM"}, + + {"MIC_GAIN_CTL", NULL, "MIC1LP P-Terminal"}, + {"MIC_GAIN_CTL", NULL, "MIC1RP P-Terminal"}, + {"MIC_GAIN_CTL", NULL, "MIC1LM P-Terminal"}, + {"MIC_GAIN_CTL", NULL, "MIC1LM M-Terminal"}, + + {"ADC", NULL, "MIC_GAIN_CTL"}, + + /* Left Output */ + {"Output Left", "From Left DAC", "DAC Left"}, + {"Output Left", "From MIC1LP", "MIC1LP"}, + {"Output Left", "From MIC1RP", "MIC1RP"}, + + /* Right Output */ + {"Output Right", "From Right DAC", "DAC Right"}, + {"Output Right", "From MIC1RP", "MIC1RP"}, + + /* HPL path */ + {"HP Left", "Switch", "Output Left"}, + {"HPL Driver", NULL, "HP Left"}, + {"HPL", NULL, "HPL Driver"}, + + /* HPR path */ + {"HP Right", "Switch", "Output Right"}, + {"HPR Driver", NULL, "HP Right"}, + {"HPR", NULL, "HPR Driver"}, +}; + +static const struct snd_soc_dapm_route +aic311x_audio_map[] = { + /* SP L path */ + {"Speaker Left", "Switch", "Output Left"}, + {"SPL ClassD", NULL, "Speaker Left"}, + {"SPL", NULL, "SPL ClassD"}, + + /* SP R path */ + {"Speaker Right", "Switch", "Output Right"}, + {"SPR ClassD", NULL, "Speaker Right"}, + {"SPR", NULL, "SPR ClassD"}, +}; + +static const struct snd_soc_dapm_route +aic310x_audio_map[] = { + /* SP L path */ + {"Speaker", "Switch", "Output Left"}, + {"SPK ClassD", NULL, "Speaker"}, + {"SPK", NULL, "SPK ClassD"}, +}; + +static int aic31xx_add_controls(struct snd_soc_codec *codec) +{ + int ret = 0; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + + if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) + ret = snd_soc_add_codec_controls( + codec, aic311x_snd_controls, + ARRAY_SIZE(aic311x_snd_controls)); + else + ret = snd_soc_add_codec_controls( + codec, aic310x_snd_controls, + ARRAY_SIZE(aic310x_snd_controls)); + + return ret; +} + +static int aic31xx_add_widgets(struct snd_soc_codec *codec) +{ + struct snd_soc_dapm_context *dapm = &codec->dapm; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + if (aic31xx->pdata.codec_type & AIC31XX_STEREO_CLASS_D_BIT) { + ret = snd_soc_dapm_new_controls( + dapm, aic311x_dapm_widgets, + ARRAY_SIZE(aic311x_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, aic311x_audio_map, + ARRAY_SIZE(aic311x_audio_map)); + if (ret) + return ret; + } else { + ret = snd_soc_dapm_new_controls( + dapm, aic310x_dapm_widgets, + ARRAY_SIZE(aic310x_dapm_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, aic310x_audio_map, + ARRAY_SIZE(aic310x_audio_map)); + if (ret) + return ret; + } + + return 0; +} + +static int aic31xx_setup_pll(struct snd_soc_codec *codec, + struct snd_pcm_hw_params *params) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int bclk_n = 0; + int i; + + /* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */ + snd_soc_update_bits(codec, AIC31XX_CLKMUX, + AIC31XX_CODEC_CLKIN_MASK, AIC31XX_CODEC_CLKIN_PLL); + snd_soc_update_bits(codec, AIC31XX_IFACE2, + AIC31XX_BDIVCLK_MASK, AIC31XX_DAC2BCLK); + + for (i = 0; i < ARRAY_SIZE(aic31xx_divs); i++) { + if (aic31xx_divs[i].rate == params_rate(params) && + aic31xx_divs[i].mclk == aic31xx->sysclk) + break; + } + + if (i == ARRAY_SIZE(aic31xx_divs)) { + dev_err(codec->dev, "%s: Sampling rate %u not supported\n", + __func__, params_rate(params)); + return -EINVAL; + } + + /* PLL configuration */ + snd_soc_update_bits(codec, AIC31XX_PLLPR, AIC31XX_PLL_MASK, + (aic31xx_divs[i].p_val << 4) | 0x01); + snd_soc_write(codec, AIC31XX_PLLJ, aic31xx_divs[i].pll_j); + + snd_soc_write(codec, AIC31XX_PLLDMSB, + aic31xx_divs[i].pll_d >> 8); + snd_soc_write(codec, AIC31XX_PLLDLSB, + aic31xx_divs[i].pll_d & 0xff); + + /* DAC dividers configuration */ + snd_soc_update_bits(codec, AIC31XX_NDAC, AIC31XX_PLL_MASK, + aic31xx_divs[i].ndac); + snd_soc_update_bits(codec, AIC31XX_MDAC, AIC31XX_PLL_MASK, + aic31xx_divs[i].mdac); + + snd_soc_write(codec, AIC31XX_DOSRMSB, aic31xx_divs[i].dosr >> 8); + snd_soc_write(codec, AIC31XX_DOSRLSB, aic31xx_divs[i].dosr & 0xff); + + /* ADC dividers configuration. Write reset value 1 if not used. */ + snd_soc_update_bits(codec, AIC31XX_NADC, AIC31XX_PLL_MASK, + aic31xx_divs[i].nadc ? aic31xx_divs[i].nadc : 1); + snd_soc_update_bits(codec, AIC31XX_MADC, AIC31XX_PLL_MASK, + aic31xx_divs[i].madc ? aic31xx_divs[i].madc : 1); + + snd_soc_write(codec, AIC31XX_AOSR, aic31xx_divs[i].aosr); + + /* Bit clock divider configuration. */ + bclk_n = (aic31xx_divs[i].dosr * aic31xx_divs[i].mdac) + / snd_soc_params_to_frame_size(params); + if (bclk_n == 0) { + dev_err(codec->dev, "%s: Not enough BLCK bandwidth\n", + __func__); + return -EINVAL; + } + + snd_soc_update_bits(codec, AIC31XX_BCLKN, + AIC31XX_PLL_MASK, bclk_n); + + aic31xx->rate_div_line = i; + + dev_dbg(codec->dev, + "pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d\n", + aic31xx_divs[i].pll_j, aic31xx_divs[i].pll_d, + aic31xx_divs[i].p_val, aic31xx_divs[i].dosr, + aic31xx_divs[i].ndac, aic31xx_divs[i].mdac, + aic31xx_divs[i].aosr, aic31xx_divs[i].nadc, + aic31xx_divs[i].madc, bclk_n); + + return 0; +} + +static int aic31xx_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *tmp) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + u8 data = 0; + + dev_dbg(codec->dev, "## %s: format %d width %d rate %d\n", + __func__, params_format(params), params_width(params), + params_rate(params)); + + switch (params_width(params)) { + case 16: + break; + case 20: + data = (AIC31XX_WORD_LEN_20BITS << + AIC31XX_IFACE1_DATALEN_SHIFT); + break; + case 24: + data = (AIC31XX_WORD_LEN_24BITS << + AIC31XX_IFACE1_DATALEN_SHIFT); + break; + case 32: + data = (AIC31XX_WORD_LEN_32BITS << + AIC31XX_IFACE1_DATALEN_SHIFT); + break; + default: + dev_err(codec->dev, "%s: Unsupported format %d\n", + __func__, params_format(params)); + return -EINVAL; + } + + snd_soc_update_bits(codec, AIC31XX_IFACE1, + AIC31XX_IFACE1_DATALEN_MASK, + data); + + return aic31xx_setup_pll(codec, params); +} + +static int aic31xx_dac_mute(struct snd_soc_dai *codec_dai, int mute) +{ + struct snd_soc_codec *codec = codec_dai->codec; + + if (mute) { + snd_soc_update_bits(codec, AIC31XX_DACMUTE, + AIC31XX_DACMUTE_MASK, + AIC31XX_DACMUTE_MASK); + } else { + snd_soc_update_bits(codec, AIC31XX_DACMUTE, + AIC31XX_DACMUTE_MASK, 0x0); + } + + return 0; +} + +static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u8 iface_reg1 = 0; + u8 iface_reg3 = 0; + u8 dsp_a_val = 0; + + dev_dbg(codec->dev, "## %s: fmt = 0x%x\n", __func__, fmt); + + /* set master/slave audio interface */ + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + iface_reg1 |= AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER; + break; + default: + dev_alert(codec->dev, "Invalid DAI master/slave interface\n"); + return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + case SND_SOC_DAIFMT_DSP_A: + dsp_a_val = 0x1; + case SND_SOC_DAIFMT_DSP_B: + /* NOTE: BCLKINV bit value 1 equas NB and 0 equals IB */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + iface_reg3 |= AIC31XX_BCLKINV_MASK; + break; + case SND_SOC_DAIFMT_IB_NF: + break; + default: + return -EINVAL; + } + iface_reg1 |= (AIC31XX_DSP_MODE << + AIC31XX_IFACE1_DATATYPE_SHIFT); + break; + case SND_SOC_DAIFMT_RIGHT_J: + iface_reg1 |= (AIC31XX_RIGHT_JUSTIFIED_MODE << + AIC31XX_IFACE1_DATATYPE_SHIFT); + break; + case SND_SOC_DAIFMT_LEFT_J: + iface_reg1 |= (AIC31XX_LEFT_JUSTIFIED_MODE << + AIC31XX_IFACE1_DATATYPE_SHIFT); + break; + default: + dev_err(codec->dev, "Invalid DAI interface format\n"); + return -EINVAL; + } + + snd_soc_update_bits(codec, AIC31XX_IFACE1, + AIC31XX_IFACE1_DATATYPE_MASK | + AIC31XX_IFACE1_MASTER_MASK, + iface_reg1); + snd_soc_update_bits(codec, AIC31XX_DATA_OFFSET, + AIC31XX_DATA_OFFSET_MASK, + dsp_a_val); + snd_soc_update_bits(codec, AIC31XX_IFACE2, + AIC31XX_BCLKINV_MASK, + iface_reg3); + + return 0; +} + +static int aic31xx_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int i; + + dev_dbg(codec->dev, "## %s: clk_id = %d, freq = %d, dir = %d\n", + __func__, clk_id, freq, dir); + + for (i = 0; aic31xx_divs[i].mclk != freq; i++) { + if (i == ARRAY_SIZE(aic31xx_divs)) { + dev_err(aic31xx->dev, "%s: Unsupported frequency %d\n", + __func__, freq); + return -EINVAL; + } + } + + /* set clock on MCLK, BCLK, or GPIO1 as PLL input */ + snd_soc_update_bits(codec, AIC31XX_CLKMUX, AIC31XX_PLL_CLKIN_MASK, + clk_id << AIC31XX_PLL_CLKIN_SHIFT); + + aic31xx->sysclk = freq; + return 0; +} + +static int aic31xx_regulator_event(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct aic31xx_disable_nb *disable_nb = + container_of(nb, struct aic31xx_disable_nb, nb); + struct aic31xx_priv *aic31xx = disable_nb->aic31xx; + + if (event & REGULATOR_EVENT_DISABLE) { + /* + * Put codec to reset and as at least one of the + * supplies was disabled. + */ + if (gpio_is_valid(aic31xx->pdata.gpio_reset)) + gpio_set_value(aic31xx->pdata.gpio_reset, 0); + + regcache_mark_dirty(aic31xx->regmap); + dev_dbg(aic31xx->dev, "## %s: DISABLE received\n", __func__); + } + + return 0; +} + +static void aic31xx_clk_on(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + u8 mask = AIC31XX_PM_MASK; + u8 on = AIC31XX_PM_MASK; + + dev_dbg(codec->dev, "codec clock -> on (rate %d)\n", + aic31xx_divs[aic31xx->rate_div_line].rate); + snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, on); + mdelay(10); + snd_soc_update_bits(codec, AIC31XX_NDAC, mask, on); + snd_soc_update_bits(codec, AIC31XX_MDAC, mask, on); + if (aic31xx_divs[aic31xx->rate_div_line].nadc) + snd_soc_update_bits(codec, AIC31XX_NADC, mask, on); + if (aic31xx_divs[aic31xx->rate_div_line].madc) + snd_soc_update_bits(codec, AIC31XX_MADC, mask, on); + snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, on); +} + +static void aic31xx_clk_off(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + u8 mask = AIC31XX_PM_MASK; + u8 off = 0; + + dev_dbg(codec->dev, "codec clock -> off\n"); + snd_soc_update_bits(codec, AIC31XX_BCLKN, mask, off); + snd_soc_update_bits(codec, AIC31XX_MADC, mask, off); + snd_soc_update_bits(codec, AIC31XX_NADC, mask, off); + snd_soc_update_bits(codec, AIC31XX_MDAC, mask, off); + snd_soc_update_bits(codec, AIC31XX_NDAC, mask, off); + snd_soc_update_bits(codec, AIC31XX_PLLPR, mask, off); +} + +static int aic31xx_power_on(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + ret = regulator_bulk_enable(ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + if (ret) + return ret; + + if (gpio_is_valid(aic31xx->pdata.gpio_reset)) { + gpio_set_value(aic31xx->pdata.gpio_reset, 1); + udelay(100); + } + regcache_cache_only(aic31xx->regmap, false); + ret = regcache_sync(aic31xx->regmap); + if (ret != 0) { + dev_err(codec->dev, + "Failed to restore cache: %d\n", ret); + regcache_cache_only(aic31xx->regmap, true); + regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + return ret; + } + return 0; +} + +static int aic31xx_power_off(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + regcache_cache_only(aic31xx->regmap, true); + ret = regulator_bulk_disable(ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + + return ret; +} + +static int aic31xx_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + dev_dbg(codec->dev, "## %s: %d -> %d\n", __func__, + codec->dapm.bias_level, level); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) + aic31xx_clk_on(codec); + break; + case SND_SOC_BIAS_STANDBY: + switch (codec->dapm.bias_level) { + case SND_SOC_BIAS_OFF: + aic31xx_power_on(codec); + break; + case SND_SOC_BIAS_PREPARE: + aic31xx_clk_off(codec); + break; + default: + BUG(); + } + break; + case SND_SOC_BIAS_OFF: + aic31xx_power_off(codec); + break; + } + codec->dapm.bias_level = level; + + return 0; +} + +static int aic31xx_suspend(struct snd_soc_codec *codec) +{ + aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF); + return 0; +} + +static int aic31xx_resume(struct snd_soc_codec *codec) +{ + aic31xx_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + return 0; +} + +static int aic31xx_codec_probe(struct snd_soc_codec *codec) +{ + int ret = 0; + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int i; + + dev_dbg(aic31xx->dev, "## %s\n", __func__); + + aic31xx = snd_soc_codec_get_drvdata(codec); + codec->control_data = aic31xx->regmap; + + aic31xx->codec = codec; + + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); + + if (ret != 0) { + dev_err(codec->dev, "snd_soc_codec_set_cache_io failed %d\n", + ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) { + aic31xx->disable_nb[i].nb.notifier_call = + aic31xx_regulator_event; + aic31xx->disable_nb[i].aic31xx = aic31xx; + ret = regulator_register_notifier(aic31xx->supplies[i].consumer, + &aic31xx->disable_nb[i].nb); + if (ret) { + dev_err(codec->dev, + "Failed to request regulator notifier: %d\n", + ret); + return ret; + } + } + + regcache_cache_only(aic31xx->regmap, true); + regcache_mark_dirty(aic31xx->regmap); + + ret = aic31xx_add_controls(codec); + if (ret) + return ret; + + ret = aic31xx_add_widgets(codec); + + return ret; +} + +static int aic31xx_codec_remove(struct snd_soc_codec *codec) +{ + struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); + int i; + /* power down chip */ + aic31xx_set_bias_level(codec, SND_SOC_BIAS_OFF); + + for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) + regulator_unregister_notifier(aic31xx->supplies[i].consumer, + &aic31xx->disable_nb[i].nb); + + return 0; +} + +static struct snd_soc_codec_driver soc_codec_driver_aic31xx = { + .probe = aic31xx_codec_probe, + .remove = aic31xx_codec_remove, + .suspend = aic31xx_suspend, + .resume = aic31xx_resume, + .set_bias_level = aic31xx_set_bias_level, + .controls = aic31xx_snd_controls, + .num_controls = ARRAY_SIZE(aic31xx_snd_controls), + .dapm_widgets = aic31xx_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic31xx_dapm_widgets), + .dapm_routes = aic31xx_audio_map, + .num_dapm_routes = ARRAY_SIZE(aic31xx_audio_map), +}; + +static struct snd_soc_dai_ops aic31xx_dai_ops = { + .hw_params = aic31xx_hw_params, + .set_sysclk = aic31xx_set_dai_sysclk, + .set_fmt = aic31xx_set_dai_fmt, + .digital_mute = aic31xx_dac_mute, +}; + +static struct snd_soc_dai_driver aic31xx_dai_driver[] = { + { + .name = "tlv320aic31xx-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = AIC31XX_RATES, + .formats = AIC31XX_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = AIC31XX_RATES, + .formats = AIC31XX_FORMATS, + }, + .ops = &aic31xx_dai_ops, + .symmetric_rates = 1, + } +}; + +#if defined(CONFIG_OF) +static const struct of_device_id tlv320aic31xx_of_match[] = { + { .compatible = "ti,tlv320aic310x" }, + { .compatible = "ti,tlv320aic311x" }, + { .compatible = "ti,tlv320aic3100" }, + { .compatible = "ti,tlv320aic3110" }, + { .compatible = "ti,tlv320aic3120" }, + { .compatible = "ti,tlv320aic3111" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tlv320aic31xx_of_match); + +static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) +{ + struct device_node *np = aic31xx->dev->of_node; + unsigned int value = MICBIAS_2_0V; + int ret; + + of_property_read_u32(np, "ai31xx-micbias-vg", &value); + switch (value) { + case MICBIAS_2_0V: + case MICBIAS_2_5V: + case MICBIAS_AVDDV: + aic31xx->pdata.micbias_vg = value; + break; + default: + dev_err(aic31xx->dev, + "Bad ai31xx-micbias-vg value %d DT\n", + value); + aic31xx->pdata.micbias_vg = MICBIAS_2_0V; + } + + ret = of_get_named_gpio(np, "gpio-reset", 0); + if (ret > 0) + aic31xx->pdata.gpio_reset = ret; +} +#else /* CONFIG_OF */ +static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) +{ +} +#endif /* CONFIG_OF */ + +void aic31xx_device_init(struct aic31xx_priv *aic31xx) +{ + int ret, i; + + dev_set_drvdata(aic31xx->dev, aic31xx); + + if (dev_get_platdata(aic31xx->dev)) + memcpy(&aic31xx->pdata, dev_get_platdata(aic31xx->dev), + sizeof(aic31xx->pdata)); + else if (aic31xx->dev->of_node) + aic31xx_pdata_from_of(aic31xx); + + if (aic31xx->pdata.gpio_reset) { + ret = devm_gpio_request_one(aic31xx->dev, + aic31xx->pdata.gpio_reset, + GPIOF_OUT_INIT_HIGH, + "aic31xx-reset-pin"); + if (ret < 0) { + dev_err(aic31xx->dev, "not able to acquire gpio\n"); + return; + } + } + + for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) + aic31xx->supplies[i].supply = aic31xx_supply_names[i]; + + ret = devm_regulator_bulk_get(aic31xx->dev, + ARRAY_SIZE(aic31xx->supplies), + aic31xx->supplies); + if (ret != 0) + dev_err(aic31xx->dev, "Failed to request supplies: %d\n", ret); + +} + +static int aic31xx_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct aic31xx_priv *aic31xx; + int ret; + const struct regmap_config *regmap_config; + + dev_dbg(&i2c->dev, "## %s: %s codec_type = %d\n", __func__, + id->name, (int) id->driver_data); + + regmap_config = &aic31xx_i2c_regmap; + + aic31xx = devm_kzalloc(&i2c->dev, sizeof(*aic31xx), GFP_KERNEL); + if (aic31xx == NULL) + return -ENOMEM; + + aic31xx->regmap = devm_regmap_init_i2c(i2c, regmap_config); + + if (IS_ERR(aic31xx->regmap)) { + ret = PTR_ERR(aic31xx->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + aic31xx->dev = &i2c->dev; + + aic31xx->pdata.codec_type = id->driver_data; + + aic31xx_device_init(aic31xx); + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, + aic31xx_dai_driver, + ARRAY_SIZE(aic31xx_dai_driver)); + + return ret; +} + +static int aic31xx_i2c_remove(struct i2c_client *i2c) +{ + struct aic31xx_priv *aic31xx = dev_get_drvdata(&i2c->dev); + + kfree(aic31xx); + return 0; +} + +static const struct i2c_device_id aic31xx_i2c_id[] = { + { "tlv320aic310x", AIC3100 }, + { "tlv320aic311x", AIC3110 }, + { "tlv320aic3100", AIC3100 }, + { "tlv320aic3110", AIC3110 }, + { "tlv320aic3120", AIC3120 }, + { "tlv320aic3111", AIC3111 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); + +static struct i2c_driver aic31xx_i2c_driver = { + .driver = { + .name = "tlv320aic31xx-codec", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(tlv320aic31xx_of_match), + }, + .probe = aic31xx_i2c_probe, + .remove = (aic31xx_i2c_remove), + .id_table = aic31xx_i2c_id, +}; + +module_i2c_driver(aic31xx_i2c_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC3111 codec driver"); +MODULE_AUTHOR("Jyri Sarha"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic31xx.h b/sound/soc/codecs/tlv320aic31xx.h new file mode 100644 index 000000000000..52ed57c69dfa --- /dev/null +++ b/sound/soc/codecs/tlv320aic31xx.h @@ -0,0 +1,258 @@ +/* + * ALSA SoC TLV320AIC31XX codec driver + * + * Copyright (C) 2013 Texas Instruments, Inc. + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ +#ifndef _TLV320AIC31XX_H +#define _TLV320AIC31XX_H + +#define AIC31XX_RATES SNDRV_PCM_RATE_8000_192000 + +#define AIC31XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ + | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + + +#define AIC31XX_STEREO_CLASS_D_BIT 0x1 +#define AIC31XX_MINIDSP_BIT 0x2 + +enum aic31xx_type { + AIC3100 = 0, + AIC3110 = AIC31XX_STEREO_CLASS_D_BIT, + AIC3120 = AIC31XX_MINIDSP_BIT, + AIC3111 = (AIC31XX_STEREO_CLASS_D_BIT | AIC31XX_MINIDSP_BIT), +}; + +struct aic31xx_pdata { + enum aic31xx_type codec_type; + unsigned int gpio_reset; + int micbias_vg; +}; + +/* Page Control Register */ +#define AIC31XX_PAGECTL 0x00 + +/* Page 0 Registers */ +/* Software reset register */ +#define AIC31XX_RESET 0x01 +/* OT FLAG register */ +#define AIC31XX_OT_FLAG 0x03 +/* Clock clock Gen muxing, Multiplexers*/ +#define AIC31XX_CLKMUX 0x04 +/* PLL P and R-VAL register */ +#define AIC31XX_PLLPR 0x05 +/* PLL J-VAL register */ +#define AIC31XX_PLLJ 0x06 +/* PLL D-VAL MSB register */ +#define AIC31XX_PLLDMSB 0x07 +/* PLL D-VAL LSB register */ +#define AIC31XX_PLLDLSB 0x08 +/* DAC NDAC_VAL register*/ +#define AIC31XX_NDAC 0x0B +/* DAC MDAC_VAL register */ +#define AIC31XX_MDAC 0x0C +/* DAC OSR setting register 1, MSB value */ +#define AIC31XX_DOSRMSB 0x0D +/* DAC OSR setting register 2, LSB value */ +#define AIC31XX_DOSRLSB 0x0E +#define AIC31XX_MINI_DSP_INPOL 0x10 +/* Clock setting register 8, PLL */ +#define AIC31XX_NADC 0x12 +/* Clock setting register 9, PLL */ +#define AIC31XX_MADC 0x13 +/* ADC Oversampling (AOSR) Register */ +#define AIC31XX_AOSR 0x14 +/* Clock setting register 9, Multiplexers */ +#define AIC31XX_CLKOUTMUX 0x19 +/* Clock setting register 10, CLOCKOUT M divider value */ +#define AIC31XX_CLKOUTMVAL 0x1A +/* Audio Interface Setting Register 1 */ +#define AIC31XX_IFACE1 0x1B +/* Audio Data Slot Offset Programming */ +#define AIC31XX_DATA_OFFSET 0x1C +/* Audio Interface Setting Register 2 */ +#define AIC31XX_IFACE2 0x1D +/* Clock setting register 11, BCLK N Divider */ +#define AIC31XX_BCLKN 0x1E +/* Audio Interface Setting Register 3, Secondary Audio Interface */ +#define AIC31XX_IFACESEC1 0x1F +/* Audio Interface Setting Register 4 */ +#define AIC31XX_IFACESEC2 0x20 +/* Audio Interface Setting Register 5 */ +#define AIC31XX_IFACESEC3 0x21 +/* I2C Bus Condition */ +#define AIC31XX_I2C 0x22 +/* ADC FLAG */ +#define AIC31XX_ADCFLAG 0x24 +/* DAC Flag Registers */ +#define AIC31XX_DACFLAG1 0x25 +#define AIC31XX_DACFLAG2 0x26 +/* Sticky Interrupt flag (overflow) */ +#define AIC31XX_OFFLAG 0x27 +/* Sticy DAC Interrupt flags */ +#define AIC31XX_INTRDACFLAG 0x2C +/* Sticy ADC Interrupt flags */ +#define AIC31XX_INTRADCFLAG 0x2D +/* DAC Interrupt flags 2 */ +#define AIC31XX_INTRDACFLAG2 0x2E +/* ADC Interrupt flags 2 */ +#define AIC31XX_INTRADCFLAG2 0x2F +/* INT1 interrupt control */ +#define AIC31XX_INT1CTRL 0x30 +/* INT2 interrupt control */ +#define AIC31XX_INT2CTRL 0x31 +/* GPIO1 control */ +#define AIC31XX_GPIO1 0x33 + +#define AIC31XX_DACPRB 0x3C +/* ADC Instruction Set Register */ +#define AIC31XX_ADCPRB 0x3D +/* DAC channel setup register */ +#define AIC31XX_DACSETUP 0x3F +/* DAC Mute and volume control register */ +#define AIC31XX_DACMUTE 0x40 +/* Left DAC channel digital volume control */ +#define AIC31XX_LDACVOL 0x41 +/* Right DAC channel digital volume control */ +#define AIC31XX_RDACVOL 0x42 +/* Headset detection */ +#define AIC31XX_HSDETECT 0x43 +/* ADC Digital Mic */ +#define AIC31XX_ADCSETUP 0x51 +/* ADC Digital Volume Control Fine Adjust */ +#define AIC31XX_ADCFGA 0x52 +/* ADC Digital Volume Control Coarse Adjust */ +#define AIC31XX_ADCVOL 0x53 + + +/* Page 1 Registers */ +/* Headphone drivers */ +#define AIC31XX_HPDRIVER 0x9F +/* Class-D Speakear Amplifier */ +#define AIC31XX_SPKAMP 0xA0 +/* HP Output Drivers POP Removal Settings */ +#define AIC31XX_HPPOP 0xA1 +/* Output Driver PGA Ramp-Down Period Control */ +#define AIC31XX_SPPGARAMP 0xA2 +/* DAC_L and DAC_R Output Mixer Routing */ +#define AIC31XX_DACMIXERROUTE 0xA3 +/* Left Analog Vol to HPL */ +#define AIC31XX_LANALOGHPL 0xA4 +/* Right Analog Vol to HPR */ +#define AIC31XX_RANALOGHPR 0xA5 +/* Left Analog Vol to SPL */ +#define AIC31XX_LANALOGSPL 0xA6 +/* Right Analog Vol to SPR */ +#define AIC31XX_RANALOGSPR 0xA7 +/* HPL Driver */ +#define AIC31XX_HPLGAIN 0xA8 +/* HPR Driver */ +#define AIC31XX_HPRGAIN 0xA9 +/* SPL Driver */ +#define AIC31XX_SPLGAIN 0xAA +/* SPR Driver */ +#define AIC31XX_SPRGAIN 0xAB +/* HP Driver Control */ +#define AIC31XX_HPCONTROL 0xAC +/* MIC Bias Control */ +#define AIC31XX_MICBIAS 0xAE +/* MIC PGA*/ +#define AIC31XX_MICPGA 0xAF +/* Delta-Sigma Mono ADC Channel Fine-Gain Input Selection for P-Terminal */ +#define AIC31XX_MICPGAPI 0xB0 +/* ADC Input Selection for M-Terminal */ +#define AIC31XX_MICPGAMI 0xB1 +/* Input CM Settings */ +#define AIC31XX_MICPGACM 0xB2 + +/* Bits, masks and shifts */ + +/* AIC31XX_CLKMUX */ +#define AIC31XX_PLL_CLKIN_MASK 0x0c +#define AIC31XX_PLL_CLKIN_SHIFT 2 +#define AIC31XX_PLL_CLKIN_MCLK 0 +#define AIC31XX_CODEC_CLKIN_MASK 0x03 +#define AIC31XX_CODEC_CLKIN_SHIFT 0 +#define AIC31XX_CODEC_CLKIN_PLL 3 +#define AIC31XX_CODEC_CLKIN_BCLK 1 + +/* AIC31XX_PLLPR, AIC31XX_NDAC, AIC31XX_MDAC, AIC31XX_NADC, AIC31XX_MADC, + AIC31XX_BCLKN */ +#define AIC31XX_PLL_MASK 0x7f +#define AIC31XX_PM_MASK 0x80 + +/* AIC31XX_IFACE1 */ +#define AIC31XX_WORD_LEN_16BITS 0x00 +#define AIC31XX_WORD_LEN_20BITS 0x01 +#define AIC31XX_WORD_LEN_24BITS 0x02 +#define AIC31XX_WORD_LEN_32BITS 0x03 +#define AIC31XX_IFACE1_DATALEN_MASK 0x30 +#define AIC31XX_IFACE1_DATALEN_SHIFT (4) +#define AIC31XX_IFACE1_DATATYPE_MASK 0xC0 +#define AIC31XX_IFACE1_DATATYPE_SHIFT (6) +#define AIC31XX_I2S_MODE 0x00 +#define AIC31XX_DSP_MODE 0x01 +#define AIC31XX_RIGHT_JUSTIFIED_MODE 0x02 +#define AIC31XX_LEFT_JUSTIFIED_MODE 0x03 +#define AIC31XX_IFACE1_MASTER_MASK 0x0C +#define AIC31XX_BCLK_MASTER 0x08 +#define AIC31XX_WCLK_MASTER 0x04 + +/* AIC31XX_DATA_OFFSET */ +#define AIC31XX_DATA_OFFSET_MASK 0xFF + +/* AIC31XX_IFACE2 */ +#define AIC31XX_BCLKINV_MASK 0x08 +#define AIC31XX_BDIVCLK_MASK 0x03 +#define AIC31XX_DAC2BCLK 0x00 +#define AIC31XX_DACMOD2BCLK 0x01 +#define AIC31XX_ADC2BCLK 0x02 +#define AIC31XX_ADCMOD2BCLK 0x03 + +/* AIC31XX_ADCFLAG */ +#define AIC31XX_ADCPWRSTATUS_MASK 0x40 + +/* AIC31XX_DACFLAG1 */ +#define AIC31XX_LDACPWRSTATUS_MASK 0x80 +#define AIC31XX_RDACPWRSTATUS_MASK 0x08 +#define AIC31XX_HPLDRVPWRSTATUS_MASK 0x20 +#define AIC31XX_HPRDRVPWRSTATUS_MASK 0x02 +#define AIC31XX_SPLDRVPWRSTATUS_MASK 0x10 +#define AIC31XX_SPRDRVPWRSTATUS_MASK 0x01 + +/* AIC31XX_INTRDACFLAG */ +#define AIC31XX_HPSCDETECT_MASK 0x80 +#define AIC31XX_BUTTONPRESS_MASK 0x20 +#define AIC31XX_HSPLUG_MASK 0x10 +#define AIC31XX_LDRCTHRES_MASK 0x08 +#define AIC31XX_RDRCTHRES_MASK 0x04 +#define AIC31XX_DACSINT_MASK 0x02 +#define AIC31XX_DACAINT_MASK 0x01 + +/* AIC31XX_INT1CTRL */ +#define AIC31XX_HSPLUGDET_MASK 0x80 +#define AIC31XX_BUTTONPRESSDET_MASK 0x40 +#define AIC31XX_DRCTHRES_MASK 0x20 +#define AIC31XX_AGCNOISE_MASK 0x10 +#define AIC31XX_OC_MASK 0x08 +#define AIC31XX_ENGINE_MASK 0x04 + +/* AIC31XX_DACSETUP */ +#define AIC31XX_SOFTSTEP_MASK 0x03 + +/* AIC31XX_DACMUTE */ +#define AIC31XX_DACMUTE_MASK 0x0C + +/* AIC31XX_MICBIAS */ +#define AIC31XX_MICBIAS_MASK 0x03 +#define AIC31XX_MICBIAS_SHIFT 0 + +#endif /* _TLV320AIC31XX_H */ -- cgit v1.2.3 From a2d57678ce98534a87de42e55e599cae730d17ca Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 13 Mar 2014 17:37:52 +0200 Subject: ASoC: tlv320aic31xx: Fix unused variable warning from aic31xx_clk_off Fix "warning: unused variable 'aic31xx'" from function 'aic31xx_clk_off'. Signed-off-by: Jyri Sarha Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic31xx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index e60e37b43a1b..bdc0d8bd47b4 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -943,7 +943,6 @@ static void aic31xx_clk_on(struct snd_soc_codec *codec) static void aic31xx_clk_off(struct snd_soc_codec *codec) { - struct aic31xx_priv *aic31xx = snd_soc_codec_get_drvdata(codec); u8 mask = AIC31XX_PM_MASK; u8 off = 0; -- cgit v1.2.3 From bc236fa7301c6ca0ccf5470a964842d1a60e786f Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 13 Mar 2014 18:22:35 +0200 Subject: ASoC: tlv320aic31xx: Remove snd_soc_codec_set_cache_io() call Remove snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP) call and codec->control_data = aic31xx->regmap assignment since that already done by core. Signed-off-by: Jyri Sarha Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic31xx.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index bdc0d8bd47b4..dcdc5751048f 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1049,18 +1049,9 @@ static int aic31xx_codec_probe(struct snd_soc_codec *codec) dev_dbg(aic31xx->dev, "## %s\n", __func__); aic31xx = snd_soc_codec_get_drvdata(codec); - codec->control_data = aic31xx->regmap; aic31xx->codec = codec; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - - if (ret != 0) { - dev_err(codec->dev, "snd_soc_codec_set_cache_io failed %d\n", - ret); - return ret; - } - for (i = 0; i < ARRAY_SIZE(aic31xx->supplies); i++) { aic31xx->disable_nb[i].nb.notifier_call = aic31xx_regulator_event; -- cgit v1.2.3 From 9296f4da3bafa23d8b9abc5cd271a66ea8f90cd2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 13 Mar 2014 17:44:22 +0000 Subject: ASoC: tlv320aic31xx: Staticise non-exported symbols Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic31xx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index dcdc5751048f..d3517a919776 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -129,7 +129,7 @@ static const struct regmap_range_cfg aic31xx_ranges[] = { }, }; -struct regmap_config aic31xx_i2c_regmap = { +static const struct regmap_config aic31xx_i2c_regmap = { .reg_bits = 8, .val_bits = 8, .writeable_reg = aic31xx_writeable, @@ -321,9 +321,9 @@ static const struct snd_kcontrol_new ldac_in_control = static const struct snd_kcontrol_new rdac_in_control = SOC_DAPM_ENUM("DAC Right Input", rdac_in_enum); -int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg, - unsigned int mask, unsigned int wbits, int sleep, - int count) +static int aic31xx_wait_bits(struct aic31xx_priv *aic31xx, unsigned int reg, + unsigned int mask, unsigned int wbits, int sleep, + int count) { unsigned int bits; int counter = count; @@ -1177,7 +1177,7 @@ static void aic31xx_pdata_from_of(struct aic31xx_priv *aic31xx) } #endif /* CONFIG_OF */ -void aic31xx_device_init(struct aic31xx_priv *aic31xx) +static void aic31xx_device_init(struct aic31xx_priv *aic31xx) { int ret, i; -- cgit v1.2.3 From 7f0af4ae86110c46b43fb57f2e0002aa81ca6a67 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:32 +0100 Subject: ASoC: omap-abe-twl6040: Register machine level DMIC DAPM routes with the card Machine level DAPM widgets and routes should be registered in the card's DAPM context, rather than in the CODEC's context. Signed-off-by: Lars-Peter Clausen Acked-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-abe-twl6040.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index ebb13906b3a0..024dafc3e298 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -203,8 +203,7 @@ static const struct snd_soc_dapm_route dmic_audio_map[] = { static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_dapm_context *dapm = &rtd->card->dapm; return snd_soc_dapm_add_routes(dapm, dmic_audio_map, ARRAY_SIZE(dmic_audio_map)); -- cgit v1.2.3 From d343a660d3c94423759382869b7f90c8657ebbf1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:35 +0100 Subject: ASoC: davinci-evm: Register machine level DAPM elements with the card Machine level DAPM widgets and routes should be registered in the card's DAPM context, rather than in the CODEC's context. While we are at it also drop the snd_soc_dapm_enable_pin() calls, since pins are enabled by default and also turn the snd_soc_dapm_disable_pin() calls into snd_soc_dapm_nc_pin() calls for unconnected pins. Signed-off-by: Lars-Peter Clausen Acked-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-evm.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 621e9a997d4c..cab98a580053 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -123,35 +123,29 @@ static const struct snd_soc_dapm_route audio_map[] = { /* Logic for a aic3x as connected on a davinci-evm */ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_card *card = rtd->card; struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; struct device_node *np = codec->card->dev->of_node; int ret; /* Add davinci-evm specific widgets */ - snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, + snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets, ARRAY_SIZE(aic3x_dapm_widgets)); if (np) { - ret = snd_soc_of_parse_audio_routing(codec->card, - "ti,audio-routing"); + ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing"); if (ret) return ret; } else { /* Set up davinci-evm specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + snd_soc_dapm_add_routes(&card->dapm, audio_map, + ARRAY_SIZE(audio_map)); } /* not connected */ - snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); - snd_soc_dapm_disable_pin(dapm, "HPLCOM"); - snd_soc_dapm_disable_pin(dapm, "HPRCOM"); - - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Line Out"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Line In"); + snd_soc_dapm_nc_pin(&codec->dapm, "MONO_LOUT"); + snd_soc_dapm_nc_pin(&codec->dapm, "HPLCOM"); + snd_soc_dapm_nc_pin(&codec->dapm, "HPRCOM"); return 0; } -- cgit v1.2.3 From e585ca342dbbfe7102985d9ed4eae3f9e1d77ced Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 14 Mar 2014 09:33:36 +0100 Subject: ASoC: max98090: Remove unused control_data field The driver assigns a value to the control_data field of the driver's state struct, but never reads it again. Which means it is unused and can be removed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/max98090.c | 1 - sound/soc/codecs/max98090.h | 1 - 2 files changed, 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index c7b9e901bdac..361862d4fa65 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2350,7 +2350,6 @@ static int max98090_i2c_probe(struct i2c_client *i2c, max98090->devtype = id->driver_data; i2c_set_clientdata(i2c, max98090); - max98090->control_data = i2c; max98090->pdata = i2c->dev.platform_data; max98090->irq = i2c->irq; diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h index 7e103f249053..1a4e2334a7b2 100644 --- a/sound/soc/codecs/max98090.h +++ b/sound/soc/codecs/max98090.h @@ -1523,7 +1523,6 @@ struct max98090_priv { struct regmap *regmap; struct snd_soc_codec *codec; enum max98090_type devtype; - void *control_data; struct max98090_pdata *pdata; unsigned int sysclk; unsigned int bclk; -- cgit v1.2.3 From c7a507eea1db1430476289f525f9c853d5d485e8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 13 Mar 2014 17:56:25 -0700 Subject: ASoC: fsi: fixup SND_SOC_DAIFMT_CBx_CFx flags SND_SOC_DAIFMT_CBx_CFx means "codec" side master/slave mode. Then, FSI will be master mode if it was SND_SOC_DAIFMT_CBS_CFS. This patch fixup platform settings too. Then, it tidyups SND_SOC_DAIFMT_INV settings. Acked-by: Simon Horman Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- arch/arm/mach-shmobile/board-armadillo800eva.c | 4 +--- arch/arm/mach-shmobile/board-kzm9g.c | 4 +--- arch/arm/mach-shmobile/board-mackerel.c | 6 ++---- arch/sh/boards/mach-ecovec24/setup.c | 4 +--- arch/sh/boards/mach-se/7724/setup.c | 4 +--- sound/soc/sh/fsi.c | 2 +- 6 files changed, 7 insertions(+), 17 deletions(-) (limited to 'sound/soc') diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 93533e2710a8..9323854242ca 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -988,14 +988,12 @@ static struct asoc_simple_card_info fsi_wm8978_info = { .card = "FSI2A-WM8978", .codec = "wm8978.0-001a", .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_I2S, + .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "wm8978-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF, .sysclk = 12288000, }, }; diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index bc40b853ffd3..03dc3ac84502 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -589,14 +589,12 @@ static struct asoc_simple_card_info fsi2_ak4648_info = { .card = "FSI2A-AK4648", .codec = "ak4642-codec.0-0012", .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_LEFT_J, + .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS, }, .codec_dai = { .name = "ak4642-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, .sysclk = 11289600, }, }; diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 3aba0372f630..8c4332182b42 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -509,9 +509,9 @@ static struct asoc_simple_card_info fsi2_hdmi_info = { .card = "FSI2B-HDMI", .codec = "sh-mobile-hdmi", .platform = "sh_fsi2", + .fmt = SND_SOC_DAIFMT_CBS_CFS, .cpu_dai = { .name = "fsib-dai", - .fmt = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "sh_mobile_hdmi-hifi", @@ -905,14 +905,12 @@ static struct asoc_simple_card_info fsi2_ak4643_info = { .card = "FSI2A-AK4643", .codec = "ak4642-codec.0-0013", .platform = "sh_fsi2", - .daifmt = SND_SOC_DAIFMT_LEFT_J, + .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS, }, .codec_dai = { .name = "ak4642-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, .sysclk = 11289600, }, }; diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 5bc3a15465c7..85d5255d259f 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -861,14 +861,12 @@ static struct asoc_simple_card_info fsi_da7210_info = { .card = "FSIB-DA7210", .codec = "da7210.0-001a", .platform = "sh_fsi.0", - .daifmt = SND_SOC_DAIFMT_I2S, + .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsib-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "da7210-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, }, }; diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 21e4230659a5..1162bc6945a3 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -304,14 +304,12 @@ static struct asoc_simple_card_info fsi_ak4642_info = { .card = "FSIA-AK4642", .codec = "ak4642-codec.0-0012", .platform = "sh_fsi.0", - .daifmt = SND_SOC_DAIFMT_LEFT_J, + .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, .cpu_dai = { .name = "fsia-dai", - .fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_IB_NF, }, .codec_dai = { .name = "ak4642-hifi", - .fmt = SND_SOC_DAIFMT_CBM_CFM, .sysclk = 11289600, }, }; diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 1967f44e7cd4..710a079a7377 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1711,9 +1711,9 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - fsi->clk_master = 1; break; case SND_SOC_DAIFMT_CBS_CFS: + fsi->clk_master = 1; /* codec is slave, cpu is master */ break; default: return -EINVAL; -- cgit v1.2.3 From e1508289404ab6ca28e0dc931612600f0441c417 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 13 Mar 2014 17:56:43 -0700 Subject: ASoC: rcar: fixup SND_SOC_DAIFMT_CBx_CFx flags SND_SOC_DAIFMT_CBx_CFx means "codec" side master/slave mode. Then, rcar will be master mode if it was SND_SOC_DAIFMT_CBS_CFS. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 743de5e3b1e1..3a4fe9d0d4f2 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -486,10 +486,10 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - rdai->clk_master = 1; + rdai->clk_master = 0; break; case SND_SOC_DAIFMT_CBS_CFS: - rdai->clk_master = 0; + rdai->clk_master = 1; /* codec is slave, cpu is master */ break; default: return -EINVAL; -- cgit v1.2.3 From e512e001dafa54e5ac7244416e340750a4356b41 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 11 Mar 2014 10:03:40 +0100 Subject: ASoC: simple-card: Fix the reference count of device nodes The reference count of some device nodes is not correctly reset at end of card probe. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 50 ++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 5dd47691ba41..dcf37fb69b35 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -105,12 +105,12 @@ asoc_simple_card_sub_parse_of(struct device_node *np, /* get dai->name */ ret = snd_soc_of_get_dai_name(np, name); if (ret < 0) - goto parse_error; + return ret; /* parse TDM slot */ ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); if (ret) - goto parse_error; + return ret; /* * bitclock-inversion, frame-inversion @@ -130,7 +130,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, clk = of_clk_get(np, 0); if (IS_ERR(clk)) { ret = PTR_ERR(clk); - goto parse_error; + return ret; } dai->sysclk = clk_get_rate(clk); @@ -144,12 +144,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, dai->sysclk = clk_get_rate(clk); } - ret = 0; - -parse_error: - of_node_put(node); - - return ret; + return 0; } static int asoc_simple_card_parse_of(struct device_node *node, @@ -187,22 +182,26 @@ static int asoc_simple_card_parse_of(struct device_node *node, /* CPU sub-node */ ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,cpu"); - if (np) + if (np) { ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, &priv->cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_dai_name); + of_node_put(np); + } if (ret < 0) return ret; /* CODEC sub-node */ ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,codec"); - if (np) + if (np) { ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, &priv->codec_dai, &dai_link->codec_of_node, &dai_link->codec_dai_name); + of_node_put(np); + } if (ret < 0) return ret; @@ -248,6 +247,27 @@ static int asoc_simple_card_parse_of(struct device_node *node, return 0; } +/* update the reference count of the devices nodes at end of probe */ +static int asoc_simple_card_unref(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct snd_soc_dai_link *dai_link; + struct device_node *np; + int num_links; + + for (num_links = 0, dai_link = card->dai_link; + num_links < card->num_links; + num_links++, dai_link++) { + np = (struct device_node *) dai_link->cpu_of_node; + if (np) + of_node_put(np); + np = (struct device_node *) dai_link->codec_of_node; + if (np) + of_node_put(np); + } + return 0; +} + static int asoc_simple_card_probe(struct platform_device *pdev) { struct simple_card_data *priv; @@ -275,7 +295,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); - return ret; + goto err; } } else { struct asoc_simple_card_info *cinfo; @@ -318,7 +338,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(&priv->snd_card, priv); - return devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); + ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); + +err: + asoc_simple_card_unref(pdev); + return ret; } static const struct of_device_id asoc_simple_of_match[] = { -- cgit v1.2.3 From fd218aa3e5d4ee522cbfe88ad4dd83eb891096fb Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 17 Mar 2014 09:31:31 +0200 Subject: ASoC: tlv320aic31xx: Turn power off only once. Regulator code keep count of enables and disables. Double disable causes an ugly warning. Signed-off-by: Jyri Sarha Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic31xx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index d3517a919776..1f243c2c98fd 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1020,7 +1020,8 @@ static int aic31xx_set_bias_level(struct snd_soc_codec *codec, } break; case SND_SOC_BIAS_OFF: - aic31xx_power_off(codec); + if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) + aic31xx_power_off(codec); break; } codec->dapm.bias_level = level; -- cgit v1.2.3 From 58726f58a6432495bd71d1fc7c9454cbc85f5a5c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Mar 2014 16:42:45 +0200 Subject: ASoC: davinci: Add edma dmaengine platform driver Platform driver glue for SoC using eDMA3 to use dmaengine PCM. The maximum number of periods need to be limited to 19 since the edma dmaengine driver limits the paRAM slot use for audio at in cyclic mode. Signed-off-by: Peter Ujfalusi Reviewed-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/davinci/edma-pcm.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/davinci/edma-pcm.h | 25 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 sound/soc/davinci/edma-pcm.c create mode 100644 sound/soc/davinci/edma-pcm.h (limited to 'sound/soc') diff --git a/sound/soc/davinci/edma-pcm.c b/sound/soc/davinci/edma-pcm.c new file mode 100644 index 000000000000..d38afb1c61ae --- /dev/null +++ b/sound/soc/davinci/edma-pcm.c @@ -0,0 +1,57 @@ +/* + * edma-pcm.c - eDMA PCM driver using dmaengine for AM3xxx, AM4xxx + * + * Copyright (C) 2014 Texas Instruments, Inc. + * + * Author: Peter Ujfalusi + * + * Based on: sound/soc/tegra/tegra_pcm.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +static const struct snd_pcm_hardware edma_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_INTERLEAVED, + .buffer_bytes_max = 128 * 1024, + .period_bytes_min = 32, + .period_bytes_max = 64 * 1024, + .periods_min = 2, + .periods_max = 19, /* Limit by edma dmaengine driver */ +}; + +static const struct snd_dmaengine_pcm_config edma_dmaengine_pcm_config = { + .pcm_hardware = &edma_pcm_hardware, + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, + .compat_filter_fn = edma_filter_fn, + .prealloc_buffer_size = 128 * 1024, +}; + +int edma_pcm_platform_register(struct device *dev) +{ + return devm_snd_dmaengine_pcm_register(dev, &edma_dmaengine_pcm_config, + SND_DMAENGINE_PCM_FLAG_COMPAT); +} +EXPORT_SYMBOL_GPL(edma_pcm_platform_register); + +MODULE_AUTHOR("Peter Ujfalusi "); +MODULE_DESCRIPTION("eDMA PCM ASoC platform driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/davinci/edma-pcm.h b/sound/soc/davinci/edma-pcm.h new file mode 100644 index 000000000000..894c378c0f74 --- /dev/null +++ b/sound/soc/davinci/edma-pcm.h @@ -0,0 +1,25 @@ +/* + * edma-pcm.h - eDMA PCM driver using dmaengine for AM3xxx, AM4xxx + * + * Copyright (C) 2014 Texas Instruments, Inc. + * + * Author: Peter Ujfalusi + * + * Based on: sound/soc/tegra/tegra_pcm.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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 __EDMA_PCM_H__ +#define __EDMA_PCM_H__ + +int edma_pcm_platform_register(struct device *dev); + +#endif /* __EDMA_PCM_H__ */ -- cgit v1.2.3 From 8de131f2e6de83f23059527fc4732c1efe27f93d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 14 Mar 2014 16:42:46 +0200 Subject: ASoC: davinci-mcasp: Provide correct filter_data for dmaengine for non-DT boot When we boot with non-DT mode the damengine will need the channel number and a filter function in order to get the channel. The filter_data is filled in the DAI driver while the filter_function will be provided by the edma-pcm driver. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b0ae0677f023..a01ae97c90aa 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -1026,6 +1026,7 @@ nodata: static int davinci_mcasp_probe(struct platform_device *pdev) { struct davinci_pcm_dma_params *dma_params; + struct snd_dmaengine_dai_dma_data *dma_data; struct resource *mem, *ioarea, *res, *dat; struct davinci_mcasp_pdata *pdata; struct davinci_mcasp *mcasp; @@ -1095,6 +1096,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) mcasp->dat_port = true; dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; + dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; dma_params->asp_chan_q = pdata->asp_chan_q; dma_params->ram_chan_q = pdata->ram_chan_q; dma_params->sram_pool = pdata->sram_pool; @@ -1105,7 +1107,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dma_params->dma_addr = mem->start + pdata->tx_dma_offset; /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_params->dma_addr; + dma_data->addr = dma_params->dma_addr; res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (res) @@ -1113,7 +1115,14 @@ static int davinci_mcasp_probe(struct platform_device *pdev) else dma_params->channel = pdata->tx_dma_channel; + /* dmaengine filter data for DT and non-DT boot */ + if (pdev->dev.of_node) + dma_data->filter_data = "tx"; + else + dma_data->filter_data = &dma_params->channel; + dma_params = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE]; + dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; dma_params->asp_chan_q = pdata->asp_chan_q; dma_params->ram_chan_q = pdata->ram_chan_q; dma_params->sram_pool = pdata->sram_pool; @@ -1124,7 +1133,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dma_params->dma_addr = mem->start + pdata->rx_dma_offset; /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_params->dma_addr; + dma_data->addr = dma_params->dma_addr; if (mcasp->version < MCASP_VERSION_3) { mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; @@ -1140,9 +1149,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev) else dma_params->channel = pdata->rx_dma_channel; - /* Unconditional dmaengine stuff */ - mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = "tx"; - mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = "rx"; + /* dmaengine filter data for DT and non-DT boot */ + if (pdev->dev.of_node) + dma_data->filter_data = "rx"; + else + dma_data->filter_data = &dma_params->channel; dev_set_drvdata(&pdev->dev, mcasp); -- cgit v1.2.3 From c56c4d74c6f96d0ff605d8948e127099cf5e6681 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 15 Mar 2014 11:32:42 +0100 Subject: ASoC: simple-card: Simplify code The global DAI format is used only in the function asoc_simple_card_parse_of(). So, move it from the private data to the stack. Signed-off-by: Jean-Francois Moine Reviewed-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index dcf37fb69b35..ca7e63ef858a 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -20,7 +20,6 @@ struct simple_card_data { struct snd_soc_card snd_card; - unsigned int daifmt; struct asoc_simple_dai cpu_dai; struct asoc_simple_dai codec_dai; struct snd_soc_dai_link snd_link; @@ -154,13 +153,14 @@ static int asoc_simple_card_parse_of(struct device_node *node, struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; struct device_node *np; char *name; + unsigned int daifmt; int ret; /* parsing the card name from DT */ snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); /* get CPU/CODEC common format via simple-audio-card,format */ - priv->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & + daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); /* off-codec widgets */ @@ -183,7 +183,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,cpu"); if (np) { - ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, + ret = asoc_simple_card_sub_parse_of(np, daifmt, &priv->cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_dai_name); @@ -196,7 +196,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, ret = -EINVAL; np = of_get_child_by_name(node, "simple-audio-card,codec"); if (np) { - ret = asoc_simple_card_sub_parse_of(np, priv->daifmt, + ret = asoc_simple_card_sub_parse_of(np, daifmt, &priv->codec_dai, &dai_link->codec_of_node, &dai_link->codec_dai_name); @@ -223,7 +223,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, dai_link->platform_of_node = dai_link->cpu_of_node; dev_dbg(dev, "card-name : %s\n", name); - dev_dbg(dev, "platform : %04x\n", priv->daifmt); + dev_dbg(dev, "platform : %04x\n", daifmt); dev_dbg(dev, "cpu : %s / %04x / %d\n", dai_link->cpu_dai_name, priv->cpu_dai.fmt, -- cgit v1.2.3 From bfe723f6eae285e399615d99f297d1646a6253fe Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 14 Mar 2014 09:26:11 +0100 Subject: ASoC: sirf-audio-codec: Remove snd_soc_codec_set_cache_io() call There was a overlap between the snd_soc_codec_set_cache_io() cleanup and the addition of the sirf-audio-codec resulting in the sirf-audio-codec driver still using the old signature of snd_soc_codec_set_cache_io(), which will cause a compile error. Since the core is able to automatically setup IO for this driver we can just remove both the snd_soc_set_cache_io() call and the control_data assignment. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/sirf-audio-codec.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c index 90e3a228bae4..58e7c1f23771 100644 --- a/sound/soc/codecs/sirf-audio-codec.c +++ b/sound/soc/codecs/sirf-audio-codec.c @@ -337,18 +337,9 @@ struct snd_soc_dai_driver sirf_audio_codec_dai = { static int sirf_audio_codec_probe(struct snd_soc_codec *codec) { - int ret; struct snd_soc_dapm_context *dapm = &codec->dapm; - struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); pm_runtime_enable(codec->dev); - codec->control_data = sirf_audio_codec->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } if (of_device_is_compatible(codec->dev->of_node, "sirf,prima2-audio-codec")) { snd_soc_dapm_new_controls(dapm, -- cgit v1.2.3 From dac7e40404a6b1e7442c01ef4c2e7e149b9627e5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 16 Mar 2014 23:06:25 +0800 Subject: ASoC: tlv320aic31xx: Don't call kfree for memory allocated by devm_kzalloc The kfree call is not necessary, but we need to call snd_soc_unregister_codec() in remove(). Signed-off-by: Axel Lin Acked-by: Jyri Sarha Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic31xx.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 1f243c2c98fd..e463ae7fe1f4 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1229,7 +1229,6 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, return -ENOMEM; aic31xx->regmap = devm_regmap_init_i2c(i2c, regmap_config); - if (IS_ERR(aic31xx->regmap)) { ret = PTR_ERR(aic31xx->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", @@ -1242,18 +1241,14 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c, aic31xx_device_init(aic31xx); - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, + return snd_soc_register_codec(&i2c->dev, &soc_codec_driver_aic31xx, aic31xx_dai_driver, ARRAY_SIZE(aic31xx_dai_driver)); - - return ret; } static int aic31xx_i2c_remove(struct i2c_client *i2c) { - struct aic31xx_priv *aic31xx = dev_get_drvdata(&i2c->dev); - - kfree(aic31xx); + snd_soc_unregister_codec(&i2c->dev); return 0; } @@ -1275,7 +1270,7 @@ static struct i2c_driver aic31xx_i2c_driver = { .of_match_table = of_match_ptr(tlv320aic31xx_of_match), }, .probe = aic31xx_i2c_probe, - .remove = (aic31xx_i2c_remove), + .remove = aic31xx_i2c_remove, .id_table = aic31xx_i2c_id, }; -- cgit v1.2.3 From ab64246cf8c31f70a390dcabd134097c3aec45ab Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 13 Mar 2014 21:24:54 +0100 Subject: ASoC: codecs: Replace instances of rtd->codec with dai->codec With CODEC to CODEC links rtd->codec does not necessarily point to the driver's CODEC. CODEC drivers should always use dai->codec and never even look at the PCM runtime. Signed-off-by: Lars-Peter Clausen Acked-by: Charles Keepax Acked-by: Jyri Sarha Signed-off-by: Mark Brown --- sound/soc/codecs/isabelle.c | 3 +-- sound/soc/codecs/mc13783.c | 6 ++---- sound/soc/codecs/rt5640.c | 3 +-- sound/soc/codecs/sta529.c | 3 +-- sound/soc/codecs/tlv320aic31xx.c | 5 ++--- sound/soc/codecs/uda134x.c | 3 +-- sound/soc/codecs/uda1380.c | 3 +-- sound/soc/codecs/wm8580.c | 3 +-- 8 files changed, 10 insertions(+), 19 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 5839048ec467..7c8ba02a6d1b 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -910,8 +910,7 @@ static int isabelle_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; u16 aif = 0; unsigned int fs_val = 0; diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 582c2bbd42cb..bebba7fb8819 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -106,8 +106,7 @@ static int mc13783_pcm_hw_params_dac(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; unsigned int rate = params_rate(params); int i; @@ -126,8 +125,7 @@ static int mc13783_pcm_hw_params_codec(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; unsigned int rate = params_rate(params); unsigned int val; diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index a3fb41179636..7877a5e14c54 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1601,8 +1601,7 @@ static int get_clk_info(int sclk, int rate) static int rt5640_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); unsigned int val_len = 0, val_clk, mask_clk; int dai_sel, pre_div, bclk_ms, frame_size; diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 40c07be9b581..fa4b050fe6e6 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -193,8 +193,7 @@ static int sta529_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; int pdata, play_freq_val, record_freq_val; int bclk_to_fs_ratio; diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index e463ae7fe1f4..fa158cfe9b32 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -753,10 +753,9 @@ static int aic31xx_setup_pll(struct snd_soc_codec *codec, static int aic31xx_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, - struct snd_soc_dai *tmp) + struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; u8 data = 0; dev_dbg(codec->dev, "## %s: format %d width %d rate %d\n", diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index c94d4c1e3dac..edf27acc1d77 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -203,8 +203,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); u8 hw_params; diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 726df6d43c2b..dc47f6f5cd83 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -564,8 +564,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); /* shut down WSPLL power if running from this clock */ diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 318989acbbe5..49c2869b681c 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -504,8 +504,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); u16 paifa = 0; u16 paifb = 0; -- cgit v1.2.3 From cece5656901f09db13fbb569ff04f627ec2e0ab6 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 12 Feb 2014 18:20:57 +0100 Subject: ASoC: add S/PDIF support to Armada 370 DB ASoC driver The Armada 370 DB board not only has analog audio input/output, but also S/PDIF input/output. This commit adds support for S/PDIF in the ASoC machine driver of the Armada 370 DB platform, and adjusts the Device Tree bindings documentation accordingly. Signed-off-by: Thomas Petazzoni Signed-off-by: Mark Brown --- .../bindings/sound/armada-370db-audio.txt | 9 ++++--- sound/soc/kirkwood/Kconfig | 1 + sound/soc/kirkwood/armada-370-db.c | 28 ++++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/armada-370db-audio.txt b/Documentation/devicetree/bindings/sound/armada-370db-audio.txt index 3893b4d15a20..bf984d238620 100644 --- a/Documentation/devicetree/bindings/sound/armada-370db-audio.txt +++ b/Documentation/devicetree/bindings/sound/armada-370db-audio.txt @@ -11,14 +11,17 @@ Mandatory properties: * marvell,audio-controller: a phandle that points to the audio controller of the Armada 370 SoC. - * marvell,audio-codec: a phandle that points to the analog audio - codec connected to the Armada 370 SoC. + * marvell,audio-codec: a set of three phandles that points to: + + 1/ the analog audio codec connected to the Armada 370 SoC + 2/ the S/PDIF transceiver + 3/ the S/PDIF receiver Example: sound { compatible = "marvell,a370db-audio"; marvell,audio-controller = <&audio_controller>; - marvell,audio-codec = <&audio_codec>; + marvell,audio-codec = <&audio_codec &spdif_out &spdif_in>; status = "okay"; }; diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 2dc3ecf34801..49f8437665de 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig @@ -10,6 +10,7 @@ config SND_KIRKWOOD_SOC_ARMADA370_DB tristate "SoC Audio support for Armada 370 DB" depends on SND_KIRKWOOD_SOC && (ARCH_MVEBU || COMPILE_TEST) && I2C select SND_SOC_CS42L51 + select SND_SOC_SPDIF help Say Y if you want to add support for SoC audio on the Armada 370 Development Board. diff --git a/sound/soc/kirkwood/armada-370-db.c b/sound/soc/kirkwood/armada-370-db.c index 977639b3ffde..c44333849259 100644 --- a/sound/soc/kirkwood/armada-370-db.c +++ b/sound/soc/kirkwood/armada-370-db.c @@ -67,6 +67,20 @@ static struct snd_soc_dai_link a370db_dai[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, .ops = &a370db_ops, }, +{ + .name = "S/PDIF out", + .stream_name = "spdif-out", + .cpu_dai_name = "spdif", + .codec_dai_name = "dit-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, +}, +{ + .name = "S/PDIF in", + .stream_name = "spdif-in", + .cpu_dai_name = "spdif", + .codec_dai_name = "dir-hifi", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, +}, }; static struct snd_soc_card a370db = { @@ -95,6 +109,20 @@ static int a370db_probe(struct platform_device *pdev) of_parse_phandle(pdev->dev.of_node, "marvell,audio-codec", 0); + a370db_dai[1].cpu_of_node = a370db_dai[0].cpu_of_node; + a370db_dai[1].platform_of_node = a370db_dai[0].cpu_of_node; + + a370db_dai[1].codec_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-codec", 1); + + a370db_dai[2].cpu_of_node = a370db_dai[0].cpu_of_node; + a370db_dai[2].platform_of_node = a370db_dai[0].cpu_of_node; + + a370db_dai[2].codec_of_node = + of_parse_phandle(pdev->dev.of_node, + "marvell,audio-codec", 2); + return devm_snd_soc_register_card(card->dev, card); } -- cgit v1.2.3 From 1555b652970e541fa1cb80c61ffc696bbfb92bb7 Mon Sep 17 00:00:00 2001 From: Brian Austin Date: Tue, 18 Mar 2014 13:56:21 -0500 Subject: ASoC: cs42l73: Fix mask bits for SOC_VALUE_ENUM_SINGLE The mask bits values were wrong for the SOC_VALUE_ENUM_SINGLE for the mono mix controls. Reported-by: Takashi Iwai Signed-off-by: Brian Austin Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/cs42l73.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 549d5d6a3fef..7b95f7cbc515 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -319,7 +319,7 @@ static const char * const cs42l73_mono_mix_texts[] = { static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 }; static const struct soc_enum spk_asp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1, + SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 3, ARRAY_SIZE(cs42l73_mono_mix_texts), cs42l73_mono_mix_texts, cs42l73_mono_mix_values); @@ -337,7 +337,7 @@ static const struct snd_kcontrol_new spk_xsp_mixer = SOC_DAPM_ENUM("Route", spk_xsp_enum); static const struct soc_enum esl_asp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5, + SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 3, ARRAY_SIZE(cs42l73_mono_mix_texts), cs42l73_mono_mix_texts, cs42l73_mono_mix_values); @@ -346,7 +346,7 @@ static const struct snd_kcontrol_new esl_asp_mixer = SOC_DAPM_ENUM("Route", esl_asp_enum); static const struct soc_enum esl_xsp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7, + SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 3, ARRAY_SIZE(cs42l73_mono_mix_texts), cs42l73_mono_mix_texts, cs42l73_mono_mix_values); -- cgit v1.2.3 From d31a33dd7792c7d6c11fda226a3b9e4fb7f86f95 Mon Sep 17 00:00:00 2001 From: Brian Austin Date: Tue, 18 Mar 2014 14:01:47 -0500 Subject: ASoC: cs42l52: Fix mask bits for SOC_VALUE_ENUM_SINGLE The mask bits values were wrong for the SOC_VALUE_ENUM_SINGLE for the PCM/ADC Swap controls Reported-by: Takashi Iwai Signed-off-by: Brian Austin Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/cs42l52.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 0bac6d5a4ac8..1102ced9b20e 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -347,7 +347,7 @@ static const char * const right_swap_text[] = { static const unsigned int swap_values[] = { 0, 1, 3 }; static const struct soc_enum adca_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 3, ARRAY_SIZE(left_swap_text), left_swap_text, swap_values); @@ -356,7 +356,7 @@ static const struct snd_kcontrol_new adca_mixer = SOC_DAPM_ENUM("Route", adca_swap_enum); static const struct soc_enum pcma_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 3, ARRAY_SIZE(left_swap_text), left_swap_text, swap_values); @@ -365,7 +365,7 @@ static const struct snd_kcontrol_new pcma_mixer = SOC_DAPM_ENUM("Route", pcma_swap_enum); static const struct soc_enum adcb_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 3, ARRAY_SIZE(right_swap_text), right_swap_text, swap_values); @@ -374,7 +374,7 @@ static const struct snd_kcontrol_new adcb_mixer = SOC_DAPM_ENUM("Route", adcb_swap_enum); static const struct soc_enum pcmb_swap_enum = - SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 1, + SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 3, ARRAY_SIZE(right_swap_text), right_swap_text, swap_values); -- cgit v1.2.3 From 46c39cae292fd691f32e573e6c2c854e36614c93 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 12 Mar 2014 11:02:11 +0800 Subject: ASoC: simple-card: overwrite cpu_dai->fmt with codec_dai->fmt The current simple-card driver separates the daimft for cpu_dai and codec_dai. So we might get different values for them (0x4003 and 0x1003 for example): asoc-simple-card sound-cs42888.12: cpu : 2024000.esai / 4003 / 132000000 asoc-simple-card sound-cs42888.12: codec : cs42888 / 1003 / 24576000 asoc-simple-card sound-cs42888.12: cs42888 <-> 2024000.esai mapping ok This is not allowed at all as we need to keep the DAIFMT settings identical for both the ends of the link. Thus this patch fixes it by overwriting the cpu_dai->fmt with codec_dai->fmt since we defined the DAIFMT_MASTER basing on CODEC at the first place while the other bits are same. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/simple-card.txt | 6 ++++++ sound/soc/generic/simple-card.c | 20 ++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index b30c222f9cd3..881914b139ca 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -43,6 +43,12 @@ Optional CPU/CODEC subnodes properties: clock node (= common clock), or "system-clock-frequency" (if system doens't support common clock) +Note: + * For 'format', 'frame-master', 'bitclock-master', 'bitclock-inversion' and + 'frame-inversion', the simple card will use the settings of CODEC for both + CPU and CODEC sides as we need to keep the settings identical for both ends + of the link. + Example: sound { diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index ca7e63ef858a..2ee8ed56bcf1 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -151,6 +151,8 @@ static int asoc_simple_card_parse_of(struct device_node *node, struct device *dev) { struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; + struct asoc_simple_dai *codec_dai = &priv->codec_dai; + struct asoc_simple_dai *cpu_dai = &priv->cpu_dai; struct device_node *np; char *name; unsigned int daifmt; @@ -184,7 +186,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, np = of_get_child_by_name(node, "simple-audio-card,cpu"); if (np) { ret = asoc_simple_card_sub_parse_of(np, daifmt, - &priv->cpu_dai, + cpu_dai, &dai_link->cpu_of_node, &dai_link->cpu_dai_name); of_node_put(np); @@ -197,7 +199,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, np = of_get_child_by_name(node, "simple-audio-card,codec"); if (np) { ret = asoc_simple_card_sub_parse_of(np, daifmt, - &priv->codec_dai, + codec_dai, &dai_link->codec_of_node, &dai_link->codec_dai_name); of_node_put(np); @@ -205,6 +207,12 @@ static int asoc_simple_card_parse_of(struct device_node *node, if (ret < 0) return ret; + /* + * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC + * while the other bits should be identical unless buggy SW/HW design. + */ + cpu_dai->fmt = codec_dai->fmt; + if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) return -EINVAL; @@ -226,12 +234,12 @@ static int asoc_simple_card_parse_of(struct device_node *node, dev_dbg(dev, "platform : %04x\n", daifmt); dev_dbg(dev, "cpu : %s / %04x / %d\n", dai_link->cpu_dai_name, - priv->cpu_dai.fmt, - priv->cpu_dai.sysclk); + cpu_dai->fmt, + cpu_dai->sysclk); dev_dbg(dev, "codec : %s / %04x / %d\n", dai_link->codec_dai_name, - priv->codec_dai.fmt, - priv->codec_dai.sysclk); + codec_dai->fmt, + codec_dai->sysclk); /* * soc_bind_dai_link() will check cpu name -- cgit v1.2.3 From 657254714ad2ba69b73fcb02f0b1db378b1f220e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 20 Feb 2014 09:08:43 +0900 Subject: ASoC: io: Remove support for ASoC cache in conjunction with regmap Since all regmap CODECs should be (and are) using the more advance regmap cache infrastructure remove the code which supports that and just proxy I/O straight through to regmap. Signed-off-by: Mark Brown --- sound/soc/soc-io.c | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c index 8aa086996866..260efc8466fc 100644 --- a/sound/soc/soc-io.c +++ b/sound/soc/soc-io.c @@ -23,21 +23,6 @@ static int hw_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { - int ret; - - if (!snd_soc_codec_volatile_register(codec, reg) && - reg < codec->driver->reg_cache_size && - !codec->cache_bypass) { - ret = snd_soc_cache_write(codec, reg, value); - if (ret < 0) - return -1; - } - - if (codec->cache_only) { - codec->cache_sync = 1; - return 0; - } - return regmap_write(codec->control_data, reg, value); } @@ -46,23 +31,11 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg) int ret; unsigned int val; - if (reg >= codec->driver->reg_cache_size || - snd_soc_codec_volatile_register(codec, reg) || - codec->cache_bypass) { - if (codec->cache_only) - return -1; - - ret = regmap_read(codec->control_data, reg, &val); - if (ret == 0) - return val; - else - return -1; - } - - ret = snd_soc_cache_read(codec, reg, &val); - if (ret < 0) + ret = regmap_read(codec->control_data, reg, &val); + if (ret == 0) + return val; + else return -1; - return val; } /** -- cgit v1.2.3 From 7272e051157ccd5871b5d939548d0ba5a94a2965 Mon Sep 17 00:00:00 2001 From: Brian Austin Date: Wed, 19 Mar 2014 10:40:02 -0500 Subject: ASoC: cs42l51: Fix SOC_DOUBLE_R_SX_TLV shift values for ADC, PCM, and Analog kcontrols The shift values for the ADC,PCM, and Analog kcontrols were wrong causing wrong values for the SOC_DOUBLE_R_SX_TLV macros Fixed the TLV for aout_tlv to show -102dB correctly Fixes: 1d99f2436d (ASoC: core: Rework SOC_DOUBLE_R_SX_TLV add SOC_SINGLE_SX_TLV) Reported-by: Thomas Petazzoni Signed-off-by: Brian Austin Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/cs42l51.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 6e9ea8379a91..7a272fa90b39 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -124,9 +124,8 @@ static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol, static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0); static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0); -/* This is a lie. after -102 db, it stays at -102 */ -/* maybe a range would be better */ -static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0); + +static const DECLARE_TLV_DB_SCALE(aout_tlv, -10200, 50, 0); static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0); static const char *chan_mix[] = { @@ -141,7 +140,7 @@ static const struct soc_enum cs42l51_chan_mix = static const struct snd_kcontrol_new cs42l51_snd_controls[] = { SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, - 6, 0x19, 0x7F, adc_pcm_tlv), + 0, 0x19, 0x7F, adc_pcm_tlv), SOC_DOUBLE_R("PCM Playback Switch", CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1), SOC_DOUBLE_R_SX_TLV("Analog Playback Volume", @@ -149,7 +148,7 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = { 0, 0x34, 0xE4, aout_tlv), SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, - 6, 0x19, 0x7F, adc_pcm_tlv), + 0, 0x19, 0x7F, adc_pcm_tlv), SOC_DOUBLE_R("ADC Mixer Switch", CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1), SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0), -- cgit v1.2.3 From 591d14f00796a4250d800d316e3db1fea8a57e20 Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Mon, 17 Mar 2014 22:08:49 -0700 Subject: ASoC: tegra: Use flat regcache When using an rbtree cache, there can be allocations the first time a register is accessed. This can cause an attempt to schedule while atomic in the case that the regmap is using a spinlock. This could be fixed by either initializing all the registers or using a flat cache. The register maps for tegra30_ahub and tegra30_i2s are dense and don't save much from using a tree so convert them to flat. Tegra30 changes tested on Norrin, Tegra20 changes compile. Signed-off-by: Dylan Reid Tested-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_ac97.c | 2 +- sound/soc/tegra/tegra20_das.c | 2 +- sound/soc/tegra/tegra20_i2s.c | 2 +- sound/soc/tegra/tegra20_spdif.c | 2 +- sound/soc/tegra/tegra30_ahub.c | 4 ++-- sound/soc/tegra/tegra30_i2s.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index cf5e1cfe818d..0a59e2383ef3 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -306,7 +306,7 @@ static const struct regmap_config tegra20_ac97_regmap_config = { .readable_reg = tegra20_ac97_wr_rd_reg, .volatile_reg = tegra20_ac97_volatile_reg, .precious_reg = tegra20_ac97_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_ac97_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index e72392927bd2..a634f13b3ffc 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c @@ -128,7 +128,7 @@ static const struct regmap_config tegra20_das_regmap_config = { .max_register = LAST_REG(DAC_INPUT_DATA_CLK_SEL), .writeable_reg = tegra20_das_wr_rd_reg, .readable_reg = tegra20_das_wr_rd_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_das_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 42c1f6bfaf2e..79a9932ffe6e 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -333,7 +333,7 @@ static const struct regmap_config tegra20_i2s_regmap_config = { .readable_reg = tegra20_i2s_wr_rd_reg, .volatile_reg = tegra20_i2s_volatile_reg, .precious_reg = tegra20_i2s_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_i2s_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 8c7c1028e579..a0ce92400faf 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -259,7 +259,7 @@ static const struct regmap_config tegra20_spdif_regmap_config = { .readable_reg = tegra20_spdif_wr_rd_reg, .volatile_reg = tegra20_spdif_volatile_reg, .precious_reg = tegra20_spdif_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static int tegra20_spdif_platform_probe(struct platform_device *pdev) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index d6f4c9940e0c..0db68f49f4d9 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -471,7 +471,7 @@ static const struct regmap_config tegra30_ahub_apbif_regmap_config = { .readable_reg = tegra30_ahub_apbif_wr_rd_reg, .volatile_reg = tegra30_ahub_apbif_volatile_reg, .precious_reg = tegra30_ahub_apbif_precious_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static bool tegra30_ahub_ahub_wr_rd_reg(struct device *dev, unsigned int reg) @@ -490,7 +490,7 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = { .max_register = LAST_REG(AUDIO_RX), .writeable_reg = tegra30_ahub_ahub_wr_rd_reg, .readable_reg = tegra30_ahub_ahub_wr_rd_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static struct tegra30_ahub_soc_data soc_data_tegra30 = { diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 49ad9366add8..f146c41dd3ec 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -357,7 +357,7 @@ static const struct regmap_config tegra30_i2s_regmap_config = { .writeable_reg = tegra30_i2s_wr_rd_reg, .readable_reg = tegra30_i2s_wr_rd_reg, .volatile_reg = tegra30_i2s_volatile_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_FLAT, }; static const struct tegra30_i2s_soc_data tegra30_i2s_config = { -- cgit v1.2.3 From 0c516b4ff85c0be4cee5b30ae59c9565c7f91a00 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 20 Mar 2014 18:18:37 +0800 Subject: ASoC: cs42xx8: Add codec driver support for CS42448/CS42888 This patch adds support for the Cirrus Logic CS42448/CS42888 Audio CODEC that has six/four 24-bit AD and eight 24-bit DA converters. [ CS42448/CS42888 supports both I2C and SPI control ports. As initial patch, this patch only adds the support for I2C. ] Signed-off-by: Nicolin Chen Acked-by: Brian Austin Acked-by: Paul Handrigan Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/cs42xx8.txt | 28 + sound/soc/codecs/Kconfig | 10 + sound/soc/codecs/Makefile | 4 + sound/soc/codecs/cs42xx8-i2c.c | 64 +++ sound/soc/codecs/cs42xx8.c | 602 +++++++++++++++++++++ sound/soc/codecs/cs42xx8.h | 238 ++++++++ 6 files changed, 946 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/cs42xx8.txt create mode 100644 sound/soc/codecs/cs42xx8-i2c.c create mode 100644 sound/soc/codecs/cs42xx8.c create mode 100644 sound/soc/codecs/cs42xx8.h (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/cs42xx8.txt b/Documentation/devicetree/bindings/sound/cs42xx8.txt new file mode 100644 index 000000000000..f631fbca6284 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cs42xx8.txt @@ -0,0 +1,28 @@ +CS42448/CS42888 audio CODEC + +Required properties: + + - compatible : must contain one of "cirrus,cs42448" and "cirrus,cs42888" + + - reg : the I2C address of the device for I2C + + - clocks : a list of phandles + clock-specifiers, one for each entry in + clock-names + + - clock-names : must contain "mclk" + + - VA-supply, VD-supply, VLS-supply, VLC-supply: power supplies for the device, + as covered in Documentation/devicetree/bindings/regulator/regulator.txt + +Example: + +codec: cs42888@48 { + compatible = "cirrus,cs42888"; + reg = <0x48>; + clocks = <&codec_mclk 0>; + clock-names = "mclk"; + VA-supply = <®_audio>; + VD-supply = <®_audio>; + VLS-supply = <®_audio>; + VLC-supply = <®_audio>; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..a79c0d141f90 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -37,6 +37,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CS42L73 if I2C select SND_SOC_CS4270 if I2C select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI + select SND_SOC_CS42XX8_I2C if I2C select SND_SOC_CX20442 if TTY select SND_SOC_DA7210 if I2C select SND_SOC_DA7213 if I2C @@ -254,6 +255,15 @@ config SND_SOC_CS4270_VD33_ERRATA config SND_SOC_CS4271 tristate +config SND_SOC_CS42XX8 + tristate + +config SND_SOC_CS42XX8_I2C + tristate "Cirrus Logic CS42448/CS42888 CODEC (I2C)" + depends on I2C + select SND_SOC_CS42XX8 + select REGMAP_I2C + config SND_SOC_CX20442 tristate depends on TTY diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..cfe5d634c812 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -23,6 +23,8 @@ snd-soc-cs42l52-objs := cs42l52.o snd-soc-cs42l73-objs := cs42l73.o snd-soc-cs4270-objs := cs4270.o snd-soc-cs4271-objs := cs4271.o +snd-soc-cs42xx8-objs := cs42xx8.o +snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o snd-soc-cx20442-objs := cx20442.o snd-soc-da7210-objs := da7210.o snd-soc-da7213-objs := da7213.o @@ -156,6 +158,8 @@ obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o +obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o +obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o obj-$(CONFIG_SND_SOC_DA7213) += snd-soc-da7213.o diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c new file mode 100644 index 000000000000..657dce27eade --- /dev/null +++ b/sound/soc/codecs/cs42xx8-i2c.c @@ -0,0 +1,64 @@ +/* + * Cirrus Logic CS42448/CS42888 Audio CODEC DAI I2C driver + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * Author: Nicolin Chen + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include + +#include "cs42xx8.h" + +static int cs42xx8_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + u32 ret = cs42xx8_probe(&i2c->dev, + devm_regmap_init_i2c(i2c, &cs42xx8_regmap_config)); + if (ret) + return ret; + + pm_runtime_enable(&i2c->dev); + pm_request_idle(&i2c->dev); + + return 0; +} + +static int cs42xx8_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + pm_runtime_disable(&i2c->dev); + + return 0; +} + +static struct i2c_device_id cs42xx8_i2c_id[] = { + {"cs42448", (kernel_ulong_t)&cs42448_data}, + {"cs42888", (kernel_ulong_t)&cs42888_data}, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id); + +static struct i2c_driver cs42xx8_i2c_driver = { + .driver = { + .name = "cs42xx8", + .owner = THIS_MODULE, + .pm = &cs42xx8_pm, + }, + .probe = cs42xx8_i2c_probe, + .remove = cs42xx8_i2c_remove, + .id_table = cs42xx8_i2c_id, +}; + +module_i2c_driver(cs42xx8_i2c_driver); + +MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec I2C Driver"); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c new file mode 100644 index 000000000000..082299a4e2fa --- /dev/null +++ b/sound/soc/codecs/cs42xx8.c @@ -0,0 +1,602 @@ +/* + * Cirrus Logic CS42448/CS42888 Audio CODEC Digital Audio Interface (DAI) driver + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * Author: Nicolin Chen + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cs42xx8.h" + +#define CS42XX8_NUM_SUPPLIES 4 +static const char *const cs42xx8_supply_names[CS42XX8_NUM_SUPPLIES] = { + "VA", + "VD", + "VLS", + "VLC", +}; + +#define CS42XX8_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +/* codec private data */ +struct cs42xx8_priv { + struct regulator_bulk_data supplies[CS42XX8_NUM_SUPPLIES]; + const struct cs42xx8_driver_data *drvdata; + struct regmap *regmap; + struct clk *clk; + + bool slave_mode; + unsigned long sysclk; +}; + +/* -127.5dB to 0dB with step of 0.5dB */ +static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); +/* -64dB to 24dB with step of 0.5dB */ +static const DECLARE_TLV_DB_SCALE(adc_tlv, -6400, 50, 0); + +static const char *const cs42xx8_adc_single[] = { "Differential", "Single-Ended" }; +static const char *const cs42xx8_szc[] = { "Immediate Change", "Zero Cross", + "Soft Ramp", "Soft Ramp on Zero Cross" }; + +static const struct soc_enum adc1_single_enum = + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 4, 2, cs42xx8_adc_single); +static const struct soc_enum adc2_single_enum = + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 3, 2, cs42xx8_adc_single); +static const struct soc_enum adc3_single_enum = + SOC_ENUM_SINGLE(CS42XX8_ADCCTL, 2, 2, cs42xx8_adc_single); +static const struct soc_enum dac_szc_enum = + SOC_ENUM_SINGLE(CS42XX8_TXCTL, 5, 4, cs42xx8_szc); +static const struct soc_enum adc_szc_enum = + SOC_ENUM_SINGLE(CS42XX8_TXCTL, 0, 4, cs42xx8_szc); + +static const struct snd_kcontrol_new cs42xx8_snd_controls[] = { + SOC_DOUBLE_R_TLV("DAC1 Playback Volume", CS42XX8_VOLAOUT1, + CS42XX8_VOLAOUT2, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_TLV("DAC2 Playback Volume", CS42XX8_VOLAOUT3, + CS42XX8_VOLAOUT4, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_TLV("DAC3 Playback Volume", CS42XX8_VOLAOUT5, + CS42XX8_VOLAOUT6, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_TLV("DAC4 Playback Volume", CS42XX8_VOLAOUT7, + CS42XX8_VOLAOUT8, 0, 0xff, 1, dac_tlv), + SOC_DOUBLE_R_S_TLV("ADC1 Capture Volume", CS42XX8_VOLAIN1, + CS42XX8_VOLAIN2, 0, -0x80, 0x30, 7, 0, adc_tlv), + SOC_DOUBLE_R_S_TLV("ADC2 Capture Volume", CS42XX8_VOLAIN3, + CS42XX8_VOLAIN4, 0, -0x80, 0x30, 7, 0, adc_tlv), + SOC_DOUBLE("DAC1 Invert Switch", CS42XX8_DACINV, 0, 1, 1, 0), + SOC_DOUBLE("DAC2 Invert Switch", CS42XX8_DACINV, 2, 3, 1, 0), + SOC_DOUBLE("DAC3 Invert Switch", CS42XX8_DACINV, 4, 5, 1, 0), + SOC_DOUBLE("DAC4 Invert Switch", CS42XX8_DACINV, 6, 7, 1, 0), + SOC_DOUBLE("ADC1 Invert Switch", CS42XX8_ADCINV, 0, 1, 1, 0), + SOC_DOUBLE("ADC2 Invert Switch", CS42XX8_ADCINV, 2, 3, 1, 0), + SOC_SINGLE("ADC High-Pass Filter Switch", CS42XX8_ADCCTL, 7, 1, 1), + SOC_SINGLE("DAC De-emphasis Switch", CS42XX8_ADCCTL, 5, 1, 0), + SOC_ENUM("ADC1 Single Ended Mode Switch", adc1_single_enum), + SOC_ENUM("ADC2 Single Ended Mode Switch", adc2_single_enum), + SOC_SINGLE("DAC Single Volume Control Switch", CS42XX8_TXCTL, 7, 1, 0), + SOC_ENUM("DAC Soft Ramp & Zero Cross Control Switch", dac_szc_enum), + SOC_SINGLE("DAC Auto Mute Switch", CS42XX8_TXCTL, 4, 1, 0), + SOC_SINGLE("Mute ADC Serial Port Switch", CS42XX8_TXCTL, 3, 1, 0), + SOC_SINGLE("ADC Single Volume Control Switch", CS42XX8_TXCTL, 2, 1, 0), + SOC_ENUM("ADC Soft Ramp & Zero Cross Control Switch", adc_szc_enum), +}; + +static const struct snd_kcontrol_new cs42xx8_adc3_snd_controls[] = { + SOC_DOUBLE_R_S_TLV("ADC3 Capture Volume", CS42XX8_VOLAIN5, + CS42XX8_VOLAIN6, 0, -0x80, 0x30, 7, 0, adc_tlv), + SOC_DOUBLE("ADC3 Invert Switch", CS42XX8_ADCINV, 4, 5, 1, 0), + SOC_ENUM("ADC3 Single Ended Mode Switch", adc3_single_enum), +}; + +static const struct snd_soc_dapm_widget cs42xx8_dapm_widgets[] = { + SND_SOC_DAPM_DAC("DAC1", "Playback", CS42XX8_PWRCTL, 1, 1), + SND_SOC_DAPM_DAC("DAC2", "Playback", CS42XX8_PWRCTL, 2, 1), + SND_SOC_DAPM_DAC("DAC3", "Playback", CS42XX8_PWRCTL, 3, 1), + SND_SOC_DAPM_DAC("DAC4", "Playback", CS42XX8_PWRCTL, 4, 1), + + SND_SOC_DAPM_OUTPUT("AOUT1L"), + SND_SOC_DAPM_OUTPUT("AOUT1R"), + SND_SOC_DAPM_OUTPUT("AOUT2L"), + SND_SOC_DAPM_OUTPUT("AOUT2R"), + SND_SOC_DAPM_OUTPUT("AOUT3L"), + SND_SOC_DAPM_OUTPUT("AOUT3R"), + SND_SOC_DAPM_OUTPUT("AOUT4L"), + SND_SOC_DAPM_OUTPUT("AOUT4R"), + + SND_SOC_DAPM_ADC("ADC1", "Capture", CS42XX8_PWRCTL, 5, 1), + SND_SOC_DAPM_ADC("ADC2", "Capture", CS42XX8_PWRCTL, 6, 1), + + SND_SOC_DAPM_INPUT("AIN1L"), + SND_SOC_DAPM_INPUT("AIN1R"), + SND_SOC_DAPM_INPUT("AIN2L"), + SND_SOC_DAPM_INPUT("AIN2R"), + + SND_SOC_DAPM_SUPPLY("PWR", CS42XX8_PWRCTL, 0, 1, NULL, 0), +}; + +static const struct snd_soc_dapm_widget cs42xx8_adc3_dapm_widgets[] = { + SND_SOC_DAPM_ADC("ADC3", "Capture", CS42XX8_PWRCTL, 7, 1), + + SND_SOC_DAPM_INPUT("AIN3L"), + SND_SOC_DAPM_INPUT("AIN3R"), +}; + +static const struct snd_soc_dapm_route cs42xx8_dapm_routes[] = { + /* Playback */ + { "AOUT1L", NULL, "DAC1" }, + { "AOUT1R", NULL, "DAC1" }, + { "DAC1", NULL, "PWR" }, + + { "AOUT2L", NULL, "DAC2" }, + { "AOUT2R", NULL, "DAC2" }, + { "DAC2", NULL, "PWR" }, + + { "AOUT3L", NULL, "DAC3" }, + { "AOUT3R", NULL, "DAC3" }, + { "DAC3", NULL, "PWR" }, + + { "AOUT4L", NULL, "DAC4" }, + { "AOUT4R", NULL, "DAC4" }, + { "DAC4", NULL, "PWR" }, + + /* Capture */ + { "ADC1", NULL, "AIN1L" }, + { "ADC1", NULL, "AIN1R" }, + { "ADC1", NULL, "PWR" }, + + { "ADC2", NULL, "AIN2L" }, + { "ADC2", NULL, "AIN2R" }, + { "ADC2", NULL, "PWR" }, +}; + +static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = { + /* Capture */ + { "ADC3", NULL, "AIN3L" }, + { "ADC3", NULL, "AIN3R" }, + { "ADC3", NULL, "PWR" }, +}; + +struct cs42xx8_ratios { + unsigned int ratio; + unsigned char speed; + unsigned char mclk; +}; + +static const struct cs42xx8_ratios cs42xx8_ratios[] = { + { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) }, + { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) }, + { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) }, + { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) }, + { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) }, + { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) }, + { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) }, + { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) }, + { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) } +}; + +static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + + cs42xx8->sysclk = freq; + + return 0; +} + +static int cs42xx8_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int format) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + u32 val; + + /* Set DAI format */ + switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_LEFT_J: + val = CS42XX8_INTF_DAC_DIF_LEFTJ | CS42XX8_INTF_ADC_DIF_LEFTJ; + break; + case SND_SOC_DAIFMT_I2S: + val = CS42XX8_INTF_DAC_DIF_I2S | CS42XX8_INTF_ADC_DIF_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + val = CS42XX8_INTF_DAC_DIF_RIGHTJ | CS42XX8_INTF_ADC_DIF_RIGHTJ; + break; + default: + dev_err(codec->dev, "unsupported dai format\n"); + return -EINVAL; + } + + regmap_update_bits(cs42xx8->regmap, CS42XX8_INTF, + CS42XX8_INTF_DAC_DIF_MASK | + CS42XX8_INTF_ADC_DIF_MASK, val); + + /* Set master/slave audio interface */ + switch (format & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + cs42xx8->slave_mode = true; + break; + case SND_SOC_DAIFMT_CBM_CFM: + cs42xx8->slave_mode = false; + break; + default: + dev_err(codec->dev, "unsupported master/slave mode\n"); + return -EINVAL; + } + + return 0; +} + +static int cs42xx8_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + u32 ratio = cs42xx8->sysclk / params_rate(params); + u32 i, fm, val, mask; + + for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { + if (cs42xx8_ratios[i].ratio == ratio) + break; + } + + if (i == ARRAY_SIZE(cs42xx8_ratios)) { + dev_err(codec->dev, "unsupported sysclk ratio\n"); + return -EINVAL; + } + + mask = CS42XX8_FUNCMOD_MFREQ_MASK; + val = cs42xx8_ratios[i].mclk; + + fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed; + + regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, + CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask, + CS42XX8_FUNCMOD_xC_FM(tx, fm) | val); + + return 0; +} + +static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + + regmap_update_bits(cs42xx8->regmap, CS42XX8_DACMUTE, + CS42XX8_DACMUTE_ALL, mute ? CS42XX8_DACMUTE_ALL : 0); + + return 0; +} + +static const struct snd_soc_dai_ops cs42xx8_dai_ops = { + .set_fmt = cs42xx8_set_dai_fmt, + .set_sysclk = cs42xx8_set_dai_sysclk, + .hw_params = cs42xx8_hw_params, + .digital_mute = cs42xx8_digital_mute, +}; + +static struct snd_soc_dai_driver cs42xx8_dai = { + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = CS42XX8_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = CS42XX8_FORMATS, + }, + .ops = &cs42xx8_dai_ops, +}; + +static const struct reg_default cs42xx8_reg[] = { + { 0x01, 0x01 }, /* Chip I.D. and Revision Register */ + { 0x02, 0x00 }, /* Power Control */ + { 0x03, 0xF0 }, /* Functional Mode */ + { 0x04, 0x46 }, /* Interface Formats */ + { 0x05, 0x00 }, /* ADC Control & DAC De-Emphasis */ + { 0x06, 0x10 }, /* Transition Control */ + { 0x07, 0x00 }, /* DAC Channel Mute */ + { 0x08, 0x00 }, /* Volume Control AOUT1 */ + { 0x09, 0x00 }, /* Volume Control AOUT2 */ + { 0x0a, 0x00 }, /* Volume Control AOUT3 */ + { 0x0b, 0x00 }, /* Volume Control AOUT4 */ + { 0x0c, 0x00 }, /* Volume Control AOUT5 */ + { 0x0d, 0x00 }, /* Volume Control AOUT6 */ + { 0x0e, 0x00 }, /* Volume Control AOUT7 */ + { 0x0f, 0x00 }, /* Volume Control AOUT8 */ + { 0x10, 0x00 }, /* DAC Channel Invert */ + { 0x11, 0x00 }, /* Volume Control AIN1 */ + { 0x12, 0x00 }, /* Volume Control AIN2 */ + { 0x13, 0x00 }, /* Volume Control AIN3 */ + { 0x14, 0x00 }, /* Volume Control AIN4 */ + { 0x15, 0x00 }, /* Volume Control AIN5 */ + { 0x16, 0x00 }, /* Volume Control AIN6 */ + { 0x17, 0x00 }, /* ADC Channel Invert */ + { 0x18, 0x00 }, /* Status Control */ + { 0x1a, 0x00 }, /* Status Mask */ + { 0x1b, 0x00 }, /* MUTEC Pin Control */ +}; + +static bool cs42xx8_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS42XX8_STATUS: + return true; + default: + return false; + } +} + +static bool cs42xx8_writeable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS42XX8_CHIPID: + case CS42XX8_STATUS: + return false; + default: + return true; + } +} + +const struct regmap_config cs42xx8_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = CS42XX8_LASTREG, + .reg_defaults = cs42xx8_reg, + .num_reg_defaults = ARRAY_SIZE(cs42xx8_reg), + .volatile_reg = cs42xx8_volatile_register, + .writeable_reg = cs42xx8_writeable_register, + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL_GPL(cs42xx8_regmap_config); + +static int cs42xx8_codec_probe(struct snd_soc_codec *codec) +{ + struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = &codec->dapm; + + switch (cs42xx8->drvdata->num_adcs) { + case 3: + snd_soc_add_codec_controls(codec, cs42xx8_adc3_snd_controls, + ARRAY_SIZE(cs42xx8_adc3_snd_controls)); + snd_soc_dapm_new_controls(dapm, cs42xx8_adc3_dapm_widgets, + ARRAY_SIZE(cs42xx8_adc3_dapm_widgets)); + snd_soc_dapm_add_routes(dapm, cs42xx8_adc3_dapm_routes, + ARRAY_SIZE(cs42xx8_adc3_dapm_routes)); + break; + default: + break; + } + + /* Mute all DAC channels */ + regmap_write(cs42xx8->regmap, CS42XX8_DACMUTE, CS42XX8_DACMUTE_ALL); + + return 0; +} + +static const struct snd_soc_codec_driver cs42xx8_driver = { + .probe = cs42xx8_codec_probe, + .idle_bias_off = true, + + .controls = cs42xx8_snd_controls, + .num_controls = ARRAY_SIZE(cs42xx8_snd_controls), + .dapm_widgets = cs42xx8_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs42xx8_dapm_widgets), + .dapm_routes = cs42xx8_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(cs42xx8_dapm_routes), +}; + +const struct cs42xx8_driver_data cs42448_data = { + .name = "cs42448", + .num_adcs = 3, +}; +EXPORT_SYMBOL_GPL(cs42448_data); + +const struct cs42xx8_driver_data cs42888_data = { + .name = "cs42888", + .num_adcs = 2, +}; +EXPORT_SYMBOL_GPL(cs42888_data); + +const struct of_device_id cs42xx8_of_match[] = { + { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, + { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cs42xx8_of_match); +EXPORT_SYMBOL_GPL(cs42xx8_of_match); + +int cs42xx8_probe(struct device *dev, struct regmap *regmap) +{ + const struct of_device_id *of_id = of_match_device(cs42xx8_of_match, dev); + struct cs42xx8_priv *cs42xx8; + int ret, val, i; + + cs42xx8 = devm_kzalloc(dev, sizeof(*cs42xx8), GFP_KERNEL); + if (cs42xx8 == NULL) + return -ENOMEM; + + dev_set_drvdata(dev, cs42xx8); + + if (of_id) + cs42xx8->drvdata = of_id->data; + + if (!cs42xx8->drvdata) { + dev_err(dev, "failed to find driver data\n"); + return -EINVAL; + } + + cs42xx8->clk = devm_clk_get(dev, "mclk"); + if (IS_ERR(cs42xx8->clk)) { + dev_err(dev, "failed to get the clock: %ld\n", + PTR_ERR(cs42xx8->clk)); + return -EINVAL; + } + + cs42xx8->sysclk = clk_get_rate(cs42xx8->clk); + + for (i = 0; i < ARRAY_SIZE(cs42xx8->supplies); i++) + cs42xx8->supplies[i].supply = cs42xx8_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, + ARRAY_SIZE(cs42xx8->supplies), cs42xx8->supplies); + if (ret) { + dev_err(dev, "failed to request supplies: %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + if (ret) { + dev_err(dev, "failed to enable supplies: %d\n", ret); + return ret; + } + + /* Make sure hardware reset done */ + msleep(5); + + cs42xx8->regmap = regmap; + if (IS_ERR(cs42xx8->regmap)) { + ret = PTR_ERR(cs42xx8->regmap); + dev_err(dev, "failed to allocate regmap: %d\n", ret); + goto err_enable; + } + + /* + * We haven't marked the chip revision as volatile due to + * sharing a register with the right input volume; explicitly + * bypass the cache to read it. + */ + regcache_cache_bypass(cs42xx8->regmap, true); + + /* Validate the chip ID */ + regmap_read(cs42xx8->regmap, CS42XX8_CHIPID, &val); + if (val < 0) { + dev_err(dev, "failed to get device ID: %x", val); + ret = -EINVAL; + goto err_enable; + } + + /* The top four bits of the chip ID should be 0000 */ + if ((val & CS42XX8_CHIPID_CHIP_ID_MASK) != 0x00) { + dev_err(dev, "unmatched chip ID: %d\n", + val & CS42XX8_CHIPID_CHIP_ID_MASK); + ret = -EINVAL; + goto err_enable; + } + + dev_info(dev, "found device, revision %X\n", + val & CS42XX8_CHIPID_REV_ID_MASK); + + regcache_cache_bypass(cs42xx8->regmap, false); + + cs42xx8_dai.name = cs42xx8->drvdata->name; + + /* Each adc supports stereo input */ + cs42xx8_dai.capture.channels_max = cs42xx8->drvdata->num_adcs * 2; + + ret = snd_soc_register_codec(dev, &cs42xx8_driver, &cs42xx8_dai, 1); + if (ret) { + dev_err(dev, "failed to register codec:%d\n", ret); + goto err_enable; + } + + regcache_cache_only(cs42xx8->regmap, true); + +err_enable: + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + + return ret; +} +EXPORT_SYMBOL_GPL(cs42xx8_probe); + +#ifdef CONFIG_PM_RUNTIME +static int cs42xx8_runtime_resume(struct device *dev) +{ + struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(cs42xx8->clk); + if (ret) { + dev_err(dev, "failed to enable mclk: %d\n", ret); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + if (ret) { + dev_err(dev, "failed to enable supplies: %d\n", ret); + goto err_clk; + } + + /* Make sure hardware reset done */ + msleep(5); + + regcache_cache_only(cs42xx8->regmap, false); + + ret = regcache_sync(cs42xx8->regmap); + if (ret) { + dev_err(dev, "failed to sync regmap: %d\n", ret); + goto err_bulk; + } + + return 0; + +err_bulk: + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); +err_clk: + clk_disable_unprepare(cs42xx8->clk); + + return ret; +} + +static int cs42xx8_runtime_suspend(struct device *dev) +{ + struct cs42xx8_priv *cs42xx8 = dev_get_drvdata(dev); + + regcache_cache_only(cs42xx8->regmap, true); + + regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies), + cs42xx8->supplies); + + clk_disable_unprepare(cs42xx8->clk); + + return 0; +} +#endif + +const struct dev_pm_ops cs42xx8_pm = { + SET_RUNTIME_PM_OPS(cs42xx8_runtime_suspend, cs42xx8_runtime_resume, NULL) +}; +EXPORT_SYMBOL_GPL(cs42xx8_pm); + +MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec Driver"); +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42xx8.h b/sound/soc/codecs/cs42xx8.h new file mode 100644 index 000000000000..da0b94aee419 --- /dev/null +++ b/sound/soc/codecs/cs42xx8.h @@ -0,0 +1,238 @@ +/* + * cs42xx8.h - Cirrus Logic CS42448/CS42888 Audio CODEC driver header file + * + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * Author: Nicolin Chen + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef _CS42XX8_H +#define _CS42XX8_H + +struct cs42xx8_driver_data { + char name[32]; + int num_adcs; +}; + +extern const struct dev_pm_ops cs42xx8_pm; +extern const struct cs42xx8_driver_data cs42448_data; +extern const struct cs42xx8_driver_data cs42888_data; +extern const struct regmap_config cs42xx8_regmap_config; +int cs42xx8_probe(struct device *dev, struct regmap *regmap); + +/* CS42888 register map */ +#define CS42XX8_CHIPID 0x01 /* Chip ID */ +#define CS42XX8_PWRCTL 0x02 /* Power Control */ +#define CS42XX8_FUNCMOD 0x03 /* Functional Mode */ +#define CS42XX8_INTF 0x04 /* Interface Formats */ +#define CS42XX8_ADCCTL 0x05 /* ADC Control */ +#define CS42XX8_TXCTL 0x06 /* Transition Control */ +#define CS42XX8_DACMUTE 0x07 /* DAC Mute Control */ +#define CS42XX8_VOLAOUT1 0x08 /* Volume Control AOUT1 */ +#define CS42XX8_VOLAOUT2 0x09 /* Volume Control AOUT2 */ +#define CS42XX8_VOLAOUT3 0x0A /* Volume Control AOUT3 */ +#define CS42XX8_VOLAOUT4 0x0B /* Volume Control AOUT4 */ +#define CS42XX8_VOLAOUT5 0x0C /* Volume Control AOUT5 */ +#define CS42XX8_VOLAOUT6 0x0D /* Volume Control AOUT6 */ +#define CS42XX8_VOLAOUT7 0x0E /* Volume Control AOUT7 */ +#define CS42XX8_VOLAOUT8 0x0F /* Volume Control AOUT8 */ +#define CS42XX8_DACINV 0x10 /* DAC Channel Invert */ +#define CS42XX8_VOLAIN1 0x11 /* Volume Control AIN1 */ +#define CS42XX8_VOLAIN2 0x12 /* Volume Control AIN2 */ +#define CS42XX8_VOLAIN3 0x13 /* Volume Control AIN3 */ +#define CS42XX8_VOLAIN4 0x14 /* Volume Control AIN4 */ +#define CS42XX8_VOLAIN5 0x15 /* Volume Control AIN5 */ +#define CS42XX8_VOLAIN6 0x16 /* Volume Control AIN6 */ +#define CS42XX8_ADCINV 0x17 /* ADC Channel Invert */ +#define CS42XX8_STATUSCTL 0x18 /* Status Control */ +#define CS42XX8_STATUS 0x19 /* Status */ +#define CS42XX8_STATUSM 0x1A /* Status Mask */ +#define CS42XX8_MUTEC 0x1B /* MUTEC Pin Control */ + +#define CS42XX8_FIRSTREG CS42XX8_CHIPID +#define CS42XX8_LASTREG CS42XX8_MUTEC +#define CS42XX8_NUMREGS (CS42XX8_LASTREG - CS42XX8_FIRSTREG + 1) +#define CS42XX8_I2C_INCR 0x80 + +/* Chip I.D. and Revision Register (Address 01h) */ +#define CS42XX8_CHIPID_CHIP_ID_MASK 0xF0 +#define CS42XX8_CHIPID_REV_ID_MASK 0x0F + +/* Power Control (Address 02h) */ +#define CS42XX8_PWRCTL_PDN_ADC3_SHIFT 7 +#define CS42XX8_PWRCTL_PDN_ADC3_MASK (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC3 (1 << CS42XX8_PWRCTL_PDN_ADC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC2_SHIFT 6 +#define CS42XX8_PWRCTL_PDN_ADC2_MASK (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC2 (1 << CS42XX8_PWRCTL_PDN_ADC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC1_SHIFT 5 +#define CS42XX8_PWRCTL_PDN_ADC1_MASK (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_ADC1 (1 << CS42XX8_PWRCTL_PDN_ADC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC4_SHIFT 4 +#define CS42XX8_PWRCTL_PDN_DAC4_MASK (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC4 (1 << CS42XX8_PWRCTL_PDN_DAC4_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC3_SHIFT 3 +#define CS42XX8_PWRCTL_PDN_DAC3_MASK (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC3 (1 << CS42XX8_PWRCTL_PDN_DAC3_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC2_SHIFT 2 +#define CS42XX8_PWRCTL_PDN_DAC2_MASK (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC2 (1 << CS42XX8_PWRCTL_PDN_DAC2_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC1_SHIFT 1 +#define CS42XX8_PWRCTL_PDN_DAC1_MASK (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_DAC1 (1 << CS42XX8_PWRCTL_PDN_DAC1_SHIFT) +#define CS42XX8_PWRCTL_PDN_SHIFT 0 +#define CS42XX8_PWRCTL_PDN_MASK (1 << CS42XX8_PWRCTL_PDN_SHIFT) +#define CS42XX8_PWRCTL_PDN (1 << CS42XX8_PWRCTL_PDN_SHIFT) + +/* Functional Mode (Address 03h) */ +#define CS42XX8_FUNCMOD_DAC_FM_SHIFT 6 +#define CS42XX8_FUNCMOD_DAC_FM_WIDTH 2 +#define CS42XX8_FUNCMOD_DAC_FM_MASK (((1 << CS42XX8_FUNCMOD_DAC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_DAC_FM_SHIFT) +#define CS42XX8_FUNCMOD_DAC_FM(v) ((v) << CS42XX8_FUNCMOD_DAC_FM_SHIFT) +#define CS42XX8_FUNCMOD_ADC_FM_SHIFT 4 +#define CS42XX8_FUNCMOD_ADC_FM_WIDTH 2 +#define CS42XX8_FUNCMOD_ADC_FM_MASK (((1 << CS42XX8_FUNCMOD_ADC_FM_WIDTH) - 1) << CS42XX8_FUNCMOD_ADC_FM_SHIFT) +#define CS42XX8_FUNCMOD_ADC_FM(v) ((v) << CS42XX8_FUNCMOD_ADC_FM_SHIFT) +#define CS42XX8_FUNCMOD_xC_FM_MASK(x) ((x) ? CS42XX8_FUNCMOD_DAC_FM_MASK : CS42XX8_FUNCMOD_ADC_FM_MASK) +#define CS42XX8_FUNCMOD_xC_FM(x, v) ((x) ? CS42XX8_FUNCMOD_DAC_FM(v) : CS42XX8_FUNCMOD_ADC_FM(v)) +#define CS42XX8_FUNCMOD_MFREQ_SHIFT 1 +#define CS42XX8_FUNCMOD_MFREQ_WIDTH 3 +#define CS42XX8_FUNCMOD_MFREQ_MASK (((1 << CS42XX8_FUNCMOD_MFREQ_WIDTH) - 1) << CS42XX8_FUNCMOD_MFREQ_SHIFT) +#define CS42XX8_FUNCMOD_MFREQ_256(s) ((0 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_384(s) ((1 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_512(s) ((2 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_768(s) ((3 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) +#define CS42XX8_FUNCMOD_MFREQ_1024(s) ((4 << CS42XX8_FUNCMOD_MFREQ_SHIFT) >> (s >> 1)) + +#define CS42XX8_FM_SINGLE 0 +#define CS42XX8_FM_DOUBLE 1 +#define CS42XX8_FM_QUAD 2 +#define CS42XX8_FM_AUTO 3 + +/* Interface Formats (Address 04h) */ +#define CS42XX8_INTF_FREEZE_SHIFT 7 +#define CS42XX8_INTF_FREEZE_MASK (1 << CS42XX8_INTF_FREEZE_SHIFT) +#define CS42XX8_INTF_FREEZE (1 << CS42XX8_INTF_FREEZE_SHIFT) +#define CS42XX8_INTF_AUX_DIF_SHIFT 6 +#define CS42XX8_INTF_AUX_DIF_MASK (1 << CS42XX8_INTF_AUX_DIF_SHIFT) +#define CS42XX8_INTF_AUX_DIF (1 << CS42XX8_INTF_AUX_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_SHIFT 3 +#define CS42XX8_INTF_DAC_DIF_WIDTH 3 +#define CS42XX8_INTF_DAC_DIF_MASK (((1 << CS42XX8_INTF_DAC_DIF_WIDTH) - 1) << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_LEFTJ (0 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_I2S (1 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_RIGHTJ (2 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_ONELINE_20 (4 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_ONELINE_24 (6 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_DAC_DIF_TDM (7 << CS42XX8_INTF_DAC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_SHIFT 0 +#define CS42XX8_INTF_ADC_DIF_WIDTH 3 +#define CS42XX8_INTF_ADC_DIF_MASK (((1 << CS42XX8_INTF_ADC_DIF_WIDTH) - 1) << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_LEFTJ (0 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_I2S (1 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_RIGHTJ (2 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_RIGHTJ_16 (3 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_ONELINE_20 (4 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_ONELINE_24 (6 << CS42XX8_INTF_ADC_DIF_SHIFT) +#define CS42XX8_INTF_ADC_DIF_TDM (7 << CS42XX8_INTF_ADC_DIF_SHIFT) + +/* ADC Control & DAC De-Emphasis (Address 05h) */ +#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT 7 +#define CS42XX8_ADCCTL_ADC_HPF_FREEZE_MASK (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT) +#define CS42XX8_ADCCTL_ADC_HPF_FREEZE (1 << CS42XX8_ADCCTL_ADC_HPF_FREEZE_SHIFT) +#define CS42XX8_ADCCTL_DAC_DEM_SHIFT 5 +#define CS42XX8_ADCCTL_DAC_DEM_MASK (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT) +#define CS42XX8_ADCCTL_DAC_DEM (1 << CS42XX8_ADCCTL_DAC_DEM_SHIFT) +#define CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT 4 +#define CS42XX8_ADCCTL_ADC1_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC1_SINGLE (1 << CS42XX8_ADCCTL_ADC1_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT 3 +#define CS42XX8_ADCCTL_ADC2_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC2_SINGLE (1 << CS42XX8_ADCCTL_ADC2_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT 2 +#define CS42XX8_ADCCTL_ADC3_SINGLE_MASK (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_ADC3_SINGLE (1 << CS42XX8_ADCCTL_ADC3_SINGLE_SHIFT) +#define CS42XX8_ADCCTL_AIN5_MUX_SHIFT 1 +#define CS42XX8_ADCCTL_AIN5_MUX_MASK (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT) +#define CS42XX8_ADCCTL_AIN5_MUX (1 << CS42XX8_ADCCTL_AIN5_MUX_SHIFT) +#define CS42XX8_ADCCTL_AIN6_MUX_SHIFT 0 +#define CS42XX8_ADCCTL_AIN6_MUX_MASK (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT) +#define CS42XX8_ADCCTL_AIN6_MUX (1 << CS42XX8_ADCCTL_AIN6_MUX_SHIFT) + +/* Transition Control (Address 06h) */ +#define CS42XX8_TXCTL_DAC_SNGVOL_SHIFT 7 +#define CS42XX8_TXCTL_DAC_SNGVOL_MASK (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_DAC_SNGVOL (1 << CS42XX8_TXCTL_DAC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_SHIFT 5 +#define CS42XX8_TXCTL_DAC_SZC_WIDTH 2 +#define CS42XX8_TXCTL_DAC_SZC_MASK (((1 << CS42XX8_TXCTL_DAC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_IC (0 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_ZC (1 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_SR (2 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_DAC_SZC_SRZC (3 << CS42XX8_TXCTL_DAC_SZC_SHIFT) +#define CS42XX8_TXCTL_AMUTE_SHIFT 4 +#define CS42XX8_TXCTL_AMUTE_MASK (1 << CS42XX8_TXCTL_AMUTE_SHIFT) +#define CS42XX8_TXCTL_AMUTE (1 << CS42XX8_TXCTL_AMUTE_SHIFT) +#define CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT 3 +#define CS42XX8_TXCTL_MUTE_ADC_SP_MASK (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT) +#define CS42XX8_TXCTL_MUTE_ADC_SP (1 << CS42XX8_TXCTL_MUTE_ADC_SP_SHIFT) +#define CS42XX8_TXCTL_ADC_SNGVOL_SHIFT 2 +#define CS42XX8_TXCTL_ADC_SNGVOL_MASK (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_ADC_SNGVOL (1 << CS42XX8_TXCTL_ADC_SNGVOL_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_SHIFT 0 +#define CS42XX8_TXCTL_ADC_SZC_MASK (((1 << CS42XX8_TXCTL_ADC_SZC_WIDTH) - 1) << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_IC (0 << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_ZC (1 << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_SR (2 << CS42XX8_TXCTL_ADC_SZC_SHIFT) +#define CS42XX8_TXCTL_ADC_SZC_SRZC (3 << CS42XX8_TXCTL_ADC_SZC_SHIFT) + +/* DAC Channel Mute (Address 07h) */ +#define CS42XX8_DACMUTE_AOUT(n) (0x1 << n) +#define CS42XX8_DACMUTE_ALL 0xff + +/* Status Control (Address 18h)*/ +#define CS42XX8_STATUSCTL_INI_SHIFT 2 +#define CS42XX8_STATUSCTL_INI_WIDTH 2 +#define CS42XX8_STATUSCTL_INI_MASK (((1 << CS42XX8_STATUSCTL_INI_WIDTH) - 1) << CS42XX8_STATUSCTL_INI_SHIFT) +#define CS42XX8_STATUSCTL_INT_ACTIVE_HIGH (0 << CS42XX8_STATUSCTL_INI_SHIFT) +#define CS42XX8_STATUSCTL_INT_ACTIVE_LOW (1 << CS42XX8_STATUSCTL_INI_SHIFT) +#define CS42XX8_STATUSCTL_INT_OPEN_DRAIN (2 << CS42XX8_STATUSCTL_INI_SHIFT) + +/* Status (Address 19h)*/ +#define CS42XX8_STATUS_DAC_CLK_ERR_SHIFT 4 +#define CS42XX8_STATUS_DAC_CLK_ERR_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_SHIFT) +#define CS42XX8_STATUS_ADC_CLK_ERR_SHIFT 3 +#define CS42XX8_STATUS_ADC_CLK_ERR_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_SHIFT) +#define CS42XX8_STATUS_ADC3_OVFL_SHIFT 2 +#define CS42XX8_STATUS_ADC3_OVFL_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_SHIFT) +#define CS42XX8_STATUS_ADC2_OVFL_SHIFT 1 +#define CS42XX8_STATUS_ADC2_OVFL_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_SHIFT) +#define CS42XX8_STATUS_ADC1_OVFL_SHIFT 0 +#define CS42XX8_STATUS_ADC1_OVFL_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_SHIFT) + +/* Status Mask (Address 1Ah) */ +#define CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT 4 +#define CS42XX8_STATUS_DAC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_DAC_CLK_ERR_M_SHIFT) +#define CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT 3 +#define CS42XX8_STATUS_ADC_CLK_ERR_M_MASK (1 << CS42XX8_STATUS_ADC_CLK_ERR_M_SHIFT) +#define CS42XX8_STATUS_ADC3_OVFL_M_SHIFT 2 +#define CS42XX8_STATUS_ADC3_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC3_OVFL_M_SHIFT) +#define CS42XX8_STATUS_ADC2_OVFL_M_SHIFT 1 +#define CS42XX8_STATUS_ADC2_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC2_OVFL_M_SHIFT) +#define CS42XX8_STATUS_ADC1_OVFL_M_SHIFT 0 +#define CS42XX8_STATUS_ADC1_OVFL_M_MASK (1 << CS42XX8_STATUS_ADC1_OVFL_M_SHIFT) + +/* MUTEC Pin Control (Address 1Bh) */ +#define CS42XX8_MUTEC_MCPOLARITY_SHIFT 1 +#define CS42XX8_MUTEC_MCPOLARITY_MASK (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) +#define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_LOW (0 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) +#define CS42XX8_MUTEC_MCPOLARITY_ACTIVE_HIGH (1 << CS42XX8_MUTEC_MCPOLARITY_SHIFT) +#define CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT 0 +#define CS42XX8_MUTEC_MUTEC_ACTIVE_MASK (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT) +#define CS42XX8_MUTEC_MUTEC_ACTIVE (1 << CS42XX8_MUTEC_MUTEC_ACTIVE_SHIFT) +#endif /* _CS42XX8_H */ -- cgit v1.2.3 From 43b956349de28884265e8237a5cd1f669fbaa485 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:31 +0100 Subject: ASoC: mfld_machine: Convert to table based DAPM and control setup Use table based setup to register the controls and DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. The mfld_machine driver is a bit special in that it directly writes to one of the CODEC registers from one of the control handlers. Previous to this patch it was able to get a pointer to the CODEC from the control, since the control was registered with the CODEC. This won't be possible anymore once the control is registered with the card. Since there are already global variables in the driver accessed in the same function the patch adds a global variable that holds a pointer to the CODEC and uses that. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/intel/mfld_machine.c | 49 +++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/mfld_machine.c b/sound/soc/intel/mfld_machine.c index 0cef32e9d402..461694263c46 100644 --- a/sound/soc/intel/mfld_machine.c +++ b/sound/soc/intel/mfld_machine.c @@ -53,6 +53,7 @@ enum soc_mic_bias_zones { static unsigned int hs_switch; static unsigned int lo_dac; +static struct snd_soc_codec *mfld_codec; struct mfld_mc_private { void __iomem *int_base; @@ -100,8 +101,8 @@ static int headset_get_switch(struct snd_kcontrol *kcontrol, static int headset_set_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = &card->dapm; if (ucontrol->value.integer.value[0] == hs_switch) return 0; @@ -127,10 +128,8 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol, return 0; } -static void lo_enable_out_pins(struct snd_soc_codec *codec) +static void lo_enable_out_pins(struct snd_soc_dapm_context *dapm) { - struct snd_soc_dapm_context *dapm = &codec->dapm; - snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTL"); snd_soc_dapm_enable_pin_unlocked(dapm, "IHFOUTR"); snd_soc_dapm_enable_pin_unlocked(dapm, "LINEOUTL"); @@ -156,8 +155,8 @@ static int lo_get_switch(struct snd_kcontrol *kcontrol, static int lo_set_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = &card->dapm; if (ucontrol->value.integer.value[0] == lo_dac) return 0; @@ -167,35 +166,35 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol, /* we dont want to work with last state of lineout so just enable all * pins and then disable pins not required */ - lo_enable_out_pins(codec); + lo_enable_out_pins(dapm); switch (ucontrol->value.integer.value[0]) { case 0: pr_debug("set vibra path\n"); snd_soc_dapm_disable_pin_unlocked(dapm, "VIB1OUT"); snd_soc_dapm_disable_pin_unlocked(dapm, "VIB2OUT"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0); + snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0); break; case 1: pr_debug("set hs path\n"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphones"); snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22); + snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x22); break; case 2: pr_debug("set spkr path\n"); snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTL"); snd_soc_dapm_disable_pin_unlocked(dapm, "IHFOUTR"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44); + snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x44); break; case 3: pr_debug("set null path\n"); snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTL"); snd_soc_dapm_disable_pin_unlocked(dapm, "LINEOUTR"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66); + snd_soc_update_bits(mfld_codec, SN95031_LOCTL, 0x66, 0x66); break; } @@ -238,26 +237,11 @@ static void mfld_jack_check(unsigned int intr_status) static int mfld_init(struct snd_soc_pcm_runtime *runtime) { - struct snd_soc_codec *codec = runtime->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_dapm_context *dapm = &runtime->card->dapm; int ret_val; - /* Add jack sense widgets */ - snd_soc_dapm_new_controls(dapm, mfld_widgets, ARRAY_SIZE(mfld_widgets)); - - /* Set up the map */ - snd_soc_dapm_add_routes(dapm, mfld_map, ARRAY_SIZE(mfld_map)); + mfld_codec = runtime->codec; - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Headphones"); - snd_soc_dapm_enable_pin(dapm, "Mic"); - - ret_val = snd_soc_add_codec_controls(codec, mfld_snd_controls, - ARRAY_SIZE(mfld_snd_controls)); - if (ret_val) { - pr_err("soc_add_controls failed %d", ret_val); - return ret_val; - } /* default is earpiece pin, userspace sets it explcitly */ snd_soc_dapm_disable_pin(dapm, "Headphones"); /* default is lineout NC, userspace sets it explcitly */ @@ -352,6 +336,13 @@ static struct snd_soc_card snd_soc_card_mfld = { .owner = THIS_MODULE, .dai_link = mfld_msic_dailink, .num_links = ARRAY_SIZE(mfld_msic_dailink), + + .controls = mfld_snd_controls, + .num_controls = ARRAY_SIZE(mfld_snd_controls), + .dapm_widgets = mfld_widgets, + .num_dapm_widgets = ARRAY_SIZE(mfld_widgets), + .dapm_routes = mfld_map, + .num_dapm_routes = ARRAY_SIZE(mfld_map), }; static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev) -- cgit v1.2.3 From 90e8e50fce3585d6f9902701de08389b027dadc6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 17 Mar 2014 19:29:55 -0700 Subject: ASoC: rsnd: add DeviceTree support Support for loading the Renesas R-Car sound driver via DeviceTree. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/renesas,rsnd.txt | 96 ++++++++++++++++ sound/soc/sh/rcar/adg.c | 1 + sound/soc/sh/rcar/core.c | 122 ++++++++++++++++++++- sound/soc/sh/rcar/gen.c | 15 +++ sound/soc/sh/rcar/rsnd.h | 11 ++ sound/soc/sh/rcar/src.c | 36 ++++++ sound/soc/sh/rcar/ssi.c | 56 ++++++++++ 7 files changed, 334 insertions(+), 3 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/renesas,rsnd.txt (limited to 'sound/soc') diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt new file mode 100644 index 000000000000..7c6d33f29796 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt @@ -0,0 +1,96 @@ +Renesas R-Car sound + +Required properties: +- compatible : "renesas,rcar_sound-gen1" if generation1 + "renesas,rcar_sound-gen2" if generation2 +- reg : Should contain the register physical address. + required register is + SRU/ADG/SSI if generation1 + SRU/ADG/SSIU/SSI if generation2 +- rcar_sound,ssi : SSI subnode +- rcar_sound,scu : SCU subnode +- rcar_sound,dai : DAI subnode + +SSI subnode properties: +- interrupts : Should contain SSI interrupt for PIO transfer +- shared-pin : if shared clock pin + +DAI subnode properties: +- playback : list of playback modules +- capture : list of capture modules + +Example: + +rcar_sound: rcar_sound@0xffd90000 { + #sound-dai-cells = <1>; + compatible = "renesas,rcar_sound-gen2"; + reg = <0 0xec500000 0 0x1000>, /* SCU */ + <0 0xec5a0000 0 0x100>, /* ADG */ + <0 0xec540000 0 0x1000>, /* SSIU */ + <0 0xec541000 0 0x1280>; /* SSI */ + + rcar_sound,src { + src0: src@0 { }; + src1: src@1 { }; + src2: src@2 { }; + src3: src@3 { }; + src4: src@4 { }; + src5: src@5 { }; + src6: src@6 { }; + src7: src@7 { }; + src8: src@8 { }; + src9: src@9 { }; + }; + + rcar_sound,ssi { + ssi0: ssi@0 { + interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi1: ssi@1 { + interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi2: ssi@2 { + interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi3: ssi@3 { + interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi4: ssi@4 { + interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi5: ssi@5 { + interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi6: ssi@6 { + interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi7: ssi@7 { + interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi8: ssi@8 { + interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>; + }; + ssi9: ssi@9 { + interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + rcar_sound,dai { + dai0 { + playback = <&ssi5 &src5>; + capture = <&ssi6>; + }; + dai1 { + playback = <&ssi3>; + }; + dai2 { + capture = <&ssi4>; + }; + dai3 { + playback = <&ssi7>; + }; + dai4 { + capture = <&ssi8>; + }; + }; +}; diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 953f1cce982d..69c44269ebdb 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -392,6 +392,7 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) } int rsnd_adg_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct rsnd_adg *adg; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 6a1b45df8101..e77f7716f1d7 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -100,6 +100,21 @@ #define RSND_RATES SNDRV_PCM_RATE_8000_96000 #define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) +static struct rsnd_of_data rsnd_of_data_gen1 = { + .flags = RSND_GEN1, +}; + +static struct rsnd_of_data rsnd_of_data_gen2 = { + .flags = RSND_GEN2, +}; + +static struct of_device_id rsnd_of_match[] = { + { .compatible = "renesas,rcar_sound-gen1", .data = &rsnd_of_data_gen1 }, + { .compatible = "renesas,rcar_sound-gen2", .data = &rsnd_of_data_gen2 }, + {}, +}; +MODULE_DEVICE_TABLE(of, rsnd_of_match); + /* * rsnd_platform functions */ @@ -620,7 +635,92 @@ static int rsnd_path_init(struct rsnd_priv *priv, return ret; } +static void rsnd_of_parse_dai(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct device_node *dai_node, *dai_np; + struct device_node *ssi_node, *ssi_np; + struct device_node *src_node, *src_np; + struct device_node *playback, *capture; + struct rsnd_dai_platform_info *dai_info; + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = &pdev->dev; + int nr, i; + int dai_i, ssi_i, src_i; + + if (!of_data) + return; + + dai_node = of_get_child_by_name(dev->of_node, "rcar_sound,dai"); + if (!dai_node) + return; + + nr = of_get_child_count(dai_node); + if (!nr) + return; + + dai_info = devm_kzalloc(dev, + sizeof(struct rsnd_dai_platform_info) * nr, + GFP_KERNEL); + if (!dai_info) { + dev_err(dev, "dai info allocation error\n"); + return; + } + + info->dai_info_nr = nr; + info->dai_info = dai_info; + + ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); + src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); + +#define mod_parse(name) \ +if (name##_node) { \ + struct rsnd_##name##_platform_info *name##_info; \ + \ + name##_i = 0; \ + for_each_child_of_node(name##_node, name##_np) { \ + name##_info = info->name##_info + name##_i; \ + \ + if (name##_np == playback) \ + dai_info->playback.name = name##_info; \ + if (name##_np == capture) \ + dai_info->capture.name = name##_info; \ + \ + name##_i++; \ + } \ +} + + /* + * parse all dai + */ + dai_i = 0; + for_each_child_of_node(dai_node, dai_np) { + dai_info = info->dai_info + dai_i; + + for (i = 0;; i++) { + + playback = of_parse_phandle(dai_np, "playback", i); + capture = of_parse_phandle(dai_np, "capture", i); + + if (!playback && !capture) + break; + + mod_parse(ssi); + mod_parse(src); + + if (playback) + of_node_put(playback); + if (capture) + of_node_put(capture); + } + + dai_i++; + } +} + static int rsnd_dai_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct snd_soc_dai_driver *drv; @@ -628,13 +728,16 @@ static int rsnd_dai_probe(struct platform_device *pdev, struct rsnd_dai *rdai; struct rsnd_mod *pmod, *cmod; struct device *dev = rsnd_priv_to_dev(priv); - int dai_nr = info->dai_info_nr; + int dai_nr; int i; + rsnd_of_parse_dai(pdev, of_data, priv); + /* * dai_nr should be set via dai_info_nr, * but allow it to keeping compatible */ + dai_nr = info->dai_info_nr; if (!dai_nr) { /* get max dai nr */ for (dai_nr = 0; dai_nr < 32; dai_nr++) { @@ -802,7 +905,10 @@ static int rsnd_probe(struct platform_device *pdev) struct rsnd_priv *priv; struct device *dev = &pdev->dev; struct rsnd_dai *rdai; + const struct of_device_id *of_id = of_match_device(rsnd_of_match, dev); + const struct rsnd_of_data *of_data; int (*probe_func[])(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) = { rsnd_gen_probe, rsnd_ssi_probe, @@ -812,7 +918,16 @@ static int rsnd_probe(struct platform_device *pdev) }; int ret, i; - info = pdev->dev.platform_data; + info = NULL; + of_data = NULL; + if (of_id) { + info = devm_kzalloc(&pdev->dev, + sizeof(struct rcar_snd_info), GFP_KERNEL); + of_data = of_id->data; + } else { + info = pdev->dev.platform_data; + } + if (!info) { dev_err(dev, "driver needs R-Car sound information\n"); return -ENODEV; @@ -835,7 +950,7 @@ static int rsnd_probe(struct platform_device *pdev) * init each module */ for (i = 0; i < ARRAY_SIZE(probe_func); i++) { - ret = probe_func[i](pdev, priv); + ret = probe_func[i](pdev, of_data, priv); if (ret) return ret; } @@ -903,6 +1018,7 @@ static int rsnd_remove(struct platform_device *pdev) static struct platform_driver rsnd_driver = { .driver = { .name = "rcar_sound", + .of_match_table = rsnd_of_match, }, .probe = rsnd_probe, .remove = rsnd_remove, diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 9094970dbdfb..50a1ef3eb1c6 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -359,13 +359,28 @@ static int rsnd_gen1_probe(struct platform_device *pdev, /* * Gen */ +static void rsnd_of_parse_gen(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct rcar_snd_info *info = priv->info; + + if (!of_data) + return; + + info->flags = of_data->flags; +} + int rsnd_gen_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_gen *gen; int ret; + rsnd_of_parse_gen(pdev, of_data, priv); + gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); if (!gen) { dev_err(dev, "GEN allocate failed\n"); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index c46e0afa54ae..619d198c7d2e 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -113,6 +115,7 @@ enum rsnd_reg { #define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18 #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 +struct rsnd_of_data; struct rsnd_priv; struct rsnd_mod; struct rsnd_dai; @@ -260,6 +263,7 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); * R-Car Gen1/Gen2 */ int rsnd_gen_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv); void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, struct rsnd_mod *mod, @@ -273,6 +277,7 @@ void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); int rsnd_adg_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv); int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, @@ -290,6 +295,10 @@ int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, /* * R-Car sound priv */ +struct rsnd_of_data { + u32 flags; +}; + struct rsnd_priv { struct device *dev; @@ -348,6 +357,7 @@ struct rsnd_priv { * R-Car SRC */ int rsnd_src_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv); struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, @@ -366,6 +376,7 @@ int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, * R-Car SSI */ int rsnd_ssi_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv); struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index ea6a214985d0..eee75ebf961c 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -628,7 +628,41 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) return &((struct rsnd_src *)(priv->src) + id)->mod; } +static void rsnd_of_parse_src(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct device_node *src_node; + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct rsnd_src_platform_info *src_info; + struct device *dev = &pdev->dev; + int nr; + + if (!of_data) + return; + + src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); + if (!src_node) + return; + + nr = of_get_child_count(src_node); + if (!nr) + return; + + src_info = devm_kzalloc(dev, + sizeof(struct rsnd_src_platform_info) * nr, + GFP_KERNEL); + if (!src_info) { + dev_err(dev, "src info allocation error\n"); + return; + } + + info->src_info = src_info; + info->src_info_nr = nr; +} + int rsnd_src_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct rcar_snd_info *info = rsnd_priv_to_info(priv); @@ -639,6 +673,8 @@ int rsnd_src_probe(struct platform_device *pdev, char name[RSND_SRC_NAME_SIZE]; int i, nr; + rsnd_of_parse_src(pdev, of_data, priv); + /* * init SRC */ diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 633b23d209b9..4b7e20603dd7 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -588,7 +588,61 @@ static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *s } } + +static void rsnd_of_parse_ssi(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct device_node *node; + struct device_node *np; + struct rsnd_ssi_platform_info *ssi_info; + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = &pdev->dev; + int nr, i; + + if (!of_data) + return; + + node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); + if (!node) + return; + + nr = of_get_child_count(node); + if (!nr) + return; + + ssi_info = devm_kzalloc(dev, + sizeof(struct rsnd_ssi_platform_info) * nr, + GFP_KERNEL); + if (!ssi_info) { + dev_err(dev, "ssi info allocation error\n"); + return; + } + + info->ssi_info = ssi_info; + info->ssi_info_nr = nr; + + i = -1; + for_each_child_of_node(node, np) { + i++; + + ssi_info = info->ssi_info + i; + + /* + * pin settings + */ + if (of_get_property(np, "shared-pin", NULL)) + ssi_info->flags |= RSND_SSI_CLK_PIN_SHARE; + + /* + * irq + */ + ssi_info->pio_irq = irq_of_parse_and_map(np, 0); + } +} + int rsnd_ssi_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct rcar_snd_info *info = rsnd_priv_to_info(priv); @@ -600,6 +654,8 @@ int rsnd_ssi_probe(struct platform_device *pdev, char name[RSND_SSI_NAME_SIZE]; int i, nr; + rsnd_of_parse_ssi(pdev, of_data, priv); + /* * init SSI */ -- cgit v1.2.3 From 546d4dd3bb99466e4268256bad615a5ed6457a55 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 21 Mar 2014 20:23:51 +0100 Subject: ASoC: mfld_machine: Fix compile error Fixes: 115f3f8 ("ASoC: mfld_machine: Convert to table based DAPM and control setup") Reported-by: kbuild test robot Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/intel/mfld_machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/intel/mfld_machine.c b/sound/soc/intel/mfld_machine.c index 461694263c46..031d78783fc8 100644 --- a/sound/soc/intel/mfld_machine.c +++ b/sound/soc/intel/mfld_machine.c @@ -254,7 +254,7 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime) snd_soc_dapm_disable_pin(dapm, "LINEINR"); /* Headset and button jack detection */ - ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack", + ret_val = snd_soc_jack_new(mfld_codec, "Intel(R) MID Audio Jack", SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1, &mfld_jack); if (ret_val) { -- cgit v1.2.3 From 017d9491ce203c620ad1377f46a3ce78d554b2de Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 22 Mar 2014 18:29:15 +0000 Subject: ASoC: pcm: Drop incorrect double/extra frees The changes in "ASoC: pcm: free path list before exiting from error conditions" actually introduced both double frees (in case where the path list was allocated but empty) and frees of unallocated memory (in cases where the error being handled was -ENOMEM. Drop the commit for now. Fixes: e4ad1accb (ASoC: pcm: free path list before exiting from error conditions) Reported-by: Ben Hutchings Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/soc-pcm.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 28522bd03b8e..47e1ce771e65 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1989,7 +1989,6 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list); if (paths < 0) { - dpcm_path_put(&list); dev_warn(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name, "playback"); mutex_unlock(&card->mutex); @@ -2019,7 +2018,6 @@ capture: paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list); if (paths < 0) { - dpcm_path_put(&list); dev_warn(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name, "capture"); mutex_unlock(&card->mutex); @@ -2084,7 +2082,6 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) fe->dpcm[stream].runtime = fe_substream->runtime; if (dpcm_path_get(fe, stream, &list) <= 0) { - dpcm_path_put(&list); dev_dbg(fe->dev, "ASoC: %s no valid %s route\n", fe->dai_link->name, stream ? "capture" : "playback"); } -- cgit v1.2.3