From 1a95d8d09ef7e40563afd587cce52868e3d076a0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 18 Mar 2014 15:20:37 +0200 Subject: ASoC: davinci-pcm: Add empty functions for !CONFIG_SND_DAVINCI_SOC builds To save drivers using davinci-pcm and edma-pcm the need to fiddle with !CONFIG_SND_DAVINCI_SOC in their code. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-pcm.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index fbb710c76c08..5fd4737ab398 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -29,7 +29,17 @@ struct davinci_pcm_dma_params { unsigned int fifo_level; }; +#if IS_ENABLED(CONFIG_SND_DAVINCI_SOC) int davinci_soc_platform_register(struct device *dev); void davinci_soc_platform_unregister(struct device *dev); +#else +static inline int davinci_soc_platform_register(struct device *dev) +{ + return 0; +} +static inline void davinci_soc_platform_unregister(struct device *dev) +{ +} +#endif /* CONFIG_SND_DAVINCI_SOC */ #endif -- cgit v1.2.2 From d5902f693698076e5bda44cbfa999e9c02bb83ab Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 1 Apr 2014 15:55:07 +0300 Subject: ASoC: davinci-mcasp: Assign the dma_data earlier in dai_probe callback Set up the playback_dma_data/capture_dma_data for the dai at probe time since the generic dmaengine PCM stack needs to have access to this information early. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 4f75cac462d1..b4c5cf58b030 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -716,22 +716,7 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, return ret; } -static int davinci_mcasp_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - - if (mcasp->version == MCASP_VERSION_4) - snd_soc_dai_set_dma_data(dai, substream, - &mcasp->dma_data[substream->stream]); - else - snd_soc_dai_set_dma_data(dai, substream, mcasp->dma_params); - - return 0; -} - static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { - .startup = davinci_mcasp_startup, .trigger = davinci_mcasp_trigger, .hw_params = davinci_mcasp_hw_params, .set_fmt = davinci_mcasp_set_dai_fmt, @@ -739,6 +724,25 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .set_sysclk = davinci_mcasp_set_sysclk, }; +static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) +{ + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + + if (mcasp->version == MCASP_VERSION_4) { + /* Using dmaengine PCM */ + dai->playback_dma_data = + &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; + dai->capture_dma_data = + &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; + } else { + /* Using davinci-pcm */ + dai->playback_dma_data = mcasp->dma_params; + dai->capture_dma_data = mcasp->dma_params; + } + + return 0; +} + #ifdef CONFIG_PM_SLEEP static int davinci_mcasp_suspend(struct snd_soc_dai *dai) { @@ -792,6 +796,7 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai) static struct snd_soc_dai_driver davinci_mcasp_dai[] = { { .name = "davinci-mcasp.0", + .probe = davinci_mcasp_dai_probe, .suspend = davinci_mcasp_suspend, .resume = davinci_mcasp_resume, .playback = { @@ -811,6 +816,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { }, { .name = "davinci-mcasp.1", + .probe = davinci_mcasp_dai_probe, .playback = { .channels_min = 1, .channels_max = 384, -- cgit v1.2.2 From f5b02b4a2cb7eaa223ddaba8e4338b31bcdaf369 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 1 Apr 2014 15:55:08 +0300 Subject: ASoC: davinci-mcasp: Fix debug typo in davinci_mcasp_hw_params() requred -> required Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index b4c5cf58b030..eb46dc69248f 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -620,7 +620,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, 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"); + dev_err(mcasp->dev, "Can't produce required BCLK\n"); return -EINVAL; } davinci_mcasp_set_clkdiv( -- cgit v1.2.2 From 0bf0e8aeceaf4b12524559fce9c6b91a90b63381 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 1 Apr 2014 15:55:09 +0300 Subject: ASoC: davinci-mcasp: Simplify and clean up the AFIFO configuration code We can have more linear code flow by using variables in mcasp_common_hw_param() related to the AFIFO configuration. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 48 +++++++++++++++++++-------------------- sound/soc/davinci/davinci-mcasp.h | 1 + 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index eb46dc69248f..aa063a4e7b0c 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -37,6 +37,8 @@ #include "davinci-pcm.h" #include "davinci-mcasp.h" +#define MCASP_MAX_AFIFO_DEPTH 64 + struct davinci_mcasp_context { u32 txfmtctl; u32 rxfmtctl; @@ -469,9 +471,9 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, int i; u8 tx_ser = 0; u8 rx_ser = 0; - u8 ser; u8 slots = mcasp->tdm_slots; u8 max_active_serializers = (channels + slots - 1) / slots; + u8 active_serializers, numevt; u32 reg; /* Default configuration */ if (mcasp->version != MCASP_VERSION_4) @@ -505,36 +507,34 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, } } - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - ser = tx_ser; - else - ser = rx_ser; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + active_serializers = tx_ser; + numevt = mcasp->txnumevt; + reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; + } else { + active_serializers = rx_ser; + numevt = mcasp->rxnumevt; + reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; + } - if (ser < max_active_serializers) { + if (active_serializers < max_active_serializers) { dev_warn(mcasp->dev, "stream has more channels (%d) than are " - "enabled in mcasp (%d)\n", channels, ser * slots); + "enabled in mcasp (%d)\n", channels, + active_serializers * slots); return -EINVAL; } - if (mcasp->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (mcasp->txnumevt * tx_ser > 64) - mcasp->txnumevt = 1; - - reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; - mcasp_mod_bits(mcasp, reg, tx_ser, NUMDMA_MASK); - mcasp_mod_bits(mcasp, reg, ((mcasp->txnumevt * tx_ser) << 8), - NUMEVT_MASK); - } + /* AFIFO is not in use */ + if (!numevt) + return 0; - if (mcasp->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { - if (mcasp->rxnumevt * rx_ser > 64) - mcasp->rxnumevt = 1; + if (numevt * active_serializers > MCASP_MAX_AFIFO_DEPTH) + numevt = active_serializers; - reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; - mcasp_mod_bits(mcasp, reg, rx_ser, NUMDMA_MASK); - mcasp_mod_bits(mcasp, reg, ((mcasp->rxnumevt * rx_ser) << 8), - NUMEVT_MASK); - } + /* Configure the AFIFO */ + numevt *= active_serializers; + mcasp_mod_bits(mcasp, reg, active_serializers, NUMDMA_MASK); + mcasp_mod_bits(mcasp, reg, NUMEVT(numevt), NUMEVT_MASK); return 0; } diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 8fed757d6087..98fbc451892a 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -283,6 +283,7 @@ */ #define FIFO_ENABLE BIT(16) #define NUMEVT_MASK (0xFF << 8) +#define NUMEVT(x) (((x) & 0xFF) << 8) #define NUMDMA_MASK (0xFF) #endif /* DAVINCI_MCASP_H */ -- cgit v1.2.2 From 5f04c603a52d4951e6f6b2f059049e7c5ee93db7 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 1 Apr 2014 15:55:10 +0300 Subject: ASoC: davinci-mcasp: Configure the AFIFO and DMA burst size at the same place Move the dma_params->fifo_level and dma_data->maxburst configuration to the mcasp_common_hw_param() function where we configure the AFIFO registers. It makes the code regarding to AFIFO and DMA configuration more easy to follow since it is now clear how the AFIFO and how the DMA is going to be configured. Previously this has been done in two functions using a bit different calculation form - which ended up with the same result in both case at the end, but it was confusing. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index aa063a4e7b0c..ab4fa1291795 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -468,6 +468,8 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, int channels) { + struct davinci_pcm_dma_params *dma_params = &mcasp->dma_params[stream]; + struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[stream]; int i; u8 tx_ser = 0; u8 rx_ser = 0; @@ -524,9 +526,14 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, return -EINVAL; } + /* AFIFO is not in use */ - if (!numevt) + if (!numevt) { + /* Configure the burst size for platform drivers */ + dma_params->fifo_level = 0; + dma_data->maxburst = 0; return 0; + } if (numevt * active_serializers > MCASP_MAX_AFIFO_DEPTH) numevt = active_serializers; @@ -536,6 +543,10 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, mcasp_mod_bits(mcasp, reg, active_serializers, NUMDMA_MASK); mcasp_mod_bits(mcasp, reg, NUMEVT(numevt), NUMEVT_MASK); + /* Configure the burst size for platform drivers */ + dma_params->fifo_level = numevt; + dma_data->maxburst = numevt; + return 0; } @@ -607,12 +618,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); struct davinci_pcm_dma_params *dma_params = &mcasp->dma_params[substream->stream]; - struct snd_dmaengine_dai_dma_data *dma_data = - &mcasp->dma_data[substream->stream]; int word_length; - u8 fifo_level; - u8 slots = mcasp->tdm_slots; - u8 active_serializers; int channels = params_channels(params); int ret; @@ -671,21 +677,11 @@ 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) + if (mcasp->version == MCASP_VERSION_2 && !dma_params->fifo_level) dma_params->acnt = 4; else dma_params->acnt = dma_params->data_type; - dma_params->fifo_level = fifo_level; - dma_data->maxburst = fifo_level; - davinci_config_channel_size(mcasp, word_length); return 0; -- cgit v1.2.2 From dd093a0f1962fb71e8852411f03fec7290027a90 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 1 Apr 2014 15:55:11 +0300 Subject: ASoC: davinic-mcasp: Adopt the AFIFO/DMA configuration to the stream (dynamic depth) Configure the AFIFO numevt parameter based on the requested tx/rx_numevt, active serializers and period size in words. In this way McASP can adopt it's (and the DMA) configuration runtime and can pick the most optimal setup which satisfy the parameters. This way we do not need to place any constraint on the stream itself, allowing application greater freedom on how they want to set up ALSA. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index ab4fa1291795..9454d123f4bb 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -466,7 +466,7 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, } static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, - int channels) + int period_words, int channels) { struct davinci_pcm_dma_params *dma_params = &mcasp->dma_params[stream]; struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[stream]; @@ -475,7 +475,7 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, u8 rx_ser = 0; u8 slots = mcasp->tdm_slots; u8 max_active_serializers = (channels + slots - 1) / slots; - u8 active_serializers, numevt; + int active_serializers, numevt, n; u32 reg; /* Default configuration */ if (mcasp->version != MCASP_VERSION_4) @@ -526,7 +526,6 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, return -EINVAL; } - /* AFIFO is not in use */ if (!numevt) { /* Configure the burst size for platform drivers */ @@ -535,11 +534,26 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, return 0; } - if (numevt * active_serializers > MCASP_MAX_AFIFO_DEPTH) + if (period_words % active_serializers) { + dev_err(mcasp->dev, "Invalid combination of period words and " + "active serializers: %d, %d\n", period_words, + active_serializers); + return -EINVAL; + } + + /* + * Calculate the optimal AFIFO depth for platform side: + * The number of words for numevt need to be in steps of active + * serializers. + */ + n = numevt % active_serializers; + if (n) + numevt += (active_serializers - n); + while (period_words % numevt && numevt > 0) + numevt -= active_serializers; + if (numevt <= 0) numevt = active_serializers; - /* Configure the AFIFO */ - numevt *= active_serializers; mcasp_mod_bits(mcasp, reg, active_serializers, NUMDMA_MASK); mcasp_mod_bits(mcasp, reg, NUMEVT(numevt), NUMEVT_MASK); @@ -620,6 +634,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, &mcasp->dma_params[substream->stream]; int word_length; int channels = params_channels(params); + int period_size = params_period_size(params); int ret; /* If mcasp is BCLK master we need to set BCLK divider */ @@ -633,7 +648,8 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); } - ret = mcasp_common_hw_param(mcasp, substream->stream, channels); + ret = mcasp_common_hw_param(mcasp, substream->stream, + period_size * channels, channels); if (ret) return ret; -- cgit v1.2.2 From 33445643c3146fa43af3e9aa1cce08da9fe03157 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 1 Apr 2014 15:55:12 +0300 Subject: ASoC: davinci-mcasp: Fine tune and correct the DMA burst configuration When the AFIFO is not enabled but more than one serializers are used the DMA need to transfer number of words equal to active serializers when a DMA request is generated. When configuring the burst for the DMA avoid using value '1' for the burst since it is going to enable additional logic in the DMA drivers. Burst '1' means that the DMA should send/receive one word per DMA requests. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 9454d123f4bb..196158f2d1c4 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -529,8 +529,19 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, /* AFIFO is not in use */ if (!numevt) { /* Configure the burst size for platform drivers */ - dma_params->fifo_level = 0; - dma_data->maxburst = 0; + if (active_serializers > 1) { + /* + * If more than one serializers are in use we have one + * DMA request to provide data for all serializers. + * For example if three serializers are enabled the DMA + * need to transfer three words per DMA request. + */ + dma_params->fifo_level = active_serializers; + dma_data->maxburst = active_serializers; + } else { + dma_params->fifo_level = 0; + dma_data->maxburst = 0; + } return 0; } @@ -558,6 +569,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, mcasp_mod_bits(mcasp, reg, NUMEVT(numevt), NUMEVT_MASK); /* Configure the burst size for platform drivers */ + if (numevt == 1) + numevt = 0; dma_params->fifo_level = numevt; dma_data->maxburst = numevt; -- cgit v1.2.2 From 6dfa9a4e6aacba70bff24c47871ac9aba3e76020 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 4 Apr 2014 14:31:42 +0300 Subject: ASoC: davinci-mcasp: Format data delay configuration enhancement Use intermediate variable for the data delay needed for the specific format and write the register after the format configuration at once. This will help to control the number of lines as support for more formats going to be added. Also fixes a case when we switch between two formats with different delay requirements. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 196158f2d1c4..f0c98653bfe7 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -271,6 +271,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); int ret = 0; + u32 data_delay; pm_runtime_get_sync(mcasp->dev); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -278,18 +279,25 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, case SND_SOC_DAIFMT_AC97: mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); + + /* No delay after FS */ + data_delay = 0; break; default: /* configure a full-word SYNC pulse (LRCLK) */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); - /* make 1st data bit occur one ACLK cycle after the frame sync */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(1)); - mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(1)); + /* 1st data bit occur one ACLK cycle after the frame sync */ + data_delay = 1; break; } + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(data_delay), + FSXDLY(3)); + mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(data_delay), + FSRDLY(3)); + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* codec is clock and frame slave */ -- cgit v1.2.2 From 188edc59c297fcd971d6a4ae5f5f5dacff7b315b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 4 Apr 2014 14:31:43 +0300 Subject: ASoC: davinci-mcasp: Support for DSP_A format DSP_A is like DSP_B mode but with one bit delay after the FS. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index f0c98653bfe7..58b6d47cc8f8 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -275,6 +275,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, pm_runtime_get_sync(mcasp->dev); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); + mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); + + /* 1st data bit occur one ACLK cycle after the frame sync */ + data_delay = 1; + break; case SND_SOC_DAIFMT_DSP_B: case SND_SOC_DAIFMT_AC97: mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); -- cgit v1.2.2 From 83f12503bd1fb18d3fd460871660b34faf671918 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 4 Apr 2014 14:31:44 +0300 Subject: ASoC: davinci-mcasp: Move the FS polarity change out from the switch case FS polarity can be either rising or falling edge in McASP. Instead of accessing the registers in every switch/case set a flag and write the registers after the switch for the invert configuration. This change will help when adding support for more formats also. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 58b6d47cc8f8..113e74c9479f 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -272,6 +272,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); int ret = 0; u32 data_delay; + bool fs_pol_rising; pm_runtime_get_sync(mcasp->dev); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -351,39 +352,39 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_IB_NF: mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); + fs_pol_rising = true; break; case SND_SOC_DAIFMT_NB_IF: mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); + fs_pol_rising = false; break; case SND_SOC_DAIFMT_IB_IF: mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); + fs_pol_rising = false; break; case SND_SOC_DAIFMT_NB_NF: mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); + fs_pol_rising = true; break; default: ret = -EINVAL; - break; + goto out; + } + + if (fs_pol_rising) { + mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); + mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); + } else { + mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); + mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); } out: pm_runtime_put_sync(mcasp->dev); -- cgit v1.2.2 From ffd950f75dd71f13194b5d5c8ec67926a1996102 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 4 Apr 2014 14:31:45 +0300 Subject: ASoC: davinci-mcasp: Add support for I2S format The FS needs to be inverted in McASP compared to other supported formats. Use a flag to indicate if the FS needs to be inverted. At the same time fail when non supported format is asked since the default case was anyways configuring McASP to a not valid format. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 113e74c9479f..d4d640004bed 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -273,6 +273,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, int ret = 0; u32 data_delay; bool fs_pol_rising; + bool inv_fs = false; pm_runtime_get_sync(mcasp->dev); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -291,14 +292,19 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* No delay after FS */ data_delay = 0; break; - default: + case SND_SOC_DAIFMT_I2S: /* configure a full-word SYNC pulse (LRCLK) */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); /* 1st data bit occur one ACLK cycle after the frame sync */ data_delay = 1; + /* FS need to be inverted */ + inv_fs = true; break; + default: + ret = -EINVAL; + goto out; } mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(data_delay), @@ -379,6 +385,9 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, goto out; } + if (inv_fs) + fs_pol_rising = !fs_pol_rising; + if (fs_pol_rising) { mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); -- cgit v1.2.2 From 423761e0cab39c98f0fd9387ea44b98c2a4ca6fa Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 4 Apr 2014 14:31:46 +0300 Subject: ASoC: davinci-mcasp: Support for LEFT_J format Configuration for LEFT_J format. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index d4d640004bed..2b6722024fbd 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -302,6 +302,13 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* FS need to be inverted */ inv_fs = true; break; + case SND_SOC_DAIFMT_LEFT_J: + /* configure a full-word SYNC pulse (LRCLK) */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); + mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); + /* No delay after FS */ + data_delay = 0; + break; default: ret = -EINVAL; goto out; -- cgit v1.2.2 From 3c25f916d378da6f06874abfc5c18e5a40e2d8c0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 4 Apr 2014 14:31:47 +0300 Subject: ASoC: davinci-mcasp: Remove excess empty lines from davinci_mcasp_set_dai_fmt() To make the code look uniform. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 2b6722024fbd..8007fcf428d9 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -280,7 +280,6 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, case SND_SOC_DAIFMT_DSP_A: mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); - /* 1st data bit occur one ACLK cycle after the frame sync */ data_delay = 1; break; @@ -288,7 +287,6 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, case SND_SOC_DAIFMT_AC97: mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); - /* No delay after FS */ data_delay = 0; break; @@ -296,7 +294,6 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* configure a full-word SYNC pulse (LRCLK) */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); - /* 1st data bit occur one ACLK cycle after the frame sync */ data_delay = 1; /* FS need to be inverted */ @@ -356,7 +353,6 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); mcasp->bclk_master = 0; break; - default: ret = -EINVAL; goto out; @@ -368,25 +364,21 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); fs_pol_rising = true; break; - case SND_SOC_DAIFMT_NB_IF: mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); fs_pol_rising = false; break; - case SND_SOC_DAIFMT_IB_IF: mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); fs_pol_rising = false; break; - case SND_SOC_DAIFMT_NB_NF: mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); fs_pol_rising = true; break; - default: ret = -EINVAL; goto out; -- cgit v1.2.2 From 74a1672068c7f52f1525a5fca17cdc1ed6961239 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:30 +0100 Subject: ASoC: ams-delta: 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/omap/ams-delta.c | 64 +++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 56a5219c0a00..2ac0a0c3b570 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -38,7 +38,6 @@ #include "omap-mcbsp.h" #include "../codecs/cx20442.h" - /* Board specific DAPM widgets */ static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = { /* Handset */ @@ -90,17 +89,23 @@ static const unsigned short ams_delta_audio_mode_pins[] = { static unsigned short ams_delta_audio_agc; +/* + * Used for passing a codec structure pointer + * from the board initialization code to the tty line discipline. + */ +static struct snd_soc_codec *cx20442_codec; + static int ams_delta_set_audio_mode(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; struct soc_enum *control = (struct soc_enum *)kcontrol->private_value; unsigned short pins; int pin, changed = 0; /* Refuse any mode changes if we are not able to control the codec. */ - if (!codec->hw_write) + if (!cx20442_codec->hw_write) return -EUNATCH; if (ucontrol->value.enumerated.item[0] >= control->items) @@ -166,8 +171,8 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, static int ams_delta_get_audio_mode(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; unsigned short pins, mode; pins = ((snd_soc_dapm_get_pin_status(dapm, "Mouthpiece") << @@ -270,12 +275,6 @@ static void cx81801_timeout(unsigned long data) ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0); } -/* - * Used for passing a codec structure pointer - * from the board initialization code to the tty line discipline. - */ -static struct snd_soc_codec *cx20442_codec; - /* Line discipline .open() */ static int cx81801_open(struct tty_struct *tty) { @@ -302,7 +301,7 @@ static int cx81801_open(struct tty_struct *tty) static void cx81801_close(struct tty_struct *tty) { struct snd_soc_codec *codec = tty->disc_data; - struct snd_soc_dapm_context *dapm = &codec->dapm; + struct snd_soc_dapm_context *dapm = &codec->card->dapm; del_timer_sync(&cx81801_timer); @@ -475,15 +474,14 @@ static void ams_delta_shutdown(struct snd_pcm_substream *substream) static int ams_delta_cx20442_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_dai *codec_dai = rtd->codec_dai; struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = &card->dapm; int ret; /* Codec is ready, now add/activate board specific controls */ /* Store a pointer to the codec structure for tty ldisc use */ - cx20442_codec = codec; + cx20442_codec = rtd->codec; /* Set up digital mute if not provided by the codec */ if (!codec_dai->driver->ops) { @@ -520,25 +518,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) return 0; } - /* Add board specific DAPM widgets and routes */ - ret = snd_soc_dapm_new_controls(dapm, ams_delta_dapm_widgets, - ARRAY_SIZE(ams_delta_dapm_widgets)); - if (ret) { - dev_warn(card->dev, - "Failed to register DAPM controls, " - "will continue without any.\n"); - return 0; - } - - ret = snd_soc_dapm_add_routes(dapm, ams_delta_audio_map, - ARRAY_SIZE(ams_delta_audio_map)); - if (ret) { - dev_warn(card->dev, - "Failed to set up DAPM routes, " - "will continue with codec default map.\n"); - return 0; - } - /* Set up initial pin constellation */ snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); snd_soc_dapm_enable_pin(dapm, "Earpiece"); @@ -547,14 +526,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_disable_pin(dapm, "AGCIN"); snd_soc_dapm_disable_pin(dapm, "AGCOUT"); - /* Add virtual switch */ - ret = snd_soc_add_codec_controls(codec, ams_delta_audio_controls, - ARRAY_SIZE(ams_delta_audio_controls)); - if (ret) - dev_warn(card->dev, - "Failed to register audio mode control, " - "will continue without it.\n"); - return 0; } @@ -576,6 +547,13 @@ static struct snd_soc_card ams_delta_audio_card = { .owner = THIS_MODULE, .dai_link = &ams_delta_dai_link, .num_links = 1, + + .controls = ams_delta_audio_controls, + .num_controls = ARRAY_SIZE(ams_delta_audio_controls), + .dapm_widgets = ams_delta_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ams_delta_dapm_widgets), + .dapm_routes = ams_delta_audio_map, + .num_dapm_routes = ARRAY_SIZE(ams_delta_audio_map), }; /* Module init/exit */ -- cgit v1.2.2 From 81fc5dd4d19faa3dda886910cb8fdad639fa828b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:33 +0100 Subject: ASoC: omap: rx51: Convert to table based control and DAPM 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/omap/rx51.c | 47 +++++++---------------------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 7fb3d4b10370..2b4641123142 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -237,9 +237,6 @@ static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event), SND_SOC_DAPM_MIC("HS Mic", NULL), SND_SOC_DAPM_LINE("FM Transmitter", NULL), -}; - -static const struct snd_soc_dapm_widget aic34_dapm_widgetsb[] = { SND_SOC_DAPM_SPK("Earphone", NULL), }; @@ -253,9 +250,7 @@ static const struct snd_soc_dapm_route audio_map[] = { {"DMic Rate 64", NULL, "Mic Bias"}, {"Mic Bias", NULL, "DMic"}, -}; -static const struct snd_soc_dapm_route audio_mapb[] = { {"b LINE2R", NULL, "MONO_LOUT"}, {"Earphone", NULL, "b HPLOUT"}, @@ -281,9 +276,6 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = { SOC_ENUM_EXT("Jack Function", rx51_enum[2], rx51_get_jack, rx51_set_jack), SOC_DAPM_PIN_SWITCH("FM Transmitter"), -}; - -static const struct snd_kcontrol_new aic34_rx51_controlsb[] = { SOC_DAPM_PIN_SWITCH("Earphone"), }; @@ -298,19 +290,6 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "MIC3R"); snd_soc_dapm_nc_pin(dapm, "LINE1R"); - /* Add RX-51 specific controls */ - err = snd_soc_add_card_controls(rtd->card, aic34_rx51_controls, - ARRAY_SIZE(aic34_rx51_controls)); - if (err < 0) - return err; - - /* Add RX-51 specific widgets */ - snd_soc_dapm_new_controls(dapm, aic34_dapm_widgets, - ARRAY_SIZE(aic34_dapm_widgets)); - - /* Set up RX-51 specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - err = tpa6130a2_add_controls(codec); if (err < 0) return err; @@ -333,24 +312,6 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) return err; } -static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm) -{ - int err; - - err = snd_soc_add_card_controls(dapm->card, aic34_rx51_controlsb, - ARRAY_SIZE(aic34_rx51_controlsb)); - if (err < 0) - return err; - - err = snd_soc_dapm_new_controls(dapm, aic34_dapm_widgetsb, - ARRAY_SIZE(aic34_dapm_widgetsb)); - if (err < 0) - return 0; - - return snd_soc_dapm_add_routes(dapm, audio_mapb, - ARRAY_SIZE(audio_mapb)); -} - /* Digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link rx51_dai[] = { { @@ -371,7 +332,6 @@ static struct snd_soc_aux_dev rx51_aux_dev[] = { { .name = "TLV320AIC34b", .codec_name = "tlv320aic3x-codec.2-0019", - .init = rx51_aic34b_init, }, }; @@ -392,6 +352,13 @@ static struct snd_soc_card rx51_sound_card = { .num_aux_devs = ARRAY_SIZE(rx51_aux_dev), .codec_conf = rx51_codec_conf, .num_configs = ARRAY_SIZE(rx51_codec_conf), + + .controls = aic34_rx51_controls, + .num_controls = ARRAY_SIZE(aic34_rx51_controls), + .dapm_widgets = aic34_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(aic34_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *rx51_snd_device; -- cgit v1.2.2 From b2e69054ea1a36f2c1ace15a55240937aa091cba Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:34 +0100 Subject: ASoC: omap3pandora: Convert to table based DAPM 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/omap/omap3pandora.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index cf604a2faa18..02181bb70400 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c @@ -121,7 +121,7 @@ static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w, * |A| <~~clk~~+ * |P| <--- TWL4030 <--------- Line In and MICs */ -static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { +static const struct snd_soc_dapm_widget omap3pandora_dapm_widgets[] = { SND_SOC_DAPM_DAC_E("PCM DAC", "HiFi Playback", SND_SOC_NOPM, 0, 0, omap3pandora_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), @@ -130,22 +130,18 @@ static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_LINE("Line Out", NULL), -}; -static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = { SND_SOC_DAPM_MIC("Mic (internal)", NULL), SND_SOC_DAPM_MIC("Mic (external)", NULL), SND_SOC_DAPM_LINE("Line In", NULL), }; -static const struct snd_soc_dapm_route omap3pandora_out_map[] = { +static const struct snd_soc_dapm_route omap3pandora_map[] = { {"PCM DAC", NULL, "APLL Enable"}, {"Headphone Amplifier", NULL, "PCM DAC"}, {"Line Out", NULL, "PCM DAC"}, {"Headphone Jack", NULL, "Headphone Amplifier"}, -}; -static const struct snd_soc_dapm_route omap3pandora_in_map[] = { {"AUXL", NULL, "Line In"}, {"AUXR", NULL, "Line In"}, @@ -160,7 +156,6 @@ static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; /* All TWL4030 output pins are floating */ snd_soc_dapm_nc_pin(dapm, "EARPIECE"); @@ -174,20 +169,13 @@ static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "HFR"); snd_soc_dapm_nc_pin(dapm, "VIBRA"); - ret = snd_soc_dapm_new_controls(dapm, omap3pandora_out_dapm_widgets, - ARRAY_SIZE(omap3pandora_out_dapm_widgets)); - if (ret < 0) - return ret; - - return snd_soc_dapm_add_routes(dapm, omap3pandora_out_map, - ARRAY_SIZE(omap3pandora_out_map)); + return 0; } static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; /* Not comnnected */ snd_soc_dapm_nc_pin(dapm, "HSMIC"); @@ -195,13 +183,7 @@ static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "DIGIMIC0"); snd_soc_dapm_nc_pin(dapm, "DIGIMIC1"); - ret = snd_soc_dapm_new_controls(dapm, omap3pandora_in_dapm_widgets, - ARRAY_SIZE(omap3pandora_in_dapm_widgets)); - if (ret < 0) - return ret; - - return snd_soc_dapm_add_routes(dapm, omap3pandora_in_map, - ARRAY_SIZE(omap3pandora_in_map)); + return 0; } static struct snd_soc_ops omap3pandora_ops = { @@ -241,6 +223,11 @@ static struct snd_soc_card snd_soc_card_omap3pandora = { .owner = THIS_MODULE, .dai_link = omap3pandora_dai, .num_links = ARRAY_SIZE(omap3pandora_dai), + + .dapm_widgets = omap3pandora_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(omap3pandora_dapm_widgets), + .dapm_routes = omap3pandora_map, + .num_dapm_routes = ARRAY_SIZE(omap3pandora_map), }; static struct platform_device *omap3pandora_snd_device; -- cgit v1.2.2 From 40448e5e977b59a4753fce3619f537b63fcedc02 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 4 Apr 2014 15:56:30 +0300 Subject: ASoC: davinci-mcasp: Do not touch 0x04 register above McASP_VERSION_2 This register is not defined in TI81xx and on AM335x/AM437x it is the SYSCONFIG register which should not be touched by drivers since it is related to PM and handled by the generic PM code. This register write was there since the first time the davinci-mcasp driver was appeared in the kernel. The reason why it did not caused any issues on AM335x/AM437x is that it sets bit 1 in SYSCONFIG register which in turn will enable the smart-idle mode. This is the default mode and this is the mode McASP should be in also when in use. On TI81xx the register is not defined. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 8007fcf428d9..af92d3e8671d 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -502,7 +502,7 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, int active_serializers, numevt, n; u32 reg; /* Default configuration */ - if (mcasp->version != MCASP_VERSION_4) + if (mcasp->version < MCASP_VERSION_3) mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); /* All PINS as McASP */ -- cgit v1.2.2 From a1253ef6d3fabfe60838cd417b0624ab53df285e Mon Sep 17 00:00:00 2001 From: Brian Austin Date: Tue, 15 Apr 2014 15:49:33 -0500 Subject: ASoC: cs42l51: split i2c from codec driver This patch removes the i2c bus code from the codec driver and creates seperate i2c driver. Signed-off-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 +++- sound/soc/codecs/Makefile | 2 ++ sound/soc/codecs/cs42l51-i2c.c | 59 +++++++++++++++++++++++++++++++++ sound/soc/codecs/cs42l51.c | 75 +++++++++++------------------------------- sound/soc/codecs/cs42l51.h | 5 +++ 5 files changed, 90 insertions(+), 57 deletions(-) create mode 100644 sound/soc/codecs/cs42l51-i2c.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f0e840137887..5279ef41597d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -39,7 +39,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_ALC5623 if I2C select SND_SOC_ALC5632 if I2C select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC - select SND_SOC_CS42L51 if I2C + select SND_SOC_CS42L51_I2C if I2C select SND_SOC_CS42L52 if I2C select SND_SOC_CS42L73 if I2C select SND_SOC_CS4270 if I2C @@ -280,6 +280,10 @@ config SND_SOC_CQ0093VC config SND_SOC_CS42L51 tristate +config SND_SOC_CS42L51_I2C + tristate + select SND_SOC_CS42L51 + config SND_SOC_CS42L52 tristate "Cirrus Logic CS42L52 CODEC" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 3c4d275d064b..e06f10032344 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -26,6 +26,7 @@ snd-soc-ak5386-objs := ak5386.o snd-soc-arizona-objs := arizona.o snd-soc-cq93vc-objs := cq93vc.o snd-soc-cs42l51-objs := cs42l51.o +snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o snd-soc-cs42l52-objs := cs42l52.o snd-soc-cs42l73-objs := cs42l73.o snd-soc-cs4270-objs := cs4270.o @@ -177,6 +178,7 @@ obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o +obj-$(CONFIG_SND_SOC_CS42L51_I2C) += snd-soc-cs42l51-i2c.o 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 diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c new file mode 100644 index 000000000000..cee51ae177c1 --- /dev/null +++ b/sound/soc/codecs/cs42l51-i2c.c @@ -0,0 +1,59 @@ +/* + * cs42l56.c -- CS42L51 ALSA SoC I2C audio driver + * + * Copyright 2014 CirrusLogic, Inc. + * + * Author: Brian Austin + * + * 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 "cs42l51.h" + +static struct i2c_device_id cs42l51_i2c_id[] = { + {"cs42l51", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_id); + +static int cs42l51_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap_config config; + + config = cs42l51_regmap; + config.val_bits = 8; + config.reg_bits = 8; + + return cs42l51_probe(&i2c->dev, devm_regmap_init_i2c(i2c, &config)); +} + +static int cs42l51_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + + return 0; +} + +static struct i2c_driver cs42l51_i2c_driver = { + .driver = { + .name = "cs42l51", + .owner = THIS_MODULE, + }, + .probe = cs42l51_i2c_probe, + .remove = cs42l51_i2c_remove, + .id_table = cs42l51_i2c_id, +}; + +module_i2c_driver(cs42l51_i2c_driver); + +MODULE_DESCRIPTION("ASoC CS42L51 I2C Driver"); +MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 6c0da2baa154..46abd3e02f14 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include "cs42l51.h" @@ -483,7 +482,7 @@ static struct snd_soc_dai_driver cs42l51_dai = { .ops = &cs42l51_dai_ops, }; -static int cs42l51_probe(struct snd_soc_codec *codec) +static int cs42l51_codec_probe(struct snd_soc_codec *codec) { int ret, reg; @@ -504,7 +503,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { - .probe = cs42l51_probe, + .probe = cs42l51_codec_probe, .controls = cs42l51_snd_controls, .num_controls = ARRAY_SIZE(cs42l51_snd_controls), @@ -514,91 +513,55 @@ 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, - +const struct regmap_config cs42l51_regmap = { .max_register = CS42L51_CHARGE_FREQ, .cache_type = REGCACHE_RBTREE, }; +EXPORT_SYMBOL_GPL(cs42l51_regmap); -static int cs42l51_i2c_probe(struct i2c_client *i2c_client, - const struct i2c_device_id *id) +int cs42l51_probe(struct device *dev, struct regmap *regmap) { 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; - } + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + cs42l51 = devm_kzalloc(dev, sizeof(struct cs42l51_private), + GFP_KERNEL); + if (!cs42l51) + return -ENOMEM; + + dev_set_drvdata(dev, cs42l51); /* Verify that we have a CS42L51 */ ret = regmap_read(regmap, CS42L51_CHIP_REV_ID, &val); if (ret < 0) { - dev_err(&i2c_client->dev, "failed to read I2C\n"); + dev_err(dev, "failed to read I2C\n"); goto error; } 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); + dev_err(dev, "Invalid chip id: %x\n", val); ret = -ENODEV; goto error; } + dev_info(dev, "Cirrus Logic CS42L51, Revision: %02X\n", val & 0xFF); - dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", - val & 7); - - cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), - GFP_KERNEL); - if (!cs42l51) - return -ENOMEM; - - i2c_set_clientdata(i2c_client, cs42l51); - - ret = snd_soc_register_codec(&i2c_client->dev, + ret = snd_soc_register_codec(dev, &soc_codec_device_cs42l51, &cs42l51_dai, 1); error: return ret; } - -static int cs42l51_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id cs42l51_id[] = { - {"cs42l51", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, cs42l51_id); +EXPORT_SYMBOL_GPL(cs42l51_probe); 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, - .remove = cs42l51_i2c_remove, -}; - -module_i2c_driver(cs42l51_i2c_driver); - MODULE_AUTHOR("Arnaud Patard "); MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h index 2beeb171db4b..641ef18435b3 100644 --- a/sound/soc/codecs/cs42l51.h +++ b/sound/soc/codecs/cs42l51.h @@ -18,6 +18,11 @@ #ifndef _CS42L51_H #define _CS42L51_H +struct device; + +extern const struct regmap_config cs42l51_regmap; +int cs42l51_probe(struct device *dev, struct regmap *regmap); + #define CS42L51_CHIP_ID 0x1B #define CS42L51_CHIP_REV_A 0x00 #define CS42L51_CHIP_REV_B 0x01 -- cgit v1.2.2 From 1025c05f727be33e065bb502a223637681c7991d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 17 Apr 2014 16:35:43 +0800 Subject: ASoC: cs42l51: Fix mask for REVID The REVID mask was changed by commit a1253ef6d3fa "ASoC: cs42l51: split i2c from codec driver". Fix it. Signed-off-by: Axel Lin Acked-by: Brian Austin Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l51.c | 3 ++- sound/soc/codecs/cs42l51.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 46abd3e02f14..6aa69e5aaa3f 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -548,7 +548,8 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap) ret = -ENODEV; goto error; } - dev_info(dev, "Cirrus Logic CS42L51, Revision: %02X\n", val & 0xFF); + dev_info(dev, "Cirrus Logic CS42L51, Revision: %02X\n", + val & CS42L51_CHIP_REV_MASK); ret = snd_soc_register_codec(dev, &soc_codec_device_cs42l51, &cs42l51_dai, 1); diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h index 641ef18435b3..8c55bf384bc6 100644 --- a/sound/soc/codecs/cs42l51.h +++ b/sound/soc/codecs/cs42l51.h @@ -26,6 +26,7 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap); #define CS42L51_CHIP_ID 0x1B #define CS42L51_CHIP_REV_A 0x00 #define CS42L51_CHIP_REV_B 0x01 +#define CS42L51_CHIP_REV_MASK 0x07 #define CS42L51_CHIP_REV_ID 0x01 #define CS42L51_MK_CHIP_REV(a, b) ((a)<<3|(b)) -- cgit v1.2.2 From 8931bf6208776292b1b888dd8534229f63e2eaa2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 16 Apr 2014 15:46:11 +0300 Subject: ASoC: Add resource managed snd_soc_register_platform() Simplify error handling and remove repetitive (and rarely executed) code for unregistration by providing a devm_snd_soc_register_platform() platform. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- include/sound/soc.h | 2 ++ sound/soc/soc-devres.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index 0b83168d8ff4..34c34d6e095c 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -377,6 +377,8 @@ int snd_soc_resume(struct device *dev); int snd_soc_poweroff(struct device *dev); int snd_soc_register_platform(struct device *dev, const struct snd_soc_platform_driver *platform_drv); +int devm_snd_soc_register_platform(struct device *dev, + const struct snd_soc_platform_driver *platform_drv); void snd_soc_unregister_platform(struct device *dev); int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, const struct snd_soc_platform_driver *platform_drv); diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c index 7ac745df1412..e94aa0277250 100644 --- a/sound/soc/soc-devres.c +++ b/sound/soc/soc-devres.c @@ -52,6 +52,40 @@ int devm_snd_soc_register_component(struct device *dev, } EXPORT_SYMBOL_GPL(devm_snd_soc_register_component); +static void devm_platform_release(struct device *dev, void *res) +{ + snd_soc_unregister_platform(*(struct device **)res); +} + +/** + * devm_snd_soc_register_platform - resource managed platform registration + * @dev: Device used to manage platform + * @platform: platform to register + * + * Register a platform driver with automatic unregistration when the device is + * unregistered. + */ +int devm_snd_soc_register_platform(struct device *dev, + const struct snd_soc_platform_driver *platform_drv) +{ + struct device **ptr; + int ret; + + ptr = devres_alloc(devm_platform_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = snd_soc_register_platform(dev, platform_drv); + if (ret == 0) { + *ptr = dev; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ret; +} + static void devm_card_release(struct device *dev, void *res) { snd_soc_unregister_card(*(struct snd_soc_card **)res); -- cgit v1.2.2 From fe7b5868809a89a7316eef064f0bb7796aa8c225 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 16 Apr 2014 15:46:12 +0300 Subject: ASoC: omap-pcm: Support for binding the platform driver to dai devices With the new calls it is going to be possible to bind the platform driver to a dai device which makes it easier for us in a long run to handle DT boots, and opens the possibility to move machine driver to generic simple card. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/omap/omap-pcm.c | 6 ++++++ sound/soc/omap/omap-pcm.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 sound/soc/omap/omap-pcm.h diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 07b8b7bc9d20..c3711b582d5f 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -232,6 +232,12 @@ static struct snd_soc_platform_driver omap_soc_platform = { .pcm_free = omap_pcm_free_dma_buffers, }; +int omap_pcm_platform_register(struct device *dev) +{ + return devm_snd_soc_register_platform(dev, &omap_soc_platform); +} +EXPORT_SYMBOL_GPL(omap_pcm_platform_register); + static int omap_pcm_probe(struct platform_device *pdev) { return snd_soc_register_platform(&pdev->dev, diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h new file mode 100644 index 000000000000..c1d2f31d71e9 --- /dev/null +++ b/sound/soc/omap/omap-pcm.h @@ -0,0 +1,30 @@ +/* + * omap-pcm.h - OMAP PCM driver + * + * Copyright (C) 2014 Texas Instruments, Inc. + * + * Author: Peter Ujfalusi + * + * 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 __OMAP_PCM_H__ +#define __OMAP_PCM_H__ + +#if IS_ENABLED(CONFIG_SND_OMAP_SOC) +int omap_pcm_platform_register(struct device *dev); +#else +static inline int omap_pcm_platform_register(struct device *dev) +{ + return 0; +} +#endif /* CONFIG_SND_OMAP_SOC */ + +#endif /* __OMAP_PCM_H__ */ -- cgit v1.2.2 From d5c6c59a9d46113aebfd71f995b9e6e9af6a12b8 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 16 Apr 2014 15:46:20 +0300 Subject: ASoC: davinci-mcasp: Update MCASP_VERSION_4 platform driver registration Version 4 of McASP is using omap-pcm as platform driver and the omap-pcm platform need to be registered using the cpu dai's device. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index af92d3e8671d..d505fe7292a4 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -36,6 +36,7 @@ #include "davinci-pcm.h" #include "davinci-mcasp.h" +#include "../omap/omap-pcm.h" #define MCASP_MAX_AFIFO_DEPTH 64 @@ -1220,12 +1221,25 @@ static int davinci_mcasp_probe(struct platform_device *pdev) if (ret != 0) goto err_release_clk; - if (mcasp->version != MCASP_VERSION_4) { + switch (mcasp->version) { + case MCASP_VERSION_1: + case MCASP_VERSION_2: + case MCASP_VERSION_3: ret = davinci_soc_platform_register(&pdev->dev); - if (ret) { - dev_err(&pdev->dev, "register PCM failed: %d\n", ret); - goto err_unregister_component; - } + break; + case MCASP_VERSION_4: + ret = omap_pcm_platform_register(&pdev->dev); + break; + default: + dev_err(&pdev->dev, "Invalid McASP version: %d\n", + mcasp->version); + ret = -EINVAL; + break; + } + + if (ret) { + dev_err(&pdev->dev, "register PCM failed: %d\n", ret); + goto err_unregister_component; } return 0; @@ -1243,8 +1257,19 @@ static int davinci_mcasp_remove(struct platform_device *pdev) struct davinci_mcasp *mcasp = dev_get_drvdata(&pdev->dev); snd_soc_unregister_component(&pdev->dev); - if (mcasp->version != MCASP_VERSION_4) + + switch (mcasp->version) { + case MCASP_VERSION_1: + case MCASP_VERSION_2: + case MCASP_VERSION_3: davinci_soc_platform_unregister(&pdev->dev); + break; + case MCASP_VERSION_4: + /* Using the resource managed omap-pcm as platform driver */ + break; + default: + break; + } pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); -- cgit v1.2.2 From 70e7a023cc9e9afafe503fa5533323ffe7091604 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 22 Apr 2014 14:03:12 +0300 Subject: ASoC: davinci-pcm: Convert to use devm_snd_soc_register_platform() Remove the cleanup code related to the platform from the DAI drivers at the same time to avoid breakage. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-i2s.c | 1 - sound/soc/davinci/davinci-mcasp.c | 15 --------------- sound/soc/davinci/davinci-pcm.c | 8 +------- sound/soc/davinci/davinci-pcm.h | 4 ---- sound/soc/davinci/davinci-vcif.c | 1 - 5 files changed, 1 insertion(+), 28 deletions(-) diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index ebe82947bab3..7682af31d6e6 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -757,7 +757,6 @@ static int davinci_i2s_remove(struct platform_device *pdev) struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); snd_soc_unregister_component(&pdev->dev); - davinci_soc_platform_unregister(&pdev->dev); clk_disable(dev->clk); clk_put(dev->clk); diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index d505fe7292a4..44a03840f76c 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -1254,23 +1254,8 @@ err_release_clk: static int davinci_mcasp_remove(struct platform_device *pdev) { - struct davinci_mcasp *mcasp = dev_get_drvdata(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); - switch (mcasp->version) { - case MCASP_VERSION_1: - case MCASP_VERSION_2: - case MCASP_VERSION_3: - davinci_soc_platform_unregister(&pdev->dev); - break; - case MCASP_VERSION_4: - /* Using the resource managed omap-pcm as platform driver */ - break; - default: - break; - } - pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 14145cdf8a11..7809e9d935fc 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -852,16 +852,10 @@ static struct snd_soc_platform_driver davinci_soc_platform = { int davinci_soc_platform_register(struct device *dev) { - return snd_soc_register_platform(dev, &davinci_soc_platform); + return devm_snd_soc_register_platform(dev, &davinci_soc_platform); } EXPORT_SYM