From a5d93da13c8671f6453ae273cbf1d5c61b897a33 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 17 Oct 2016 19:27:16 +0800 Subject: [PATCH 01/28] ASoC: rt5670: Enable MCLK detection There is a power saving mechanism in rt5670. It will turn off some unused power when MCLK is not present. We call that "MCLK detection" and it should be enabled by default. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 4 +++- sound/soc/codecs/rt5670.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 49caf1393aeb..6caac92143d4 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2889,6 +2889,9 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, if (ret != 0) dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); + regmap_update_bits(rt5670->regmap, RT5670_DIG_MISC, + RT5670_MCLK_DET, RT5670_MCLK_DET); + if (rt5670->pdata.in2_diff) regmap_update_bits(rt5670->regmap, RT5670_IN2, RT5670_IN_DF2, RT5670_IN_DF2); @@ -2903,7 +2906,6 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ); regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); - regmap_update_bits(rt5670->regmap, RT5670_DIG_MISC, 0x8, 0x8); } if (rt5670->pdata.jd_mode) { diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index 3f1b0f1df809..5ba485cae4e6 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h @@ -1914,6 +1914,7 @@ enum { #define RT5670_IF1_ADC1_IN2_SFT 11 #define RT5670_IF1_ADC2_IN1_SEL (0x1 << 10) #define RT5670_IF1_ADC2_IN1_SFT 10 +#define RT5670_MCLK_DET (0x1 << 3) /* General Control2 (0xfb) */ #define RT5670_RXDC_SRC_MASK (0x1 << 7) From 5faf071d08ddd1c1be66deaa93a09ccf43f5b538 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 21 Oct 2016 14:18:48 +0100 Subject: [PATCH 02/28] ASoC: samsung: i2s: Fixup last IRQ unsafe spin lock call Unfortunately, I seem to have missed a case where an IRQ safe spinlock was required, in samsung_i2s_dai_remove, when I fixed up the other calls in this patch: 316fa9e09ad7 ("ASoC: samsung: Use IRQ safe spin lock calls") This causes a lockdep warning when unbinding and rebinding the audio card: [ 104.357664] CPU0 CPU1 [ 104.362174] ---- ---- [ 104.366692] lock(&(&pri_dai->spinlock)->rlock); [ 104.371372] local_irq_disable(); [ 104.377283] lock(&(&substream->self_group.lock)->rlock); [ 104.385259] lock(&(&pri_dai->spinlock)->rlock); [ 104.392469] [ 104.395072] lock(&(&substream->self_group.lock)->rlock); [ 104.400710] [ 104.400710] *** DEADLOCK *** Fixes: ce8bcdbb61d9 ("ASoC: samsung: i2s: Protect more registers with a spinlock") Signed-off-by: Charles Keepax Reviewed-by: Krzysztof Kozlowski Reviewed-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 7e32cf4581f8..588aa0160a3f 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1029,12 +1029,13 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) { struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai); + unsigned long flags; if (!is_secondary(i2s)) { if (i2s->quirks & QUIRK_NEED_RSTCLR) { - spin_lock(i2s->lock); + spin_lock_irqsave(i2s->lock, flags); writel(0, i2s->addr + I2SCON); - spin_unlock(i2s->lock); + spin_unlock_irqrestore(i2s->lock, flags); } } From 892ccf0f2173a9ede5448411e9475616fb21fb51 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 25 Oct 2016 12:57:57 +0200 Subject: [PATCH 03/28] ASoC: s3c24xx_uda134x: Move global variables to driver's data structure Gather all driver's private variables in common data structure and allocate the data structure dynamically. Also unused ENFORCE_RATES symbol and local variable (leftovers from an erroneous rebase) are removed. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/s3c24xx_uda134x.c | 79 ++++++++++++++++------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 7853fbe6ccc9..81a78940967c 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c @@ -19,9 +19,15 @@ #include #include "regs-iis.h" - #include "s3c24xx-i2s.h" +struct s3c24xx_uda134x { + struct clk *xtal; + struct clk *pclk; + struct mutex clk_lock; + int clk_users; +}; + /* #define ENFORCE_RATES 1 */ /* Unfortunately the S3C24XX in master mode has a limited capacity of @@ -36,15 +42,6 @@ possible an error will be returned. */ -static struct clk *xtal; -static struct clk *pclk; -/* this is need because we don't have a place where to keep the - * pointers to the clocks in each substream. We get the clocks only - * when we are actually using them so we don't block stuff like - * frequency change or oscillator power-off */ -static int clk_users; -static DEFINE_MUTEX(clk_lock); - static unsigned int rates[33 * 2]; #ifdef ENFORCE_RATES static struct snd_pcm_hw_constraint_list hw_constraints_rates = { @@ -57,26 +54,24 @@ static struct snd_pcm_hw_constraint_list hw_constraints_rates = { static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct s3c24xx_uda134x *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -#ifdef ENFORCE_RATES - struct snd_pcm_runtime *runtime = substream->runtime; -#endif int ret = 0; - mutex_lock(&clk_lock); + mutex_lock(&priv->clk_lock); - if (clk_users == 0) { - xtal = clk_get(rtd->dev, "xtal"); - if (IS_ERR(xtal)) { + if (priv->clk_users == 0) { + priv->xtal = clk_get(rtd->dev, "xtal"); + if (IS_ERR(priv->xtal)) { dev_err(rtd->dev, "%s cannot get xtal\n", __func__); - ret = PTR_ERR(xtal); + ret = PTR_ERR(priv->xtal); } else { - pclk = clk_get(cpu_dai->dev, "iis"); - if (IS_ERR(pclk)) { + priv->pclk = clk_get(cpu_dai->dev, "iis"); + if (IS_ERR(priv->pclk)) { dev_err(rtd->dev, "%s cannot get pclk\n", __func__); - clk_put(xtal); - ret = PTR_ERR(pclk); + clk_put(priv->xtal); + ret = PTR_ERR(priv->pclk); } } if (!ret) { @@ -85,18 +80,19 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) for (i = 0; i < 2; i++) { int fs = i ? 256 : 384; - rates[i*33] = clk_get_rate(xtal) / fs; + rates[i*33] = clk_get_rate(priv->xtal) / fs; for (j = 1; j < 33; j++) - rates[i*33 + j] = clk_get_rate(pclk) / + rates[i*33 + j] = clk_get_rate(priv->pclk) / (j * fs); } } } - clk_users += 1; - mutex_unlock(&clk_lock); + priv->clk_users += 1; + mutex_unlock(&priv->clk_lock); + if (!ret) { #ifdef ENFORCE_RATES - ret = snd_pcm_hw_constraint_list(runtime, 0, + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); if (ret < 0) @@ -109,15 +105,18 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream) { - mutex_lock(&clk_lock); - clk_users -= 1; - if (clk_users == 0) { - clk_put(xtal); - xtal = NULL; - clk_put(pclk); - pclk = NULL; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct s3c24xx_uda134x *priv = snd_soc_card_get_drvdata(rtd->card); + + mutex_lock(&priv->clk_lock); + priv->clk_users -= 1; + if (priv->clk_users == 0) { + clk_put(priv->xtal); + priv->xtal = NULL; + clk_put(priv->pclk); + priv->pclk = NULL; } - mutex_unlock(&clk_lock); + mutex_unlock(&priv->clk_lock); } static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, @@ -228,10 +227,18 @@ static struct snd_soc_card snd_soc_s3c24xx_uda134x = { static int s3c24xx_uda134x_probe(struct platform_device *pdev) { struct snd_soc_card *card = &snd_soc_s3c24xx_uda134x; + struct s3c24xx_uda134x *priv; int ret; - platform_set_drvdata(pdev, card); + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + mutex_init(&priv->clk_lock); + card->dev = &pdev->dev; + platform_set_drvdata(pdev, card); + snd_soc_card_set_drvdata(card, priv); ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) From b57a089bd4213b5e33007f8293bf83a8b14e4729 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 25 Oct 2016 17:08:40 +0200 Subject: [PATCH 04/28] ASoC: samsung: s3c24xx-i2s: Don't use platform_data for DMA parameters Since the s3c24xx-dma is converted to use DMA map we can rely on the DMA subsystem to match DMA channels and slave devices, rather than passing DMA details from platform_data. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/s3c24xx-i2s.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index d59a47d8ca0f..29196a9933a6 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -30,8 +30,6 @@ #include "dma.h" #include "s3c24xx-i2s.h" -#include - static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_out = { .addr_width = 2, }; @@ -449,14 +447,8 @@ static const struct snd_soc_component_driver s3c24xx_i2s_component = { static int s3c24xx_iis_dev_probe(struct platform_device *pdev) { - int ret = 0; struct resource *res; - struct s3c_audio_pdata *pdata = dev_get_platdata(&pdev->dev); - - if (!pdata) { - dev_err(&pdev->dev, "missing platform data"); - return -ENXIO; - } + int ret = 0; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -468,9 +460,7 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) return PTR_ERR(s3c24xx_i2s.regs); s3c24xx_i2s_pcm_stereo_out.addr = res->start + S3C2410_IISFIFO; - s3c24xx_i2s_pcm_stereo_out.filter_data = pdata->dma_playback; s3c24xx_i2s_pcm_stereo_in.addr = res->start + S3C2410_IISFIFO; - s3c24xx_i2s_pcm_stereo_in.filter_data = pdata->dma_capture; ret = devm_snd_soc_register_component(&pdev->dev, &s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1); @@ -479,8 +469,7 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) return ret; } - ret = samsung_asoc_dma_platform_register(&pdev->dev, - pdata->dma_filter, + ret = samsung_asoc_dma_platform_register(&pdev->dev, NULL, NULL, NULL); if (ret) pr_err("failed to register the dma: %d\n", ret); From 2ef9555bd13d00c63fdbe3cdca6ab0e2ded42695 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 25 Oct 2016 17:08:41 +0200 Subject: [PATCH 05/28] ASoC: samsung: s3c24xx-i2s: Debug/error trace cleanup pr_err() are replaced with dev_err() so information about device the error logs refer to is also included. pr_debug() at beginning of each function are removed as they are likely very rarely used and can always be added again when doing any serious debugging. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/s3c24xx-i2s.c | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 29196a9933a6..7c7061bc0ded 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -54,8 +54,6 @@ static void s3c24xx_snd_txctrl(int on) u32 iiscon; u32 iismod; - pr_debug("Entered %s\n", __func__); - iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); @@ -99,8 +97,6 @@ static void s3c24xx_snd_rxctrl(int on) u32 iiscon; u32 iismod; - pr_debug("Entered %s\n", __func__); - iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); @@ -147,8 +143,6 @@ static int s3c24xx_snd_lrsync(void) u32 iiscon; int timeout = 50; /* 5ms */ - pr_debug("Entered %s\n", __func__); - while (1) { iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); if (iiscon & S3C2410_IISCON_LRINDEX) @@ -167,8 +161,6 @@ static int s3c24xx_snd_lrsync(void) */ static inline int s3c24xx_snd_is_clkmaster(void) { - pr_debug("Entered %s\n", __func__); - return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1; } @@ -180,8 +172,6 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, { u32 iismod; - pr_debug("Entered %s\n", __func__); - iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); pr_debug("hw_params r: IISMOD: %x \n", iismod); @@ -209,6 +199,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); pr_debug("hw_params w: IISMOD: %x \n", iismod); + return 0; } @@ -219,8 +210,6 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_dmaengine_dai_dma_data *dma_data; u32 iismod; - pr_debug("Entered %s\n", __func__); - dma_data = snd_soc_dai_get_dma_data(dai, substream); /* Working copies of register */ @@ -242,6 +231,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); pr_debug("hw_params w: IISMOD: %x\n", iismod); + return 0; } @@ -250,8 +240,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, { int ret = 0; - pr_debug("Entered %s\n", __func__); - switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -293,8 +281,6 @@ static int s3c24xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, { u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("Entered %s\n", __func__); - iismod &= ~S3C2440_IISMOD_MPLL; switch (clk_id) { @@ -319,8 +305,6 @@ static int s3c24xx_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, { u32 reg; - pr_debug("Entered %s\n", __func__); - switch (div_id) { case S3C24XX_DIV_BCLK: reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_FS_MASK; @@ -354,8 +338,6 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) { - pr_debug("Entered %s\n", __func__); - snd_soc_dai_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out, &s3c24xx_i2s_pcm_stereo_in); @@ -381,8 +363,6 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) #ifdef CONFIG_PM static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) { - pr_debug("Entered %s\n", __func__); - s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); s3c24xx_i2s.iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); @@ -395,7 +375,6 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) { - pr_debug("Entered %s\n", __func__); clk_prepare_enable(s3c24xx_i2s.iis_clk); writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); @@ -410,7 +389,6 @@ static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) #define s3c24xx_i2s_resume NULL #endif - #define S3C24XX_I2S_RATES \ (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ @@ -465,14 +443,14 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) 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"); + dev_err(&pdev->dev, "Failed to register the DAI\n"); return ret; } ret = samsung_asoc_dma_platform_register(&pdev->dev, NULL, NULL, NULL); if (ret) - pr_err("failed to register the dma: %d\n", ret); + dev_err(&pdev->dev, "Failed to register the DMA: %d\n", ret); return ret; } From c8c6f0d81de67198522e3f31142986c27d3cba81 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 27 Oct 2016 13:21:54 +0800 Subject: [PATCH 06/28] ASoC: rt5670: increse LDO power Inrecse LDO power for better performance. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 6caac92143d4..12d3bc14a558 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2618,7 +2618,7 @@ static int rt5670_set_bias_level(struct snd_soc_codec *codec, RT5670_OSW_L_DIS | RT5670_OSW_R_DIS); snd_soc_update_bits(codec, RT5670_DIG_MISC, 0x1, 0x1); snd_soc_update_bits(codec, RT5670_PWR_ANLG1, - RT5670_LDO_SEL_MASK, 0x3); + RT5670_LDO_SEL_MASK, 0x5); } break; case SND_SOC_BIAS_STANDBY: @@ -2626,7 +2626,7 @@ static int rt5670_set_bias_level(struct snd_soc_codec *codec, RT5670_PWR_VREF1 | RT5670_PWR_VREF2 | RT5670_PWR_FV1 | RT5670_PWR_FV2, 0); snd_soc_update_bits(codec, RT5670_PWR_ANLG1, - RT5670_LDO_SEL_MASK, 0x1); + RT5670_LDO_SEL_MASK, 0x3); break; case SND_SOC_BIAS_OFF: if (rt5670->pdata.jd_mode) From 15a190ffec3b3f5e632faaa01b92f4cef32d63a3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Oct 2016 03:37:26 +0000 Subject: [PATCH 07/28] ASoC: simple-scu-card: code sync: follow to simple family style simple sound card family are using very similar style, but because of its historical reason, there are small differences. For example pointer style, function name, caller postion etc... This patch synchronized simple card style to other simple card family Current simple-scu-card function naming is different from other simple card family. And related to it, the necessary operation position is also different. This patch synchronize these to other simple card family. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/generic/simple-scu-card.c | 105 ++++++++++++---------------- 1 file changed, 46 insertions(+), 59 deletions(-) diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index b9973a56bcb0..b8d8437ef3dd 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -101,7 +101,7 @@ static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } -static int asoc_simple_card_parse_links(struct device_node *np, +static int asoc_simple_card_dai_link_of(struct device_node *np, struct asoc_simple_card_priv *priv, unsigned int daifmt, int idx, bool is_fe) @@ -195,69 +195,19 @@ static int asoc_simple_card_parse_links(struct device_node *np, return 0; } -static int asoc_simple_card_dai_link_of(struct device_node *node, - struct asoc_simple_card_priv *priv) +static int asoc_simple_card_parse_of(struct device_node *node, + struct asoc_simple_card_priv *priv) + { struct device *dev = simple_priv_to_dev(priv); struct device_node *np; unsigned int daifmt = 0; - int ret, i; bool is_fe; - - /* find 1st codec */ - np = of_get_child_by_name(node, PREFIX "codec"); - if (!np) - return -ENODEV; - - ret = asoc_simple_card_parse_daifmt(dev, node, np, - PREFIX, &daifmt); - if (ret < 0) - return ret; - - i = 0; - for_each_child_of_node(node, np) { - is_fe = false; - if (strcmp(np->name, PREFIX "cpu") == 0) - is_fe = true; - - ret = asoc_simple_card_parse_links(np, priv, daifmt, i, is_fe); - if (ret < 0) - return ret; - i++; - } - - return 0; -} - -static int asoc_simple_card_parse_of(struct device_node *node, - struct asoc_simple_card_priv *priv, - struct device *dev) -{ - struct asoc_simple_dai *props; - struct snd_soc_dai_link *links; - int ret; - int num; + int ret, i; if (!node) return -EINVAL; - num = of_get_child_count(node); - props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL); - links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL); - if (!props || !links) - return -ENOMEM; - - priv->dai_props = props; - priv->dai_link = links; - - /* Init snd_soc_card */ - priv->snd_card.owner = THIS_MODULE; - priv->snd_card.dev = dev; - priv->snd_card.dai_link = priv->dai_link; - priv->snd_card.num_links = num; - priv->snd_card.codec_conf = &priv->codec_conf; - priv->snd_card.num_configs = 1; - ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing"); if (ret < 0) return ret; @@ -268,10 +218,27 @@ static int asoc_simple_card_parse_of(struct device_node *node, /* channels transfer */ of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels); - ret = asoc_simple_card_dai_link_of(node, priv); + /* find 1st codec */ + np = of_get_child_by_name(node, PREFIX "codec"); + if (!np) + return -ENODEV; + + ret = asoc_simple_card_parse_daifmt(dev, node, np, PREFIX, &daifmt); if (ret < 0) return ret; + i = 0; + for_each_child_of_node(node, np) { + is_fe = false; + if (strcmp(np->name, PREFIX "cpu") == 0) + is_fe = true; + + ret = asoc_simple_card_dai_link_of(np, priv, daifmt, i, is_fe); + if (ret < 0) + return ret; + i++; + } + ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX); if (ret < 0) return ret; @@ -287,16 +254,36 @@ static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_probe(struct platform_device *pdev) { struct asoc_simple_card_priv *priv; - struct device_node *np = pdev->dev.of_node; + struct snd_soc_dai_link *links; + struct asoc_simple_dai *props; struct device *dev = &pdev->dev; - int ret; + struct device_node *np = pdev->dev.of_node; + int num, ret; /* Allocate the private data */ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - ret = asoc_simple_card_parse_of(np, priv, dev); + num = of_get_child_count(np); + + props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL); + links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL); + if (!props || !links) + return -ENOMEM; + + priv->dai_props = props; + priv->dai_link = links; + + /* Init snd_soc_card */ + priv->snd_card.owner = THIS_MODULE; + priv->snd_card.dev = dev; + priv->snd_card.dai_link = priv->dai_link; + priv->snd_card.num_links = num; + priv->snd_card.codec_conf = &priv->codec_conf; + priv->snd_card.num_configs = 1; + + ret = asoc_simple_card_parse_of(np, priv); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); From 6910e8679ff4d256028003be2451deb31f13948e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Oct 2016 03:37:44 +0000 Subject: [PATCH 08/28] ASoC: simple-scu-card: code sync: rename asoc_simple_card_priv simple sound card family are using very similar style, but because of its historical reason, there are small differences. For example pointer style, function name, caller postion etc... This patch synchronized simple card style to other simple card family This patch renames asoc_simple_card_priv to simple_card_data, same as other simple card family. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/generic/simple-scu-card.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index b8d8437ef3dd..1704b187f6ee 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -22,7 +22,7 @@ #include #include -struct asoc_simple_card_priv { +struct simple_card_data { struct snd_soc_card snd_card; struct snd_soc_codec_conf codec_conf; struct asoc_simple_dai *dai_props; @@ -42,7 +42,7 @@ struct asoc_simple_card_priv { static int asoc_simple_card_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, rtd->num); @@ -52,7 +52,7 @@ static int asoc_simple_card_startup(struct snd_pcm_substream *substream) static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, rtd->num); @@ -66,7 +66,7 @@ static struct snd_soc_ops asoc_simple_card_ops = { static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) { - struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *dai; struct snd_soc_dai_link *dai_link; struct asoc_simple_dai *dai_props; @@ -84,7 +84,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { - struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, @@ -102,7 +102,7 @@ static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, } static int asoc_simple_card_dai_link_of(struct device_node *np, - struct asoc_simple_card_priv *priv, + struct simple_card_data *priv, unsigned int daifmt, int idx, bool is_fe) { @@ -196,7 +196,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *np, } static int asoc_simple_card_parse_of(struct device_node *node, - struct asoc_simple_card_priv *priv) + struct simple_card_data *priv) { struct device *dev = simple_priv_to_dev(priv); @@ -253,7 +253,7 @@ static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_probe(struct platform_device *pdev) { - struct asoc_simple_card_priv *priv; + struct simple_card_data *priv; struct snd_soc_dai_link *links; struct asoc_simple_dai *props; struct device *dev = &pdev->dev; From 193599264f3eb632f43f83f738b17241f91dbd5a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Oct 2016 03:38:00 +0000 Subject: [PATCH 09/28] ASoC: simple-scu-card: code sync: tidyup props/link naming simple sound card family are using very similar style, but because of its historical reason, there are small differences. For example pointer style, function name, caller postion etc... This patch synchronizes style to other simple card family so that be enable to easy reviewing. This patch uses dai_link/dai_props instead of links/props. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/generic/simple-scu-card.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index 1704b187f6ee..348e9a7c4d10 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -254,8 +254,8 @@ static int asoc_simple_card_parse_of(struct device_node *node, static int asoc_simple_card_probe(struct platform_device *pdev) { struct simple_card_data *priv; - struct snd_soc_dai_link *links; - struct asoc_simple_dai *props; + struct snd_soc_dai_link *dai_link; + struct asoc_simple_dai *dai_props; struct device *dev = &pdev->dev; struct device_node *np = pdev->dev.of_node; int num, ret; @@ -267,13 +267,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) num = of_get_child_count(np); - props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL); - links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL); - if (!props || !links) + dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL); + dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL); + if (!dai_props || !dai_link) return -ENOMEM; - priv->dai_props = props; - priv->dai_link = links; + priv->dai_props = dai_props; + priv->dai_link = dai_link; /* Init snd_soc_card */ priv->snd_card.owner = THIS_MODULE; From 6c1c06cb776cf9a34ceafc5be288aa3670aa3ef2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Oct 2016 03:38:28 +0000 Subject: [PATCH 10/28] ASoC: simple-card-utils: remove unnecessary cpu/codec pointer check Remove cpu/codec pointer check from asoc_simple_card_canonicalize_dailink() This is verbose check, and will be issue if CPU name was created by fmt_single_name() on simple-scu-card.c. see also asoc_simple_card_canonicalize_cpu() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/generic/simple-card-utils.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 1cb39309f5d5..e5b80f53093a 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -195,9 +195,6 @@ EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai); int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link) { - if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) - return -EINVAL; - /* Assumes platform == cpu */ if (!dai_link->platform_of_node) dai_link->platform_of_node = dai_link->cpu_of_node; From d8dbb4b327a84a7d373c8c4bf173bcab22f102ff Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 2 Nov 2016 12:28:17 +0100 Subject: [PATCH 11/28] ASoC: samsung: pcm: Conversion to use devm_ioremap_resource() This simplifies the code a bit and removes a hard coded IO memory region size. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/pcm.c | 60 +++++++++++------------------------------ 1 file changed, 16 insertions(+), 44 deletions(-) diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index c484985812ed..d50a6377c23d 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -499,13 +499,6 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) pcm_pdata = pdev->dev.platform_data; - /* Check for availability of necessary resource */ - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem_res) { - dev_err(&pdev->dev, "Unable to get register resource\n"); - return -ENXIO; - } - if (pcm_pdata && pcm_pdata->cfg_gpio && pcm_pdata->cfg_gpio(pdev)) { dev_err(&pdev->dev, "Unable to configure gpio\n"); return -EINVAL; @@ -519,36 +512,26 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) /* Default is 128fs */ pcm->sclk_per_fs = 128; + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pcm->regs = devm_ioremap_resource(&pdev->dev, mem_res); + if (IS_ERR(pcm->regs)) + return PTR_ERR(pcm->regs); + 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); - goto err1; + dev_err(&pdev->dev, "failed to get audio-bus clock\n"); + return PTR_ERR(pcm->cclk); } clk_prepare_enable(pcm->cclk); /* record our pcm structure for later use in the callbacks */ dev_set_drvdata(&pdev->dev, pcm); - if (!request_mem_region(mem_res->start, - resource_size(mem_res), "samsung-pcm")) { - dev_err(&pdev->dev, "Unable to request register region\n"); - ret = -EBUSY; - goto err2; - } - - pcm->regs = ioremap(mem_res->start, 0x100); - if (pcm->regs == NULL) { - dev_err(&pdev->dev, "cannot ioremap registers\n"); - ret = -ENXIO; - goto err3; - } - 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; - goto err4; + dev_err(&pdev->dev, "failed to get pcm clock\n"); + ret = PTR_ERR(pcm->pclk); + goto err_dis_cclk; } clk_prepare_enable(pcm->pclk); @@ -569,7 +552,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) NULL, NULL); if (ret) { dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); - goto err5; + goto err_dis_pclk; } pm_runtime_enable(&pdev->dev); @@ -578,36 +561,25 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) &s3c_pcm_dai[pdev->id], 1); if (ret != 0) { dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret); - goto err6; + goto err_dis_pm; } return 0; -err6: + +err_dis_pm: pm_runtime_disable(&pdev->dev); -err5: +err_dis_pclk: clk_disable_unprepare(pcm->pclk); -err4: - iounmap(pcm->regs); -err3: - release_mem_region(mem_res->start, resource_size(mem_res)); -err2: +err_dis_cclk: clk_disable_unprepare(pcm->cclk); -err1: return ret; } static int s3c_pcm_dev_remove(struct platform_device *pdev) { struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; - struct resource *mem_res; pm_runtime_disable(&pdev->dev); - - iounmap(pcm->regs); - - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem_res->start, resource_size(mem_res)); - clk_disable_unprepare(pcm->cclk); clk_disable_unprepare(pcm->pclk); From 5d3c1f633ea2984602bbbfe84e3e858050cb36f3 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 2 Nov 2016 12:11:47 +0100 Subject: [PATCH 12/28] ASoC: samsung: s2c24xx-i2s: remove redundant error message There is no need to report the resource request error in the driver as it is already handled within devm_ioremap_resource(). While at it also drop a redundant variable initialization. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/s3c24xx-i2s.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 3b4bef9025a7..c93169823c7c 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -426,13 +426,9 @@ static const struct snd_soc_component_driver s3c24xx_i2s_component = { static int s3c24xx_iis_dev_probe(struct platform_device *pdev) { struct resource *res; - int ret = 0; + int ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Can't get IO resource.\n"); - return -ENOENT; - } s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(s3c24xx_i2s.regs)) return PTR_ERR(s3c24xx_i2s.regs); From a076d418235fc94030733b43114a4f1a0a3b4489 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 2 Nov 2016 12:06:55 +0100 Subject: [PATCH 13/28] ASoC: samsung: Drop AC97 drivers The AC97 drivers are broken and it seems these have not been used for a long time. This patch removes the unused code, i.e. Samsung SoC AC97 controller driver and related machine drivers: ln2440sbc_alc650, smdk2443_wm9710, smdk_wm9713. Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 32 -- sound/soc/samsung/Makefile | 2 - sound/soc/samsung/ac97.c | 437 --------------------------- sound/soc/samsung/ln2440sbc_alc650.c | 72 ----- sound/soc/samsung/regs-ac97.h | 66 ---- sound/soc/samsung/smdk2443_wm9710.c | 68 ----- sound/soc/samsung/smdk_wm9713.c | 108 ------- 7 files changed, 785 deletions(-) delete mode 100644 sound/soc/samsung/ac97.c delete mode 100644 sound/soc/samsung/ln2440sbc_alc650.c delete mode 100644 sound/soc/samsung/regs-ac97.h delete mode 100644 sound/soc/samsung/smdk2443_wm9710.c delete mode 100644 sound/soc/samsung/smdk_wm9713.c diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index f6023b46c107..1d2ef4c2afd0 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -22,10 +22,6 @@ config SND_S3C2412_SOC_I2S config SND_SAMSUNG_PCM tristate "Samsung PCM interface support" -config SND_SAMSUNG_AC97 - tristate - select SND_SOC_AC97_BUS - config SND_SAMSUNG_SPDIF tristate "Samsung SPDIF transmitter support" select SND_SOC_SPDIF @@ -69,26 +65,6 @@ config SND_SOC_SAMSUNG_SMDK_WM8994 help Say Y if you want to add support for SoC audio on the SMDKs. -config SND_SOC_SAMSUNG_SMDK2443_WM9710 - tristate "SoC AC97 Audio support for SMDK2443 - WM9710" - depends on MACH_SMDK2443 - select AC97_BUS - select SND_SOC_AC97_CODEC - select SND_SAMSUNG_AC97 - help - Say Y if you want to add support for SoC audio on smdk2443 - with the WM9710. - -config SND_SOC_SAMSUNG_LN2440SBC_ALC650 - tristate "SoC AC97 Audio support for LN2440SBC - ALC650" - depends on ARCH_S3C24XX - select AC97_BUS - select SND_SOC_AC97_CODEC - select SND_SAMSUNG_AC97 - help - Say Y if you want to add support for SoC audio on ln2440sbc - with the ALC650. - config SND_SOC_SAMSUNG_S3C24XX_UDA134X tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" depends on ARCH_S3C24XX @@ -131,14 +107,6 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380 help This driver provides audio support for HP iPAQ RX1950 PDA. -config SND_SOC_SAMSUNG_SMDK_WM9713 - tristate "SoC AC97 Audio support for SMDK with WM9713" - depends on MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 - select SND_SOC_WM9713 - select SND_SAMSUNG_AC97 - help - Say Y if you want to add support for SoC audio on the SMDK. - config SND_SOC_SMARTQ tristate "SoC I2S Audio support for SmartQ board" depends on MACH_SMARTQ && I2C diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 5d03f5ce6916..f3f4a32cd376 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -3,7 +3,6 @@ snd-soc-s3c-dma-objs := dmaengine.o snd-soc-idma-objs := idma.o snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o -snd-soc-ac97-objs := ac97.o snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o snd-soc-samsung-spdif-objs := spdif.o snd-soc-pcm-objs := pcm.o @@ -11,7 +10,6 @@ snd-soc-i2s-objs := i2s.o obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c-dma.o obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o -obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c deleted file mode 100644 index cbc0023c2bc8..000000000000 --- a/sound/soc/samsung/ac97.c +++ /dev/null @@ -1,437 +0,0 @@ -/* sound/soc/samsung/ac97.c - * - * ALSA SoC Audio Layer - S3C AC97 Controller driver - * Evolved from s3c2443-ac97.c - * - * Copyright (c) 2010 Samsung Electronics Co. Ltd - * Author: Jaswinder Singh - * Credits: Graeme Gregory, Sean Choi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include - -#include "regs-ac97.h" -#include - -#include "dma.h" - -#define AC_CMD_ADDR(x) (x << 16) -#define AC_CMD_DATA(x) (x & 0xffff) - -#define S3C_AC97_DAI_PCM 0 -#define S3C_AC97_DAI_MIC 1 - -struct s3c_ac97_info { - struct clk *ac97_clk; - void __iomem *regs; - struct mutex lock; - struct completion done; -}; -static struct s3c_ac97_info s3c_ac97; - -static struct snd_dmaengine_dai_dma_data s3c_ac97_pcm_out = { - .addr_width = 4, -}; - -static struct snd_dmaengine_dai_dma_data s3c_ac97_pcm_in = { - .addr_width = 4, -}; - -static struct snd_dmaengine_dai_dma_data s3c_ac97_mic_in = { - .addr_width = 4, -}; - -static void s3c_ac97_activate(struct snd_ac97 *ac97) -{ - u32 ac_glbctrl, stat; - - stat = readl(s3c_ac97.regs + S3C_AC97_GLBSTAT) & 0x7; - if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE) - return; /* Return if already active */ - - reinit_completion(&s3c_ac97.done); - - ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); - ac_glbctrl = S3C_AC97_GLBCTRL_ACLINKON; - writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - msleep(1); - - ac_glbctrl |= S3C_AC97_GLBCTRL_TRANSFERDATAENABLE; - writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - msleep(1); - - ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); - ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE; - writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - - if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) - pr_err("AC97: Unable to activate!\n"); -} - -static unsigned short s3c_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - u32 ac_glbctrl, ac_codec_cmd; - u32 stat, addr, data; - - mutex_lock(&s3c_ac97.lock); - - s3c_ac97_activate(ac97); - - reinit_completion(&s3c_ac97.done); - - ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD); - ac_codec_cmd = S3C_AC97_CODEC_CMD_READ | AC_CMD_ADDR(reg); - writel(ac_codec_cmd, s3c_ac97.regs + S3C_AC97_CODEC_CMD); - - udelay(50); - - ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); - ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE; - writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - - if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) - pr_err("AC97: Unable to read!\n"); - - stat = readl(s3c_ac97.regs + S3C_AC97_STAT); - addr = (stat >> 16) & 0x7f; - data = (stat & 0xffff); - - if (addr != reg) - pr_err("ac97: req addr = %02x, rep addr = %02x\n", - reg, addr); - - mutex_unlock(&s3c_ac97.lock); - - return (unsigned short)data; -} - -static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - u32 ac_glbctrl, ac_codec_cmd; - - mutex_lock(&s3c_ac97.lock); - - s3c_ac97_activate(ac97); - - reinit_completion(&s3c_ac97.done); - - ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD); - ac_codec_cmd = AC_CMD_ADDR(reg) | AC_CMD_DATA(val); - writel(ac_codec_cmd, s3c_ac97.regs + S3C_AC97_CODEC_CMD); - - udelay(50); - - ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); - ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE; - writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - - if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) - pr_err("AC97: Unable to write!\n"); - - ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD); - ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ; - writel(ac_codec_cmd, s3c_ac97.regs + S3C_AC97_CODEC_CMD); - - mutex_unlock(&s3c_ac97.lock); -} - -static void s3c_ac97_cold_reset(struct snd_ac97 *ac97) -{ - pr_debug("AC97: Cold reset\n"); - writel(S3C_AC97_GLBCTRL_COLDRESET, - s3c_ac97.regs + S3C_AC97_GLBCTRL); - msleep(1); - - writel(0, s3c_ac97.regs + S3C_AC97_GLBCTRL); - msleep(1); -} - -static void s3c_ac97_warm_reset(struct snd_ac97 *ac97) -{ - u32 stat; - - stat = readl(s3c_ac97.regs + S3C_AC97_GLBSTAT) & 0x7; - if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE) - return; /* Return if already active */ - - pr_debug("AC97: Warm reset\n"); - - writel(S3C_AC97_GLBCTRL_WARMRESET, s3c_ac97.regs + S3C_AC97_GLBCTRL); - msleep(1); - - writel(0, s3c_ac97.regs + S3C_AC97_GLBCTRL); - msleep(1); - - s3c_ac97_activate(ac97); -} - -static irqreturn_t s3c_ac97_irq(int irq, void *dev_id) -{ - u32 ac_glbctrl, ac_glbstat; - - ac_glbstat = readl(s3c_ac97.regs + S3C_AC97_GLBSTAT); - - if (ac_glbstat & S3C_AC97_GLBSTAT_CODECREADY) { - - ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); - ac_glbctrl &= ~S3C_AC97_GLBCTRL_CODECREADYIE; - writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - - complete(&s3c_ac97.done); - } - - ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); - ac_glbctrl |= (1<<30); /* Clear interrupt */ - writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - - return IRQ_HANDLED; -} - -static struct snd_ac97_bus_ops s3c_ac97_ops = { - .read = s3c_ac97_read, - .write = s3c_ac97_write, - .warm_reset = s3c_ac97_warm_reset, - .reset = s3c_ac97_cold_reset, -}; - -static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - u32 ac_glbctrl; - - ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMINTM_MASK; - else - ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMOUTTM_MASK; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - ac_glbctrl |= S3C_AC97_GLBCTRL_PCMINTM_DMA; - else - ac_glbctrl |= S3C_AC97_GLBCTRL_PCMOUTTM_DMA; - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - break; - } - - writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - - return 0; -} - -static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - u32 ac_glbctrl; - - ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); - ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ac_glbctrl |= S3C_AC97_GLBCTRL_MICINTM_DMA; - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - break; - } - - writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - - return 0; -} - -static const struct snd_soc_dai_ops s3c_ac97_dai_ops = { - .trigger = s3c_ac97_trigger, -}; - -static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = { - .trigger = s3c_ac97_mic_trigger, -}; - -static int s3c_ac97_dai_probe(struct snd_soc_dai *dai) -{ - snd_soc_dai_init_dma_data(dai, &s3c_ac97_pcm_out, &s3c_ac97_pcm_in); - - return 0; -} - -static int s3c_ac97_mic_dai_probe(struct snd_soc_dai *dai) -{ - snd_soc_dai_init_dma_data(dai, NULL, &s3c_ac97_mic_in); - - return 0; -} - -static struct snd_soc_dai_driver s3c_ac97_dai[] = { - [S3C_AC97_DAI_PCM] = { - .name = "samsung-ac97", - .bus_control = true, - .playback = { - .stream_name = "AC97 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .stream_name = "AC97 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .probe = s3c_ac97_dai_probe, - .ops = &s3c_ac97_dai_ops, - }, - [S3C_AC97_DAI_MIC] = { - .name = "samsung-ac97-mic", - .bus_control = true, - .capture = { - .stream_name = "AC97 Mic Capture", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .probe = s3c_ac97_mic_dai_probe, - .ops = &s3c_ac97_mic_dai_ops, - }, -}; - -static const struct snd_soc_component_driver s3c_ac97_component = { - .name = "s3c-ac97", -}; - -static int s3c_ac97_probe(struct platform_device *pdev) -{ - struct resource *mem_res, *irq_res; - struct s3c_audio_pdata *ac97_pdata; - int ret; - - ac97_pdata = pdev->dev.platform_data; - if (!ac97_pdata || !ac97_pdata->cfg_gpio) { - dev_err(&pdev->dev, "cfg_gpio callback not provided!\n"); - return -EINVAL; - } - - /* Check for availability of necessary resource */ - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq_res) { - dev_err(&pdev->dev, "AC97 IRQ not provided!\n"); - return -ENXIO; - } - - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res); - if (IS_ERR(s3c_ac97.regs)) - return PTR_ERR(s3c_ac97.regs); - - s3c_ac97_pcm_out.filter_data = ac97_pdata->dma_playback; - s3c_ac97_pcm_out.addr = mem_res->start + S3C_AC97_PCM_DATA; - s3c_ac97_pcm_in.filter_data = ac97_pdata->dma_capture; - s3c_ac97_pcm_in.addr = mem_res->start + S3C_AC97_PCM_DATA; - s3c_ac97_mic_in.filter_data = ac97_pdata->dma_capture_mic; - s3c_ac97_mic_in.addr = mem_res->start + S3C_AC97_MIC_DATA; - - init_completion(&s3c_ac97.done); - mutex_init(&s3c_ac97.lock); - - s3c_ac97.ac97_clk = devm_clk_get(&pdev->dev, "ac97"); - if (IS_ERR(s3c_ac97.ac97_clk)) { - dev_err(&pdev->dev, "ac97 failed to get ac97_clock\n"); - ret = -ENODEV; - goto err2; - } - clk_prepare_enable(s3c_ac97.ac97_clk); - - if (ac97_pdata->cfg_gpio(pdev)) { - dev_err(&pdev->dev, "Unable to configure gpio\n"); - ret = -EINVAL; - goto err3; - } - - ret = request_irq(irq_res->start, s3c_ac97_irq, - 0, "AC97", NULL); - if (ret < 0) { - dev_err(&pdev->dev, "ac97: interrupt request failed.\n"); - goto err4; - } - - ret = snd_soc_set_ac97_ops(&s3c_ac97_ops); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); - goto err4; - } - - ret = samsung_asoc_dma_platform_register(&pdev->dev, - ac97_pdata->dma_filter, - NULL, NULL); - if (ret) { - dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); - goto err5; - } - - ret = devm_snd_soc_register_component(&pdev->dev, &s3c_ac97_component, - s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); - if (ret) - goto err5; - - return 0; -err5: - free_irq(irq_res->start, NULL); -err4: -err3: - clk_disable_unprepare(s3c_ac97.ac97_clk); -err2: - snd_soc_set_ac97_ops(NULL); - return ret; -} - -static int s3c_ac97_remove(struct platform_device *pdev) -{ - struct resource *irq_res; - - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (irq_res) - free_irq(irq_res->start, NULL); - - clk_disable_unprepare(s3c_ac97.ac97_clk); - snd_soc_set_ac97_ops(NULL); - - return 0; -} - -static struct platform_driver s3c_ac97_driver = { - .probe = s3c_ac97_probe, - .remove = s3c_ac97_remove, - .driver = { - .name = "samsung-ac97", - }, -}; - -module_platform_driver(s3c_ac97_driver); - -MODULE_AUTHOR("Jaswinder Singh, "); -MODULE_DESCRIPTION("AC97 driver for the Samsung SoC"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:samsung-ac97"); diff --git a/sound/soc/samsung/ln2440sbc_alc650.c b/sound/soc/samsung/ln2440sbc_alc650.c deleted file mode 100644 index 9342fc270c2b..000000000000 --- a/sound/soc/samsung/ln2440sbc_alc650.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SoC audio for ln2440sbc - * - * Copyright 2007 KonekTel, a.s. - * Author: Ivan Kuten - * ivan.kuten@promwad.com - * - * Heavily based on smdk2443_wm9710.c - * Copyright 2007 Wolfson Microelectronics PLC. - * Author: Graeme Gregory - * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com - * - * 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 - -static struct snd_soc_card ln2440sbc; - -static struct snd_soc_dai_link ln2440sbc_dai[] = { -{ - .name = "AC97", - .stream_name = "AC97 HiFi", - .cpu_dai_name = "samsung-ac97", - .codec_dai_name = "ac97-hifi", - .codec_name = "ac97-codec", - .platform_name = "samsung-ac97", -}, -}; - -static struct snd_soc_card ln2440sbc = { - .name = "LN2440SBC", - .owner = THIS_MODULE, - .dai_link = ln2440sbc_dai, - .num_links = ARRAY_SIZE(ln2440sbc_dai), -}; - -static struct platform_device *ln2440sbc_snd_ac97_device; - -static int __init ln2440sbc_init(void) -{ - int ret; - - ln2440sbc_snd_ac97_device = platform_device_alloc("soc-audio", -1); - if (!ln2440sbc_snd_ac97_device) - return -ENOMEM; - - platform_set_drvdata(ln2440sbc_snd_ac97_device, &ln2440sbc); - ret = platform_device_add(ln2440sbc_snd_ac97_device); - - if (ret) - platform_device_put(ln2440sbc_snd_ac97_device); - - return ret; -} - -static void __exit ln2440sbc_exit(void) -{ - platform_device_unregister(ln2440sbc_snd_ac97_device); -} - -module_init(ln2440sbc_init); -module_exit(ln2440sbc_exit); - -/* Module information */ -MODULE_AUTHOR("Ivan Kuten"); -MODULE_DESCRIPTION("ALSA SoC ALC650 LN2440SBC"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/samsung/regs-ac97.h b/sound/soc/samsung/regs-ac97.h deleted file mode 100644 index a71be45bbffc..000000000000 --- a/sound/soc/samsung/regs-ac97.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2006 Simtec Electronics - * http://www.simtec.co.uk/products/SWLINUX/ - * - * 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. - * - * S3C2440 AC97 Controller -*/ - -#ifndef __SAMSUNG_REGS_AC97_H__ -#define __SAMSUNG_REGS_AC97_H__ - -#define S3C_AC97_GLBCTRL (0x00) - -#define S3C_AC97_GLBCTRL_CODECREADYIE (1<<22) -#define S3C_AC97_GLBCTRL_PCMOUTURIE (1<<21) -#define S3C_AC97_GLBCTRL_PCMINORIE (1<<20) -#define S3C_AC97_GLBCTRL_MICINORIE (1<<19) -#define S3C_AC97_GLBCTRL_PCMOUTTIE (1<<18) -#define S3C_AC97_GLBCTRL_PCMINTIE (1<<17) -#define S3C_AC97_GLBCTRL_MICINTIE (1<<16) -#define S3C_AC97_GLBCTRL_PCMOUTTM_OFF (0<<12) -#define S3C_AC97_GLBCTRL_PCMOUTTM_PIO (1<<12) -#define S3C_AC97_GLBCTRL_PCMOUTTM_DMA (2<<12) -#define S3C_AC97_GLBCTRL_PCMOUTTM_MASK (3<<12) -#define S3C_AC97_GLBCTRL_PCMINTM_OFF (0<<10) -#define S3C_AC97_GLBCTRL_PCMINTM_PIO (1<<10) -#define S3C_AC97_GLBCTRL_PCMINTM_DMA (2<<10) -#define S3C_AC97_GLBCTRL_PCMINTM_MASK (3<<10) -#define S3C_AC97_GLBCTRL_MICINTM_OFF (0<<8) -#define S3C_AC97_GLBCTRL_MICINTM_PIO (1<<8) -#define S3C_AC97_GLBCTRL_MICINTM_DMA (2<<8) -#define S3C_AC97_GLBCTRL_MICINTM_MASK (3<<8) -#define S3C_AC97_GLBCTRL_TRANSFERDATAENABLE (1<<3) -#define S3C_AC97_GLBCTRL_ACLINKON (1<<2) -#define S3C_AC97_GLBCTRL_WARMRESET (1<<1) -#define S3C_AC97_GLBCTRL_COLDRESET (1<<0) - -#define S3C_AC97_GLBSTAT (0x04) - -#define S3C_AC97_GLBSTAT_CODECREADY (1<<22) -#define S3C_AC97_GLBSTAT_PCMOUTUR (1<<21) -#define S3C_AC97_GLBSTAT_PCMINORI (1<<20) -#define S3C_AC97_GLBSTAT_MICINORI (1<<19) -#define S3C_AC97_GLBSTAT_PCMOUTTI (1<<18) -#define S3C_AC97_GLBSTAT_PCMINTI (1<<17) -#define S3C_AC97_GLBSTAT_MICINTI (1<<16) -#define S3C_AC97_GLBSTAT_MAINSTATE_IDLE (0<<0) -#define S3C_AC97_GLBSTAT_MAINSTATE_INIT (1<<0) -#define S3C_AC97_GLBSTAT_MAINSTATE_READY (2<<0) -#define S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE (3<<0) -#define S3C_AC97_GLBSTAT_MAINSTATE_LP (4<<0) -#define S3C_AC97_GLBSTAT_MAINSTATE_WARM (5<<0) - -#define S3C_AC97_CODEC_CMD (0x08) - -#define S3C_AC97_CODEC_CMD_READ (1<<23) - -#define S3C_AC97_STAT (0x0c) -#define S3C_AC97_PCM_ADDR (0x10) -#define S3C_AC97_PCM_DATA (0x18) -#define S3C_AC97_MIC_DATA (0x1C) - -#endif /* __SAMSUNG_REGS_AC97_H__ */ diff --git a/sound/soc/samsung/smdk2443_wm9710.c b/sound/soc/samsung/smdk2443_wm9710.c deleted file mode 100644 index c390aad68cfb..000000000000 --- a/sound/soc/samsung/smdk2443_wm9710.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * smdk2443_wm9710.c -- SoC audio for smdk2443 - * - * Copyright 2007 Wolfson Microelectronics PLC. - * Author: Graeme Gregory - * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include - -static struct snd_soc_card smdk2443; - -static struct snd_soc_dai_link smdk2443_dai[] = { -{ - .name = "AC97", - .stream_name = "AC97 HiFi", - .cpu_dai_name = "samsung-ac97", - .codec_dai_name = "ac97-hifi", - .codec_name = "ac97-codec", - .platform_name = "samsung-ac97", -}, -}; - -static struct snd_soc_card smdk2443 = { - .name = "SMDK2443", - .owner = THIS_MODULE, - .dai_link = smdk2443_dai, - .num_links = ARRAY_SIZE(smdk2443_dai), -}; - -static struct platform_device *smdk2443_snd_ac97_device; - -static int __init smdk2443_init(void) -{ - int ret; - - smdk2443_snd_ac97_device = platform_device_alloc("soc-audio", -1); - if (!smdk2443_snd_ac97_device) - return -ENOMEM; - - platform_set_drvdata(smdk2443_snd_ac97_device, &smdk2443); - ret = platform_device_add(smdk2443_snd_ac97_device); - - if (ret) - platform_device_put(smdk2443_snd_ac97_device); - - return ret; -} - -static void __exit smdk2443_exit(void) -{ - platform_device_unregister(smdk2443_snd_ac97_device); -} - -module_init(smdk2443_init); -module_exit(smdk2443_exit); - -/* Module information */ -MODULE_AUTHOR("Graeme Gregory, graeme.gregory@wolfsonmicro.com, www.wolfsonmicro.com"); -MODULE_DESCRIPTION("ALSA SoC WM9710 SMDK2443"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/samsung/smdk_wm9713.c b/sound/soc/samsung/smdk_wm9713.c deleted file mode 100644 index 0d20e4ed27aa..000000000000 --- a/sound/soc/samsung/smdk_wm9713.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * smdk_wm9713.c -- SoC audio for SMDK - * - * Copyright 2010 Samsung Electronics Co. Ltd. - * Author: Jaswinder Singh Brar - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - */ - -#include -#include - -static struct snd_soc_card smdk; - -/* - * Default CFG switch settings to use this driver: - * - * SMDK6410: Set CFG1 1-3 On, CFG2 1-4 Off - * SMDKC100: Set CFG6 1-3 On, CFG7 1 On - * SMDKC110: Set CFGB10 1-2 Off, CFGB12 1-3 On - * SMDKV210: Set CFGB10 1-2 Off, CFGB12 1-3 On - * SMDKV310: Set CFG2 1-2 Off, CFG4 All On, CFG7 All Off, CFG8 1-On - */ - -/* - Playback (HeadPhone):- - $ amixer sset 'Headphone' unmute - $ amixer sset 'Right Headphone Out Mux' 'Headphone' - $ amixer sset 'Left Headphone Out Mux' 'Headphone' - $ amixer sset 'Right HP Mixer PCM' unmute - $ amixer sset 'Left HP Mixer PCM' unmute - - Capture (LineIn):- - $ amixer sset 'Right Capture Source' 'Line' - $ amixer sset 'Left Capture Source' 'Line' -*/ - -static struct snd_soc_dai_link smdk_dai = { - .name = "AC97", - .stream_name = "AC97 PCM", - .platform_name = "samsung-ac97", - .cpu_dai_name = "samsung-ac97", - .codec_dai_name = "wm9713-hifi", - .codec_name = "wm9713-codec", -}; - -static struct snd_soc_card smdk = { - .name = "SMDK WM9713", - .owner = THIS_MODULE, - .dai_link = &smdk_dai, - .num_links = 1, -}; - -static struct platform_device *smdk_snd_wm9713_device; -static struct platform_device *smdk_snd_ac97_device; - -static int __init smdk_init(void) -{ - int ret; - - smdk_snd_wm9713_device = platform_device_alloc("wm9713-codec", -1); - if (!smdk_snd_wm9713_device) - return -ENOMEM; - - ret = platform_device_add(smdk_snd_wm9713_device); - if (ret) - goto err1; - - smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); - if (!smdk_snd_ac97_device) { - ret = -ENOMEM; - goto err2; - } - - platform_set_drvdata(smdk_snd_ac97_device, &smdk); - - ret = platform_device_add(smdk_snd_ac97_device); - if (ret) - goto err3; - - return 0; - -err3: - platform_device_put(smdk_snd_ac97_device); -err2: - platform_device_del(smdk_snd_wm9713_device); -err1: - platform_device_put(smdk_snd_wm9713_device); - return ret; -} - -static void __exit smdk_exit(void) -{ - platform_device_unregister(smdk_snd_ac97_device); - platform_device_unregister(smdk_snd_wm9713_device); -} - -module_init(smdk_init); -module_exit(smdk_exit); - -/* Module information */ -MODULE_AUTHOR("Jaswinder Singh Brar, jassisinghbrar@gmail.com"); -MODULE_DESCRIPTION("ALSA SoC SMDK+WM9713"); -MODULE_LICENSE("GPL"); From 6c9473c55e7bb93dd4086f74e8e727dd3350855d Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 2 Nov 2016 12:04:36 +0100 Subject: [PATCH 14/28] ASoC: samsung: s3c24xx-i2s.c merge fixup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a build error as below which appeared after merging branch fix/samsung and also proper error messages are restored. sound/soc/samsung/s3c24xx-i2s.c: In function ‘s3c24xx_iis_dev_probe’: sound/soc/samsung/s3c24xx-i2s.c:444:8: error: ‘pdata’ undeclared (first use in this function) sound/soc/samsung/s3c24xx-i2s.c:444:8: note: each undeclared identifier is reported only once for each function it appears in Signed-off-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/s3c24xx-i2s.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index c93169823c7c..07f5091b33e8 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -436,18 +436,17 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev) s3c24xx_i2s_pcm_stereo_out.addr = res->start + S3C2410_IISFIFO; s3c24xx_i2s_pcm_stereo_in.addr = res->start + S3C2410_IISFIFO; - ret = samsung_asoc_dma_platform_register(&pdev->dev, - pdata->dma_filter, + ret = samsung_asoc_dma_platform_register(&pdev->dev, NULL, NULL, NULL); if (ret) { - dev_err(&pdev->dev, "Failed to register the DAI\n"); + dev_err(&pdev->dev, "Failed to register the DMA: %d\n", ret); return ret; } 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"); + dev_err(&pdev->dev, "Failed to register the DAI\n"); return ret; } From 5acbd343980b034b6ea9b01824cc28d0b01cf4d8 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Thu, 10 Nov 2016 08:11:55 +0100 Subject: [PATCH 15/28] ASoC: samsung: Makefile cleanup Commit a076d418235f ("ASoC: samsung: Drop AC97 drivers") removed some unused code and the associated Kconfig options, but left those options referenced in the Makefile. Remove the leftover references in the Makefile. Signed-off-by: Valentin Rothberg Reviewed-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index f3f4a32cd376..27956621c849 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -45,8 +45,6 @@ snd-soc-arndale-rt5631-objs := arndale_rt5631.o obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o -obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o -obj-$(CONFIG_SND_SOC_SAMSUNG_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o obj-$(CONFIG_SND_SOC_SAMSUNG_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC) += snd-soc-s3c24xx-simtec.o obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o @@ -56,7 +54,6 @@ 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 obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o From f174c1db904fe49713571a3ea2547b79da025fa9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 9 Nov 2016 19:45:10 +0100 Subject: [PATCH 16/28] ASoC: samsung: Remove unselectable smdk_wm8580pcm The SND_SOC_SMDK_WM8580_PCM Kconfig entry depends on either MACH_SMDKV210 or MACH_SMDKC110. Both of which were removed in commit 28c8331d386a ("ARM: S5PV210: Remove support for board files") over two years ago. The driver has been unselectable ever since. Considering the lack of complaints about this it can be concluded that the driver is unused and can be removed. Signed-off-by: Lars-Peter Clausen Reviewed-by: Krzysztof Kozlowski Reviewed-by: Sylwester Nawrocki Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 9 -- sound/soc/samsung/Makefile | 2 - sound/soc/samsung/smdk_wm8580pcm.c | 175 ----------------------------- 3 files changed, 186 deletions(-) delete mode 100644 sound/soc/samsung/smdk_wm8580pcm.c diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 1d2ef4c2afd0..79ae6a7c93ff 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -119,15 +119,6 @@ config SND_SOC_SAMSUNG_SMDK_SPDIF help Say Y if you want to add support for SoC S/PDIF audio on the SMDK. -config SND_SOC_SMDK_WM8580_PCM - tristate "SoC PCM Audio support for WM8580 on SMDK" - depends on MACH_SMDKV210 || MACH_SMDKC110 - depends on I2C - select SND_SOC_WM8580 - select SND_SAMSUNG_PCM - help - Say Y if you want to add support for SoC audio on the SMDK. - config SND_SOC_SMDK_WM8994_PCM tristate "SoC PCM Audio support for WM8994 on SMDK" depends on I2C=y diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 27956621c849..c95b6835361f 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -34,7 +34,6 @@ 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-smdk-spdif-objs := smdk_spdif.o -snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o snd-soc-speyside-objs := speyside.o snd-soc-tobermory-objs := tobermory.o @@ -56,7 +55,6 @@ 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_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF) += snd-soc-smdk-spdif.o -obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c deleted file mode 100644 index a6d223310c67..000000000000 --- a/sound/soc/samsung/smdk_wm8580pcm.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * sound/soc/samsung/smdk_wm8580pcm.c - * - * Copyright (c) 2011 Samsung Electronics Co. Ltd - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include -#include - -#include - -#include "../codecs/wm8580.h" -#include "pcm.h" - -/* - * Board Settings: - * o '1' means 'ON' - * o '0' means 'OFF' - * o 'X' means 'Don't care' - * - * SMDK6410 Base B/D: CFG1-0000, CFG2-1111 - * SMDKC110, SMDKV210: CFGB11-100100, CFGB12-0000 - */ - -#define SMDK_WM8580_EXT_OSC 12000000 -#define SMDK_WM8580_EXT_MCLK 4096000 -#define SMDK_WM8580_EXT_VOICE 2048000 - -static unsigned long mclk_freq; -static unsigned long xtal_freq; - -/* - * If MCLK clock directly gets from XTAL, we don't have to use PLL - * to make MCLK, but if XTAL clock source connects with other codec - * pin (like XTI), we should have to set codec's PLL to make MCLK. - * Because Samsung SoC does not support pcmcdclk output like I2S. - */ - -static int smdk_wm8580_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int rfs, ret; - - switch (params_rate(params)) { - case 8000: - break; - default: - printk(KERN_ERR "%s:%d Sampling Rate %u not supported!\n", - __func__, __LINE__, params_rate(params)); - return -EINVAL; - } - - rfs = mclk_freq / params_rate(params) / 2; - - if (mclk_freq == xtal_freq) { - ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_MCLK, - mclk_freq, SND_SOC_CLOCK_IN); - if (ret < 0) - return ret; - - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, - WM8580_CLKSRC_MCLK); - if (ret < 0) - return ret; - } else { - ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA, - mclk_freq, SND_SOC_CLOCK_IN); - if (ret < 0) - return ret; - - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, - WM8580_CLKSRC_PLLA); - if (ret < 0) - return ret; - - ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, - xtal_freq, mclk_freq); - if (ret < 0) - return ret; - } - - /* Set PCM source clock on CPU */ - ret = snd_soc_dai_set_sysclk(cpu_dai, S3C_PCM_CLKSRC_MUX, - mclk_freq, SND_SOC_CLOCK_IN); - if (ret < 0) - return ret; - - /* Set SCLK_DIV for making bclk */ - ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_PCM_SCLK_PER_FS, rfs); - if (ret < 0) - return ret; - - return 0; -} - -static struct snd_soc_ops smdk_wm8580_pcm_ops = { - .hw_params = smdk_wm8580_pcm_hw_params, -}; - -#define SMDK_DAI_FMT (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | \ - SND_SOC_DAIFMT_CBS_CFS) - -static struct snd_soc_dai_link smdk_dai[] = { - { - .name = "WM8580 PAIF PCM RX", - .stream_name = "Playback", - .cpu_dai_name = "samsung-pcm.0", - .codec_dai_name = "wm8580-hifi-playback", - .platform_name = "samsung-audio", - .codec_name = "wm8580.0-001b", - .dai_fmt = SMDK_DAI_FMT, - .ops = &smdk_wm8580_pcm_ops, - }, { - .name = "WM8580 PAIF PCM TX", - .stream_name = "Capture", - .cpu_dai_name = "samsung-pcm.0", - .codec_dai_name = "wm8580-hifi-capture", - .platform_name = "samsung-pcm.0", - .codec_name = "wm8580.0-001b", - .dai_fmt = SMDK_DAI_FMT, - .ops = &smdk_wm8580_pcm_ops, - }, -}; - -static struct snd_soc_card smdk_pcm = { - .name = "SMDK-PCM", - .owner = THIS_MODULE, - .dai_link = smdk_dai, - .num_links = 2, -}; - -/* - * After SMDKC110 Base Board's Rev is '0.1', 12MHz External OSC(X1) - * is absent (or not connected), so we connect EXT_VOICE_CLK(OSC4), - * 2.0484Mhz, directly with MCLK both Codec and SoC. - */ -static int snd_smdk_probe(struct platform_device *pdev) -{ - int ret = 0; - - xtal_freq = SMDK_WM8580_EXT_OSC; - mclk_freq = SMDK_WM8580_EXT_MCLK; - - if (machine_is_smdkc110() || machine_is_smdkv210()) - xtal_freq = mclk_freq = SMDK_WM8580_EXT_VOICE; - - smdk_pcm.dev = &pdev->dev; - 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; -} - -static struct platform_driver snd_smdk_driver = { - .driver = { - .name = "samsung-smdk-pcm", - }, - .probe = snd_smdk_probe, -}; - -module_platform_driver(snd_smdk_driver); - -MODULE_AUTHOR("Sangbeom Kim, "); -MODULE_DESCRIPTION("ALSA SoC SMDK WM8580 for PCM"); -MODULE_LICENSE("GPL"); From 0c95666f0d7364e364ab53e068f7891c98e90012 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 16 Nov 2016 21:08:41 +0800 Subject: [PATCH 17/28] ASoC: rt5665: Fix missing mutex_unlock in rt5665_calibrate Reported-by: Julia Lawall Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/rt5665.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 34254fd47efe..7dfaaf1c2d14 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -4587,7 +4587,7 @@ static void rt5665_calibrate(struct rt5665_priv *rt5665) pr_err("HP Calibration Failure\n"); regmap_write(rt5665->regmap, RT5665_RESET, 0); regcache_cache_bypass(rt5665->regmap, false); - return; + goto out_unlock; } count++; @@ -4606,7 +4606,7 @@ static void rt5665_calibrate(struct rt5665_priv *rt5665) pr_err("MONO Calibration Failure\n"); regmap_write(rt5665->regmap, RT5665_RESET, 0); regcache_cache_bypass(rt5665->regmap, false); - return; + goto out_unlock; } count++; @@ -4621,6 +4621,7 @@ static void rt5665_calibrate(struct rt5665_priv *rt5665) regmap_write(rt5665->regmap, RT5665_BIAS_CUR_CTRL_8, 0xa602); regmap_write(rt5665->regmap, RT5665_ASRC_8, 0x0120); +out_unlock: mutex_unlock(&rt5665->calibrate_mutex); } From f2826c1fe5d071fa437d337c41df979b60f0fc32 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 16 Nov 2016 21:08:42 +0800 Subject: [PATCH 18/28] ASoC: rt5665: Use devm_gpio_request_one() Simplify the code a bit. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/rt5665.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 7dfaaf1c2d14..324461e985b3 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -4677,11 +4677,9 @@ static int rt5665_i2c_probe(struct i2c_client *i2c, } if (gpio_is_valid(rt5665->pdata.ldo1_en)) { - if (devm_gpio_request(&i2c->dev, rt5665->pdata.ldo1_en, - "rt5665")) + if (devm_gpio_request_one(&i2c->dev, rt5665->pdata.ldo1_en, + GPIOF_OUT_INIT_HIGH, "rt5665")) dev_err(&i2c->dev, "Fail gpio_request gpio_ldo\n"); - else if (gpio_direction_output(rt5665->pdata.ldo1_en, 1)) - dev_err(&i2c->dev, "Fail gpio_direction gpio_ldo\n"); } /* Sleep for 300 ms miniumum */ From a40db07fbf6c47dd40aa6b5e0408e48cbae1338a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 14 Nov 2016 22:17:45 +0100 Subject: [PATCH 19/28] ASoC: rt5677: Remove superfluous linux/kthread.h inclusion It's nowhere used in this driver code. Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677-spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt5677-spi.c b/sound/soc/codecs/rt5677-spi.c index 91879ea95415..ebd0f7c5ad3b 100644 --- a/sound/soc/codecs/rt5677-spi.c +++ b/sound/soc/codecs/rt5677-spi.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include From f8cbab42d98298ab9c4878dc9105d350b0b902ff Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 20 Nov 2016 21:24:51 +0200 Subject: [PATCH 20/28] ASoC: samsung: Remove non-existing MACH dependencies MACH_SMDKC100 was removed in commit b8529ec1c1b0 ("ARM: S5PC100: no more support S5PC100 SoC"). MACH_SMDKV210 and MACH_SMDKC110 in commit 28c8331d386 ("ARM: S5PV210: Remove support for board files"). Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 79ae6a7c93ff..ea0fa9971a0c 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -49,7 +49,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 config SND_SOC_SAMSUNG_SMDK_WM8580 tristate "SoC I2S Audio support for WM8580 on SMDK" - depends on MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 + depends on MACH_SMDK6410 depends on I2C select SND_SOC_WM8580 select SND_SAMSUNG_I2S From cd9e2b62768c21c051c585f9d4935b4fa6e9603e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 20 Nov 2016 21:24:52 +0200 Subject: [PATCH 21/28] ASoC: samsung: smdk_wm8580: Remove old platforms and drop mach-types usage MACH_SMDKC100, MACH_SMDKV210 and MACH_SMDKC110 are no longer supported so we can drop the dead code. After this the driver no longer differentiates between machines (S3C24xx machines are not supported by it) so there is no need to override I2S device id in cpu_dai_name and SEC_PLAYBACK dai_link can be removed as well. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8580.c | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index 548bfd993788..de724ce7b955 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c @@ -14,8 +14,6 @@ #include #include -#include - #include "../codecs/wm8580.h" #include "i2s.h" @@ -147,7 +145,6 @@ static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd) enum { PRI_PLAYBACK = 0, PRI_CAPTURE, - SEC_PLAYBACK, }; #define SMDK_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \ @@ -157,7 +154,7 @@ static struct snd_soc_dai_link smdk_dai[] = { [PRI_PLAYBACK] = { /* Primary Playback i/f */ .name = "WM8580 PAIF RX", .stream_name = "Playback", - .cpu_dai_name = "samsung-i2s.0", + .cpu_dai_name = "samsung-i2s.2", .codec_dai_name = "wm8580-hifi-playback", .platform_name = "samsung-i2s.0", .codec_name = "wm8580.0-001b", @@ -167,7 +164,7 @@ static struct snd_soc_dai_link smdk_dai[] = { [PRI_CAPTURE] = { /* Primary Capture i/f */ .name = "WM8580 PAIF TX", .stream_name = "Capture", - .cpu_dai_name = "samsung-i2s.0", + .cpu_dai_name = "samsung-i2s.2", .codec_dai_name = "wm8580-hifi-capture", .platform_name = "samsung-i2s.0", .codec_name = "wm8580.0-001b", @@ -175,23 +172,13 @@ static struct snd_soc_dai_link smdk_dai[] = { .init = smdk_wm8580_init_paiftx, .ops = &smdk_ops, }, - [SEC_PLAYBACK] = { /* Sec_Fifo Playback i/f */ - .name = "Sec_FIFO TX", - .stream_name = "Playback", - .cpu_dai_name = "samsung-i2s-sec", - .codec_dai_name = "wm8580-hifi-playback", - .platform_name = "samsung-i2s-sec", - .codec_name = "wm8580.0-001b", - .dai_fmt = SMDK_DAI_FMT, - .ops = &smdk_ops, - }, }; static struct snd_soc_card smdk = { .name = "SMDK-I2S", .owner = THIS_MODULE, .dai_link = smdk_dai, - .num_links = 2, + .num_links = ARRAY_SIZE(smdk_dai), .dapm_widgets = smdk_wm8580_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(smdk_wm8580_dapm_widgets), @@ -204,17 +191,6 @@ static struct platform_device *smdk_snd_device; static int __init smdk_audio_init(void) { int ret; - char *str; - - if (machine_is_smdkc100() - || machine_is_smdkv210() || machine_is_smdkc110()) { - smdk.num_links = 3; - } else if (machine_is_smdk6410()) { - str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name; - str[strlen(str) - 1] = '2'; - str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name; - str[strlen(str) - 1] = '2'; - } smdk_snd_device = platform_device_alloc("soc-audio", -1); if (!smdk_snd_device) From a41dcdeee5d87cf3852b857cc3a8507832ec8b42 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 20 Nov 2016 21:24:54 +0200 Subject: [PATCH 22/28] ASoC: samsung: Enable COMPILE_TEST for entire Samsung ASoc Instead of build time, Samsung ASoC drivers have rather runtime dependency on Exynos or other Samsung platforms. For building they require Common Clock Framework. If it is provided they could be compile tested to increase build coverage. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index ea0fa9971a0c..48dcd3dd9ec7 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -1,6 +1,7 @@ menuconfig SND_SOC_SAMSUNG tristate "ASoC support for Samsung" - depends on (PLAT_SAMSUNG || ARCH_EXYNOS) + depends on PLAT_SAMSUNG || ARCH_EXYNOS || COMPILE_TEST + depends on COMMON_CLK select SND_SOC_GENERIC_DMAENGINE_PCM ---help--- Say Y or M if you want to add support for codecs attached to From 95f5609d223d661419061bd6231da01a317c30d9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 20 Nov 2016 21:24:53 +0200 Subject: [PATCH 23/28] ASoC: samsung: Enable COMPILE_TEST for SmartQ and WM8580 The I2S sound drivers for SmartQ board and WM8580 codec can be compile tested to increase build coverage. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 48dcd3dd9ec7..a6cc6ca93fa7 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -50,7 +50,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750 config SND_SOC_SAMSUNG_SMDK_WM8580 tristate "SoC I2S Audio support for WM8580 on SMDK" - depends on MACH_SMDK6410 + depends on MACH_SMDK6410 || COMPILE_TEST depends on I2C select SND_SOC_WM8580 select SND_SAMSUNG_I2S @@ -110,7 +110,8 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380 config SND_SOC_SMARTQ tristate "SoC I2S Audio support for SmartQ board" - depends on MACH_SMARTQ && I2C + depends on MACH_SMARTQ || COMPILE_TEST + depends on I2C select SND_SAMSUNG_I2S select SND_SOC_WM8750 From b4ff47d2843f7df61b956c8ee4a576bf83b11fab Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 30 Nov 2016 17:19:20 +0100 Subject: [PATCH 24/28] ASoC: rt5670: Enable Braswell platform workaround for Dell Wyse 3040 Dell Wyse 3040 requires the platform workaround for enabling dmic and jack detection as defined for Braswell CRB. Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 12d3bc14a558..d32ebe73c2c9 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2826,6 +2826,13 @@ static const struct dmi_system_id dmi_platform_intel_braswell[] = { DMI_MATCH(DMI_BOARD_NAME, "Braswell CRB"), }, }, + { + .ident = "Dell Wyse 3040", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Wyse 3040"), + }, + }, {} }; From d25280060835e1b2b84c242905da8334ab15c5b4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 30 Nov 2016 14:55:29 +0100 Subject: [PATCH 25/28] ASoC: rt5670: Add missing 10EC5072 ACPI ID rt5670 driver supports also RT5672 codec, but its ACPI ID is missing. This was found on Dell Wyse 3040 box. Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index d32ebe73c2c9..97bafac3bc15 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2813,6 +2813,7 @@ MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); #ifdef CONFIG_ACPI static const struct acpi_device_id rt5670_acpi_match[] = { { "10EC5670", 0}, + { "10EC5672", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match); From 48a760279ba31c59b8cfb14c5be9ed1c8e191038 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 2 Nov 2016 17:02:37 +0100 Subject: [PATCH 26/28] ASoC: samsung: Add DT bindings documentation for TM2 sound subsystem This patch adds DT binding documentation for Exnos5433 based TM2 and TM2E boards sound subsystem. Signed-off-by: Sylwester Nawrocki Acked-by: Rob Herring Signed-off-by: Mark Brown --- .../bindings/sound/samsung,tm2-audio.txt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt diff --git a/Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt b/Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt new file mode 100644 index 000000000000..94442e5673b3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt @@ -0,0 +1,38 @@ +Samsung Exynos5433 TM2(E) audio complex with WM5110 codec + +Required properties: + + - compatible : "samsung,tm2-audio" + - model : the user-visible name of this sound complex + - audio-codec : the phandle of the wm5110 audio codec node, + as described in ../mfd/arizona.txt + - i2s-controller : the phandle of the I2S controller + - audio-amplifier : the phandle of the MAX98504 amplifier + - samsung,audio-routing : a list of the connections between audio components; + each entry is a pair of strings, the first being the + connection's sink, the second being the connection's + source; valid names for sources and sinks are the + WM5110's and MAX98504's pins and the jacks on the + board: HP, SPK, Main Mic, Sub Mic, Third Mic, + Headset Mic + - mic-bias-gpios : GPIO pin that enables the Main Mic bias regulator + + +Example: + +sound { + compatible = "samsung,tm2-audio"; + audio-codec = <&wm5110>; + i2s-controller = <&i2s0>; + audio-amplifier = <&max98504>; + mic-bias-gpios = <&gpr3 2 0>; + model = "wm5110"; + samsung,audio-routing = + "HP", "HPOUT1L", + "HP", "HPOUT1R", + "SPK", "SPKOUT", + "SPKOUT", "HPOUT2L", + "SPKOUT", "HPOUT2R", + "Main Mic", "MICBIAS2", + "IN1R", "Main Mic"; +}; From 1bfbc260a5b474f1376bdfdfbc590f75645d62af Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 2 Nov 2016 17:05:45 +0100 Subject: [PATCH 27/28] ASoC: samsung: Add machine driver for Exynos5433 based TM2 board This patch adds the sound machine driver for the TM2 and TM2E boards. Speaker and headphone playback, Main Mic capture, Bluetooth, Voice call and external accessory are supported. Signed-off-by: Inha Song [k.kozlowski: rebased on 4.1] Signed-off-by: Krzysztof Kozlowski [s.nawrocki: rebased to 4.7, adjustment to the ASoC core changes, removed unused ops and direct calls to the max98504 function, added parsing of "audio-amplifier" and "audio-codec" properties, added TDM API calls, switched to gpiod API] Signed-off-by: Sylwester Nawrocki Reviewed-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/samsung/Kconfig | 9 + sound/soc/samsung/Makefile | 2 + sound/soc/samsung/tm2_wm5110.c | 552 +++++++++++++++++++++++++++++++++ 3 files changed, 563 insertions(+) create mode 100644 sound/soc/samsung/tm2_wm5110.c diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index a6cc6ca93fa7..7c423151ef7d 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -190,4 +190,13 @@ config SND_SOC_ARNDALE_RT5631_ALC5631 select SND_SAMSUNG_I2S select SND_SOC_RT5631 +config SND_SOC_SAMSUNG_TM2_WM5110 + tristate "SoC I2S Audio support for WM5110 on TM2 board" + depends on SND_SOC_SAMSUNG && MFD_ARIZONA && I2C && SPI_MASTER + select SND_SOC_MAX98504 + select SND_SOC_WM5110 + select SND_SAMSUNG_I2S + help + Say Y if you want to add support for SoC audio on the TM2 board. + endif #SND_SOC_SAMSUNG diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index c95b6835361f..b5df5e2e3d94 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -41,6 +41,7 @@ snd-soc-lowland-objs := lowland.o snd-soc-littlemill-objs := littlemill.o snd-soc-bells-objs := bells.o snd-soc-arndale-rt5631-objs := arndale_rt5631.o +snd-soc-tm2-wm5110-objs := tm2_wm5110.o obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o @@ -62,3 +63,4 @@ obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o obj-$(CONFIG_SND_SOC_ARNDALE_RT5631_ALC5631) += snd-soc-arndale-rt5631.o +obj-$(CONFIG_SND_SOC_SAMSUNG_TM2_WM5110) += snd-soc-tm2-wm5110.o diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c new file mode 100644 index 000000000000..5cdf7d19b87f --- /dev/null +++ b/sound/soc/samsung/tm2_wm5110.c @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2015 - 2016 Samsung Electronics Co., Ltd. + * + * Authors: Inha Song + * Sylwester Nawrocki + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include "i2s.h" +#include "../codecs/wm5110.h" + +/* + * The source clock is XCLKOUT with its mux set to the external fixed rate + * oscillator (XXTI). + */ +#define MCLK_RATE 24000000U + +#define TM2_DAI_AIF1 0 +#define TM2_DAI_AIF2 1 + +struct tm2_machine_priv { + struct snd_soc_codec *codec; + unsigned int sysclk_rate; + struct gpio_desc *gpio_mic_bias; +}; + +static int tm2_start_sysclk(struct snd_soc_card *card) +{ + struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_codec *codec = priv->codec; + int ret; + + ret = snd_soc_codec_set_pll(codec, WM5110_FLL1_REFCLK, + ARIZONA_FLL_SRC_MCLK1, + MCLK_RATE, + priv->sysclk_rate); + if (ret < 0) { + dev_err(codec->dev, "Failed to set FLL1 source: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_pll(codec, WM5110_FLL1, + ARIZONA_FLL_SRC_MCLK1, + MCLK_RATE, + priv->sysclk_rate); + if (ret < 0) { + dev_err(codec->dev, "Failed to start FLL1: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, + ARIZONA_CLK_SRC_FLL1, + priv->sysclk_rate, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec->dev, "Failed to set SYSCLK source: %d\n", ret); + return ret; + } + + return 0; +} + +static int tm2_stop_sysclk(struct snd_soc_card *card) +{ + struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_codec *codec = priv->codec; + int ret; + + ret = snd_soc_codec_set_pll(codec, WM5110_FLL1, 0, 0, 0); + if (ret < 0) { + dev_err(codec->dev, "Failed to stop FLL1: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, + ARIZONA_CLK_SRC_FLL1, 0, 0); + if (ret < 0) { + dev_err(codec->dev, "Failed to stop SYSCLK: %d\n", ret); + return ret; + } + + return 0; +} + +static int tm2_aif1_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(rtd->card); + + switch (params_rate(params)) { + case 4000: + case 8000: + case 12000: + case 16000: + case 24000: + case 32000: + case 48000: + case 96000: + case 192000: + /* Highest possible SYSCLK frequency: 147.456MHz */ + priv->sysclk_rate = 147456000U; + break; + case 11025: + case 22050: + case 44100: + case 88200: + case 176400: + /* Highest possible SYSCLK frequency: 135.4752 MHz */ + priv->sysclk_rate = 135475200U; + break; + default: + dev_err(codec->dev, "Not supported sample rate: %d\n", + params_rate(params)); + return -EINVAL; + } + + return tm2_start_sysclk(rtd->card); +} + +static struct snd_soc_ops tm2_aif1_ops = { + .hw_params = tm2_aif1_hw_params, +}; + +static int tm2_aif2_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + unsigned int asyncclk_rate; + int ret; + + switch (params_rate(params)) { + case 8000: + case 12000: + case 16000: + /* Highest possible ASYNCCLK frequency: 49.152MHz */ + asyncclk_rate = 49152000U; + break; + case 11025: + /* Highest possible ASYNCCLK frequency: 45.1584 MHz */ + asyncclk_rate = 45158400U; + break; + default: + dev_err(codec->dev, "Not supported sample rate: %d\n", + params_rate(params)); + return -EINVAL; + } + + ret = snd_soc_codec_set_pll(codec, WM5110_FLL2_REFCLK, + ARIZONA_FLL_SRC_MCLK1, + MCLK_RATE, + asyncclk_rate); + if (ret < 0) { + dev_err(codec->dev, "Failed to set FLL2 source: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_pll(codec, WM5110_FLL2, + ARIZONA_FLL_SRC_MCLK1, + MCLK_RATE, + asyncclk_rate); + if (ret < 0) { + dev_err(codec->dev, "Failed to start FLL2: %d\n", ret); + return ret; + } + + ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK, + ARIZONA_CLK_SRC_FLL2, + asyncclk_rate, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec->dev, "Failed to set ASYNCCLK source: %d\n", ret); + return ret; + } + + return 0; +} + +static int tm2_aif2_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + int ret; + + /* disable FLL2 */ + ret = snd_soc_codec_set_pll(codec, WM5110_FLL2, ARIZONA_FLL_SRC_MCLK1, + 0, 0); + if (ret < 0) + dev_err(codec->dev, "Failed to stop FLL2: %d\n", ret); + + return ret; +} + +static struct snd_soc_ops tm2_aif2_ops = { + .hw_params = tm2_aif2_hw_params, + .hw_free = tm2_aif2_hw_free, +}; + +static int tm2_mic_bias(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_card *card = w->dapm->card; + struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + gpiod_set_value_cansleep(priv->gpio_mic_bias, 1); + break; + case SND_SOC_DAPM_POST_PMD: + gpiod_set_value_cansleep(priv->gpio_mic_bias, 0); + break; + } + + return 0; +} + +static int tm2_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level) +{ + struct snd_soc_pcm_runtime *rtd; + + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name); + + if (dapm->dev != rtd->codec_dai->dev) + return 0; + + switch (level) { + case SND_SOC_BIAS_STANDBY: + if (card->dapm.bias_level == SND_SOC_BIAS_OFF) + tm2_start_sysclk(card); + break; + case SND_SOC_BIAS_OFF: + tm2_stop_sysclk(card); + break; + default: + break; + } + + return 0; +} + +static struct snd_soc_aux_dev tm2_speaker_amp_dev; + +static int tm2_late_probe(struct snd_soc_card *card) +{ + struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); + struct snd_soc_dai_link_component dlc = { 0 }; + unsigned int ch_map[] = { 0, 1 }; + struct snd_soc_dai *amp_pdm_dai; + struct snd_soc_pcm_runtime *rtd; + struct snd_soc_dai *aif1_dai; + struct snd_soc_dai *aif2_dai; + int ret; + + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[TM2_DAI_AIF1].name); + aif1_dai = rtd->codec_dai; + priv->codec = rtd->codec; + + ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); + if (ret < 0) { + dev_err(aif1_dai->dev, "Failed to set SYSCLK: %d\n", ret); + return ret; + } + + rtd = snd_soc_get_pcm_runtime(card, card->dai_link[TM2_DAI_AIF2].name); + aif2_dai = rtd->codec_dai; + + ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); + if (ret < 0) { + dev_err(aif2_dai->dev, "Failed to set ASYNCCLK: %d\n", ret); + return ret; + } + + dlc.of_node = tm2_speaker_amp_dev.codec_of_node; + amp_pdm_dai = snd_soc_find_dai(&dlc); + if (!amp_pdm_dai) + return -ENODEV; + + /* Set the MAX98504 V/I sense PDM Tx DAI channel mapping */ + ret = snd_soc_dai_set_channel_map(amp_pdm_dai, ARRAY_SIZE(ch_map), + ch_map, 0, NULL); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_tdm_slot(amp_pdm_dai, 0x3, 0x0, 2, 16); + if (ret < 0) + return ret; + + return 0; +} + +static const struct snd_kcontrol_new tm2_controls[] = { + SOC_DAPM_PIN_SWITCH("HP"), + SOC_DAPM_PIN_SWITCH("SPK"), + SOC_DAPM_PIN_SWITCH("RCV"), + SOC_DAPM_PIN_SWITCH("VPS"), + SOC_DAPM_PIN_SWITCH("HDMI"), + + SOC_DAPM_PIN_SWITCH("Main Mic"), + SOC_DAPM_PIN_SWITCH("Sub Mic"), + SOC_DAPM_PIN_SWITCH("Third Mic"), + + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +const struct snd_soc_dapm_widget tm2_dapm_widgets[] = { + SND_SOC_DAPM_HP("HP", NULL), + SND_SOC_DAPM_SPK("SPK", NULL), + SND_SOC_DAPM_SPK("RCV", NULL), + SND_SOC_DAPM_LINE("VPS", NULL), + SND_SOC_DAPM_LINE("HDMI", NULL), + + SND_SOC_DAPM_MIC("Main Mic", tm2_mic_bias), + SND_SOC_DAPM_MIC("Sub Mic", NULL), + SND_SOC_DAPM_MIC("Third Mic", NULL), + + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_component_driver tm2_component = { + .name = "tm2-audio", +}; + +static struct snd_soc_dai_driver tm2_ext_dai[] = { + { + .name = "Voice call", + .playback = { + .channels_min = 1, + .channels_max = 4, + .rate_min = 8000, + .rate_max = 48000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 4, + .rate_min = 8000, + .rate_max = 48000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, + { + .name = "Bluetooth", + .playback = { + .channels_min = 1, + .channels_max = 4, + .rate_min = 8000, + .rate_max = 16000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 16000, + .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + }, +}; + +static struct snd_soc_dai_link tm2_dai_links[] = { + { + .name = "WM5110 AIF1", + .stream_name = "HiFi Primary", + .codec_dai_name = "wm5110-aif1", + .ops = &tm2_aif1_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, + }, { + .name = "WM5110 Voice", + .stream_name = "Voice call", + .codec_dai_name = "wm5110-aif2", + .ops = &tm2_aif2_ops, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, + .ignore_suspend = 1, + }, { + .name = "WM5110 BT", + .stream_name = "Bluetooth", + .codec_dai_name = "wm5110-aif3", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM, + .ignore_suspend = 1, + } +}; + +static struct snd_soc_card tm2_card = { + .owner = THIS_MODULE, + + .dai_link = tm2_dai_links, + .num_links = ARRAY_SIZE(tm2_dai_links), + .controls = tm2_controls, + .num_controls = ARRAY_SIZE(tm2_controls), + .dapm_widgets = tm2_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tm2_dapm_widgets), + .aux_dev = &tm2_speaker_amp_dev, + .num_aux_devs = 1, + + .late_probe = tm2_late_probe, + .set_bias_level = tm2_set_bias_level, +}; + +static int tm2_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct snd_soc_card *card = &tm2_card; + struct tm2_machine_priv *priv; + struct device_node *cpu_dai_node, *codec_dai_node; + int ret, i; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + snd_soc_card_set_drvdata(card, priv); + card->dev = dev; + + priv->gpio_mic_bias = devm_gpiod_get(dev, "mic-bias", + GPIOF_OUT_INIT_LOW); + if (IS_ERR(priv->gpio_mic_bias)) { + dev_err(dev, "Failed to get mic bias gpio\n"); + return PTR_ERR(priv->gpio_mic_bias); + } + + ret = snd_soc_of_parse_card_name(card, "model"); + if (ret < 0) { + dev_err(dev, "Card name is not specified\n"); + return ret; + } + + ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); + if (ret < 0) { + dev_err(dev, "Audio routing is not specified or invalid\n"); + return ret; + } + + card->aux_dev[0].codec_of_node = of_parse_phandle(dev->of_node, + "audio-amplifier", 0); + if (!card->aux_dev[0].codec_of_node) { + dev_err(dev, "audio-amplifier property invalid or missing\n"); + return -EINVAL; + } + + cpu_dai_node = of_parse_phandle(dev->of_node, "i2s-controller", 0); + if (!cpu_dai_node) { + dev_err(dev, "i2s-controllers property invalid or missing\n"); + ret = -EINVAL; + goto amp_node_put; + } + + codec_dai_node = of_parse_phandle(dev->of_node, "audio-codec", 0); + if (!codec_dai_node) { + dev_err(dev, "audio-codec property invalid or missing\n"); + ret = -EINVAL; + goto cpu_dai_node_put; + } + + for (i = 0; i < card->num_links; i++) { + card->dai_link[i].cpu_dai_name = NULL; + card->dai_link[i].cpu_name = NULL; + card->dai_link[i].platform_name = NULL; + card->dai_link[i].codec_of_node = codec_dai_node; + card->dai_link[i].cpu_of_node = cpu_dai_node; + card->dai_link[i].platform_of_node = cpu_dai_node; + } + + ret = devm_snd_soc_register_component(dev, &tm2_component, + tm2_ext_dai, ARRAY_SIZE(tm2_ext_dai)); + if (ret < 0) { + dev_err(dev, "Failed to register component: %d\n", ret); + goto codec_dai_node_put; + } + + ret = devm_snd_soc_register_card(dev, card); + if (ret < 0) { + dev_err(dev, "Failed to register card: %d\n", ret); + goto codec_dai_node_put; + } + +codec_dai_node_put: + of_node_put(codec_dai_node); +cpu_dai_node_put: + of_node_put(cpu_dai_node); +amp_node_put: + of_node_put(card->aux_dev[0].codec_of_node); + return ret; +} + +static int tm2_pm_prepare(struct device *dev) +{ + struct snd_soc_card *card = dev_get_drvdata(dev); + + return tm2_stop_sysclk(card); +} + +static void tm2_pm_complete(struct device *dev) +{ + struct snd_soc_card *card = dev_get_drvdata(dev); + + tm2_start_sysclk(card); +} + +const struct dev_pm_ops tm2_pm_ops = { + .prepare = tm2_pm_prepare, + .suspend = snd_soc_suspend, + .resume = snd_soc_resume, + .complete = tm2_pm_complete, + .freeze = snd_soc_suspend, + .thaw = snd_soc_resume, + .poweroff = snd_soc_poweroff, + .restore = snd_soc_resume, +}; + +static const struct of_device_id tm2_of_match[] = { + { .compatible = "samsung,tm2-audio" }, + { }, +}; +MODULE_DEVICE_TABLE(of, tm2_of_match); + +static struct platform_driver tm2_driver = { + .driver = { + .name = "tm2-audio", + .pm = &tm2_pm_ops, + .of_match_table = tm2_of_match, + }, + .probe = tm2_probe, +}; +module_platform_driver(tm2_driver); + +MODULE_AUTHOR("Inha Song "); +MODULE_DESCRIPTION("ALSA SoC Exynos TM2 Audio Support"); +MODULE_LICENSE("GPL v2"); From 29a43aa9b4b609eba73e76c5fd92d435fc6e35ce Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 2 Dec 2016 05:27:30 +0000 Subject: [PATCH 28/28] ASoC: simple_card_utils: tidyup file comment/define simple_card_utils was created as simple_card_core in 1st prototype, and current code still have it. Let's tidyup Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 8 ++++---- sound/soc/generic/simple-card-utils.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index fd6412551145..64e90ca9ad32 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -1,5 +1,5 @@ /* - * simple_card_core.h + * simple_card_utils.h * * Copyright (c) 2016 Kuninori Morimoto * @@ -7,8 +7,8 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#ifndef __SIMPLE_CARD_CORE_H -#define __SIMPLE_CARD_CORE_H +#ifndef __SIMPLE_CARD_UTILS_H +#define __SIMPLE_CARD_UTILS_H #include @@ -68,4 +68,4 @@ void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, int asoc_simple_card_clean_reference(struct snd_soc_card *card); -#endif /* __SIMPLE_CARD_CORE_H */ +#endif /* __SIMPLE_CARD_UTILS_H */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index e5b80f53093a..cf026252cd4a 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -1,5 +1,5 @@ /* - * simple-card-core.c + * simple-card-utils.c * * Copyright (c) 2016 Kuninori Morimoto *