From b87704cef258a4f44ab1386a70b7628ec3cefd36 Mon Sep 17 00:00:00 2001 From: Rongjun Ying Date: Thu, 20 Mar 2014 15:46:19 +0800 Subject: [PATCH 01/25] ASoC: sirf: Move the tx rx enable from port to codec, that will not need register sharing The port driver only used to register component and dmaengine pcm. Signed-off-by: Rongjun Ying Signed-off-by: Mark Brown --- sound/soc/codecs/sirf-audio-codec.c | 74 ++++++++++++++++--- sound/soc/codecs/sirf-audio-codec.h | 50 +++++++++++++ sound/soc/sirf/sirf-audio-port.c | 107 ---------------------------- sound/soc/sirf/sirf-audio-port.h | 62 ---------------- 4 files changed, 116 insertions(+), 177 deletions(-) delete mode 100644 sound/soc/sirf/sirf-audio-port.h diff --git a/sound/soc/codecs/sirf-audio-codec.c b/sound/soc/codecs/sirf-audio-codec.c index 58e7c1f23771..c5177bc5df82 100644 --- a/sound/soc/codecs/sirf-audio-codec.c +++ b/sound/soc/codecs/sirf-audio-codec.c @@ -279,13 +279,63 @@ static const struct snd_soc_dapm_route sirf_audio_codec_map[] = { {"Mic input mode mux", "Differential", "MICIN1"}, }; +static void sirf_audio_codec_tx_enable(struct sirf_audio_codec *sirf_audio_codec) +{ + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET); + regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_INT_MSK, 0); + regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, IC_TX_ENABLE); +} + +static void sirf_audio_codec_tx_disable(struct sirf_audio_codec *sirf_audio_codec) +{ + regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_TXFIFO_OP, 0); + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_PORT_IC_CODEC_TX_CTRL, IC_TX_ENABLE, ~IC_TX_ENABLE); +} + +static void sirf_audio_codec_rx_enable(struct sirf_audio_codec *sirf_audio_codec, + int channels) +{ + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_RESET, AUDIO_FIFO_RESET); + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_RESET, ~AUDIO_FIFO_RESET); + regmap_write(sirf_audio_codec->regmap, + AUDIO_PORT_IC_RXFIFO_INT_MSK, 0); + regmap_write(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, 0); + regmap_update_bits(sirf_audio_codec->regmap, AUDIO_PORT_IC_RXFIFO_OP, + AUDIO_FIFO_START, AUDIO_FIFO_START); + if (channels == 1) + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_MONO, IC_RX_ENABLE_MONO); + else + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, IC_RX_ENABLE_STEREO); +} + +static void sirf_audio_codec_rx_disable(struct sirf_audio_codec *sirf_audio_codec) +{ + regmap_update_bits(sirf_audio_codec->regmap, + AUDIO_PORT_IC_CODEC_RX_CTRL, + IC_RX_ENABLE_STEREO, ~IC_RX_ENABLE_STEREO); +} + 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; + struct sirf_audio_codec *sirf_audio_codec = snd_soc_codec_get_drvdata(codec); + int playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; /* * This is a workaround, When stop playback, @@ -295,20 +345,28 @@ static int sirf_audio_codec_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (playback) { + snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, + IC_HSLEN | IC_HSREN, 0); + sirf_audio_codec_tx_disable(sirf_audio_codec); + } else + sirf_audio_codec_rx_disable(sirf_audio_codec); break; case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (playback) - val = IC_HSLEN | IC_HSREN; + if (playback) { + sirf_audio_codec_tx_enable(sirf_audio_codec); + snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, + IC_HSLEN | IC_HSREN, IC_HSLEN | IC_HSREN); + } else + sirf_audio_codec_rx_enable(sirf_audio_codec, + substream->runtime->channels); break; default: return -EINVAL; } - if (playback) - snd_soc_update_bits(codec, AUDIO_IC_CODEC_CTRL0, - IC_HSLEN | IC_HSREN, val); return 0; } @@ -392,7 +450,7 @@ 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, + .max_register = AUDIO_PORT_IC_RXFIFO_INT_MSK, .cache_type = REGCACHE_NONE, }; diff --git a/sound/soc/codecs/sirf-audio-codec.h b/sound/soc/codecs/sirf-audio-codec.h index d4c187b8e54a..ba1adc03839f 100644 --- a/sound/soc/codecs/sirf-audio-codec.h +++ b/sound/soc/codecs/sirf-audio-codec.h @@ -72,4 +72,54 @@ #define IC_RXPGAR 0x7B #define IC_RXPGAL 0x7B +#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_CODEC_H*/ diff --git a/sound/soc/sirf/sirf-audio-port.c b/sound/soc/sirf/sirf-audio-port.c index b04a53f2b4f6..b4afa31b2bc1 100644 --- a/sound/soc/sirf/sirf-audio-port.c +++ b/sound/soc/sirf/sirf-audio-port.c @@ -6,60 +6,15 @@ * 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) { @@ -69,41 +24,6 @@ static int sirf_audio_port_dai_probe(struct snd_soc_dai *dai) 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", @@ -120,49 +40,22 @@ static struct snd_soc_dai_driver sirf_audio_port_dai = { .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) diff --git a/sound/soc/sirf/sirf-audio-port.h b/sound/soc/sirf/sirf-audio-port.h deleted file mode 100644 index f32dc54f4499..000000000000 --- a/sound/soc/sirf/sirf-audio-port.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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*/ From d66eac3e2b09690e28f9ac405969d6857325ee9d Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Wed, 23 Apr 2014 13:34:24 +0530 Subject: [PATCH 02/25] ASoC: samsung: Don't clear clock setting during i2s_startup In exiting kernel, if DAIFMT flags are set in dai_link and I2S is set to run in master mode, the I2S clocks are not getting configured resulting in no output. Existing code clears the current I2S clock settings during i2s_startup and requires that the clocks are reconfigured. It then assumes that sound-card driver would call snd_soc_dai_{set_sysclk/set_fmt} to configure the root clock. 1. Since I2S clock settings remain fixed for a board, it would be better to set the clocks once during sound-card probe. 2. Also if the DAIFMT flags are set in dai_link, snd_soc_dai_set_fmt is called during DAI probe. If both these conditions are true, then I2S clock remains unconfigured during audio playback. Fix this by removing the code to clear rclk_srcrate in i2s_startup. Instead, reset this during DAI probe. Signed-off-by: Tushar Behera Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 048ead967199..6e61db75ec4e 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -724,9 +724,6 @@ static int i2s_startup(struct snd_pcm_substream *substream, else i2s->mode |= DAI_MANAGER; - /* Enforce set_sysclk in Master mode */ - i2s->rclk_srcrate = 0; - if (!any_active(i2s) && (i2s->quirks & QUIRK_NEED_RSTCLR)) writel(CON_RSTCLR, i2s->addr + I2SCON); @@ -984,6 +981,7 @@ probe_exit: /* Reset any constraint on RFS and BFS */ i2s->rfs = 0; i2s->bfs = 0; + i2s->rclk_srcrate = 0; i2s_txctrl(i2s, 0); i2s_rxctrl(i2s, 0); i2s_fifo(i2s, FIC_TXFLUSH); From 389cb8348cf5ac4a702c71bf13673c4c8bf01e34 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 24 Mar 2014 12:15:24 +0200 Subject: [PATCH 03/25] ASoC: core: Update snd_soc_of_parse_daifmt() interface Adds struct device_node **bitclkmaster and struct device_node **framemaster function parameters. With the new syntax bitclock-master and frame-master properties can explicitly indicate the dai-link bit-clock and frame masters with a phandle. This patch also makes the minimal changes to simple-card for it to work with the updated snd_soc_of_parse_daifmt(). Simple-card appears to be the only user of snd_soc_of_parse_daifmt() for now. Signed-off-by: Jyri Sarha Acked-by: Jean-Francois Moine Signed-off-by: Mark Brown --- include/sound/soc.h | 4 +++- sound/soc/generic/simple-card.c | 5 +++-- sound/soc/soc-core.c | 8 +++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 0b83168d8ff4..58784105289a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1241,7 +1241,9 @@ int snd_soc_of_parse_tdm_slot(struct device_node *np, 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, - const char *prefix); + const char *prefix, + struct device_node **bitclkmaster, + struct device_node **framemaster); int snd_soc_of_get_dai_name(struct device_node *of_node, const char **dai_name); diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 21f1ccbdf582..835fd0258243 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -121,7 +121,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, * bitclock-master, frame-master * and specific "format" if it has */ - dai->fmt = snd_soc_of_parse_daifmt(np, NULL); + dai->fmt = snd_soc_of_parse_daifmt(np, NULL, NULL, NULL); dai->fmt |= daifmt; /* @@ -201,7 +201,8 @@ static int asoc_simple_card_parse_of(struct device_node *node, snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); /* get CPU/CODEC common format via simple-audio-card,format */ - daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") & + daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,", NULL, + NULL) & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK); /* off-codec widgets */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 051c006281f5..3487a55c9a06 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4554,7 +4554,9 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, - const char *prefix) + const char *prefix, + struct device_node **bitclkmaster, + struct device_node **framemaster) { int ret, i; char prop[128]; @@ -4637,9 +4639,13 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, */ snprintf(prop, sizeof(prop), "%sbitclock-master", prefix); bit = !!of_get_property(np, prop, NULL); + if (bit && bitclkmaster) + *bitclkmaster = of_parse_phandle(np, prop, 0); snprintf(prop, sizeof(prop), "%sframe-master", prefix); frame = !!of_get_property(np, prop, NULL); + if (frame && framemaster) + *framemaster = of_parse_phandle(np, prop, 0); switch ((bit << 4) + frame) { case 0x11: From b3ca11ff59bc5842b01f13421a17e6d9a8936784 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 24 Mar 2014 12:15:25 +0200 Subject: [PATCH 04/25] ASoC: simple-card: Move dai-link level properties away from dai subnodes The properties like format, bitclock-master, frame-master, bitclock-inversion, and frame-inversion should be common to the dais connected with a dai-link. For bitclock-master and frame-master properties to be unambiguous they need to indicate the mastering dai node with a phandle. Signed-off-by: Jyri Sarha Acked-by: Jean-Francois Moine Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/simple-card.txt | 88 ++++--- sound/soc/generic/simple-card.c | 243 ++++++++++-------- 2 files changed, 192 insertions(+), 139 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index 131aa2ad7f1a..9b9df146fd1a 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -1,6 +1,6 @@ Simple-Card: -Simple-Card specifies audio DAI connection of SoC <-> codec. +Simple-Card specifies audio DAI connections of SoC <-> codec. Required properties: @@ -10,26 +10,51 @@ Optional properties: - simple-audio-card,name : User specified audio sound card name, one string property. -- simple-audio-card,format : CPU/CODEC common audio format. - "i2s", "right_j", "left_j" , "dsp_a" - "dsp_b", "ac97", "pdm", "msb", "lsb" - simple-audio-card,widgets : Please refer to widgets.txt. - simple-audio-card,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. -- dai-tdm-slot-num : Please refer to tdm-slot.txt. -- dai-tdm-slot-width : Please refer to tdm-slot.txt. +Optional subnodes: -Required subnodes: +- simple-audio-card,dai-link : Container for dai-link level + properties and the CPU and CODEC + sub-nodes. This container may be + omitted when the card has only one + DAI link. See the examples and the + section bellow. -- simple-audio-card,dai-link : container for the CPU and CODEC sub-nodes - This container may be omitted when the - card has only one DAI link. - See the examples. +Dai-link subnode properties and subnodes: -- simple-audio-card,cpu : CPU sub-node -- simple-audio-card,codec : CODEC sub-node +If dai-link subnode is omitted and the subnode properties are directly +under "sound"-node the subnode property and subnode names have to be +prefixed with "simple-audio-card,"-prefix. + +Required dai-link subnodes: + +- cpu : CPU sub-node +- codec : CODEC sub-node + +Optional dai-link subnode properties: + +- format : CPU/CODEC common audio format. + "i2s", "right_j", "left_j" , "dsp_a" + "dsp_b", "ac97", "pdm", "msb", "lsb" +- frame-master : Indicates dai-link frame master. + phandle to a cpu or codec subnode. +- bitclock-master : Indicates dai-link bit clock master. + phandle to a cpu or codec subnode. +- bitclock-inversion : bool property. Add this if the + dai-link uses bit clock inversion. +- frame-inversion : bool property. Add this if the + dai-link uses frame clock inversion. + +For backward compatibility the frame-master and bitclock-master +properties can be used as booleans in codec subnode to indicate if the +codec is the dai-link frame or bit clock master. In this case there +should be no dai-link node, the same properties should not be present +at sound-node level, and the bitclock-inversion and frame-inversion +properties should also be placed in the codec node if needed. Required CPU/CODEC subnodes properties: @@ -37,29 +62,21 @@ Required CPU/CODEC subnodes properties: Optional CPU/CODEC subnodes properties: -- format : CPU/CODEC specific audio format if needed. - see simple-audio-card,format -- frame-master : bool property. add this if subnode is frame master -- bitclock-master : bool property. add this if subnode is bitclock master -- bitclock-inversion : bool property. add this if subnode has clock inversion -- frame-inversion : bool property. add this if subnode has frame inversion +- dai-tdm-slot-num : Please refer to tdm-slot.txt. +- dai-tdm-slot-width : Please refer to tdm-slot.txt. - clocks / system-clock-frequency : specify subnode's clock if needed. it can be specified via "clocks" if system has 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 1 - single DAI link: sound { compatible = "simple-audio-card"; simple-audio-card,name = "VF610-Tower-Sound-Card"; simple-audio-card,format = "left_j"; + simple-audio-card,bitclock-master = <&dailink0_master>; + simple-audio-card,frame-master = <&dailink0_master>; simple-audio-card,widgets = "Microphone", "Microphone Jack", "Headphone", "Headphone Jack", @@ -69,17 +86,12 @@ 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>; }; - simple-audio-card,codec { + dailink0_master: simple-audio-card,codec { sound-dai = <&ak4648>; - bitclock-master; - frame-master; clocks = <&osc>; }; }; @@ -105,31 +117,31 @@ Example 2 - many DAI links: sound { compatible = "simple-audio-card"; simple-audio-card,name = "Cubox Audio"; - simple-audio-card,format = "i2s"; simple-audio-card,dai-link@0 { /* I2S - HDMI */ - simple-audio-card,cpu { + format = "i2s"; + cpu { sound-dai = <&audio1 0>; }; - simple-audio-card,codec { + codec { sound-dai = <&tda998x 0>; }; }; simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */ - simple-audio-card,cpu { + cpu { sound-dai = <&audio1 1>; }; - simple-audio-card,codec { + codec { sound-dai = <&tda998x 1>; }; }; simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */ - simple-audio-card,cpu { + cpu { sound-dai = <&audio1 1>; }; - simple-audio-card,codec { + codec { sound-dai = <&spdif_codec>; }; }; diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 835fd0258243..3f2e5807d7eb 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -88,7 +88,6 @@ 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) @@ -116,14 +115,6 @@ asoc_simple_card_sub_parse_of(struct device_node *np, if (ret) return ret; - /* - * bitclock-inversion, frame-inversion - * bitclock-master, frame-master - * and specific "format" if it has - */ - dai->fmt = snd_soc_of_parse_daifmt(np, NULL, NULL, NULL); - dai->fmt |= daifmt; - /* * dai->sysclk come from * "clocks = <&xxx>" (if system has common clock) @@ -151,37 +142,135 @@ asoc_simple_card_sub_parse_of(struct device_node *np, return 0; } -static int simple_card_cpu_codec_of(struct device_node *node, - int daifmt, - struct snd_soc_dai_link *dai_link, - struct simple_dai_props *dai_props) +static int simple_card_dai_link_of(struct device_node *node, + struct device *dev, + struct snd_soc_dai_link *dai_link, + struct simple_dai_props *dai_props) { - struct device_node *np; + struct device_node *np = NULL; + struct device_node *bitclkmaster = NULL; + struct device_node *framemaster = NULL; + unsigned int daifmt; + char *name; + char prop[128]; + char *prefix = ""; int ret; - /* CPU sub-node */ - ret = -EINVAL; - np = of_get_child_by_name(node, "simple-audio-card,cpu"); - if (np) { - ret = asoc_simple_card_sub_parse_of(np, daifmt, - &dai_props->cpu_dai, - &dai_link->cpu_of_node, - &dai_link->cpu_dai_name); - of_node_put(np); - } - if (ret < 0) - return ret; + if (!strcmp("sound", node->name)) + prefix = "simple-audio-card,"; - /* CODEC sub-node */ - ret = -EINVAL; - np = of_get_child_by_name(node, "simple-audio-card,codec"); - if (np) { - ret = asoc_simple_card_sub_parse_of(np, daifmt, - &dai_props->codec_dai, - &dai_link->codec_of_node, - &dai_link->codec_dai_name); - of_node_put(np); + daifmt = snd_soc_of_parse_daifmt(node, prefix, + &bitclkmaster, &framemaster); + daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; + + snprintf(prop, sizeof(prop), "%scpu", prefix); + np = of_get_child_by_name(node, prop); + if (!np) { + ret = -EINVAL; + dev_err(dev, "%s: Can't find simple-audio-card,cpu DT node\n", + __func__); + goto dai_link_of_err; } + + ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai, + &dai_link->cpu_of_node, + &dai_link->cpu_dai_name); + if (ret < 0) + goto dai_link_of_err; + + dai_props->cpu_dai.fmt = daifmt; + switch (((np == bitclkmaster)<<4)|(np == framemaster)) { + case 0x11: + dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS; + break; + case 0x10: + dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM; + break; + case 0x01: + dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS; + break; + default: + dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM; + break; + } + + of_node_put(np); + snprintf(prop, sizeof(prop), "%scodec", prefix); + np = of_get_child_by_name(node, prop); + if (!np) { + ret = -EINVAL; + dev_err(dev, "%s: Can't find simple-audio-card,codec DT node\n", + __func__); + goto dai_link_of_err; + } + + ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai, + &dai_link->codec_of_node, + &dai_link->codec_dai_name); + if (ret < 0) + goto dai_link_of_err; + + if (strlen(prefix) && !bitclkmaster && !framemaster) { + /* No dai-link level and master setting was not found from + sound node level, revert back to legacy DT parsing and + take the settings from codec node. */ + dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n", + __func__); + dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt = + snd_soc_of_parse_daifmt(np, NULL, NULL, NULL) | + (daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK); + } else { + dai_props->codec_dai.fmt = daifmt; + switch (((np == bitclkmaster)<<4)|(np == framemaster)) { + case 0x11: + dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM; + break; + case 0x10: + dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS; + break; + case 0x01: + dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM; + break; + default: + dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS; + break; + } + } + + if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { + ret = -EINVAL; + goto dai_link_of_err; + } + + /* simple-card assumes platform == cpu */ + dai_link->platform_of_node = dai_link->cpu_of_node; + + /* Link name is created from CPU/CODEC dai name */ + name = devm_kzalloc(dev, + strlen(dai_link->cpu_dai_name) + + strlen(dai_link->codec_dai_name) + 2, + GFP_KERNEL); + sprintf(name, "%s-%s", dai_link->cpu_dai_name, + dai_link->codec_dai_name); + dai_link->name = dai_link->stream_name = name; + + dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); + dev_dbg(dev, "\tcpu : %s / %04x / %d\n", + dai_link->cpu_dai_name, + dai_props->cpu_dai.fmt, + dai_props->cpu_dai.sysclk); + dev_dbg(dev, "\tcodec : %s / %04x / %d\n", + dai_link->codec_dai_name, + dai_props->codec_dai.fmt, + dai_props->codec_dai.sysclk); + +dai_link_of_err: + if (np) + of_node_put(np); + if (bitclkmaster) + of_node_put(bitclkmaster); + if (framemaster) + of_node_put(framemaster); return ret; } @@ -192,19 +281,11 @@ static int asoc_simple_card_parse_of(struct device_node *node, { struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; struct simple_dai_props *dai_props = priv->dai_props; - 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 */ - daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,", NULL, - NULL) & - (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, @@ -221,71 +302,31 @@ static int asoc_simple_card_parse_of(struct device_node *node, return ret; } - /* loop on the DAI links */ - np = NULL; - for (;;) { - if (multi) { - np = of_get_next_child(node, np); - if (!np) - break; - } + dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? + priv->snd_card.name : ""); - ret = simple_card_cpu_codec_of(multi ? np : node, - daifmt, dai_link, dai_props); + if (multi) { + struct device_node *np = NULL; + int i; + for (i = 0; (np = of_get_next_child(node, np)); i++) { + dev_dbg(dev, "\tlink %d:\n", i); + ret = simple_card_dai_link_of(np, dev, dai_link + i, + dai_props + i); + if (ret < 0) { + of_node_put(np); + return ret; + } + } + } else { + ret = simple_card_dai_link_of(node, dev, dai_link, dai_props); if (ret < 0) - goto err; - - /* - * 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. - */ - dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt; - - if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { - ret = -EINVAL; - goto err; - } - - /* simple-card assumes platform == cpu */ - dai_link->platform_of_node = dai_link->cpu_of_node; - - name = devm_kzalloc(dev, - strlen(dai_link->cpu_dai_name) + - strlen(dai_link->codec_dai_name) + 2, - GFP_KERNEL); - sprintf(name, "%s-%s", dai_link->cpu_dai_name, - dai_link->codec_dai_name); - dai_link->name = dai_link->stream_name = name; - - if (!multi) - break; - - dai_link++; - dai_props++; + return ret; } - /* card name is created from CPU/CODEC dai name */ - dai_link = priv->snd_card.dai_link; if (!priv->snd_card.name) - priv->snd_card.name = dai_link->name; - - dev_dbg(dev, "card-name : %s\n", priv->snd_card.name); - dev_dbg(dev, "platform : %04x\n", daifmt); - dai_props = priv->dai_props; - dev_dbg(dev, "cpu : %s / %04x / %d\n", - dai_link->cpu_dai_name, - dai_props->cpu_dai.fmt, - dai_props->cpu_dai.sysclk); - dev_dbg(dev, "codec : %s / %04x / %d\n", - dai_link->codec_dai_name, - dai_props->codec_dai.fmt, - dai_props->codec_dai.sysclk); + priv->snd_card.name = priv->snd_card.dai_link->name; return 0; - -err: - of_node_put(np); - return ret; } /* update the reference count of the devices nodes at end of probe */ From 50e6c718a1eb2ae6d05f22615d8268b026175a4a Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 24 Apr 2014 19:13:58 +0800 Subject: [PATCH 05/25] ASoC: simple-card: Drop node->name checking The current simple-card driver limits the DT node name to "sound". Any of other names is forbidden while actually we should allow DT to pass other node names. And if this function is being called, the node must already have the compatible "simple-audio-card" in DTB. So there should be no need to check the name here. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 3f2e5807d7eb..383a4a18d51f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -156,8 +156,7 @@ static int simple_card_dai_link_of(struct device_node *node, char *prefix = ""; int ret; - if (!strcmp("sound", node->name)) - prefix = "simple-audio-card,"; + prefix = "simple-audio-card,"; daifmt = snd_soc_of_parse_daifmt(node, prefix, &bitclkmaster, &framemaster); From 966b8063607fbf43c8fdeef579fd8de8a35ca45d Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 24 Apr 2014 19:13:59 +0800 Subject: [PATCH 06/25] ASoC: simple-card: Simplify error msg in simple_card_dai_link_of() It would look better to use prop instead. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 383a4a18d51f..c091557666d5 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -166,8 +166,7 @@ static int simple_card_dai_link_of(struct device_node *node, np = of_get_child_by_name(node, prop); if (!np) { ret = -EINVAL; - dev_err(dev, "%s: Can't find simple-audio-card,cpu DT node\n", - __func__); + dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); goto dai_link_of_err; } @@ -198,8 +197,7 @@ static int simple_card_dai_link_of(struct device_node *node, np = of_get_child_by_name(node, prop); if (!np) { ret = -EINVAL; - dev_err(dev, "%s: Can't find simple-audio-card,codec DT node\n", - __func__); + dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); goto dai_link_of_err; } From 781cbebed750af26341e551b785048a1ea347c5e Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 24 Apr 2014 19:14:00 +0800 Subject: [PATCH 07/25] ASoC: simple-card: Improve coding style Improve indentation and space. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index c091557666d5..98f97e543c29 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -66,8 +66,7 @@ err: static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct simple_card_data *priv = - snd_soc_card_get_drvdata(rtd->card); + 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; struct simple_dai_props *dai_props; @@ -177,7 +176,7 @@ static int simple_card_dai_link_of(struct device_node *node, goto dai_link_of_err; dai_props->cpu_dai.fmt = daifmt; - switch (((np == bitclkmaster)<<4)|(np == framemaster)) { + switch (((np == bitclkmaster) << 4) | (np == framemaster)) { case 0x11: dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS; break; @@ -218,7 +217,7 @@ static int simple_card_dai_link_of(struct device_node *node, (daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK); } else { dai_props->codec_dai.fmt = daifmt; - switch (((np == bitclkmaster)<<4)|(np == framemaster)) { + switch (((np == bitclkmaster) << 4) | (np == framemaster)) { case 0x11: dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM; break; @@ -235,8 +234,8 @@ static int simple_card_dai_link_of(struct device_node *node, } if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { - ret = -EINVAL; - goto dai_link_of_err; + ret = -EINVAL; + goto dai_link_of_err; } /* simple-card assumes platform == cpu */ @@ -417,10 +416,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev) return -EINVAL; } - if (!cinfo->name || - !cinfo->codec_dai.name || - !cinfo->codec || - !cinfo->platform || + if (!cinfo->name || + !cinfo->codec_dai.name || + !cinfo->codec || + !cinfo->platform || !cinfo->cpu_dai.name) { dev_err(dev, "insufficient asoc_simple_card_info settings\n"); return -EINVAL; @@ -464,11 +463,11 @@ MODULE_DEVICE_TABLE(of, asoc_simple_of_match); static struct platform_driver asoc_simple_card = { .driver = { - .name = "asoc-simple-card", + .name = "asoc-simple-card", .owner = THIS_MODULE, .of_match_table = asoc_simple_of_match, }, - .probe = asoc_simple_card_probe, + .probe = asoc_simple_card_probe, }; module_platform_driver(asoc_simple_card); From 63e54cd9caa3ce03635810608519e2b37d8bc706 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 24 Apr 2014 14:13:08 -0300 Subject: [PATCH 08/25] ASoC: sgtl5000: Use devm_regulator_bulk_get() Using devm_regulator_bulk_get() can make the code cleaner and smaller as we do not need to call regulator_bulk_free() in the error and remove paths. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index d3ed1be5a186..75f820c58833 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1322,7 +1322,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) return ret; } - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), + ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), sgtl5000->supplies); if (ret) goto err_ldo_remove; @@ -1330,16 +1330,13 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), sgtl5000->supplies); if (ret) - goto err_regulator_free; + goto err_ldo_remove; /* wait for all power rails bring up */ udelay(10); return 0; -err_regulator_free: - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); err_ldo_remove: if (!external_vddd) ldo_regulator_remove(codec); @@ -1409,8 +1406,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) err: regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), sgtl5000->supplies); - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); ldo_regulator_remove(codec); return ret; @@ -1424,8 +1419,6 @@ static int sgtl5000_remove(struct snd_soc_codec *codec) regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), sgtl5000->supplies); - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); ldo_regulator_remove(codec); return 0; From e9382e3b7a048d4cfc39139caa86b755a74d4da8 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 24 Apr 2014 22:27:03 -0300 Subject: [PATCH 09/25] ASoC: tlv320dac33: Use devm_regulator_bulk_get() Using devm_regulator_bulk_get() can make the code cleaner and smaller as we do not need to call regulator_bulk_free() in the error and remove paths. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320dac33.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 6bfc8a17331b..0ef856c8dfeb 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1540,7 +1540,7 @@ static int dac33_i2c_probe(struct i2c_client *client, for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) dac33->supplies[i].supply = dac33_supply_names[i]; - ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies), + ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies), dac33->supplies); if (ret != 0) { @@ -1551,11 +1551,9 @@ static int dac33_i2c_probe(struct i2c_client *client, ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_tlv320dac33, &dac33_dai, 1); if (ret < 0) - goto err_register; + goto err_get; return ret; -err_register: - regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); err_get: if (dac33->power_gpio >= 0) gpio_free(dac33->power_gpio); @@ -1573,8 +1571,6 @@ static int dac33_i2c_remove(struct i2c_client *client) if (dac33->power_gpio >= 0) gpio_free(dac33->power_gpio); - regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); - snd_soc_unregister_codec(&client->dev); return 0; } From 31c26a6a842d541ca475a482112dda5993df2374 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Mon, 28 Apr 2014 10:14:39 +0530 Subject: [PATCH 10/25] ASoC: samsung: Add sound card driver for Snow board Added machine driver to instantiate I2S based sound card on Snow board. It has MAX98095 audio codec on board. There are some other variants for Snow board which have MAX98090 audio codec. Hence support for MAX98090 is also added to this driver. Signed-off-by: Tushar Behera Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/snow.txt | 17 +++ sound/soc/samsung/Kconfig | 10 ++ sound/soc/samsung/Makefile | 2 + sound/soc/samsung/snow.c | 122 ++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/snow.txt create mode 100644 sound/soc/samsung/snow.c diff --git a/Documentation/devicetree/bindings/sound/snow.txt b/Documentation/devicetree/bindings/sound/snow.txt new file mode 100644 index 000000000000..678b191c37b8 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/snow.txt @@ -0,0 +1,17 @@ +Audio Binding for Snow boards + +Required properties: +- compatible : Can be one of the following, + "google,snow-audio-max98090" or + "google,snow-audio-max98095" +- samsung,i2s-controller: The phandle of the Samsung I2S controller +- samsung,audio-codec: The phandle of the audio codec + +Example: + +sound { + compatible = "google,snow-audio-max98095"; + + samsung,i2s-controller = <&i2s0>; + samsung,audio-codec = <&max98095>; +}; diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index f2e289180e46..50aa28963f49 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -231,3 +231,13 @@ config SND_SOC_LITTLEMILL select SND_SAMSUNG_I2S select MFD_WM8994 select SND_SOC_WM8994 + +config SND_SOC_SNOW + tristate "Audio support for Google Snow boards" + depends on SND_SOC_SAMSUNG + select SND_SOC_MAX98090 + select SND_SOC_MAX98095 + select SND_SAMSUNG_I2S + help + Say Y if you want to add audio support for various Snow + boards based on Exynos5 series of SoCs. diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 86715d8efee6..6d0212ba571c 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -34,6 +34,7 @@ snd-soc-h1940-uda1380-objs := h1940_uda1380.o snd-soc-rx1950-uda1380-objs := rx1950_uda1380.o snd-soc-smdk-wm8580-objs := smdk_wm8580.o snd-soc-smdk-wm8994-objs := smdk_wm8994.o +snd-soc-snow-objs := snow.o snd-soc-smdk-wm9713-objs := smdk_wm9713.o snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o snd-soc-goni-wm8994-objs := goni_wm8994.o @@ -58,6 +59,7 @@ obj-$(CONFIG_SND_SOC_SAMSUNG_H1940_UDA1380) += snd-soc-h1940-uda1380.o obj-$(CONFIG_SND_SOC_SAMSUNG_RX1950_UDA1380) += snd-soc-rx1950-uda1380.o obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8580) += snd-soc-smdk-wm8580.o obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994) += snd-soc-smdk-wm8994.o +obj-$(CONFIG_SND_SOC_SNOW) += snd-soc-snow.o obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM9713) += snd-soc-smdk-wm9713.o obj-$(CONFIG_SND_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c new file mode 100644 index 000000000000..0fa89a41d8c0 --- /dev/null +++ b/sound/soc/samsung/snow.c @@ -0,0 +1,122 @@ +/* + * ASoC machine driver for Snow boards + * + * 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 "i2s.h" + +#define FIN_PLL_RATE 24000000 + +static struct snd_soc_dai_link snow_dai[] = { + { + .name = "Primary", + .stream_name = "Primary", + .codec_dai_name = "HiFi", + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + }, +}; + +static int snow_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; + struct snd_soc_dai *cpu_dai = card->rtd[0].cpu_dai; + int ret; + + /* Set the MCLK rate for the codec */ + ret = snd_soc_dai_set_sysclk(codec_dai, 0, + FIN_PLL_RATE, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + /* Select I2S Bus clock to set RCLK and BCLK */ + ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0, + 0, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_card snow_snd = { + .name = "Snow-I2S", + .dai_link = snow_dai, + .num_links = ARRAY_SIZE(snow_dai), + + .late_probe = snow_late_probe, +}; + +static int snow_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &snow_snd; + struct device_node *i2s_node, *codec_node; + int i, ret; + + i2s_node = of_parse_phandle(pdev->dev.of_node, + "samsung,i2s-controller", 0); + if (!i2s_node) { + dev_err(&pdev->dev, + "Property 'i2s-controller' missing or invalid\n"); + return -EINVAL; + } + + codec_node = of_parse_phandle(pdev->dev.of_node, + "samsung,audio-codec", 0); + if (!codec_node) { + dev_err(&pdev->dev, + "Property 'audio-codec' missing or invalid\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(snow_dai); i++) { + snow_dai[i].codec_of_node = codec_node; + snow_dai[i].cpu_of_node = i2s_node; + snow_dai[i].platform_of_node = i2s_node; + } + + card->dev = &pdev->dev; + + 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; + } + + return ret; +} + +static const struct of_device_id snow_of_match[] = { + { .compatible = "google,snow-audio-max98090", }, + { .compatible = "google,snow-audio-max98095", }, + {}, +}; + +static struct platform_driver snow_driver = { + .driver = { + .name = "snow-audio", + .owner = THIS_MODULE, + .of_match_table = snow_of_match, + }, + .probe = snow_probe, +}; + +module_platform_driver(snow_driver); + +MODULE_DESCRIPTION("ALSA SoC Audio machine driver for Snow"); +MODULE_LICENSE("GPL"); From 01c2cb67eaa37f86196e3e6074dea096fe46511a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 29 Apr 2014 19:18:24 +0800 Subject: [PATCH 11/25] ASoC: samsung: SMDK_WM8580_PCM needs REGMAP_I2C This adds a missing dependency for SND_SOC_SMDK_WM8580_PCM to require REGMAP_I2C to be enabled, avoiding possible build erorrs. Signed-off-by: Arnd Bergmann Signed-off-by: Xia Kaixu Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 50aa28963f49..c5fd242e6dab 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -64,6 +64,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 config SND_SOC_SAMSUNG_SMDK_WM8580 tristate "SoC I2S Audio support for WM8580 on SMDK" depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDK6440 || MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) + depends on REGMAP_I2C select SND_SOC_WM8580 select SND_SAMSUNG_I2S help @@ -178,6 +179,7 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF config SND_SOC_SMDK_WM8580_PCM tristate "SoC PCM Audio support for WM8580 on SMDK" depends on SND_SOC_SAMSUNG && (MACH_SMDK6450 || MACH_SMDKV210 || MACH_SMDKC110) + depends on REGMAP_I2C select SND_SOC_WM8580 select SND_SAMSUNG_PCM help From 1aa91b6dd44a9517dee42913ecf9f51650b32cb6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 29 Apr 2014 19:18:25 +0800 Subject: [PATCH 12/25] ASoC: samsung-idma: avoid 64-bit division dma_addr_t may be 64 bit wide, which causes a build failure when doing a division on it. Here it is safe to cast to an u32 type, which avoids the problem. Signed-off-by: Arnd Bergmann Signed-off-by: Xia Kaixu Tested-by: Tushar Behera Signed-off-by: Mark Brown --- sound/soc/samsung/idma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c index 3d5cf1530b6f..e9891b44f0e2 100644 --- a/sound/soc/samsung/idma.c +++ b/sound/soc/samsung/idma.c @@ -274,7 +274,7 @@ static irqreturn_t iis_irq(int irqno, void *dev_id) addr = readl(idma.regs + I2SLVL0ADDR) - idma.lp_tx_addr; addr += prtd->periodsz; - addr %= (prtd->end - prtd->start); + addr %= (u32)(prtd->end - prtd->start); addr += idma.lp_tx_addr; writel(addr, idma.regs + I2SLVL0ADDR); From 654da9f5228f10d5390e429f786e251104ae12ae Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 29 Apr 2014 19:18:28 +0800 Subject: [PATCH 13/25] ASoC: samsung: UDA1380 needs I2C The UDA1380 driver needs I2C to be enabled, so SND_SOC_SAMSUNG_H1940_UDA1380 and SND_SOC_SAMSUNG_RX1950_UDA1380 also require this. Signed-off-by: Arnd Bergmann Signed-off-by: Xia Kaixu Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index c5fd242e6dab..ef448b07a3bb 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -130,7 +130,7 @@ config SND_SOC_SAMSUNG_SIMTEC_HERMES config SND_SOC_SAMSUNG_H1940_UDA1380 tristate "Audio support for the HP iPAQ H1940" - depends on SND_SOC_SAMSUNG && ARCH_H1940 + depends on SND_SOC_SAMSUNG && ARCH_H1940 && I2C select SND_S3C24XX_I2S select SND_SOC_UDA1380 help @@ -138,7 +138,7 @@ config SND_SOC_SAMSUNG_H1940_UDA1380 config SND_SOC_SAMSUNG_RX1950_UDA1380 tristate "Audio support for the HP iPAQ RX1950" - depends on SND_SOC_SAMSUNG && MACH_RX1950 + depends on SND_SOC_SAMSUNG && MACH_RX1950 && I2C select SND_S3C24XX_I2S select SND_SOC_UDA1380 help From 7ec91cd017a97a6ccaf9a3e533456e518fe80e17 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 29 Apr 2014 19:18:31 +0800 Subject: [PATCH 14/25] ASoC: samsung: TLV320AIC23 and Simtec Hermes audio need I2C This codec requires I2C to be enabled, so any other option that selects it should also depend on I2C. Signed-off-by: Arnd Bergmann Signed-off-by: Xia Kaixu Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index ef448b07a3bb..68c13bd07041 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -116,14 +116,14 @@ config SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" - depends on SND_SOC_SAMSUNG && ARCH_S3C24XX + depends on SND_SOC_SAMSUNG && ARCH_S3C24XX && I2C select SND_S3C24XX_I2S select SND_SOC_TLV320AIC23_I2C select SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_SIMTEC_HERMES tristate "SoC I2S Audio support for Simtec Hermes board" - depends on SND_SOC_SAMSUNG && ARCH_S3C24XX + depends on SND_SOC_SAMSUNG && ARCH_S3C24XX && I2C select SND_S3C24XX_I2S select SND_SOC_TLV320AIC3X select SND_SOC_SAMSUNG_SIMTEC From 7b6ad9e85bad73bac3ce799864e0e3a66a0469e2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 29 Apr 2014 19:18:30 +0800 Subject: [PATCH 15/25] ASoC: sh: Migo-R sound needs I2C The WM8978 driver needs I2C to be enabled, so the SND_SIU_MIGOR option also requires this. Signed-off-by: Arnd Bergmann Signed-off-by: Xia Kaixu Signed-off-by: Mark Brown --- sound/soc/sh/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index ff60e11ecb56..b43fdf0d08af 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -56,7 +56,7 @@ config SND_SH7760_AC97 config SND_SIU_MIGOR tristate "SIU sound support on Migo-R" - depends on SH_MIGOR + depends on SH_MIGOR && I2C select SND_SOC_SH4_SIU select SND_SOC_WM8978 help From 09af62ff184bfeae4a72874ab28ed637a2329ee4 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 5 May 2014 11:49:22 +0200 Subject: [PATCH 16/25] ASoC: sta350: fix DT bindings document Fix a misleading property description, and denote the fact that st,output-conf and st,ch*-output-mapping have to be passed as /bits/ 8. Signed-off-by: Daniel Mack Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/st,sta350.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/st,sta350.txt b/Documentation/devicetree/bindings/sound/st,sta350.txt index 950188891abd..ecd7a623c8bd 100644 --- a/Documentation/devicetree/bindings/sound/st,sta350.txt +++ b/Documentation/devicetree/bindings/sound/st,sta350.txt @@ -25,6 +25,7 @@ Optional properties: 2: 2 Channel (Full-Bridge) Power, 1 Channel FFX 3: 1 Channel Mono-Parallel If parameter is missing, mode 0 will be enabled. + This property has to be specified as '/bits/ 8' value. - st,ch1-output-mapping: Channel 1 output mapping - st,ch2-output-mapping: Channel 2 output mapping @@ -33,6 +34,7 @@ Optional properties: 1: Channel 2 2: Channel 3 If parameter is missing, channel 1 is choosen. + This properties have to be specified as '/bits/ 8' values. - st,thermal-warning-recover: If present, thermal warning recovery is enabled. @@ -82,7 +84,7 @@ Optional properties: If not present, preset DC coefficient is used. - st,invalid-input-detect-mute: - If not present, automatic invalid input detect mute is enabled. + If present, automatic invalid input detect mute is enabled. @@ -93,12 +95,12 @@ codec: sta350@38 { reg = <0x1c>; reset-gpios = <&gpio1 19 0>; power-down-gpios = <&gpio1 16 0>; - st,output-conf = <0x3>; // set output to 2-channel + st,output-conf = /bits/ 8 <0x3>; // set output to 2-channel // (full-bridge) power, // 2-channel data-out - st,ch1-output-mapping = <0>; // set channel 1 output ch 1 - st,ch2-output-mapping = <0>; // set channel 2 output ch 1 - st,ch3-output-mapping = <0>; // set channel 3 output ch 1 + st,ch1-output-mapping = /bits/ 8 <0>; // set channel 1 output ch 1 + st,ch2-output-mapping = /bits/ 8 <0>; // set channel 2 output ch 1 + st,ch3-output-mapping = /bits/ 8 <0>; // set channel 3 output ch 1 st,max-power-correction; // enables power bridge // correction for THD reduction // near maximum power output From 7c2fcccc323909c1a4e56b79fc882168a0880146 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 5 May 2014 11:49:23 +0200 Subject: [PATCH 17/25] ASoC: sta350: add support for bits in miscellaneous registers Add support for RPDNEN, NSHHPEN, BRIDGOFF, CPWMEN and PNDLSL, and add DT bindings to access them. Signed-off-by: Daniel Mack Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/st,sta350.txt | 22 +++++++++ include/sound/sta350.h | 5 +++ sound/soc/codecs/sta350.c | 45 +++++++++++++++++++ sound/soc/codecs/sta350.h | 10 +++++ 4 files changed, 82 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/st,sta350.txt b/Documentation/devicetree/bindings/sound/st,sta350.txt index ecd7a623c8bd..b7e71bf5caf4 100644 --- a/Documentation/devicetree/bindings/sound/st,sta350.txt +++ b/Documentation/devicetree/bindings/sound/st,sta350.txt @@ -86,7 +86,29 @@ Optional properties: - st,invalid-input-detect-mute: If present, automatic invalid input detect mute is enabled. + - st,activate-mute-output: + If present, a mute output will be activated in ase the volume will + reach a value lower than -76 dBFS. + - st,bridge-immediate-off: + If present, the bridge will be switched off immediately after the + power-down-gpio goes low. Otherwise, the bridge will wait for 13 + million clock cycles to pass before shutting down. + + - st,noise-shape-dc-cut: + If present, the noise-shaping technique on the DC cutoff filter are + enabled. + + - st,powerdown-master-volume: + If present, the power-down pin and I2C power-down functions will + act on the master volume. Otherwise, the functions will act on the + mute commands. + + - st,powerdown-delay-divider: + If present, the bridge power-down time will be divided by the provided + value. If not specified, a divider of 1 will be used. Allowed values + are 1, 2, 4, 8, 16, 32, 64 and 128. + This property has to be specified as '/bits/ 8' value. Example: diff --git a/include/sound/sta350.h b/include/sound/sta350.h index 3a3298106b22..42edceb096a0 100644 --- a/include/sound/sta350.h +++ b/include/sound/sta350.h @@ -37,6 +37,7 @@ struct sta350_platform_data { u8 ch3_output_mapping; u8 ffx_power_output_mode; u8 drop_compensation_ns; + u8 powerdown_delay_divider; unsigned int thermal_warning_recovery:1; unsigned int thermal_warning_adjustment:1; unsigned int fault_detect_recovery:1; @@ -47,6 +48,10 @@ struct sta350_platform_data { unsigned int odd_pwm_speed_mode:1; unsigned int distortion_compensation:1; unsigned int invalid_input_detect_mute:1; + unsigned int activate_mute_output:1; + unsigned int bridge_immediate_off:1; + unsigned int noise_shape_dc_cut:1; + unsigned int powerdown_master_vol:1; }; #endif /* __LINUX_SND__STA350_H */ diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 12ebbaf5d95f..cc97dd52aa9c 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -1020,6 +1020,29 @@ static int sta350_probe(struct snd_soc_codec *codec) pdata->ch3_output_mapping << STA350_CxCFG_OM_SHIFT); + /* miscellaneous registers */ + regmap_update_bits(sta350->regmap, STA350_MISC1, + STA350_MISC1_CPWMEN, + pdata->activate_mute_output ? + STA350_MISC1_CPWMEN : 0); + regmap_update_bits(sta350->regmap, STA350_MISC1, + STA350_MISC1_BRIDGOFF, + pdata->bridge_immediate_off ? + STA350_MISC1_BRIDGOFF : 0); + regmap_update_bits(sta350->regmap, STA350_MISC1, + STA350_MISC1_NSHHPEN, + pdata->noise_shape_dc_cut ? + STA350_MISC1_NSHHPEN : 0); + regmap_update_bits(sta350->regmap, STA350_MISC1, + STA350_MISC1_RPDNEN, + pdata->powerdown_master_vol ? + STA350_MISC1_RPDNEN: 0); + + regmap_update_bits(sta350->regmap, STA350_MISC2, + STA350_MISC2_PNDLSL_MASK, + pdata->powerdown_delay_divider + << STA350_MISC2_PNDLSL_SHIFT); + /* initialize coefficient shadow RAM with reset values */ for (i = 4; i <= 49; i += 5) sta350->coef_shadow[i] = 0x400000; @@ -1094,6 +1117,7 @@ static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350) struct sta350_platform_data *pdata; const char *ffx_power_mode; u16 tmp; + u8 tmp8; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -1158,6 +1182,27 @@ static int sta350_probe_dt(struct device *dev, struct sta350_priv *sta350) if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) pdata->invalid_input_detect_mute = 1; + /* MISC */ + if (of_get_property(np, "st,activate-mute-output", NULL)) + pdata->activate_mute_output = 1; + + if (of_get_property(np, "st,bridge-immediate-off", NULL)) + pdata->bridge_immediate_off = 1; + + if (of_get_property(np, "st,noise-shape-dc-cut", NULL)) + pdata->noise_shape_dc_cut = 1; + + if (of_get_property(np, "st,powerdown-master-volume", NULL)) + pdata->powerdown_master_vol = 1; + + if (!of_property_read_u8(np, "st,powerdown-delay-divider", &tmp8)) { + if (is_power_of_2(tmp8) && tmp8 >= 1 && tmp8 <= 128) + pdata->powerdown_delay_divider = ilog2(tmp8); + else + dev_warn(dev, "Unsupported powerdown delay divider %d\n", + tmp8); + } + sta350->pdata = pdata; return 0; diff --git a/sound/soc/codecs/sta350.h b/sound/soc/codecs/sta350.h index c3248f0fad2c..fb7285290779 100644 --- a/sound/soc/codecs/sta350.h +++ b/sound/soc/codecs/sta350.h @@ -225,4 +225,14 @@ #define STA350_C3_MIX1 60 #define STA350_C3_MIX2 61 +/* miscellaneous register 1 */ +#define STA350_MISC1_CPWMEN BIT(2) +#define STA350_MISC1_BRIDGOFF BIT(5) +#define STA350_MISC1_NSHHPEN BIT(6) +#define STA350_MISC1_RPDNEN BIT(7) + +/* miscellaneous register 2 */ +#define STA350_MISC2_PNDLSL_MASK 0x1c +#define STA350_MISC2_PNDLSL_SHIFT 2 + #endif /* _ASOC_STA_350_H */ From deeaa686b9381ff9a66e599af57976ba7e54ec54 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Wed, 14 May 2014 08:49:06 +0530 Subject: [PATCH 18/25] ASoC: samsung: Add missing pm ops for Snow sound card driver Adding missing pm ops so that audio playback works across suspend and resume cycle. Signed-off-by: Tushar Behera Signed-off-by: Mark Brown --- sound/soc/samsung/snow.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 0fa89a41d8c0..014c177840ba 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -111,6 +111,7 @@ static struct platform_driver snow_driver = { .driver = { .name = "snow-audio", .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, .of_match_table = snow_of_match, }, .probe = snow_probe, From c1406846e4e1ae92c4fb96fcb4532a63a2bceb21 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 19 May 2014 08:03:04 +0200 Subject: [PATCH 19/25] ASoC: rt5651: Do not use rtd->codec rtd->codec does not necessarily point to the CODEC instance for which the callback was called (e.g. for CODEC<->CODEC or multi-CODEC links). Use dai->codec instead. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/rt5651.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index f785b81238ae..9c88d89f41f0 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1368,8 +1368,7 @@ static int get_clk_info(int sclk, int rate) static int rt5651_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 rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); unsigned int val_len = 0, val_clk, mask_clk; int pre_div, bclk_ms, frame_size; From c86d50f9dc525cb0264c25ed5186faf0f1d00477 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 19 May 2014 19:30:38 +0200 Subject: [PATCH 20/25] ASoC: samsung: Allow setting OP_CLK of the IIS Multi Audio Interface This patch adds support for setting source clock of the "Core CLK" of the IIS Multi Audio Interface. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 4 ++++ sound/soc/samsung/i2s.h | 1 + 2 files changed, 5 insertions(+) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 6e61db75ec4e..1e99071fb624 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -451,6 +451,10 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, u32 mod = readl(i2s->addr + I2SMOD); switch (clk_id) { + case SAMSUNG_I2S_OPCLK: + mod &= ~MOD_OPCLK_MASK; + mod |= dir; + break; case SAMSUNG_I2S_CDCLK: /* Shouldn't matter in GATING(CLOCK_IN) mode */ if (dir == SND_SOC_CLOCK_IN) diff --git a/sound/soc/samsung/i2s.h b/sound/soc/samsung/i2s.h index 7966afc934db..21ff24e930db 100644 --- a/sound/soc/samsung/i2s.h +++ b/sound/soc/samsung/i2s.h @@ -18,5 +18,6 @@ #define SAMSUNG_I2S_RCLKSRC_0 0 #define SAMSUNG_I2S_RCLKSRC_1 1 #define SAMSUNG_I2S_CDCLK 2 +#define SAMSUNG_I2S_OPCLK 3 #endif /* __SND_SOC_SAMSUNG_I2S_H */ From fbfad49076646165bbd72de4dccf1d5132ab7856 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 20 May 2014 11:13:28 +0200 Subject: [PATCH 21/25] ASoC: neo1973_wm8753: Automatically disconnected non-connected pins The DAPM routes for this board are complete, hence we can let the core take care of disconnecting non-connected pins rather than doing it manually. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/samsung/neo1973_wm8753.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index b0800337b79e..9b4a09f14b6c 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -271,15 +271,8 @@ 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_card *card = rtd->card; - /* set up NC codec pins */ - 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(&card->dapm, "GSM Line Out"); snd_soc_dapm_disable_pin(&card->dapm, "GSM Line In"); @@ -355,6 +348,7 @@ static struct snd_soc_card neo1973 = { .num_dapm_widgets = ARRAY_SIZE(neo1973_wm8753_dapm_widgets), .dapm_routes = neo1973_wm8753_routes, .num_dapm_routes = ARRAY_SIZE(neo1973_wm8753_routes), + .fully_routed = true, }; static struct platform_device *neo1973_snd_device; From c583883ecdca277c258c95dc8c711dfb76d23b40 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Wed, 21 May 2014 08:52:17 +0530 Subject: [PATCH 22/25] ASoC: samsung: Use devm_snd_soc_register_card Replace snd_soc_register_card with devm_snd_soc_register_card. With this change, we can delete the empty remove functions. Signed-off-by: Tushar Behera Signed-off-by: Mark Brown --- sound/soc/samsung/bells.c | 16 +++------------- sound/soc/samsung/littlemill.c | 18 +++--------------- sound/soc/samsung/lowland.c | 18 +++--------------- sound/soc/samsung/smdk_wm8580pcm.c | 15 +++------------ sound/soc/samsung/smdk_wm8994pcm.c | 15 +++------------ sound/soc/samsung/speyside.c | 18 +++--------------- sound/soc/samsung/tobermory.c | 18 +++--------------- 7 files changed, 21 insertions(+), 97 deletions(-) diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index 84f5d8b76679..5b21207cf551 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c @@ -433,22 +433,13 @@ static int bells_probe(struct platform_device *pdev) bells_cards[pdev->id].dev = &pdev->dev; - ret = snd_soc_register_card(&bells_cards[pdev->id]); - if (ret) { + ret = devm_snd_soc_register_card(&pdev->dev, &bells_cards[pdev->id]); + if (ret) dev_err(&pdev->dev, "snd_soc_register_card(%s) failed: %d\n", bells_cards[pdev->id].name, ret); - return ret; - } - return 0; -} - -static int bells_remove(struct platform_device *pdev) -{ - snd_soc_unregister_card(&bells_cards[pdev->id]); - - return 0; + return ret; } static struct platform_driver bells_driver = { @@ -458,7 +449,6 @@ static struct platform_driver bells_driver = { .pm = &snd_soc_pm_ops, }, .probe = bells_probe, - .remove = bells_remove, }; module_platform_driver(bells_driver); diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index bfb91f34a22a..840787e63cb1 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -304,23 +304,12 @@ static int littlemill_probe(struct platform_device *pdev) card->dev = &pdev->dev; - ret = snd_soc_register_card(card); - if (ret) { + 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; - } - return 0; -} - -static int littlemill_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; + return ret; } static struct platform_driver littlemill_driver = { @@ -330,7 +319,6 @@ static struct platform_driver littlemill_driver = { .pm = &snd_soc_pm_ops, }, .probe = littlemill_probe, - .remove = littlemill_remove, }; module_platform_driver(littlemill_driver); diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c index 570cf5229508..bd5f0d643a86 100644 --- a/sound/soc/samsung/lowland.c +++ b/sound/soc/samsung/lowland.c @@ -187,23 +187,12 @@ static int lowland_probe(struct platform_device *pdev) card->dev = &pdev->dev; - ret = snd_soc_register_card(card); - if (ret) { + 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; - } - return 0; -} - -static int lowland_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; + return ret; } static struct platform_driver lowland_driver = { @@ -213,7 +202,6 @@ static struct platform_driver lowland_driver = { .pm = &snd_soc_pm_ops, }, .probe = lowland_probe, - .remove = lowland_remove, }; module_platform_driver(lowland_driver); diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c index 23a9204b106d..e119aaa91c28 100644 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ b/sound/soc/samsung/smdk_wm8580pcm.c @@ -164,19 +164,11 @@ static int snd_smdk_probe(struct platform_device *pdev) xtal_freq = mclk_freq = SMDK_WM8580_EXT_VOICE; smdk_pcm.dev = &pdev->dev; - ret = snd_soc_register_card(&smdk_pcm); - if (ret) { + ret = devm_snd_soc_register_card(&pdev->dev, &smdk_pcm); + if (ret) dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); - return ret; - } - return 0; -} - -static int snd_smdk_remove(struct platform_device *pdev) -{ - snd_soc_unregister_card(&smdk_pcm); - return 0; + return ret; } static struct platform_driver snd_smdk_driver = { @@ -185,7 +177,6 @@ static struct platform_driver snd_smdk_driver = { .name = "samsung-smdk-pcm", }, .probe = snd_smdk_probe, - .remove = snd_smdk_remove, }; module_platform_driver(snd_smdk_driver); diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index 0c84ca099612..b6c09979be1f 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c @@ -134,19 +134,11 @@ static int snd_smdk_probe(struct platform_device *pdev) int ret = 0; smdk_pcm.dev = &pdev->dev; - ret = snd_soc_register_card(&smdk_pcm); - if (ret) { + ret = devm_snd_soc_register_card(&pdev->dev, &smdk_pcm); + if (ret) dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); - return ret; - } - return 0; -} - -static int snd_smdk_remove(struct platform_device *pdev) -{ - snd_soc_unregister_card(&smdk_pcm); - return 0; + return ret; } static struct platform_driver snd_smdk_driver = { @@ -155,7 +147,6 @@ static struct platform_driver snd_smdk_driver = { .name = "samsung-smdk-pcm", }, .probe = snd_smdk_probe, - .remove = snd_smdk_remove, }; module_platform_driver(snd_smdk_driver); diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index 57df90d6b7c1..9902efcb8ea1 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c @@ -327,23 +327,12 @@ static int speyside_probe(struct platform_device *pdev) card->dev = &pdev->dev; - ret = snd_soc_register_card(card); - if (ret) { + 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; - } - return 0; -} - -static int speyside_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; + return ret; } static struct platform_driver speyside_driver = { @@ -353,7 +342,6 @@ static struct platform_driver speyside_driver = { .pm = &snd_soc_pm_ops, }, .probe = speyside_probe, - .remove = speyside_remove, }; module_platform_driver(speyside_driver); diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index 1807b75ccc12..6a2b9f14d624 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c @@ -223,23 +223,12 @@ static int tobermory_probe(struct platform_device *pdev) card->dev = &pdev->dev; - ret = snd_soc_register_card(card); - if (ret) { + 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; - } - return 0; -} - -static int tobermory_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; + return ret; } static struct platform_driver tobermory_driver = { @@ -249,7 +238,6 @@ static struct platform_driver tobermory_driver = { .pm = &snd_soc_pm_ops, }, .probe = tobermory_probe, - .remove = tobermory_remove, }; module_platform_driver(tobermory_driver); From 55313bd3b09b68ce28e328e9dde79bfc389ea921 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Wed, 21 May 2014 08:52:18 +0530 Subject: [PATCH 23/25] ASoC: samsung: Use devm_snd_soc_register_platform Replaced snd_soc_register_platform with devm_snd_soc_register_platform in samsung_asoc_dma_platform_register(). This makes the function samsung_asoc_dma_platform_unregister() redundant. This is removed and all its users are updated. Signed-off-by: Tushar Behera Signed-off-by: Mark Brown --- sound/soc/samsung/ac97.c | 1 - sound/soc/samsung/dma.c | 8 +------- sound/soc/samsung/dma.h | 1 - sound/soc/samsung/dmaengine.c | 13 ++++--------- sound/soc/samsung/i2s.c | 2 -- sound/soc/samsung/idma.c | 9 +-------- sound/soc/samsung/pcm.c | 1 - sound/soc/samsung/s3c2412-i2s.c | 1 - sound/soc/samsung/s3c24xx-i2s.c | 1 - sound/soc/samsung/spdif.c | 1 - 10 files changed, 6 insertions(+), 32 deletions(-) diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 76b072bd4ba2..fbce03bbdb2b 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c @@ -461,7 +461,6 @@ static int s3c_ac97_remove(struct platform_device *pdev) { struct resource *irq_res; - samsung_asoc_dma_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index dc09b71b7d9f..d9dc7bcc0336 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c @@ -445,16 +445,10 @@ EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); int samsung_asoc_dma_platform_register(struct device *dev) { - return snd_soc_register_platform(dev, &samsung_asoc_platform); + return devm_snd_soc_register_platform(dev, &samsung_asoc_platform); } EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); -void samsung_asoc_dma_platform_unregister(struct device *dev) -{ - snd_soc_unregister_platform(dev); -} -EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister); - MODULE_AUTHOR("Ben Dooks, "); MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h index ad7c0f04f00d..070ab0f09609 100644 --- a/sound/soc/samsung/dma.h +++ b/sound/soc/samsung/dma.h @@ -33,6 +33,5 @@ void samsung_asoc_init_dma_data(struct snd_soc_dai *dai, struct s3c_dma_params *playback, struct s3c_dma_params *capture); int samsung_asoc_dma_platform_register(struct device *dev); -void samsung_asoc_dma_platform_unregister(struct device *dev); #endif diff --git a/sound/soc/samsung/dmaengine.c b/sound/soc/samsung/dmaengine.c index 750ce5808d9f..a0e4e7948909 100644 --- a/sound/soc/samsung/dmaengine.c +++ b/sound/soc/samsung/dmaengine.c @@ -66,18 +66,13 @@ EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data); int samsung_asoc_dma_platform_register(struct device *dev) { - return snd_dmaengine_pcm_register(dev, &samsung_dmaengine_pcm_config, - SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME | - SND_DMAENGINE_PCM_FLAG_COMPAT); + return devm_snd_dmaengine_pcm_register(dev, + &samsung_dmaengine_pcm_config, + SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME | + SND_DMAENGINE_PCM_FLAG_COMPAT); } EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register); -void samsung_asoc_dma_platform_unregister(struct device *dev) -{ - return snd_dmaengine_pcm_unregister(dev); -} -EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister); - MODULE_AUTHOR("Mark Brown "); MODULE_DESCRIPTION("Samsung dmaengine ASoC driver"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 1e99071fb624..07ff3e7cb890 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1295,8 +1295,6 @@ static int samsung_i2s_remove(struct platform_device *pdev) i2s->pri_dai = NULL; i2s->sec_dai = NULL; - samsung_asoc_dma_platform_unregister(&pdev->dev); - return 0; } diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c index e9891b44f0e2..8cc5770abb39 100644 --- a/sound/soc/samsung/idma.c +++ b/sound/soc/samsung/idma.c @@ -413,13 +413,7 @@ static int asoc_idma_platform_probe(struct platform_device *pdev) if (idma_irq < 0) return idma_irq; - return snd_soc_register_platform(&pdev->dev, &asoc_idma_platform); -} - -static int asoc_idma_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; + return devm_snd_soc_register_platform(&pdev->dev, &asoc_idma_platform); } static struct platform_driver asoc_idma_driver = { @@ -429,7 +423,6 @@ static struct platform_driver asoc_idma_driver = { }, .probe = asoc_idma_platform_probe, - .remove = asoc_idma_platform_remove, }; module_platform_driver(asoc_idma_driver); diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index ab54e297957c..38df2a86bd5f 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -624,7 +624,6 @@ static int s3c_pcm_dev_remove(struct platform_device *pdev) struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; struct resource *mem_res; - samsung_asoc_dma_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index e9bb5d7a71ee..f42da8df3e3c 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -192,7 +192,6 @@ err: static int s3c2412_iis_dev_remove(struct platform_device *pdev) { - samsung_asoc_dma_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); return 0; } diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index d7b8457b5650..8380443b1b39 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -496,7 +496,6 @@ err: static int s3c24xx_iis_dev_remove(struct platform_device *pdev) { - samsung_asoc_dma_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); return 0; } diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index cfe63b7bcc9f..7d89d016fa49 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -467,7 +467,6 @@ static int spdif_remove(struct platform_device *pdev) struct samsung_spdif_info *spdif = &spdif_info; struct resource *mem_res; - samsung_asoc_dma_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); iounmap(spdif->regs); From 7253e354e712d2cab7b640c62c8bb82653447c44 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Wed, 21 May 2014 08:52:19 +0530 Subject: [PATCH 24/25] ASoC: samsung: Use devm_snd_soc_register_component Replaced snd_soc_register_component with its devres equivalent, devm_snd_soc_register_component. Signed-off-by: Tushar Behera Signed-off-by: Mark Brown --- sound/soc/samsung/ac97.c | 8 ++------ sound/soc/samsung/goni_wm8994.c | 9 +++------ sound/soc/samsung/pcm.c | 8 ++------ sound/soc/samsung/s3c-i2s-v2.c | 2 +- sound/soc/samsung/s3c2412-i2s.c | 14 +------------- sound/soc/samsung/s3c24xx-i2s.c | 18 +++--------------- sound/soc/samsung/spdif.c | 10 +++------- 7 files changed, 15 insertions(+), 54 deletions(-) diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index fbce03bbdb2b..68d9303047e8 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c @@ -433,7 +433,7 @@ static int s3c_ac97_probe(struct platform_device *pdev) goto err4; } - ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component, + ret = devm_snd_soc_register_component(&pdev->dev, &s3c_ac97_component, s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); if (ret) goto err5; @@ -441,12 +441,10 @@ static int s3c_ac97_probe(struct platform_device *pdev) ret = samsung_asoc_dma_platform_register(&pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); - goto err6; + goto err5; } return 0; -err6: - snd_soc_unregister_component(&pdev->dev); err5: free_irq(irq_res->start, NULL); err4: @@ -461,8 +459,6 @@ static int s3c_ac97_remove(struct platform_device *pdev) { struct resource *irq_res; - snd_soc_unregister_component(&pdev->dev); - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (irq_res) free_irq(irq_res->start, NULL); diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c index 415ad81999c4..9506d7617223 100644 --- a/sound/soc/samsung/goni_wm8994.c +++ b/sound/soc/samsung/goni_wm8994.c @@ -274,8 +274,8 @@ static int __init goni_init(void) return -ENOMEM; /* register voice DAI here */ - ret = snd_soc_register_component(&goni_snd_device->dev, &voice_component, - &voice_dai, 1); + ret = devm_snd_soc_register_component(&goni_snd_device->dev, + &voice_component, &voice_dai, 1); if (ret) { platform_device_put(goni_snd_device); return ret; @@ -284,17 +284,14 @@ static int __init goni_init(void) platform_set_drvdata(goni_snd_device, &goni); ret = platform_device_add(goni_snd_device); - if (ret) { - snd_soc_unregister_component(&goni_snd_device->dev); + if (ret) platform_device_put(goni_snd_device); - } return ret; } static void __exit goni_exit(void) { - snd_soc_unregister_component(&goni_snd_device->dev); platform_device_unregister(goni_snd_device); } diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 38df2a86bd5f..90fcd522be1c 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -588,7 +588,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - ret = snd_soc_register_component(&pdev->dev, &s3c_pcm_component, + ret = devm_snd_soc_register_component(&pdev->dev, &s3c_pcm_component, &s3c_pcm_dai[pdev->id], 1); if (ret != 0) { dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret); @@ -598,13 +598,11 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) ret = samsung_asoc_dma_platform_register(&pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); - goto err6; + goto err5; } return 0; -err6: - snd_soc_unregister_component(&pdev->dev); err5: clk_disable_unprepare(pcm->pclk); clk_put(pcm->pclk); @@ -624,8 +622,6 @@ static int s3c_pcm_dev_remove(struct platform_device *pdev) struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; struct resource *mem_res; - snd_soc_unregister_component(&pdev->dev); - pm_runtime_disable(&pdev->dev); iounmap(pcm->regs); diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 79e7efb9283c..77a2ae50dc94 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -745,7 +745,7 @@ int s3c_i2sv2_register_component(struct device *dev, int id, dai_drv->suspend = s3c2412_i2s_suspend; dai_drv->resume = s3c2412_i2s_resume; - return snd_soc_register_component(dev, cmp_drv, dai_drv, 1); + return devm_snd_soc_register_component(dev, cmp_drv, dai_drv, 1); } EXPORT_SYMBOL_GPL(s3c_i2sv2_register_component); diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index f42da8df3e3c..843f315dcb3a 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -179,26 +179,14 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev) } ret = samsung_asoc_dma_platform_register(&pdev->dev); - if (ret) { + if (ret) pr_err("failed to register the DMA: %d\n", ret); - goto err; - } - return 0; -err: - snd_soc_unregister_component(&pdev->dev); return ret; } -static int s3c2412_iis_dev_remove(struct platform_device *pdev) -{ - snd_soc_unregister_component(&pdev->dev); - return 0; -} - static struct platform_driver s3c2412_iis_driver = { .probe = s3c2412_iis_dev_probe, - .remove = s3c2412_iis_dev_remove, .driver = { .name = "s3c2412-iis", .owner = THIS_MODULE, diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 8380443b1b39..4a6d206db222 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -475,34 +475,22 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) { int ret = 0; - ret = snd_soc_register_component(&pdev->dev, &s3c24xx_i2s_component, - &s3c24xx_i2s_dai, 1); + ret = devm_snd_soc_register_component(&pdev->dev, + &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); if (ret) { pr_err("failed to register the dai\n"); return ret; } ret = samsung_asoc_dma_platform_register(&pdev->dev); - if (ret) { + if (ret) pr_err("failed to register the dma: %d\n", ret); - goto err; - } - return 0; -err: - snd_soc_unregister_component(&pdev->dev); return ret; } -static int s3c24xx_iis_dev_remove(struct platform_device *pdev) -{ - snd_soc_unregister_component(&pdev->dev); - return 0; -} - static struct platform_driver s3c24xx_iis_driver = { .probe = s3c24xx_iis_dev_probe, - .remove = s3c24xx_iis_dev_remove, .driver = { .name = "s3c24xx-iis", .owner = THIS_MODULE, diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index 7d89d016fa49..e93a93e296f4 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -427,8 +427,8 @@ static int spdif_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, spdif); - ret = snd_soc_register_component(&pdev->dev, &samsung_spdif_component, - &samsung_spdif_dai, 1); + ret = devm_snd_soc_register_component(&pdev->dev, + &samsung_spdif_component, &samsung_spdif_dai, 1); if (ret != 0) { dev_err(&pdev->dev, "fail to register dai\n"); goto err4; @@ -444,12 +444,10 @@ static int spdif_probe(struct platform_device *pdev) ret = samsung_asoc_dma_platform_register(&pdev->dev); if (ret) { dev_err(&pdev->dev, "failed to register DMA: %d\n", ret); - goto err5; + goto err4; } return 0; -err5: - snd_soc_unregister_component(&pdev->dev); err4: iounmap(spdif->regs); err3: @@ -467,8 +465,6 @@ static int spdif_remove(struct platform_device *pdev) struct samsung_spdif_info *spdif = &spdif_info; struct resource *mem_res; - snd_soc_unregister_component(&pdev->dev); - iounmap(spdif->regs); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); From 1d55417e127985b955e0f87b5dd0c38daaa79cd3 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Wed, 21 May 2014 08:52:20 +0530 Subject: [PATCH 25/25] ASoC: samsung: Add devm_clk_get to pcm.c clk_get in probe function can be safely replaced with devm_clk_get. Signed-off-by: Tushar Behera Signed-off-by: Mark Brown --- sound/soc/samsung/pcm.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 90fcd522be1c..a3c9c9cba3b0 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -542,7 +542,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) /* Default is 128fs */ pcm->sclk_per_fs = 128; - pcm->cclk = clk_get(&pdev->dev, "audio-bus"); + pcm->cclk = devm_clk_get(&pdev->dev, "audio-bus"); if (IS_ERR(pcm->cclk)) { dev_err(&pdev->dev, "failed to get audio-bus\n"); ret = PTR_ERR(pcm->cclk); @@ -567,7 +567,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) goto err3; } - pcm->pclk = clk_get(&pdev->dev, "pcm"); + pcm->pclk = devm_clk_get(&pdev->dev, "pcm"); if (IS_ERR(pcm->pclk)) { dev_err(&pdev->dev, "failed to get pcm_clock\n"); ret = -ENOENT; @@ -605,14 +605,12 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) err5: clk_disable_unprepare(pcm->pclk); - clk_put(pcm->pclk); err4: iounmap(pcm->regs); err3: release_mem_region(mem_res->start, resource_size(mem_res)); err2: clk_disable_unprepare(pcm->cclk); - clk_put(pcm->cclk); err1: return ret; } @@ -631,8 +629,6 @@ static int s3c_pcm_dev_remove(struct platform_device *pdev) clk_disable_unprepare(pcm->cclk); clk_disable_unprepare(pcm->pclk); - clk_put(pcm->pclk); - clk_put(pcm->cclk); return 0; }